form detection w/site configs and ajax
This commit is contained in:
Родитель
5df0ec63cf
Коммит
3736e850e2
|
@ -9,3 +9,5 @@ Setup
|
|||
-----
|
||||
|
||||
Make sure to check out submodules (` git submodule update --init `) before running.
|
||||
|
||||
Building the site configuration file requires running `build_site_configs.rb`. This is only needed when site_configs.yml is updated. This script uses the js-yaml commmand line tool [https://github.com/nodeca/js-yaml], which must be in your PATH.
|
|
@ -1,6 +1,8 @@
|
|||
<!doctype html>
|
||||
<script src="../lib/jquery.js"></script>
|
||||
<script src="../lib/jsuri.js"></script>
|
||||
<script src="../lib/tldjs.js"></script>
|
||||
<script src="../lib/js-yaml.js"></script>
|
||||
<script src="../infobar/manager.js"></script>
|
||||
<script src="util.js"></script>
|
||||
<script src="browser_action_interface.js"></script>
|
||||
|
@ -10,8 +12,8 @@
|
|||
<script src="chrome_messaging.js"></script>
|
||||
<script src="command_handler.js"></script>
|
||||
<script src="storage.js"></script>
|
||||
<script src="tld_service.js"></script>
|
||||
<script src="captured_credential_storage.js"></script>
|
||||
<script src="site_configs.js"></script>
|
||||
<script src="main.js"></script>
|
||||
<body>
|
||||
<!-- Invisible <textarea> used to copy data onto the clipboard -->
|
||||
|
|
|
@ -14,12 +14,9 @@ var CapturedCredentialStorage = function(TldService) {
|
|||
// id: identifier for the credential's source
|
||||
// url: url of the credential's source
|
||||
function setCredentials(credentials, source) {
|
||||
var callback = function(tld) {
|
||||
credentials.domain = tld;
|
||||
credentials.domain = TldService.getDomain((new Uri(source.url)).host());
|
||||
storage[source.id] = credentials;
|
||||
console.log("Storing credentials", credentials);
|
||||
};
|
||||
TldService.tldForDomain((new Uri(source.url)).host(), callback);
|
||||
}
|
||||
|
||||
function getCrendentials(credentials, source, callback) {
|
||||
|
|
|
@ -124,7 +124,7 @@ var CommandHandler = function(Messaging, CapturedCredentialStorage) {
|
|||
}
|
||||
|
||||
function getSavedCredentials(message, sender, callback) {
|
||||
var hostname = (new Uri(sender.tab.url)).host();
|
||||
var hostname = Gombot.TldService.getDomain((new Uri(sender.tab.url)).host());
|
||||
getLoginsForSite(hostname, function(logins) {
|
||||
callback(logins);
|
||||
});
|
||||
|
@ -148,6 +148,10 @@ var CommandHandler = function(Messaging, CapturedCredentialStorage) {
|
|||
return true;
|
||||
}
|
||||
|
||||
function getSiteConfig(message, sender, callback) {
|
||||
callback(Gombot.SiteConfigs[Gombot.TldService.getDomain(new Uri(sender.tab.url).host())] || {});
|
||||
}
|
||||
|
||||
var commandHandlers = {
|
||||
'add_login': addLogin,
|
||||
'observing_page': observingPage,
|
||||
|
@ -156,7 +160,8 @@ var CommandHandler = function(Messaging, CapturedCredentialStorage) {
|
|||
'set_captured_credentials': setCapturedCredentials,
|
||||
'get_captured_credentials': getCapturedCredentials,
|
||||
'delete_captured_credentials': deleteCapturedCredentials,
|
||||
'get_saved_credentials': getSavedCredentials
|
||||
'get_saved_credentials': getSavedCredentials,
|
||||
'get_site_config': getSiteConfig
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
@ -10,7 +10,8 @@ initGombot();
|
|||
|
||||
var Gombot = {};
|
||||
Gombot.Messaging = ChromeMessaging();
|
||||
Gombot.TldService = TldService();
|
||||
Gombot.TldService = Tld;
|
||||
Gombot.SiteConfigs = SiteConfigs;
|
||||
Gombot.CapturedCredentialStorage = CapturedCredentialStorage(Gombot.TldService);
|
||||
Gombot.CommandHandler = CommandHandler(Gombot.Messaging, Gombot.CapturedCredentialStorage);
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
// AUTOGENERATED FILE: EDIT 'site_configs.yml' instead and run 'build_site_configs.rb'
|
||||
var SiteConfigs = { "hulu.com": { "clickOn": "input.inactive.dummy.user" }};
|
|
@ -0,0 +1,2 @@
|
|||
hulu.com:
|
||||
clickOn: "input.inactive.dummy.user"
|
|
@ -1,11 +0,0 @@
|
|||
var TldService = function() {
|
||||
|
||||
// TODO: flesh this out
|
||||
function tldForDomain(domain, callback) {
|
||||
callback(domain);
|
||||
}
|
||||
|
||||
return {
|
||||
tldForDomain: tldForDomain
|
||||
};
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/ruby
|
||||
|
||||
output = "// AUTOGENERATED FILE: edit 'site_configs.yml' instead and run 'build_site_configs.rb'\n"
|
||||
output += "var SiteConfigs = "+`js-yaml -j #{Dir.pwd+"/background/site_configs.yml"}`.gsub(/\n/,"")+";"
|
||||
File.open(Dir.pwd+"/background/site_configs.js", 'w') {|f| f.write(output) }
|
|
@ -3,8 +3,8 @@ var Gombot = {};
|
|||
Gombot.Messaging = ContentMessaging();
|
||||
Gombot.MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
|
||||
Gombot.DomMonitor = DomMonitor(jQuery, Gombot.MutationObserver);
|
||||
Gombot.PasswordForm = PasswordForm(jQuery, Gombot.DomMonitor);
|
||||
//Gombot.InputMonitor = InputMonitor(Gombot.MutationObserver); not used, replaced by DomMonitor
|
||||
Gombot.SiteConfig = {};
|
||||
Gombot.PasswordForm = PasswordForm(jQuery, Gombot.DomMonitor, Gombot.SiteConfig);
|
||||
Gombot.Linker = {};
|
||||
Gombot.PasswordFormInspector = PasswordFormInspector(jQuery, Gombot.PasswordForm, Gombot.DomMonitor);
|
||||
|
||||
|
@ -58,7 +58,8 @@ function formsFound(formInspector) {
|
|||
|
||||
var formInspectorObserver = {
|
||||
formsFound: formsFound,
|
||||
credentialsCaptured: credentialsCaptured
|
||||
credentialsCaptured: credentialsCaptured,
|
||||
link: maybePromptToSaveCapturedCredentials
|
||||
};
|
||||
|
||||
function start() {
|
||||
|
@ -68,4 +69,7 @@ function start() {
|
|||
Gombot.PasswordFormInspector.observe(formInspectorObserver);
|
||||
}
|
||||
|
||||
start();
|
||||
Gombot.Messaging.messageToChrome({type: "get_site_config"}, function(config) {
|
||||
Gombot.SiteConfig.config = config;
|
||||
start();
|
||||
});
|
|
@ -1,22 +1,33 @@
|
|||
var PasswordForm = function($, DomMonitor) {
|
||||
var PasswordForm = function($, DomMonitor, SiteConfig) {
|
||||
|
||||
function notifyObserver(fn) {
|
||||
var args;
|
||||
if (this.observer[fn]) {
|
||||
args = Array.prototype.slice.call(arguments,1);
|
||||
// Add self as first argument
|
||||
args.unshift(this);
|
||||
this.observer[fn].apply(this.observer, args);
|
||||
}
|
||||
}
|
||||
|
||||
function passwordFieldRemovedCallback(domMonitor) {
|
||||
//console.log("PasswordForm.passwordFieldRemovedCallback username=",this.getUsername(),"password=",this.getPassword());
|
||||
// Stop listening for the password field to be removed
|
||||
DomMonitor.off("isRemoved.pwdEl"+this.id);
|
||||
if (this.getPassword()) { // if we have a password in the form
|
||||
// Notify observer of credentials in the form
|
||||
notifyObserver.call(this, "credentialsCaptured");
|
||||
}
|
||||
// Notify observers they should link if they have captured creds
|
||||
// TODO: maybe should qualify this a bit, e.g., only notify if user
|
||||
// actually entered credentials into this form
|
||||
// Note: this should be called even if the password field is empty because
|
||||
// the page may have deleted the password field contents before removing it.
|
||||
notifyObserver.call(this, "link");
|
||||
}
|
||||
|
||||
function capturedCredentialsCallback(event) {
|
||||
notifyObserver.call(this, "credentialsCaptured");
|
||||
}
|
||||
|
||||
var PasswordForm = function(id, usernameField, passwordField, containingEl) {
|
||||
this.id = id;
|
||||
this.usernameField = usernameField;
|
||||
|
@ -38,11 +49,8 @@ var PasswordForm = function($, DomMonitor) {
|
|||
// becomes visible, invisible, or removed.
|
||||
PasswordForm.prototype.observe = function(observer) {
|
||||
this.observer = observer;
|
||||
var capturedCredentialsNotify = function(event) {
|
||||
notifyObserver.call(this, "credentialsCaptured");
|
||||
};
|
||||
this.$containingEl.on(this.inputEvents, "input", capturedCredentialsNotify.bind(this));
|
||||
this.$containingEl.on(this.submitEvents, capturedCredentialsNotify.bind(this));
|
||||
this.$containingEl.on(this.inputEvents, "input", capturedCredentialsCallback.bind(this));
|
||||
this.$containingEl.on(this.submitEvents, capturedCredentialsCallback.bind(this));
|
||||
return this;
|
||||
};
|
||||
|
||||
|
@ -54,6 +62,10 @@ var PasswordForm = function($, DomMonitor) {
|
|||
};
|
||||
|
||||
PasswordForm.prototype.fill = function(credentials) {
|
||||
var clickOn = SiteConfig.config.clickOn;
|
||||
if (clickOn) {
|
||||
$(clickOn).click();
|
||||
}
|
||||
this.usernameField.el.value = credentials.username;
|
||||
this.passwordField.el.value = credentials.password;
|
||||
return this;
|
||||
|
|
|
@ -71,9 +71,13 @@ var PasswordFormInspector = function($, PasswordForm, DomMonitor) {
|
|||
visitObservers("credentialsCaptured", creds);
|
||||
}
|
||||
|
||||
function link(passwordForm) {
|
||||
visitObservers("link");
|
||||
}
|
||||
|
||||
var passwordFormObserver = {
|
||||
credentialsCaptured: credentialsCaptured,
|
||||
link: function() { visitObservers("link"); }
|
||||
link: link
|
||||
};
|
||||
|
||||
// internal function to start observing the form collection
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Загрузка…
Ссылка в новой задаче