You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by sg...@apache.org on 2014/09/11 09:16:42 UTC

git commit: CB-7452 Windows. Rewrite ApplyPlatformConfig.ps1 using NodeJS

Repository: cordova-windows
Updated Branches:
  refs/heads/master 1a80ff818 -> 93d463d81


CB-7452 Windows. Rewrite ApplyPlatformConfig.ps1 using NodeJS


Project: http://git-wip-us.apache.org/repos/asf/cordova-windows/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-windows/commit/93d463d8
Tree: http://git-wip-us.apache.org/repos/asf/cordova-windows/tree/93d463d8
Diff: http://git-wip-us.apache.org/repos/asf/cordova-windows/diff/93d463d8

Branch: refs/heads/master
Commit: 93d463d81a6dc900543275bdca7a78633a00b866
Parents: 1a80ff8
Author: sgrebnov <v-...@microsoft.com>
Authored: Wed Sep 3 21:14:50 2014 +0400
Committer: sgrebnov <v-...@microsoft.com>
Committed: Thu Sep 11 11:12:28 2014 +0400

----------------------------------------------------------------------
 .../cordova/lib/ApplyPlatformConfig.ps1         | 305 -------------------
 windows/template/cordova/lib/ConfigParser.js    |  22 ++
 windows/template/cordova/lib/build.js           |  13 +-
 windows/template/cordova/lib/prepare.js         | 261 ++++++++++++++++
 windows/template/cordova/lib/utils.js           |  14 -
 5 files changed, 288 insertions(+), 327 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/93d463d8/windows/template/cordova/lib/ApplyPlatformConfig.ps1
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/ApplyPlatformConfig.ps1 b/windows/template/cordova/lib/ApplyPlatformConfig.ps1
deleted file mode 100644
index 93f49a8..0000000
--- a/windows/template/cordova/lib/ApplyPlatformConfig.ps1
+++ /dev/null
@@ -1,305 +0,0 @@
-<#
-       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.
-#>
-
-param(
-    [Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
-    [string] $platformRoot
-)
-
-Write-Host "Applying Platform Config..."
-
-Function UpdateManifest ($manifestFile)
-{
-  [xml]$manifest = Get-Content $manifestFile -Encoding UTF8
-
-  # Replace app start page with config.xml setting.
-
-  $startPage = $config.widget.content.src
-  if (-not $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"
-  }
-  $manifest.Package.Applications.Application.StartPage = "www/$startpage"
-
-  # Update app name & version
-
-  # update identity name
-  $identityname = $config.widget.id
-  if ($identityname) {
-    $manifest.Package.Identity.Name = $identityname
-    $manifest.Package.Applications.Application.Id = $identityname
-  }
-
-  # update app display name
-  $displayname = $config.widget.name
-
-  $manifestDisplayName = $manifest.Package.Properties.DisplayName
-  if ($displayname -and $manifestDisplayName) {
-    $manifestDisplayName = $displayname
-  }
-
-  $visualelems = $manifest.Package.Applications.Application.VisualElements
-  if ($displayname -and $visualelems) {
-    $visualelems.DisplayName = $displayname
-  }
-
-  # update publisher display name
-  $publisher = $config.widget.author.InnerText
-  $manifestPublisher = $manifest.Package.Properties.PublisherDisplayName
-  if ($publisher -and $manifestPublisher) {
-    $manifestPublisher = $publisher.InnerText
-  }
-
-  # Adjust version number as per CB-5337 Windows8 build fails due to invalid app version
-  $version = $config.widget.version
-  if ($version -and $version -match "\." ) {
-      while ($version.Split(".").Length -lt 4) {
-          $version = $version + ".0"
-      }
-      $manifest.Package.Identity.Version = $version
-  }
-
-  # Sort capabilities elements
-  $capabilities = $manifest.Package.Capabilities
-  if ($capabilities) {
-    # Get sorted list of elements
-    $sorted = $capabilities.ChildNodes | sort
-    # Remove parent node
-    $manifest.Package.RemoveChild($capabilities) | Out-Null
-    # Create new node
-    $capabilities = $manifest.CreateElement("Capabilities", $manifest.DocumentElement.NamespaceURI)
-    # Then add sorted children
-    $sorted | foreach {
-        $Capabilities.AppendChild($_) | Out-Null
-    }
-    $manifest.Package.AppendChild($capabilities) | Out-Null
-  }
-
-  # Add domain whitelist rules
-  $rules = $manifest.Package.Applications.Application.ApplicationContentUriRules
-
-  # Remove existing rules from manifest
-  if ($rules) {
-    $manifest.Package.Applications.Application.RemoveChild($rules) | Out-Null
-  }
-  if ($acls -and ($acls -notcontains "*")) {
-    $rules = $manifest.CreateElement("ApplicationContentUriRules", $manifest.DocumentElement.NamespaceURI)
-    $manifest.Package.Applications.Application.AppendChild($rules) | Out-Null
-    $acls | foreach {
-      $elem = $manifest.CreateElement("Rule", $manifest.DocumentElement.NamespaceURI)
-      $elem.SetAttribute("Match", $_)
-      $elem.SetAttribute("Type", "include")
-      $rules.AppendChild($elem) | Out-Null
-    }
-  }
-
-  # Format splash screen background color to windows8 format
-  $configSplashScreenBGColor = $config.SelectNodes('//*[local-name()="preference"][@name="SplashScreenBackgroundColor"]').value
-  if($configSplashScreenBGColor) 
-  {
-    "Setting SplashScreenBackgroundColor = $configSplashScreenBGColor"
-
-    $bgColor = ($configSplashScreenBGColor -replace "0x", "") -replace "#", ""
-
-    # Double all bytes if color specified as "fff"
-    if ($bgColor.Length -eq 3) {
-      $bgColor = $bgColor[0] + $bgColor[0] + $bgColor[1] + $bgColor[1] + $bgColor[2] + $bgColor[2] 
-    }
-
-    # Parse hex representation to array of color bytes [b, g, r, a]
-    $colorBytes = [System.BitConverter]::GetBytes(
-      [int]::Parse($bgColor,
-      [System.Globalization.NumberStyles]::HexNumber))
-
-    Add-Type -AssemblyName PresentationCore
-
-    # Create new Color object ignoring alpha, because windows 8 doesn't support it
-    # see http://msdn.microsoft.com/en-us/library/windows/apps/br211471.aspx
-    $color = ([System.Windows.Media.Color]::FromRgb(
-      $colorBytes[2], $colorBytes[1], $colorBytes[0]
-      # FromRGB method add 100% alpha, so we remove it from resulting string
-      ).ToString()) -replace "#FF", "#"
-
-    $manifest.Package.Applications.Application.VisualElements.SplashScreen.BackgroundColor = [string]$color
-  }
-
-  # Format background color to windows format
-
-  $configBgColor = $config.SelectNodes('//*[local-name()="preference"][@name="BackgroundColor"]').value
-  if ($configBgColor) {
-    $bgColor = ($configBgColor -replace "0x", "") -replace "#", ""
-
-    # Double all bytes if color specified as "fff"
-    if ($bgColor.Length -eq 3) {
-      $bgColor = $bgColor[0] + $bgColor[0] + $bgColor[1] + $bgColor[1] + $bgColor[2] + $bgColor[2] 
-    }
-
-    # Parse hex representation to array of color bytes [b, g, r, a]
-    $colorBytes = [System.BitConverter]::GetBytes(
-      [int]::Parse($bgColor, [System.Globalization.NumberStyles]::HexNumber)
-    )
-
-    Add-Type -AssemblyName PresentationCore
-
-    # Create new Color object ignoring alpha, because windows doesn't support it
-    # see http://msdn.microsoft.com/en-us/library/windows/apps/dn423310.aspx
-    $color = ([System.Windows.Media.Color]::FromRgb(
-      $colorBytes[2], $colorBytes[1], $colorBytes[0]
-      # FromRGB method add 100% alpha, so we remove it from resulting string
-      ).ToString()) -replace "#FF", "#"
-
-    $manifest.Package.Applications.Application.VisualElements.BackgroundColor = [string]$color
-  }
-
-  # Write out manifest file
-
-  $xmlWriter = New-Object System.Xml.XmlTextWriter($manifestFile, $null)
-  $xmlWriter.Formatting = "Indented"
-  $xmlWriter.Indentation = 4
-  $manifest.WriteContentTo($xmlWriter)
-  $xmlWriter.Close()
-}
-
-Function CopyImage($src, $dest) 
-{
-  $resolvedPath = $null;
-
-  # do search relative to platform and app folders
-  foreach ($testPath in @($src, "..\..\$src")) 
-  {
-    $testPath = join-path $platformRoot $testPath
-    if (Test-Path -PathType Leaf $testPath)
-    {
-      $resolvedPath = $testPath;
-      break
-    }
-  }
-
-  if ($resolvedPath -eq $null)
-  {
-      Write-Host "Image doesn't exist: $src"
-      return
-  }
-  Copy-Item $resolvedPath -Destination (join-path $platformRoot $dest)
-}
-
-Function Get-Access-Rules () 
-{
-  $aclsAll = ([string[]]$config.widget.access.origin)
-  if ($aclsAll -eq $null) {
-    return @();
-  }
-
-  $acls = @()
- 
-  $aclsAll | foreach {
-      if ($_.StartsWith("https://","CurrentCultureIgnoreCase") -or ($_ -eq "*")) {
-        $acls += $_
-      } else {
-        Write-Host "Access rules must begin with 'https://', the following rule is ignored: $_"
-      }
-    }
-  return $acls
-}
-
-Function UpdateAssets ()
-{
-  $configFile = "$platformRoot\config.xml"
-  [xml]$config = Get-Content $configFile
-
-  # Splash screen images
-  $splashScreens = $config.SelectNodes('//*[local-name()="splash"]')
-
-  foreach ($splash in $splashScreens)
-  {
-    $width = $splash.getAttribute("width")
-    $height= $splash.getAttribute("height")
-    $src = $splash.getAttribute("src")
-    if ($width -eq 620 -and $height -eq 300) {
-      CopyImage $src "images/splashscreen.png"
-      continue
-    }
-    if ($width -eq 1152 -and $height -eq 1920) {
-      CopyImage $src "images/SplashScreen.scale-240.png"
-      continue
-    }
-     Write-Host "Unknown image ($src) size, skip"
-  }
-
-  # App icons
-  $configIcons= $config.SelectNodes('//*[local-name()="icon"]')
-
-  foreach ($icon in $configIcons)
-  {
-    $width = $icon.getAttribute("width")
-    $height= $icon.getAttribute("height")
-    $src = $icon.getAttribute("src")
-
-    if ($width -eq 150) {
-      CopyImage $src "images/logo.png"
-      continue
-    }
-    if ($width -eq 30) {
-      CopyImage $src "images/smalllogo.png"
-      continue
-    }
-    if ($width -eq 50) {
-      CopyImage $src "images/storelogo.png"
-      continue
-    }
-    if ($width -eq 120) {
-      CopyImage $src "images/StoreLogo.scale-240.png"
-      continue
-    }
-
-    if ($width -eq 106) {
-      CopyImage $src "images/Square44x44Logo.scale-240.png"
-      continue
-    }
-    if ($width -eq 170) {
-      CopyImage $src "images/Square71x71Logo.scale-240.png"
-      continue
-    }
-    if ($width -eq 360) {
-      CopyImage $src "images/Square150x150Logo.scale-240.png"
-      continue
-    }
-    if ($width -eq 744 -and $height -eq 360) {
-      CopyImage $src "images/Wide310x150Logo.scale-240.png"
-      continue
-    }
-
-     Write-Host "Unknown image ($src) size, skip"
-  }
-
-}
-
-$configFile = "$platformRoot\config.xml"
-[xml]$config = Get-Content $configFile -Encoding UTF8
-
-# Domain whitelist rules defined in configuration file
-$acls = Get-Access-Rules $config
-
-UpdateManifest "$platformRoot\package.windows.appxmanifest"
-UpdateManifest "$platformRoot\package.windows80.appxmanifest"
-UpdateManifest "$platformRoot\package.phone.appxmanifest"
-
-# replace splash screen images and icons
-UpdateAssets

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/93d463d8/windows/template/cordova/lib/ConfigParser.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/ConfigParser.js b/windows/template/cordova/lib/ConfigParser.js
index 31a53e6..36a3e9d 100644
--- a/windows/template/cordova/lib/ConfigParser.js
+++ b/windows/template/cordova/lib/ConfigParser.js
@@ -73,6 +73,13 @@ ConfigParser.prototype = {
         var el = findOrCreate(this.doc, 'name');
         el.text = name;
     },
+    startPage: function() {
+        var content = this.doc.find('content');
+        if (content) {
+            return content.attrib.src;
+        }
+        return null;
+    },
     description: function() {
         return this.doc.find('description').text.trim();
     },
@@ -200,6 +207,21 @@ ConfigParser.prototype = {
      */
     getSplashScreens: function(platform) {
         return this.getStaticResources(platform, 'splash');
+    },
+
+    /**
+     * Returns all access rules.
+     * @return {string[]}      Array of access rules.
+     */
+    getAccessRules: function() { 
+        var rules = this.doc.getroot().findall('access'); 
+        var ret = []; 
+        rules.forEach(function (rule) { 
+         if (rule.attrib.origin) {
+             ret.push(rule.attrib.origin); 
+         } 
+        }); 
+        return ret; 
     }
 };
 

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/93d463d8/windows/template/cordova/lib/build.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/build.js b/windows/template/cordova/lib/build.js
index 0281dbb..5af4ba0 100644
--- a/windows/template/cordova/lib/build.js
+++ b/windows/template/cordova/lib/build.js
@@ -22,6 +22,7 @@ var Q     = require('Q'),
     nopt  = require('nopt'),
     spawn = require('./spawn'),
     utils = require('./utils'),
+    prepare = require('./prepare'),
     MSBuildTools = require('./MSBuildTools'),
     ConfigParser = require('./ConfigParser');
 
@@ -55,11 +56,14 @@ module.exports.run = function run (argv) {
         return Q.reject(error);
     }
 
+    // update platform as per configuration settings
+    prepare.applyPlatformConfig();
+
     return MSBuildTools.findAvailableVersion().then(
         function(msbuildTools) {
             msbuild = msbuildTools;
             console.log('MSBuildToolsPath: ' + msbuild.path);
-            return applyPlatformConfig().then(buildTargets);
+            return buildTargets();
         });
 };
 
@@ -130,13 +134,6 @@ function buildTargets() {
     }, Q()); 
 }
 
-function applyPlatformConfig() {
-    // run powershell ApplyPlatformConfig.ps1
-    return utils.getApplyPlatformConfigScript().then(function(ApplyPlatformConfigScript) {
-        return spawn('Powershell', ['-ExecutionPolicy', 'RemoteSigned', '-File',  ApplyPlatformConfigScript, ROOT]);
-    });
-}
-
 function getBuildTargets() {
     var config = new ConfigParser(path.join(ROOT, 'config.xml'));
     var targets = [];

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/93d463d8/windows/template/cordova/lib/prepare.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/prepare.js b/windows/template/cordova/lib/prepare.js
new file mode 100644
index 0000000..ed159a0
--- /dev/null
+++ b/windows/template/cordova/lib/prepare.js
@@ -0,0 +1,261 @@
+/*
+       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.
+*/
+
+var path  = require('path'),
+    fs  = require('fs'),
+    et = require('elementtree'),
+    shell = require('shelljs'),
+    ConfigParser = require('./ConfigParser');
+
+var ROOT = path.join(__dirname, '..', '..'),
+    accessRules;
+
+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;
+    });
+
+    ['package.windows.appxmanifest', 'package.windows80.appxmanifest', 'package.phone.appxmanifest'].forEach(
+        function(manifestFile) {
+            updateManifestFile(config, path.join(ROOT, manifestFile));
+    })
+
+    copyImages(config);
+}
+
+function updateManifestFile (config, manifestPath) {
+
+    var contents = fs.readFileSync(manifestPath, 'utf-8');
+    if(contents) {
+        //Windows is the BOM. Skip the Byte Order Mark.
+        contents = contents.substring(contents.indexOf('<'));
+    };
+
+    var manifest =  new et.ElementTree(et.XML(contents));
+
+    applyCoreProperties(config, manifest);
+    // sort Capability elements as per CB-5350 Windows8 build fails due to invalid 'Capabilities' definition
+    sortCapabilities(manifest);
+    applyAccessRules(config, manifest);
+    applyBackgroundColor(config, manifest);
+
+    //Write out manifest
+    fs.writeFileSync(manifestPath, manifest.write({indent: 4}), 'utf-8');
+}
+
+function applyCoreProperties(config, manifest) {
+    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) {
+        throw new Error('Invalid manifest file (no <Identity> node): ' + manifestPath);
+    }
+    // Update identity name and version
+    pkgName && (identityNode.attrib.Name = pkgName);
+    version && (identityNode.attrib.Version = version);
+
+    // Update name (windows8 has it in the Application[@Id] and Application.VisualElements[@DisplayName])
+    var app = manifest.find('.//Application');
+    if(!app) {
+        throw new Error('Invalid manifest file (no <Application> node): ' + manifestPath);
+    }
+    if (pkgName) {
+        // 64 symbols restriction goes from manifest schema definition
+        // http://msdn.microsoft.com/en-us/library/windows/apps/br211415.aspx
+        var appId = pkgName.length <= 64 ? pkgName : pkgName.substr(0, 64);
+        app.attrib.Id = appId;
+    }
+    app.attrib.StartPage = 'www/' + startPage;
+
+    var visualElems = manifest.find('.//VisualElements') // windows 8.0
+        || manifest.find('.//m2:VisualElements') // windows 8.1
+        || manifest.find('.//m3:VisualElements'); // windows phone 8.1
+
+    if(!visualElems) {
+        throw new Error('Invalid manifest file (no <VisualElements> node): ' + manifestPath);
+    }
+    name && (visualElems.attrib.DisplayName = name);
+
+    // Update properties
+    var properties = manifest.find('.//Properties');
+    if (properties && properties.find) {
+        var displayNameElement = properties.find('.//DisplayName');
+        if (displayNameElement && name) {
+            displayNameElement.text = name;
+        }
+
+        var publisherNameElement = properties.find('.//PublisherDisplayName');
+        if (publisherNameElement && author) {
+            publisherNameElement.text = author;
+        }
+    }
+}
+
+// Adjust version number as per CB-5337 Windows8 build fails due to invalid app version
+function fixConfigVersion (version) {
+    if(version && version.match(/\.\d/g)) {
+        var numVersionComponents = version.match(/\.\d/g).length + 1;
+        while (numVersionComponents++ < 4) {
+            version += '.0';
+        }
+    }
+    return version;
+}
+
+function applyAccessRules (config, manifest) {
+    // Updates WhiteListing rules
+    //<ApplicationContentUriRules>
+    //    <Rule Match="https://www.example.com" Type="include"/>
+    //</ApplicationContentUriRules>
+    var appUriRulesRoot = manifest.find('.//Application'),
+        appUriRules = appUriRulesRoot.find('.//ApplicationContentUriRules');
+
+    if (appUriRules != null) {
+        appUriRulesRoot.remove(null, appUriRules);
+    }
+    // rules are not defined or allow any
+    if (accessRules.length == 0 || accessRules.indexOf('*') > -1) {
+        return;
+    } 
+
+    appUriRules = et.Element('ApplicationContentUriRules');
+    appUriRulesRoot.append(appUriRules);
+
+    accessRules.forEach(function(rule) {
+        var el = et.Element('Rule')
+        el.attrib.Match = rule;
+        el.attrib.Type = 'include';
+        appUriRules.append(el);
+    });
+}
+
+function sortCapabilities(manifest) {
+    var capabilitiesRoot = manifest.find('.//Capabilities'),
+        capabilities = capabilitiesRoot._children || [];
+    // to sort elements we remove them and then add again in the appropriate order
+    capabilities.forEach(function(elem) { // no .clear() method
+        capabilitiesRoot.remove(0, elem);
+    });
+    capabilities.sort(function(a, b) {
+        return (a.tag > b.tag) ? 1: -1;
+    });
+    capabilities.forEach(function(elem){
+        capabilitiesRoot.append(elem);
+    });
+}
+
+function copyImages(config) {
+    var platformRoot = ROOT;
+    // TODO find the way to detect whether command was triggered by CLI or not
+    var appRoot = path.join(platformRoot, '..', '..');
+
+    function copyImage(src, dest) {
+        src = path.join(appRoot, src),
+        dest = path.join(platformRoot, dest);
+        console.log('Copying image from ' + src + ' to ' + dest);
+        shell.cp('-f', src, dest);
+    }
+
+    // Icons, supported by the platform
+    var platformIcons = [
+        {dest: 'images/logo.png', width: 150, height: 150},
+        {dest: 'images/smalllogo.png', width: 30, height: 30},
+        {dest: 'images/storelogo.png', width: 50, height: 50},
+        {dest: 'images/StoreLogo.scale-240.png', width: 120, height: 120},
+        {dest: 'images/Square44x44Logo.scale-240.png', width: 106, height: 106},
+        {dest: 'images/Square71x71Logo.scale-240.png', width: 170, height: 170},
+        {dest: 'images/Square150x150Logo.scale-240.png', width: 360, height: 360},
+        {dest: 'images/Wide310x150Logo.scale-240.png', width: 744, height: 360},
+    ];
+
+    var icons = config.getIcons();
+    platformIcons.forEach(function (item) {
+        var img = icons.getBySize(item.width, item.height);
+        if (img) {
+            copyImage(img.src, item.dest);
+        }
+    });
+
+    // Splash screen images, supported by the platform
+    var platformSplashImages = [
+        {dest: 'images/splashscreen.png', width: 620, height: 300},
+        {dest: 'images/SplashScreen.scale-240.png', width: 1152, height: 1920}
+    ];
+
+    var splashImages = config.getSplashScreens();
+
+    platformSplashImages.forEach(function (item) {
+        var img = splashImages.getBySize(item.width, item.height);
+        if (img) {
+            copyImage(img.src, item.dest);
+        }
+    });
+}
+
+function applyBackgroundColor (config, manifest) {
+
+    function refineColor(color) {
+        // return three-byte hexadecimal number preceded by "#" (required for Windows)
+        color = color.replace('0x', '').replace('#', '');
+        if (color.length == 3) {
+            color = color[0] + color[0] + color[1] + color[1] + color[2] + color[2]
+        }
+        // alpha is not supported, so we remove it
+        if (color.length == 8) { // AArrggbb
+            color = color.slice(2);
+        }
+        return '#' + color;
+    }
+    // background color
+    var bgColor = config.getPreference('BackgroundColor');
+    if (bgColor) {
+        var visualElems = manifest.find('.//VisualElements') // windows 8.0
+            || manifest.find('.//m2:VisualElements') // windows 8.1
+            || manifest.find('.//m3:VisualElements'); // windows phone 8.1
+        visualElems.attrib.BackgroundColor = refineColor(bgColor);
+    }
+
+    // Splash Screen background color
+    bgColor = config.getPreference('SplashScreenBackgroundColor');
+    if (bgColor) {
+        var visualElems = manifest.find('.//SplashScreen') // windows 8.0
+            || manifest.find('.//m2:SplashScreen') // windows 8.1
+            || manifest.find('.//m3:SplashScreen'); // windows phone 8.1
+        visualElems.attrib.BackgroundColor = refineColor(bgColor);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-windows/blob/93d463d8/windows/template/cordova/lib/utils.js
----------------------------------------------------------------------
diff --git a/windows/template/cordova/lib/utils.js b/windows/template/cordova/lib/utils.js
index 12282e7..c409b86 100644
--- a/windows/template/cordova/lib/utils.js
+++ b/windows/template/cordova/lib/utils.js
@@ -63,20 +63,6 @@ module.exports.getAppStoreUtils = function () {
     });
 };
 
-// unblocks and returns path to ApplyPlatformConfig.ps1
-module.exports.getApplyPlatformConfigScript = function () {
-    var scriptPath = path.join(__dirname, 'ApplyPlatformConfig.ps1');
-    if (!fs.existsSync (scriptPath)) {
-        return Q.reject("Can't unblock ApplyPlatformConfig.ps1 script");
-    }
-    //console.log("Removing execution restrictions from ApplyPlatformConfig...");
-    return spawn('powershell', ['Unblock-File', module.exports.quote(scriptPath)]).then(function () {
-        return Q.resolve(scriptPath);
-    }).fail(function (err) {
-        return Q.reject(err);
-    });
-};
-
 // 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"]),