зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 7c5e444f3350 (bug 1585620) for causing browser chrome failures CLOSED TREE
This commit is contained in:
Родитель
913447fb35
Коммит
6fa26b1439
|
@ -551,7 +551,6 @@ XPCOMUtils.defineLazyGetter(
|
|||
// lazy module getters
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AboutCertViewerHandler: "resource://gre/modules/AboutCertViewerHandler.jsm",
|
||||
AboutPrivateBrowsingHandler:
|
||||
"resource:///modules/aboutpages/AboutPrivateBrowsingHandler.jsm",
|
||||
AboutProtectionsHandler:
|
||||
|
@ -1664,8 +1663,6 @@ BrowserGlue.prototype = {
|
|||
|
||||
NewTabUtils.init();
|
||||
|
||||
AboutCertViewerHandler.init();
|
||||
|
||||
AboutPrivateBrowsingHandler.init();
|
||||
|
||||
AboutProtectionsHandler.init();
|
||||
|
@ -1914,7 +1911,6 @@ BrowserGlue.prototype = {
|
|||
SearchTelemetry.uninit();
|
||||
PageThumbs.uninit();
|
||||
NewTabUtils.uninit();
|
||||
AboutCertViewerHandler.uninit();
|
||||
AboutPrivateBrowsingHandler.uninit();
|
||||
AboutProtectionsHandler.uninit();
|
||||
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["AboutCertViewerHandler"];
|
||||
|
||||
const { RemotePages } = ChromeUtils.import(
|
||||
"resource://gre/modules/remotepagemanager/RemotePageManagerParent.jsm"
|
||||
);
|
||||
|
||||
const TYPE_UNKNOWN = 0;
|
||||
const TYPE_CA = 1;
|
||||
const TYPE_USER = 2;
|
||||
const TYPE_EMAIL = 4;
|
||||
const TYPE_SERVER = 8;
|
||||
const TYPE_ANY = 0xffff;
|
||||
|
||||
var AboutCertViewerHandler = {
|
||||
_inited: false,
|
||||
_topics: ["getCertificates"],
|
||||
|
||||
initCerts() {
|
||||
let certs = {
|
||||
[TYPE_UNKNOWN]: [],
|
||||
[TYPE_CA]: [],
|
||||
[TYPE_USER]: [],
|
||||
[TYPE_EMAIL]: [],
|
||||
[TYPE_SERVER]: [],
|
||||
[TYPE_ANY]: [],
|
||||
};
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
||||
Ci.nsIX509CertDB
|
||||
);
|
||||
let certcache = certdb.getCerts();
|
||||
for (let cert of certcache) {
|
||||
for (let certType of Object.keys(certs)) {
|
||||
if (certType & cert.certType) {
|
||||
certs[cert.certType].push({
|
||||
displayName: cert.displayName,
|
||||
derb64: cert.getBase64DERString(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return certs;
|
||||
},
|
||||
|
||||
init() {
|
||||
this.pageListener = new RemotePages("about:certificate");
|
||||
this.receiveMessage = this.receiveMessage.bind(this);
|
||||
for (let topic of this._topics) {
|
||||
this.pageListener.addMessageListener(topic, this.receiveMessage);
|
||||
}
|
||||
this._inited = true;
|
||||
},
|
||||
|
||||
uninit() {
|
||||
if (!this._inited) {
|
||||
return;
|
||||
}
|
||||
for (let topic of this._topics) {
|
||||
this.pageListener.removeMessageListener(topic, this.receiveMessage);
|
||||
}
|
||||
this.pageListener.destroy();
|
||||
},
|
||||
|
||||
receiveMessage(aMessage) {
|
||||
switch (aMessage.name) {
|
||||
case "getCertificates": {
|
||||
let certs = this.initCerts();
|
||||
aMessage.target.sendAsyncMessage("certificates", {
|
||||
certs,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
|
@ -19,13 +19,9 @@
|
|||
<script defer="defer" type="module" src="chrome://global/content/certviewer/certDecoder.js"></script>
|
||||
<script defer="defer" type="module" src="chrome://global/content/certviewer/certviewer.js"></script>
|
||||
<script defer="defer" type="module" src="chrome://global/content/certviewer/components/info-group.js"></script>
|
||||
<script defer="defer" type="module" src="chrome://global/content/certviewer/components/info-group-container.js"></script>
|
||||
<script defer="defer" type="module" src="chrome://global/content/certviewer/components/info-item.js"></script>
|
||||
<script defer="defer" type="module" src="chrome://global/content/certviewer/components/certificate-tabs-section.js"></script>
|
||||
<script defer="defer" type="module" src="chrome://global/content/certviewer/components/certificate-section.js"></script>
|
||||
<script defer="defer" type="module" src="chrome://global/content/certviewer/components/error-section.js"></script>
|
||||
<script defer="defer" type="module" src="chrome://global/content/certviewer/components/about-certificate-section.js"></script>
|
||||
<script defer="defer" type="module" src="chrome://global/content/certviewer/components/about-certificate-items.js"></script>
|
||||
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
|
||||
<link rel="stylesheet" href="chrome://global/content/certviewer/certviewer.css">
|
||||
<title>about:certificate</title>
|
||||
|
@ -34,13 +30,8 @@
|
|||
<template id="certificate-section-template" class="section">
|
||||
<link rel="stylesheet" href="chrome://global/content/certviewer/components/certificate-section.css">
|
||||
<h1 class="title"></h1>
|
||||
</template>
|
||||
|
||||
<template id="certificate-tabs-template">
|
||||
<div class="certificate-tabs" role="tablist"></div>
|
||||
</template>
|
||||
|
||||
<template id="info-groups-template">
|
||||
<div class="info-groups"></div>
|
||||
</template>
|
||||
|
||||
<template id="info-item-template">
|
||||
|
@ -61,20 +52,5 @@
|
|||
<h1 class="title"></h1>
|
||||
<span class="error"></span>
|
||||
</template>
|
||||
|
||||
<template id="about-certificate-template" class="section">
|
||||
<link rel="stylesheet" href="chrome://global/content/certviewer/components/certificate-section.css">
|
||||
<h1 class="title"></h1>
|
||||
</template>
|
||||
|
||||
<template id="about-certificate-items-template">
|
||||
<link rel="stylesheet" href="chrome://global/content/certviewer/components/about-certificate-section.css">
|
||||
</template>
|
||||
|
||||
<template id="list-item-template">
|
||||
<link rel="stylesheet" href="chrome://global/content/certviewer/components/list-item.css">
|
||||
<a class="cert-url"><span class="item-name"></span></a>
|
||||
<button class="export"></button>
|
||||
</template>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -13,7 +13,7 @@ document.addEventListener("DOMContentLoaded", async e => {
|
|||
let url = new URL(document.URL);
|
||||
let certInfo = url.searchParams.getAll("cert");
|
||||
if (certInfo.length === 0) {
|
||||
render({}, false, true);
|
||||
await render(false, true);
|
||||
return;
|
||||
}
|
||||
certInfo = certInfo.map(cert => decodeURIComponent(cert));
|
||||
|
@ -23,9 +23,7 @@ document.addEventListener("DOMContentLoaded", async e => {
|
|||
export const updateSelectedItem = (() => {
|
||||
let state;
|
||||
return selectedItem => {
|
||||
let certificateSection =
|
||||
document.querySelector("certificate-section") ||
|
||||
document.querySelector("about-certificate-section");
|
||||
let certificateSection = document.querySelector("certificate-section");
|
||||
if (selectedItem) {
|
||||
if (state !== selectedItem) {
|
||||
state = selectedItem;
|
||||
|
@ -408,20 +406,10 @@ export const adjustCertInformation = cert => {
|
|||
};
|
||||
};
|
||||
|
||||
// isAboutCertificate means to the standalone page about:certificate, which
|
||||
// uses a different customElement than opening a certain certificate
|
||||
const render = async (certs, error, isAboutCertificate = false) => {
|
||||
if (isAboutCertificate) {
|
||||
await customElements.whenDefined("about-certificate-section");
|
||||
const AboutCertificateSection = customElements.get(
|
||||
"about-certificate-section"
|
||||
);
|
||||
document.querySelector("body").append(new AboutCertificateSection(certs));
|
||||
} else {
|
||||
await customElements.whenDefined("certificate-section");
|
||||
const CertificateSection = customElements.get("certificate-section");
|
||||
document.querySelector("body").append(new CertificateSection(certs, error));
|
||||
}
|
||||
const render = async (certs, error) => {
|
||||
await customElements.whenDefined("certificate-section");
|
||||
const CertificateSection = customElements.get("certificate-section");
|
||||
document.querySelector("body").append(new CertificateSection(certs, error));
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
/* eslint-env mozilla/frame-script */
|
||||
|
||||
import { ListItem } from "./list-item.js";
|
||||
|
||||
export class AboutCertificateItems extends HTMLElement {
|
||||
constructor(id, data) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
let template = document.getElementById("about-certificate-items-template");
|
||||
let templateHtml = template.content.cloneNode(true);
|
||||
|
||||
this.attachShadow({ mode: "open" }).appendChild(templateHtml);
|
||||
|
||||
document.l10n.connectRoot(this.shadowRoot);
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
for (let cert of this.data) {
|
||||
this.shadowRoot.append(new ListItem(cert));
|
||||
}
|
||||
}
|
||||
}
|
||||
customElements.define("about-certificate-items", AboutCertificateItems);
|
|
@ -1,7 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
:host {
|
||||
margin: 2em;
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
/* eslint-env mozilla/frame-script */
|
||||
|
||||
import { InfoGroupContainer } from "./info-group-container.js";
|
||||
import { CertificateTabsSection } from "./certificate-tabs-section.js";
|
||||
|
||||
const TYPE_UNKNOWN = 0;
|
||||
const TYPE_CA = 1;
|
||||
const TYPE_USER = 2;
|
||||
const TYPE_EMAIL = 4;
|
||||
const TYPE_SERVER = 8;
|
||||
|
||||
export class AboutCertificateSection extends HTMLElement {
|
||||
constructor(certs) {
|
||||
super();
|
||||
this.certs = certs;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
let template = document.getElementById("about-certificate-template");
|
||||
let templateHtml = template.content.cloneNode(true);
|
||||
|
||||
this.attachShadow({ mode: "open" }).appendChild(templateHtml);
|
||||
|
||||
document.l10n.connectRoot(this.shadowRoot);
|
||||
|
||||
this.certificateTabsSection = new CertificateTabsSection(true);
|
||||
this.shadowRoot.appendChild(this.certificateTabsSection.tabsElement);
|
||||
this.infoGroupsContainers = new InfoGroupContainer(true);
|
||||
|
||||
this.certData = {
|
||||
[TYPE_UNKNOWN]: {
|
||||
name: "certificate-viewer-tab-unkonwn",
|
||||
data: null,
|
||||
},
|
||||
[TYPE_CA]: {
|
||||
name: "certificate-viewer-tab-ca",
|
||||
data: null,
|
||||
},
|
||||
[TYPE_USER]: {
|
||||
name: "certificate-viewer-tab-mine",
|
||||
data: null,
|
||||
},
|
||||
[TYPE_EMAIL]: {
|
||||
name: "certificate-viewer-tab-people",
|
||||
data: null,
|
||||
},
|
||||
[TYPE_SERVER]: {
|
||||
name: "certificate-viewer-tab-servers",
|
||||
data: null,
|
||||
},
|
||||
};
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
RPMAddMessageListener("certificates", this.filterCerts.bind(this));
|
||||
RPMSendAsyncMessage("getCertificates");
|
||||
|
||||
let title = this.shadowRoot.querySelector(".title");
|
||||
title.setAttribute(
|
||||
"data-l10n-id",
|
||||
"certificate-viewer-certificate-section-title"
|
||||
);
|
||||
}
|
||||
|
||||
filterCerts(message) {
|
||||
this.certData[TYPE_UNKNOWN].data = message.data.certs[TYPE_UNKNOWN];
|
||||
this.certData[TYPE_CA].data = message.data.certs[TYPE_CA];
|
||||
this.certData[TYPE_USER].data = message.data.certs[TYPE_USER];
|
||||
this.certData[TYPE_EMAIL].data = message.data.certs[TYPE_EMAIL];
|
||||
this.certData[TYPE_SERVER].data = message.data.certs[TYPE_SERVER];
|
||||
|
||||
let final = false;
|
||||
let i = 0;
|
||||
for (let data of Object.values(this.certData)) {
|
||||
if (i === this.certs.length - 1) {
|
||||
final = true;
|
||||
}
|
||||
this.infoGroupsContainers.createInfoGroupsContainers({}, i, final, data);
|
||||
this.shadowRoot.appendChild(
|
||||
this.infoGroupsContainers.infoGroupsContainers[i]
|
||||
);
|
||||
this.certificateTabsSection.createTabSection(data.name, i);
|
||||
this.infoGroupsContainers.addClass("selected", 0);
|
||||
i++;
|
||||
}
|
||||
this.setAccessibilityEventListeners();
|
||||
this.addClassForPadding();
|
||||
}
|
||||
|
||||
// Adds class selector for items that need padding,
|
||||
// as nth-child/parent-based selectors aren't supported
|
||||
// due to the encapsulation of custom-element CSS.
|
||||
addClassForPadding() {
|
||||
let embeddedScts = this.shadowRoot.querySelector(".embedded-scts");
|
||||
if (!embeddedScts) {
|
||||
return;
|
||||
}
|
||||
let items = embeddedScts.shadowRoot.querySelectorAll(".version");
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
items[i].classList.add("padding");
|
||||
}
|
||||
}
|
||||
|
||||
setAccessibilityEventListeners() {
|
||||
this.certificateTabsSection.setAccessibilityEventListeners();
|
||||
}
|
||||
|
||||
updateSelectedTab(index) {
|
||||
this.certificateTabsSection.updateSelectedTab(index);
|
||||
}
|
||||
|
||||
updateCertificateSource(index) {
|
||||
this.infoGroupsContainers.updateCertificateSource(index);
|
||||
}
|
||||
}
|
||||
customElements.define("about-certificate-section", AboutCertificateSection);
|
|
@ -2,9 +2,10 @@
|
|||
* 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/. */
|
||||
|
||||
import { updateSelectedItem } from "../certviewer.js";
|
||||
import { InfoGroup } from "./info-group.js";
|
||||
import { ErrorSection } from "./error-section.js";
|
||||
import { InfoGroupContainer } from "./info-group-container.js";
|
||||
import { CertificateTabsSection } from "./certificate-tabs-section.js";
|
||||
import { normalizeToKebabCase } from "../utils.js";
|
||||
|
||||
class CertificateSection extends HTMLElement {
|
||||
constructor(certs, error) {
|
||||
|
@ -21,40 +22,30 @@ class CertificateSection extends HTMLElement {
|
|||
|
||||
document.l10n.connectRoot(this.shadowRoot);
|
||||
|
||||
this.certificateTabsSection = new CertificateTabsSection();
|
||||
this.shadowRoot.appendChild(this.certificateTabsSection.tabsElement);
|
||||
this.infoGroupsContainers = new InfoGroupContainer();
|
||||
this.infoGroupsContainers = [];
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
let certificateTabs = this.shadowRoot.querySelector(".certificate-tabs");
|
||||
|
||||
let title = this.shadowRoot.querySelector(".title");
|
||||
title.setAttribute(
|
||||
"data-l10n-id",
|
||||
"certificate-viewer-certificate-section-title"
|
||||
);
|
||||
|
||||
this.infoGroupContainer = this.shadowRoot.querySelector(".info-groups");
|
||||
|
||||
if (this.error) {
|
||||
title.classList.add("error");
|
||||
this.certificateTabsSection.appendChild(new ErrorSection());
|
||||
certificateTabs.appendChild(new ErrorSection());
|
||||
return;
|
||||
}
|
||||
let final = false;
|
||||
for (let i = 0; i < this.certs.length; i++) {
|
||||
if (i === this.certs.length - 1) {
|
||||
final = true;
|
||||
}
|
||||
this.infoGroupsContainers.createInfoGroupsContainers(
|
||||
this.certs[i].certItems,
|
||||
i,
|
||||
final
|
||||
);
|
||||
this.shadowRoot.appendChild(
|
||||
this.infoGroupsContainers.infoGroupsContainers[i]
|
||||
);
|
||||
this.certificateTabsSection.createTabSection(this.certs[i].tabName, i);
|
||||
this.infoGroupsContainers.addClass("selected", 0);
|
||||
this.createInfoGroupsContainers(this.certs[i].certItems, i);
|
||||
this.createTabSection(this.certs[i].tabName, i, certificateTabs);
|
||||
}
|
||||
this.setAccessibilityEventListeners();
|
||||
this.addClassForPadding();
|
||||
|
@ -75,16 +66,110 @@ class CertificateSection extends HTMLElement {
|
|||
}
|
||||
}
|
||||
|
||||
/* Information on setAccessibilityEventListeners() can be found
|
||||
* at https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Tab_Role */
|
||||
setAccessibilityEventListeners() {
|
||||
this.certificateTabsSection.setAccessibilityEventListeners();
|
||||
const tabs = this.shadowRoot.querySelectorAll('[role="tab"]');
|
||||
const tabList = this.shadowRoot.querySelector('[role="tablist"]');
|
||||
|
||||
// Add a click event handler to each tab
|
||||
tabs.forEach(tab => {
|
||||
tab.addEventListener("click", e =>
|
||||
updateSelectedItem(e.target.getAttribute("idnumber"))
|
||||
);
|
||||
});
|
||||
|
||||
// Enable arrow navigation between tabs in the tab list
|
||||
let tabFocus = 0;
|
||||
|
||||
tabList.addEventListener("keydown", e => {
|
||||
// Move right
|
||||
if (e.keyCode === 39 || e.keyCode === 37) {
|
||||
// After navigating away from the current tab,
|
||||
// prevent that tab from being tabbable -
|
||||
// so as to only allow arrow navigation within the tablist.
|
||||
tabs[tabFocus].setAttribute("tabindex", -1);
|
||||
if (e.keyCode === 39) {
|
||||
tabFocus++;
|
||||
// If we're at the end, go to the start
|
||||
if (tabFocus > tabs.length - 1) {
|
||||
tabFocus = 0;
|
||||
}
|
||||
// Move left
|
||||
} else if (e.keyCode === 37) {
|
||||
tabFocus--;
|
||||
// If we're at the start, move to the end
|
||||
if (tabFocus < 0) {
|
||||
tabFocus = tabs.length;
|
||||
}
|
||||
}
|
||||
tabs[tabFocus].setAttribute("tabindex", 0);
|
||||
tabs[tabFocus].focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
createInfoGroupsContainers(certArray, i) {
|
||||
this.infoGroupsContainers[i] = document.createElement("div");
|
||||
this.infoGroupsContainers[i].setAttribute("id", "panel" + i);
|
||||
this.infoGroupsContainers[i].setAttribute("role", "tabpanel");
|
||||
this.infoGroupsContainers[i].setAttribute("tabindex", 0);
|
||||
this.infoGroupsContainers[i].setAttribute("aria-labelledby", "tab" + i);
|
||||
if (i !== 0) {
|
||||
this.infoGroupsContainers[i].setAttribute("hidden", true);
|
||||
}
|
||||
this.infoGroupsContainers[i].classList.add("info-groups");
|
||||
this.shadowRoot.appendChild(this.infoGroupsContainers[i]);
|
||||
|
||||
let final = false;
|
||||
if (i === this.certs.length - 1) {
|
||||
final = true;
|
||||
}
|
||||
|
||||
for (let j = 0; j < certArray.length; j++) {
|
||||
this.infoGroupsContainers[i].appendChild(
|
||||
new InfoGroup(certArray[j], final)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
createTabSection(tabName, i, certificateTabs) {
|
||||
let tab = document.createElement("button");
|
||||
tab.textContent = tabName;
|
||||
tab.setAttribute("id", normalizeToKebabCase(tabName));
|
||||
tab.setAttribute("aria-controls", "panel" + i);
|
||||
tab.setAttribute("idnumber", i);
|
||||
tab.setAttribute("role", "tab");
|
||||
tab.classList.add("certificate-tab");
|
||||
tab.classList.add("tab");
|
||||
certificateTabs.appendChild(tab);
|
||||
|
||||
// If it is the first tab, allow it to be tabbable by the user.
|
||||
// If it isn't the first tab, do not allow tab functionality,
|
||||
// as arrow functionality is implemented in certviewer.js.
|
||||
if (i === 0) {
|
||||
tab.classList.add("selected");
|
||||
tab.setAttribute("tabindex", 0);
|
||||
} else {
|
||||
tab.setAttribute("tabindex", -1);
|
||||
}
|
||||
this.infoGroupsContainers[0].classList.add("selected");
|
||||
}
|
||||
|
||||
updateSelectedTab(index) {
|
||||
this.certificateTabsSection.updateSelectedTab(index);
|
||||
let tabs = this.shadowRoot.querySelectorAll(".certificate-tab");
|
||||
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
tabs[i].classList.remove("selected");
|
||||
}
|
||||
tabs[index].classList.add("selected");
|
||||
}
|
||||
|
||||
updateCertificateSource(index) {
|
||||
this.infoGroupsContainers.updateCertificateSource(index);
|
||||
for (let i = 0; i < this.infoGroupsContainers.length; i++) {
|
||||
this.infoGroupsContainers[i].classList.remove("selected");
|
||||
}
|
||||
this.infoGroupsContainers[index].classList.add("selected");
|
||||
}
|
||||
}
|
||||
customElements.define("certificate-section", CertificateSection);
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
import { normalizeToKebabCase } from "../utils.js";
|
||||
import { updateSelectedItem } from "../certviewer.js";
|
||||
|
||||
export class CertificateTabsSection extends HTMLElement {
|
||||
constructor(isAboutCertificate) {
|
||||
super();
|
||||
this.isAboutCertificate = isAboutCertificate || false;
|
||||
this.connectedCallback();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
let certificateTabsTemplate = document.getElementById(
|
||||
"certificate-tabs-template"
|
||||
);
|
||||
this.attachShadow({ mode: "open" }).appendChild(
|
||||
certificateTabsTemplate.content.cloneNode(true)
|
||||
);
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
this.tabsElement = this.shadowRoot.querySelector(".certificate-tabs");
|
||||
}
|
||||
|
||||
appendChild(child) {
|
||||
this.tabsElement.appendChild(child);
|
||||
}
|
||||
|
||||
createTabSection(tabName, i) {
|
||||
let tab = document.createElement("button");
|
||||
tab.textContent = tabName;
|
||||
tab.setAttribute("id", normalizeToKebabCase(tabName));
|
||||
tab.setAttribute("aria-controls", "panel" + i);
|
||||
tab.setAttribute("idnumber", i);
|
||||
tab.setAttribute("role", "tab");
|
||||
tab.classList.add("certificate-tab");
|
||||
tab.classList.add("tab");
|
||||
if (this.isAboutCertificate) {
|
||||
tab.setAttribute("data-l10n-id", tabName);
|
||||
}
|
||||
this.tabsElement.appendChild(tab);
|
||||
|
||||
// If it is the first tab, allow it to be tabbable by the user.
|
||||
// If it isn't the first tab, do not allow tab functionality,
|
||||
// as arrow functionality is implemented in certviewer.js.
|
||||
if (i === 0) {
|
||||
tab.classList.add("selected");
|
||||
tab.setAttribute("tabindex", 0);
|
||||
} else {
|
||||
tab.setAttribute("tabindex", -1);
|
||||
}
|
||||
}
|
||||
|
||||
updateSelectedTab(index) {
|
||||
let tabs = this.tabsElement.querySelectorAll(".certificate-tab");
|
||||
|
||||
for (let tab of tabs) {
|
||||
tab.classList.remove("selected");
|
||||
}
|
||||
tabs[index].classList.add("selected");
|
||||
}
|
||||
|
||||
/* Information on setAccessibilityEventListeners() can be found
|
||||
* at https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Tab_Role */
|
||||
setAccessibilityEventListeners() {
|
||||
let tabs = this.tabsElement.querySelectorAll('[role="tab"]');
|
||||
|
||||
// Add a click event handler to each tab
|
||||
for (let tab of tabs) {
|
||||
tab.addEventListener("click", e =>
|
||||
updateSelectedItem(e.target.getAttribute("idnumber"))
|
||||
);
|
||||
}
|
||||
|
||||
// Enable arrow navigation between tabs in the tab list
|
||||
let tabFocus = 0;
|
||||
|
||||
this.tabsElement.addEventListener("keydown", e => {
|
||||
// Move right
|
||||
if (e.keyCode === 39 || e.keyCode === 37) {
|
||||
// After navigating away from the current tab,
|
||||
// prevent that tab from being tabbable -
|
||||
// so as to only allow arrow navigation within the tablist.
|
||||
tabs[tabFocus].setAttribute("tabindex", -1);
|
||||
if (e.keyCode === 39) {
|
||||
tabFocus++;
|
||||
// If we're at the end, go to the start
|
||||
if (tabFocus > tabs.length - 1) {
|
||||
tabFocus = 0;
|
||||
}
|
||||
// Move left
|
||||
} else if (e.keyCode === 37) {
|
||||
tabFocus--;
|
||||
// If we're at the start, move to the end
|
||||
if (tabFocus < 0) {
|
||||
tabFocus = tabs.length;
|
||||
}
|
||||
}
|
||||
tabs[tabFocus].setAttribute("tabindex", 0);
|
||||
tabs[tabFocus].focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("certificate-tabs-section", CertificateTabsSection);
|
|
@ -1,65 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
import { InfoGroup } from "./info-group.js";
|
||||
import { AboutCertificateItems } from "./about-certificate-items.js";
|
||||
|
||||
export class InfoGroupContainer extends HTMLElement {
|
||||
constructor(isAboutCertificate = false) {
|
||||
super();
|
||||
this.infoGroupsContainers = [];
|
||||
this.isAboutCertificate = isAboutCertificate;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
let infoGroupContainerTemplate = document.getElementById(
|
||||
"info-groups-template"
|
||||
);
|
||||
this.attachShadow({ mode: "open" }).appendChild(
|
||||
infoGroupContainerTemplate.content.cloneNode(true)
|
||||
);
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {}
|
||||
|
||||
createInfoGroupsContainers(certArray, i, final, certData = []) {
|
||||
this.infoGroupsContainers[i] = document.createElement("div");
|
||||
this.infoGroupsContainers[i].setAttribute("id", "panel" + i);
|
||||
this.infoGroupsContainers[i].setAttribute("role", "tabpanel");
|
||||
this.infoGroupsContainers[i].setAttribute("tabindex", 0);
|
||||
this.infoGroupsContainers[i].setAttribute("aria-labelledby", "tab" + i);
|
||||
// Hiding all the certificzte contents except for the first tab that is
|
||||
// selected and shown by default
|
||||
if (i !== 0) {
|
||||
this.infoGroupsContainers[i].setAttribute("hidden", true);
|
||||
}
|
||||
this.infoGroupsContainers[i].classList.add("info-groups");
|
||||
|
||||
if (this.isAboutCertificate) {
|
||||
this.infoGroupsContainers[i].appendChild(
|
||||
new AboutCertificateItems(certData.name, certData.data)
|
||||
);
|
||||
} else {
|
||||
for (let j = 0; j < certArray.length; j++) {
|
||||
this.infoGroupsContainers[i].appendChild(
|
||||
new InfoGroup(certArray[j], final)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addClass(className, index) {
|
||||
this.infoGroupsContainers[index].classList.add(className);
|
||||
}
|
||||
|
||||
updateCertificateSource(index) {
|
||||
for (let i = 0; i < this.infoGroupsContainers.length; i++) {
|
||||
this.infoGroupsContainers[i].classList.remove("selected");
|
||||
}
|
||||
this.infoGroupsContainers[index].classList.add("selected");
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("info-group-container", InfoGroupContainer);
|
|
@ -1,43 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
:host {
|
||||
display: grid;
|
||||
padding: 1em 0 1em;
|
||||
background-color: #f1f1f1;
|
||||
border-style: solid;
|
||||
border-color: #363535;
|
||||
border-width: .5px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:host(:hover) {
|
||||
background-color: #f9f9fa;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.cert-url {
|
||||
padding-left: 0.8em;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.export {
|
||||
position: absolute;
|
||||
right: 2em;
|
||||
top: 0.3em;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.export a {
|
||||
position: relative;
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
/* 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/. */
|
||||
|
||||
import { normalizeToKebabCase } from "../utils.js";
|
||||
|
||||
export class ListItem extends HTMLElement {
|
||||
constructor(item) {
|
||||
super();
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
let ListItemTemplate = document.getElementById("list-item-template");
|
||||
|
||||
this.attachShadow({ mode: "open" }).appendChild(
|
||||
ListItemTemplate.content.cloneNode(true)
|
||||
);
|
||||
|
||||
document.l10n.translateFragment(this.shadowRoot);
|
||||
document.l10n.connectRoot(this.shadowRoot);
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
let label = this.shadowRoot.querySelector(".item-name");
|
||||
label.textContent = this.item.displayName;
|
||||
|
||||
this.handleExport();
|
||||
|
||||
let link = this.shadowRoot.querySelector(".cert-url");
|
||||
let derb64 = encodeURIComponent(this.item.derb64);
|
||||
let url = `about:certificate?cert=${derb64}`;
|
||||
link.setAttribute("href", url);
|
||||
}
|
||||
|
||||
handleExport() {
|
||||
let exportButton = this.shadowRoot.querySelector(".export");
|
||||
// Wrap the Base64 string into lines of 64 characters,
|
||||
// with CRLF line breaks (as specified in RFC 1421).
|
||||
let wrapped = this.item.derb64.replace(/(\S{64}(?!$))/g, "$1\r\n");
|
||||
let download =
|
||||
"-----BEGIN CERTIFICATE-----\r\n" +
|
||||
wrapped +
|
||||
"\r\n-----END CERTIFICATE-----\r\n";
|
||||
|
||||
let element = document.createElement("a");
|
||||
element.setAttribute("href", "data:," + encodeURI(download));
|
||||
let fileName = normalizeToKebabCase(this.item.displayName);
|
||||
document.l10n.setAttributes(element, "certificate-viewer-export", {
|
||||
fileName,
|
||||
});
|
||||
exportButton.appendChild(element);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("list-item", ListItem);
|
|
@ -6,21 +6,14 @@ toolkit.jar:
|
|||
content/global/certviewer/certviewer.html (content/certviewer.html)
|
||||
content/global/certviewer/certviewer.css (content/certviewer.css)
|
||||
content/global/certviewer/certviewer.js (content/certviewer.js)
|
||||
content/global/certviewer/components/about-certificate-section.js (content/components/about-certificate-section.js)
|
||||
content/global/certviewer/components/about-certificate-section.css (content/components/about-certificate-section.css)
|
||||
content/global/certviewer/components/about-certificate-items.js (content/components/about-certificate-items.js)
|
||||
content/global/certviewer/components/certificate-section.js (content/components/certificate-section.js)
|
||||
content/global/certviewer/components/certificate-tabs-section.js (content/components/certificate-tabs-section.js)
|
||||
content/global/certviewer/components/certificate-section.css (content/components/certificate-section.css)
|
||||
content/global/certviewer/components/error-section.js (content/components/error-section.js)
|
||||
content/global/certviewer/components/error-section.css (content/components/error-section.css)
|
||||
content/global/certviewer/components/info-group.js (content/components/info-group.js)
|
||||
content/global/certviewer/components/info-group.css (content/components/info-group.css)
|
||||
content/global/certviewer/components/info-group-container.js (content/components/info-group-container.js)
|
||||
content/global/certviewer/components/info-item.js (content/components/info-item.js)
|
||||
content/global/certviewer/components/info-item.css (content/components/info-item.css)
|
||||
content/global/certviewer/components/list-item.js (content/components/list-item.js)
|
||||
content/global/certviewer/components/list-item.css (content/components/list-item.css)
|
||||
content/global/certviewer/certDecoder.js (content/certDecoder.js)
|
||||
content/global/certviewer/strings.js (content/strings.js)
|
||||
content/global/certviewer/ctlognames.js (content/ctlognames.js)
|
||||
|
|
|
@ -14,9 +14,5 @@ MOCHITEST_CHROME_MANIFESTS += [
|
|||
'tests/chrome/chrome.ini'
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'AboutCertViewerHandler.jsm',
|
||||
]
|
||||
|
||||
with Files('**'):
|
||||
BUG_COMPONENT = ("Firefox", "Security")
|
||||
|
|
|
@ -8,7 +8,6 @@ support-files =
|
|||
[browser_checkNonRepeatedCertTabs.js]
|
||||
[browser_checkNonUndefinedStrings.js]
|
||||
[browser_checkOCSP.js]
|
||||
[browser_checkStandAlonePage.js]
|
||||
[browser_checkAuthorityKeyID.js]
|
||||
[browser_checkValiditySection.js]
|
||||
[browser_handleMultipleCertsURL.js]
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -1,185 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const TYPE_UNKNOWN = 0;
|
||||
const TYPE_CA = 1;
|
||||
const TYPE_USER = 2;
|
||||
const TYPE_EMAIL = 4;
|
||||
const TYPE_SERVER = 8;
|
||||
const TYPE_ANY = 0xffff;
|
||||
|
||||
add_task(async function test_certificateItems() {
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(
|
||||
gBrowser,
|
||||
"about:certificate"
|
||||
);
|
||||
});
|
||||
|
||||
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function() {
|
||||
let aboutCertificateSection = await ContentTaskUtils.waitForCondition(
|
||||
() => {
|
||||
return content.document.querySelector("about-certificate-section");
|
||||
},
|
||||
"Found aboutCertificateSection."
|
||||
);
|
||||
|
||||
let certificateTabs = aboutCertificateSection.shadowRoot.querySelectorAll(
|
||||
".certificate-tab"
|
||||
);
|
||||
let expected = [
|
||||
"Unknown",
|
||||
"Authorities",
|
||||
"Servers",
|
||||
"People",
|
||||
"Your Certificates",
|
||||
];
|
||||
Assert.ok(certificateTabs, "Certificate tabs should exist.");
|
||||
Assert.equal(
|
||||
certificateTabs.length,
|
||||
expected.length,
|
||||
`There should be ${expected.length} tabs.`
|
||||
);
|
||||
let checked = []; // to avoid repeated tabs
|
||||
for (let tab of certificateTabs) {
|
||||
Assert.ok(
|
||||
expected.includes(tab.textContent) &&
|
||||
!checked.includes(tab.textContent),
|
||||
`${tab.textContent} should be one tab`
|
||||
);
|
||||
checked.push(tab.textContent);
|
||||
}
|
||||
|
||||
let certificateItems = aboutCertificateSection.shadowRoot.querySelectorAll(
|
||||
"about-certificate-items"
|
||||
);
|
||||
Assert.ok(certificateItems, "Certificate items should exist.");
|
||||
Assert.equal(
|
||||
certificateItems.length,
|
||||
certificateTabs.length,
|
||||
`There should be ${certificateTabs.length} certificate items`
|
||||
);
|
||||
|
||||
for (let item of certificateItems) {
|
||||
let listItems = item.shadowRoot.querySelectorAll("list-item");
|
||||
Assert.ok(listItems, "list items should exist");
|
||||
}
|
||||
});
|
||||
gBrowser.removeCurrentTab(); // closes about:certificate
|
||||
});
|
||||
|
||||
async function checkItem(expected) {
|
||||
await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
|
||||
gBrowser.selectedTab = BrowserTestUtils.addTab(
|
||||
gBrowser,
|
||||
"about:certificate"
|
||||
);
|
||||
});
|
||||
|
||||
await SpecialPowers.spawn(
|
||||
gBrowser.selectedBrowser,
|
||||
[expected],
|
||||
async function(expected) {
|
||||
let aboutCertificateSection = await ContentTaskUtils.waitForCondition(
|
||||
() => {
|
||||
return content.document.querySelector("about-certificate-section");
|
||||
},
|
||||
"Found aboutCertificateSection."
|
||||
);
|
||||
|
||||
let tab = aboutCertificateSection.shadowRoot.querySelector(
|
||||
`.certificate-tabs #certificate-viewer-tab-${expected.certificateItemsID}`
|
||||
);
|
||||
Assert.ok(tab, `${expected.tabName} tab should exist.`);
|
||||
tab.click();
|
||||
|
||||
let certificateItems = aboutCertificateSection.shadowRoot.querySelector(
|
||||
`.info-groups #certificate-viewer-tab-${expected.certificateItemsID}`
|
||||
);
|
||||
|
||||
let listItems = certificateItems.shadowRoot.querySelectorAll("list-item");
|
||||
if (expected.displayName == null) {
|
||||
Assert.equal(
|
||||
listItems.length,
|
||||
0,
|
||||
"There shouldn't be elements in the list"
|
||||
);
|
||||
} else {
|
||||
let found = false;
|
||||
for (let item of listItems) {
|
||||
let name = item.shadowRoot.querySelector(".item-name").textContent;
|
||||
if (name == expected.displayName) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Assert.equal(found, true, `${expected.displayName} should be listed`);
|
||||
}
|
||||
}
|
||||
);
|
||||
gBrowser.removeCurrentTab(); // closes about:certificate
|
||||
}
|
||||
|
||||
add_task(async function test_dbItemDisplayed() {
|
||||
let certs = {
|
||||
[TYPE_UNKNOWN]: null,
|
||||
[TYPE_CA]: null,
|
||||
[TYPE_USER]: null,
|
||||
[TYPE_EMAIL]: null,
|
||||
[TYPE_SERVER]: null,
|
||||
[TYPE_ANY]: null,
|
||||
};
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
|
||||
Ci.nsIX509CertDB
|
||||
);
|
||||
Assert.ok(certdb, "certdb not null");
|
||||
let certcache = certdb.getCerts();
|
||||
Assert.ok(certcache, "certcache not null");
|
||||
|
||||
let totalSaved = 0;
|
||||
for (let cert of certcache) {
|
||||
if (totalSaved == certs.length) {
|
||||
break;
|
||||
}
|
||||
if (certs[cert.certType] == null) {
|
||||
totalSaved += 1;
|
||||
certs[cert.certType] = {
|
||||
displayName: cert.displayName,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let tests = [
|
||||
{
|
||||
tabName: "Unknown",
|
||||
displayName: certs[TYPE_UNKNOWN] ? certs[TYPE_UNKNOWN].displayName : null,
|
||||
certificateItemsID: "unkonwn",
|
||||
},
|
||||
{
|
||||
tabName: "Authorities",
|
||||
displayName: certs[TYPE_CA] ? certs[TYPE_CA].displayName : null,
|
||||
certificateItemsID: "ca",
|
||||
},
|
||||
{
|
||||
tabName: "Servers",
|
||||
displayName: certs[TYPE_SERVER] ? certs[TYPE_SERVER].displayName : null,
|
||||
certificateItemsID: "servers",
|
||||
},
|
||||
{
|
||||
tabName: "People",
|
||||
displayName: certs[TYPE_EMAIL] ? certs[TYPE_EMAIL].displayName : null,
|
||||
certificateItemsID: "people",
|
||||
},
|
||||
{
|
||||
tabName: "Your Certificates",
|
||||
displayName: certs[TYPE_USER] ? certs[TYPE_USER].displayName : null,
|
||||
certificateItemsID: "mine",
|
||||
},
|
||||
];
|
||||
|
||||
for (let test of tests) {
|
||||
await checkItem(test);
|
||||
}
|
||||
});
|
|
@ -76,7 +76,6 @@ certificate-viewer-authority-info-aia = Authority Info (AIA)
|
|||
certificate-viewer-certificate-policies = Certificate Policies
|
||||
certificate-viewer-embedded-scts = Embedded SCTs
|
||||
certificate-viewer-crl-endpoints = CRL Endpoints
|
||||
|
||||
# This message is used as a row header in the Miscellaneous section.
|
||||
# The associated data cell contains links to download the certificate.
|
||||
certificate-viewer-download = Download
|
||||
|
@ -95,13 +94,3 @@ certificate-viewer-download-pem = PEM (cert)
|
|||
.download = { $fileName }.pem
|
||||
certificate-viewer-download-pem-chain = PEM (chain)
|
||||
.download = { $fileName }-chain.pem
|
||||
certificate-viewer-export = Export
|
||||
.download = { $fileName }.pem
|
||||
|
||||
## Labels for tabs displayed in stand-alone about:certificate page
|
||||
|
||||
certificate-viewer-tab-mine = Your Certificates
|
||||
certificate-viewer-tab-people = People
|
||||
certificate-viewer-tab-servers = Servers
|
||||
certificate-viewer-tab-ca = Authorities
|
||||
certificate-viewer-tab-unkonwn = Unknown
|
Загрузка…
Ссылка в новой задаче