blob: a60099b95af94dc986bd2389390e2246210c4c14 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview
* Class for detecting when the application is idle. Note that chrome.idle is
* not suitable for this purpose because it detects when the computer is idle,
* and we'd like to close the application and free up VM resources even if the
* user has been using another application for a long time.
*
* There are two idle timeouts. The first controls the visibility of the idle
* timeout warning dialog and is reset on mouse input; when it expires, the
* idle warning dialog is displayed. The second controls the length of time
* for which the idle warning dialog is displayed; when it expires, the ctor
* callback is invoked, which it is assumed will exit the application--no
* further idle detection is done.
*/
'use strict';
/** @suppress {duplicate} */
var remoting = remoting || {};
/**
* @param {HTMLElement} rootElement The idle warning dialog.
* @param {remoting.WindowShape} windowShape
* @param {string} applicationName
* @param {function():void} callback Called when the idle warning dialog has
* timed out or the user has explicitly indicated that they are no longer
* using the session.
* @constructor
* @implements {base.Disposable}
*/
remoting.IdleDetector = function(rootElement, windowShape, applicationName,
callback) {
/** @private */
this.callback_ = callback;
/**
* @private {base.OneShotTimer}
*/
this.timer_ = null;
/** @private {?function():void} */
this.resetTimeoutRef_ = null;
var message = rootElement.querySelector('.idle-warning-message');
l10n.localizeElement(message, applicationName);
/** @private */
this.dialog_ = new remoting.Html5ModalDialog({
dialog: /** @type {HTMLDialogElement} */ (rootElement),
primaryButton: rootElement.querySelector('.idle-dialog-continue'),
secondaryButton: rootElement.querySelector('.idle-dialog-disconnect'),
closeOnEscape: false,
windowShape: windowShape
});
this.resetTimeout_();
};
remoting.IdleDetector.prototype.dispose = function() {
base.dispose(this.timer_);
this.timer_ = null;
if (this.resetTimeoutRef_) {
this.registerInputDetectionCallbacks_(false);
}
base.dispose(this.dialog_);
this.dialog_ = null;
};
/**
* @param {boolean} register True to register the callbacks; false to remove
* them.
* @private
*/
remoting.IdleDetector.prototype.registerInputDetectionCallbacks_ =
function(register) {
var events = [ 'mousemove', 'mousedown', 'mouseup', 'click',
'keyup', 'keydown', 'keypress' ];
if (register) {
console.assert(this.resetTimeoutRef_ == null,
'|resetTimeoutRef_| already exists.');
this.resetTimeoutRef_ = this.resetTimeout_.bind(this);
for (var i = 0; i < events.length; ++i) {
document.body.addEventListener(events[i], this.resetTimeoutRef_, true);
}
} else {
console.assert(this.resetTimeoutRef_ != null,
'|resetTimeoutRef_| does not exist.');
for (var i = 0; i < events.length; ++i) {
document.body.removeEventListener(events[i], this.resetTimeoutRef_, true);
}
this.resetTimeoutRef_ = null;
}
};
/**
* @private
*/
remoting.IdleDetector.prototype.resetTimeout_ = function() {
if (this.resetTimeoutRef_ == null) {
this.registerInputDetectionCallbacks_(true);
}
base.dispose(this.timer_);
this.timer_ = new base.OneShotTimer(this.onIdleTimeout_.bind(this),
remoting.IdleDetector.kIdleTimeoutMs);
};
/**
* @private
*/
remoting.IdleDetector.prototype.onIdleTimeout_ = function() {
this.registerInputDetectionCallbacks_(false);
this.timer_ = new base.OneShotTimer(this.onDialogTimeout_.bind(this),
remoting.IdleDetector.kDialogTimeoutMs);
this.showIdleWarning_();
};
/**
* @private
*/
remoting.IdleDetector.prototype.onDialogTimeout_ = function() {
base.dispose(this.timer_);
this.timer_ = null;
this.dialog_.close(remoting.MessageDialog.Result.SECONDARY);
};
/**
* @private
*/
remoting.IdleDetector.prototype.showIdleWarning_ = function() {
var that = this;
this.dialog_.show().then(function(
/** remoting.MessageDialog.Result */ result) {
if (result === remoting.MessageDialog.Result.PRIMARY) {
// Continue.
that.resetTimeout_();
} else if (result === remoting.MessageDialog.Result.SECONDARY) {
// Disconnect.
base.dispose(that.timer_);
that.timer_ = null;
that.callback_();
}
});
};
// Time-out after 1hr of no activity.
remoting.IdleDetector.kIdleTimeoutMs = 60 * 60 * 1000;
// Show the idle warning dialog for 2 minutes.
remoting.IdleDetector.kDialogTimeoutMs = 2 * 60 * 1000;