@@ -30,6 +30,16 @@ goog.require('goog.Promise');
30
30
goog . require ( 'goog.array' ) ;
31
31
32
32
33
+ /**
34
+ * This is the interface defining a MessageChannel/handler pair.
35
+ *
36
+ * @typedef {{
37
+ * onMessage: function(!Event),
38
+ * messageChannel: !MessageChannel
39
+ * }}
40
+ */
41
+ fireauth . messagechannel . MessageHandler ;
42
+
33
43
34
44
/**
35
45
* Helper static function to create messageChannel errors.
@@ -60,17 +70,11 @@ fireauth.messagechannel.Sender = function(postMessager) {
60
70
* PostMessager.
61
71
*/
62
72
this . postMessager_ = postMessager ;
73
+ /** @private {boolean} Whether the connection was closed. */
74
+ this . closed_ = false ;
63
75
/**
64
- * @private {?MessageChannel} The messageChannel reference if
65
- * supported.
66
- */
67
- this . messageChannel_ =
68
- fireauth . messagechannel . utils . initializeMessageChannel ( ) ;
69
- /** @private {boolean} Whether the connection was started. */
70
- this . started_ = false ;
71
- /**
72
- * @const @private {!Array<function(!Event)>} The list of subscribed message
73
- * handlers.
76
+ * @const @private {!Array<!fireauth.messagechannel.MessageHandler>} The list
77
+ * of subscribed message handlers and their corresponding MessageChannels.
74
78
*/
75
79
this . messageHandlers_ = [ ] ;
76
80
} ;
@@ -94,24 +98,38 @@ fireauth.messagechannel.Sender = function(postMessager) {
94
98
* @param {string } eventType The event type identifying the message. This is
95
99
* used to help the receiver handle this message.
96
100
* @param {?Object= } opt_data The optional data to send along the message.
101
+ * @param {?boolean= } opt_useLongTimeout Whether long timeout should be used
102
+ * for ACK responses.
97
103
* @return {!goog.Promise<!Array<{fulfilled: boolean,
98
104
* value: (*|undefined),
99
105
* reason: (*|undefined)}>>} A promise that
100
106
* resolves with the receiver responses.
101
107
*/
102
- fireauth . messagechannel . Sender . prototype . send = function ( eventType , opt_data ) {
108
+ fireauth . messagechannel . Sender . prototype . send = function (
109
+ eventType , opt_data , opt_useLongTimeout ) {
103
110
var self = this ;
104
111
var eventId ;
105
112
var data = opt_data || { } ;
106
113
var onMessage ;
107
114
var ackTimer ;
108
115
var completionTimer ;
116
+ var entry = null ;
117
+ if ( this . closed_ ) {
118
+ return goog . Promise . reject ( fireauth . messagechannel . createError_ (
119
+ fireauth . messagechannel . Error . CONNECTION_UNAVAILABLE ) ) ;
120
+ }
121
+ var ackTimeout =
122
+ ! ! opt_useLongTimeout ?
123
+ fireauth . messagechannel . TimeoutDuration . LONG_ACK :
124
+ fireauth . messagechannel . TimeoutDuration . ACK ;
125
+ var messageChannel =
126
+ fireauth . messagechannel . utils . initializeMessageChannel ( ) ;
109
127
return new goog . Promise ( function ( resolve , reject ) {
110
128
// Send message along with port for reply
111
- if ( self . messageChannel_ ) {
129
+ if ( messageChannel ) {
112
130
eventId = fireauth . messagechannel . utils . generateEventId ( ) ;
113
131
// Start the connection if not already started.
114
- self . start ( ) ;
132
+ messageChannel . port1 . start ( ) ;
115
133
// Handler for receiving message reply from receiver.
116
134
// Blocks promise resolution until service worker detects the change.
117
135
ackTimer = setTimeout ( function ( ) {
@@ -121,7 +139,7 @@ fireauth.messagechannel.Sender.prototype.send = function(eventType, opt_data) {
121
139
// Timeout after some time.
122
140
reject ( fireauth . messagechannel . createError_ (
123
141
fireauth . messagechannel . Error . UNSUPPORTED_EVENT ) ) ;
124
- } , fireauth . messagechannel . TimeoutDuration . ACK ) ;
142
+ } , ackTimeout ) ;
125
143
onMessage = function ( event ) {
126
144
// Process only the expected events that match current event ID.
127
145
if ( event . data [ 'eventId' ] !== eventId ) {
@@ -153,8 +171,12 @@ fireauth.messagechannel.Sender.prototype.send = function(eventType, opt_data) {
153
171
fireauth . messagechannel . Error . INVALID_RESPONSE ) ) ;
154
172
}
155
173
} ;
156
- self . messageHandlers_ . push ( onMessage ) ;
157
- self . messageChannel_ . port1 . addEventListener ( 'message' , onMessage ) ;
174
+ entry = {
175
+ 'messageChannel' : messageChannel ,
176
+ 'onMessage' : onMessage
177
+ } ;
178
+ self . messageHandlers_ . push ( entry ) ;
179
+ messageChannel . port1 . addEventListener ( 'message' , onMessage ) ;
158
180
var request = {
159
181
'eventType' : eventType ,
160
182
'eventId' : eventId ,
@@ -165,7 +187,7 @@ fireauth.messagechannel.Sender.prototype.send = function(eventType, opt_data) {
165
187
// receiver or using an outdated version.
166
188
self . postMessager_ . postMessage (
167
189
request ,
168
- [ self . messageChannel_ . port2 ] ) ;
190
+ [ messageChannel . port2 ] ) ;
169
191
} else {
170
192
// No connection available.
171
193
reject ( fireauth . messagechannel . createError_ (
@@ -174,64 +196,45 @@ fireauth.messagechannel.Sender.prototype.send = function(eventType, opt_data) {
174
196
} ) . then ( function ( result ) {
175
197
// On completion, remove the message handler. A new one is needed for a
176
198
// new message.
177
- self . removeMessageHandler_ ( onMessage ) ;
199
+ self . removeMessageHandler_ ( entry ) ;
178
200
return result ;
179
201
} ) . thenCatch ( function ( error ) {
180
202
// On failure, remove the message handler. A new one is needed for a new
181
203
// message.
182
- self . removeMessageHandler_ ( onMessage ) ;
204
+ self . removeMessageHandler_ ( entry ) ;
183
205
throw error ;
184
206
} ) ;
185
207
} ;
186
208
187
209
188
210
/**
189
- * @param {function(!Event) } onMessage The message handler to remove.
211
+ * Removes the onMessage handler for the specified messageChannel.
212
+ * @param {?fireauth.messagechannel.MessageHandler } messageHandler
190
213
* @private
191
214
*/
192
215
fireauth . messagechannel . Sender . prototype . removeMessageHandler_ =
193
- function ( onMessage ) {
194
- if ( this . messageChannel_ ) {
195
- goog . array . removeAllIf ( this . messageHandlers_ , function ( ele ) {
196
- return ele == onMessage ;
197
- } ) ;
198
- this . messageChannel_ . port1 . removeEventListener ( 'message' , onMessage ) ;
216
+ function ( messageHandler ) {
217
+ if ( ! messageHandler ) {
218
+ return ;
199
219
}
200
- } ;
201
-
202
-
203
- /**
204
- * Removing all subscribed message handlers.
205
- * @private
206
- */
207
- fireauth . messagechannel . Sender . prototype . removeAllMessageHandlers_ =
208
- function ( ) {
209
- while ( this . messageHandlers_ . length > 0 ) {
210
- var onMessage = this . messageHandlers_ . pop ( ) ;
211
- this . messageChannel_ . port1 . removeEventListener ( 'message' , onMessage ) ;
220
+ var messageChannel = messageHandler [ 'messageChannel' ] ;
221
+ var onMessage = messageHandler [ 'onMessage' ] ;
222
+ if ( messageChannel ) {
223
+ messageChannel . port1 . removeEventListener ( 'message' , onMessage ) ;
224
+ messageChannel . port1 . close ( ) ;
212
225
}
226
+ goog . array . removeAllIf ( this . messageHandlers_ , function ( ele ) {
227
+ return ele == messageHandler ;
228
+ } ) ;
213
229
} ;
214
230
215
231
216
232
/** Closes the underlying MessageChannel connection. */
217
233
fireauth . messagechannel . Sender . prototype . close = function ( ) {
218
- if ( this . messageChannel_ ) {
219
- // Any pending event will timeout.
220
- this . removeAllMessageHandlers_ ( ) ;
221
- // No new messages will be returned.
222
- this . messageChannel_ . port1 . close ( ) ;
223
- this . messageChannel_ = null ;
224
- this . started_ = false ;
234
+ // Any pending event will timeout.
235
+ while ( this . messageHandlers_ . length > 0 ) {
236
+ this . removeMessageHandler_ ( this . messageHandlers_ [ 0 ] ) ;
225
237
}
238
+ this . closed_ = true ;
226
239
} ;
227
240
228
-
229
- /** Starts the underlying MessageChannel connection if not already started. */
230
- fireauth . messagechannel . Sender . prototype . start = function ( ) {
231
- // Note that re-connection is not supported. If a connection is closed, a new
232
- // sender has to be created.
233
- if ( this . messageChannel_ && ! this . started_ ) {
234
- this . messageChannel_ . port1 . start ( ) ;
235
- this . started_ = true ;
236
- }
237
- } ;
0 commit comments