forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			430 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			430 lines
		
	
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* 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;
 | |
|     document.l10n.setAttributes(descriptionColumn, `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);
 | |
| }
 | 
