Implement fetch (#4)

* Implement fetch & launch action
* Fix scroll behavior
* Remove horizontal scrollbar
* Add stubs for filling username / password
* Don't pre-filter for chrome:// URLs
* Add inject.js
This commit is contained in:
Erayd
2018-04-20 00:40:22 +12:00
committed by GitHub
parent 92f2ecea1b
commit 9ca48cea41
9 changed files with 175 additions and 13 deletions

View File

@@ -60,6 +60,12 @@ async function handleMessage(settings, message, sendResponse) {
sendResponse({ status: "error", message: "Action is missing" });
}
// fetch file & parse fields if a login entry is present
if (typeof message.login !== "undefined") {
await parseFields(settings, message.login);
}
// route action
switch (message.action) {
case "getSettings":
sendResponse({
@@ -76,7 +82,53 @@ async function handleMessage(settings, message, sendResponse) {
var response = await hostAction(settings, "list");
sendResponse(response.data.files);
} catch (e) {
console.log(e);
sendResponse({
status: "error",
message: "Unable to enumerate password files" + e.toString()
});
}
break;
case "launch":
try {
var tab = (await browser.tabs.query({ active: true, currentWindow: true }))[0];
var url = message.login.fields.url ? message.login.fields.url : response.login.url;
if (!url.match(/:\/\//)) {
url = "http://" + url;
}
chrome.tabs.update(tab.id, { url: url });
sendResponse({ status: "ok" });
} catch (e) {
sendResponse({
status: "error",
message: "Unable to launch URL: " + e.toString()
});
}
break;
case "fill":
try {
var tab = (await browser.tabs.query({ active: true, currentWindow: true }))[0];
await browser.tabs.executeScript(tab.id, { file: "js/inject.dist.js" });
// check login fields
if (message.login.fields.login === null) {
throw new Error("No login is available");
}
if (message.login.fields.secret === null) {
throw new Error("No password is available");
}
var fillFields = JSON.stringify({
login: message.login.fields.login,
secret: message.login.fields.secret
});
// fill form via injected script
await browser.tabs.executeScript(tab.id, {
code: `window.browserpass.fillLogin(${fillFields});`
});
sendResponse({ status: "ok" });
} catch (e) {
sendResponse({
status: "error",
message: "Unable to fill credentials: " + e.toString()
});
}
break;
default:
@@ -110,6 +162,65 @@ function hostAction(settings, action, params = {}) {
return browser.runtime.sendNativeMessage(appID, request);
}
/**
* Fetch file & parse fields
*
* @since 3.0.0
*
* @param object settings Settings object
* @param object login Login object
* @return void
*/
async function parseFields(settings, login) {
var response = await hostAction(settings, "fetch", {
store: login.store,
file: login.login + ".gpg"
});
if (response.status != "ok") {
throw new Error(JSON.stringify(response)); // TODO handle host error
}
// save raw data inside login
login.raw = response.data.contents;
// parse lines
login.fields = {
secret: ["secret", "password", "pass"],
login: ["login", "username", "user", "email"],
url: ["url", "uri", "website", "site", "link", "launch"]
};
var lines = login.raw.split(/[\r\n]+/).filter(line => line.trim().length > 0);
lines.forEach(function(line) {
// split key / value
var parts = line
.split(":", 2)
.map(value => value.trim())
.filter(value => value.length);
if (parts.length != 2) {
return;
}
// assign to fields
for (var key in login.fields) {
if (Array.isArray(login.fields[key]) && login.fields[key].indexOf(parts[0]) >= 0) {
login.fields[key] = parts[1];
break;
}
}
});
// clean up unassigned fields
for (var key in login.fields) {
if (Array.isArray(login.fields[key])) {
if (key == "secret" && lines.length) {
login.fields.secret = lines[0];
} else {
login.fields[key] = null;
}
}
}
}
/**
* Wrap inbound messages to fetch native configuration
*