-
-
{{title | translate}}
+
+
{{notification.title | translate}}
-
{{text | translate}}
+
{{notification.text | translate}}
-
{{progressText | translate:"{ PROGRESS: progress, UNIT: progressUnit }"}}
+
{{notification.progress.text | translate:"{ PROGRESS: notification.progress.value, UNIT: notification.progress.unit}"}}
-
{{countdownText | translate:"{ REMAINING: timeRemaining }"}}
+
{{notification.countdown.text | translate:"{ REMAINING: timeRemaining}"}}
-
\ No newline at end of file
+
diff --git a/guacamole/src/main/webapp/app/notification/types/Notification.js b/guacamole/src/main/webapp/app/notification/types/Notification.js
new file mode 100644
index 000000000..dfb5ef9fa
--- /dev/null
+++ b/guacamole/src/main/webapp/app/notification/types/Notification.js
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2014 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * Provides the Notification class definition.
+ */
+angular.module('notification').factory('Notification', [function defineNotification() {
+
+ /**
+ * Creates a new Notification, initializing the properties of that
+ * Notification with the corresponding properties of the given template.
+ *
+ * @constructor
+ * @param {Notification|Object} [template={}]
+ * The object whose properties should be copied within the new
+ * Notification.
+ */
+ var Notification = function Notification(template) {
+
+ // Use empty object by default
+ template = template || {};
+
+ /**
+ * The CSS class to associate with the notification, if any.
+ *
+ * @type String
+ */
+ this.className = template.className;
+
+ /**
+ * The title of the notification.
+ *
+ * @type String
+ */
+ this.title = template.title;
+
+ /**
+ * The body text of the notification.
+ *
+ * @type String
+ */
+ this.text = template.text;
+
+ /**
+ * An array of all actions available to the user in response to this
+ * notification.
+ *
+ * @type NotificationAction[]
+ */
+ this.actions = template.actions || [];
+
+ /**
+ * The current progress state of the ongoing action associated with this
+ * notification.
+ *
+ * @type NotificationProgress
+ */
+ this.progress = template.progress;
+
+ /**
+ * The countdown and corresponding default action which applies to
+ * this notification, if any.
+ *
+ * @type NotificationCountdown
+ */
+ this.countdown = template.countdown;
+
+ };
+
+ return Notification;
+
+}]);
diff --git a/guacamole/src/main/webapp/app/notification/types/NotificationAction.js b/guacamole/src/main/webapp/app/notification/types/NotificationAction.js
new file mode 100644
index 000000000..d0e75cb6d
--- /dev/null
+++ b/guacamole/src/main/webapp/app/notification/types/NotificationAction.js
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * Provides the NotificationAction class definition.
+ */
+angular.module('notification').factory('NotificationAction', [function defineNotificationAction() {
+
+ /**
+ * Creates a new NotificationAction, which pairs an arbitrary callback with
+ * an action name. The name of this action will ultimately be presented to
+ * the user when the user is prompted to choose among available actions.
+ *
+ * @constructor
+ * @param {String} name The name of this action.
+ *
+ * @param {Function} callback
+ * The callback to call when the user elects to perform this action.
+ */
+ var NotificationAction = function NotificationAction(name, callback) {
+
+ /**
+ * Reference to this NotificationAction.
+ *
+ * @type NotificationAction
+ */
+ var action = this;
+
+ /**
+ * The name of this action.
+ *
+ * @type String
+ */
+ this.name = name;
+
+ /**
+ * The callback to call when this action is performed.
+ *
+ * @type Function
+ */
+ this.callback = callback;
+
+ /**
+ * Calls the callback associated with this NotificationAction, if any.
+ * If no callback is associated with this NotificationAction, this
+ * function has no effect.
+ */
+ this.performAction = function performAction() {
+ if (action.callback)
+ action.callback();
+ };
+
+ };
+
+ return NotificationAction;
+
+}]);
diff --git a/guacamole/src/main/webapp/app/notification/types/NotificationCountdown.js b/guacamole/src/main/webapp/app/notification/types/NotificationCountdown.js
new file mode 100644
index 000000000..1f834508e
--- /dev/null
+++ b/guacamole/src/main/webapp/app/notification/types/NotificationCountdown.js
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * Provides the NotificationCountdown class definition.
+ */
+angular.module('notification').factory('NotificationCountdown', [function defineNotificationCountdown() {
+
+ /**
+ * Creates a new NotificationCountdown which describes an action that
+ * should be performed after a specific number of seconds has elapsed.
+ *
+ * @constructor
+ * @param {String} text The body text of the notification countdown.
+ *
+ * @param {Number} remaining
+ * The number of seconds remaining in the countdown.
+ *
+ * @param {Function} [callback]
+ * The callback to call when the countdown elapses.
+ */
+ var NotificationCountdown = function NotificationCountdown(text, remaining, callback) {
+
+ /**
+ * Reference to this NotificationCountdown.
+ *
+ * @type NotificationCountdown
+ */
+ var countdown = this;
+
+ /**
+ * The body text of the notification countdown. For the sake of i18n,
+ * the variable REMAINING should be applied within the translation
+ * string for formatting plurals, etc.
+ *
+ * @type String
+ */
+ this.text = text;
+
+ /**
+ * The number of seconds remaining in the countdown. After this number
+ * of seconds elapses, the callback associated with this
+ * NotificationCountdown will be called.
+ *
+ * @type Number
+ */
+ this.remaining = remaining;
+
+ /**
+ * The callback to call when this countdown expires.
+ *
+ * @type Function
+ */
+ this.callback = callback;
+
+ /**
+ * Calls the callback associated with this NotificationCountdown, if any.
+ * If no callback is associated with this NotificationCountdown, this
+ * function has no effect.
+ */
+ this.performAction = function performAction() {
+ if (countdown.callback)
+ countdown.callback();
+ };
+
+ };
+
+ return NotificationCountdown;
+
+}]);
diff --git a/guacamole/src/main/webapp/app/notification/types/NotificationProgress.js b/guacamole/src/main/webapp/app/notification/types/NotificationProgress.js
new file mode 100644
index 000000000..5c3a45c0c
--- /dev/null
+++ b/guacamole/src/main/webapp/app/notification/types/NotificationProgress.js
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Glyptodon LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * Provides the NotificationProgress class definition.
+ */
+angular.module('notification').factory('NotificationProgress', [function defineNotificationProgress() {
+
+ /**
+ * Creates a new NotificationProgress which describes the current status
+ * of an operation, and how much of that operation remains to be performed.
+ *
+ * @constructor
+ * @param {String} text The text describing the operation progress.
+ *
+ * @param {Number} value
+ * The current state of operation progress, as an arbitrary number
+ * which increases as the operation continues.
+ *
+ * @param {String} [unit]
+ * The unit of the arbitrary value, if that value has an associated
+ * unit.
+ *
+ * @param {Number} [ratio]
+ * If known, the current status of the operation as a value between 0
+ * and 1 inclusive, where 0 is not yet started, and 1 is complete.
+ */
+ var NotificationProgress = function NotificationProgress(text, value, unit, ratio) {
+
+ /**
+ * The text describing the operation progress. For the sake of i18n,
+ * the variable PROGRESS should be applied within the translation
+ * string for formatting plurals, etc., while UNIT should be used
+ * for the progress unit, if any.
+ *
+ * @type String
+ */
+ this.text = text;
+
+ /**
+ * The current state of operation progress, as an arbitrary number which
+ * increases as the operation continues.
+ *
+ * @type Number
+ */
+ this.value = value;
+
+ /**
+ * The unit of the arbitrary value, if that value has an associated
+ * unit.
+ *
+ * @type String
+ */
+ this.unit = unit;
+
+ /**
+ * If known, the current status of the operation as a value between 0
+ * and 1 inclusive, where 0 is not yet started, and 1 is complete.
+ *
+ * @type String
+ */
+ this.ratio = ratio;
+
+ };
+
+ return NotificationProgress;
+
+}]);
diff --git a/guacamole/src/main/webapp/app/permission/permissionModule.js b/guacamole/src/main/webapp/app/permission/permissionModule.js
index e6afa2826..524f058f5 100644
--- a/guacamole/src/main/webapp/app/permission/permissionModule.js
+++ b/guacamole/src/main/webapp/app/permission/permissionModule.js
@@ -23,4 +23,4 @@
/**
* A module for code relating to permissions.
*/
-angular.module('permission', []);
+angular.module('permission', ['auth']);
diff --git a/guacamole/src/main/webapp/app/permission/services/permissionDAO.js b/guacamole/src/main/webapp/app/permission/services/permissionDAO.js
index 5a51c61bf..b26e66683 100644
--- a/guacamole/src/main/webapp/app/permission/services/permissionDAO.js
+++ b/guacamole/src/main/webapp/app/permission/services/permissionDAO.js
@@ -23,8 +23,8 @@
/**
* The DAO for permission operations agains the REST API.
*/
-angular.module('permission').factory('permissionDAO', ['$http', 'localStorageUtility',
- function permissionDAO($http, localStorageUtility) {
+angular.module('permission').factory('permissionDAO', ['$http', 'authenticationService',
+ function permissionDAO($http, authenticationService) {
var service = {};
@@ -37,7 +37,7 @@ angular.module('permission').factory('permissionDAO', ['$http', 'localStorageUti
* @returns {promise} A promise for the HTTP call.
*/
service.getPermissions = function getPermissions(userID) {
- return $http.get("api/permission/" + userID + "/?token=" + localStorageUtility.get('authToken'));
+ return $http.get("api/permission/" + userID + "/?token=" + authenticationService.getCurrentToken());
};
/**
@@ -50,7 +50,7 @@ angular.module('permission').factory('permissionDAO', ['$http', 'localStorageUti
* @returns {promise} A promise for the HTTP call.
*/
service.addPermission = function addPermission(userID, permission) {
- return $http.post("api/permission/" + userID + "/?token=" + localStorageUtility.get('authToken'), permission);
+ return $http.post("api/permission/" + userID + "/?token=" + authenticationService.getCurrentToken(), permission);
};
@@ -65,7 +65,7 @@ angular.module('permission').factory('permissionDAO', ['$http', 'localStorageUti
* @returns {promise} A promise for the HTTP call.
*/
service.removePermission = function removePermission(userID, permission) {
- return $http.post("api/permission/remove/" + userID + "/?token=" + localStorageUtility.get('authToken'), permission);
+ return $http.post("api/permission/remove/" + userID + "/?token=" + authenticationService.getCurrentToken(), permission);
};
@@ -103,7 +103,7 @@ angular.module('permission').factory('permissionDAO', ['$http', 'localStorageUti
// Make the HTTP call
return $http({
method : 'PATCH',
- url : "api/permission/?token=" + localStorageUtility.get('authToken'),
+ url : "api/permission/?token=" + authenticationService.getCurrentToken(),
data : permissionPatch
});
}
diff --git a/guacamole/src/main/webapp/app/user/services/userDAO.js b/guacamole/src/main/webapp/app/user/services/userDAO.js
index 99ffd12b8..c8ba6f376 100644
--- a/guacamole/src/main/webapp/app/user/services/userDAO.js
+++ b/guacamole/src/main/webapp/app/user/services/userDAO.js
@@ -23,8 +23,8 @@
/**
* The DAO for connection operations agains the REST API.
*/
-angular.module('user').factory('userDAO', ['$http', 'localStorageUtility',
- function userDAO($http, localStorageUtility) {
+angular.module('user').factory('userDAO', ['$http', 'authenticationService',
+ function userDAO($http, authenticationService) {
var service = {};
@@ -35,7 +35,7 @@ angular.module('user').factory('userDAO', ['$http', 'localStorageUtility',
* @returns {promise} A promise for the HTTP call.
*/
service.getUsers = function getUsers() {
- return $http.get("api/user?token=" + localStorageUtility.get('authToken'));
+ return $http.get("api/user?token=" + authenticationService.getCurrentToken());
};
/**
@@ -47,7 +47,7 @@ angular.module('user').factory('userDAO', ['$http', 'localStorageUtility',
* @returns {promise} A promise for the HTTP call.
*/
service.getUser = function getUser(userID) {
- return $http.get("api/user/" + userID + "/?token=" + localStorageUtility.get('authToken'));
+ return $http.get("api/user/" + userID + "/?token=" + authenticationService.getCurrentToken());
};
/**
@@ -61,7 +61,7 @@ angular.module('user').factory('userDAO', ['$http', 'localStorageUtility',
service.deleteUser = function deleteUser(user) {
return $http['delete'](
"api/user/" + user.username +
- "?token=" + localStorageUtility.get('authToken'));
+ "?token=" + authenticationService.getCurrentToken());
};
@@ -76,7 +76,7 @@ angular.module('user').factory('userDAO', ['$http', 'localStorageUtility',
service.createUser = function createUser(user) {
return $http.post(
"api/user/"
- + "?token=" + localStorageUtility.get('authToken'),
+ + "?token=" + authenticationService.getCurrentToken(),
user
);
}
@@ -92,7 +92,7 @@ angular.module('user').factory('userDAO', ['$http', 'localStorageUtility',
service.saveUser = function saveUser(user) {
return $http.post(
"api/user/" + user.username +
- "?token=" + localStorageUtility.get('authToken'),
+ "?token=" + authenticationService.getCurrentToken(),
user);
};
diff --git a/guacamole/src/main/webapp/app/user/userModule.js b/guacamole/src/main/webapp/app/user/userModule.js
index 4e3a5f602..abfef1c13 100644
--- a/guacamole/src/main/webapp/app/user/userModule.js
+++ b/guacamole/src/main/webapp/app/user/userModule.js
@@ -23,4 +23,4 @@
/**
* A module for code relating to users.
*/
-angular.module('user', []);
+angular.module('user', ['auth']);
diff --git a/guacamole/src/main/webapp/app/util/services/localStorageUtility.js b/guacamole/src/main/webapp/app/util/services/localStorageUtility.js
deleted file mode 100644
index 5841d14fc..000000000
--- a/guacamole/src/main/webapp/app/util/services/localStorageUtility.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2014 Glyptodon LLC
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/**
- * A service for handling storage and retrieval of values on localStorage.
- * If local storage is not available, cookies will be used as a fallback.
- */
-angular.module('util').factory('localStorageUtility', ['$cookieStore',
- function localStorageUtility($cookieStore) {
-
- var service = {};
-
- // The prefix to use when storing cookies
- var COOKIE_PREFIX = "guacamole.ui.localstorage.";
-
- // Check if we can actually use localStorage
- var localStorageEnabled;
- try {
- window.localStorage.setItem("test", "test");
- window.localStorage.removeItem("test");
- localStorageEnabled = true;
- } catch(e) {
- localStorageEnabled = false;
- }
-
- var getFunc, setFunc;
-
- if(localStorageEnabled) {
-
- // Just a passthrough to localStorage
- getFunc = function getFromLocalStorage(key) {
- return window.localStorage.getItem(key);
- };
-
- setFunc = function setOnLocalStorage(key, value) {
- return window.localStorage.setItem(key, value);
- };
- }
- else {
-
- // Store the values as cookies
- getFunc = function getValueFromCookie(key) {
- return $cookieStore.get(COOKIE_PREFIX + key);
- };
-
- setFunc = function setValueOnCookie(key, value) {
- return $cookieStore.put(COOKIE_PREFIX + key, value);
- }
- }
-
- /**
- * Gets a value from the persistent local store.
- *
- * @param {string} key The key to use as an index into the map.
- *
- * @returns {string} The value, if found.
- */
- service.get = getFunc;
-
- /**
- * Sets a value on the persistent local store.
- *
- * @param {string} key The key to use as an index into the map.
- * @param {string} value The value to store in the map.
- */
- service.set = setFunc;
-
- /**
- * Clear a value from the persistent local store.
- *
- * @param {string} key The key to clear from the map.
- */
- service.clear = function clear(key) {
- return service.set(key, undefined);
- };
-
- return service;
-}]);
diff --git a/guacamole/src/main/webapp/app/util/utilModule.js b/guacamole/src/main/webapp/app/util/utilModule.js
index b86ffb432..89429303c 100644
--- a/guacamole/src/main/webapp/app/util/utilModule.js
+++ b/guacamole/src/main/webapp/app/util/utilModule.js
@@ -23,4 +23,4 @@
/**
* A module for miscellaneous services and utilities that don't belong elsewhere.
*/
-angular.module('util', ['ngCookies']);
+angular.module('util', []);
diff --git a/guacamole/src/main/webapp/index.html b/guacamole/src/main/webapp/index.html
index 8206371ad..472e18ca6 100644
--- a/guacamole/src/main/webapp/index.html
+++ b/guacamole/src/main/webapp/index.html
@@ -37,20 +37,7 @@ THE SOFTWARE.
@@ -60,20 +47,7 @@ THE SOFTWARE.
-
-
-
+
diff --git a/guacamole/src/main/webapp/scripts/history.js b/guacamole/src/main/webapp/scripts/history.js
deleted file mode 100644
index 5165e8df0..000000000
--- a/guacamole/src/main/webapp/scripts/history.js
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2013 Glyptodon LLC
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/**
- * Set of thumbnails for each connection, indexed by ID.
- */
-GuacamoleHistory = new (function() {
-
- /**
- * Reference to this GuacamoleHistory.
- */
- var guac_history = this;
-
- /**
- * The number of entries to allow before removing old entries based on the
- * cutoff.
- */
- var IDEAL_LENGTH = 6;
-
- /**
- * The maximum age of a history entry before it is removed, in
- * milliseconds.
- */
- var CUTOFF_AGE = 900000;
-
- var history = {};
-
- function truncate() {
-
- // Build list of entries
- var entries = [];
- for (var old_id in history)
- entries.push(history[old_id]);
-
- // Avoid history growth beyond defined number of entries
- if (entries.length > IDEAL_LENGTH) {
-
- // Sort list
- entries.sort(GuacamoleHistory.Entry.compare);
-
- // Remove entries until length is ideal or all are recent
- var now = new Date().getTime();
- while (entries.length > IDEAL_LENGTH
- && now - entries[0].accessed > CUTOFF_AGE) {
-
- // Remove entry
- var removed = entries.shift();
- delete history[removed.id];
-
- }
-
- }
-
- }
-
- /**
- * Returns the URL for the thumbnail of the connection with the given ID,
- * or undefined if no thumbnail is associated with that connection.
- */
- this.get = function(id) {
- return history[id] || new GuacamoleHistory.Entry();
- };
-
- /**
- * Updates the thumbnail and access time of the history entry for the
- * connection with the given ID.
- */
- this.update = function(id, thumbnail) {
-
- /* Do nothing if localStorage not present */
- if (!localStorage)
- return;
-
- // Create updated entry
- var entry = new GuacamoleHistory.Entry(
- id,
- thumbnail,
- new Date().getTime()
- );
-
- // Store entry in history
- history[id] = entry;
- truncate();
-
- // Save updated history, ignore inability to use localStorage
- try {
- localStorage.setItem("GUAC_HISTORY", JSON.stringify(history));
- }
- catch (ignore) {}
-
- };
-
- /**
- * Reloads all history data.
- */
- this.reload = function() {
-
- /* Do nothing if localStorage not present */
- if (!localStorage)
- return;
-
- // Get old and new for comparison, ignore inability to use localStorage
- var old_history = history;
- try {
- var new_history = JSON.parse(localStorage.getItem("GUAC_HISTORY") || "{}");
- }
- catch (ignore) {
- return;
- }
-
- // Update history
- history = new_history;
-
- // Call onchange handler as necessary
- if (guac_history.onchange) {
-
- // Produce union of all known IDs
- var known_ids = {};
- for (var new_id in new_history) known_ids[new_id] = true;
- for (var old_id in old_history) known_ids[old_id] = true;
-
- // For each known ID
- for (var id in known_ids) {
-
- // Get entries
- var old_entry = old_history[id];
- var new_entry = new_history[id];
-
- // Call handler for all changed
- if (!old_entry || !new_entry
- || old_entry.accessed != new_entry.accessed)
- guac_history.onchange(id, old_entry, new_entry);
-
- }
-
- } // end onchange
-
- };
-
- /**
- * Event handler called whenever a history entry is changed.
- *
- * @event
- * @param {String} id The ID of the connection whose history entry is
- * changing.
- * @param {GuacamoleHistory.Entry} old_entry The old value of the entry, if
- * any.
- * @param {GuacamoleHistory.Entry} new_entry The new value of the entry, if
- * any.
- */
- this.onchange = null;
-
- // Reload when modified
- window.addEventListener("storage", guac_history.reload, false);
-
- // Initial load
- guac_history.reload();
-
-})();
-
-/**
- * A single entry in the indexed connection usage history.
- *
- * @constructor
- * @param {String} id The ID of this connection.
- * @param {String} thumbnail The URL of the thumbnail to use to represent this
- * connection.
- * @param {Number} last_access The time this connection was last accessed, in
- * seconds.
- */
-GuacamoleHistory.Entry = function(id, thumbnail, last_access) {
-
- /**
- * The ID of the connection associated with this history entry.
- */
- this.id = id;
-
- /**
- * The thumbnail associated with the connection associated with this history
- * entry.
- */
- this.thumbnail = thumbnail;
-
- /**
- * The time the connection associated with this entry was last accessed.
- */
- this.accessed = last_access;
-
-};
-
-GuacamoleHistory.Entry.compare = function(a, b) {
- return a.accessed - b.accessed;
-};
diff --git a/guacamole/src/main/webapp/scripts/session.js b/guacamole/src/main/webapp/scripts/session.js
deleted file mode 100644
index 7afc9b6b2..000000000
--- a/guacamole/src/main/webapp/scripts/session.js
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2013 Glyptodon LLC
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/**
- * Global storage for Guacamole pages.
- */
-GuacamoleSessionStorage = (function() {
-
- // Retrieve storage from owner of window, if possible
- var opener_storage = null;
- try {
- opener_storage = opener && opener.GuacamoleSessionStorage;
- }
- catch (e) {}
-
- return opener_storage;
-
-})() || new (function() {
-
- /**
- * The contents of storage, as a JSON string containing name/value pairs as
- * properties.
- *
- * @private
- * @type String
- */
- var stored_json = "{}";
-
- /**
- * Called whenever an item value changes.
- *
- * @callback onchange
- * @param {String} name The name of the item changed.
- * @param value The new item value.
- */
-
- /**
- * All attached listeners.
- *
- * @type onchange[]
- */
- var listeners = [];
-
- /**
- * Notifies all listeners that an item has changed.
- *
- * @param {String} name The name of the item that changed.
- * @param value The new item value.
- */
- function __notify_changed(name, value) {
- for (var i=0; i