dom/wifi/WifiNetUtil.jsm
author Masayuki Nakano <masayuki@d-toybox.com>
Sat, 11 Jun 2016 11:06:37 +0900
changeset 341662 b64f33cd6b5431a6bd97c3afea39f943ca2b9022
parent 279210 475a5b2d58dba883df289549adf23dc9ffb2d107
permissions -rw-r--r--
Bug 1278014 part.2 Define mozilla::SelectionType as an enum class and use it instead of RawSelectionType as far as possible r=smaug This patch defines mozilla::SelectionType as an enum class. This is safer than nsISelectionController::SELECTION_* since setting illegal value to its variable is checked at build time. So, as far as possible, this should be used everywhere (but of course, this isn't available in scriptable interfaces). And also this implements some useful methods for managing SelectionType and RawSelectionType which are implemented in layout/nsSelection.cpp because nsISelectionController is implemented by both PresShell and nsTextEditorState. Therefore, implementing one of them may make hard to find them. On the other hand, nsSelection.cpp is a better file name to look for them. Note that this patch creates mozilla::Selection::RawType() for binding. Native code should keep using Selection::Type() but the binding code needs to use RawType() due to impossible to convert from SelectionType to RawSelectionType without explicit cast. MozReview-Commit-ID: 81vX7A0hHQN

/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

"use strict";

const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;

Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/systemlibs.js");

XPCOMUtils.defineLazyServiceGetter(this, "gNetworkService",
                                   "@mozilla.org/network/service;1",
                                   "nsINetworkService");

this.EXPORTED_SYMBOLS = ["WifiNetUtil"];

const DHCP_PROP = "init.svc.dhcpcd";
const DHCP      = "dhcpcd";
const DEBUG     = false;

this.WifiNetUtil = function(controlMessage) {
  function debug(msg) {
    if (DEBUG) {
      dump('-------------- NetUtil: ' + msg);
    }
  }

  var util = {};

  util.runDhcp = function (ifname, gen, callback) {
    util.stopDhcp(ifname, function() {
      gNetworkService.dhcpRequest(ifname, function(success, dhcpInfo) {
        util.runIpConfig(ifname, dhcpInfo, function(data) {
          callback(data, gen);
        });
      });
    });
  };

  util.stopDhcp = function (ifname, callback) {
    // This function does exactly what dhcp_stop does. Unforunately, if we call
    // this function twice before the previous callback is returned. We may block
    // our self waiting for the callback. It slows down the wifi startup procedure.
    // Therefore, we have to roll our own version here.
    let dhcpService = DHCP_PROP + "_" + ifname;
    let suffix = (ifname.substr(0, 3) === "p2p") ? "p2p" : ifname;
    let processName = DHCP + "_" + suffix;

    // The implementation of |dhcp_do_request| would wait until the
    // |result_prop_name| (e.g. dhcp.wlan0.result) to be non-null
    // or 30 second timeout. So we manually change the result property
    // to 'ko' to avoid timeout.
    //
    // http://androidxref.com/4.4.4_r1/xref/system/core/libnetutils/dhcp_utils.c#234
    setProperty('dhcp.' + suffix + '.result', 'ko', function() {
      stopProcess(dhcpService, processName, callback);
    });
  };

  util.startDhcpServer = function (config, callback) {
    gNetworkService.setDhcpServer(true, config, function (error) {
      callback(!error);
    });
  };

  util.stopDhcpServer = function (callback) {
    gNetworkService.setDhcpServer(false, null, function (error) {
      callback(!error);
    });
  };

  util.runIpConfig = function (name, data, callback) {
    if (!data) {
      debug("IP config failed to run");
      callback({ info: data });
      return;
    }

    setProperty("net." + name + ".dns1", ipToString(data.dns1),
                function(ok) {
      if (!ok) {
        debug("Unable to set net.<ifname>.dns1");
        return;
      }
      setProperty("net." + name + ".dns2", ipToString(data.dns2),
                  function(ok) {
        if (!ok) {
          debug("Unable to set net.<ifname>.dns2");
          return;
        }
        setProperty("net." + name + ".gw", ipToString(data.gateway),
                    function(ok) {
          if (!ok) {
            debug("Unable to set net.<ifname>.gw");
            return;
          }
          callback({ info: data });
        });
      });
    });
  };

  //--------------------------------------------------
  // Helper functions.
  //--------------------------------------------------

  function stopProcess(service, process, callback) {
    var count = 0;
    var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
    function tick() {
      let result = libcutils.property_get(service);
      if (result === null) {
        callback();
        return;
      }
      if (result === "stopped" || ++count >= 5) {
        // Either we succeeded or ran out of time.
        timer = null;
        callback();
        return;
      }

      // Else it's still running, continue waiting.
      timer.initWithCallback(tick, 1000, Ci.nsITimer.TYPE_ONE_SHOT);
    }

    setProperty("ctl.stop", process, tick);
  }

  // Wrapper around libcutils.property_set that returns true if setting the
  // value was successful.
  // Note that the callback is not called asynchronously.
  function setProperty(key, value, callback) {
    let ok = true;
    try {
      libcutils.property_set(key, value);
    } catch(e) {
      ok = false;
    }
    callback(ok);
  }

  function ipToString(n) {
    return String((n >>  0) & 0xFF) + "." +
                 ((n >>  8) & 0xFF) + "." +
                 ((n >> 16) & 0xFF) + "." +
                 ((n >> 24) & 0xFF);
  }

  return util;
};