dom/system/gonk/NetworkService.js

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

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 "use strict";
michael@0 6
michael@0 7 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
michael@0 8
michael@0 9 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 10 Cu.import("resource://gre/modules/Services.jsm");
michael@0 11 Cu.import("resource://gre/modules/NetUtil.jsm");
michael@0 12 Cu.import("resource://gre/modules/FileUtils.jsm");
michael@0 13
michael@0 14 const NETWORKSERVICE_CONTRACTID = "@mozilla.org/network/service;1";
michael@0 15 const NETWORKSERVICE_CID = Components.ID("{baec696c-c78d-42db-8b44-603f8fbfafb4}");
michael@0 16
michael@0 17 XPCOMUtils.defineLazyServiceGetter(this, "gNetworkWorker",
michael@0 18 "@mozilla.org/network/worker;1",
michael@0 19 "nsINetworkWorker");
michael@0 20
michael@0 21 // 1xx - Requested action is proceeding
michael@0 22 const NETD_COMMAND_PROCEEDING = 100;
michael@0 23 // 2xx - Requested action has been successfully completed
michael@0 24 const NETD_COMMAND_OKAY = 200;
michael@0 25 // 4xx - The command is accepted but the requested action didn't
michael@0 26 // take place.
michael@0 27 const NETD_COMMAND_FAIL = 400;
michael@0 28 // 5xx - The command syntax or parameters error
michael@0 29 const NETD_COMMAND_ERROR = 500;
michael@0 30 // 6xx - Unsolicited broadcasts
michael@0 31 const NETD_COMMAND_UNSOLICITED = 600;
michael@0 32
michael@0 33 const WIFI_CTRL_INTERFACE = "wl0.1";
michael@0 34
michael@0 35 const MANUAL_PROXY_CONFIGURATION = 1;
michael@0 36
michael@0 37 let DEBUG = false;
michael@0 38
michael@0 39 // Read debug setting from pref.
michael@0 40 try {
michael@0 41 let debugPref = Services.prefs.getBoolPref("network.debugging.enabled");
michael@0 42 DEBUG = DEBUG || debugPref;
michael@0 43 } catch (e) {}
michael@0 44
michael@0 45 function netdResponseType(code) {
michael@0 46 return Math.floor(code / 100) * 100;
michael@0 47 }
michael@0 48
michael@0 49 function isError(code) {
michael@0 50 let type = netdResponseType(code);
michael@0 51 return (type !== NETD_COMMAND_PROCEEDING && type !== NETD_COMMAND_OKAY);
michael@0 52 }
michael@0 53
michael@0 54 function debug(msg) {
michael@0 55 dump("-*- NetworkService: " + msg + "\n");
michael@0 56 }
michael@0 57
michael@0 58 /**
michael@0 59 * This component watches for network interfaces changing state and then
michael@0 60 * adjusts routes etc. accordingly.
michael@0 61 */
michael@0 62 function NetworkService() {
michael@0 63 if(DEBUG) debug("Starting net_worker.");
michael@0 64
michael@0 65 let self = this;
michael@0 66
michael@0 67 if (gNetworkWorker) {
michael@0 68 let networkListener = {
michael@0 69 onEvent: function(event) {
michael@0 70 self.handleWorkerMessage(event);
michael@0 71 }
michael@0 72 };
michael@0 73 gNetworkWorker.start(networkListener);
michael@0 74 }
michael@0 75 // Callbacks to invoke when a reply arrives from the net_worker.
michael@0 76 this.controlCallbacks = Object.create(null);
michael@0 77
michael@0 78 this.shutdown = false;
michael@0 79 Services.obs.addObserver(this, "xpcom-shutdown", false);
michael@0 80 }
michael@0 81
michael@0 82 NetworkService.prototype = {
michael@0 83 classID: NETWORKSERVICE_CID,
michael@0 84 classInfo: XPCOMUtils.generateCI({classID: NETWORKSERVICE_CID,
michael@0 85 contractID: NETWORKSERVICE_CONTRACTID,
michael@0 86 classDescription: "Network Service",
michael@0 87 interfaces: [Ci.nsINetworkService]}),
michael@0 88 QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkService]),
michael@0 89
michael@0 90 // Helpers
michael@0 91
michael@0 92 idgen: 0,
michael@0 93 controlMessage: function(params, callback) {
michael@0 94 if (this.shutdown) {
michael@0 95 return;
michael@0 96 }
michael@0 97
michael@0 98 if (callback) {
michael@0 99 let id = this.idgen++;
michael@0 100 params.id = id;
michael@0 101 this.controlCallbacks[id] = callback;
michael@0 102 }
michael@0 103 if (gNetworkWorker) {
michael@0 104 gNetworkWorker.postMessage(params);
michael@0 105 }
michael@0 106 },
michael@0 107
michael@0 108 handleWorkerMessage: function(response) {
michael@0 109 if(DEBUG) debug("NetworkManager received message from worker: " + JSON.stringify(response));
michael@0 110 let id = response.id;
michael@0 111 if (response.broadcast === true) {
michael@0 112 Services.obs.notifyObservers(null, response.topic, response.reason);
michael@0 113 return;
michael@0 114 }
michael@0 115 let callback = this.controlCallbacks[id];
michael@0 116 if (callback) {
michael@0 117 callback.call(this, response);
michael@0 118 delete this.controlCallbacks[id];
michael@0 119 }
michael@0 120 },
michael@0 121
michael@0 122 // nsINetworkService
michael@0 123
michael@0 124 getNetworkInterfaceStats: function(networkName, callback) {
michael@0 125 if(DEBUG) debug("getNetworkInterfaceStats for " + networkName);
michael@0 126
michael@0 127 if (this.shutdown) {
michael@0 128 return;
michael@0 129 }
michael@0 130
michael@0 131 let file = new FileUtils.File("/proc/net/dev");
michael@0 132 if (!file) {
michael@0 133 callback.networkStatsAvailable(false, -1, -1, new Date());
michael@0 134 return;
michael@0 135 }
michael@0 136
michael@0 137 NetUtil.asyncFetch(file, function(inputStream, status) {
michael@0 138 let result = {
michael@0 139 success: true, // netd always return success even interface doesn't exist.
michael@0 140 rxBytes: 0,
michael@0 141 txBytes: 0
michael@0 142 };
michael@0 143 result.date = new Date();
michael@0 144
michael@0 145 if (Components.isSuccessCode(status)) {
michael@0 146 // Find record for corresponding interface.
michael@0 147 let statExpr = /(\S+): +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +(\d+) +\d+ +\d+ +\d+ +\d+ +\d+ +\d+ +\d+/;
michael@0 148 let data = NetUtil.readInputStreamToString(inputStream,
michael@0 149 inputStream.available()).split("\n");
michael@0 150 for (let i = 2; i < data.length; i++) {
michael@0 151 let parseResult = statExpr.exec(data[i]);
michael@0 152 if (parseResult && parseResult[1] === networkName) {
michael@0 153 result.rxBytes = parseInt(parseResult[2], 10);
michael@0 154 result.txBytes = parseInt(parseResult[3], 10);
michael@0 155 break;
michael@0 156 }
michael@0 157 }
michael@0 158 }
michael@0 159
michael@0 160 callback.networkStatsAvailable(result.success, result.rxBytes,
michael@0 161 result.txBytes, result.date);
michael@0 162 });
michael@0 163 },
michael@0 164
michael@0 165 setNetworkInterfaceAlarm: function(networkName, threshold, callback) {
michael@0 166 if (!networkName) {
michael@0 167 callback.networkUsageAlarmResult(-1);
michael@0 168 return;
michael@0 169 }
michael@0 170
michael@0 171 let self = this;
michael@0 172 this._disableNetworkInterfaceAlarm(networkName, function(result) {
michael@0 173 if (threshold < 0) {
michael@0 174 if (!isError(result.resultCode)) {
michael@0 175 callback.networkUsageAlarmResult(null);
michael@0 176 return;
michael@0 177 }
michael@0 178 callback.networkUsageAlarmResult(result.reason);
michael@0 179 return
michael@0 180 }
michael@0 181
michael@0 182 self._setNetworkInterfaceAlarm(networkName, threshold, callback);
michael@0 183 });
michael@0 184 },
michael@0 185
michael@0 186 _setNetworkInterfaceAlarm: function(networkName, threshold, callback) {
michael@0 187 if(DEBUG) debug("setNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
michael@0 188
michael@0 189 let params = {
michael@0 190 cmd: "setNetworkInterfaceAlarm",
michael@0 191 ifname: networkName,
michael@0 192 threshold: threshold
michael@0 193 };
michael@0 194
michael@0 195 params.report = true;
michael@0 196 params.isAsync = true;
michael@0 197
michael@0 198 this.controlMessage(params, function(result) {
michael@0 199 if (!isError(result.resultCode)) {
michael@0 200 callback.networkUsageAlarmResult(null);
michael@0 201 return;
michael@0 202 }
michael@0 203
michael@0 204 this._enableNetworkInterfaceAlarm(networkName, threshold, callback);
michael@0 205 });
michael@0 206 },
michael@0 207
michael@0 208 _enableNetworkInterfaceAlarm: function(networkName, threshold, callback) {
michael@0 209 if(DEBUG) debug("enableNetworkInterfaceAlarm for " + networkName + " at " + threshold + "bytes");
michael@0 210
michael@0 211 let params = {
michael@0 212 cmd: "enableNetworkInterfaceAlarm",
michael@0 213 ifname: networkName,
michael@0 214 threshold: threshold
michael@0 215 };
michael@0 216
michael@0 217 params.report = true;
michael@0 218 params.isAsync = true;
michael@0 219
michael@0 220 this.controlMessage(params, function(result) {
michael@0 221 if (!isError(result.resultCode)) {
michael@0 222 callback.networkUsageAlarmResult(null);
michael@0 223 return;
michael@0 224 }
michael@0 225 callback.networkUsageAlarmResult(result.reason);
michael@0 226 });
michael@0 227 },
michael@0 228
michael@0 229 _disableNetworkInterfaceAlarm: function(networkName, callback) {
michael@0 230 if(DEBUG) debug("disableNetworkInterfaceAlarm for " + networkName);
michael@0 231
michael@0 232 let params = {
michael@0 233 cmd: "disableNetworkInterfaceAlarm",
michael@0 234 ifname: networkName,
michael@0 235 };
michael@0 236
michael@0 237 params.report = true;
michael@0 238 params.isAsync = true;
michael@0 239
michael@0 240 this.controlMessage(params, function(result) {
michael@0 241 callback(result);
michael@0 242 });
michael@0 243 },
michael@0 244
michael@0 245 setWifiOperationMode: function(interfaceName, mode, callback) {
michael@0 246 if(DEBUG) debug("setWifiOperationMode on " + interfaceName + " to " + mode);
michael@0 247
michael@0 248 let params = {
michael@0 249 cmd: "setWifiOperationMode",
michael@0 250 ifname: interfaceName,
michael@0 251 mode: mode
michael@0 252 };
michael@0 253
michael@0 254 params.report = true;
michael@0 255 params.isAsync = true;
michael@0 256
michael@0 257 this.controlMessage(params, function(result) {
michael@0 258 if (isError(result.resultCode)) {
michael@0 259 callback.wifiOperationModeResult("netd command error");
michael@0 260 } else {
michael@0 261 callback.wifiOperationModeResult(null);
michael@0 262 }
michael@0 263 });
michael@0 264 },
michael@0 265
michael@0 266 resetRoutingTable: function(network) {
michael@0 267 let ips = {};
michael@0 268 let prefixLengths = {};
michael@0 269 let length = network.getAddresses(ips, prefixLengths);
michael@0 270
michael@0 271 for (let i = 0; i < length; i++) {
michael@0 272 let ip = ips.value[i];
michael@0 273 let prefixLength = prefixLengths.value[i];
michael@0 274
michael@0 275 let options = {
michael@0 276 cmd: "removeNetworkRoute",
michael@0 277 ifname: network.name,
michael@0 278 ip: ip,
michael@0 279 prefixLength: prefixLength
michael@0 280 };
michael@0 281 this.controlMessage(options);
michael@0 282 }
michael@0 283 },
michael@0 284
michael@0 285 setDNS: function(networkInterface) {
michael@0 286 if(DEBUG) debug("Going DNS to " + networkInterface.name);
michael@0 287 let dnses = networkInterface.getDnses();
michael@0 288 let options = {
michael@0 289 cmd: "setDNS",
michael@0 290 ifname: networkInterface.name,
michael@0 291 domain: "mozilla." + networkInterface.name + ".doman",
michael@0 292 dnses: dnses
michael@0 293 };
michael@0 294 this.controlMessage(options);
michael@0 295 },
michael@0 296
michael@0 297 setDefaultRouteAndDNS: function(network, oldInterface) {
michael@0 298 if(DEBUG) debug("Going to change route and DNS to " + network.name);
michael@0 299 let gateways = network.getGateways();
michael@0 300 let dnses = network.getDnses();
michael@0 301 let options = {
michael@0 302 cmd: "setDefaultRouteAndDNS",
michael@0 303 ifname: network.name,
michael@0 304 oldIfname: (oldInterface && oldInterface !== network) ? oldInterface.name : null,
michael@0 305 gateways: gateways,
michael@0 306 domain: "mozilla." + network.name + ".doman",
michael@0 307 dnses: dnses
michael@0 308 };
michael@0 309 this.controlMessage(options);
michael@0 310 this.setNetworkProxy(network);
michael@0 311 },
michael@0 312
michael@0 313 removeDefaultRoute: function(network) {
michael@0 314 if(DEBUG) debug("Remove default route for " + network.name);
michael@0 315 let gateways = network.getGateways();
michael@0 316 let options = {
michael@0 317 cmd: "removeDefaultRoute",
michael@0 318 ifname: network.name,
michael@0 319 gateways: gateways
michael@0 320 };
michael@0 321 this.controlMessage(options);
michael@0 322 },
michael@0 323
michael@0 324 addHostRoute: function(network) {
michael@0 325 if(DEBUG) debug("Going to add host route on " + network.name);
michael@0 326 let gateways = network.getGateways();
michael@0 327 let dnses = network.getDnses();
michael@0 328 let options = {
michael@0 329 cmd: "addHostRoute",
michael@0 330 ifname: network.name,
michael@0 331 gateways: gateways,
michael@0 332 hostnames: dnses.concat(network.httpProxyHost)
michael@0 333 };
michael@0 334 this.controlMessage(options);
michael@0 335 },
michael@0 336
michael@0 337 removeHostRoute: function(network) {
michael@0 338 if(DEBUG) debug("Going to remove host route on " + network.name);
michael@0 339 let gateways = network.getGateways();
michael@0 340 let dnses = network.getDnses();
michael@0 341 let options = {
michael@0 342 cmd: "removeHostRoute",
michael@0 343 ifname: network.name,
michael@0 344 gateways: gateways,
michael@0 345 hostnames: dnses.concat(network.httpProxyHost)
michael@0 346 };
michael@0 347 this.controlMessage(options);
michael@0 348 },
michael@0 349
michael@0 350 removeHostRoutes: function(ifname) {
michael@0 351 if(DEBUG) debug("Going to remove all host routes on " + ifname);
michael@0 352 let options = {
michael@0 353 cmd: "removeHostRoutes",
michael@0 354 ifname: ifname,
michael@0 355 };
michael@0 356 this.controlMessage(options);
michael@0 357 },
michael@0 358
michael@0 359 addHostRouteWithResolve: function(network, hosts) {
michael@0 360 if(DEBUG) debug("Going to add host route after dns resolution on " + network.name);
michael@0 361 let gateways = network.getGateways();
michael@0 362 let options = {
michael@0 363 cmd: "addHostRoute",
michael@0 364 ifname: network.name,
michael@0 365 gateways: gateways,
michael@0 366 hostnames: hosts
michael@0 367 };
michael@0 368 this.controlMessage(options);
michael@0 369 },
michael@0 370
michael@0 371 removeHostRouteWithResolve: function(network, hosts) {
michael@0 372 if(DEBUG) debug("Going to remove host route after dns resolution on " + network.name);
michael@0 373 let gateways = network.getGateways();
michael@0 374 let options = {
michael@0 375 cmd: "removeHostRoute",
michael@0 376 ifname: network.name,
michael@0 377 gateways: gateways,
michael@0 378 hostnames: hosts
michael@0 379 };
michael@0 380 this.controlMessage(options);
michael@0 381 },
michael@0 382
michael@0 383 addSecondaryRoute: function(ifname, route) {
michael@0 384 if(DEBUG) debug("Going to add route to secondary table on " + ifname);
michael@0 385 let options = {
michael@0 386 cmd: "addSecondaryRoute",
michael@0 387 ifname: ifname,
michael@0 388 ip: route.ip,
michael@0 389 prefix: route.prefix,
michael@0 390 gateway: route.gateway
michael@0 391 };
michael@0 392 this.controlMessage(options);
michael@0 393 },
michael@0 394
michael@0 395 removeSecondaryRoute: function(ifname, route) {
michael@0 396 if(DEBUG) debug("Going to remove route from secondary table on " + ifname);
michael@0 397 let options = {
michael@0 398 cmd: "removeSecondaryRoute",
michael@0 399 ifname: ifname,
michael@0 400 ip: route.ip,
michael@0 401 prefix: route.prefix,
michael@0 402 gateway: route.gateway
michael@0 403 };
michael@0 404 this.controlMessage(options);
michael@0 405 },
michael@0 406
michael@0 407 setNetworkProxy: function(network) {
michael@0 408 try {
michael@0 409 if (!network.httpProxyHost || network.httpProxyHost === "") {
michael@0 410 // Sets direct connection to internet.
michael@0 411 Services.prefs.clearUserPref("network.proxy.type");
michael@0 412 Services.prefs.clearUserPref("network.proxy.share_proxy_settings");
michael@0 413 Services.prefs.clearUserPref("network.proxy.http");
michael@0 414 Services.prefs.clearUserPref("network.proxy.http_port");
michael@0 415 Services.prefs.clearUserPref("network.proxy.ssl");
michael@0 416 Services.prefs.clearUserPref("network.proxy.ssl_port");
michael@0 417 if(DEBUG) debug("No proxy support for " + network.name + " network interface.");
michael@0 418 return;
michael@0 419 }
michael@0 420
michael@0 421 if(DEBUG) debug("Going to set proxy settings for " + network.name + " network interface.");
michael@0 422 // Sets manual proxy configuration.
michael@0 423 Services.prefs.setIntPref("network.proxy.type", MANUAL_PROXY_CONFIGURATION);
michael@0 424 // Do not use this proxy server for all protocols.
michael@0 425 Services.prefs.setBoolPref("network.proxy.share_proxy_settings", false);
michael@0 426 Services.prefs.setCharPref("network.proxy.http", network.httpProxyHost);
michael@0 427 Services.prefs.setCharPref("network.proxy.ssl", network.httpProxyHost);
michael@0 428 let port = network.httpProxyPort === 0 ? 8080 : network.httpProxyPort;
michael@0 429 Services.prefs.setIntPref("network.proxy.http_port", port);
michael@0 430 Services.prefs.setIntPref("network.proxy.ssl_port", port);
michael@0 431 } catch(ex) {
michael@0 432 if(DEBUG) debug("Exception " + ex + ". Unable to set proxy setting for " +
michael@0 433 network.name + " network interface.");
michael@0 434 }
michael@0 435 },
michael@0 436
michael@0 437 // Enable/Disable DHCP server.
michael@0 438 setDhcpServer: function(enabled, config, callback) {
michael@0 439 if (null === config) {
michael@0 440 config = {};
michael@0 441 }
michael@0 442
michael@0 443 config.cmd = "setDhcpServer";
michael@0 444 config.isAsync = true;
michael@0 445 config.enabled = enabled;
michael@0 446
michael@0 447 this.controlMessage(config, function setDhcpServerResult(response) {
michael@0 448 if (!response.success) {
michael@0 449 callback.dhcpServerResult('Set DHCP server error');
michael@0 450 return;
michael@0 451 }
michael@0 452 callback.dhcpServerResult(null);
michael@0 453 });
michael@0 454 },
michael@0 455
michael@0 456 // Enable/disable WiFi tethering by sending commands to netd.
michael@0 457 setWifiTethering: function(enable, config, callback) {
michael@0 458 // config should've already contained:
michael@0 459 // .ifname
michael@0 460 // .internalIfname
michael@0 461 // .externalIfname
michael@0 462 config.wifictrlinterfacename = WIFI_CTRL_INTERFACE;
michael@0 463 config.cmd = "setWifiTethering";
michael@0 464
michael@0 465 // The callback function in controlMessage may not be fired immediately.
michael@0 466 config.isAsync = true;
michael@0 467 this.controlMessage(config, function setWifiTetheringResult(data) {
michael@0 468 let code = data.resultCode;
michael@0 469 let reason = data.resultReason;
michael@0 470 let enable = data.enable;
michael@0 471 let enableString = enable ? "Enable" : "Disable";
michael@0 472
michael@0 473 if(DEBUG) debug(enableString + " Wifi tethering result: Code " + code + " reason " + reason);
michael@0 474
michael@0 475 if (isError(code)) {
michael@0 476 callback.wifiTetheringEnabledChange("netd command error");
michael@0 477 } else {
michael@0 478 callback.wifiTetheringEnabledChange(null);
michael@0 479 }
michael@0 480 });
michael@0 481 },
michael@0 482
michael@0 483 // Enable/disable USB tethering by sending commands to netd.
michael@0 484 setUSBTethering: function(enable, config, callback) {
michael@0 485 config.cmd = "setUSBTethering";
michael@0 486 // The callback function in controlMessage may not be fired immediately.
michael@0 487 config.isAsync = true;
michael@0 488 this.controlMessage(config, function setUsbTetheringResult(data) {
michael@0 489 let code = data.resultCode;
michael@0 490 let reason = data.resultReason;
michael@0 491 let enable = data.enable;
michael@0 492 let enableString = enable ? "Enable" : "Disable";
michael@0 493
michael@0 494 if(DEBUG) debug(enableString + " USB tethering result: Code " + code + " reason " + reason);
michael@0 495
michael@0 496 if (isError(code)) {
michael@0 497 callback.usbTetheringEnabledChange("netd command error");
michael@0 498 } else {
michael@0 499 callback.usbTetheringEnabledChange(null);
michael@0 500 }
michael@0 501 });
michael@0 502 },
michael@0 503
michael@0 504 // Switch usb function by modifying property of persist.sys.usb.config.
michael@0 505 enableUsbRndis: function(enable, callback) {
michael@0 506 if(DEBUG) debug("enableUsbRndis: " + enable);
michael@0 507
michael@0 508 let params = {
michael@0 509 cmd: "enableUsbRndis",
michael@0 510 enable: enable
michael@0 511 };
michael@0 512 // Ask net work to report the result when this value is set to true.
michael@0 513 if (callback) {
michael@0 514 params.report = true;
michael@0 515 } else {
michael@0 516 params.report = false;
michael@0 517 }
michael@0 518
michael@0 519 // The callback function in controlMessage may not be fired immediately.
michael@0 520 params.isAsync = true;
michael@0 521 //this._usbTetheringAction = TETHERING_STATE_ONGOING;
michael@0 522 this.controlMessage(params, function(data) {
michael@0 523 callback.enableUsbRndisResult(data.result, data.enable);
michael@0 524 });
michael@0 525 },
michael@0 526
michael@0 527 updateUpStream: function(previous, current, callback) {
michael@0 528 let params = {
michael@0 529 cmd: "updateUpStream",
michael@0 530 isAsync: true,
michael@0 531 preInternalIfname: previous.internalIfname,
michael@0 532 preExternalIfname: previous.externalIfname,
michael@0 533 curInternalIfname: current.internalIfname,
michael@0 534 curExternalIfname: current.externalIfname
michael@0 535 };
michael@0 536
michael@0 537 this.controlMessage(params, function(data) {
michael@0 538 let code = data.resultCode;
michael@0 539 let reason = data.resultReason;
michael@0 540 if(DEBUG) debug("updateUpStream result: Code " + code + " reason " + reason);
michael@0 541 callback.updateUpStreamResult(!isError(code), data.curExternalIfname);
michael@0 542 });
michael@0 543 },
michael@0 544
michael@0 545 shutdown: false,
michael@0 546
michael@0 547 observe: function observe(aSubject, aTopic, aData) {
michael@0 548 switch (aTopic) {
michael@0 549 case "xpcom-shutdown":
michael@0 550 debug("NetworkService shutdown");
michael@0 551 this.shutdown = true;
michael@0 552 Services.obs.removeObserver(this, "xpcom-shutdown");
michael@0 553 if (gNetworkWorker) {
michael@0 554 gNetworkWorker.shutdown();
michael@0 555 gNetworkWorker = null;
michael@0 556 }
michael@0 557 break;
michael@0 558 }
michael@0 559 },
michael@0 560 };
michael@0 561
michael@0 562 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkService]);

mercurial