OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 define("mojo/public/js/lib/interface_endpoint_client", [ | |
6 "console", | |
7 "mojo/public/js/codec", | |
8 "mojo/public/js/lib/control_message_handler", | |
9 "mojo/public/js/lib/control_message_proxy", | |
10 "mojo/public/js/lib/interface_endpoint_handle", | |
11 "mojo/public/js/validator", | |
12 "timer", | |
13 ], function(console, | |
14 codec, | |
15 controlMessageHandler, | |
16 controlMessageProxy, | |
17 interfaceEndpointHandle, | |
18 validator, | |
19 timer) { | |
20 | |
21 var ControlMessageHandler = controlMessageHandler.ControlMessageHandler; | |
22 var ControlMessageProxy = controlMessageProxy.ControlMessageProxy; | |
23 var MessageReader = codec.MessageReader; | |
24 var Validator = validator.Validator; | |
25 var InterfaceEndpointHandle = interfaceEndpointHandle.InterfaceEndpointHandle; | |
26 | |
27 function InterfaceEndpointClient(interfaceEndpointHandle, receiver, | |
28 interfaceVersion) { | |
29 this.controller_ = null; | |
30 this.encounteredError_ = false; | |
31 this.handle_ = interfaceEndpointHandle; | |
32 this.incomingReceiver_ = receiver; | |
33 | |
34 if (interfaceVersion !== undefined) { | |
35 this.controlMessageHandler_ = new ControlMessageHandler( | |
36 interfaceVersion); | |
37 } else { | |
38 this.controlMessageProxy_ = new ControlMessageProxy(this); | |
39 } | |
40 | |
41 this.nextRequestID_ = 0; | |
42 this.completers_ = new Map(); | |
43 this.payloadValidators_ = []; | |
44 this.connectionErrorHandler_ = null; | |
45 | |
46 if (interfaceEndpointHandle.pendingAssociation()) { | |
47 interfaceEndpointHandle.setAssociationEventHandler( | |
48 this.onAssociationEvent.bind(this)); | |
49 } else { | |
50 this.initControllerIfNecessary_(); | |
51 } | |
52 } | |
53 | |
54 InterfaceEndpointClient.prototype.initControllerIfNecessary_ = function() { | |
55 if (this.controller_ || this.handle_.pendingAssociation()) { | |
56 return; | |
57 } | |
58 | |
59 this.controller_ = this.handle_.groupController().attachEndpointClient( | |
60 this.handle_, this); | |
61 }; | |
62 | |
63 InterfaceEndpointClient.prototype.onAssociationEvent = function( | |
64 associationEvent) { | |
65 if (associationEvent === | |
66 InterfaceEndpointHandle.AssociationEvent.ASSOCIATED) { | |
67 this.initControllerIfNecessary_(); | |
68 } else if (associationEvent === | |
69 InterfaceEndpointHandle.AssociationEvent | |
70 .PEER_CLOSED_BEFORE_ASSOCIATION) { | |
71 timer.createOneShot(0, this.notifyError.bind(this, | |
72 this.handle_.disconnectReason())); | |
73 } | |
74 }; | |
75 | |
76 InterfaceEndpointClient.prototype.passHandle = function() { | |
77 if (!this.handle_.isValid()) { | |
78 return new InterfaceEndpointHandle(); | |
79 } | |
80 | |
81 // Used to clear the previously set callback. | |
82 this.handle_.setAssociationEventHandler(undefined); | |
83 | |
84 if (this.controller_) { | |
85 this.controller_ = null; | |
86 this.handle_.groupController().detachEndpointClient(this.handle_); | |
87 } | |
88 var handle = this.handle_; | |
89 this.handle_ = null; | |
90 return handle; | |
91 }; | |
92 | |
93 InterfaceEndpointClient.prototype.closeWithReason = function(reason) { | |
94 var handle = this.passHandle(); | |
95 handle.reset(reason); | |
96 }; | |
97 | |
98 InterfaceEndpointClient.prototype.accept = function(message) { | |
99 if (this.encounteredError_) { | |
100 return false; | |
101 } | |
102 | |
103 this.initControllerIfNecessary_(); | |
104 return this.controller_.sendMessage(message); | |
105 }; | |
106 | |
107 InterfaceEndpointClient.prototype.acceptAndExpectResponse = function( | |
108 message){ | |
yzshen1
2017/03/28 00:46:00
nit: one space between ) and {
wangjimmy
2017/03/29 17:01:18
Done.
| |
109 if (this.encounteredError_) { | |
110 return Promise.reject(); | |
111 } | |
112 | |
113 this.initControllerIfNecessary_(); | |
114 | |
115 // Reserve 0 in case we want it to convey special meaning in the future. | |
116 var requestID = this.nextRequestID_++; | |
117 if (requestID === 0) | |
118 requestID = this.nextRequestID_++; | |
119 | |
120 message.setRequestID(requestID); | |
121 var result = this.controller_.sendMessage(message); | |
122 if (!result) | |
123 return Promise.reject(Error("Connection error")); | |
124 | |
125 var completer = {}; | |
126 this.completers_.set(requestID, completer); | |
127 return new Promise(function(resolve, reject) { | |
128 completer.resolve = resolve; | |
129 completer.reject = reject; | |
130 }); | |
131 }; | |
132 | |
133 InterfaceEndpointClient.prototype.setPayloadValidators = function( | |
134 payloadValidators) { | |
135 this.payloadValidators_ = payloadValidators; | |
136 }; | |
137 | |
138 InterfaceEndpointClient.prototype.setIncomingReceiver = function(receiver) { | |
139 this.incomingReceiver_ = receiver; | |
140 }; | |
141 | |
142 InterfaceEndpointClient.prototype.setConnectionErrorHandler = function( | |
143 handler) { | |
144 this.connectionErrorHandler_ = handler; | |
145 }; | |
146 | |
147 InterfaceEndpointClient.prototype.handleIncomingMessage_ = function( | |
148 message) { | |
149 var noError = validator.validationError.NONE; | |
150 var messageValidator = new Validator(message); | |
151 var err = noError; | |
152 for (var i = 0; err === noError && i < this.payloadValidators_.length; ++i) | |
153 err = this.payloadValidators_[i](messageValidator); | |
154 | |
155 if (err == noError) { | |
156 return this.handleValidIncomingMessage_(message); | |
157 } else { | |
158 validator.reportValidationError(err); | |
159 return false; | |
160 } | |
161 }; | |
162 | |
163 InterfaceEndpointClient.prototype.handleValidIncomingMessage_ = function( | |
164 message) { | |
165 if (validator.isTestingMode()) { | |
166 return true; | |
167 } | |
168 | |
169 if (this.encounteredError_) { | |
170 return false; | |
171 } | |
172 | |
173 var ok = false; | |
174 | |
175 if (message.expectsResponse()) { | |
176 if (controlMessageHandler.isControlMessage(message) && | |
177 this.controlMessageHandler_) { | |
178 ok = this.controlMessageHandler_.acceptWithResponder(message, this); | |
179 } else if (this.incomingReceiver_) { | |
180 ok = this.incomingReceiver_.acceptWithResponder(message, this); | |
181 } | |
182 } else if (message.isResponse()) { | |
183 var reader = new MessageReader(message); | |
184 var requestID = reader.requestID; | |
185 var completer = this.completers_.get(requestID); | |
186 if (completer) { | |
187 this.completers_.delete(requestID); | |
188 completer.resolve(message); | |
189 ok = true; | |
190 } else { | |
191 console.log("Unexpected response with request ID: " + requestID); | |
192 } | |
193 } else { | |
194 if (controlMessageHandler.isControlMessage(message) && | |
195 this.controlMessageHandler_) { | |
yzshen1
2017/03/28 00:46:00
The indent is still incorrect.
wangjimmy
2017/03/29 17:01:18
Done.
| |
196 ok = this.controlMessageHandler_.accept(message); | |
197 } else if (this.incomingReceiver_) { | |
198 ok = this.incomingReceiver_.accept(message); | |
199 } | |
200 } | |
201 return ok; | |
202 }; | |
203 | |
204 InterfaceEndpointClient.prototype.notifyError = function(reason) { | |
205 if (this.encounteredError_) { | |
206 return; | |
207 } | |
208 this.encounteredError_ = true; | |
209 | |
210 this.completers_.forEach(function(value) { | |
211 value.reject(); | |
212 }); | |
213 this.completers_.clear(); // Drop any responders. | |
214 | |
215 if (this.connectionErrorHandler_) { | |
216 this.connectionErrorHandler_(reason); | |
217 } | |
218 }; | |
219 | |
220 InterfaceEndpointClient.prototype.queryVersion = function() { | |
221 return this.controlMessageProxy_.queryVersion(); | |
222 }; | |
223 | |
224 InterfaceEndpointClient.prototype.requireVersion = function(version) { | |
225 this.controlMessageProxy_.requireVersion(version); | |
226 }; | |
227 | |
228 var exports = {}; | |
229 exports.InterfaceEndpointClient = InterfaceEndpointClient; | |
230 | |
231 return exports; | |
232 }); | |
OLD | NEW |