blob: bb3b34dfc8f4f7c9118003046a34cd816e1d9153 [file] [log] [blame]
/*
* Copyright 2012 Research In Motion Limited.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var _self,
os = require("os"),
fs = require('fs'),
path = require('path'),
bb10_utils = require('./utils'),
blackberryProperties = bb10_utils.getProperties();
//fix older blackberry10.json files
//these may include 'simulator' type rather than 'emulator'
function replaceSimulator(targets) {
var replace = false,
t;
for (t in targets) {
if (targets.hasOwnProperty(t) && targets[t].type === "simulator") {
targets[t].type = "emulator";
replace = true;
}
}
if (replace) {
blackberryProperties.targets = targets;
bb10_utils.writeToPropertiesFile(blackberryProperties);
}
}
_self = {
getTargetList : function (type, pruneDisconnected, callback) {
var targList = [],
count = 0,
targets = blackberryProperties.targets,
addItem = function (t) {
targets[t].name = t;
targList.push(targets[t]);
},
complete = function () {
if (count === Object.keys(targets).length) {
callback(targList);
}
},
checkConnection = function (name) {
_self.checkConnection(targets[name].ip, type, function (connected) {
count++;
if (connected) {
addItem(name);
}
complete();
});
},
t;
if (targets) {
replaceSimulator(targets);
for (t in targets) {
if (targets.hasOwnProperty(t) && targets[t].type === type) {
if (pruneDisconnected) {
checkConnection(t);
}
else {
addItem(t);
count++;
}
} else {
count++;
}
}
}
complete();
},
getDeviceInfo: function (ip, password, callback) {
var cmd = path.join(process.env.CORDOVA_BBTOOLS, 'blackberry-deploy'),
args = [
'-listDeviceInfo',
ip
],
options = {
_customOptions: { silent: true }
};
if (password) {
args.push('-password');
args.push(password);
}
bb10_utils.exec(cmd, args, options, function (error, stdout, stderr) {
var err = error,
result = {},
name = /modelname::(.*?)(\r?)\n/.exec(stdout),
pin = /devicepin::0x(.*?)(\r?)\n/.exec(stdout);
if (name && name.length > 0) {
result.name = name[1];
}
if (pin && pin.length > 0) {
result.pin = pin[1];
}
if (!result.name) {
if (stdout.indexOf("Error:") !== -1) {
err = stdout.slice(stdout.indexOf("Error:") + 6);
} else if (stdout === "" && stderr.indexOf("Error:") === 0) {
err = stderr.slice(7);
} else {
err = "Unable to authenticate with BlackBerry 10 device/emulator at " + ip + ".";
}
}
callback(err, result);
});
},
findConnectedDevice: function (callback) {
var defaultIp = '169.254.0.1',
count = 0,
i;
_self.discoverUsb(function (result) {
if (!result || result.length === 0) {
result = [defaultIp];
}
for (i = 0; i < result.length; i++) {
/* jshint ignore:start */
_self.checkConnection(result[i], 'device', function (connection, ip) {
if (connection) {
callback(ip);
return;
} else if (++count === result.length) {
callback();
}
});
/* jshint ignore:end */
}
});
},
discoverUsb: function (callback) {
var IPV4_TYPE = "IPv4",
IP_SPLIT_REGEXP = /(169\.254\.\d{1,3}\.)(\d{1,3})/,
networkInterfaces = os.networkInterfaces(),
result,
matches = [],
ni,
i;
for (ni in networkInterfaces) {
if (networkInterfaces.hasOwnProperty(ni)) {
for (i = 0; i < networkInterfaces[ni].length; i++) {
if (networkInterfaces[ni][i].family === IPV4_TYPE) {
result = IP_SPLIT_REGEXP.exec(networkInterfaces[ni][i].address);
if (result && result[1] && result[2]) {
matches.push(result[1] + (result[2] - 1));
}
}
}
}
}
callback(matches);
},
findConnectedSimulator: function (callback) {
var pathVmDhcpLeases,
pathUserProfile,
pathAllUserProfile,
vmDhcpLeasesFiles,
DHCP_LEASES_REGEX = /VMware\\vmnetdhcp.leases$/,
targets = blackberryProperties.targets,
ipsToTest = [],
dhcpIPs = [],
t;
// Firstly, check targets in the properties file
if (targets) {
for (t in targets) {
if (targets.hasOwnProperty(t) && targets[t].type === "emulator" && targets[t].ip) {
ipsToTest.push(targets[t].ip);
}
}
}
// Secondly, check VMware dhcp.leases file
if (bb10_utils.isWindows()) {
pathUserProfile = process.env.USERPROFILE;
pathAllUserProfile = pathUserProfile.substr(0, pathUserProfile.lastIndexOf("\\") + 1) + "All Users";
vmDhcpLeasesFiles = bb10_utils.readdirSyncRecursive(pathAllUserProfile).filter(function (file) {
return DHCP_LEASES_REGEX.test(file);
});
pathVmDhcpLeases = vmDhcpLeasesFiles[0];
} else if (bb10_utils.isOSX()) {
pathVmDhcpLeases = "/private/var/db/vmware/vmnet-dhcpd-vmnet8.leases";
} else {
pathVmDhcpLeases = "/var/db/vmware/vmnet-dhcpd-vmnet8.leases";
}
fs.readFile(pathVmDhcpLeases, 'utf8', function (err, data) {
if (!err) {
// Find all lines that start with "lease xxx.xxx.xxx.xxx "
dhcpIPs = data.match(/lease \d{1,3}.\d{1,3}.\d{1,3}.\d{1,3} /g) || [];
dhcpIPs = dhcpIPs.map(function (result) {
return result.substr(6, result.indexOf(' ', 7) - 6);
});
}
ipsToTest = ipsToTest.concat(dhcpIPs);
// Remove duplicated ip
ipsToTest = ipsToTest.filter(function (item, index, arr) {
return arr.indexOf(item) === index;
});
_self.checkConnectionRecursive(ipsToTest, 0, callback);
});
},
checkConnectionRecursive: function (ips, index, callback) {
var ip;
if (!ips || index === ips.length) {
callback();
return;
}
console.log("Searching for connected BlackBerry 10 Simulator (" + (index + 1) + "/" + ips.length + ")...");
ip = ips[index];
_self.checkConnection(ip, "emulator", function (connection) {
if (connection) {
callback(ip);
} else {
_self.checkConnectionRecursive(ips, index + 1, callback);
}
});
},
checkConnection: function (ip, type, callback) {
var script = path.join(process.env.CORDOVA_BBTOOLS, 'blackberry-deploy'),
args = [
'-test',
ip
],
options = {
_customOptions: { silent: true }
};
bb10_utils.exec(script, args, options, function (error, stdout, stderr) {
// error code 3 corresponds to connected device with password
// null or "Error: null" in stderr corresponds to connected simulator or device without password
var connected =
error === null ||
(error && error.code === 3) ||
stderr.length === 0 ||
stderr.indexOf('Error: null') >= 0 ||
stderr.indexOf('Error: Authentication failed') >= 0;
callback(connected, ip);
});
},
listTargets : function (type, pruneDisconnected) {
_self.getTargetList(type, pruneDisconnected, function (targets) {
for (var t in targets) {
if (targets.hasOwnProperty(t)) {
console.log(targets[t].name + ' ip: ' + targets[t].ip);
}
}
});
}
};
module.exports = _self;