New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

crosswalk-app-tools

Package Overview
Dependencies
Maintainers
2
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

crosswalk-app-tools - npm Package Compare versions

Comparing version 0.6.1 to 0.7.0

android/lib/ProjectProperties.js

3

android/lib/AndroidDependencies.js

@@ -208,3 +208,4 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

}
InvalidChannelError.prototype = Error.prototype;
InvalidChannelError.prototype = Object.create(Error.prototype);
InvalidChannelError.prototype.constructor = InvalidChannelError;

@@ -211,0 +212,0 @@ AndroidDependencies.prototype.InvalidChannelError = InvalidChannelError;

@@ -13,2 +13,3 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

* @param {String} path Path to manifest.json
* @constructor
*/

@@ -26,12 +27,19 @@ function AndroidManifest(output, path) {

this._applicationIcon = null;
var node = this.findApplicationNode(doc);
if (node) {
this._applicationIcon = node.getAttribute("android:icon");
var appNode = this.findApplicationNode(doc);
if (appNode) {
this._applicationIcon = appNode.getAttribute("android:icon");
}
this._applicationLabel = null;
node = this.findApplicationNode(doc);
if (node) {
this._applicationLabel = node.getAttribute("android:label");
appNode = this.findApplicationNode(doc);
if (appNode) {
this._applicationLabel = appNode.getAttribute("android:label");
}
var activityNode = this.findChildNode(appNode, "activity");
if (activityNode) {
this._screenOrientation = activityNode.getAttribute("android:screenOrientation");
}
// TODO read other values from manifest and initialize members
}

@@ -135,2 +143,7 @@

node.setAttribute("android:label", applicationLabel);
// Also set name on the activity
var activityNode = this.findChildNode(node, "activity");
if (activityNode)
activityNode.setAttribute("android:label", applicationLabel);
// Save
this.write(doc);

@@ -145,2 +158,97 @@ }

/**
* Orientation
* @member {String} screenOrientation Value for <activity android:screenOrientation= in the android manifest
* @instance
* @memberOf AndroidManifest
*/
Object.defineProperty(AndroidManifest.prototype, "screenOrientation", {
get: function() {
return this._screenOrientation;
},
set: function(orientation) {
// Check
var values = ["unspecified", "behind",
"landscape", "portrait",
"reverseLandscape", "reversePortrait",
"sensorLandscape", "sensorPortrait",
"userLandscape", "userPortrait",
"sensor", "fullSensor", "nosensor",
"user", "fullUser", "locked"];
if (values.indexOf(orientation) < 0) {
this._output.warning("Invalid screenOrientation: " + orientation);
return;
}
// Look up <application> node
var doc = this.read();
var node = this.findApplicationNode(doc);
if (node) {
var activityNode = this.findChildNode(node, "activity");
if (activityNode) {
activityNode.setAttribute("android:screenOrientation", orientation);
this._screenOrientation = orientation;
} else {
this._output.warning("Did not find <activity> element in AndroidManifest.xml");
}
// Save
this.write(doc);
} else {
this._output.warning("Did not find <application> element in AndroidManifest.xml");
}
}
});
/**
* Permissions
* @member {Array} permissions Android permissisons
* @instance
* @memberOf AndroidManifest
*/
Object.defineProperty(AndroidManifest.prototype, "permissions", {
get: function() {
var permissions = [];
var doc = this.read();
for (var idx in doc.documentElement.childNodes) {
var n = doc.documentElement.childNodes[idx];
if (n.nodeName === "uses-permission") {
var value = n.getAttribute("android:name");
// e.g. android.permissions.CAMERA, index 2 is actual value
var suffix = value.split(".")[2];
permissions.push(suffix);
}
}
return permissions;
},
set: function(permissions) {
if (!(permissions instanceof Array)) {
this._output.warning("Invalid permissions: " + permissions);
return;
}
var doc = this.read();
// Remove permissions
var child;
var permNodes = doc.getElementsByTagName("uses-permission");
for (var i = 0; permNodes[i]; i++) {
child = permNodes[i];
doc.documentElement.removeChild(child);
}
// Add new permissions
this._output.info("Adding permissions " + permissions.join(","));
permissions.forEach(function (permission) {
child = doc.createElement("uses-permission");
child.setAttribute("android:name", "android.permission." + permission);
doc.documentElement.appendChild(child);
});
this.write(doc);
}
});
/**
* Read AndroidManifest.xml

@@ -195,2 +303,24 @@ * @returns {xmldom.Document} XML Document

/**
* Find named child node
* @param {xmldom.Node} node
* @param {String} name Child name
* @returns {xmldom.Node} Node if found or null
* @private
*/
AndroidManifest.prototype.findChildNode =
function(node, name) {
var child = null;
for (var idx in node.childNodes) {
child = node.childNodes[idx];
if (child.nodeName === name) {
return child;
}
}
return null;
};
module.exports = AndroidManifest;

@@ -5,5 +5,8 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

var ChildProcess = require("child_process");
var FS = require("fs");
var Path = require('path');
var FormatJson = require("format-json");
var MkTemp = require('mktemp');
var ShellJS = require("shelljs");

@@ -14,4 +17,4 @@

var AndroidSDK = require("./AndroidSDK");
var CrosswalkZip = require("./CrosswalkZip");
var JavaActivity = require("./JavaActivity");
var ProjectProperties = require("./ProjectProperties");
var XmlTheme = require("./XmlTheme");

@@ -44,2 +47,4 @@

instance._channel = "stable";
instance._shared = false;
instance._apiTarget = null;

@@ -50,3 +55,10 @@ return instance;

/**
* Minimal API level.
* FIXME: this is not the optimal way to specify this.
*/
AndroidPlatform.MIN_API_LEVEL = 21;
/**
* Accessor function for platform-specific command-line argument spec.
* @static
*/

@@ -58,3 +70,4 @@ AndroidPlatform.getArgs =

"crosswalk": "\t\t\tChannel name (stable/beta/canary)\n" +
"\t\t\t\t\t\tor version number (w.x.y.z)"
"\t\t\t\t\t\tor version number (w.x.y.z)",
"shared": " Depend on shared crosswalk installation"
}

@@ -66,2 +79,3 @@ };

* Accessor function for platform-specific environment variables spec.
* @static
*/

@@ -76,2 +90,137 @@ AndroidPlatform.getEnv =

/**
* Check host setup.
* @param {OutputIface} output Output to write to
* @param {Function} callback Function(success) to be called when done
* @static
*/
AndroidPlatform.check =
AndroidPlatform.prototype.check =
function(output, callback) {
// Checking deps
var deps = [
"android",
"ant",
"java"
];
var found = true;
var msg;
deps.forEach(function (dep) {
var path = ShellJS.which(dep);
msg = "Checking for " + dep + "... " + path;
if (path) {
output.info(msg);
} else {
found = false;
output.error(msg);
}
});
// Checking env
var androidHome = "ANDROID_HOME";
msg = "Checking for " + androidHome + "... ";
if (process.env[androidHome]) {
output.info(msg + process.env[androidHome]);
} else {
found = false;
output.info(msg + "empty");
output.error(androidHome + " needs to be set for builds to work");
}
if (!found) {
callback(false);
return;
}
// Build dummy project
var app = {
output: output
};
ShellJS.pushd(ShellJS.tempdir());
var dir = MkTemp.createDirSync("XXXXXX");
// Delete dir right after, just allocate name.
ShellJS.rm("-rf", dir);
ShellJS.popd();
var path = Path.join(ShellJS.tempdir(), dir);
output.info("Testing dummy project in " + path);
var dummyPackageId = "com.example.foo";
var dummyLog = "";
var sdk = new AndroidSDK(app);
// Progress display
var indicator = output.createInfiniteProgress("Building " + dummyPackageId);
sdk.onData = function(data) {
dummyLog += data;
// Scan first 7 chars if data starts with a [tag]
var tag = null;
for (var i = 0; i < 7 && i < data.length; i++) {
if (data[i] === '[') {
// Scan on a bit if there's a closing ']'
for (j = i+1; j < i+15; j++) {
if (data[j] === ']') {
tag = data.substring(i+1, j);
indicator.update(tag);
return;
}
}
} else if (data[i] != ' ') {
break;
}
}
};
sdk.queryTarget(AndroidPlatform.MIN_API_LEVEL,
function(apiTarget, errormsg) {
if (errormsg) {
callback(errormsg);
return;
}
sdk.generateProjectSkeleton(path, dummyPackageId, apiTarget,
function (path, logmsg, errormsg) {
dummyLog += logmsg;
if (!path || errormsg) {
output.error(errormsg);
ShellJS.rm("-rf", path);
output.error("Generating project failed");
if (dummyLog) {
FS.writeFileSync(path, dummyLog);
output.error("Consult logfile " + path);
}
callback(false);
return;
}
// Build
ShellJS.pushd(path);
sdk.buildProject(false,
function(success) {
ShellJS.popd();
ShellJS.rm("-rf", path);
indicator.done();
if (!success) {
output.error("Building project failed");
if (dummyLog) {
FS.writeFileSync(path, dummyLog);
output.error("Consult logfile " + path);
}
}
callback(success);
});
});
});
};
/**
* Fill template files and put them into the project skeleton.

@@ -93,3 +242,4 @@ * @param {String} apiTarget Android API target (greater android-14)

"packageName" : this.packageId,
"apiTarget" : apiTarget
"apiTarget" : apiTarget,
"xwalkLibrary" : this._shared ? "xwalk_shared_library" : "xwalk_core_library"
};

@@ -110,6 +260,5 @@

// Make html5 app dir and copy sample content
var assetsPath = Path.join(platformPath, "assets");
ShellJS.mkdir("-p", assetsPath);
var wwwPath = Path.join(assetsPath, "www");
ShellJS.ln("-s", this.appPath, wwwPath);
var wwwPath = Path.join(platformPath, "assets", "www");
ShellJS.mkdir("-p", wwwPath);
ShellJS.cp("-rf", this.appPath + Path.sep + "*", wwwPath);

@@ -129,2 +278,5 @@ // TODO check for errors

// Namespace util
var util = this.application.util;
var output = this.application.output;

@@ -137,3 +289,3 @@

try {
zip = new CrosswalkZip(crosswalkPath);
zip = new util.CrosswalkZip(crosswalkPath);
} catch (e) {

@@ -165,8 +317,11 @@ // HACK we're in the midst of a progress display, force line break

// Extract xwalk_core_library
// Extract xwalk_core_library or xwalk_shared_library
var path;
var name = zip.root + "xwalk_core_library/";
var xwalkLibrary = this._shared ?
"xwalk_shared_library" :
"xwalk_core_library";
var name = zip.root + xwalkLibrary + "/";
entry = zip.getEntry(name);
if (entry) {
path = platformPath + Path.sep + "xwalk_core_library";
path = Path.join(platformPath, xwalkLibrary);
// Remove existing dir to prevent stale files when updating crosswalk

@@ -181,5 +336,11 @@ ShellJS.rm("-rf", path);

// Extract jars
indicator.update(0.5);
// Update project properties
var props = new ProjectProperties(Path.join(this.platformPath, "project.properties"), output);
props.androidLibraryReference1 = xwalkLibrary;
props = new ProjectProperties(Path.join(this.platformPath, xwalkLibrary, "project.properties"), output);
props.target = this._apiTarget;
indicator.update(0.6);

@@ -254,3 +415,16 @@

if (AndroidDependencies.CHANNELS.indexOf(versionSpec) > -1) {
if (ShellJS.test("-f", versionSpec)) {
// versionSpec is a filename, import directly
var filename = Path.normalize(Path.resolve(versionSpec));
output.info("Using " + versionSpec);
errormsg = null;
var importedVersion = this.importCrosswalkFromZip(filename, platformPath);
if (!importedVersion) {
errormsg = "Failed to extract " + filename;
}
callback(importedVersion, errormsg);
return;
} else if (AndroidDependencies.CHANNELS.indexOf(versionSpec) > -1) {
// versionSpec is a channel name

@@ -262,2 +436,3 @@ channel = versionSpec;

// Download
this.findCrosswalkVersion(version, channel,

@@ -307,4 +482,7 @@ function(version, channel, errormsg) {

var minApiLevel = 21;
this._sdk.queryTarget(minApiLevel,
if (args.shared) {
this._shared = true;
}
this._sdk.queryTarget(AndroidPlatform.MIN_API_LEVEL,
function(apiTarget, errormsg) {

@@ -317,2 +495,3 @@

this._apiTarget = apiTarget;
output.info("Building against API level " + apiTarget);

@@ -437,14 +616,25 @@

this.importCrosswalk(versionSpec, this.platformPath,
function(version, errormsg) {
var sdk = new AndroidSDK(this.application);
sdk.queryTarget(AndroidPlatform.MIN_API_LEVEL,
function(apiTarget, errormsg) {
if (errormsg) {
output.error(errormsg);
callback("Updating crosswalk to '" + version + "' failed");
callback(errormsg);
return;
}
this._apiTarget = apiTarget;
output.info("Project updated to crosswalk '" + version + "'");
callback(null);
});
this.importCrosswalk(versionSpec, this.platformPath,
function(version, errormsg) {
if (errormsg) {
output.error(errormsg);
callback("Updating crosswalk to '" + version + "' failed");
return;
}
output.info("Project updated to crosswalk '" + version + "'");
callback(null);
});
}.bind(this));
};

@@ -469,3 +659,10 @@

if (!ShellJS.test("-d", "xwalk_core_library/libs")) {
// There is no need to enable/disable various ABIs when building shared.
// Only one APK is being built.
if (this._shared) {
return true;
}
var libsDir = "xwalk_core_library/libs";
if (!ShellJS.test("-d", libsDir)) {
output.error("This does not appear to be the root of a Crosswalk project.");

@@ -475,3 +672,3 @@ return false;

ShellJS.pushd("xwalk_core_library/libs");
ShellJS.pushd(libsDir);

@@ -521,9 +718,9 @@ var abiMatched = false;

if (release) {
apkInPattern = "*-release-unsigned.apk";
apkInPattern = "-release-unsigned.apk";
} else {
apkInPattern = "*-debug.apk";
apkInPattern = "-debug.apk";
}
ShellJS.pushd("bin");
var apkInName = ShellJS.ls(apkInPattern)[0];
var apkInName = ShellJS.ls("*" + apkInPattern)[0];
ShellJS.popd();

@@ -536,4 +733,7 @@

var base = apkInName.substring(0, apkInName.length - ".apk".length);
var apkOutName = base + "." + abi + ".apk";
var base = apkInName.substring(0, apkInName.length - apkInPattern.length);
var apkOutName = base + "-" +
this.application.manifest.appVersion + "-" +
(release ? "release-unsigned" : "debug") + "." +
abi + ".apk";
ShellJS.mv("bin" + Path.sep + apkInName,

@@ -569,2 +769,3 @@ "bin" + Path.sep + apkOutName);

var abiCodes = {
"shared": 2, // use same as ARM, TODO check if correct.
"armeabi-v7a": 2,

@@ -723,31 +924,81 @@ // "arm64": 3, TODO check name

/**
* Update icons from the manifest.
* Apply icon if none yet, or source has higher quality
* @param {String} srcPath Icon to apply
* @param {String} dstDir Path to destination directory
* @param {String} iconFilename Destination icon filename without extension
* @param {Function} callback Error callback
* @returns {Boolean} True if applied, otherwise false.
*/
AndroidPlatform.prototype.updateManifest =
function(callback) {
AndroidPlatform.prototype.applyIcon =
function(srcPath, dstDir, iconFilename, callback) {
var output = this.application.output;
var manifest = new AndroidManifest(output,
Path.join(this.platformPath, "AndroidManifest.xml"));
// Different image types get different priorities.
var score = {
"png": 3,
"jpeg": 2,
"jpg": 2,
"gif": 1
};
// Renaming package is not supported.
if (manifest.package !== this.application.manifest.packageId) {
callback("Renaming of package not supported (" +
manifest.package + "/" + this.application.manifest.packageId + ")");
return;
// extname() includes the ".", so strip it
var srcExt = Path.extname(srcPath);
if (srcExt && srcExt[0] === ".")
srcExt = srcExt.substring(1);
var srcScore = score[srcExt.toLowerCase()];
if (!srcScore) {
output.warning("Image type not supported: " + srcPath);
return false;
}
manifest.versionName = this.application.manifest.appVersion;
manifest.applicationLabel = this.application.manifest.name;
// Replace existing icon if we have a better one.
var curPath = null;
var curScore = -1;
var ls = ShellJS.ls(Path.join(dstDir, iconFilename + "*"));
if (ls.length > 1) {
output.warning("Unexpected extra files in " + dstDir);
}
if (ls.length > 0) {
// Update icons
// extname() includes the ".", so strip it
curPath = ls[0];
var curExt = Path.extname(curPath);
if (curExt && curExt[0] === ".")
curExt = curExt.substring(1);
curScore = +score[curExt.toLowerCase()];
}
if (srcScore >= curScore) {
if (curPath) {
// We have found a better quality icon
ShellJS.rm(curPath);
}
var dstPath = Path.join(dstDir, iconFilename + Path.extname(srcPath));
ShellJS.cp("-f", srcPath, dstPath);
}
return true;
};
/**
* Update launcher icons.
* @param {AndroidManifest} androidManifest
* @param {Function} callback Error callback
*/
AndroidPlatform.prototype.updateIcons =
function(androidManifest, callback) {
var output = this.application.output;
// See http://iconhandbook.co.uk/reference/chart/android/
var sizes = {
"ldpi": 47,
"mdpi": 71,
"hdpi": 95,
"xhdpi": 143,
"xxhdpi": 191,
"xxxhdpi": 511, // whatever, this is default for even bigger icons.
"ldpi": 36,
"mdpi": 48,
"hdpi": 72,
"xhdpi": 96,
"xxhdpi": 144,
"xxxhdpi": 192,
match: function(size) {

@@ -760,11 +1011,17 @@

// Match size as per categories above.
for (var prop in this) {
if (this[prop] >= size) {
// Start from the biggest size, and pick the first
// one where the icon is bigger or same.
var keys = Object.keys(this);
for (var k = keys.length - 1; k >= 0; k--) {
var prop = keys[k];
if (size >= this[prop]) {
return prop;
}
}
return "xxxhdpi";
// Default to smallest size when below 36.
return "ldpi";
}
};
var nUpdated = 0;
var iconFilename = "crosswalk_icon";

@@ -791,17 +1048,109 @@

var dstPath = Path.join(this.platformPath, "res", "mipmap-" + density);
var dst = Path.join(dstPath, iconFilename + Path.extname(icon.src));
ShellJS.mkdir(dstPath);
ShellJS.cp(src, dst);
var ret = this.applyIcon(src, dstPath, iconFilename, callback);
if (ret)
nUpdated++;
}
}
manifest.applicationIcon = "@mipmap/" + iconFilename;
if (nUpdated > 0) {
androidManifest.applicationIcon = "@mipmap/" + iconFilename;
} else {
output.warning("No usable icons found in manifest.json");
output.warning("Using builtin default icon");
} else {
output.warning("No icons found in manifest.json");
// Fall back to the default icon
manifest.applicationIcon = "@drawable/crosswalk";
androidManifest.applicationIcon = "@drawable/crosswalk";
// Make sure the icon is present.
ShellJS.cp(Path.join(__dirname, "..", "..", "app-template", "icon.png"),
Path.join(this.platformPath, "res", "drawable-hdpi", "crosswalk.png"));
}
return nUpdated;
};
/**
* Configure crosswalk runtime.
*/
AndroidPlatform.prototype.updateEngine =
function() {
var output = this.application.output;
// Write command-line params file.
var path = Path.join(this.platformPath, "assets", "xwalk-command-line");
if (this.application.manifest.commandLine) {
// Write file.
output.info("Writing command-line parameters file");
var commandLine = "xwalk " + this.application.manifest.commandLine;
FS.writeFileSync(path, commandLine);
} else {
// Delete file to make sure there's not a stale one
ShellJS.rm(path);
}
};
/**
* Update android manifest.
* @param {Function} callback Error callback
*/
AndroidPlatform.prototype.updateManifest =
function(callback) {
var output = this.application.output;
var manifest = new AndroidManifest(output,
Path.join(this.platformPath, "AndroidManifest.xml"));
// Renaming package is not supported.
if (manifest.package !== this.application.manifest.packageId) {
callback("Renaming of package not supported (" +
manifest.package + "/" + this.application.manifest.packageId + ")");
return;
}
manifest.versionName = this.application.manifest.appVersion;
manifest.applicationLabel = this.application.manifest.name;
// Update icons
this.updateIcons(manifest, callback);
// Update orientation
switch (this.application.manifest.orientation) {
case "any":
manifest.screenOrientation = "unspecified";
break;
case "natural":
manifest.screenOrientation = "sensor";
break;
case "landscape":
manifest.screenOrientation = "sensorLandscape";
break;
case "portrait":
manifest.screenOrientation = "sensorPortrait";
break;
case "portrait-primary":
manifest.screenOrientation = "portrait";
break;
case "portrait-secondary":
manifest.screenOrientation = "reversePortrait";
break;
case "landscape-primary":
manifest.screenOrientation = "landscape";
break;
case "landscape-secondary":
manifest.screenOrientation = "reverseLandscape";
break;
default:
output.warning("Unsupported orientation value in web manifest: " + this.application.manifest.orientation);
}
// Update permissions
manifest.permissions = this.application.manifest.androidPermissions;
};
/**
* Update java activity file for build config.

@@ -854,2 +1203,208 @@ * @param {Boolean} release True if release build, false if debug

/**
* Convert assets to webp format
*/
AndroidPlatform.prototype.updateWebApp =
function() {
var output = this.application.output;
// Always copy over the app tree to the android project
var wwwPath = Path.join(this.platformPath, "assets", "www");
ShellJS.rm("-rf", wwwPath + Path.sep + "*");
output.info("Copying app to " + wwwPath);
ShellJS.cp("-rf", this.appPath + Path.sep + "*", wwwPath);
var params = this.application.manifest.androidWebp;
if (!params) {
// No webp conversion needed.
return;
}
output.info("Converting image assets to webp format (" + params + ")");
// Check for conversion tool
var cwebp = ShellJS.which("cwebp");
output.info("Checking for cwebp ... " + cwebp);
if (!cwebp) {
output.warning("Webp conversion tool not found, install from http://downloads.webmproject.org/releases/webp");
output.warning("Webp conversion failed, packaging unconverted assets");
return;
}
// Quality parameters
var jpegQuality = 80;
var pngQuality = 80;
var pngAlphaQuality = 80;
var argsList = [];
if (typeof params === "string")
argsList = params.split(/[ ,]+/);
if (argsList && argsList.length > 0)
jpegQuality = argsList[0];
if (argsList && argsList.length > 1)
pngQuality = argsList[1];
if (argsList && argsList.length > 2)
pngAlphaQuality = argsList[2];
// Directory traversal function
function walk(dir) {
var results = [];
var list = FS.readdirSync(dir);
list.forEach(function(file) {
file = dir + "/" + file;
var stat = FS.statSync(file);
if (stat && stat.isDirectory())
results = results.concat(walk(file));
else
results.push(file);
});
return results;
}
// Do conversion
var fileList = walk(wwwPath);
var progress = output.createInfiniteProgress("Converting images to webp");
for (var i in fileList) {
if (FS.lstatSync(fileList[i]).isFile()) {
var filePath = fileList[i];
var tmpFilePath = filePath + ".webp";
var ext = Path.extname(filePath);
progress.update(filePath);
if (".jpeg" == ext || ".jpg" == ext) {
execSync(cwebp +
" " + filePath +
" -q " + jpegQuality +
" -o " + tmpFilePath);
ShellJS.mv("-f", tmpFilePath, filePath);
} else if (".png" == ext) {
execSync(cwebp +
" " + filePath +
" -q " + pngQuality +
" -alpha_q " + pngAlphaQuality +
" -o " + tmpFilePath);
ShellJS.mv("-f", tmpFilePath, filePath);
}
}
}
progress.done();
var logOutput = this.logOutput;
var execSyncImpl;
function execSync(cmd) {
// On first run, work out which implementation to use.
if (typeof execSyncImpl === "undefined") {
if (ChildProcess.execSync) {
// Nodejs >= 0.12
execSyncImpl = ChildProcess.execSync;
} else {
// Try to use npm module.
try {
// Exec-sync does throw even though it works, so let's use this hack,
// it's just for nodejs 0.10 compat anyway.
execSyncImpl = function(cmd) { try { return require("exec-sync")(cmd); } catch (e) {} return null; };
} catch (e) {
output.error("NPM module 'exec-sync' not found");
output.error("Please install this package manually when on nodejs < 0.12");
execSyncImpl = null;
}
}
}
if (execSyncImpl !== null) {
var ret = execSyncImpl(cmd);
if (ret) {
logOutput.write(cmd + "\n" + ret + "\n");
}
}
}
};
/**
* Import extensions.
* The directory of one external extension should be like:
* myextension/
* myextension.jar
* myextension.js
* myextension.json
* That means the name of the internal files should be the same as the
* directory name.
* For .jar files, they'll be copied to libs/ and then
* built into classes.dex in the APK.
* For .js files, they'll be copied into assets/xwalk-extensions/.
* For .json files, the'll be merged into one file called
* extensions-config.json and copied into assets/.
*/
AndroidPlatform.prototype.importExtensions =
function() {
var output = this.application.output;
var extensionsConfig = [];
var extensionsPerms = [];
this.application.manifest.extensions.forEach(function (extPath) {
// Test integrity
if (!ShellJS.test("-d", extPath)) {
output.warning("Skipping invalid extension dir " + extPath);
return;
}
var extName = Path.basename(extPath);
var jarPath = Path.join(extPath, extName + ".jar");
if (!ShellJS.test("-f", jarPath)) {
output.warning("Skipping extension, file not found " + jarPath);
return;
}
var jsPath = Path.join(extPath, extName + ".js");
if (!ShellJS.test("-f", jsPath)) {
output.warning("Skipping extension, file not found " + jsPath);
return;
}
var jsonPath = Path.join(extPath, extName + ".json");
if (!ShellJS.test("-f", jsonPath)) {
output.warning("Skipping extension, file not found " + jsonPath);
return;
}
// Copy
ShellJS.cp("-f", jarPath, Path.join(this.platformPath, "libs"));
var jsDstPath = Path.join(this.platformPath, "assets", "xwalk-extensions");
ShellJS.mkdir(jsDstPath);
ShellJS.cp("-f", jsPath, jsDstPath);
// Accumulate config
var jsonBuf = FS.readFileSync(jsonPath, {"encoding": "utf8"});
var configJson = JSON.parse(jsonBuf);
configJson.jsapi = [ "xwalk-extensions", configJson.jsapi ].join("/");
extensionsConfig.push(configJson);
// Accumulate permissions
for (var i = 0; configJson.permissions && i < configJson.permissions.length; i++) {
var perm = configJson.permissions[i];
// Support both android.permission.FOO namespaced and plain
// version by using last component.
perm = perm.split(".").pop();
extensionsPerms.push(perm);
}
}.bind(this));
// Write config
if (extensionsConfig.length > 0) {
var configJsonPath = Path.join(this.platformPath, "assets", "extensions-config.json");
FS.writeFileSync(configJsonPath, FormatJson.plain(extensionsConfig));
}
// Add permissions to manifest, so they end up in AndroidManifest.xml later
extensionsPerms.forEach(function (perm) {
var perms = this.application.manifest.androidPermissions;
if (perms.indexOf(perm) < 0) {
perms.push(perm);
}
}.bind(this));
};
/**
* Implements {@link PlatformBase.build}

@@ -865,7 +1420,15 @@ */

// Embedded or shared build?
if (ShellJS.test("-d", Path.join(this.platformPath, "xwalk_shared_library"))) {
this._shared = true;
}
this.updateEngine();
this.importExtensions();
this.updateManifest(callback);
this.updateJavaActivity(configId === "release");
this.updateWebApp(this.application.manifest.androidWebp);
var closure = {
abis: ["armeabi-v7a", "x86"], // TODO export option
abis: this._shared ? ["shared"] : ["armeabi-v7a", "x86"], // TODO export option
abiIndex : 0,

@@ -887,4 +1450,8 @@ release: configId == "release", // TODO verify above

output.highlight(" + " + closure.apks[i]);
output.write(" + " + closure.apks[i] + "\n");
}
if (configId === "release") {
output.highlight(" Sign APKs before publishing: " +
"https://developer.android.com/tools/publishing/app-signing.html#signing-manually");
}
}

@@ -891,0 +1458,0 @@ callback(errormsg);

@@ -167,8 +167,10 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

var child = ChildProcess.execFile(this._scriptPath, args, {},
function(errmsg, stdlog, errlog) {
function(error, stdlog, errlog) {
errlog = this.filterErrorLog(errlog);
if (errlog && !errmsg) {
// Pass back errlog output as error message.
errmsg = errlog;
errmsg = this.filterErrorLog(errlog);
if (error && error.message) {
errmsg += error.message;
indicator.done("error");
} else {
indicator.done();
}

@@ -185,3 +187,2 @@

indicator.done();
callback(path, stdlog, errmsg);

@@ -266,3 +267,4 @@ return;

}
SDKNotFoundError.prototype = Error.prototype;
SDKNotFoundError.prototype = Object.create(Error.prototype);
SDKNotFoundError.prototype.constructor = SDKNotFoundError;

@@ -269,0 +271,0 @@ AndroidSDK.prototype.SDKNotFoundError = SDKNotFoundError;

@@ -14,2 +14,3 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

* @param {String} path Path to android app's main java activity file
* @constructor
*/

@@ -208,3 +209,3 @@ function JavaActivity(output, path) {

found = false;
while (lines[i] !== " }") {
while (lines[i] !== " super.onCreate(savedInstanceState);") {
outBuf.push(lines[i]);

@@ -211,0 +212,0 @@ i++;

@@ -13,2 +13,3 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

* @param {String} path Path to manifest.json
* @constructor
*/

@@ -15,0 +16,0 @@ function XmlTheme(output, path) {

@@ -134,3 +134,57 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

test.done();
},
permissions: function(test) {
test.expect(4);
var manifest;
var path = createManifest();
manifest = new AndroidManifest(_output, path);
manifest.permissions = ["CAMERA", "INTERNET"];
manifest = new AndroidManifest(_output, path);
var permissions = manifest.permissions;
test.equal(permissions instanceof Array, true);
test.equal(permissions.length === 2, true);
test.equal(permissions.indexOf("CAMERA") > -1, true);
test.equal(permissions.indexOf("INTERNET") > -1, true);
ShellJS.rm("-f", path);
test.done();
},
screenOrientation: function(test) {
test.expect(18);
var manifest;
var path = createManifest();
manifest = new AndroidManifest(_output, path);
// Default
test.equal(manifest.screenOrientation, "unspecified");
var values = ["unspecified", "behind",
"landscape", "portrait",
"reverseLandscape", "reversePortrait",
"sensorLandscape", "sensorPortrait",
"userLandscape", "userPortrait",
"sensor", "fullSensor", "nosensor",
"user", "fullUser", "locked"];
values.forEach(function (value) {
// Test write, then read and compare.
manifest.screenOrientation = value;
test.equal(manifest.screenOrientation, value);
});
manifest.screenOrientation = "unspecified";
// Test bogus value
manifest.screenOrientation = "foo";
test.equal(manifest.screenOrientation, "unspecified");
ShellJS.rm("-f", path);
test.done();
}
};
{
"name": "crosswalk-app-tools",
"version": "0.6.1",
"version": "0.7.0",
"description": "An APK packager for the Crosswalk Project -- http://crosswalk-project.org",
"author": "Robert Staudinger <robert.staudinger@intel.com>",
"license": "Apache V2",
"license": "Apache-2.0",
"engines" : {
"node" : ">=0.12"
},
"bin": {
"crosswalk-app": "./src/crosswalk-app"
"crosswalk-app": "./src/crosswalk-app",
"crosswalk-pkg": "./src/crosswalk-pkg"
},

@@ -25,3 +29,6 @@ "scripts": {

"mustache": "~0.8.2",
"node-uuid": "~1.4.3",
"readdir": "~0.0.13",
"shelljs": "~0.3.0",
"xmlbuilder": "~2.6.4",
"xmldom": "~0.1.19"

@@ -33,5 +40,5 @@ },

"grunt-contrib-nodeunit": "~0.4.1",
"grunt-jsdoc": "~0.4.2",
"grunt-jsdoc": "~0.6.7",
"grunt-release": "~0.9.0",
"jsdoc": "https://github.com/jsdoc3/jsdoc/archive/v3.2.2.tar.gz",
"jsdoc": "~3.3.2",
"nodeunit": "~0.9.0"

@@ -59,4 +66,5 @@ },

"test",
"test-util"
"test-util",
"windows"
]
}
Crosswalk-app-tools
===================
Command line tools to create and package Crosswalk applications. The license for this project is Apache License
Version 2.0, please refer to the LICENSE-APACHE-V2 included with the package.
Crosswalk-app-tools is our forthcoming packaging tool for creating Crosswalk applications. We are inviting early adopters to build their web applications using crosswalk-app-tools, and provide feedback for future improvements.

@@ -12,75 +9,91 @@

Crosswalk-app-tools is cross-platform by virtue of being based on Node.js. We are supporting Microsoft Windows, Apple OS X and Linux (testing is mostly done on Fedora and Ubuntu distributions).
The tools are cross-platform by virtue of being based on Node.js. We are supporting Microsoft Windows, Apple OS X and Linux as host operating systems.
The following components are required
1. Android SDK with 5.0 (target-21) installed
2. Java JDK and Apache Ant
3. Node.js and NPM
1. Node.js and NPM
2. Android SDK with 5.0 (target-21) or later installed, plus Java JDK and Apache Ant for creating Android APK packages
In order to get the tools available from the command-line easily, global npm installation is recommended.
Microsoft Windows: `npm install -g crosswalk-app-tools`
Apple OS X and Linux: `sudo npm install -g crosswalk-app-tools`
The best way to check if a machine has all the required dependencies is to create and build a plain empty Android app
on the system. If this does not work, then building Crosswalk apps will not succeed either.
on the system. If this does not work, then building Crosswalk apps will not succeed either. App-tools provides a command for doing this:
```
android create project -a MainActivity -k com.example.foo -p com.example.foo -t android-21
cd com.example.foo
ant debug
crosswalk-app check android
```
In order to get the `crosswalk-app` script available everywhere, global npm installation is required.
```
Microsoft Windows: npm install -g crosswalk-app-tools
Apple OS X and Linux: sudo npm install -g crosswalk-app-tools
```
Two executables are provided, `crosswalk-app` implements low level helper commands, `crosswalk-pkg` is the main tool for creating packages.
### Usage
```
Crosswalk Project Application Packaging Tool
Crosswalk Project Packaging Tool -- https://crosswalk-project.org
Usage: crosswalk-pkg <options> <path>
crosswalk-app create <package-id> Create project <package-id>
--platforms=<target> Optional, e.g. "windows"
<options>
-c --crosswalk=<version-spec>: Runtime version
-h --help: Print usage information
-p --platforms=<android|windows>: Target platform
-r --release=true: Build release packages
-v --version: Print tool version
crosswalk-app build [release|debug] [<dir>] Build project to create packages
Defaults to "debug" when not given
Tries to build in current dir by default
<path>
Path to directory that contains a web app
crosswalk-app update <channel>|<version> Update Crosswalk to latest in named
channel, or specific version
<version-spec>
* Channel name, i.e. "stable". "beta", or "canary"
* Version number, e.g. 14.43.343.25
* Path to release, e.g. $HOME/Downloads/crosswalk-14.43.343.25.zip
crosswalk-app platforms List available target platforms
Environment variables
CROSSWALK_APP_TOOLS_CACHE_DIR=<path>: Keep downloaded files in this dir
```
### Example: Creating and packaging an application
crosswalk-app help Display usage information
To get started, all you need is a web manifest, and an html file. The web manifest holds name and settings for your application. A minimal manifest.json looks like this:
```
{
"name": "My first Crosswalk application",
"start_url": "index.html",
"xwalk_package_id": "com.example.foo"
}
```
crosswalk-app version Display version information
Then add an index.html in the same directory:
```
<html>
<head>
<title>My first Crosswalk application</title>
</head>
<body>This is my first Crosswalk application</body>
</html>
```
Options for platform 'android'
For command 'create'
--android-crosswalk Channel name (stable/beta/canary)
or version number (w.x.y.z)
Environment variables for platform 'android'
CROSSWALK_APP_TOOLS_CACHE_DIR Keep downloaded files in this dir
Finally, time to create the apk package:
```
#### Example: Create App
`crosswalk-app create com.example.foo`: This sets up a skeleton project in directory com.example.foo/, downloads and imports Crosswalk, and puts a sample "hello world" web app under com.example.foo/app/.
crosswalk-pkg <path>
```
This sets up a skeleton project, downloads and imports Crosswalk, and creates a package using the files above.
#### Example: Build App
`cd com.example.foo` and then `crosswalk-app build` builds packages. The APKs can be found in the current directory when done.
#### Example: Update Crosswalk
`crosswalk-app update stable` updates Crosswalk to the latest version available in the stable channel.
### Next steps and limitations
* Android release packages will have to be signed manually before they are published on Google's Play Store, as that functionality is not yet integrated. See https://developer.android.com/tools/publishing/app-signing.html#signing-manually for details.
* We encourage everyone to use this app-tools and appreciate feedback, as we are looking to improve user friendliness and integration with Crosswalk in the coming releases.
### Additional target platforms
There is forthcoming support for additional target platforms. For iOS packaging, see
https://github.com/crosswalk-project/crosswalk-app-tools-ios, Windows support is planned for the 0.8 release.
### Limitations
* Android release packages will have to be signed manually before they are published on Google's Play Store, as that functionality is not yet integrated.
* This is alpha stage software and under continuous development. We encourage trying it and appreciate feedback, but use in a production environment is not supported at this point in time.
### Run development versions from git
1. Download: `npm install https://github.com/crosswalk-project/crosswalk-app-tools.git`
4. The main script is `crosswalk-app-tools/src/crosswalk-pkg`. Set environment PATH or invoke with directory.
### Run development versions from git
1. Download: `git clone https://github.com/crosswalk-project/crosswalk-app-tools.git`
3. Install dependencies: `cd crosswalk-app-tools`, then `npm install`, and `cd ..`
4. The main script is `crosswalk-app-tools/src/crosswalk-app`. Set environment PATH or invoke with directory.
### License
The license for this project is the Apache License Version 2.0, please refer to the LICENSE-APACHE-V2 included with the package for details.

@@ -12,5 +12,5 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

var IllegalAccessException = require("./util/exceptions").IllegalAccessException;
var InvalidPathException = require("./util/exceptions").InvalidPathException;
var LogfileOutput = require("./LogfileOutput");
var Manifest = require("./Manifest");
var OutputIface = require("./OutputIface");
var OutputTee = require("./OutputTee");

@@ -26,3 +26,3 @@ var TerminalOutput = require("./TerminalOutput");

* @param {String} [packageId] Package ID in com.example.foo format, or null
* @throws {InvalidPathException} If packageId not passed and current working dir not a project.
* @throws {Error} If packageId not passed and current working dir not a project.
* @protected

@@ -32,9 +32,13 @@ */

var output = TerminalOutput.getInstance();
// cwd must be absolute and exist.
if (!cwd ||
Path.resolve(cwd) != Path.normalize(cwd)) {
throw new InvalidPathException("Path not absolute: " + cwd);
output.error("Path not absolute: " + cwd);
throw new Error("Path not absolute: " + cwd);
}
if (!ShellJS.test("-d", cwd)) {
throw new InvalidPathException("Path does not exist: " + cwd);
output.error("Path does not exist: " + cwd);
throw new Error("Path does not exist: " + cwd);
}

@@ -50,3 +54,4 @@

if (ShellJS.test("-d", rootPath)) {
throw new InvalidPathException("Failed to create project, path already exists: " + rootPath);
output.error("Failed to create project, path already exists: " + rootPath);
throw new Error("Failed to create project, path already exists: " + rootPath);
}

@@ -62,6 +67,7 @@

// Get packageId from manifest
var manifest = new Manifest(this._output, Path.join(cwd, "app", "manifest.json"));
var manifest = new Manifest(TerminalOutput.getInstance(), Path.join(cwd, "app", "manifest.json"));
this._packageId = manifest.packageId;
if (!this._packageId) {
throw new InvalidPathException("Path does not seem to be a project toplevel: " + cwd);
output.error("Path does not seem to be a project toplevel: " + cwd);
throw new Error("Path does not seem to be a project toplevel: " + cwd);
}

@@ -74,15 +80,20 @@

if (!ShellJS.test("-d", this._rootPath)) {
throw new InvalidPathException("Failed to load, invalid path: " + this._rootPath);
output.error("Failed to load, invalid path: " + this._rootPath);
throw new Error("Failed to load, invalid path: " + this._rootPath);
}
if (!ShellJS.test("-d", this._appPath)) {
throw new InvalidPathException("Failed to load, invalid path: " + this._appPath);
output.error("Failed to load, invalid path: " + this._appPath);
throw new Error("Failed to load, invalid path: " + this._appPath);
}
if (!ShellJS.test("-d", this._logPath)) {
throw new InvalidPathException("Failed to load, invalid path: " + this._logPath);
output.error("Failed to load, invalid path: " + this._logPath);
throw new Error("Failed to load, invalid path: " + this._logPath);
}
if (!ShellJS.test("-d", this._pkgPath)) {
throw new InvalidPathException("Failed to load, invalid path: " + this._pkgPath);
output.error("Failed to load, invalid path: " + this._pkgPath);
throw new Error("Failed to load, invalid path: " + this._pkgPath);
}
if (!ShellJS.test("-d", this._prjPath)) {
throw new InvalidPathException("Failed to load, invalid path: " + this._prjPath);
output.error("Failed to load, invalid path: " + this._prjPath);
throw new Error("Failed to load, invalid path: " + this._prjPath);
}

@@ -99,5 +110,9 @@

this._manifest = new Manifest(this._output, Path.join(this._appPath, "manifest.json"));
this.loadManifest(Path.join(this._appPath, "manifest.json"));
}
/**
* Initialize paths.
* @param {String} rootPath Root path inside the project
*/
function initMembers(rootPath) {

@@ -122,2 +137,16 @@

/**
* Load web manifest.
* @param {String} path Path to web manifest file
*/
Application.prototype.loadManifest =
function(path) {
if (!ShellJS.test("-f", path)) {
throw new Error("File not found: ", path);
}
this._manifest = new Manifest(this._output, path);
};
/**
* Package identifier in reverse host format, i.e. com.example.foo.

@@ -272,3 +301,7 @@ * @member {String} packageId

set: function(output) {
throw new IllegalAccessException("Attempting to write read-only property Application.output");
if (output instanceof OutputIface) {
this._output = output;
} else {
throw new IllegalAccessException("Application.output must implement OutputIface");
}
}

@@ -275,0 +308,0 @@ });

@@ -8,2 +8,3 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

var Minimist = require("minimist");
var ShellJS = require("shelljs");

@@ -38,2 +39,5 @@ /**

"\n" +
" crosswalk-app check [<platforms>] Check host setup\n" +
" Check all platforms if none given\n" +
"\n" +
" crosswalk-app create <package-id> Create project <package-id>\n" +

@@ -46,4 +50,5 @@ " --platforms=<target> Optional, e.g. \"windows\"\n" +

"\n" +
" crosswalk-app update <channel>|<version> Update Crosswalk to latest in named\n" +
" crosswalk-app update [<version>] [<dir>] Update Crosswalk to latest in named\n" +
" channel, or specific version\n" +
" Version is \"stable\" when not given" +
"\n" +

@@ -67,2 +72,4 @@ " crosswalk-app platforms List available target platforms\n" +

switch (cmd) {
case "check":
return cmd;
case "create":

@@ -73,3 +80,3 @@ var packageId = this.createGetPackageId();

var version = this.updateGetVersion();
if (version === false) {
if (!version) {
// Error: version could not be parsed.

@@ -114,3 +121,3 @@ return null;

if (["create", "update", "refresh", "build", "platforms"].indexOf(command) > -1) {
if (["check", "create", "update", "refresh", "build", "platforms"].indexOf(command) > -1) {
return command;

@@ -123,2 +130,16 @@ }

/**
* Get platforms to check the host configuration for.
* @returns {String[]} Array of platform IDs or empty array to check all available platforms.
*/
CommandParser.prototype.checkGetPlatforms =
function() {
// Command goes like this
// node crosswalk-app create platforms*
// So we take everything from the third index
var platforms = this._argv.slice(3);
return platforms;
};
/**
* Get package name when command is "create".

@@ -148,28 +169,53 @@ * @returns {String} Package name as per Android conventions or null.

var errormsg = "Version must be channel 'stable', 'beta', 'canary', or format ab.cd.ef.gh";
// argv is filled like this:
// node crosswalk-app update [version] [dir]
// So argv[3] is either version or dir.
if (this._argv.length < 4) {
return null;
return "stable";
}
var version = this._argv[3];
// Recognise channel name for version
if (["beta", "canary", "stable"].indexOf(version) > -1) {
if (CommandParser.validateVersion(version, null)) {
return version;
}
var match = version.match("[0-9\\.]*");
if (match[0] != version) {
this._output.error(errormsg);
return false;
return null;
};
// FIXME require node 0.12 and use Path.isAbsolute
CommandParser.prototype.isAbsolute =
function(path) {
if (Path.sep === "/" &&
path[0] === Path.sep) {
return true;
}
var parts = version.split('.');
if (parts.length != 4) {
this._output.error(errormsg);
return false;
// Windows
return path.match(/^[a-zA-z]:/) !== null;
};
/**
* Get dir when command is "update". Defaults to current dir.
*/
CommandParser.prototype.updateGetDir =
function() {
// argv is filled like this:
// node crosswalk-app update [version] [dir]
// Dir can only be specified if version is given, though,
// no guessing around here.
if (this._argv.length < 5) {
// Dir not given.
return process.cwd();
}
return version;
var path = this._argv[4];
if (this.isAbsolute(path)) {
return Path.resolve(Path.normalize(path));
}
return Path.resolve(Path.normalize(Path.join(process.cwd(), path)));
};

@@ -277,2 +323,35 @@

/**
* Validate crosswalk version.
* @param {String} version Version string
* @param {OutputIface} [output]
* @returns {Boolean} true if valid, otherwise false.
*/
CommandParser.validateVersion =
function(version, output) {
var errormsg = "Version must be channel 'stable', 'beta', 'canary', or format ab.cd.ef.gh";
// Recognise channel name for version
if (["beta", "canary", "stable"].indexOf(version) > -1) {
return true;
}
var match = version.match("[0-9\\.]*");
if (match[0] != version) {
if (output)
output.error(errormsg);
return false;
}
var parts = version.split('.');
if (parts.length != 4) {
if (output)
output.error(errormsg);
return false;
}
return true;
};
module.exports = CommandParser;

@@ -15,5 +15,18 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

this._label = label;
this._active = false;
}
/**
* Whether the indicator has already been activated (first update() call)
* @member {Boolean} isActive
* @instance
* @memberOf FiniteProgress
*/
Object.defineProperty(FiniteProgress.prototype, "isActive", {
get: function() {
return this._active;
}
});
/**
* Update progress indicator.

@@ -25,2 +38,4 @@ * @param {Number} progress Progress value between 0.0 and 1.0

this._active = true;
// Clamp

@@ -63,4 +78,7 @@ progress = progress < 0 ? 0 :

this._output.write(" " + message + "\n");
this._output.endProgress();
this._active = false;
};
module.exports = FiniteProgress;

@@ -15,5 +15,18 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

this._label = label;
this._active = false;
}
/**
* Whether the indicator has already been activated (first update() call)
* @member {Boolean} isActive
* @instance
* @memberOf InfiniteProgress
*/
Object.defineProperty(InfiniteProgress.prototype, "isActive", {
get: function() {
return this._active;
}
});
/**
* Update progress indicator.

@@ -25,2 +38,4 @@ * @param {String} tag Tag for current activity

this._active = true;
// Clear line

@@ -54,4 +69,7 @@ this._output.write('\033[2K');

this._output.write(line);
this._output.endProgress();
this._active = false;
};
module.exports = InfiniteProgress;

@@ -36,6 +36,5 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

}
LogfileOutput.prototype = Object.create(OutputIface.prototype);
LogfileOutput.prototype.constructor = LogfileOutput;
// FIXME I have no idea why this breaks, something about the singleton maybe?
// LogfileOutput.prototype = OutputIface.prototype;
LogfileOutput.prototype.error =

@@ -42,0 +41,0 @@ function(message) {

@@ -15,6 +15,4 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

var TerminalOutput = require("./TerminalOutput");
var util = require("./util/index.js");
var MAIN_EXIT_CODE_OK = 0;
var MAIN_EXIT_CODE_ERROR = 127;
/**

@@ -42,4 +40,8 @@ * Callback signature for toplevel operations.

}
Main.prototype = Application.prototype;
Main.prototype = Object.create(Application.prototype);
Main.prototype.constructor = Main;
Main.EXIT_CODE_OK = 0;
Main.EXIT_CODE_ERROR = 127;
/* TODO move to android project

@@ -90,2 +92,65 @@ function workingDirectoryIsProject() {

/**
* Have platform implementations check the host setup.
* @param {String[]} platformIds Platforms to check, null or empty array checks all.
* @param {OutputIface} output Output to write to
* @param {Main~mainOperationCb} callback Callback function
* @static
*/
Main.prototype.check =
function(platformIds, output, callback) {
var mgr = new PlatformsManager(output);
var platforms = [];
if (platformIds && platformIds.length > 0) {
platformIds.forEach(function (platformId) {
var errormsg = null;
var platformInfo = mgr.load(platformId,
function (errormsg_) {
errormsg = errormsg_;
});
if (platformInfo) {
platforms.push(platformInfo);
} else {
output.error(errormsg);
output.error("Failed to load platform '" + platformId + "'");
callback(Main.EXIT_CODE_ERROR);
return;
}
});
} else {
platforms = mgr.loadAll();
}
if (!platforms || platforms.length === 0) {
output.error("Failed to load platform modules");
callback(Main.EXIT_CODE_ERROR);
return;
}
function checkPlatform(platformInfo, next) {
if (platformInfo.Ctor.check) {
output.info("Checking host setup for target " + platformInfo.platformId);
platformInfo.Ctor.check(output,
function(success) {
next();
});
} else {
output.warning("Skipping '" + platformInfo.platformId + "': 'check' not implemented");
next();
}
}
util.iterate(platforms, checkPlatform,
function () {
callback(Main.EXIT_CODE_OK);
});
};
/**
* Collect arguments

@@ -126,3 +191,8 @@ */

// for new project.
var platform = extraArgs.platforms;
var platform = null;
if (typeof extraArgs.platforms === "string") {
platform = extraArgs.platforms;
} else if (extraArgs.platforms instanceof Array) {
platform = extraArgs.platforms[0];
}
if (platform) {

@@ -133,3 +203,3 @@ try {

output.error("Invalid target platform '" + platform + "'");
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
return;

@@ -143,3 +213,3 @@ }

output.error("Could not find app template in " + templatePath);
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
return;

@@ -152,3 +222,3 @@ }

if (!project) {
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
return;

@@ -169,6 +239,6 @@ }

output.info("Logfiles at " + this.logPath);
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
return;
} else {
callback(MAIN_EXIT_CODE_OK);
callback(Main.EXIT_CODE_OK);
return;

@@ -193,3 +263,3 @@ }

if (!project) {
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
return;

@@ -210,6 +280,6 @@ }

output.info("Logfiles at " + this.logPath);
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
return;
} else {
callback(MAIN_EXIT_CODE_OK);
callback(Main.EXIT_CODE_OK);
return;

@@ -243,3 +313,3 @@ }

if (!project) {
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
return;

@@ -261,6 +331,6 @@ }

output.info("Logfiles at " + this.logPath);
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
return;
} else {
callback(MAIN_EXIT_CODE_OK);
callback(Main.EXIT_CODE_OK);
return;

@@ -321,3 +391,3 @@ }

if (Object.keys(platformInfo.envSpec).length > 0) {
output.write("Environment variables for platform '" + platformInfo.platformId + "'\n\n");
output.write("\nEnvironment variables for platform '" + platformInfo.platformId + "'\n\n");
for (var env in platformInfo.envSpec) {

@@ -357,2 +427,3 @@ output.write(" " + env + " " + platformInfo.envSpec[env] + "\n");

var app = new Main();
var rootDir = null;

@@ -362,3 +433,3 @@ if (process.argv.length < 3) {

app.printHelp(parser, output);
callback(MAIN_EXIT_CODE_OK);
callback(Main.EXIT_CODE_OK);
return;

@@ -371,3 +442,3 @@ }

output.error("Unhandled command '" + process.argv[2] + "'");
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
return;

@@ -378,14 +449,13 @@ }

switch (cmd) {
case "check":
var platforms = parser.checkGetPlatforms();
app.check(platforms, output, callback);
break;
case "create":
var packageId = parser.createGetPackageId();
try {
// Chain up the constructor.
Application.call(app, process.cwd(), packageId);
app.create(packageId, extraArgs, callback);
} catch (e) {
output.error("Failed to initialize");
output.error("Ensure directory '" + packageId + "' does not already exist");
callback(MAIN_EXIT_CODE_ERROR);
}
// Chain up the constructor.
Application.call(app, process.cwd(), packageId);
app.create(packageId, extraArgs, callback);
break;

@@ -395,12 +465,7 @@

var version = parser.updateGetVersion();
rootDir = parser.updateGetDir();
try {
// Chain up the constructor.
Application.call(app, process.cwd(), null);
app.update(version, extraArgs, callback);
} catch (e) {
output.error("Failed to initialize");
output.error("Ensure to invoke 'crosswalk-app-tools' from a toplevel project directory");
callback(MAIN_EXIT_CODE_ERROR);
}
// Chain up the constructor.
Application.call(app, rootDir, null);
app.update(version, extraArgs, callback);
break;

@@ -410,13 +475,7 @@

var type = parser.buildGetType();
var rootDir = parser.buildGetDir();
rootDir = parser.buildGetDir();
try {
// Chain up the constructor.
Application.call(app, rootDir, null);
app.build(type, extraArgs, callback);
} catch (e) {
output.error("Failed to initialize");
output.error("Ensure to invoke 'crosswalk-app-tools' from a toplevel project directory");
callback(MAIN_EXIT_CODE_ERROR);
}
// Chain up the constructor.
Application.call(app, rootDir, null);
app.build(type, extraArgs, callback);
break;

@@ -438,3 +497,3 @@

output.error("Unhandled command " + cmd);
callback(MAIN_EXIT_CODE_ERROR);
callback(Main.EXIT_CODE_ERROR);
}

@@ -444,1 +503,3 @@ };

module.exports = new Main();
module.exports.EXIT_CODE_OK = Main.EXIT_CODE_OK;
module.exports.EXIT_CODE_ERROR = Main.EXIT_CODE_ERROR;

@@ -6,4 +6,6 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

var FS = require("fs");
var Path = require("path");
var FormatJson = require("format-json");
var ShellJS = require("shelljs");

@@ -17,2 +19,3 @@ var CommandParser = require("./CommandParser");

* @param {String} path Path to manifest.json
* @constructor
*/

@@ -57,3 +60,3 @@ function Manifest(output, path) {

output.error("Invalid app version '" + json.xwalk_app_version + "' in the manifest");
// TODO maybe exception
throw new Error("Invalid app version '" + json.xwalk_app_version + "' in the manifest");
}

@@ -77,2 +80,4 @@

var values;
// Display

@@ -82,3 +87,5 @@ this._display = "standalone";

if (["fullscreen", "standalone"].indexOf(json.display) > -1) {
values = ["fullscreen", "standalone", "minimal-ui", "browser"];
if (values.indexOf(json.display) > -1) {
// supported mode

@@ -91,2 +98,23 @@ this._display = json.display;

// Orientation
this._orientation = "any";
if (json.orientation) {
values = [ "any",
"natural",
"landscape",
"portrait",
"portrait-primary",
"portrait-secondary",
"landscape-primary",
"landscape-secondary" ];
if (values.indexOf(json.orientation) > -1) {
// supported mode
this._orientation = json.orientation;
} else {
output.warning("Unsupported value '" + json.orientation + "' in manifest.json");
}
}
// Start URL

@@ -106,2 +134,12 @@ // TODO check value

// Command line params
this._commandLine = null;
if (json.xwalk_command_line) {
if (typeof json.xwalk_command_line === "string") {
this._commandLine = json.xwalk_command_line;
} else {
output.warning("Invalid command line '" + json.xwalk_command_line + "'");
}
}
// Package ID

@@ -115,2 +153,20 @@ if (json.xwalk_package_id &&

// Extensions
this._extensions = [];
if (json.xwalk_extensions) {
if (json.xwalk_extensions instanceof Array) {
json.xwalk_extensions.forEach(function (path) {
var absPath = Path.resolve(Path.dirname(this._path), path);
absPath = Path.normalize(absPath);
if (ShellJS.test("-e", absPath)) {
this._extensions.push(absPath);
} else {
output.warning("Skipping extension because dir not found: " + absPath);
}
}.bind(this));
} else {
output.warning("Invalid extensions " + json.xwalk_extensions);
}
}
// Target platforms

@@ -151,2 +207,29 @@ if (json.xwalk_target_platforms &&

// Android permissions
this._androidPermissions = Manifest.ANDROID_DEFAULT_PERMISSIONS.concat([]); // clone array
if (json.xwalk_android_permissions) {
if (json.xwalk_android_permissions instanceof Array) {
// Merge permissions to the default ones.
json.xwalk_android_permissions.forEach(function (permission) {
if (this._androidPermissions.indexOf(permission) < 0) {
this._androidPermissions.push(permission);
}
}.bind(this));
} else {
output.warning("Invalid android permissions '" + json.xwalk_android_permissions + "'");
}
}
// Android webp
this._androidWebp = false;
if (json.xwalk_android_webp) {
if (typeof json.xwalk_android_webp === "string") {
// TODO better check
this._androidWebp = json.xwalk_android_webp;
} else {
output.warning("Invalid webp parameters '" + json.xwalk_android_webp + "'");
}
}
// Windows update ID

@@ -186,12 +269,15 @@ // Optional field, only check if present.

/**
* Create manifest at project creation stage.
* @param {OutputIface} output Output implementation
* @param {String} path Path to manifest.json
* Default permissions needed on android.
*/
Manifest.ANDROID_DEFAULT_PERMISSIONS = [ "ACCESS_NETWORK_STATE", "ACCESS_WIFI_STATE", "INTERNET" ];
/**
* Create default manifest data.
* @param {String} packageId Unique package identifier com.example.foo
* @returns {Manifest} Loaded manifest instance.
* @returns {Object} Manifest JSON representation
* @memberOf Manifest
* @static
*/
Manifest.create =
function(path, packageId) {
Manifest.createDefaultJson =
function(packageId) {

@@ -204,8 +290,2 @@ // Emulate old behaviour of using default backend,

// Default icon
var icon = {
src: "icon.png",
sizes: "72x72"
};
// Create windows update id

@@ -226,3 +306,3 @@ // Format is: 12345678-1234-1234-1234-111111111111

var buffer = FormatJson.plain({
return {
// Standard fields

@@ -232,6 +312,7 @@ "name": packageId,

"display": "standalone",
"icons": [ icon ],
"orientation": "any",
"start_url": "index.html",
// Crosswalk fields
"xwalk_app_version": "1",
"xwalk_app_version": "0.1",
"xwalk_command_line": "",
"xwalk_package_id": packageId,

@@ -242,6 +323,61 @@ "xwalk_target_platforms": platformInfo.platformId,

"xwalk_android_keep_screen_on": false,
// Set external storage by default, needed for shared mode/fallback.
"xwalk_android_permissions": Manifest.ANDROID_DEFAULT_PERMISSIONS,
// Windows fields
"xwalk_windows_update_id": windowsUpdateId,
"xwalk_windows_vendor": "(Vendor)" // optional, placeholder
});
"xwalk_windows_update_id": windowsUpdateId
};
};
/**
* Create manifest at project creation stage.
* @param {String} path Path to manifest.json
* @param {String} packageId Unique package identifier com.example.foo
* @memberOf Manifest
* @static
*/
Manifest.create =
function(path, packageId) {
var json = Manifest.createDefaultJson(packageId);
// Default icon
var icon = {
src: "icon.png",
sizes: "72x72"
};
json.icons = [ icon ];
FS.writeFileSync(path, FormatJson.plain(json));
};
/**
* Add missing default fields to manifest.
* @param {String} path Path to manifest.json
* @param {String} packageId Unique package identifier com.example.foo
* @memberOf Manifest
* @static
*/
Manifest.addDefaults =
function(output, path, packageId) {
var buffer;
var json = {};
if (ShellJS.test("-f", path)) {
buffer = FS.readFileSync(path, {"encoding": "utf8"});
json = JSON.parse(buffer);
} else {
output.warning("File not found " + path);
output.warning("Using default manifest.json");
}
// Just a shallow assignment of missing fields.
var defaultsJson = Manifest.createDefaultJson(packageId);
for (var key in defaultsJson) {
if (!json[key]) {
json[key] = defaultsJson[key];
}
}
// Write back
buffer = FormatJson.plain(json);
FS.writeFileSync(path, buffer);

@@ -355,2 +491,15 @@ };

/**
* Orientation
* @member {String} orientation
* @instance
* @memberOf Manifest
* @see https://w3c.github.io/manifest/#orientation-member
*/
Object.defineProperty(Manifest.prototype, "orientation", {
get: function() {
return this._orientation;
}
});
/**
* Icons

@@ -382,2 +531,14 @@ * @member {String} icons

/**
* Command line params
* @member {String} commandLine
* @instance
* @memberOf Manifest
*/
Object.defineProperty(Manifest.prototype, "commandLine", {
get: function() {
return this._commandLine;
}
});
/**
* Package ID

@@ -419,2 +580,38 @@ * @member {String} packageId

/**
* Android permissions.
* @member {String} androidPermissions
* @instance
* @memberOf Manifest
*/
Object.defineProperty(Manifest.prototype, "androidPermissions", {
get: function() {
return this._androidPermissions;
}
});
/**
* Android webp conversion.
* @member {String} androidWebp
* @instance
* @memberOf Manifest
*/
Object.defineProperty(Manifest.prototype, "androidWebp", {
get: function() {
return this._androidWebp;
}
});
/**
* Extensions.
* @member {String} extensions
* @instance
* @memberOf Manifest
*/
Object.defineProperty(Manifest.prototype, "extensions", {
get: function() {
return this._extensions;
}
});
/**
* Build target platforms for the apps

@@ -421,0 +618,0 @@ * @member {String} targetPlatforms

@@ -22,3 +22,4 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

}
// OutputTee.prototype = OutputIface.prototype;
OutputTee.prototype = Object.create(OutputIface.prototype);
OutputTee.prototype.constructor = OutputTee;

@@ -25,0 +26,0 @@ /**

@@ -194,3 +194,6 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

ShellJS.mv('-f', packagePath, this.pkgPath);
// ShellJS.mv() gives weird can not link error when moving
// across file systems, so play save and copy/delete.
ShellJS.cp(packagePath, this.pkgPath);
ShellJS.rm("-f", packagePath);
};

@@ -197,0 +200,0 @@

@@ -71,2 +71,14 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

/**
* Module constructor.
* @member {Function} Ctor
* @instance
* @memberOf PlatformInfo
*/
Object.defineProperty(PlatformInfo.prototype, "Ctor", {
get: function() {
return this._Ctor;
}
});
/**
* Instantiate platform backend.

@@ -73,0 +85,0 @@ * @param {Application} application Application instance

@@ -33,2 +33,4 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

function silentCb(errormsg) {}
var output = this._output;

@@ -41,3 +43,4 @@

platformInfo = this.load(platformId);
// Silent error callback because we just try loading all.
platformInfo = this.load(platformId, silentCb);
if (platformInfo) {

@@ -61,3 +64,3 @@ break;

/**
* Load default backend.
* Load all installed backends.
* @returns {PlatformInfo} Metadata object for loaded platform.

@@ -68,2 +71,4 @@ */

function silentCb(errormsg) {}
var output = this._output;

@@ -75,3 +80,4 @@

platformInfo = this.load(platformId);
// Silent error callback because we just try loading all.
platformInfo = this.load(platformId, silentCb);
if (platformInfo) {

@@ -94,4 +100,3 @@ backends.push(platformInfo);

if (!callback)
callback = function(errormsg) {};
var output = this._output;

@@ -108,3 +113,7 @@ var platformInfo = null;

callback(e.message);
if (callback)
callback(e.message);
else
output.error(e.message);
return null;
}

@@ -111,0 +120,0 @@

@@ -5,2 +5,4 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

var Os = require("os");
var FiniteProgress = require("./FiniteProgress");

@@ -24,12 +26,19 @@ var InfiniteProgress = require("./InfiniteProgress");

this._progress = null;
return TerminalOutput._instance;
}
TerminalOutput.prototype = Object.create(OutputIface.prototype);
TerminalOutput.prototype.constructor = TerminalOutput;
TerminalOutput.prototype = OutputIface.prototype;
TerminalOutput.prototype.error =
function(message) {
if (!_config.getSilentConsole())
if (!_config.getSilentConsole()) {
if (this._progress &&
this._progress.isActive) {
console.log("");
}
console.error("*** ERROR: " + message);
}
};

@@ -40,4 +49,9 @@

if (!_config.getSilentConsole())
if (!_config.getSilentConsole()) {
if (this._progress &&
this._progress.isActive) {
console.log("");
}
console.error(" ** WARNING: " + message);
}
};

@@ -48,4 +62,9 @@

if (!_config.getSilentConsole())
if (!_config.getSilentConsole()) {
if (this._progress &&
this._progress.isActive) {
console.log("");
}
console.log(" * " + message);
}
};

@@ -56,4 +75,9 @@

if (!_config.getSilentConsole())
if (!_config.getSilentConsole()) {
if (this._progress &&
this._progress.isActive) {
console.log("");
}
console.log('\033[1m' + message + '\033[0m');
}
};

@@ -85,4 +109,4 @@

var indicator = new FiniteProgress(this, label);
return indicator;
this._progress = new FiniteProgress(this, label);
return this._progress;
};

@@ -106,7 +130,18 @@

var indicator = new InfiniteProgress(this, label);
return indicator;
this._progress = new InfiniteProgress(this, label);
return this._progress;
};
/**
* End progress display and switch back to line mode.
* Only to be called from the progress indicator classes.
* @private
*/
TerminalOutput.prototype.endProgress =
function() {
this._progress = null;
};
/**
* Retrieve singleton instance.

@@ -113,0 +148,0 @@ * @function getInstance

@@ -19,3 +19,4 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

}
FileCreationFailed.prototype = Error.prototype;
FileCreationFailed.prototype = Object.create(Error.prototype);
FileCreationFailed.prototype.constructor = FileCreationFailed;

@@ -32,3 +33,4 @@ /**

}
IllegalAccessException.prototype = Error.prototype;
IllegalAccessException.prototype = Object.create(Error.prototype);
IllegalAccessException.prototype.constructor = IllegalAccessException;

@@ -45,3 +47,4 @@ /**

}
InvalidPathException.prototype = Error.prototype;
InvalidPathException.prototype = Object.create(Error.prototype);
InvalidPathException.prototype.constructor = InvalidPathException;

@@ -48,0 +51,0 @@

@@ -9,2 +9,4 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

var util = {
/** {@link CrosswalkZip} */
CrosswalkZip: require("./CrosswalkZip"),
/** {@link Downloader} */

@@ -17,5 +19,26 @@ Downloader: require("./Downloader"),

/** {@link TemplateFile} */
TemplateFile: require("./TemplateFile")
TemplateFile: require("./TemplateFile"),
/**
* Iterate an array with provisions for asynchronous processing of each item.
* @param {Array} a Array to iterate over
* @param {Function} callback Function(item, next) to be called for each item.
* Parameter next when called continues iteration.
* @param {Function} done Function to be called when done iterating.
*/
iterate: function(a, callback, done) {
var i = -1;
function next() {
i++;
if (i < a.length) {
callback(a[i], next);
} else if (done) {
done();
}
}
next();
}
};
module.exports = util;

@@ -11,3 +11,4 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

}
TestPlatform.prototype = PlatformBase.prototype;
TestPlatform.prototype = Object.create(PlatformBase.prototype);
TestPlatform.prototype.constructor = TestPlatform;

@@ -14,0 +15,0 @@ TestPlatform.prototype.create =

@@ -16,2 +16,3 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

var OutputTee = require("../src/OutputTee");
var TerminalOutput = require("../src/TerminalOutput");
var Util = require("../test-util/Util.js");

@@ -91,3 +92,3 @@

test.equal(manifest instanceof Manifest, true);
test.equal(manifest.appVersion, "1");
test.equal(manifest.appVersion, "0.1");
Util.deleteTmpApplication(application);

@@ -156,2 +157,15 @@ test.done();

setOutput2: function(test) {
test.expect(1);
var application = Util.createTmpApplication("com.example.foo");
application.output = TerminalOutput.getInstance();
// If we get here without exception, all is good.
test.equal(true, true);
Util.deleteTmpApplication(application);
test.done();
},
logging: function(test) {

@@ -158,0 +172,0 @@

@@ -123,3 +123,3 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

// No version, good test
// No version, good test, default to "stable"
var argv0 = ["node", "foo", "update"];

@@ -134,3 +134,3 @@ var cp0 = new CommandParser(_output, argv0);

var version0 = cp0.updateGetVersion();
test.equal(version0, null);
test.equal(version0, "stable");

@@ -156,3 +156,3 @@ // Good test

var version2 = cp2.updateGetVersion();
test.equal(version2, false);
test.equal(version2, null);

@@ -162,2 +162,39 @@ test.done();

updateGetDir: function(test) {
test.expect(8);
// build inside project
var argv0 = ["node", "foo", "update"];
var cp0 = new CommandParser(_output, argv0);
test.equal(cp0.getCommand(), "update");
var cmd0 = cp0.getCommand();
test.equal(cmd0, argv0[2]);
var version0 = cp0.updateGetVersion();
test.equal(version0, "stable");
var dir0 = cp0.updateGetDir();
test.equal(dir0, process.cwd());
// command-line with dir specified
var argv1 = ["node", "foo", "update", "beta", "com.example.foo"];
var cp1 = new CommandParser(_output, argv1);
test.equal(cp1.getCommand(), "update");
var cmd1 = cp1.getCommand();
test.equal(cmd1, argv1[2]);
var version1 = cp1.updateGetVersion();
test.equal(version1, argv1[3]);
var dir1 = cp1.updateGetDir();
test.equal(dir1, Path.join(process.cwd(), argv1[4]));
test.done();
},
buildGetType: function(test) {

@@ -164,0 +201,0 @@

@@ -34,3 +34,36 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

}
},
interruptedProgress: function(test) {
test.expect(10);
var progress = 0;
var indicator = _output.createFiniteProgress("foo");
var interval = setInterval(callback, 200);
function callback() {
indicator.update(progress);
progress += 0.1;
if (progress > 0.19 && progress < 0.21)
_output.info("info " + progress);
else if (progress > 0.39 && progress < 0.41)
_output.warning("warning " + progress);
else if (progress > 0.59 && progress < 0.61)
_output.error("error " + progress);
else if (progress > 0.79 && progress < 0.81)
_output.highlight("highlight " + progress);
if (progress > 1) {
clearInterval(interval);
indicator.done("done");
test.done();
return;
}
test.equal(true, true);
}
}
};

@@ -34,3 +34,43 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

}
},
interruptedProgress: function(test) {
test.expect(5);
var tags = ["foo", "bar", "baz", "maman", "quux"];
var index = 0;
var indicator = _output.createInfiniteProgress("foo");
var interval = setInterval(callback, 300);
function callback() {
indicator.update(tags[index]);
switch (index) {
case 0:
_output.info("info " + index);
break;
case 1:
_output.warning("warning " + index);
break;
case 2:
_output.error("error " + index);
break;
case 3:
_output.highlight("highlight " + index);
break;
}
index++;
test.equal(true, true);
if (index >= tags.length) {
indicator.done("done");
clearInterval(interval);
test.done();
return;
}
}
}
};

@@ -34,6 +34,48 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

check0: function(test) {
test.expect(1);
// Good test.
// Run check without platforms
var tmpdir = Util.createTmpDir();
ShellJS.pushd(tmpdir);
var app = require("../src/Main");
app.check([], TerminalOutput.getInstance(), function(errno) {
test.equal(errno, 0);
ShellJS.popd();
ShellJS.rm("-rf", tmpdir);
test.done();
});
},
check1: function(test) {
test.expect(1);
// Good test.
// Run check "android"
var tmpdir = Util.createTmpDir();
ShellJS.pushd(tmpdir);
var app = require("../src/Main");
app.check(["android"], TerminalOutput.getInstance(), function(errno) {
test.equal(errno, 0);
ShellJS.popd();
ShellJS.rm("-rf", tmpdir);
test.done();
});
},
create: function(test) {
test.expect(1);
// Good test.

@@ -40,0 +82,0 @@ var tmpdir = Util.createTmpDir();

@@ -65,25 +65,55 @@ // Copyright © 2014 Intel Corporation. All rights reserved.

version = "2.";
path = produceManifest({"xwalk_app_version": version});
test.equal(false, version == consumeManifest(path).appVersion);
try {
version = "2.";
path = produceManifest({"xwalk_app_version": version});
consumeManifest(path);
} catch (e) {
// Invalid version, just make sure it throws.
test.equal(true, true);
}
version = "2.2.";
path = produceManifest({"xwalk_app_version": version});
test.equal(false, version == consumeManifest(path).appVersion);
try {
version = "2.2.";
path = produceManifest({"xwalk_app_version": version});
consumeManifest(path);
} catch (e) {
// Invalid version, just make sure it throws.
test.equal(true, true);
}
version = "2.2.2.";
path = produceManifest({"xwalk_app_version": version});
test.equal(false, version == consumeManifest(path).appVersion);
try {
version = "2.2.2.";
path = produceManifest({"xwalk_app_version": version});
consumeManifest(path);
} catch (e) {
// Invalid version, just make sure it throws.
test.equal(true, true);
}
version = "3333";
path = produceManifest({"xwalk_app_version": version});
test.equal(false, version == consumeManifest(path).appVersion);
try {
version = "3333";
path = produceManifest({"xwalk_app_version": version});
consumeManifest(path);
} catch (e) {
// Invalid version, just make sure it throws.
test.equal(true, true);
}
version = "333.333";
path = produceManifest({"xwalk_app_version": version});
test.equal(false, version == consumeManifest(path).appVersion);
try {
version = "333.333";
path = produceManifest({"xwalk_app_version": version});
consumeManifest(path);
} catch (e) {
// Invalid version, just make sure it throws.
test.equal(true, true);
}
version = "33.333.333";
path = produceManifest({"xwalk_app_version": version});
test.equal(false, version == consumeManifest(path).appVersion);
try {
version = "33.333.333";
path = produceManifest({"xwalk_app_version": version});
consumeManifest(path);
} catch (e) {
// Invalid version, just make sure it throws.
test.equal(true, true);
}

@@ -135,5 +165,5 @@ test.done();

test.expect(3);
test.expect(6);
// Default to "false"
// Default to "standalone"
var path = produceManifest();

@@ -143,6 +173,9 @@ var manifest = consumeManifest(path);

// Test reading "fullscreen"
path = produceManifest({"display": "fullscreen"});
manifest = consumeManifest(path);
test.equal(manifest.display, "fullscreen");
// Test reading various values
var values = ["fullscreen", "standalone", "minimal-ui", "browser"];
values.forEach(function (value) {
path = produceManifest({"display": value});
manifest = consumeManifest(path);
test.equal(manifest.display, value);
});

@@ -157,2 +190,35 @@ // Test reading bogus value "foo", default to "standalone"

orientation: function(test) {
test.expect(10);
// Default to "any"
var path = produceManifest();
var manifest = consumeManifest(path);
test.equal(manifest.orientation, "any");
// Test reading various values
var values = [ "any",
"natural",
"landscape",
"portrait",
"portrait-primary",
"portrait-secondary",
"landscape-primary",
"landscape-secondary"
];
values.forEach(function (value) {
path = produceManifest({"orientation": value});
manifest = consumeManifest(path);
test.equal(manifest.orientation, value);
});
// Test reading bogus value "foo", default to "any"
path = produceManifest({"orientation": "foo"});
manifest = consumeManifest(path);
test.equal(manifest.orientation, "any");
test.done();
},
icons: function(test) {

@@ -199,2 +265,19 @@

commandLine: function(test) {
test.expect(2);
// default
var path = produceManifest();
var manifest = consumeManifest(path);
test.equal(manifest.commandLine, null);
// custom value
path = produceManifest({"xwalk_command_line": "foo"});
manifest = consumeManifest(path);
test.equal(manifest.commandLine, "foo");
test.done();
},
packageId: function(test) {

@@ -225,3 +308,3 @@

test.expect(1);
test.expect(2);

@@ -234,2 +317,9 @@ var path = produceManifest({"xwalk_target_platforms": "android"});

// write
manifest.targetPlatforms = "windows";
// read back
manifest = consumeManifest(path);
test.equal(manifest.targetPlatforms, "windows");
test.done();

@@ -272,2 +362,36 @@ },

androidPermissions: function(test) {
test.expect(2);
// Default, check INTERNET is set (also needs networks etc)
var path = produceManifest();
var manifest = consumeManifest(path);
test.equal(manifest.androidPermissions.indexOf("INTERNET") >= 0, true);
// Test adding CAMERA
path = produceManifest({"xwalk_android_permissions": [ "CAMERA" ]});
manifest = consumeManifest(path);
test.equal(manifest.androidPermissions.indexOf("CAMERA") >= 0, true);
test.done();
},
androidWebp: function(test) {
test.expect(2);
// Default to "false"
var path = produceManifest();
var manifest = consumeManifest(path);
test.equal(!manifest.androidWebp, true);
// Test reading "true"
path = produceManifest({"xwalk_android_webp": "80 80 100"});
manifest = consumeManifest(path);
test.equal(manifest.androidWebp, "80 80 100");
test.done();
},
windowsUpdateId: function(test) {

@@ -289,10 +413,14 @@

test.expect(1);
test.expect(2);
var path3 = produceManifest();
var m3 = consumeManifest(path3);
var path1 = produceManifest();
var m1 = consumeManifest(path1);
test.equal(m1.windowsVendor, null);
test.equal(typeof m3.windowsVendor === "string", true);
var path2 = produceManifest({"xwalk_windows_vendor": "foo"});
var m2 = consumeManifest(path2);
test.equal(m2.windowsVendor, "foo");
test.done();
}
};

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc