blob: fb7fefdd4cfafa051242418bb355a4801d562aa1 [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 fs = require("fs"),
path = require("path"),
utils = require("./utils"),
targetUtils = require("./target-utils.js"),
localize = require("./localize"),
pkgrUtils = require("./packager-utils"),
debugTokenHelper = require("./debugtoken-helper"),
xml2js = require('xml2js'),
logger = require("./logger"),
async = require("async"),
session = require("./session"),
properties = utils.getProperties(),
workingdir = path.normalize(__dirname + "/.."),
_self;
//Options looking for are: (Device | Emulator, query, devicepass). Calls back with: (error || options object, target object)
function getTargetName(options, done) {
var ipFinder = options.emulator ? targetUtils.findConnectedSimulator : targetUtils.findConnectedDevice,
targetType = options.emulator ? "emulator" : "device";
if (options.target) {
done(null, options, options.target);
} else {
if (options.device && options.emulator) {
localize.translate("WARN_RUN_DEVICE_OVERRIDES_EMULATOR");
}
async.series(
{
ip: function (done) {
ipFinder(function (ip) {
done(ip ? null : "No connected BlackBerry 10 " + targetType + " found", ip);
});
},
devicePass: function (done) {
if (!options.devicepass && options.devicepass !== "") {
if (options.query) {
utils.prompt({description: getPasswordPrompt(targetType), hidden: true}, done);
} else {
done("");
}
} else {
done(null, options.devicepass);
}
}
},
function (err, results) {
if (err) {
done(err);
} else {
options.devicepass = results.devicePass;
_self.checkDeviceInfo(options, results.ip, targetType, results.devicePass, done);
}
});
}
}
//Options looking for are: (query, devicepass). Calls back with: (error || target object)
function validateTarget(options, targetName, allDone) {
var deployTarget,
err,
runTasks = [];
if (!targetName) {
err = "No target exists, to add that target please run: target add <name> <ip> [-t | --type <device | simulator>] [-p <password>] [--pin <devicepin>]";
} else if (!properties.targets[targetName]) {
err = "The target \"" + targetName + "\" does not exist, to add that target please run: target add " + targetName + " <ip> [-t | --type <device | simulator>] [-p <password>] [--pin <devicepin>]";
} else {
deployTarget = utils.clone(properties.targets[targetName]);
deployTarget.name = targetName;
if (!deployTarget.ip) {
if (options.query) {
runTasks.push(function (done) {
utils.prompt({description: "Please enter the IP address for target " + deployTarget.name + ": "}, function (e, ip) {
deployTarget.ip = ip;
done(e);
});
});
} else {
err = "IP is not defined in target \"" + deployTarget.name + "\"";
}
}
if (err === undefined && !deployTarget.password && deployTarget.password !== "") {
if (options.devicepass || options.devicepass === "") {
deployTarget.password = options.devicepass;
} else {
if (options.query) {
runTasks.push(function (done) {
utils.prompt({description: getPasswordPrompt(deployTarget.type), hidden: true}, function (e, devicePass) {
deployTarget.password = devicePass;
done(e);
});
});
} else if (!options.emulator) {
err = "No device password provided. You can omit --no-query, use --devicepass, or enter a value for 'password' to the target " + deployTarget.name + " defined at " + utils.getPropertiesFilePath();
}
}
}
if (!deployTarget.pin) {
runTasks.push(function (done) {
targetUtils.getDeviceInfo(deployTarget.ip, deployTarget.password, function (err, result) {
deployTarget.pin = result.pin;
done(err);
});
});
}
}
async.series(runTasks, function (e) {
var finalErr = err || e;
if (!finalErr && deployTarget) {
logger.info("Target " + deployTarget.name + " selected");
}
allDone(err || e, options, deployTarget);
});
}
//Options looking for are: (keystorepass, query). Calls back with: (error || target object)
function handleDebugToken(options, deployTarget, allDone) {
options.keystorepass = session.getKeyStorePass(options);
// deploy debug token for device debug builds only
if (deployTarget.pin && !options.emulator && options.build && !options.release) {
async.waterfall(
[
debugTokenHelper.checkDebugToken.bind(this, deployTarget.pin),
function (done) {
//If no keystorepass is provided debugTokenHelper will throw an error.
if (!options.keystorepass && options.query) {
utils.prompt({description: "Please enter your keystore password: ", hidden: true}, function (err, result) {
options.keystorepass = result;
done(null, result);
});
} else {
done(null, options.keystorepass);
}
},
debugTokenHelper.createToken.bind(this, properties, "all")
],
function (err, results) {
// If the error is true, then the debug token is valid and creation was skipped.
if (err === true) {
logger.info(localize.translate("PROGRESS_DEBUG_TOKEN_IS_VALID"));
//Clear the error so it is still deployed
err = null;
}
if (!err) {
debugTokenHelper.deployToken(deployTarget.name, deployTarget.ip, deployTarget.password, function (code) {
allDone(code, deployTarget);
});
} else {
allDone(null, deployTarget);
}
}
);
} else {
allDone(null, deployTarget);
}
}
function generateDeployOptions(options, deployTarget) {
var deployOptions = [],
barPath = pkgrUtils.escapeStringForShell(
path.normalize(__dirname + "/../../build/" +
(deployTarget.type === "device" ? "device" : "simulator") +
"/" + utils.genBarName() + ".bar"));
deployOptions.push("-device");
deployOptions.push(deployTarget.ip);
if (deployTarget.password) {
deployOptions.push("-password");
deployOptions.push(deployTarget.password);
}
deployOptions.push("-package");
deployOptions.push(barPath);
deployOptions.push("-uninstallApp");
deployOptions.push("-installApp");
if (options.launch) {
deployOptions.push("-launchApp");
}
return deployOptions;
}
function execNativeDeploy(deployOptions, callback) {
var script = path.normalize(path.join(process.env.CORDOVA_BBTOOLS, "blackberry-deploy"));
utils.exec(script, deployOptions, {
"cwd": workingdir,
"env": process.env
}, callback);
}
function getPasswordPrompt(targetType) {
var prompt = "Please enter your " + targetType + " password";
if (targetType === "emulator") {
prompt += " (For no password press ENTER)";
}
prompt += ": ";
return prompt;
}
_self = {
//options looking for are: (query, devicepass, password, target, (device || emulator)) Function returns (error || deployTarget)
getValidatedTarget : function (options, callback) {
async.waterfall(
[
getTargetName.bind(this, options),
validateTarget,
handleDebugToken
], callback
);
},
//Function returns (error || null)
install : function (options, deployTarget, allDone) {
var script = path.join(process.env.CORDOVA_BBTOOLS, "blackberry-deploy"),
args = [
"-device",
deployTarget.ip
],
projectRootDir = path.normalize(path.join(__dirname, "..")),
installedAppsOutput,
runTasks = [];
if (deployTarget.password) {
args.push("-password", deployTarget.password);
}
runTasks = [
function uninstallInstallLaunchApp(result, done) {
var deployOptions = generateDeployOptions(options, deployTarget);
execNativeDeploy(deployOptions, done);
}
];
async.waterfall(runTasks,
function (err, results) {
allDone(null, deployTarget);
}
);
},
//Function returns (error || deployTarget)
checkBuild : function (deployTarget, allDone) {
var barPath = path.normalize(__dirname + "/../../build/" +
(deployTarget.type === "device" ? "device" : "simulator") +
"/" + utils.genBarName() + ".bar");
if (fs.existsSync(barPath)) {
allDone(null, deployTarget);
} else {
allDone("No build file exists, please run: build [--debug | --release] [--keystorepass <password>] [--buildId <number>] [--params <json>] [--loglevel <level>] [--web-inspector] [--no-signing]");
}
},
//No options needed within function Function returns (error || options, targetName)
checkDeviceInfo : function (options, ip, deviceType, devicePass, done) {
var props = utils.getProperties(),
targetName;
targetUtils.getDeviceInfo(ip, devicePass, function (err, device) {
if (!err) {
targetName = device.name.replace(/ /g, "-") + "-" + device.pin;
props.targets[targetName] = {
ip: ip,
pin: device.pin,
type: deviceType
};
utils.writeToPropertiesFile(props);
}
done(err, options, targetName);
});
}
};
module.exports = _self;