dom/wifi/WifiP2pWorkerObserver.jsm

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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/. */
     7 "use strict";
     9 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
    11 const CONNECTION_STATUS_DISCONNECTED  = "disconnected";
    12 const CONNECTION_STATUS_CONNECTING    = "connecting";
    13 const CONNECTION_STATUS_CONNECTED     = "connected";
    14 const CONNECTION_STATUS_DISCONNECTING = "disconnecting";
    16 const DEBUG = false;
    18 this.EXPORTED_SYMBOLS = ["WifiP2pWorkerObserver"];
    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   }
    38   // Private member variables.
    39   let _localDevice;
    40   let _peerList = {}; // List of P2pDevice.
    41   let _domManagers = [];
    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;
    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   }
    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;
    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   }
    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   }
   108   function addDomManager(aMsg) {
   109     if (-1 === _domManagers.indexOf(aMsg.manager)) {
   110       _domManagers.push(aMsg.manager);
   111     }
   112   }
   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   }
   120   function handlePeerListUpdated() {
   121     fireEvent("onpeerinfoupdate", {});
   122   }
   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     },
   131     onEnabled: function() {
   132       _peerList = [];
   133       fireEvent("p2pUp", {});
   134     },
   136     onDisbaled: function() {
   137       fireEvent("p2pDown", {});
   138     },
   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     },
   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     },
   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;
   170       fireEvent('onconnecting', { peer: peer });
   171     },
   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);
   185       fireEvent('onconnected', { groupOwner: go, peer: peer });
   186     },
   188     onDisconnected: function(aPeer) {
   189       let peer = _peerList[aPeer.address];
   190       if (!peer) {
   191         debug('Unknown peer disconnected: ' + aPeer.address);
   192         return;
   193       }
   195       peer.connectionStatus = CONNECTION_STATUS_DISCONNECTED;
   196       fireEvent('ondisconnected', { peer: peer });
   197     },
   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     },
   211     onDOMMessage: function(aMessage) {
   212       let msg = aMessage.data || {};
   213       msg.manager = aMessage.target;
   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       }
   223       if (!aMessage.target.assertPermission("wifi-manage")) {
   224         return;
   225       }
   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.
   232         case "WifiP2pManager:setScanEnabled":
   233           {
   234             let enabled = msg.data;
   236             aDomMsgResponder.setScanEnabled(enabled, function(success) {
   237               returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
   238             });
   239           }
   240           break;
   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             }
   252             returnMessage(aMessage.name, true, peerArray, msg);
   253           }
   254           break;
   256         case "WifiP2pManager:connect":
   257           {
   258             let peer = msg.data;
   260             let onDoConnect = function(success) {
   261               returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
   262             };
   264             aDomMsgResponder.connect(peer.address, peer.wpsMethod,
   265                                      peer.goIntent, onDoConnect);
   266           }
   267           break;
   269         case "WifiP2pManager:disconnect":
   270           {
   271             let address = msg.data;
   273             aDomMsgResponder.disconnect(address, function(success) {
   274               returnMessage(aMessage.name, success, (success ? true : "ERROR"), msg);
   275             });
   276           }
   277           break;
   279         case "WifiP2pManager:setPairingConfirmation":
   280           {
   281             let result = msg.data;
   282             aDomMsgResponder.setPairingConfirmation(result);
   283             returnMessage(aMessage.name, true, true, msg);
   284           }
   285           break;
   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;
   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