dom/wifi/WifiP2pWorkerObserver.jsm

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:903a3985b227
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 "use strict";
8
9 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
10
11 const CONNECTION_STATUS_DISCONNECTED = "disconnected";
12 const CONNECTION_STATUS_CONNECTING = "connecting";
13 const CONNECTION_STATUS_CONNECTED = "connected";
14 const CONNECTION_STATUS_DISCONNECTING = "disconnecting";
15
16 const DEBUG = false;
17
18 this.EXPORTED_SYMBOLS = ["WifiP2pWorkerObserver"];
19
20 // WifiP2pWorkerObserver resides in WifiWorker to handle DOM message
21 // by either 1) returning internally maintained information or
22 // 2) delegating to aDomMsgResponder. It is also responsible
23 // for observing events from WifiP2pManager and dispatch to DOM.
24 //
25 // @param aDomMsgResponder handles DOM messages, including
26 // - setScanEnabled
27 // - connect
28 // - disconnect
29 // - setPairingConfirmation
30 // The instance is actually WifiP2pManager.
31 this.WifiP2pWorkerObserver = function(aDomMsgResponder) {
32 function debug(aMsg) {
33 if (DEBUG) {
34 dump('-------------- WifiP2pWorkerObserver: ' + aMsg);
35 }
36 }
37
38 // Private member variables.
39 let _localDevice;
40 let _peerList = {}; // List of P2pDevice.
41 let _domManagers = [];
42
43 // Constructor of P2pDevice. It will be exposed to DOM.
44 //
45 // @param aPeer object representing a P2P device:
46 // .name: string for the device name.
47 // .address: Mac address.
48 // .isGroupOwner: boolean to indicate if this device is the group owner.
49 // .wpsCapabilities: array of string of {"pbc", "display", "keypad"}.
50 function P2pDevice(aPeer) {
51 this.address = aPeer.address;
52 this.name = (aPeer.name ? aPeer.name : aPeer.address);
53 this.isGroupOwner = aPeer.isGroupOwner;
54 this.wpsCapabilities = aPeer.wpsCapabilities;
55 this.connectionStatus = CONNECTION_STATUS_DISCONNECTED;
56
57 // Since this object will be exposed to web, defined the exposed
58 // properties here.
59 this.__exposedProps__ = {
60 address: "r",
61 name: "r",
62 isGroupOwner: "r",
63 wpsCapabilities: "r",
64 connectionStatus: "r"
65 };
66 }
67
68 // Constructor of P2pGroupOwner.
69 //
70 // @param aGroupOwner:
71 // .macAddress
72 // .ipAddress
73 // .passphrase
74 // .ssid
75 // .freq
76 // .isLocal
77 function P2pGroupOwner(aGroupOwner) {
78 this.macAddress = aGroupOwner.macAddress; // The identifier to get further information.
79 this.ipAddress = aGroupOwner.ipAddress;
80 this.passphrase = aGroupOwner.passphrase;
81 this.ssid = aGroupOwner.ssid; // e.g. DIRECT-xy.
82 this.freq = aGroupOwner.freq;
83 this.isLocal = aGroupOwner.isLocal;
84
85 let detail = _peerList[aGroupOwner.macAddress];
86 if (detail) {
87 this.name = detail.name;
88 this.wpsCapabilities = detail.wpsCapabilities;
89 } else if (_localDevice.address === this.macAddress) {
90 this.name = _localDevice.name;
91 this.wpsCapabilities = _localDevice.wpsCapabilities;
92 } else {
93 debug("We don't know this group owner: " + aGroupOwner.macAddress);
94 this.name = aGroupOwner.macAddress;
95 this.wpsCapabilities = [];
96 }
97 }
98
99 function fireEvent(aMessage, aData) {
100 debug('domManager: ' + JSON.stringify(_domManagers));
101 _domManagers.forEach(function(manager) {
102 // Note: We should never have a dead message manager here because we
103 // observe our child message managers shutting down below.
104 manager.sendAsyncMessage("WifiP2pManager:" + aMessage, aData);
105 });
106 }
107
108 function addDomManager(aMsg) {
109 if (-1 === _domManagers.indexOf(aMsg.manager)) {
110 _domManagers.push(aMsg.manager);
111 }
112 }
113
114 function returnMessage(aMessage, aSuccess, aData, aMsg) {
115 let rMsg = aMessage + ":Return:" + (aSuccess ? "OK" : "NO");
116 aMsg.manager.sendAsyncMessage(rMsg,
117 { data: aData, rid: aMsg.rid, mid: aMsg.mid });
118 }
119
120 function handlePeerListUpdated() {
121 fireEvent("onpeerinfoupdate", {});
122 }
123
124 // Return a literal object as the constructed object.
125 return {
126 onLocalDeviceChanged: function(aDevice) {
127 _localDevice = aDevice;
128 debug('Local device updated to: ' + JSON.stringify(_localDevice));
129 },
130
131 onEnabled: function() {
132 _peerList = [];
133 fireEvent("p2pUp", {});
134 },
135
136 onDisbaled: function() {
137 fireEvent("p2pDown", {});
138 },
139
140 onPeerFound: function(aPeer) {
141 let newFoundPeer = new P2pDevice(aPeer);
142 let origianlPeer = _peerList[aPeer.address];
143 _peerList[aPeer.address] = newFoundPeer;
144 if (origianlPeer) {
145 newFoundPeer.connectionStatus = origianlPeer.connectionStatus;
146 }
147 handlePeerListUpdated();
148 },
149
150 onPeerLost: function(aPeer) {
151 let lostPeer = _peerList[aPeer.address];
152 if (!lostPeer) {
153 debug('Unknown peer lost: ' + aPeer.address);
154 return;
155 }
156 delete _peerList[aPeer.address];
157 handlePeerListUpdated();
158 },
159
160 onConnecting: function(aPeer) {
161 let peer = _peerList[aPeer.address];
162 if (!peer) {
163 debug('Unknown peer connecting: ' + aPeer.address);
164 peer = new P2pDevice(aPeer);
165 _peerList[aPeer.address] = peer;
166 handlePeerListUpdated();
167 }
168 peer.connectionStatus = CONNECTION_STATUS_CONNECTING;
169
170 fireEvent('onconnecting', { peer: peer });
171 },
172
173 onConnected: function(aGroupOwner, aPeer) {
174 let go = new P2pGroupOwner(aGroupOwner);
175 let peer = _peerList[aPeer.address];
176 if (!peer) {
177 debug('Unknown peer connected: ' + aPeer.address);
178 peer = new P2pDevice(aPeer);
179 _peerList[aPeer.address] = peer;
180 handlePeerListUpdated();
181 }
182 peer.connectionStatus = CONNECTION_STATUS_CONNECTED;
183 peer.isGroupOwner = (aPeer.address === aGroupOwner.address);
184
185 fireEvent('onconnected', { groupOwner: go, peer: peer });
186 },
187
188 onDisconnected: function(aPeer) {
189 let peer = _peerList[aPeer.address];
190 if (!peer) {
191 debug('Unknown peer disconnected: ' + aPeer.address);
192 return;
193 }
194
195 peer.connectionStatus = CONNECTION_STATUS_DISCONNECTED;
196 fireEvent('ondisconnected', { peer: peer });
197 },
198
199 getObservedDOMMessages: function() {
200 return [
201 "WifiP2pManager:getState",
202 "WifiP2pManager:getPeerList",
203 "WifiP2pManager:setScanEnabled",
204 "WifiP2pManager:connect",
205 "WifiP2pManager:disconnect",
206 "WifiP2pManager:setPairingConfirmation",
207 "WifiP2pManager:setDeviceName"
208 ];
209 },
210
211 onDOMMessage: function(aMessage) {
212 let msg = aMessage.data || {};
213 msg.manager = aMessage.target;
214
215 if ("child-process-shutdown" === aMessage.name) {
216 let i;
217 if (-1 !== (i = _domManagers.indexOf(msg.manager))) {
218 _domManagers.splice(i, 1);
219 }
220 return;
221 }
222
223 if (!aMessage.target.assertPermission("wifi-manage")) {
224 return;
225 }
226
227 switch (aMessage.name) {
228 case "WifiP2pManager:getState": // A new DOM manager is created.
229 addDomManager(msg);
230 return { peerList: _peerList, }; // Synchronous call. Simply return it.
231
232 case "WifiP2pManager:setScanEnabled":
233 {
234 let enabled = msg.data;
235
236 aDomMsgResponder.setScanEnabled(enabled, function(success) {
237 returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
238 });
239 }
240 break;
241
242 case "WifiP2pManager:getPeerList":
243 {
244 // Convert the object to an array.
245 let peerArray = [];
246 for (let key in _peerList) {
247 if (_peerList.hasOwnProperty(key)) {
248 peerArray.push(_peerList[key]);
249 }
250 }
251
252 returnMessage(aMessage.name, true, peerArray, msg);
253 }
254 break;
255
256 case "WifiP2pManager:connect":
257 {
258 let peer = msg.data;
259
260 let onDoConnect = function(success) {
261 returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
262 };
263
264 aDomMsgResponder.connect(peer.address, peer.wpsMethod,
265 peer.goIntent, onDoConnect);
266 }
267 break;
268
269 case "WifiP2pManager:disconnect":
270 {
271 let address = msg.data;
272
273 aDomMsgResponder.disconnect(address, function(success) {
274 returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
275 });
276 }
277 break;
278
279 case "WifiP2pManager:setPairingConfirmation":
280 {
281 let result = msg.data;
282 aDomMsgResponder.setPairingConfirmation(result);
283 returnMessage(aMessage.name, true, true, msg);
284 }
285 break;
286
287 case "WifiP2pManager:setDeviceName":
288 {
289 let newDeviceName = msg.data;
290 aDomMsgResponder.setDeviceName(newDeviceName, function(success) {
291 returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
292 });
293 }
294 break;
295
296 default:
297 if (0 === aMessage.name.indexOf("WifiP2pManager:")) {
298 debug("DOM WifiP2pManager message not handled: " + aMessage.name);
299 }
300 } // End of switch.
301 }
302 };
303 };

mercurial