-
Notifications
You must be signed in to change notification settings - Fork 80
Add feature to launch URLs & support basic auth #224
Changes from all commits
0efc727
91cc637
a309160
6dc747d
5ec6d76
dd9a741
57f7908
21de295
207c798
fcfe36f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
"author": "Danny van Kooten", | ||
"homepage_url": "https://github.com/dannyvankooten/browserpass", | ||
"background": { | ||
"persistent": false, | ||
"persistent": true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you comment on why this is needed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Chrome doesn't allow non-persistent event pages to use the |
||
"scripts": [ | ||
"background.js" | ||
] | ||
|
@@ -28,6 +28,8 @@ | |
"nativeMessaging", | ||
"notifications", | ||
"storage", | ||
"webRequest", | ||
"webRequestBlocking", | ||
"http://*/*", | ||
"https://*/*" | ||
], | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
|
||
var m = require("mithril"); | ||
var FuzzySort = require("fuzzysort"); | ||
var Tldjs = require("tldjs"); | ||
var app = "com.dannyvankooten.browserpass"; | ||
var activeTab; | ||
var searching = false; | ||
|
@@ -45,6 +46,10 @@ function view() { | |
|
||
return m("div.entry", [ | ||
m(selector, options, login), | ||
m("button.launch.url", { | ||
onclick: launchURL.bind({ entry: login, what: "url" }), | ||
tabindex: -1 | ||
}), | ||
m("button.copy.username", { | ||
onclick: loginToClipboard.bind({ entry: login, what: "username" }), | ||
tabindex: -1 | ||
|
@@ -76,7 +81,7 @@ function view() { | |
type: "text", | ||
id: "search-field", | ||
name: "s", | ||
placeholder: "Search passwords..", | ||
placeholder: "Search passwords...", | ||
autocomplete: "off", | ||
autofocus: "on", | ||
oninput: filterLogins | ||
|
@@ -150,7 +155,6 @@ function showFilterHint(show=true) { | |
|
||
function submitSearchForm(e) { | ||
e.preventDefault(); | ||
|
||
if (fillOnSubmit && logins.length > 0) { | ||
// fill using the first result | ||
getLoginData.bind(logins[0])(); | ||
|
@@ -232,6 +236,50 @@ function getFaviconUrl(domain) { | |
return null; | ||
} | ||
|
||
function launchURL() { | ||
var what = this.what; | ||
var entry = this.entry; | ||
chrome.runtime.sendNativeMessage( | ||
app, | ||
{ action: "get", entry: this.entry }, | ||
function(response) { | ||
if (chrome.runtime.lastError) { | ||
error = chrome.runtime.lastError.message; | ||
m.redraw(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nitpick: could you please reduce the nesting?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure. |
||
return; | ||
} | ||
// get url from login path if not available in the host app response | ||
if (!response.hasOwnProperty("url") || response.url.length == 0) { | ||
var parts = entry.split(/\//).reverse(); | ||
for (var i in parts) { | ||
var part = parts[i]; | ||
var info = Tldjs.parse(part); | ||
if (info.isValid && info.tldExists && info.domain !== null && info.hostname === part) { | ||
response.url = part; | ||
break; | ||
} | ||
} | ||
} | ||
// if a url is present, then launch a new tab via the background script | ||
if (response.hasOwnProperty("url") && response.url.length > 0) { | ||
var url = response.url.match(/^([a-z]+:)?\/\//i) ? response.url : "http://" + response.url; | ||
chrome.runtime.sendMessage({action: "launch", url: url, username: response.u, password: response.p}); | ||
window.close(); | ||
return; | ||
} | ||
// no url available | ||
if (!response.hasOwnProperty("url")) { | ||
resetWithError( | ||
"Unable to determine the URL for this entry. If you have defined one in the password file, " + | ||
"your host application must be at least v2.0.14 for this to be usable." | ||
); | ||
} else { | ||
resetWithError("Unable to determine the URL for this entry."); | ||
} | ||
} | ||
); | ||
} | ||
|
||
function getLoginData() { | ||
searching = true; | ||
logins = resultLogins = []; | ||
|
@@ -298,16 +346,18 @@ function keyHandler(e) { | |
break; | ||
case "c": | ||
if (e.target.id != "search-field" && e.ctrlKey) { | ||
document.activeElement["nextElementSibling"][ | ||
"nextElementSibling" | ||
].click(); | ||
document.activeElement.parentNode.querySelector("button.copy.password").click(); | ||
} | ||
break; | ||
case "C": | ||
if (e.target.id != "search-field") { | ||
document.activeElement["nextElementSibling"].click(); | ||
document.activeElement.parentNode.querySelector("button.copy.username").click(); | ||
} | ||
break; | ||
case "g": | ||
if (e.target.id != "search-field") { | ||
document.activeElement.parentNode.querySelector("button.launch.url").click(); | ||
} | ||
} | ||
} | ||
|
||
|
@@ -336,3 +386,18 @@ function oncreate() { | |
document.getElementById("search-field").focus(); | ||
}, 100); | ||
} | ||
|
||
function resetWithError(errMsg) { | ||
domain = ''; | ||
logins = resultLogins = []; | ||
fillOnSubmit = false; | ||
searching = false; | ||
var filterSearch = document.getElementById("filter-search"); | ||
filterSearch.style.display = "none"; | ||
filterSearch.textContent = ''; | ||
var searchField = document.getElementById("search-field"); | ||
searchField.setAttribute("placeholder", "Search passwords..."); | ||
error = errMsg; | ||
m.redraw(); | ||
searchField.focus(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@erayd do you think this code should also compare
tabId
with thetab.id
before removing the listeners?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't need to, because the listeners are specific to the tab anyway.
There is a security problem, but that's not it. I'm filing an issue now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure that this doesn't register a listener that fires for all tabs? Maybe it's just a weird API, but the tab object is not used when registering the listener, and the
tabId
is provided as a first argument for a reason, both of these lead me to think that this will fire for all tabs...I know that this is not about the security problem, it's just what I accidentally stumbled upon 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooh, good point. The
onAuthRequested
handler is specific to the tab, but the status listener is not. My bad.I'm going to roll the security fix PR right now - I feel quite bad I didn't notice that in the first place; I'm normally more careful than that. I will fix this at the same time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!