pusher-fake 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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);
|