mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
206 lines
7.1 KiB
JavaScript
206 lines
7.1 KiB
JavaScript
/* 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/Services.jsm");
|
|
|
|
const NETWORKMANAGER_CONTRACTID = "@mozilla.org/network/manager;1";
|
|
const NETWORKMANAGER_CID =
|
|
Components.ID("{33901e46-33b8-11e1-9869-f46d04d25bcc}");
|
|
const NETWORKINTERFACE_CONTRACTID = "@mozilla.org/network/interface;1";
|
|
const NETWORKINTERFACE_CID =
|
|
Components.ID("{266c3edd-78f0-4512-8178-2d6fee2d35ee}");
|
|
|
|
const DEFAULT_PREFERRED_NETWORK_TYPE = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
|
|
|
|
const TOPIC_INTERFACE_STATE_CHANGED = "network-interface-state-changed";
|
|
const TOPIC_INTERFACE_REGISTERED = "network-interface-registered";
|
|
const TOPIC_INTERFACE_UNREGISTERED = "network-interface-unregistered";
|
|
const TOPIC_DEFAULT_ROUTE_CHANGED = "network-default-route-changed";
|
|
|
|
const DEBUG = false;
|
|
|
|
/**
|
|
* This component watches for network interfaces changing state and then
|
|
* adjusts routes etc. accordingly.
|
|
*/
|
|
function NetworkManager() {
|
|
this.networkInterfaces = {};
|
|
Services.obs.addObserver(this, TOPIC_INTERFACE_STATE_CHANGED, true);
|
|
|
|
debug("Starting worker.");
|
|
this.worker = new ChromeWorker("resource://gre/modules/net_worker.js");
|
|
this.worker.onmessage = function onmessage(event) {
|
|
this.handleWorkerMessage(event.data);
|
|
}.bind(this);
|
|
this.worker.onerror = function onerror(event) {
|
|
debug("Received error from worker: " + event.filename +
|
|
":" + event.lineno + ": " + event.message + "\n");
|
|
// Prevent the event from bubbling any further.
|
|
event.preventDefault();
|
|
};
|
|
}
|
|
NetworkManager.prototype = {
|
|
classID: NETWORKMANAGER_CID,
|
|
classInfo: XPCOMUtils.generateCI({classID: NETWORKMANAGER_CID,
|
|
contractID: NETWORKMANAGER_CONTRACTID,
|
|
classDescription: "Network Manager",
|
|
interfaces: [Ci.nsINetworkManager]}),
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsINetworkManager,
|
|
Ci.nsISupportsWeakReference,
|
|
Ci.nsIObserver,
|
|
Ci.nsIWorkerHolder]),
|
|
|
|
// nsIWorkerHolder
|
|
|
|
worker: null,
|
|
|
|
// nsIObserver
|
|
|
|
observe: function observe(subject, topic, data) {
|
|
if (topic != TOPIC_INTERFACE_STATE_CHANGED) {
|
|
return;
|
|
}
|
|
let network = subject.QueryInterface(Ci.nsINetworkInterface);
|
|
debug("Network '" + network.name + "' changed state to " + network.state);
|
|
switch (network.state) {
|
|
case Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED:
|
|
case Ci.nsINetworkInterface.NETWORK_STATE_DISCONNECTED:
|
|
this.setAndConfigureActive();
|
|
break;
|
|
}
|
|
},
|
|
|
|
// nsINetworkManager
|
|
|
|
registerNetworkInterface: function registerNetworkInterface(network) {
|
|
if (!(network instanceof Ci.nsINetworkInterface)) {
|
|
throw Components.Exception("Argument must be nsINetworkInterface.",
|
|
Cr.NS_ERROR_INVALID_ARG);
|
|
}
|
|
if (network.name in this.networkInterfaces) {
|
|
throw Components.Exception("Network with that name already registered!",
|
|
Cr.NS_ERROR_INVALID_ARG);
|
|
}
|
|
this.networkInterfaces[network.name] = network;
|
|
this.setAndConfigureActive();
|
|
Services.obs.notifyObservers(network, TOPIC_INTERFACE_REGISTERED, null);
|
|
debug("Network '" + network.name + "' registered.");
|
|
},
|
|
|
|
unregisterNetworkInterface: function unregisterNetworkInterface(network) {
|
|
if (!(network instanceof Ci.nsINetworkInterface)) {
|
|
throw Components.Exception("Argument must be nsINetworkInterface.",
|
|
Cr.NS_ERROR_INVALID_ARG);
|
|
}
|
|
if (!(network.name in this.networkInterfaces)) {
|
|
throw Components.Exception("No network with that name registered.",
|
|
Cr.NS_ERROR_INVALID_ARG);
|
|
}
|
|
delete this.networkInterfaces[network.name];
|
|
this.setAndConfigureActive();
|
|
Services.obs.notifyObservers(network, TOPIC_INTERFACE_UNREGISTERED, null);
|
|
debug("Network '" + network.name + "' unregistered.");
|
|
},
|
|
|
|
networkInterfaces: null,
|
|
|
|
_preferredNetworkType: DEFAULT_PREFERRED_NETWORK_TYPE,
|
|
get preferredNetworkType() {
|
|
return this._preferredNetworkType;
|
|
},
|
|
set preferredNetworkType(val) {
|
|
if ([Ci.nsINetworkInterface.NETWORK_TYPE_WIFI,
|
|
Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE,
|
|
Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS].indexOf(val) == -1) {
|
|
throw "Invalid network type";
|
|
}
|
|
this._preferredNetworkType = val;
|
|
},
|
|
|
|
active: null,
|
|
_overriddenActive: null,
|
|
|
|
overrideActive: function overrideActive(network) {
|
|
this._overriddenActive = network;
|
|
this.setAndConfigureActive();
|
|
},
|
|
|
|
// Helpers
|
|
|
|
handleWorkerMessage: function handleWorkerMessage(message) {
|
|
debug("NetworkManager received message from worker: " + JSON.stringify(message));
|
|
},
|
|
|
|
/**
|
|
* Determine the active interface and configure it.
|
|
*/
|
|
setAndConfigureActive: function setAndConfigureActive() {
|
|
debug("Evaluating whether active network needs to be changed.");
|
|
let oldActive = this.active;
|
|
|
|
if (this._overriddenActive) {
|
|
debug("We have an override for the active network: " +
|
|
this._overriddenActive.name);
|
|
// The override was just set, so reconfigure the network.
|
|
if (this.active != this._overriddenActive) {
|
|
this.active = this._overriddenActive;
|
|
this.setDefaultRouteAndDNS(oldActive);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// If the active network is already of the preferred type, nothing to do.
|
|
if (this.active &&
|
|
this.active.state == Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED &&
|
|
this.active.type == this._preferredNetworkType) {
|
|
debug("Active network is already our preferred type. Not doing anything.");
|
|
return;
|
|
}
|
|
|
|
// Find a suitable network interface to activate.
|
|
this.active = null;
|
|
for each (let network in this.networkInterfaces) {
|
|
if (network.state != Ci.nsINetworkInterface.NETWORK_STATE_CONNECTED) {
|
|
continue;
|
|
}
|
|
this.active = network;
|
|
if (network.type == this.preferredNetworkType) {
|
|
debug("Found our preferred type of network: " + network.name);
|
|
break;
|
|
}
|
|
}
|
|
if (this.active && (oldActive != this.active)) {
|
|
this.setDefaultRouteAndDNS(oldActive);
|
|
}
|
|
},
|
|
|
|
setDefaultRouteAndDNS: function setDefaultRouteAndDNS(oldInterface) {
|
|
debug("Going to change route and DNS to " + this.active.name);
|
|
let options = {
|
|
cmd: this.active.dhcp ? "runDHCPAndSetDefaultRouteAndDNS" : "setDefaultRouteAndDNS",
|
|
ifname: this.active.name,
|
|
oldIfname: oldInterface ? oldInterface.name : null
|
|
};
|
|
this.worker.postMessage(options);
|
|
},
|
|
|
|
};
|
|
|
|
const NSGetFactory = XPCOMUtils.generateNSGetFactory([NetworkManager]);
|
|
|
|
|
|
let debug;
|
|
if (DEBUG) {
|
|
debug = function (s) {
|
|
dump("-*- NetworkManager: " + s + "\n");
|
|
};
|
|
} else {
|
|
debug = function (s) {};
|
|
}
|