mirror of
https://github.com/XFox111/PasswordGeneratorExtension.git
synced 2026-04-22 08:08:01 +03:00
Version 1.0 (initial commit)
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
function AddContextMenu()
|
||||
{
|
||||
chrome.contextMenus.create(
|
||||
{
|
||||
id: "generate",
|
||||
contexts: [ "all" ],
|
||||
title: chrome.i18n.getMessage("generate")
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Setting up context menu event listener
|
||||
chrome.contextMenus.onClicked.addListener(() => GeneratePassword(null));
|
||||
|
||||
// Adding context menu entry if needed
|
||||
chrome.runtime.onInstalled.addListener(() =>
|
||||
{
|
||||
// Adding context menu option
|
||||
chrome.storage.sync.get({ showContext: true }, (settings) =>
|
||||
{
|
||||
if (settings.showContext !== false)
|
||||
AddContextMenu();
|
||||
});
|
||||
});
|
||||
|
||||
chrome.storage.onChanged.addListener((changes, area) =>
|
||||
{
|
||||
if (area != "sync" || changes["showContext"] == null)
|
||||
return;
|
||||
|
||||
if (changes["showContext"].newValue === false)
|
||||
chrome.contextMenus.removeAll();
|
||||
else
|
||||
AddContextMenu();
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
// Loading input fields states
|
||||
chrome.storage.sync.get(
|
||||
{
|
||||
// Set of settings keys we retrieve and their default values
|
||||
// Generator settings
|
||||
length: 16,
|
||||
includeSymbols: true,
|
||||
includeNumbers: true,
|
||||
includeLowercase: true,
|
||||
includeUppercase: true,
|
||||
excludeSimilar: true,
|
||||
excludeSpecial: true,
|
||||
|
||||
// Extension settings
|
||||
showButton: true,
|
||||
showContext: true
|
||||
},
|
||||
(settings) =>
|
||||
{
|
||||
if (window.matchMedia("(prefers-color-scheme: dark)").matches) // Doesn't work on Fiefox
|
||||
document.querySelector("#darkStylesheet").removeAttribute("disabled");
|
||||
|
||||
document.querySelector("#length").value = settings.length; // Setting length value
|
||||
|
||||
// Setting checkboxes
|
||||
[
|
||||
"includeSymbols",
|
||||
"includeNumbers",
|
||||
"includeLowercase",
|
||||
"includeUppercase",
|
||||
"excludeSimilar",
|
||||
"excludeSpecial",
|
||||
|
||||
"showButton",
|
||||
"showContext"
|
||||
].forEach(i => document.querySelector("#" + i).checked = settings[i]);
|
||||
|
||||
SetupEventHandlers();
|
||||
document.querySelector("#version").textContent = "v" + chrome.runtime.getManifest()["version"]; // Updating display version
|
||||
document.querySelectorAll("*[loc]").forEach(i => i.textContent = chrome.i18n.getMessage(i.getAttribute("loc"))); // Updating localization
|
||||
});
|
||||
|
||||
function SetupEventHandlers()
|
||||
{
|
||||
document.querySelectorAll("input").forEach(i =>
|
||||
i.addEventListener("input",
|
||||
() => chrome.storage.sync.set(JSON.parse("{ \"" + i.id + "\": " + (i.type == "checkbox" ? i.checked : i.value) + " }"))));
|
||||
|
||||
document.querySelector("#generate").addEventListener("click", () => GeneratePassword(null));
|
||||
document.querySelector("#more").addEventListener("click", (s) =>
|
||||
{
|
||||
let group = document.querySelector("#about");
|
||||
if (group.hasAttribute("hidden"))
|
||||
{
|
||||
group.removeAttribute("hidden");
|
||||
s.currentTarget.querySelector("i").textContent = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
group.setAttribute("hidden", "");
|
||||
s.currentTarget.querySelector("i").textContent = "";
|
||||
}
|
||||
});
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
// Some constants
|
||||
const upperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
const lowerCase = upperCase.toLowerCase();
|
||||
const numbers = "1234567890";
|
||||
const specialCharacters = "@#$%";
|
||||
const ambiguousCharacters = "{}[]()/\\'\"`~,;:.<>";
|
||||
const similarCharacters = "il1Lo0O";
|
||||
|
||||
chrome.storage.sync.get({ showButton: true },
|
||||
(settings) =>
|
||||
{
|
||||
if (settings.showButton)
|
||||
InsertButtons();
|
||||
}
|
||||
);
|
||||
|
||||
// Adding button below every password field
|
||||
function InsertButtons()
|
||||
{
|
||||
document.querySelectorAll("input[type=password]").forEach(i =>
|
||||
{
|
||||
let actionLink = document.createElement("a");
|
||||
|
||||
actionLink.innerText = chrome.i18n.getMessage("generate");
|
||||
actionLink.style.margin = "5px";
|
||||
actionLink.style.display = "block";
|
||||
|
||||
// Since anchor without 'href' attrubute isn't shown as a hyperlink and '#' link potentially can break some sites logic, we add empty JS function
|
||||
actionLink.href = "javascript:void(0);";
|
||||
|
||||
actionLink.addEventListener("click", GeneratePassword);
|
||||
|
||||
i.insertAdjacentElement("afterend", actionLink); // Adding button after a password field
|
||||
});
|
||||
}
|
||||
|
||||
function GeneratePassword(e)
|
||||
{
|
||||
// Generating password
|
||||
let availableCharacters = ""; // Set of available characters to generate a password from
|
||||
|
||||
chrome.storage.sync.get(
|
||||
{
|
||||
length: 16,
|
||||
includeSymbols: true,
|
||||
includeNumbers: true,
|
||||
includeLowercase: true,
|
||||
includeUppercase: true,
|
||||
excludeSimilar: true,
|
||||
excludeSpecial: true
|
||||
},
|
||||
(settings) =>
|
||||
{
|
||||
// Adding or excluding characters from the set
|
||||
if (settings.includeSymbols)
|
||||
availableCharacters += specialCharacters;
|
||||
if (settings.includeNumbers)
|
||||
availableCharacters += numbers;
|
||||
if (settings.includeLowercase)
|
||||
availableCharacters += lowerCase;
|
||||
if (settings.includeUppercase)
|
||||
availableCharacters += upperCase;
|
||||
if (settings.excludeSimilar)
|
||||
similarCharacters.split("").forEach(i => availableCharacters = availableCharacters.replace(i, ""));
|
||||
if (settings.excludeSpecial === false)
|
||||
availableCharacters += ambiguousCharacters;
|
||||
|
||||
if (availableCharacters.length < 1)
|
||||
{
|
||||
alert(chrome.i18n.getMessage("fail"));
|
||||
return;
|
||||
}
|
||||
|
||||
let password = "";
|
||||
for (k = 0; k < settings.length; k++)
|
||||
password += availableCharacters[GetRandomInt(0, availableCharacters.length)]; // Picking random characters
|
||||
|
||||
let field = e?.target.previousElementSibling;
|
||||
// Creating a hidden field if called as standalone
|
||||
if (!field)
|
||||
{
|
||||
field = document.createElement("input");
|
||||
document.body.appendChild(field);
|
||||
}
|
||||
|
||||
field.value = password; // Setting generated password to the field
|
||||
|
||||
field.setAttribute("type", "text"); // Since we cannot copy text from a password field, we'll make it temporarly simple field
|
||||
|
||||
// Some JS clipboard copying stuff
|
||||
field.select();
|
||||
document.execCommand("copy");
|
||||
|
||||
// Setting field type back to 'password'
|
||||
field.setAttribute("type", "password");
|
||||
|
||||
if (!e)
|
||||
field.remove();
|
||||
|
||||
alert(chrome.i18n.getMessage("success"));
|
||||
});
|
||||
}
|
||||
|
||||
// See https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Math/random
|
||||
function GetRandomInt(min, max)
|
||||
{
|
||||
return Math.floor(Math.random() * (max - min)) + min;
|
||||
}
|
||||
Reference in New Issue
Block a user