Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/messaging/portoperator.js
2868 views
1
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview The central node of a {@link goog.messaging.PortNetwork}. The
17
* operator is responsible for providing the two-way communication channels (via
18
* {@link MessageChannel}s) between each pair of nodes in the network that need
19
* to communicate with one another. Each network should have one and only one
20
* operator.
21
*
22
*/
23
24
goog.provide('goog.messaging.PortOperator');
25
26
goog.require('goog.Disposable');
27
goog.require('goog.asserts');
28
goog.require('goog.log');
29
goog.require('goog.messaging.PortChannel');
30
goog.require('goog.messaging.PortNetwork'); // interface
31
goog.require('goog.object');
32
33
34
35
/**
36
* The central node of a PortNetwork.
37
*
38
* @param {string} name The name of this node.
39
* @constructor
40
* @extends {goog.Disposable}
41
* @implements {goog.messaging.PortNetwork}
42
* @final
43
*/
44
goog.messaging.PortOperator = function(name) {
45
goog.messaging.PortOperator.base(this, 'constructor');
46
47
/**
48
* The collection of channels for communicating with other contexts in the
49
* network. These are the channels that are returned to the user, as opposed
50
* to the channels used for internal network communication. This is lazily
51
* populated as the user requests communication with other contexts, or other
52
* contexts request communication with the operator.
53
*
54
* @type {!Object<!goog.messaging.PortChannel>}
55
* @private
56
*/
57
this.connections_ = {};
58
59
/**
60
* The collection of channels for internal network communication with other
61
* contexts. This is not lazily populated, and always contains entries for
62
* each member of the network.
63
*
64
* @type {!Object<!goog.messaging.MessageChannel>}
65
* @private
66
*/
67
this.switchboard_ = {};
68
69
/**
70
* The name of the operator context.
71
*
72
* @type {string}
73
* @private
74
*/
75
this.name_ = name;
76
};
77
goog.inherits(goog.messaging.PortOperator, goog.Disposable);
78
79
80
/**
81
* The logger for PortOperator.
82
* @type {goog.log.Logger}
83
* @private
84
*/
85
goog.messaging.PortOperator.prototype.logger_ =
86
goog.log.getLogger('goog.messaging.PortOperator');
87
88
89
/** @override */
90
goog.messaging.PortOperator.prototype.dial = function(name) {
91
this.connectSelfToPort_(name);
92
return this.connections_[name];
93
};
94
95
96
/**
97
* Adds a caller to the network with the given name. This port should have no
98
* services registered on it. It will be disposed along with the PortOperator.
99
*
100
* @param {string} name The name of the port to add.
101
* @param {!goog.messaging.MessageChannel} port The port to add. Must be either
102
* a {@link goog.messaging.PortChannel} or a decorator wrapping a
103
* PortChannel; in particular, it must be able to send and receive
104
* {@link MessagePort}s.
105
*/
106
goog.messaging.PortOperator.prototype.addPort = function(name, port) {
107
this.switchboard_[name] = port;
108
port.registerService(
109
goog.messaging.PortNetwork.REQUEST_CONNECTION_SERVICE,
110
goog.bind(this.requestConnection_, this, name));
111
};
112
113
114
/**
115
* Connects two contexts by creating a {@link MessageChannel} and sending one
116
* end to one context and the other end to the other. Called when we receive a
117
* request from a caller to connect it to another context (including potentially
118
* the operator).
119
*
120
* @param {string} sourceName The name of the context requesting the connection.
121
* @param {!Object|string} message The name of the context to which
122
* the connection is requested.
123
* @private
124
*/
125
goog.messaging.PortOperator.prototype.requestConnection_ = function(
126
sourceName, message) {
127
var requestedName = /** @type {string} */ (message);
128
if (requestedName == this.name_) {
129
this.connectSelfToPort_(sourceName);
130
return;
131
}
132
133
var sourceChannel = this.switchboard_[sourceName];
134
var requestedChannel = this.switchboard_[requestedName];
135
136
goog.asserts.assert(goog.isDefAndNotNull(sourceChannel));
137
if (!requestedChannel) {
138
var err = 'Port "' + sourceName + '" requested a connection to port "' +
139
requestedName + '", which doesn\'t exist';
140
goog.log.warning(this.logger_, err);
141
sourceChannel.send(
142
goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE,
143
{'success': false, 'message': err});
144
return;
145
}
146
147
var messageChannel = new MessageChannel();
148
sourceChannel.send(
149
goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE,
150
{'success': true, 'name': requestedName, 'port': messageChannel.port1});
151
requestedChannel.send(
152
goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE,
153
{'success': true, 'name': sourceName, 'port': messageChannel.port2});
154
};
155
156
157
/**
158
* Connects together the operator and a caller by creating a
159
* {@link MessageChannel} and sending one end to the remote context.
160
*
161
* @param {string} contextName The name of the context to which to connect the
162
* operator.
163
* @private
164
*/
165
goog.messaging.PortOperator.prototype.connectSelfToPort_ = function(
166
contextName) {
167
if (contextName in this.connections_) {
168
// We've already established a connection with this port.
169
return;
170
}
171
172
var contextChannel = this.switchboard_[contextName];
173
if (!contextChannel) {
174
throw Error('Port "' + contextName + '" doesn\'t exist');
175
}
176
177
var messageChannel = new MessageChannel();
178
contextChannel.send(
179
goog.messaging.PortNetwork.GRANT_CONNECTION_SERVICE,
180
{'success': true, 'name': this.name_, 'port': messageChannel.port1});
181
messageChannel.port2.start();
182
this.connections_[contextName] =
183
new goog.messaging.PortChannel(messageChannel.port2);
184
};
185
186
187
/** @override */
188
goog.messaging.PortOperator.prototype.disposeInternal = function() {
189
goog.object.forEach(this.switchboard_, goog.dispose);
190
goog.object.forEach(this.connections_, goog.dispose);
191
delete this.switchboard_;
192
delete this.connections_;
193
goog.messaging.PortOperator.base(this, 'disposeInternal');
194
};
195
196