blob: 53bcc950226a192f4a3e296e84ca65c37cd87046 [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
lib.rtdep('lib.Event');
/**
* The singleton app instance for the nassh packaged app, created by the
* background page.
*/
nassh.App = function(manifest) {
this.updateAvailable = false;
this.onInit = new lib.Event();
this.onUpdateAvailable = new lib.Event(this.onUpdateAvailable_.bind(this));
chrome.runtime.onUpdateAvailable.addListener(this.onUpdateAvailable);
this.prefs_ = new nassh.PreferenceManager();
this.omniMatches_ = [];
this.omniDefault_ = null;
};
/**
* Set the default help text in the omnibox when completing an ssh connection.
*/
nassh.App.prototype.setDefaultOmnibox_ = function() {
this.omnibox_.setDefaultSuggestion({
description: nassh.msg('OMNIBOX_DEFAULT'),
});
};
/**
* Callback when user first interacts with the ssh shortcut.
*/
nassh.App.prototype.omniboxOnInputStarted_ = function() {
this.omniMatches_.length = 0;
this.omniDefault_ = null;
// Convert a nassh profile into an object we can easily match later on.
var profileIdToOmni = function(id) {
var profile = this.prefs_.getProfile(id);
var port = profile.get('port');
if (port)
port = ':' + port;
return {
uhp: profile.get('username') + '@' + profile.get('hostname') + port,
desc: profile.get('description'),
id: id,
};
};
// Read our saved settings and construct the partial matches from all of
// our active profiles.
this.prefs_.readStorage(() => {
var ids = this.prefs_.get('profile-ids');
for (var i = 0; i < ids.length; ++i)
this.omniMatches_.push(profileIdToOmni.call(this, ids[i]));
chrome.storage.local.get('/nassh/connectDialog/lastProfileId',
(items) => {
var lastProfileId = items['/nassh/connectDialog/lastProfileId'];
if (lastProfileId)
this.omniDefault_ = profileIdToOmni.call(this, lastProfileId);
});
});
};
/**
* Callback when the user changes the input at all.
*
* @param {string} text Current input in the omnibox.
* @param {function} suggest Function for us to call to notify of our
* matches against the text.
*/
nassh.App.prototype.omniboxOnInputChanged_ = function(text, suggest) {
var resultsUhp = [];
var resultsDescLeading = [];
var resultsDescSubstr = [];
this.omniMatches_.forEach((match) => {
if (match.uhp.startsWith(text))
resultsUhp.push({
content: 'profile-id:' + match.id,
description: lib.f.replaceVars(
'<match>%escapeHTML(uhp)</match>: %escapeHTML(desc)', match),
});
if (match.desc.startsWith(text))
resultsDescLeading.push({
content: 'profile-id:' + match.id,
description: lib.f.replaceVars(
'%escapeHTML(uhp): <match>%escapeHTML(desc)</match>', match),
});
if (match.desc.includes(text))
resultsDescSubstr.push({
content: 'profile-id:' + match.id,
description: lib.f.replaceVars(
'%escapeHTML(uhp): <match>%escapeHTML(desc)</match>', match),
});
});
// Now merge the suggestions together in order.
var results = resultsUhp.concat(resultsDescLeading, resultsDescSubstr);
if (results.length == 0 || text.trim().length == 0) {
// If they're just starting input, or if we have no matches, then show the
// last connection used first.
if (this.omniDefault_)
results.unshift({
content: 'profile-id:' + this.omniDefault_.id,
description: lib.f.replaceVars('%escapeHTML(uhp): %escapeHTML(desc)',
this.omniDefault_),
});
}
if (results.length)
suggest(results);
};
/**
* Callback when the user has finish entering text.
*
* @param {string} text The text to operate on.
* @param {string} disposition Mode the user wants us to open as.
*/
nassh.App.prototype.omniboxOnInputEntered_ = function(text, disposition) {
var url = chrome.runtime.getURL('html/nassh.html#' + text);
switch (disposition) {
default:
console.warn('unknown disposition: ' + disposition);
case 'currentTab':
// Ideally we'd just call chrome.tabs.update, but that won't focus the
// new ssh session. We close the current tab and then open a new one
// right away -- Chrome will focus the content for us.
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.remove(tabs[0].id);
});
chrome.tabs.create({url: url, active: true});
break;
case 'newBackgroundTab':
chrome.tabs.create({url: url, active: false});
break;
case 'newForegroundTab':
// We'll abuse this to open a window instead of a tab.
window.open(url, '',
'chrome=no,close=yes,resize=yes,minimizable=yes,' +
'scrollbars=yes,width=900,height=600,noopener');
// Close the active tab.
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.remove(tabs[0].id);
});
break;
}
};
/**
* Callback when the user has aborted input.
*/
nassh.App.prototype.omniboxOnInputCancelled_ = function() {
// this.setDefaultOmnibox_(); needed?
this.omniMatches_.length = 0;
this.omniDefault_ = null;
};
/**
* Bind our callbacks to the omnibox.
*
* @param {object} omnibox The omnibox instance to bind to.
*/
nassh.App.prototype.installOmnibox = function(omnibox) {
this.omnibox_ = omnibox;
this.setDefaultOmnibox_();
omnibox.onInputStarted.addListener(this.omniboxOnInputStarted_.bind(this));
omnibox.onInputChanged.addListener(this.omniboxOnInputChanged_.bind(this));
omnibox.onInputEntered.addListener(this.omniboxOnInputEntered_.bind(this));
omnibox.onInputCancelled.addListener(
this.omniboxOnInputCancelled_.bind(this));
};
/**
* Bind our callbacks to the runtime.
*
* @param {object} runtime The runtime instance to bind to.
*/
nassh.App.prototype.installHandlers = function(runtime) {
runtime.onLaunched.addListener(this.onLaunched.bind(this));
runtime.onRestarted.addListener(this.onLaunched.bind(this));
};
nassh.App.prototype.onLaunched = function(e) {
chrome.app.window.create('/html/nassh.html', {
'bounds': {
'width': 900,
'height': 600
},
'id': 'mainWindow'
});
};
nassh.App.prototype.onUpdateAvailable_ = function(e) {
this.updateAvailable = true;
var onQuery = function(rv) {
if (!rv.length) {
console.log('Reloading for update.');
chrome.runtime.reload();
} else {
console.log('Not reloading for update, ' + rv.length +
' windows still open.');
}
};
var checkTabs = function() {
chrome.tabs.query({url: chrome.runtime.getURL('html/nassh.html')},
onQuery);
};
chrome.tabs.onRemoved.addListener(checkTabs);
checkTabs();
};
/**
* The firstCallback of the onInit event.
*/
nassh.App.prototype.onInit_ = function() {
console.log('nassh: Application initialized: ' + chrome.runtime.getURL(''));
};