| Index: remoting/webapp/base/js/application.js
|
| diff --git a/remoting/webapp/base/js/application.js b/remoting/webapp/base/js/application.js
|
| index bcd6cf122f2d5a5471fd16926e2e740863c23869..1171ae90180b9a60f69a07dd06b539d666ed8156 100644
|
| --- a/remoting/webapp/base/js/application.js
|
| +++ b/remoting/webapp/base/js/application.js
|
| @@ -15,10 +15,13 @@ var remoting = remoting || {};
|
| /**
|
| * @param {Array<string>} appCapabilities Array of application capabilities.
|
| * @constructor
|
| + * @implements {remoting.ApplicationInterface}
|
| */
|
| remoting.Application = function(appCapabilities) {
|
| - /** @private {remoting.Application.Delegate} */
|
| - this.delegate_ = null;
|
| + // Create global factories.
|
| + remoting.ClientPlugin.factory = new remoting.DefaultClientPluginFactory();
|
| + remoting.SessionConnector.factory =
|
| + new remoting.DefaultSessionConnectorFactory();
|
|
|
| /** @private {Array<string>} */
|
| this.appCapabilities_ = [
|
| @@ -29,26 +32,23 @@ remoting.Application = function(appCapabilities) {
|
| // Append the app-specific capabilities.
|
| this.appCapabilities_.push.apply(this.appCapabilities_, appCapabilities);
|
|
|
| - /** @private {remoting.SessionConnector} */
|
| - this.sessionConnector_ = null;
|
| + /** @protected {remoting.SessionConnector} */
|
| + this.sessionConnector_ = remoting.SessionConnector.factory.createConnector(
|
| + document.getElementById('client-container'),
|
| + this.onConnected_.bind(this),
|
| + this.onError_.bind(this),
|
| + this.onConnectionFailed_.bind(this),
|
| + this.appCapabilities_);
|
|
|
| /** @private {base.Disposable} */
|
| this.sessionConnectedHooks_ = null;
|
| };
|
|
|
| /**
|
| - * @param {remoting.Application.Delegate} appDelegate The delegate that
|
| - * contains the app-specific functionality.
|
| + * @return {remoting.SessionConnector} The session connector.
|
| */
|
| -remoting.Application.prototype.setDelegate = function(appDelegate) {
|
| - this.delegate_ = appDelegate;
|
| -};
|
| -
|
| -/**
|
| - * @return {string} Application product name to be used in UI.
|
| - */
|
| -remoting.Application.prototype.getApplicationName = function() {
|
| - return this.delegate_.getApplicationName();
|
| +remoting.Application.prototype.getSessionConnector = function() {
|
| + return this.sessionConnector_;
|
| };
|
|
|
| /**
|
| @@ -60,18 +60,33 @@ remoting.Application.prototype.hasCapability = function(capability) {
|
| return capabilities.indexOf(capability) != -1;
|
| };
|
|
|
| +/* Disconnect the remoting client. */
|
| +remoting.Application.prototype.disconnect = function() {
|
| + if (remoting.clientSession) {
|
| + remoting.clientSession.disconnect(remoting.Error.none());
|
| + console.log('Disconnected.');
|
| + }
|
| +};
|
| +
|
| +/* Public method to exit the application. */
|
| +remoting.Application.prototype.quit = function() {
|
| + this.exitApplication_();
|
| +};
|
| +
|
| +/**
|
| + * Close the main window when quitting the application. This should be called
|
| + * by exitApplication() in the subclass.
|
| + * @protected
|
| + */
|
| +remoting.Application.prototype.closeMainWindow_ = function() {
|
| + chrome.app.window.current().close();
|
| +};
|
| +
|
| /**
|
| * Initialize the application and register all event handlers. After this
|
| * is called, the app is running and waiting for user events.
|
| - *
|
| - * @return {void} Nothing.
|
| */
|
| remoting.Application.prototype.start = function() {
|
| - // Create global objects.
|
| - remoting.ClientPlugin.factory = new remoting.DefaultClientPluginFactory();
|
| - remoting.SessionConnector.factory =
|
| - new remoting.DefaultSessionConnectorFactory();
|
| -
|
| // TODO(garykac): This should be owned properly rather than living in the
|
| // global 'remoting' namespace.
|
| remoting.settings = new remoting.Settings();
|
| @@ -79,17 +94,17 @@ remoting.Application.prototype.start = function() {
|
| remoting.initGlobalObjects();
|
| remoting.initIdentity();
|
|
|
| - this.delegate_.init();
|
| + this.initApplication_();
|
|
|
| var that = this;
|
| - remoting.identity.getToken().then(
|
| - this.delegate_.start.bind(this.delegate_, this.getSessionConnector())
|
| - ).catch(remoting.Error.handler(
|
| + remoting.identity.getToken().
|
| + then(this.startApplication_.bind(this)).
|
| + catch(remoting.Error.handler(
|
| function(/** !remoting.Error */ error) {
|
| if (error.hasTag(remoting.Error.Tag.CANCELLED)) {
|
| - that.exit();
|
| + that.exitApplication_();
|
| } else {
|
| - that.delegate_.signInFailed(error);
|
| + that.signInFailed_(error);
|
| }
|
| }
|
| )
|
| @@ -97,82 +112,19 @@ remoting.Application.prototype.start = function() {
|
| };
|
|
|
| /**
|
| - * Quit the application.
|
| - */
|
| -remoting.Application.prototype.exit = function() {
|
| - this.delegate_.handleExit();
|
| - chrome.app.window.current().close();
|
| -};
|
| -
|
| -/** Disconnect the remoting client. */
|
| -remoting.Application.prototype.disconnect = function() {
|
| - if (remoting.clientSession) {
|
| - remoting.clientSession.disconnect(remoting.Error.none());
|
| - console.log('Disconnected.');
|
| - }
|
| -};
|
| -
|
| -/**
|
| * Called when a new session has been connected.
|
| *
|
| * @param {remoting.ConnectionInfo} connectionInfo
|
| * @return {void} Nothing.
|
| + * @protected
|
| */
|
| -remoting.Application.prototype.onConnected = function(connectionInfo) {
|
| +remoting.Application.prototype.initSession_ = function(connectionInfo) {
|
| this.sessionConnectedHooks_ = new base.Disposables(
|
| new base.EventHook(connectionInfo.session(), 'stateChanged',
|
| this.onSessionFinished_.bind(this)),
|
| new base.RepeatingTimer(this.updateStatistics_.bind(this), 1000)
|
| );
|
| remoting.clipboard.startSession();
|
| -
|
| - this.delegate_.handleConnected(connectionInfo);
|
| -};
|
| -
|
| -/**
|
| - * Called when the current session has been disconnected.
|
| - *
|
| - * @return {void} Nothing.
|
| - */
|
| -remoting.Application.prototype.onDisconnected = function() {
|
| - this.delegate_.handleDisconnected();
|
| -};
|
| -
|
| -/**
|
| - * Called when the current session's connection has failed.
|
| - *
|
| - * @param {!remoting.Error} error
|
| - * @return {void} Nothing.
|
| - */
|
| -remoting.Application.prototype.onConnectionFailed = function(error) {
|
| - this.delegate_.handleConnectionFailed(this.sessionConnector_, error);
|
| -};
|
| -
|
| -/**
|
| - * Called when an error needs to be displayed to the user.
|
| - *
|
| - * @param {!remoting.Error} errorTag The error to be localized and displayed.
|
| - * @return {void} Nothing.
|
| - */
|
| -remoting.Application.prototype.onError = function(errorTag) {
|
| - this.delegate_.handleError(errorTag);
|
| -};
|
| -
|
| -/**
|
| - * @return {remoting.SessionConnector} A session connector, creating a new one
|
| - * if necessary.
|
| - */
|
| -remoting.Application.prototype.getSessionConnector = function() {
|
| - // TODO(garykac): Check if this can be initialized in the ctor.
|
| - if (!this.sessionConnector_) {
|
| - this.sessionConnector_ = remoting.SessionConnector.factory.createConnector(
|
| - document.getElementById('client-container'),
|
| - this.onConnected.bind(this),
|
| - this.onError.bind(this),
|
| - this.onConnectionFailed.bind(this),
|
| - this.appCapabilities_);
|
| - }
|
| - return this.sessionConnector_;
|
| };
|
|
|
| /**
|
| @@ -186,7 +138,7 @@ remoting.Application.prototype.onSessionFinished_ = function(state) {
|
| switch (state.current) {
|
| case remoting.ClientSession.State.CLOSED:
|
| console.log('Connection closed by host');
|
| - this.onDisconnected();
|
| + this.onDisconnected_();
|
| break;
|
| case remoting.ClientSession.State.FAILED:
|
| var error = remoting.clientSession.getError();
|
| @@ -195,14 +147,14 @@ remoting.Application.prototype.onSessionFinished_ = function(state) {
|
| if (error === null) {
|
| error = remoting.Error.unexpected();
|
| }
|
| - this.onError(error);
|
| + this.onError_(error);
|
| break;
|
|
|
| default:
|
| console.error('Unexpected client plugin state: ' + state.current);
|
| // This should only happen if the web-app and client plugin get out of
|
| // sync, so MISSING_PLUGIN is a suitable error.
|
| - this.onError(new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN));
|
| + this.onError_(new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN));
|
| break;
|
| }
|
|
|
| @@ -219,83 +171,144 @@ remoting.Application.prototype.updateStatistics_ = function() {
|
| };
|
|
|
|
|
| +/*
|
| + * remoting.ApplicationInterface
|
| + * These functions must be overridden in the subclass.
|
| + */
|
| +
|
| +/** @return {string} */
|
| +remoting.Application.prototype.getApplicationName = function() {
|
| + base.debug.assert(false, "Subclass must override");
|
| +};
|
| +
|
| +/**
|
| + * @param {!remoting.Error} error
|
| + * @protected
|
| + */
|
| +remoting.Application.prototype.signInFailed_ = function(error) {
|
| + base.debug.assert(false, "Subclass must override");
|
| +};
|
| +
|
| +/** @protected */
|
| +remoting.Application.prototype.initApplication_ = function() {
|
| + base.debug.assert(false, "Subclass must override");
|
| +};
|
| +
|
| +/**
|
| + * @param {string} token
|
| + * @protected
|
| + */
|
| +remoting.Application.prototype.startApplication_ = function(token) {
|
| + base.debug.assert(false, "Subclass must override");
|
| +};
|
| +
|
| +/** @protected */
|
| +remoting.Application.prototype.exitApplication_ = function() {
|
| + base.debug.assert(false, "Subclass must override");
|
| +};
|
| +
|
| +/**
|
| + * @param {remoting.ConnectionInfo} connectionInfo
|
| + * @protected
|
| + */
|
| +remoting.Application.prototype.onConnected_ = function(connectionInfo) {
|
| + base.debug.assert(false, "Subclass must override");
|
| +};
|
| +
|
| +/** @protected */
|
| +remoting.Application.prototype.onDisconnected_ = function() {
|
| + base.debug.assert(false, "Subclass must override");
|
| +};
|
| +
|
| +/**
|
| + * @param {!remoting.Error} error
|
| + * @protected
|
| + */
|
| +remoting.Application.prototype.onConnectionFailed_ = function(error) {
|
| + base.debug.assert(false, "Subclass must override");
|
| +};
|
| +
|
| +/**
|
| + * @param {!remoting.Error} error The error to be localized and displayed.
|
| + * @protected
|
| + */
|
| +remoting.Application.prototype.onError_ = function(error) {
|
| + base.debug.assert(false, "Subclass must override");
|
| +};
|
| +
|
| +
|
| /**
|
| + * The interface specifies the methods that a subclass of remoting.Application
|
| + * is required implement to override the default behavior.
|
| + *
|
| * @interface
|
| */
|
| -remoting.Application.Delegate = function() {};
|
| +remoting.ApplicationInterface = function() {};
|
| +
|
| +/**
|
| + * @return {string} Application product name to be used in UI.
|
| + */
|
| +remoting.ApplicationInterface.prototype.getApplicationName = function() {};
|
| +
|
| +/**
|
| + * Report an authentication error to the user. This is called in lieu of
|
| + * startApplication() if the user cannot be authenticated or if they decline
|
| + * the app permissions.
|
| + *
|
| + * @param {!remoting.Error} error The failure reason.
|
| + */
|
| +remoting.ApplicationInterface.prototype.signInFailed_ = function(error) {};
|
|
|
| /**
|
| * Initialize the application. This is called before an OAuth token is requested
|
| * and should be used for tasks such as initializing the DOM, registering event
|
| - * handlers, etc.
|
| + * handlers, etc. After this is called, the app is running and waiting for
|
| + * user events.
|
| */
|
| -remoting.Application.Delegate.prototype.init = function() {};
|
| +remoting.ApplicationInterface.prototype.initApplication_ = function() {};
|
|
|
| /**
|
| - * Start the application. Once start() is called, the delegate can assume that
|
| + * Start the application. Once startApplication() is called, we can assume that
|
| * the user has consented to all permissions specified in the manifest.
|
| *
|
| - * @param {remoting.SessionConnector} connector
|
| - * @param {string} token An OAuth access token. The delegate should not cache
|
| + * @param {string} token An OAuth access token. The app should not cache
|
| * this token, but can assume that it will remain valid during application
|
| * start-up.
|
| */
|
| -remoting.Application.Delegate.prototype.start = function(connector, token) {};
|
| -
|
| -/**
|
| - * Report an authentication error to the user. This is called in lieu of start()
|
| - * if the user cannot be authenticated.
|
| - *
|
| - * @param {!remoting.Error} error The failure reason.
|
| - */
|
| -remoting.Application.Delegate.prototype.signInFailed = function(error) {};
|
| +remoting.ApplicationInterface.prototype.startApplication_ = function(token) {};
|
|
|
| /**
|
| - * @return {string} Application product name to be used in UI.
|
| + * Close down the application before exiting.
|
| */
|
| -remoting.Application.Delegate.prototype.getApplicationName = function() {};
|
| +remoting.ApplicationInterface.prototype.exitApplication_ = function() {};
|
|
|
| /**
|
| * Called when a new session has been connected.
|
| *
|
| * @param {remoting.ConnectionInfo} connectionInfo
|
| - * @return {void} Nothing.
|
| */
|
| -remoting.Application.Delegate.prototype.handleConnected = function(
|
| - connectionInfo) {};
|
| +remoting.ApplicationInterface.prototype.onConnected_ =
|
| + function(connectionInfo) {};
|
|
|
| /**
|
| * Called when the current session has been disconnected.
|
| - *
|
| - * @return {void} Nothing.
|
| */
|
| -remoting.Application.Delegate.prototype.handleDisconnected = function() {};
|
| +remoting.ApplicationInterface.prototype.onDisconnected_ = function() {};
|
|
|
| /**
|
| * Called when the current session's connection has failed.
|
| *
|
| - * @param {remoting.SessionConnector} connector
|
| * @param {!remoting.Error} error
|
| - * @return {void} Nothing.
|
| */
|
| -remoting.Application.Delegate.prototype.handleConnectionFailed =
|
| - function(connector, error) {};
|
| +remoting.ApplicationInterface.prototype.onConnectionFailed_ =
|
| + function(error) {};
|
|
|
| /**
|
| * Called when an error needs to be displayed to the user.
|
| *
|
| * @param {!remoting.Error} errorTag The error to be localized and displayed.
|
| - * @return {void} Nothing.
|
| - */
|
| -remoting.Application.Delegate.prototype.handleError = function(errorTag) {};
|
| -
|
| -/**
|
| - * Perform any application-specific cleanup before exiting. This is called in
|
| - * lieu of start() if the user declines the app permissions, and will usually
|
| - * be called immediately prior to exiting, although delegates should not rely
|
| - * on this.
|
| */
|
| -remoting.Application.Delegate.prototype.handleExit = function() {};
|
| +remoting.ApplicationInterface.prototype.onError_ = function(errorTag) {};
|
|
|
|
|
| /** @type {remoting.Application} */
|
|
|