Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / remoting / webapp / smart_reconnector.js
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6  * @fileoverview
7  * Class handling reconnecting the session when it is disconnected due to
8  * network failure.
9  *
10  * The SmartReconnector listens for changes in connection state of
11  * |clientSession| to determine if a reconnection is needed.  It then calls into
12  * |connector| to reconnect the session.
13  */
14
15 'use strict';
16
17 /** @suppress {duplicate} */
18 var remoting = remoting || {};
19
20 /**
21  * @constructor
22  * @param {remoting.SessionConnector} connector This is used to reconnect the
23  *    the session when necessary
24  * @param {remoting.ClientSession} clientSession This represents the current
25  *    remote desktop connection.  It is used to monitor the changes in
26  *    connection state.
27  * @implements {base.Disposable}
28  */
29 remoting.SmartReconnector = function(connector, clientSession) {
30   /** @private */
31   this.connector_ = connector;
32
33   /** @private */
34   this.clientSession_ = clientSession;
35
36   /** @private */
37   this.reconnectTimerId_ = null;
38
39   /** @private */
40   this.connectionTimeoutTimerId_ = null;
41
42   /** @private */
43   this.bound_ = {
44     reconnect: this.reconnect_.bind(this),
45     reconnectAsync: this.reconnectAsync_.bind(this),
46     startReconnectTimeout: this.startReconnectTimeout_.bind(this),
47     stateChanged: this.stateChanged_.bind(this),
48     videoChannelStateChanged: this.videoChannelStateChanged_.bind(this)
49   };
50
51   clientSession.addEventListener(
52       remoting.ClientSession.Events.stateChanged,
53       this.bound_.stateChanged);
54   clientSession.addEventListener(
55       remoting.ClientSession.Events.videoChannelStateChanged,
56       this.bound_.videoChannelStateChanged);
57 };
58
59 // The online event only means the network adapter is enabled, but
60 // it doesn't necessarily mean that we have a working internet connection.
61 // Therefore, delay the connection by |kReconnectDelay| to allow for the network
62 // to connect.
63 remoting.SmartReconnector.kReconnectDelay = 2000;
64
65 // If no frames are received from the server for more than |kConnectionTimeout|,
66 // disconnect the session.
67 remoting.SmartReconnector.kConnectionTimeout = 10000;
68
69 remoting.SmartReconnector.prototype = {
70   reconnect_: function() {
71     this.cancelPending_();
72     remoting.disconnect();
73     remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
74     this.connector_.reconnect();
75   },
76
77   reconnectAsync_: function() {
78     this.cancelPending_();
79     remoting.setMode(remoting.AppMode.CLIENT_CONNECTING);
80     this.reconnectTimerId_ = window.setTimeout(
81         this.bound_.reconnect, remoting.SmartReconnector.kReconnectDelay);
82   },
83
84   /**
85    * @param {remoting.ClientSession.StateEvent} event
86    */
87   stateChanged_: function(event) {
88     var State = remoting.ClientSession.State;
89     if (event.previous === State.CONNECTED && event.current === State.FAILED) {
90       this.cancelPending_();
91       if (navigator.onLine) {
92         this.reconnect_();
93       } else {
94         window.addEventListener('online', this.bound_.reconnectAsync, false);
95       }
96     }
97   },
98
99   /**
100    * @param {boolean} active  This function is called if no frames are received
101    *    on the client for more than 1 second.
102    */
103   videoChannelStateChanged_: function (active) {
104     this.cancelPending_();
105     if (!active) {
106       // If the channel becomes inactive due to a lack of network connection,
107       // wait for it to go online.  The plugin will try to reconnect the video
108       // channel once it is online.  If the video channels doesn't finish
109       // reconnecting within the timeout, tear down the session and reconnect.
110       if (navigator.onLine) {
111         this.reconnect_();
112       } else {
113         window.addEventListener(
114           'online', this.bound_.startReconnectTimeout, false);
115       }
116     }
117   },
118
119   startReconnectTimeout_: function () {
120     this.cancelPending_();
121     this.connectionTimeoutTimerId_ = window.setTimeout(
122           this.bound_.reconnect, remoting.SmartReconnector.kConnectionTimeout);
123   },
124
125   cancelPending_: function() {
126     window.removeEventListener(
127         'online', this.bound_.startReconnectTimeout, false);
128     window.removeEventListener('online', this.bound_.reconnectAsync, false);
129     window.clearTimeout(this.reconnectTimerId_);
130     window.clearTimeout(this.connectionTimeoutTimerId_);
131     this.reconnectTimerId_ = null;
132     this.connectionTimeoutTimerId_ = null;
133   },
134
135   dispose: function() {
136     this.clientSession_.removeEventListener(
137         remoting.ClientSession.Events.stateChanged,
138         this.bound_.stateChanged);
139     this.clientSession_.removeEventListener(
140         remoting.ClientSession.Events.videoChannelStateChanged,
141         this.bound_.videoChannelStateChanged);
142   }
143 };