You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ni...@apache.org on 2015/05/13 23:14:57 UTC
[02/14] cordova-windows git commit: CB-8923 Add support for Windows
10 platform
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/0d2387d9/template/cordova/lib/prepare.js
----------------------------------------------------------------------
diff --git a/template/cordova/lib/prepare.js b/template/cordova/lib/prepare.js
index 7bec13d..4a02c12 100644
--- a/template/cordova/lib/prepare.js
+++ b/template/cordova/lib/prepare.js
@@ -17,43 +17,74 @@
under the License.
*/
-var path = require('path'),
- fs = require('fs'),
- et = require('elementtree'),
- shell = require('shelljs'),
- ConfigParser = require('./ConfigParser');
+var path = require('path'),
+ fs = require('fs'),
+ et = require('elementtree'),
+ subElement = et.SubElement,
+ shell = require('shelljs'),
+ MSBuildTools = require('./MSBuildTools'),
+ Version = require('./Version'),
+ ConfigParser = require('./ConfigParser');
var ROOT = path.join(__dirname, '..', '..'),
- accessRules;
+ PROJECT_WINDOWS10 = 'CordovaApp.Windows10.jsproj',
+ MANIFEST_WINDOWS8 = 'package.windows80.appxmanifest',
+ MANIFEST_WINDOWS = 'package.windows.appxmanifest',
+ MANIFEST_PHONE = 'package.phone.appxmanifest',
+ MANIFEST_WINDOWS10 = 'package.windows10.appxmanifest',
+ JSPROJ_WINDOWS8 = 'CordovaApp.Windows80.jsproj',
+ JSPROJ_WINDOWS = 'CordovaApp.Windows.jsproj',
+ JSPROJ_PHONE = 'CordovaApp.Phone.jsproj',
+ JSPROJ_WINDOWS10 = 'CordovaApp.Windows10.jsproj',
+ BASE_UAP_VERSION = new Version(10, 0, 10030, 0),
+ UAP_RESTRICTED_CAPS = ['enterpriseAuthentication', 'sharedUserCertificates',
+ 'documentsLibrary', 'musicLibrary', 'picturesLibrary',
+ 'videosLibrary', 'removableStorage', 'internetClientClientServer',
+ 'privateNetworkClientServer'],
+ // UAP namespace capabilities come from the XSD type ST_Capability_Uap from AppxManifestTypes.xsd
+ CAPS_NEEDING_UAPNS = ['documentsLibrary', 'picturesLibrary', 'videosLibrary',
+ 'musicLibrary', 'enterpriseAuthentication', 'sharedUserCertificates',
+ 'removableStorage', 'appointments', 'contacts', 'userAccountInformation',
+ 'phoneCall', 'blockedChatMessages', 'objects3D'];
module.exports.applyPlatformConfig = function () {
console.log('Applying Platform Config...');
var config = new ConfigParser(path.join(ROOT, 'config.xml'));
- accessRules = config.getAccessRules().filter(function(rule) {
- if (rule.indexOf('https://') === 0 || rule == '*') {
- return true;
- } else {
- console.log('Access rules must begin with "https://", the following rule will be ignored: ' + rule);
- }
- return false;
- });
+ var isTargetingWin10 = false;
+ var winTargetVersion = config.getWindowsTargetVersion();
+ if (winTargetVersion === '10.0' || winTargetVersion === 'UAP') {
+ isTargetingWin10 = true;
+ }
// Apply appxmanifest changes
- [{ fileName: 'package.windows.appxmanifest', namespacePrefix: 'm2:' },
- { fileName: 'package.windows80.appxmanifest', namespacePrefix: '' },
- { fileName: 'package.phone.appxmanifest', namespacePrefix: 'm3:' }].forEach(
+ [{ fileName: MANIFEST_WINDOWS, namespacePrefix: 'm2:' },
+ { fileName: MANIFEST_WINDOWS8, namespacePrefix: '' },
+ { fileName: MANIFEST_PHONE, namespacePrefix: 'm3:' }].forEach(
function(manifestFile) {
- updateManifestFile(config, path.join(ROOT, manifestFile.fileName), manifestFile.namespacePrefix);
+ updateManifestFile(config, path.join(ROOT, manifestFile.fileName), manifestFile.namespacePrefix, null);
});
// Apply jsproj changes
- ['CordovaApp.Phone.jsproj', 'CordovaApp.Windows.jsproj', 'CordovaApp.Windows80.jsproj'].forEach(
+ [JSPROJ_PHONE, JSPROJ_WINDOWS, JSPROJ_WINDOWS8, JSPROJ_WINDOWS10].forEach(
function(jsprojFile) {
updatejsprojFile(config, path.join(ROOT, jsprojFile));
});
+ // Break out Windows 10-specific functionality because we also need to
+ // apply UAP versioning to Windows 10 appx-manifests.
+ var uapVersionInfo = getUAPVersions(config);
+
+ if (uapVersionInfo) {
+ updateManifestFile(config, path.join(ROOT, MANIFEST_WINDOWS10), 'uap:', uapVersionInfo);
+
+ applyUAPVersionToProject(path.join(ROOT, PROJECT_WINDOWS10), uapVersionInfo);
+ }
+ else if (isTargetingWin10) {
+ console.warn('Warning: Requested build targeting Windows 10, but Windows 10 tools were not detected on the system.');
+ }
+
copyImages(config);
};
@@ -71,8 +102,7 @@ function updatejsprojFile(config, jsProjFilePath) {
fs.writeFileSync(jsProjFilePath, jsProjXML.write({indent: 2}), 'utf-8');
}
-function updateManifestFile (config, manifestPath, namespacePrefix) {
-
+function updateManifestFile (config, manifestPath, namespacePrefix, uapVersionInfo) {
var contents = fs.readFileSync(manifestPath, 'utf-8');
if(contents) {
//Windows is the BOM. Skip the Byte Order Mark.
@@ -81,29 +111,27 @@ function updateManifestFile (config, manifestPath, namespacePrefix) {
var manifest = new et.ElementTree(et.XML(contents));
- applyCoreProperties(config, manifest, manifestPath, namespacePrefix);
+ applyCoreProperties(config, manifest, manifestPath, namespacePrefix, !!uapVersionInfo);
// sort Capability elements as per CB-5350 Windows8 build fails due to invalid 'Capabilities' definition
sortCapabilities(manifest);
- applyAccessRules(config, manifest);
+ applyAccessRules(config, manifest, !!uapVersionInfo);
applyBackgroundColor(config, manifest, namespacePrefix);
+ if (uapVersionInfo) {
+ applyTargetPlatformVersion(config, manifest, uapVersionInfo);
+ checkForRestrictedCapabilities(config, manifest);
+ ensureUapPrefixedCapabilities(manifest.find('.//Capabilities'));
+ }
//Write out manifest
fs.writeFileSync(manifestPath, manifest.write({indent: 4}), 'utf-8');
}
-function applyCoreProperties(config, manifest, manifestPath, xmlnsPrefix) {
+function applyCoreProperties(config, manifest, manifestPath, xmlnsPrefix, targetWin10) {
var version = fixConfigVersion(config.version());
var name = config.name();
var pkgName = config.packageName();
var author = config.author();
- var startPage = config.startPage();
-
- if (!startPage) {
- // If not specified, set default value
- // http://cordova.apache.org/docs/en/edge/config_ref_index.md.html#The%20config.xml%20File
- startPage = 'index.html';
- }
var identityNode = manifest.find('.//Identity');
if(!identityNode) {
@@ -128,7 +156,8 @@ function applyCoreProperties(config, manifest, manifestPath, xmlnsPrefix) {
var appId = pkgName.length <= 64 ? pkgName : pkgName.substr(0, 64);
app.attrib.Id = appId;
}
- app.attrib.StartPage = 'www/' + startPage;
+
+ applyStartPage(app, config, targetWin10);
var visualElementsName = './/' + xmlnsPrefix + 'VisualElements';
var visualElems = manifest.find(visualElementsName);
@@ -200,6 +229,46 @@ function applyCoreProperties(config, manifest, manifestPath, xmlnsPrefix) {
}
}
+function applyStartPage(appNode, config, targetingWin10) {
+ var startPage = config.startPage();
+
+ if (!startPage) {
+ // If not specified, set default value
+ // http://cordova.apache.org/docs/en/edge/config_ref_index.md.html#The%20config.xml%20File
+ startPage = 'index.html';
+ }
+
+ var uriPrefix = '';
+ if (targetingWin10) {
+ // for Win10, we respect config options such as WindowsDefaultUriPrefix and default to
+ // ms-appx-web:// as the homepage. Set those here.
+
+ // Only add a URI prefix if the start page doesn't specify a URI scheme
+ if (!(/^[\w-]+?\:\/\//i).test(startPage)) {
+ uriPrefix = config.getPreference('WindowsDefaultUriPrefix');
+ if (!uriPrefix) {
+ uriPrefix = 'ms-appx-web://';
+ }
+ else if (/^ms\-appx\:\/\/$/i.test(uriPrefix)) {
+ // Explicitly ignore the ms-appx:// scheme because it doesn't validate
+ // in the Windows 10 build schema (treat it as the root).
+ uriPrefix = '';
+ }
+ }
+ }
+
+ var startPagePrefix = 'www/';
+ if ((uriPrefix && uriPrefix.toLowerCase().substring(0, 4) === 'http') ||
+ startPage.toLowerCase().substring(0, 4) === 'http') {
+ startPagePrefix = '';
+ }
+ else if (uriPrefix.toLowerCase().substring(0, 7) === 'ms-appx') {
+ uriPrefix += '/'; // add a 3rd trailing forward slash for correct area resolution
+ }
+
+ appNode.attrib.StartPage = uriPrefix + startPagePrefix + startPage;
+}
+
// Adjust version number as per CB-5337 Windows8 build fails due to invalid app version
function fixConfigVersion (version) {
if(version && version.match(/\.\d/g)) {
@@ -211,29 +280,105 @@ function fixConfigVersion (version) {
return version;
}
-function applyAccessRules (config, manifest) {
+function applyAccessRules (config, manifest, isTargetingWin10) {
// Updates WhiteListing rules
//<ApplicationContentUriRules>
// <Rule Match="https://www.example.com" Type="include"/>
//</ApplicationContentUriRules>
+
+ var AppContentUriRulesElementName = 'ApplicationContentUriRules',
+ RuleElementName = 'Rule';
+
+ if (isTargetingWin10) {
+ return applyNavigationWhitelist(config, manifest);
+ }
+
+
+ var accessRules = config.getAccessRules().filter(function(rule) {
+ // https:// rules are always good, * rules are always good
+ if (rule.indexOf('https://') === 0 || rule === '*') {
+ return true;
+ } else {
+ console.warn('Access rules must begin with "https://", the following rule will be ignored: ' + rule);
+ }
+ return false;
+ });
+
+ // If * is specified, emit no access rules.
+ if (accessRules.indexOf('*') > -1) {
+ accessRules = [];
+ }
+
+ createApplicationContentUriRules(manifest, AppContentUriRulesElementName, RuleElementName, accessRules, { Type: 'include' });
+}
+
+/**
+ * Windows 10-based whitelist-plugin-compatible support for the enhanced navigation whitelist.
+ * Allows WinRT access to origins specified by <allow-navigation href="origin" /> elements.
+ */
+function applyNavigationWhitelist(config, manifest) {
+ var AppContentUriRulesElementName = 'uap:ApplicationContentUriRules';
+ var RuleElementName = 'uap:Rule';
+ var UriSchemeTest = /^(?:https?|ms-appx-web):\/\//i;
+
+ var whitelistRules = config.getNavigationWhitelistRules().filter(function(rule) {
+ if (UriSchemeTest.test(rule)) {
+ return true;
+ } else {
+ console.warn('The following navigation rule had an invalid URI scheme and is ignored: "' + rule + '".');
+ }
+ return false;
+ });
+
+ var defaultPrefix = config.getPreference('WindowsDefaultUriPrefix');
+ if ('ms-appx://' !== defaultPrefix) {
+ var hasMsAppxWeb = whitelistRules.some(function(rule) {
+ return /^ms-appx-web:\/\/\/$/i.test(rule);
+ });
+ if (!hasMsAppxWeb) {
+ whitelistRules.push('ms-appx-web:///');
+ }
+ }
+
+ createApplicationContentUriRules(manifest, AppContentUriRulesElementName, RuleElementName, whitelistRules, {
+ Type: 'include',
+ WindowsRuntimeAccess: 'all'
+ });
+}
+
+/**
+ * Private function used by applyNavigationWhitelist and applyAccessRules
+ * which creates the corresponding section in the app manifest.
+ * @param manifest {et.ElementTree} The manifest document.
+ * @param acurElementName {string} The name of the AccessContentUriRules element, including prefix if applicable.
+ * @param ruleElementName {string} The name of the Rule element, including prefix if applicable.
+ * @param rulesOrigins {string[]} The origins that will be permitted.
+ * @param commonAttributes {Object} Property bag of additional attributes that should be applied to every rule.
+ */
+function createApplicationContentUriRules(manifest, acurElementName, ruleElementName, rulesOrigins, commonAttributes) {
var appUriRulesRoot = manifest.find('.//Application'),
- appUriRules = appUriRulesRoot.find('.//ApplicationContentUriRules');
+ appUriRules = appUriRulesRoot.find(acurElementName);
if (appUriRules !== null) {
appUriRulesRoot.remove(null, appUriRules);
}
- // rules are not defined or allow any
- if (accessRules.length === 0 || accessRules.indexOf('*') > -1) {
+
+ // No rules defined
+ if (rulesOrigins.length === 0) {
return;
- }
+ }
- appUriRules = et.Element('ApplicationContentUriRules');
+ appUriRules = et.Element(acurElementName);
appUriRulesRoot.append(appUriRules);
- accessRules.forEach(function(rule) {
- var el = et.Element('Rule');
+ rulesOrigins.forEach(function(rule) {
+ var el = et.Element(ruleElementName);
el.attrib.Match = rule;
- el.attrib.Type = 'include';
+
+ var attributes = Object.keys(commonAttributes);
+ attributes.forEach(function(attributeName) {
+ el.attrib[attributeName] = commonAttributes[attributeName];
+ });
appUriRules.append(el);
});
}
@@ -262,6 +407,20 @@ function sortCapabilities(manifest) {
});
}
+function checkForRestrictedCapabilities(config, manifest) {
+ var hasRemoteUris = checkForRemoteModeUris(config);
+ if (hasRemoteUris) {
+ var capabilitiesRoot = manifest.find('.//Capabilities');
+ var badCaps = checkForRestrictedRemoteCapabilityDeclarations(capabilitiesRoot);
+ if (badCaps) {
+ console.warn('The following Capabilities were declared and are restricted:');
+ console.warn(' ' + badCaps.join(','));
+ console.warn('You will be unable to on-board your app to the public Windows Store with');
+ console.warn(' these capabilities and access rules permitting access to remote URIs.');
+ }
+ }
+}
+
function copyImages(config) {
var platformRoot = ROOT;
// TODO find the way to detect whether command was triggered by CLI or not
@@ -310,9 +469,11 @@ function copyImages(config) {
{dest: 'SplashScreen.scale-100.png', width: 620, height: 300},
// scaled images are specified here for backward compatibility only so we can find them by size
{dest: 'StoreLogo.scale-240.png', width: 120, height: 120},
+ {dest: 'Square44x44Logo.scale-100.png', width: 44, height: 44},
{dest: 'Square44x44Logo.scale-240.png', width: 106, height: 106},
- {dest: 'Square71x71Logo.scale-240.png', width: 170, height: 170},
{dest: 'Square70x70Logo.scale-100.png', width: 70, height: 70},
+ {dest: 'Square71x71Logo.scale-100.png', width: 71, height: 71},
+ {dest: 'Square71x71Logo.scale-240.png', width: 170, height: 170},
{dest: 'Square150x150Logo.scale-240.png', width: 360, height: 360},
{dest: 'Square310x310Logo.scale-100.png', width: 310, height: 310},
{dest: 'Wide310x150Logo.scale-100.png', width: 310, height: 150},
@@ -386,3 +547,176 @@ function applyBackgroundColor (config, manifest, xmlnsPrefix) {
visualElems.attrib.BackgroundColor = refineColor(bgColor);
}
}
+
+function applyUAPVersionToProject(projectFilePath, uapVersionInfo) {
+ var fileContents = fs.readFileSync(projectFilePath).toString().trim();
+ var xml = et.parse(fileContents);
+ var tpv = xml.find('./PropertyGroup/TargetPlatformVersion');
+ var tpmv = xml.find('./PropertyGroup/TargetPlatformMinVersion');
+
+ tpv.text = uapVersionInfo.targetUAPVersion.toString();
+ tpmv.text = uapVersionInfo.minUAPVersion.toString();
+
+ fs.writeFileSync(projectFilePath, xml.write({ indent: 4 }), {});
+}
+
+function applyTargetPlatformVersion(config, manifest, uapVersionInfo) {
+ var dependencies = manifest.find('./Dependencies');
+ while (dependencies.len() > 0) {
+ dependencies.delItem(0);
+ }
+
+ var uapVersionSet = getAllMinMaxUAPVersions(config);
+ var platformNames = Object.keys(uapVersionSet);
+ for (var i = 0; i < platformNames.length; i++) {
+ var curTargetPlatformName = platformNames[i];
+ var curTargetPlatformInfo = uapVersionSet[curTargetPlatformName];
+
+ var elem = subElement(dependencies, 'TargetDeviceFamily');
+ elem.set('Name', curTargetPlatformName);
+ elem.set('MinVersion', curTargetPlatformInfo.MinVersion.toString());
+ elem.set('MaxVersionTested', curTargetPlatformInfo.MaxVersionTested.toString());
+ }
+}
+
+// returns {minUAPVersion: Version, targetUAPVersion: Version} | false
+function getUAPVersions(config) {
+ // @param config: ConfigParser
+ var baselineVersions = MSBuildTools.getAvailableUAPVersions();
+ if (!baselineVersions || baselineVersions.length === 0) {
+ return false;
+ }
+
+ baselineVersions.sort(Version.comparer);
+
+ return {
+ minUAPVersion: baselineVersions[0],
+ targetUAPVersion: baselineVersions[baselineVersions.length - 1]
+ };
+}
+
+/**
+ * Gets min/max UAP versions from the configuration. If no version preferences are
+ * in the configuration file, this will provide Windows.Universal at BASE_UAP_VERSION for both min and max.
+ * This will always return a rational object or will fail; for example, if a platform expects
+ * a higher min-version than max-version, it will raise the max version to the min version.
+ *
+ * @param config {ConfigParser} The configuration parser
+ * @return An object in the shape of: { 'Windows.Mobile': {'MinVersion': Version, 'MaxVersion': Version } } (where Version is a Version object)
+ * @exception {RangeError} Thrown if a Version string is badly formed.
+ */
+function getAllMinMaxUAPVersions(config) {
+ var uapVersionPreferenceTest = /(Microsoft.+?|Windows.+?)\-(MinVersion|MaxVersionTested)/i;
+ var platformBag = Object.create(null);
+ var preferenceList = config.getMatchingPreferences(uapVersionPreferenceTest);
+ preferenceList.forEach(function(verPref) {
+ var matches = uapVersionPreferenceTest.exec(verPref.name);
+ // 'matches' should look like: ['Windows.Universal-MinVersion', 'Windows.Universal', 'MinVersion']
+ var platformName = matches[1];
+ var versionPropertyName = matches[2];
+
+ var platformVersionSet = platformBag[platformName];
+ if (typeof platformVersionSet === 'undefined') {
+ platformVersionSet = { };
+ platformBag[platformName] = platformVersionSet;
+ }
+
+ var versionTest = Version.tryParse(verPref.value);
+ if (!versionTest) {
+ throw new RangeError('Could not comprehend a valid version from the string "' + verPref.value + '" of platform-boundary "' + verPref.name + '".');
+ }
+
+ platformVersionSet[versionPropertyName] = versionTest;
+ });
+
+ for (var platformName in platformBag) {
+ // Go through each and make sure there are min/max set
+ var versionPref = platformBag[platformName];
+ if (!versionPref.MaxVersionTested && !!versionPref.MinVersion) { // min is set, but max is not
+ versionPref.MaxVersionTested = versionPref.MinVersion;
+ }
+ else if (!versionPref.MinVersion && !!versionPref.MaxVersionTested) { // max is set, min is not
+ versionPref.MinVersion = versionPref.MaxVersionTested;
+ }
+ else if (!versionPref.MinVersion && !versionPref.MaxVersionTested) { // neither are set
+ versionPref.MinVersion = BASE_UAP_VERSION;
+ versionPref.MaxVersionTested = BASE_UAP_VERSION;
+ }
+ else { // both are set
+ if (versionPref.MinVersion.gt(versionPref.MaxVersionTested)) {
+ versionPref.MaxVersionTested = versionPref.MinVersion;
+ }
+ }
+ }
+
+ if (Object.keys(platformBag).length === 0) {
+ platformBag['Windows.Universal'] = { MinVersion: BASE_UAP_VERSION, MaxVersionTested: BASE_UAP_VERSION };
+ }
+
+ return platformBag;
+}
+
+/**
+ * Checks to see whether access rules or
+ * @param config {ConfigParser} The configuration parser
+ * @return {boolean} True if the config specifies remote URIs for access or start; false otherwise.
+ */
+function checkForRemoteModeUris(config) {
+ var accessRules = config.getNavigationWhitelistRules();
+ var startPage = config.startPage();
+ var test = /(https?|ms-appx-web):\/\//i;
+
+ var hasRemoteUri = test.test(startPage);
+ hasRemoteUri = hasRemoteUri || accessRules.some(function(rule) {
+ return test.test(rule);
+ });
+
+ return hasRemoteUri;
+}
+
+/**
+ * Checks for capabilities which are Restricted in Windows 10 UAP.
+ * @param appxManifestCapabilitiesElement {ElementTree.Element} The appx manifest element for <capabilities>
+ * @return {string[]|false} An array of restricted capability names, or false.
+ */
+function checkForRestrictedRemoteCapabilityDeclarations(appxManifestCapabilitiesElement) {
+ if (!appxManifestCapabilitiesElement)
+ return false;
+
+ var hasRestrictedCapabilities = false;
+ var foundRestrictedCapabilities = [];
+
+ var children = appxManifestCapabilitiesElement.getchildren();
+ var declaredCapabilities = children.map(function(el) {
+ return el.attrib.Name;
+ });
+
+ UAP_RESTRICTED_CAPS.forEach(function(cap) {
+ if (declaredCapabilities.indexOf(cap) > -1) {
+ hasRestrictedCapabilities = true;
+ foundRestrictedCapabilities.push(cap);
+ }
+ });
+
+ return hasRestrictedCapabilities ? foundRestrictedCapabilities : hasRestrictedCapabilities;
+}
+
+/**
+ * Checks for capabilities which require the uap: prefix in Windows 10.
+ * @param appxManifestCapabilitiesElement {ElementTree.Element} The appx manifest element for <capabilities>
+ */
+function ensureUapPrefixedCapabilities(appxManifestCapabilitiesElement) {
+ var children = appxManifestCapabilitiesElement.getchildren();
+ var declaredCapabilities = children.map(function(el) {
+ return { name: el.attrib.Name, element: el, elementName: el.tag };
+ });
+
+ declaredCapabilities.forEach(function(cap) {
+ if (CAPS_NEEDING_UAPNS.indexOf(cap.name) > -1) {
+ if (cap.elementName.indexOf('uap:') === -1) {
+ cap.elementName = 'uap:' + cap.elementName;
+ cap.element.tag = cap.elementName;
+ }
+ }
+ });
+}
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/0d2387d9/template/cordova/lib/run.js
----------------------------------------------------------------------
diff --git a/template/cordova/lib/run.js b/template/cordova/lib/run.js
index 3195793..d54823d 100644
--- a/template/cordova/lib/run.js
+++ b/template/cordova/lib/run.js
@@ -32,10 +32,10 @@ module.exports.run = function (argv) {
return Q.reject('Could not find project at ' + ROOT);
}
- // parse args
+ // parse arg
var args = nopt({'debug': Boolean, 'release': Boolean, 'nobuild': Boolean,
'device': Boolean, 'emulator': Boolean, 'target': String, 'archs': String,
- 'phone': Boolean, 'win': Boolean}, {'r' : '--release'}, argv);
+ 'phone': Boolean, 'win': Boolean, 'appx': String}, {'r' : '--release'}, argv);
// Validate args
if (args.debug && args.release) {
@@ -52,11 +52,43 @@ module.exports.run = function (argv) {
var buildType = args.release ? 'release' : 'debug',
buildArchs = args.archs ? args.archs.split(' ') : ['anycpu'],
projectType = args.phone ? 'phone' : 'windows',
- deployTarget = args.target ? args.target : args.device ? 'device' : 'emulator';
+ deployTarget = args.target ? args.target : (args.emulator ? 'emulator' : 'device'),
+ projOverride = args.appx;
// for win switch we should correctly handle 8.0 and 8.1 version as per configuration
- if (projectType == 'windows' && getWindowsTargetVersion() == '8.0') {
- projectType = 'windows80';
+ // as well as 10
+ var targetWindowsVersion = getWindowsTargetVersion();
+ if (projectType == 'windows') {
+ if (targetWindowsVersion == '8.0') {
+ projectType = 'windows80';
+ }
+ else if (targetWindowsVersion === '10.0') {
+ projectType = 'windows10';
+ }
+ }
+ else if (projectType === 'phone') {
+ if (targetWindowsVersion === '10.0' || targetWindowsVersion === 'UAP') {
+ projectType = 'windows10';
+ }
+ }
+
+ if (projOverride) {
+ switch (projOverride) {
+ case '8.1-phone':
+ projectType = 'phone';
+ targetWindowsVersion = '8.1';
+ break;
+ case '8.1-win':
+ projectType = 'windows';
+ targetWindowsVersion = '8.1';
+ break;
+ case 'uap':
+ projectType = 'windows10';
+ break;
+ default:
+ console.warn('Unrecognized --appx parameter passed to run: "' + projOverride + '", ignoring.');
+ break;
+ }
}
// if --nobuild isn't specified then build app first
@@ -65,10 +97,35 @@ module.exports.run = function (argv) {
return buildPackages.then(function () {
return packages.getPackage(projectType, buildType, buildArchs[0]);
}).then(function(pkg) {
- console.log('\nDeploying ' + pkg.type + ' package to ' + deployTarget + ':\n' + pkg.file);
- return pkg.type == 'phone' ?
- packages.deployToPhone(pkg.file, deployTarget) :
- packages.deployToDesktop(pkg.file, deployTarget);
+ console.log('\nDeploying ' + pkg.type + ' package to ' + deployTarget + ':\n' + pkg.appx);
+ switch (pkg.type) {
+ case 'phone':
+ return packages.deployToPhoneAndRun(pkg, deployTarget, false).catch(function(e) {
+ if (args.target || args.emulator || args.device) {
+ throw e; // Explicit target, carry on
+ }
+
+ // 'device' was inferred initially, because no target was specified
+ return packages.deployToPhoneAndRun(pkg, 'emulator', false);
+ });
+
+ case 'windows10':
+ if (args.phone) {
+ // Win10 emulator launch is not currently supported, always force device
+ if (args.emulator || args.target === 'emulator') {
+ console.warn('Windows 10 Phone emulator is not currently supported, attempting deploy to device.');
+ }
+ return packages.deployToPhoneAndRun(pkg, 'device', true);
+ }
+ else {
+ return packages.deployToDesktop(pkg, deployTarget, projectType);
+ }
+
+ break;
+ default: // 'windows'
+ return packages.deployToDesktop(pkg, deployTarget, projectType);
+
+ }
});
};
@@ -84,6 +141,9 @@ module.exports.help = function () {
console.log(' --archs : Specific chip architectures (`anycpu`, `arm`, `x86`, `x64`).');
console.log(' --phone, --win');
console.log(' : Specifies project type to deploy');
+ console.log(' --appx=<8.1-win|8.1-phone|uap>');
+ console.log(' : Overrides WindowsTargetVersion to build Windows 8.1, ');
+ console.log(' Windows Phone 8.1, or Windows 10.');
console.log('');
console.log('Examples:');
console.log(' run');
@@ -92,21 +152,26 @@ module.exports.help = function () {
console.log(' run --target=7988B8C3-3ADE-488d-BA3E-D052AC9DC710');
console.log(' run --device --release');
console.log(' run --emulator --debug');
+ console.log(' run --device --appx=phone-8.1');
console.log('');
+
process.exit(0);
};
function getWindowsTargetVersion() {
var config = new ConfigParser(path.join(ROOT, 'config.xml'));
- var windowsTargetVersion = config.getPreference('windows-target-version');
+ var windowsTargetVersion = config.getWindowsTargetVersion();
switch(windowsTargetVersion) {
- case '8':
- case '8.0':
- return '8.0';
- case '8.1':
- return '8.1';
- default:
- throw new Error('Unsupported windows-target-version value: ' + windowsTargetVersion);
+ case '8':
+ case '8.0':
+ return '8.0';
+ case '8.1':
+ return '8.1';
+ case '10.0':
+ case 'UAP':
+ return '10.0';
+ default:
+ throw new Error('Unsupported WindowsTargetVersion value: ' + windowsTargetVersion);
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/0d2387d9/template/cordova/lib/utils.js
----------------------------------------------------------------------
diff --git a/template/cordova/lib/utils.js b/template/cordova/lib/utils.js
index 22faf13..7e7adf9 100644
--- a/template/cordova/lib/utils.js
+++ b/template/cordova/lib/utils.js
@@ -64,14 +64,27 @@ module.exports.getAppStoreUtils = function () {
});
};
+function getProgramFiles32Folder() {
+ /* jshint ignore:start */ /* Wants to use dot syntax for ProgramFiles, leaving as-is for consistency */
+ return process.env['ProgramFiles(x86)'] || process.env['ProgramFiles'];
+ /* jshint ignore:end */
+}
+
// returns path to AppDeploy util from Windows Phone 8.1 SDK
-module.exports.getAppDeployUtils = function () {
- var appDeployUtils = path.join((process.env['ProgramFiles(x86)'] || process.env['ProgramFiles']),
- 'Microsoft SDKs', 'Windows Phone', 'v8.1', 'Tools', 'AppDeploy', 'AppDeployCmd.exe');
- // Check if AppDeployCmd exists
+module.exports.getAppDeployUtils = function (targetWin10) {
+ var appDeployUtils,
+ appDeployCmdName;
+ if (targetWin10) {
+ appDeployCmdName = 'WinAppDeployCmd.exe';
+ appDeployUtils = path.join(getProgramFiles32Folder(), 'Windows Kits', '10', 'bin', 'x86', appDeployCmdName);
+ } else {
+ appDeployCmdName = 'AppDeployCmd.exe';
+ appDeployUtils = path.join(getProgramFiles32Folder(), 'Microsoft SDKs', 'Windows Phone', 'v8.1', 'Tools', 'AppDeploy', appDeployCmdName);
+ }
+ // Check if AppDeployCmd is exists
if (!fs.existsSync(appDeployUtils)) {
- console.warn('WARNING: AppDeploy tool (AppDeployCmd.exe) wasn\'t found. Make sure that it\'s in %PATH%');
- return Q.resolve('AppDeployCmd');
+ console.warn('WARNING: AppDeploy tool (' + appDeployCmdName + ') wasn\'t found. Make sure that it\'s in %PATH%');
+ return Q.resolve(appDeployCmdName);
}
return Q.resolve(appDeployUtils);
};
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/0d2387d9/template/images/Square44x44Logo.scale-100.png
----------------------------------------------------------------------
diff --git a/template/images/Square44x44Logo.scale-100.png b/template/images/Square44x44Logo.scale-100.png
new file mode 100644
index 0000000..ce84d15
Binary files /dev/null and b/template/images/Square44x44Logo.scale-100.png differ
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/0d2387d9/template/images/Square71x71Logo.scale-100.png
----------------------------------------------------------------------
diff --git a/template/images/Square71x71Logo.scale-100.png b/template/images/Square71x71Logo.scale-100.png
new file mode 100644
index 0000000..9e712ab
Binary files /dev/null and b/template/images/Square71x71Logo.scale-100.png differ
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/0d2387d9/template/package.windows10.appxmanifest
----------------------------------------------------------------------
diff --git a/template/package.windows10.appxmanifest b/template/package.windows10.appxmanifest
new file mode 100644
index 0000000..e59e019
--- /dev/null
+++ b/template/package.windows10.appxmanifest
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+<Package
+ xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
+ xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
+ xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
+ IgnorableNamespaces="uap mp">
+
+ <Identity
+ Name="$guid1$"
+ Version="1.0.0.0"
+ Publisher="CN=$username$" />
+
+ <mp:PhoneIdentity PhoneProductId="$guid1$" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
+
+ <Properties>
+ <DisplayName>$projectname$</DisplayName>
+ <PublisherDisplayName>$username$</PublisherDisplayName>
+ <Logo>images\StoreLogo.png</Logo>
+ </Properties>
+
+ <Dependencies>
+ <TargetDeviceFamily Name="Windows.Universal" MinVersion="0.0.0.0" MaxVersionTested="10.0.0.0" />
+ </Dependencies>
+
+ <Resources>
+ <Resource Language="x-generate" />
+ </Resources>
+
+ <Applications>
+ <Application
+ Id="$safeprojectname$"
+ StartPage="www/index.html">
+
+ <uap:VisualElements
+ DisplayName="$projectname$"
+ Description="CordovaApp"
+ BackgroundColor="#464646"
+ Square150x150Logo="images\Square150x150Logo.png"
+ Square44x44Logo="images\Square44x44Logo.png">
+
+ <uap:SplashScreen Image="images\splashscreen.png" />
+ <uap:DefaultTile ShortName="$projectname$"
+ Square310x310Logo="images\Square310x310Logo.png"
+ Square71x71Logo="images\Square71x71Logo.png"
+ Wide310x150Logo="images\Wide310x150Logo.png" />
+
+ </uap:VisualElements>
+ </Application>
+ </Applications>
+
+ <Capabilities>
+ <Capability Name="internetClient" />
+ </Capabilities>
+
+</Package>
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/0d2387d9/template/www/cordova.js
----------------------------------------------------------------------
diff --git a/template/www/cordova.js b/template/www/cordova.js
index 79a6ba5..56dedcc 100644
--- a/template/www/cordova.js
+++ b/template/www/cordova.js
@@ -1289,7 +1289,10 @@ module.exports = {
if (!window.WinJS) {
var scriptElem = document.createElement("script");
- if (navigator.appVersion.indexOf("Windows Phone 8.1;") !== -1) {
+ if (navigator.appVersion.indexOf('MSAppHost/3.0') !== -1) {
+ // Windows 10 UAP
+ scriptElem.src = '/WinJS/js/WinJS.js';
+ } else if (navigator.appVersion.indexOf("Windows Phone 8.1;") !== -1) {
// windows phone 8.1 + Mobile IE 11
scriptElem.src = "//Microsoft.Phone.WinJS.2.1/js/base.js";
} else if (navigator.appVersion.indexOf("MSAppHost/2.0;") !== -1) {
http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/0d2387d9/template/www/js/index.js
----------------------------------------------------------------------
diff --git a/template/www/js/index.js b/template/www/js/index.js
index 31d9064..87b5660 100644
--- a/template/www/js/index.js
+++ b/template/www/js/index.js
@@ -31,7 +31,7 @@ var app = {
// deviceready Event Handler
//
// The scope of 'this' is the event. In order to call the 'receivedEvent'
- // function, we must explicity call 'app.receivedEvent(...);'
+ // function, we must explicitly call 'app.receivedEvent(...);'
onDeviceReady: function() {
app.receivedEvent('deviceready');
},
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org