diff options
Diffstat (limited to 'browser/components/enterprisepolicies/content/aboutPolicies.js')
-rw-r--r-- | browser/components/enterprisepolicies/content/aboutPolicies.js | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/browser/components/enterprisepolicies/content/aboutPolicies.js b/browser/components/enterprisepolicies/content/aboutPolicies.js new file mode 100644 index 0000000000..e2c90167c4 --- /dev/null +++ b/browser/components/enterprisepolicies/content/aboutPolicies.js @@ -0,0 +1,430 @@ +/* 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"; + +const { XPCOMUtils } = ChromeUtils.importESModule( + "resource://gre/modules/XPCOMUtils.sys.mjs" +); + +ChromeUtils.defineESModuleGetters(this, { + schema: "resource:///modules/policies/schema.sys.mjs", +}); + +function col(text, className) { + let column = document.createElement("td"); + if (className) { + column.classList.add(className); + } + let content = document.createTextNode(text); + column.appendChild(content); + return column; +} + +function link(text) { + let column = document.createElement("td"); + let a = document.createElement("a"); + a.href = "https://mozilla.github.io/policy-templates/#" + text.toLowerCase(); + a.target = "_blank"; + let content = document.createTextNode(text); + a.appendChild(content); + column.appendChild(a); + return column; +} + +function addMissingColumns() { + const table = document.getElementById("activeContent"); + let maxColumns = 0; + + // count the number of columns per row and set the max number of columns + for (let i = 0, length = table.rows.length; i < length; i++) { + if (maxColumns < table.rows[i].cells.length) { + maxColumns = table.rows[i].cells.length; + } + } + + // add the missing columns + for (let i = 0, length = table.rows.length; i < length; i++) { + const rowLength = table.rows[i].cells.length; + + if (rowLength < maxColumns) { + let missingColumns = maxColumns - rowLength; + + while (missingColumns > 0) { + table.rows[i].insertCell(); + missingColumns--; + } + } + } +} + +/* + * This function generates the Active Policies content to be displayed by calling + * a recursive function called generatePolicy() according to the policy schema. + */ + +function generateActivePolicies(data) { + let new_cont = document.getElementById("activeContent"); + new_cont.classList.add("active-policies"); + + let policy_count = 0; + + for (let policyName in data) { + const color_class = ++policy_count % 2 === 0 ? "even" : "odd"; + + if (schema.properties[policyName].type == "array") { + for (let count in data[policyName]) { + let isFirstRow = count == 0; + let isLastRow = count == data[policyName].length - 1; + let row = document.createElement("tr"); + row.classList.add(color_class); + row.appendChild(col(isFirstRow ? policyName : "")); + generatePolicy( + data[policyName][count], + row, + 1, + new_cont, + isLastRow, + data[policyName].length > 1 + ); + } + } else if (schema.properties[policyName].type == "object") { + let count = 0; + for (let obj in data[policyName]) { + let isFirstRow = count == 0; + let isLastRow = count == Object.keys(data[policyName]).length - 1; + let row = document.createElement("tr"); + row.classList.add(color_class); + row.appendChild(col(isFirstRow ? policyName : "")); + row.appendChild(col(obj)); + generatePolicy( + data[policyName][obj], + row, + 2, + new_cont, + isLastRow, + true + ); + count++; + } + } else { + let row = document.createElement("tr"); + row.appendChild(col(policyName)); + row.appendChild(col(JSON.stringify(data[policyName]))); + row.classList.add(color_class, "last_row"); + new_cont.appendChild(row); + } + } + + if (policy_count < 1) { + let current_tab = document.querySelector(".active"); + if (Services.policies.status == Services.policies.ACTIVE) { + current_tab.classList.add("no-specified-policies"); + } else { + current_tab.classList.add("inactive-service"); + } + } + + addMissingColumns(); +} + +/* + * This is a helper recursive function that iterates levels of each + * policy and formats the content to be displayed accordingly. + */ + +function generatePolicy(data, row, depth, new_cont, islast, arr_sep = false) { + const color_class = row.classList.contains("odd") ? "odd" : "even"; + + if (Array.isArray(data)) { + for (let count in data) { + if (count == 0) { + if (count == data.length - 1) { + generatePolicy( + data[count], + row, + depth + 1, + new_cont, + islast ? islast : false, + true + ); + } else { + generatePolicy(data[count], row, depth + 1, new_cont, false, false); + } + } else if (count == data.length - 1) { + let last_row = document.createElement("tr"); + last_row.classList.add(color_class, "arr_sep"); + + for (let i = 0; i < depth; i++) { + last_row.appendChild(col("")); + } + + generatePolicy( + data[count], + last_row, + depth + 1, + new_cont, + islast ? islast : false, + arr_sep + ); + } else { + let new_row = document.createElement("tr"); + new_row.classList.add(color_class); + + for (let i = 0; i < depth; i++) { + new_row.appendChild(col("")); + } + + generatePolicy(data[count], new_row, depth + 1, new_cont, false, false); + } + } + } else if (typeof data == "object" && Object.keys(data).length) { + let count = 0; + for (let obj in data) { + if (count == 0) { + row.appendChild(col(obj)); + if (count == Object.keys(data).length - 1) { + generatePolicy( + data[obj], + row, + depth + 1, + new_cont, + islast ? islast : false, + arr_sep + ); + } else { + generatePolicy(data[obj], row, depth + 1, new_cont, false, false); + } + } else if (count == Object.keys(data).length - 1) { + let last_row = document.createElement("tr"); + for (let i = 0; i < depth; i++) { + last_row.appendChild(col("")); + } + + last_row.appendChild(col(obj)); + last_row.classList.add(color_class); + + if (arr_sep) { + last_row.classList.add("arr_sep"); + } + + generatePolicy( + data[obj], + last_row, + depth + 1, + new_cont, + islast ? islast : false, + false + ); + } else { + let new_row = document.createElement("tr"); + new_row.classList.add(color_class); + + for (let i = 0; i < depth; i++) { + new_row.appendChild(col("")); + } + + new_row.appendChild(col(obj)); + generatePolicy(data[obj], new_row, depth + 1, new_cont, false, false); + } + count++; + } + } else { + row.appendChild(col(JSON.stringify(data))); + + if (arr_sep) { + row.classList.add("arr_sep"); + } + if (islast) { + row.classList.add("last_row"); + } + new_cont.appendChild(row); + } +} + +function generateErrors() { + const consoleStorage = Cc["@mozilla.org/consoleAPI-storage;1"]; + const storage = consoleStorage.getService(Ci.nsIConsoleAPIStorage); + const consoleEvents = storage.getEvents(); + const prefixes = [ + "Enterprise Policies", + "JsonSchemaValidator.jsm", + "Policies.jsm", + "GPOParser.jsm", + "Enterprise Policies Child", + "BookmarksPolicies.jsm", + "ProxyPolicies.jsm", + "WebsiteFilter Policy", + "macOSPoliciesParser.jsm", + ]; + + let new_cont = document.getElementById("errorsContent"); + new_cont.classList.add("errors"); + + let flag = false; + for (let err of consoleEvents) { + if (prefixes.includes(err.prefix)) { + flag = true; + let row = document.createElement("tr"); + row.appendChild(col(err.arguments[0])); + new_cont.appendChild(row); + } + } + if (!flag) { + let errors_tab = document.getElementById("category-errors"); + errors_tab.style.display = "none"; + } +} + +function generateDocumentation() { + let new_cont = document.getElementById("documentationContent"); + new_cont.setAttribute("id", "documentationContent"); + + // map specific policies to a different string ID, to allow updates to + // existing descriptions + let string_mapping = { + BackgroundAppUpdate: "BackgroundAppUpdate2", + Certificates: "CertificatesDescription", + DisableMasterPasswordCreation: "DisablePrimaryPasswordCreation", + DisablePocket: "DisablePocket2", + DisableSetDesktopBackground: "DisableSetAsDesktopBackground", + FirefoxHome: "FirefoxHome2", + Permissions: "Permissions2", + SanitizeOnShutdown: "SanitizeOnShutdown2", + WindowsSSO: "Windows10SSO", + SecurityDevices: "SecurityDevices2", + }; + + for (let policyName in schema.properties) { + let main_tbody = document.createElement("tbody"); + main_tbody.classList.add("collapsible"); + main_tbody.addEventListener("click", function () { + let content = this.nextElementSibling; + content.classList.toggle("content"); + }); + let row = document.createElement("tr"); + row.appendChild(link(policyName)); + let descriptionColumn = col(""); + let stringID = string_mapping[policyName] || policyName; + descriptionColumn.setAttribute("data-l10n-id", `policy-${stringID}`); + row.appendChild(descriptionColumn); + main_tbody.appendChild(row); + let sec_tbody = document.createElement("tbody"); + sec_tbody.classList.add("content"); + sec_tbody.classList.add("content-style"); + let schema_row = document.createElement("tr"); + if (schema.properties[policyName].properties) { + let column = col( + JSON.stringify(schema.properties[policyName].properties, null, 1), + "schema" + ); + column.colSpan = "2"; + schema_row.appendChild(column); + sec_tbody.appendChild(schema_row); + } else if (schema.properties[policyName].items) { + let column = col( + JSON.stringify(schema.properties[policyName], null, 1), + "schema" + ); + column.colSpan = "2"; + schema_row.appendChild(column); + sec_tbody.appendChild(schema_row); + } else { + let column = col("type: " + schema.properties[policyName].type, "schema"); + column.colSpan = "2"; + schema_row.appendChild(column); + sec_tbody.appendChild(schema_row); + if (schema.properties[policyName].enum) { + let enum_row = document.createElement("tr"); + column = col( + "enum: " + + JSON.stringify(schema.properties[policyName].enum, null, 1), + "schema" + ); + column.colSpan = "2"; + enum_row.appendChild(column); + sec_tbody.appendChild(enum_row); + } + } + new_cont.appendChild(main_tbody); + new_cont.appendChild(sec_tbody); + } +} + +let gInited = false; +window.onload = function () { + if (gInited) { + return; + } + gInited = true; + + let data = Services.policies.getActivePolicies(); + generateActivePolicies(data); + generateErrors(); + generateDocumentation(); + + // Event delegation on #categories element + let menu = document.getElementById("categories"); + for (let category of menu.children) { + category.addEventListener("click", () => show(category)); + category.addEventListener("keypress", function (event) { + if (event.keyCode == KeyEvent.DOM_VK_RETURN) { + show(category); + } + }); + } + + if (location.hash) { + let sectionButton = document.getElementById( + "category-" + location.hash.substring(1) + ); + if (sectionButton) { + sectionButton.click(); + } + } + + window.addEventListener("hashchange", function () { + if (location.hash) { + let sectionButton = document.getElementById( + "category-" + location.hash.substring(1) + ); + sectionButton.click(); + } + }); +}; + +function show(button) { + let current_tab = document.querySelector(".active"); + let category = button.getAttribute("id").substring("category-".length); + let content = document.getElementById(category); + if (current_tab == content) { + return; + } + saveScrollPosition(current_tab.id); + current_tab.classList.remove("active"); + current_tab.hidden = true; + content.classList.add("active"); + content.hidden = false; + + let current_button = document.querySelector("[selected=true]"); + current_button.removeAttribute("selected"); + button.setAttribute("selected", "true"); + + let title = document.getElementById("sectionTitle"); + title.textContent = button.textContent; + location.hash = category; + restoreScrollPosition(category); +} + +const scrollPositions = {}; +function saveScrollPosition(category) { + const mainContent = document.querySelector(".main-content"); + scrollPositions[category] = mainContent.scrollTop; +} + +function restoreScrollPosition(category) { + const scrollY = scrollPositions[category] || 0; + const mainContent = document.querySelector(".main-content"); + mainContent.scrollTo(0, scrollY); +} |