Support OpenID (#70)

This commit is contained in:
Maxim Baz
2019-04-07 12:55:45 +02:00
committed by GitHub
parent f6c39aa64d
commit 63a81a2055
2 changed files with 77 additions and 51 deletions

View File

@@ -278,13 +278,6 @@ async function dispatchFocusOrSubmit(settings, request, allFrames, allowForeign)
* @return array List of filled fields * @return array List of filled fields
*/ */
async function fillFields(settings, login, fields) { async function fillFields(settings, login, fields) {
// check that required fields are present
for (var field of fields) {
if (login.fields[field] === null) {
throw new Error(`Required field is missing: ${field}`);
}
}
// inject script // inject script
await chrome.tabs.executeScript(settings.tab.id, { await chrome.tabs.executeScript(settings.tab.id, {
allFrames: true, allFrames: true,
@@ -298,49 +291,55 @@ async function fillFields(settings, login, fields) {
fields: fields fields: fields
}; };
// fill form via injected script
let allFrames = false; let allFrames = false;
let allowForeign = false; let allowForeign = false;
let allowNoSecret = false; let allowNoSecret = !fields.includes("secret");
let filledFields = await dispatchFill( let filledFields = [];
settings, let importantFieldToFill = fields.includes("openid") ? "openid" : "secret";
fillRequest,
allFrames, // fill form via injected script
allowForeign, filledFields = filledFields.concat(
allowNoSecret await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
); );
// try again using same-origin frames if we couldn't fill a password field // try again using same-origin frames if we couldn't fill an "important" field
if (!filledFields.includes("secret")) { if (!filledFields.includes(importantFieldToFill)) {
allFrames = true; allFrames = true;
filledFields = filledFields.concat( filledFields = filledFields.concat(
await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret) await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
); );
} }
// try again using all available frames if we couldn't fill a password field // try again using all available frames if we couldn't fill an "important" field
if (!filledFields.includes("secret") && settings.foreignFills[settings.host] !== false) { if (
!filledFields.includes(importantFieldToFill) &&
settings.foreignFills[settings.host] !== false
) {
allowForeign = true; allowForeign = true;
filledFields = filledFields.concat( filledFields = filledFields.concat(
await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret) await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
); );
} }
// try again using same-origin frames, and don't require a password field // try again, but don't require a password field (if it was required until now)
if (!filledFields.length) { if (!allowNoSecret) {
allowForeign = false;
allowNoSecret = true; allowNoSecret = true;
filledFields = filledFields.concat(
await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
);
}
// try again using all available frames, and don't require a password field // try again using same-origin frames
if (!filledFields.length && settings.foreignFills[settings.host] !== false) { if (!filledFields.length) {
allowForeign = true; allowForeign = false;
filledFields = filledFields.concat( filledFields = filledFields.concat(
await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret) await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
); );
}
// try again using all available frames
if (!filledFields.length && settings.foreignFills[settings.host] !== false) {
allowForeign = true;
filledFields = filledFields.concat(
await dispatchFill(settings, fillRequest, allFrames, allowForeign, allowNoSecret)
);
}
} }
if (!filledFields.length) { if (!filledFields.length) {
@@ -350,7 +349,8 @@ async function fillFields(settings, login, fields) {
// build focus or submit request // build focus or submit request
let focusOrSubmitRequest = { let focusOrSubmitRequest = {
origin: new URL(settings.tab.url).origin, origin: new URL(settings.tab.url).origin,
autoSubmit: getSetting("autoSubmit", login, settings) autoSubmit: getSetting("autoSubmit", login, settings),
filledFields: filledFields
}; };
// try to focus or submit form with the settings that were used to fill it // try to focus or submit form with the settings that were used to fill it
@@ -675,8 +675,10 @@ async function handleMessage(settings, message, sendResponse) {
break; break;
case "fill": case "fill":
try { try {
let fields = message.login.fields.openid ? ["openid"] : ["login", "secret"];
// dispatch initial fill request // dispatch initial fill request
var filledFields = await fillFields(settings, message.login, ["login", "secret"]); var filledFields = await fillFields(settings, message.login, fields);
saveRecent(settings, message.login); saveRecent(settings, message.login);
// no need to check filledFields, because fillFields() already throws an error if empty // no need to check filledFields, because fillFields() already throws an error if empty
@@ -751,6 +753,7 @@ async function parseFields(settings, login) {
login.fields = { login.fields = {
secret: ["secret", "password", "pass"], secret: ["secret", "password", "pass"],
login: ["login", "username", "user", "email"], login: ["login", "username", "user", "email"],
openid: ["openid"],
url: ["url", "uri", "website", "site", "link", "launch"] url: ["url", "uri", "website", "site", "link", "launch"]
}; };
login.settings = { login.settings = {

View File

@@ -1,11 +1,11 @@
(function() { (function() {
const FORM_MARKERS = ["login", "log-in", "log_in", "signin", "sign-in", "sign_in"]; const FORM_MARKERS = ["login", "log-in", "log_in", "signin", "sign-in", "sign_in"];
const OPENID_FIELDS = {
selectors: ["input[name*=openid i]", "input[id*=openid i]", "input[class*=openid i]"],
types: ["text"]
};
const USERNAME_FIELDS = { const USERNAME_FIELDS = {
selectors: [ selectors: [
"input[id*=openid i]",
"input[name*=openid i]",
"input[class*=openid i]",
"input[name*=login i]", "input[name*=login i]",
"input[name*=user i]", "input[name*=user i]",
"input[name*=email i]", "input[name*=email i]",
@@ -25,7 +25,9 @@
selectors: ["input[type=password i]"] selectors: ["input[type=password i]"]
}; };
const INPUT_FIELDS = { const INPUT_FIELDS = {
selectors: PASSWORD_FIELDS.selectors.concat(USERNAME_FIELDS.selectors) selectors: PASSWORD_FIELDS.selectors
.concat(USERNAME_FIELDS.selectors)
.concat(OPENID_FIELDS.selectors)
}; };
const SUBMIT_FIELDS = { const SUBMIT_FIELDS = {
selectors: [ selectors: [
@@ -84,10 +86,17 @@
}; };
// get the login form // get the login form
var loginForm = form(); let loginForm = undefined;
if (request.fields.includes("openid")) {
// this is an attempt to fill a form containing only openid field
loginForm = form(OPENID_FIELDS);
} else {
// this is an attempt to fill a regular login form
loginForm = form(INPUT_FIELDS);
}
// don't attempt to fill non-secret forms unless non-secret filling is allowed // don't attempt to fill non-secret forms unless non-secret filling is allowed
if (!find(PASSWORD_FIELDS, loginForm) && !request.allowNoSecret) { if (!request.allowNoSecret && !find(PASSWORD_FIELDS, loginForm)) {
return result; return result;
} }
@@ -126,6 +135,14 @@
result.filledFields.push("secret"); result.filledFields.push("secret");
} }
// fill openid field
if (
request.fields.includes("openid") &&
update(OPENID_FIELDS, request.login.fields.openid, loginForm)
) {
result.filledFields.push("openid");
}
// finished filling things successfully // finished filling things successfully
return result; return result;
} }
@@ -144,7 +161,14 @@
}; };
// get the login form // get the login form
var loginForm = form(); let loginForm = undefined;
if (request.filledFields.includes("openid")) {
// this is an attempt to focus or submit a form containing only openid field
loginForm = form(OPENID_FIELDS);
} else {
// this is an attempt to focus or submit a regular login form
loginForm = form(INPUT_FIELDS);
}
// ensure the origin is the same or allowed // ensure the origin is the same or allowed
if (window.location.origin !== request.origin) { if (window.location.origin !== request.origin) {
@@ -176,13 +200,11 @@
result.needPressEnter = true; result.needPressEnter = true;
} }
// We need to keep focus somewhere within the form, so that Enter hopefully submits the form. // We need to keep focus somewhere within the form, so that Enter hopefully submits the form.
var password = find(PASSWORD_FIELDS, loginForm); for (let selectors of [OPENID_FIELDS, PASSWORD_FIELDS, USERNAME_FIELDS]) {
if (password) { let field = find(selectors, loginForm);
password.focus(); if (field) {
} else { field.focus();
var username = find(USERNAME_FIELDS, loginForm); break;
if (username) {
username.focus();
} }
} }
} }
@@ -265,10 +287,11 @@
* *
* @since 3.0.0 * @since 3.0.0
* *
* @param array selectors Selectors to use to find the right form
* @return The login form * @return The login form
*/ */
function form() { function form(selectors) {
const elems = queryAllVisible(document, INPUT_FIELDS, undefined); const elems = queryAllVisible(document, selectors, undefined);
const forms = []; const forms = [];
for (let elem of elems) { for (let elem of elems) {
const form = elem.form; const form = elem.form;