pusher-fake 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/features/support/application/public/javascripts/vendor/{pusher-2.0.5.js → pusher-2.1.2.js} +497 -280
- data/features/support/application/views/index.erb +3 -7
- data/features/support/coveralls.rb +4 -2
- data/lib/pusher-fake.rb +4 -4
- data/lib/pusher-fake/configuration.rb +10 -0
- data/spec/lib/pusher-fake/configuration_spec.rb +14 -0
- data/spec/lib/pusher_fake_spec.rb +9 -9
- data/spec/support/coveralls.rb +4 -2
- metadata +20 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39d56e9bb6902ed10adbe4bca8166649d40749fc
|
4
|
+
data.tar.gz: 5a8e70714a86266a036d0a56c31564fbf8972dd2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 31ab418c7631fb803180cef6bca7eddac1ba06b5dc64be52cd35033412404b6e328cf631c962e11a1a8fe8f5a613dc7fa80d834004b2a0df6f3d4ea0eb62149e
|
7
|
+
data.tar.gz: bac0c88bd45616f6dc8ef8a829d2fe4682be67879778c95786aca8cc77e4175679c578bbf958b13cf64e064fc059a4a7ac56d4c55963f10ee014997b7141f22d
|
data/features/support/application/public/javascripts/vendor/{pusher-2.0.5.js → pusher-2.1.2.js}
RENAMED
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* Pusher JavaScript Library v2.
|
2
|
+
* Pusher JavaScript Library v2.1.2
|
3
3
|
* http://pusherapp.com/
|
4
4
|
*
|
5
5
|
* Copyright 2013, Pusher
|
@@ -8,70 +8,75 @@
|
|
8
8
|
|
9
9
|
;(function() {
|
10
10
|
function Pusher(app_key, options) {
|
11
|
+
checkAppKey(app_key);
|
12
|
+
options = options || {};
|
13
|
+
|
11
14
|
var self = this;
|
12
15
|
|
13
|
-
this.options = options || {};
|
14
16
|
this.key = app_key;
|
17
|
+
this.config = Pusher.Util.extend(
|
18
|
+
Pusher.getGlobalConfig(),
|
19
|
+
options.cluster ? Pusher.getClusterConfig(options.cluster) : {},
|
20
|
+
options
|
21
|
+
);
|
22
|
+
|
15
23
|
this.channels = new Pusher.Channels();
|
16
24
|
this.global_emitter = new Pusher.EventsDispatcher();
|
17
25
|
this.sessionID = Math.floor(Math.random() * 1000000000);
|
18
26
|
|
19
|
-
|
27
|
+
this.timeline = new Pusher.Timeline(this.key, this.sessionID, {
|
28
|
+
features: Pusher.Util.getClientFeatures(),
|
29
|
+
params: this.config.timelineParams || {},
|
30
|
+
limit: 50,
|
31
|
+
level: Pusher.Timeline.INFO,
|
32
|
+
version: Pusher.VERSION
|
33
|
+
});
|
34
|
+
if (!this.config.disableStats) {
|
35
|
+
this.timelineSender = new Pusher.TimelineSender(this.timeline, {
|
36
|
+
host: this.config.statsHost,
|
37
|
+
path: "/timeline"
|
38
|
+
});
|
39
|
+
}
|
20
40
|
|
21
41
|
var getStrategy = function(options) {
|
22
42
|
return Pusher.StrategyBuilder.build(
|
23
|
-
Pusher.getDefaultStrategy(),
|
24
|
-
Pusher.Util.extend({}, self.
|
43
|
+
Pusher.getDefaultStrategy(self.config),
|
44
|
+
Pusher.Util.extend({}, self.config, options)
|
25
45
|
);
|
26
46
|
};
|
27
|
-
var getTimeline = function() {
|
28
|
-
return new Pusher.Timeline(self.key, self.sessionID, {
|
29
|
-
features: Pusher.Util.getClientFeatures(),
|
30
|
-
params: self.options.timelineParams || {},
|
31
|
-
limit: 50,
|
32
|
-
level: Pusher.Timeline.INFO,
|
33
|
-
version: Pusher.VERSION
|
34
|
-
});
|
35
|
-
};
|
36
|
-
var getTimelineSender = function(timeline, options) {
|
37
|
-
if (self.options.disableStats) {
|
38
|
-
return null;
|
39
|
-
}
|
40
|
-
return new Pusher.TimelineSender(timeline, {
|
41
|
-
encrypted: self.isEncrypted() || !!options.encrypted,
|
42
|
-
host: Pusher.stats_host,
|
43
|
-
path: "/timeline"
|
44
|
-
});
|
45
|
-
};
|
46
47
|
|
47
48
|
this.connection = new Pusher.ConnectionManager(
|
48
49
|
this.key,
|
49
50
|
Pusher.Util.extend(
|
50
51
|
{ getStrategy: getStrategy,
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
unavailableTimeout: Pusher.unavailable_timeout
|
52
|
+
timeline: this.timeline,
|
53
|
+
activityTimeout: this.config.activity_timeout,
|
54
|
+
pongTimeout: this.config.pong_timeout,
|
55
|
+
unavailableTimeout: this.config.unavailable_timeout
|
56
56
|
},
|
57
|
-
this.
|
57
|
+
this.config,
|
58
58
|
{ encrypted: this.isEncrypted() }
|
59
59
|
)
|
60
60
|
);
|
61
61
|
|
62
62
|
this.connection.bind('connected', function() {
|
63
63
|
self.subscribeAll();
|
64
|
+
if (self.timelineSender) {
|
65
|
+
self.timelineSender.send(self.connection.isEncrypted());
|
66
|
+
}
|
64
67
|
});
|
65
68
|
this.connection.bind('message', function(params) {
|
66
69
|
var internal = (params.event.indexOf('pusher_internal:') === 0);
|
67
70
|
if (params.channel) {
|
68
71
|
var channel = self.channel(params.channel);
|
69
72
|
if (channel) {
|
70
|
-
channel.
|
73
|
+
channel.handleEvent(params.event, params.data);
|
71
74
|
}
|
72
75
|
}
|
73
76
|
// Emit globaly [deprecated]
|
74
|
-
if (!internal)
|
77
|
+
if (!internal) {
|
78
|
+
self.global_emitter.emit(params.event, params.data);
|
79
|
+
}
|
75
80
|
});
|
76
81
|
this.connection.bind('disconnected', function() {
|
77
82
|
self.channels.disconnect();
|
@@ -125,10 +130,25 @@
|
|
125
130
|
|
126
131
|
prototype.connect = function() {
|
127
132
|
this.connection.connect();
|
133
|
+
|
134
|
+
if (this.timelineSender) {
|
135
|
+
if (!this.timelineSenderTimer) {
|
136
|
+
var encrypted = this.connection.isEncrypted();
|
137
|
+
var timelineSender = this.timelineSender;
|
138
|
+
this.timelineSenderTimer = new Pusher.PeriodicTimer(60000, function() {
|
139
|
+
timelineSender.send(encrypted);
|
140
|
+
});
|
141
|
+
}
|
142
|
+
}
|
128
143
|
};
|
129
144
|
|
130
145
|
prototype.disconnect = function() {
|
131
146
|
this.connection.disconnect();
|
147
|
+
|
148
|
+
if (this.timelineSenderTimer) {
|
149
|
+
this.timelineSenderTimer.ensureAborted();
|
150
|
+
this.timelineSenderTimer = null;
|
151
|
+
}
|
132
152
|
};
|
133
153
|
|
134
154
|
prototype.bind = function(event_name, callback) {
|
@@ -151,35 +171,17 @@
|
|
151
171
|
};
|
152
172
|
|
153
173
|
prototype.subscribe = function(channel_name) {
|
154
|
-
var self = this;
|
155
174
|
var channel = this.channels.add(channel_name, this);
|
156
|
-
|
157
175
|
if (this.connection.state === 'connected') {
|
158
|
-
channel.
|
159
|
-
this.connection.socket_id,
|
160
|
-
this.options,
|
161
|
-
function(err, data) {
|
162
|
-
if (err) {
|
163
|
-
channel.emit('pusher:subscription_error', data);
|
164
|
-
} else {
|
165
|
-
self.send_event('pusher:subscribe', {
|
166
|
-
channel: channel_name,
|
167
|
-
auth: data.auth,
|
168
|
-
channel_data: data.channel_data
|
169
|
-
});
|
170
|
-
}
|
171
|
-
}
|
172
|
-
);
|
176
|
+
channel.subscribe();
|
173
177
|
}
|
174
178
|
return channel;
|
175
179
|
};
|
176
180
|
|
177
181
|
prototype.unsubscribe = function(channel_name) {
|
178
|
-
this.channels.remove(channel_name);
|
182
|
+
var channel = this.channels.remove(channel_name);
|
179
183
|
if (this.connection.state === 'connected') {
|
180
|
-
|
181
|
-
channel: channel_name
|
182
|
-
});
|
184
|
+
channel.unsubscribe();
|
183
185
|
}
|
184
186
|
};
|
185
187
|
|
@@ -191,7 +193,7 @@
|
|
191
193
|
if (Pusher.Util.getDocumentLocation().protocol === "https:") {
|
192
194
|
return true;
|
193
195
|
} else {
|
194
|
-
return
|
196
|
+
return Boolean(this.config.encrypted);
|
195
197
|
}
|
196
198
|
};
|
197
199
|
|
@@ -488,7 +490,11 @@
|
|
488
490
|
},
|
489
491
|
|
490
492
|
getLocalStorage: function() {
|
491
|
-
|
493
|
+
try {
|
494
|
+
return window.localStorage;
|
495
|
+
} catch (e) {
|
496
|
+
return undefined;
|
497
|
+
}
|
492
498
|
},
|
493
499
|
|
494
500
|
getClientFeatures: function() {
|
@@ -503,39 +509,40 @@
|
|
503
509
|
}).call(this);
|
504
510
|
|
505
511
|
;(function() {
|
506
|
-
Pusher.VERSION = '2.
|
512
|
+
Pusher.VERSION = '2.1.2';
|
507
513
|
Pusher.PROTOCOL = 6;
|
508
514
|
|
509
|
-
// WS connection parameters
|
515
|
+
// DEPRECATED: WS connection parameters
|
510
516
|
Pusher.host = 'ws.pusherapp.com';
|
511
517
|
Pusher.ws_port = 80;
|
512
518
|
Pusher.wss_port = 443;
|
513
|
-
// SockJS fallback parameters
|
519
|
+
// DEPRECATED: SockJS fallback parameters
|
514
520
|
Pusher.sockjs_host = 'sockjs.pusher.com';
|
515
521
|
Pusher.sockjs_http_port = 80;
|
516
522
|
Pusher.sockjs_https_port = 443;
|
517
523
|
Pusher.sockjs_path = "/pusher";
|
518
|
-
// Stats
|
524
|
+
// DEPRECATED: Stats
|
519
525
|
Pusher.stats_host = 'stats.pusher.com';
|
520
|
-
// Other settings
|
526
|
+
// DEPRECATED: Other settings
|
521
527
|
Pusher.channel_auth_endpoint = '/pusher/auth';
|
522
|
-
Pusher.cdn_http = 'http://js.pusher.com/';
|
523
|
-
Pusher.cdn_https = 'https://d3dy5gmtp8yhk7.cloudfront.net/';
|
524
|
-
Pusher.dependency_suffix = '';
|
525
528
|
Pusher.channel_auth_transport = 'ajax';
|
526
529
|
Pusher.activity_timeout = 120000;
|
527
530
|
Pusher.pong_timeout = 30000;
|
528
531
|
Pusher.unavailable_timeout = 10000;
|
532
|
+
// CDN configuration
|
533
|
+
Pusher.cdn_http = 'http://js.pusher.com/';
|
534
|
+
Pusher.cdn_https = 'https://d3dy5gmtp8yhk7.cloudfront.net/';
|
535
|
+
Pusher.dependency_suffix = '';
|
529
536
|
|
530
|
-
Pusher.getDefaultStrategy = function() {
|
537
|
+
Pusher.getDefaultStrategy = function(config) {
|
531
538
|
return [
|
532
539
|
[":def", "ws_options", {
|
533
|
-
hostUnencrypted:
|
534
|
-
hostEncrypted:
|
540
|
+
hostUnencrypted: config.wsHost + ":" + config.wsPort,
|
541
|
+
hostEncrypted: config.wsHost + ":" + config.wssPort
|
535
542
|
}],
|
536
543
|
[":def", "sockjs_options", {
|
537
|
-
hostUnencrypted:
|
538
|
-
hostEncrypted:
|
544
|
+
hostUnencrypted: config.httpHost + ":" + config.httpPort,
|
545
|
+
hostEncrypted: config.httpHost + ":" + config.httpsPort
|
539
546
|
}],
|
540
547
|
[":def", "timeouts", {
|
541
548
|
loop: true,
|
@@ -543,7 +550,12 @@
|
|
543
550
|
timeoutLimit: 60000
|
544
551
|
}],
|
545
552
|
|
546
|
-
[":def", "ws_manager", [":transport_manager", {
|
553
|
+
[":def", "ws_manager", [":transport_manager", {
|
554
|
+
lives: 2,
|
555
|
+
minPingDelay: 10000,
|
556
|
+
maxPingDelay: config.activity_timeout
|
557
|
+
}]],
|
558
|
+
|
547
559
|
[":def_transport", "ws", "ws", 3, ":ws_options", ":ws_manager"],
|
548
560
|
[":def_transport", "flash", "flash", 2, ":ws_options", ":ws_manager"],
|
549
561
|
[":def_transport", "sockjs", "sockjs", 1, ":sockjs_options"],
|
@@ -569,6 +581,34 @@
|
|
569
581
|
};
|
570
582
|
}).call(this);
|
571
583
|
|
584
|
+
;(function() {
|
585
|
+
Pusher.getGlobalConfig = function() {
|
586
|
+
return {
|
587
|
+
wsHost: Pusher.host,
|
588
|
+
wsPort: Pusher.ws_port,
|
589
|
+
wssPort: Pusher.wss_port,
|
590
|
+
httpHost: Pusher.sockjs_host,
|
591
|
+
httpPort: Pusher.sockjs_http_port,
|
592
|
+
httpsPort: Pusher.sockjs_https_port,
|
593
|
+
httpPath: Pusher.sockjs_path,
|
594
|
+
statsHost: Pusher.stats_host,
|
595
|
+
authEndpoint: Pusher.channel_auth_endpoint,
|
596
|
+
authTransport: Pusher.channel_auth_transport,
|
597
|
+
// TODO make this consistent with other options in next major version
|
598
|
+
activity_timeout: Pusher.activity_timeout,
|
599
|
+
pong_timeout: Pusher.pong_timeout,
|
600
|
+
unavailable_timeout: Pusher.unavailable_timeout
|
601
|
+
};
|
602
|
+
};
|
603
|
+
|
604
|
+
Pusher.getClusterConfig = function(clusterName) {
|
605
|
+
return {
|
606
|
+
wsHost: "ws-" + clusterName + ".pusher.com",
|
607
|
+
httpHost: "sockjs-" + clusterName + ".pusher.com"
|
608
|
+
};
|
609
|
+
};
|
610
|
+
}).call(this);
|
611
|
+
|
572
612
|
;(function() {
|
573
613
|
function buildExceptionClass(name) {
|
574
614
|
var klass = function(message) {
|
@@ -697,24 +737,22 @@
|
|
697
737
|
|
698
738
|
if (this.loaded[name]) {
|
699
739
|
callback();
|
700
|
-
|
701
|
-
|
740
|
+
} else if (this.loading[name] && this.loading[name].length > 0) {
|
741
|
+
this.loading[name].push(callback);
|
742
|
+
} else {
|
743
|
+
this.loading[name] = [callback];
|
702
744
|
|
703
|
-
|
704
|
-
|
705
|
-
}
|
706
|
-
this.loading[name].push(callback);
|
707
|
-
if (this.loading[name].length > 1) {
|
708
|
-
return;
|
709
|
-
}
|
745
|
+
require(this.getPath(name), function() {
|
746
|
+
self.loaded[name] = true;
|
710
747
|
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
748
|
+
if (self.loading[name]) {
|
749
|
+
for (var i = 0; i < self.loading[name].length; i++) {
|
750
|
+
self.loading[name][i]();
|
751
|
+
}
|
752
|
+
delete self.loading[name];
|
753
|
+
}
|
754
|
+
});
|
755
|
+
}
|
718
756
|
};
|
719
757
|
|
720
758
|
/** Returns a root URL for pusher-js CDN.
|
@@ -850,6 +888,42 @@
|
|
850
888
|
Pusher.Timer = Timer;
|
851
889
|
}).call(this);
|
852
890
|
|
891
|
+
;(function() {
|
892
|
+
/** Cross-browser compatible periodic timer abstraction.
|
893
|
+
*
|
894
|
+
* @param {Number} interval
|
895
|
+
* @param {Function} callback
|
896
|
+
*/
|
897
|
+
function PeriodicTimer(interval, callback) {
|
898
|
+
var self = this;
|
899
|
+
|
900
|
+
this.interval = setInterval(function() {
|
901
|
+
if (self.interval !== null) {
|
902
|
+
callback();
|
903
|
+
}
|
904
|
+
}, interval);
|
905
|
+
}
|
906
|
+
var prototype = PeriodicTimer.prototype;
|
907
|
+
|
908
|
+
/** Returns whether the timer is still running.
|
909
|
+
*
|
910
|
+
* @return {Boolean}
|
911
|
+
*/
|
912
|
+
prototype.isRunning = function() {
|
913
|
+
return this.interval !== null;
|
914
|
+
};
|
915
|
+
|
916
|
+
/** Aborts a timer when it's running. */
|
917
|
+
prototype.ensureAborted = function() {
|
918
|
+
if (this.interval) {
|
919
|
+
clearInterval(this.interval);
|
920
|
+
this.interval = null;
|
921
|
+
}
|
922
|
+
};
|
923
|
+
|
924
|
+
Pusher.PeriodicTimer = PeriodicTimer;
|
925
|
+
}).call(this);
|
926
|
+
|
853
927
|
(function() {
|
854
928
|
|
855
929
|
var Base64 = {
|
@@ -1114,7 +1188,9 @@
|
|
1114
1188
|
if (!error) {
|
1115
1189
|
self.sent++;
|
1116
1190
|
}
|
1117
|
-
callback
|
1191
|
+
if (callback) {
|
1192
|
+
callback(error, result);
|
1193
|
+
}
|
1118
1194
|
});
|
1119
1195
|
|
1120
1196
|
return true;
|
@@ -1135,26 +1211,30 @@
|
|
1135
1211
|
}
|
1136
1212
|
var prototype = TimelineSender.prototype;
|
1137
1213
|
|
1138
|
-
prototype.send = function(callback) {
|
1214
|
+
prototype.send = function(encrypted, callback) {
|
1139
1215
|
if (this.timeline.isEmpty()) {
|
1140
1216
|
return;
|
1141
1217
|
}
|
1142
1218
|
|
1143
|
-
var
|
1144
|
-
var scheme = "http" + (
|
1219
|
+
var self = this;
|
1220
|
+
var scheme = "http" + (encrypted ? "s" : "") + "://";
|
1145
1221
|
|
1146
1222
|
var sendJSONP = function(data, callback) {
|
1147
|
-
|
1223
|
+
var params = {
|
1148
1224
|
data: data,
|
1149
|
-
url: scheme + options.host + options.path,
|
1225
|
+
url: scheme + (self.host || self.options.host) + self.options.path,
|
1150
1226
|
receiver: Pusher.JSONP
|
1151
|
-
}
|
1227
|
+
};
|
1228
|
+
return Pusher.JSONPRequest.send(params, function(error, result) {
|
1229
|
+
if (result.host) {
|
1230
|
+
self.host = result.host;
|
1231
|
+
}
|
1232
|
+
if (callback) {
|
1233
|
+
callback(error, result);
|
1234
|
+
}
|
1235
|
+
});
|
1152
1236
|
};
|
1153
|
-
|
1154
|
-
};
|
1155
|
-
|
1156
|
-
prototype.isEncrypted = function() {
|
1157
|
-
return !!this.options.encrypted;
|
1237
|
+
self.timeline.send(sendJSONP, callback);
|
1158
1238
|
};
|
1159
1239
|
|
1160
1240
|
Pusher.TimelineSender = TimelineSender;
|
@@ -1826,7 +1906,9 @@
|
|
1826
1906
|
// Workaround for MobileSafari bug (see https://gist.github.com/2052006)
|
1827
1907
|
var self = this;
|
1828
1908
|
setTimeout(function() {
|
1829
|
-
self.socket
|
1909
|
+
if (self.socket) {
|
1910
|
+
self.socket.send(data);
|
1911
|
+
}
|
1830
1912
|
}, 0);
|
1831
1913
|
return true;
|
1832
1914
|
} else {
|
@@ -1847,14 +1929,20 @@
|
|
1847
1929
|
/** @protected */
|
1848
1930
|
prototype.onError = function(error) {
|
1849
1931
|
this.emit("error", { type: 'WebSocketError', error: error });
|
1850
|
-
this.timeline.error(this.buildTimelineMessage({
|
1851
|
-
error: getErrorDetails(error)
|
1852
|
-
}));
|
1932
|
+
this.timeline.error(this.buildTimelineMessage({}));
|
1853
1933
|
};
|
1854
1934
|
|
1855
1935
|
/** @protected */
|
1856
1936
|
prototype.onClose = function(closeEvent) {
|
1857
|
-
|
1937
|
+
if (closeEvent) {
|
1938
|
+
this.changeState("closed", {
|
1939
|
+
code: closeEvent.code,
|
1940
|
+
reason: closeEvent.reason,
|
1941
|
+
wasClean: closeEvent.wasClean
|
1942
|
+
});
|
1943
|
+
} else {
|
1944
|
+
this.changeState("closed");
|
1945
|
+
}
|
1858
1946
|
this.socket = undefined;
|
1859
1947
|
};
|
1860
1948
|
|
@@ -1926,22 +2014,6 @@
|
|
1926
2014
|
return Pusher.Util.extend({ cid: this.id }, message);
|
1927
2015
|
};
|
1928
2016
|
|
1929
|
-
function getErrorDetails(error) {
|
1930
|
-
if (typeof error === "string") {
|
1931
|
-
return error;
|
1932
|
-
}
|
1933
|
-
if (typeof error === "object") {
|
1934
|
-
return Pusher.Util.mapObject(error, function(value) {
|
1935
|
-
var valueType = typeof value;
|
1936
|
-
if (valueType === "object" || valueType == "function") {
|
1937
|
-
return valueType;
|
1938
|
-
}
|
1939
|
-
return value;
|
1940
|
-
});
|
1941
|
-
}
|
1942
|
-
return typeof error;
|
1943
|
-
}
|
1944
|
-
|
1945
2017
|
Pusher.AbstractTransport = AbstractTransport;
|
1946
2018
|
}).call(this);
|
1947
2019
|
|
@@ -2103,7 +2175,7 @@
|
|
2103
2175
|
|
2104
2176
|
/** @protected */
|
2105
2177
|
prototype.getPath = function() {
|
2106
|
-
return "/pusher";
|
2178
|
+
return this.options.httpPath || "/pusher";
|
2107
2179
|
};
|
2108
2180
|
|
2109
2181
|
/** @protected */
|
@@ -2178,8 +2250,8 @@
|
|
2178
2250
|
function AssistantToTheTransportManager(manager, transport, options) {
|
2179
2251
|
this.manager = manager;
|
2180
2252
|
this.transport = transport;
|
2181
|
-
this.minPingDelay = options.minPingDelay
|
2182
|
-
this.maxPingDelay = options.maxPingDelay
|
2253
|
+
this.minPingDelay = options.minPingDelay;
|
2254
|
+
this.maxPingDelay = options.maxPingDelay;
|
2183
2255
|
this.pingDelay = null;
|
2184
2256
|
}
|
2185
2257
|
var prototype = AssistantToTheTransportManager.prototype;
|
@@ -2214,11 +2286,11 @@
|
|
2214
2286
|
pingTimer = null;
|
2215
2287
|
}
|
2216
2288
|
|
2217
|
-
if (closeEvent.
|
2218
|
-
|
2219
|
-
|
2220
|
-
|
2221
|
-
|
2289
|
+
if (closeEvent.code === 1002 || closeEvent.code === 1003) {
|
2290
|
+
// we don't want to use transports not obeying the protocol
|
2291
|
+
self.manager.reportDeath();
|
2292
|
+
} else if (!closeEvent.wasClean && openTimestamp) {
|
2293
|
+
// report deaths only for short-living transport
|
2222
2294
|
var lifespan = Pusher.Util.now() - openTimestamp;
|
2223
2295
|
if (lifespan < 2 * self.maxPingDelay) {
|
2224
2296
|
self.manager.reportDeath();
|
@@ -2822,7 +2894,7 @@
|
|
2822
2894
|
this.state = "initialized";
|
2823
2895
|
this.connection = null;
|
2824
2896
|
this.encrypted = !!options.encrypted;
|
2825
|
-
this.timeline = this.options.
|
2897
|
+
this.timeline = this.options.timeline;
|
2826
2898
|
|
2827
2899
|
this.connectionCallbacks = this.buildConnectionCallbacks();
|
2828
2900
|
this.errorCallbacks = this.buildErrorCallbacks();
|
@@ -2844,14 +2916,6 @@
|
|
2844
2916
|
}
|
2845
2917
|
});
|
2846
2918
|
|
2847
|
-
var sendTimeline = function() {
|
2848
|
-
if (self.timelineSender) {
|
2849
|
-
self.timelineSender.send(function() {});
|
2850
|
-
}
|
2851
|
-
};
|
2852
|
-
this.bind("connected", sendTimeline);
|
2853
|
-
setInterval(sendTimeline, 60000);
|
2854
|
-
|
2855
2919
|
this.updateStrategy();
|
2856
2920
|
}
|
2857
2921
|
var prototype = ConnectionManager.prototype;
|
@@ -2883,19 +2947,18 @@
|
|
2883
2947
|
}
|
2884
2948
|
|
2885
2949
|
self.updateState("connecting");
|
2886
|
-
self.timelineSender = self.options.getTimelineSender(
|
2887
|
-
self.timeline,
|
2888
|
-
{ encrypted: self.encrypted },
|
2889
|
-
self
|
2890
|
-
);
|
2891
2950
|
|
2892
2951
|
var callback = function(error, handshake) {
|
2893
2952
|
if (error) {
|
2894
2953
|
self.runner = self.strategy.connect(0, callback);
|
2895
2954
|
} else {
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2955
|
+
if (handshake.action === "error") {
|
2956
|
+
self.timeline.error({ handshakeError: handshake.error });
|
2957
|
+
} else {
|
2958
|
+
// we don't support switching connections yet
|
2959
|
+
self.runner.abort();
|
2960
|
+
self.handshakeCallbacks[handshake.action](handshake);
|
2961
|
+
}
|
2899
2962
|
}
|
2900
2963
|
};
|
2901
2964
|
self.runner = self.strategy.connect(0, callback);
|
@@ -2946,6 +3009,10 @@
|
|
2946
3009
|
}
|
2947
3010
|
};
|
2948
3011
|
|
3012
|
+
prototype.isEncrypted = function() {
|
3013
|
+
return this.encrypted;
|
3014
|
+
};
|
3015
|
+
|
2949
3016
|
/** @private */
|
2950
3017
|
prototype.updateStrategy = function() {
|
2951
3018
|
this.strategy = this.options.getStrategy({
|
@@ -2959,6 +3026,9 @@
|
|
2959
3026
|
prototype.retryIn = function(delay) {
|
2960
3027
|
var self = this;
|
2961
3028
|
self.timeline.info({ action: "retry", delay: delay });
|
3029
|
+
if (delay > 0) {
|
3030
|
+
self.emit("connecting_in", Math.round(delay / 1000));
|
3031
|
+
}
|
2962
3032
|
self.retryTimer = new Pusher.Timer(delay || 0, function() {
|
2963
3033
|
self.disconnect();
|
2964
3034
|
self.connect();
|
@@ -3004,6 +3074,7 @@
|
|
3004
3074
|
self.activityTimer = new Pusher.Timer(
|
3005
3075
|
self.options.pongTimeout,
|
3006
3076
|
function() {
|
3077
|
+
self.timeline.error({ pong_timed_out: self.options.pongTimeout });
|
3007
3078
|
self.connection.close();
|
3008
3079
|
}
|
3009
3080
|
);
|
@@ -3055,6 +3126,7 @@
|
|
3055
3126
|
self.clearUnavailableTimer();
|
3056
3127
|
self.setConnection(handshake.connection);
|
3057
3128
|
self.socket_id = self.connection.id;
|
3129
|
+
self.timeline.info({ socket_id: self.socket_id });
|
3058
3130
|
self.updateState("connected");
|
3059
3131
|
}
|
3060
3132
|
});
|
@@ -3180,187 +3252,331 @@
|
|
3180
3252
|
}).call(this);
|
3181
3253
|
|
3182
3254
|
;(function() {
|
3183
|
-
|
3184
|
-
|
3255
|
+
/** Represents a collection of members of a presence channel. */
|
3256
|
+
function Members() {
|
3257
|
+
this.reset();
|
3258
|
+
}
|
3259
|
+
var prototype = Members.prototype;
|
3260
|
+
|
3261
|
+
/** Returns member's info for given id.
|
3262
|
+
*
|
3263
|
+
* Resulting object containts two fields - id and info.
|
3264
|
+
*
|
3265
|
+
* @param {Number} id
|
3266
|
+
* @return {Object} member's info or null
|
3267
|
+
*/
|
3268
|
+
prototype.get = function(id) {
|
3269
|
+
if (Object.prototype.hasOwnProperty.call(this.members, id)) {
|
3270
|
+
return {
|
3271
|
+
id: id,
|
3272
|
+
info: this.members[id]
|
3273
|
+
};
|
3274
|
+
} else {
|
3275
|
+
return null;
|
3276
|
+
}
|
3185
3277
|
};
|
3186
3278
|
|
3187
|
-
|
3188
|
-
|
3189
|
-
|
3190
|
-
|
3191
|
-
|
3192
|
-
|
3193
|
-
|
3194
|
-
|
3195
|
-
|
3196
|
-
|
3197
|
-
},
|
3279
|
+
/** Calls back for each member in unspecified order.
|
3280
|
+
*
|
3281
|
+
* @param {Function} callback
|
3282
|
+
*/
|
3283
|
+
prototype.each = function(callback) {
|
3284
|
+
var self = this;
|
3285
|
+
Pusher.Util.objectApply(self.members, function(member, id) {
|
3286
|
+
callback(self.get(id));
|
3287
|
+
});
|
3288
|
+
};
|
3198
3289
|
|
3199
|
-
|
3200
|
-
|
3201
|
-
|
3290
|
+
/** Updates the id for connected member. For internal use only. */
|
3291
|
+
prototype.setMyID = function(id) {
|
3292
|
+
this.myID = id;
|
3293
|
+
};
|
3202
3294
|
|
3203
|
-
|
3204
|
-
|
3205
|
-
|
3295
|
+
/** Handles subscription data. For internal use only. */
|
3296
|
+
prototype.onSubscription = function(subscriptionData) {
|
3297
|
+
this.members = subscriptionData.presence.hash;
|
3298
|
+
this.count = subscriptionData.presence.count;
|
3299
|
+
this.me = this.get(this.myID);
|
3300
|
+
};
|
3206
3301
|
|
3207
|
-
|
3208
|
-
|
3209
|
-
|
3210
|
-
|
3302
|
+
/** Adds a new member to the collection. For internal use only. */
|
3303
|
+
prototype.addMember = function(memberData) {
|
3304
|
+
if (this.get(memberData.user_id) === null) {
|
3305
|
+
this.count++;
|
3211
3306
|
}
|
3307
|
+
this.members[memberData.user_id] = memberData.user_info;
|
3308
|
+
return this.get(memberData.user_id);
|
3212
3309
|
};
|
3213
3310
|
|
3214
|
-
|
3215
|
-
|
3216
|
-
|
3217
|
-
|
3218
|
-
|
3219
|
-
|
3220
|
-
|
3221
|
-
|
3222
|
-
|
3311
|
+
/** Adds a member from the collection. For internal use only. */
|
3312
|
+
prototype.removeMember = function(memberData) {
|
3313
|
+
var member = this.get(memberData.user_id);
|
3314
|
+
if (member) {
|
3315
|
+
delete this.members[memberData.user_id];
|
3316
|
+
this.count--;
|
3317
|
+
}
|
3318
|
+
return member;
|
3319
|
+
};
|
3223
3320
|
|
3224
|
-
|
3225
|
-
|
3226
|
-
}
|
3321
|
+
/** Resets the collection to the initial state. For internal use only. */
|
3322
|
+
prototype.reset = function() {
|
3323
|
+
this.members = {};
|
3324
|
+
this.count = 0;
|
3325
|
+
this.myID = null;
|
3326
|
+
this.me = null;
|
3227
3327
|
};
|
3228
3328
|
|
3229
|
-
Pusher.
|
3230
|
-
|
3231
|
-
init: function() {},
|
3232
|
-
disconnect: function() {
|
3233
|
-
this.subscribed = false;
|
3234
|
-
this.emit("pusher_internal:disconnected");
|
3235
|
-
},
|
3329
|
+
Pusher.Members = Members;
|
3330
|
+
}).call(this);
|
3236
3331
|
|
3237
|
-
|
3238
|
-
|
3239
|
-
|
3240
|
-
|
3332
|
+
;(function() {
|
3333
|
+
/** Provides base public channel interface with an event emitter.
|
3334
|
+
*
|
3335
|
+
* Emits:
|
3336
|
+
* - pusher:subscription_succeeded - after subscribing successfully
|
3337
|
+
* - other non-internal events
|
3338
|
+
*
|
3339
|
+
* @param {String} name
|
3340
|
+
* @param {Pusher} pusher
|
3341
|
+
*/
|
3342
|
+
function Channel(name, pusher) {
|
3343
|
+
Pusher.EventsDispatcher.call(this, function(event, data) {
|
3344
|
+
Pusher.debug('No callbacks on ' + name + ' for ' + event);
|
3345
|
+
});
|
3241
3346
|
|
3242
|
-
|
3243
|
-
|
3244
|
-
|
3347
|
+
this.name = name;
|
3348
|
+
this.pusher = pusher;
|
3349
|
+
this.subscribed = false;
|
3350
|
+
}
|
3351
|
+
var prototype = Channel.prototype;
|
3352
|
+
Pusher.Util.extend(prototype, Pusher.EventsDispatcher.prototype);
|
3245
3353
|
|
3246
|
-
|
3247
|
-
|
3248
|
-
|
3354
|
+
/** Skips authorization, since public channels don't require it.
|
3355
|
+
*
|
3356
|
+
* @param {Function} callback
|
3357
|
+
*/
|
3358
|
+
prototype.authorize = function(socketId, callback) {
|
3359
|
+
return callback(false, {});
|
3249
3360
|
};
|
3250
3361
|
|
3251
|
-
|
3362
|
+
/** Triggers an event */
|
3363
|
+
prototype.trigger = function(event, data) {
|
3364
|
+
return this.pusher.send_event(event, data, this.name);
|
3365
|
+
};
|
3252
3366
|
|
3253
|
-
|
3254
|
-
|
3255
|
-
|
3256
|
-
|
3257
|
-
return authorizer.authorize(socketId, function(err, authData) {
|
3258
|
-
if(!err) {
|
3259
|
-
self.emit('pusher_internal:authorized', authData);
|
3260
|
-
}
|
3367
|
+
/** Signals disconnection to the channel. For internal use only. */
|
3368
|
+
prototype.disconnect = function() {
|
3369
|
+
this.subscribed = false;
|
3370
|
+
};
|
3261
3371
|
|
3262
|
-
|
3263
|
-
|
3372
|
+
/** Handles an event. For internal use only.
|
3373
|
+
*
|
3374
|
+
* @param {String} event
|
3375
|
+
* @param {*} data
|
3376
|
+
*/
|
3377
|
+
prototype.handleEvent = function(event, data) {
|
3378
|
+
if (event.indexOf("pusher_internal:") === 0) {
|
3379
|
+
if (event === "pusher_internal:subscription_succeeded") {
|
3380
|
+
this.subscribed = true;
|
3381
|
+
this.emit("pusher:subscription_succeeded", data);
|
3382
|
+
}
|
3383
|
+
} else {
|
3384
|
+
this.emit(event, data);
|
3264
3385
|
}
|
3265
3386
|
};
|
3266
3387
|
|
3267
|
-
|
3268
|
-
|
3269
|
-
|
3270
|
-
},
|
3388
|
+
/** Sends a subscription request. For internal use only. */
|
3389
|
+
prototype.subscribe = function() {
|
3390
|
+
var self = this;
|
3271
3391
|
|
3272
|
-
|
3273
|
-
|
3274
|
-
|
3275
|
-
|
3276
|
-
|
3392
|
+
self.authorize(self.pusher.connection.socket_id, function(error, data) {
|
3393
|
+
if (error) {
|
3394
|
+
self.handleEvent('pusher:subscription_error', data);
|
3395
|
+
} else {
|
3396
|
+
self.pusher.send_event('pusher:subscribe', {
|
3397
|
+
auth: data.auth,
|
3398
|
+
channel_data: data.channel_data,
|
3399
|
+
channel: self.name
|
3400
|
+
});
|
3401
|
+
}
|
3402
|
+
});
|
3277
3403
|
};
|
3278
3404
|
|
3279
|
-
|
3280
|
-
|
3281
|
-
|
3405
|
+
/** Sends an unsubscription request. For internal use only. */
|
3406
|
+
prototype.unsubscribe = function() {
|
3407
|
+
this.pusher.send_event('pusher:unsubscribe', {
|
3408
|
+
channel: this.name
|
3409
|
+
});
|
3410
|
+
};
|
3282
3411
|
|
3283
|
-
|
3284
|
-
|
3285
|
-
self.count = 0;
|
3286
|
-
self.me = null;
|
3287
|
-
channelData = null;
|
3288
|
-
};
|
3289
|
-
reset();
|
3412
|
+
Pusher.Channel = Channel;
|
3413
|
+
}).call(this);
|
3290
3414
|
|
3291
|
-
|
3292
|
-
|
3293
|
-
|
3294
|
-
|
3295
|
-
|
3296
|
-
|
3415
|
+
;(function() {
|
3416
|
+
/** Extends public channels to provide private channel interface.
|
3417
|
+
*
|
3418
|
+
* @param {String} name
|
3419
|
+
* @param {Pusher} pusher
|
3420
|
+
*/
|
3421
|
+
function PrivateChannel(name, pusher) {
|
3422
|
+
Pusher.Channel.call(this, name, pusher);
|
3423
|
+
}
|
3424
|
+
var prototype = PrivateChannel.prototype;
|
3425
|
+
Pusher.Util.extend(prototype, Pusher.Channel.prototype);
|
3297
3426
|
|
3298
|
-
|
3299
|
-
|
3300
|
-
|
3301
|
-
|
3427
|
+
/** Authorizes the connection to use the channel.
|
3428
|
+
*
|
3429
|
+
* @param {String} socketId
|
3430
|
+
* @param {Function} callback
|
3431
|
+
*/
|
3432
|
+
prototype.authorize = function(socketId, callback) {
|
3433
|
+
var authorizer = new Pusher.Channel.Authorizer(this, this.pusher.config);
|
3434
|
+
return authorizer.authorize(socketId, callback);
|
3435
|
+
};
|
3302
3436
|
|
3303
|
-
|
3304
|
-
|
3305
|
-
self.count++;
|
3306
|
-
}
|
3437
|
+
Pusher.PrivateChannel = PrivateChannel;
|
3438
|
+
}).call(this);
|
3307
3439
|
|
3308
|
-
|
3309
|
-
|
3310
|
-
|
3440
|
+
;(function() {
|
3441
|
+
/** Adds presence channel functionality to private channels.
|
3442
|
+
*
|
3443
|
+
* @param {String} name
|
3444
|
+
* @param {Pusher} pusher
|
3445
|
+
*/
|
3446
|
+
function PresenceChannel(name, pusher) {
|
3447
|
+
Pusher.PrivateChannel.call(this, name, pusher);
|
3448
|
+
this.members = new Pusher.Members();
|
3449
|
+
}
|
3450
|
+
var prototype = PresenceChannel.prototype;
|
3451
|
+
Pusher.Util.extend(prototype, Pusher.PrivateChannel.prototype);
|
3311
3452
|
|
3312
|
-
|
3313
|
-
|
3314
|
-
|
3315
|
-
|
3316
|
-
|
3317
|
-
|
3453
|
+
/** Authenticates the connection as a member of the channel.
|
3454
|
+
*
|
3455
|
+
* @param {String} socketId
|
3456
|
+
* @param {Function} callback
|
3457
|
+
*/
|
3458
|
+
prototype.authorize = function(socketId, callback) {
|
3459
|
+
var _super = Pusher.PrivateChannel.prototype.authorize;
|
3460
|
+
var self = this;
|
3461
|
+
_super.call(self, socketId, function(error, authData) {
|
3462
|
+
if (!error) {
|
3463
|
+
if (authData.channel_data === undefined) {
|
3464
|
+
Pusher.warn(
|
3465
|
+
"Invalid auth response for channel '" +
|
3466
|
+
self.name +
|
3467
|
+
"', expected 'channel_data' field"
|
3468
|
+
);
|
3469
|
+
callback("Invalid auth response");
|
3470
|
+
return;
|
3471
|
+
}
|
3472
|
+
var channelData = JSON.parse(authData.channel_data);
|
3473
|
+
self.members.setMyID(channelData.user_id);
|
3318
3474
|
}
|
3475
|
+
callback(error, authData);
|
3319
3476
|
});
|
3477
|
+
};
|
3320
3478
|
|
3321
|
-
|
3322
|
-
|
3323
|
-
|
3324
|
-
|
3479
|
+
/** Handles presence and subscription events. For internal use only.
|
3480
|
+
*
|
3481
|
+
* @param {String} event
|
3482
|
+
* @param {*} data
|
3483
|
+
*/
|
3484
|
+
prototype.handleEvent = function(event, data) {
|
3485
|
+
switch (event) {
|
3486
|
+
case "pusher_internal:subscription_succeeded":
|
3487
|
+
this.members.onSubscription(data);
|
3488
|
+
this.subscribed = true;
|
3489
|
+
this.emit("pusher:subscription_succeeded", this.members);
|
3490
|
+
break;
|
3491
|
+
case "pusher_internal:member_added":
|
3492
|
+
var addedMember = this.members.addMember(data);
|
3493
|
+
this.emit('pusher:member_added', addedMember);
|
3494
|
+
break;
|
3495
|
+
case "pusher_internal:member_removed":
|
3496
|
+
var removedMember = this.members.removeMember(data);
|
3497
|
+
if (removedMember) {
|
3498
|
+
this.emit('pusher:member_removed', removedMember);
|
3499
|
+
}
|
3500
|
+
break;
|
3501
|
+
default:
|
3502
|
+
Pusher.PrivateChannel.prototype.handleEvent.call(this, event, data);
|
3503
|
+
}
|
3325
3504
|
};
|
3326
3505
|
|
3327
|
-
|
3328
|
-
|
3329
|
-
|
3330
|
-
|
3331
|
-
|
3332
|
-
},
|
3506
|
+
/** Resets the channel state, including members map. For internal use only. */
|
3507
|
+
prototype.disconnect = function() {
|
3508
|
+
this.members.reset();
|
3509
|
+
Pusher.PrivateChannel.prototype.disconnect.call(this);
|
3510
|
+
};
|
3333
3511
|
|
3334
|
-
|
3335
|
-
|
3336
|
-
|
3337
|
-
|
3338
|
-
|
3339
|
-
|
3340
|
-
|
3341
|
-
|
3342
|
-
|
3512
|
+
Pusher.PresenceChannel = PresenceChannel;
|
3513
|
+
}).call(this);
|
3514
|
+
|
3515
|
+
;(function() {
|
3516
|
+
/** Handles a channel map. */
|
3517
|
+
function Channels() {
|
3518
|
+
this.channels = {};
|
3519
|
+
}
|
3520
|
+
var prototype = Channels.prototype;
|
3521
|
+
|
3522
|
+
/** Creates or retrieves an existing channel by its name.
|
3523
|
+
*
|
3524
|
+
* @param {String} name
|
3525
|
+
* @param {Pusher} pusher
|
3526
|
+
* @return {Channel}
|
3527
|
+
*/
|
3528
|
+
prototype.add = function(name, pusher) {
|
3529
|
+
if (!this.channels[name]) {
|
3530
|
+
this.channels[name] = createChannel(name, pusher);
|
3343
3531
|
}
|
3532
|
+
return this.channels[name];
|
3344
3533
|
};
|
3345
3534
|
|
3346
|
-
|
3347
|
-
|
3348
|
-
|
3349
|
-
|
3350
|
-
|
3351
|
-
|
3352
|
-
|
3353
|
-
|
3354
|
-
|
3535
|
+
/** Finds a channel by its name.
|
3536
|
+
*
|
3537
|
+
* @param {String} name
|
3538
|
+
* @return {Channel} channel or null if it doesn't exist
|
3539
|
+
*/
|
3540
|
+
prototype.find = function(name) {
|
3541
|
+
return this.channels[name];
|
3542
|
+
};
|
3543
|
+
|
3544
|
+
/** Removes a channel from the map.
|
3545
|
+
*
|
3546
|
+
* @param {String} name
|
3547
|
+
*/
|
3548
|
+
prototype.remove = function(name) {
|
3549
|
+
var channel = this.channels[name];
|
3550
|
+
delete this.channels[name];
|
3355
3551
|
return channel;
|
3356
3552
|
};
|
3553
|
+
|
3554
|
+
/** Proxies disconnection signal to all channels. */
|
3555
|
+
prototype.disconnect = function() {
|
3556
|
+
Pusher.Util.objectApply(this.channels, function(channel) {
|
3557
|
+
channel.disconnect();
|
3558
|
+
});
|
3559
|
+
};
|
3560
|
+
|
3561
|
+
function createChannel(name, pusher) {
|
3562
|
+
if (name.indexOf('private-') === 0) {
|
3563
|
+
return new Pusher.PrivateChannel(name, pusher);
|
3564
|
+
} else if (name.indexOf('presence-') === 0) {
|
3565
|
+
return new Pusher.PresenceChannel(name, pusher);
|
3566
|
+
} else {
|
3567
|
+
return new Pusher.Channel(name, pusher);
|
3568
|
+
}
|
3569
|
+
}
|
3570
|
+
|
3571
|
+
Pusher.Channels = Channels;
|
3357
3572
|
}).call(this);
|
3358
3573
|
|
3359
3574
|
;(function() {
|
3360
|
-
Pusher.Channel.Authorizer = function(channel,
|
3575
|
+
Pusher.Channel.Authorizer = function(channel, options) {
|
3361
3576
|
this.channel = channel;
|
3362
|
-
this.type =
|
3577
|
+
this.type = options.authTransport;
|
3363
3578
|
|
3579
|
+
this.options = options;
|
3364
3580
|
this.authOptions = (options || {}).auth || {};
|
3365
3581
|
};
|
3366
3582
|
|
@@ -3394,7 +3610,7 @@
|
|
3394
3610
|
xhr = (window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
|
3395
3611
|
}
|
3396
3612
|
|
3397
|
-
xhr.open("POST",
|
3613
|
+
xhr.open("POST", self.options.authEndpoint, true);
|
3398
3614
|
|
3399
3615
|
// add request headers
|
3400
3616
|
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
@@ -3436,6 +3652,7 @@
|
|
3436
3652
|
var callbackName = nextAuthCallbackID.toString();
|
3437
3653
|
nextAuthCallbackID++;
|
3438
3654
|
|
3655
|
+
var document = Pusher.Util.getDocument();
|
3439
3656
|
var script = document.createElement("script");
|
3440
3657
|
// Hacked wrapper.
|
3441
3658
|
Pusher.auth_callbacks[callbackName] = function(data) {
|
@@ -3443,7 +3660,7 @@
|
|
3443
3660
|
};
|
3444
3661
|
|
3445
3662
|
var callback_name = "Pusher.auth_callbacks['" + callbackName + "']";
|
3446
|
-
script.src =
|
3663
|
+
script.src = this.options.authEndpoint +
|
3447
3664
|
'?callback=' +
|
3448
3665
|
encodeURIComponent(callback_name) +
|
3449
3666
|
this.composeQuery(socketId);
|