CB-11968: Added support for <config-file> in config.xml
authorNikita Matrosov <v-nimatr@microsoft.com>
Fri, 28 Jul 2017 12:35:41 +0000 (15:35 +0300)
committerSteve Gill <stevengill97@gmail.com>
Wed, 23 Aug 2017 01:00:25 +0000 (18:00 -0700)
 This closes #2

spec/ConfigChanges/ConfigChanges.spec.js
spec/ConfigParser/ConfigParser.spec.js
spec/fixtures/test-config.xml
spec/fixtures/test-configfile.xml [new file with mode: 0644]
src/ConfigChanges/ConfigChanges.js
src/ConfigParser/ConfigParser.js

index 79e109a..ec7f250 100644 (file)
@@ -45,6 +45,7 @@ var PluginInfo = require('../../src/PluginInfo/PluginInfo');
 var ConfigParser = require('../../src/ConfigParser/ConfigParser');
 var xml = path.join(__dirname, '../fixtures/test-config.xml');
 var editconfig_xml = path.join(__dirname, '../fixtures/test-editconfig.xml');
+var configfile_xml = path.join(__dirname, '../fixtures/test-configfile.xml');
 var cfg = new ConfigParser(xml);
 
 // TODO: dont do fs so much
@@ -374,6 +375,25 @@ describe('config-changes module', function () {
                     expect(sdk.attrib['android:minSdkVersion']).toEqual('5');
                     expect(sdk.attrib['android:maxSdkVersion']).toBeUndefined();
                 });
+                it('should append new children to XML document tree', function () {
+                    var configfile_cfg = new ConfigParser(configfile_xml);
+                    var platformJson = PlatformJson.load(plugins_dir, 'android');
+                    var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                    munger.add_config_changes(configfile_cfg, true).save_all();
+                    var am_xml = new et.ElementTree(et.XML(fs.readFileSync(path.join(temp, 'AndroidManifest.xml'), 'utf-8')));
+                    var activity = am_xml.find('./application/activity[@android:name="com.foo.Bar"]');
+                    expect(activity).toBeDefined();
+                    expect(activity.attrib['android:label']).toEqual('@string/app_name');
+                });
+                // testing the "after" attribute of the <config-file> tag in config.xml
+                it('should append new children to XML document tree in the correct order', function () {
+                    var configfile_cfg = new ConfigParser(configfile_xml);
+                    var platformJson = PlatformJson.load(plugins_dir, 'android');
+                    var munger = new configChanges.PlatformMunger('android', temp, platformJson, pluginInfoProvider);
+                    munger.add_config_changes(configfile_cfg, true).save_all();
+                    var am_file = fs.readFileSync(path.join(temp, 'AndroidManifest.xml'), 'utf-8');
+                    expect(am_file.indexOf('android:name="zoo"')).toBeLessThan(am_file.indexOf('android:name="com.foo.Bar"'));
+                });
                 it('should throw error for conflicting plugin config munge with config.xml config munge', function () {
                     shell.cp('-rf', editconfigplugin_two, plugins_dir);
                     var platformJson = PlatformJson.load(plugins_dir, 'android');
index 1075e83..2129565 100644 (file)
@@ -245,10 +245,14 @@ describe('config.xml parser', function () {
                 var intents = cfg.getAllowIntents();
                 expect(intents.length).not.toEqual(0);
             });
-            it('it should read <edit-config> tag entries', function () {
+            it('Test 035: it should read <edit-config> tag entries', function () {
                 var editConfigs = cfg.getEditConfigs('android');
                 expect(editConfigs.length).not.toEqual(0);
             });
+            it('Test 036: it should read <config-file> tag entries', function () {
+                var configFiles = cfg.getConfigFiles('android');
+                expect(configFiles.length).not.toEqual(0);
+            });
         });
         describe('static resources', function () {
             var hasPlatformPropertyDefined = function (e) { return !!e.platform; };
index 7969d64..5dd79e6 100644 (file)
         <edit-config file="AndroidManifest.xml" target="/manifest/uses-sdk" mode="remove">
             <uses-sdk android:maxSdkVersion="24" />
         </edit-config>
+        <config-file target="AndroidManifest.xml" parent="/manifest/application">
+            <activity android:name="com.foo.Foo" android:label="@string/app_name">
+                <intent-filter>
+                </intent-filter>
+            </activity>
+        </config-file>
     </platform>
     <platform name="windows">
         <icon src="res/windows/logo.scale-200.png" target="logo.png"/>
diff --git a/spec/fixtures/test-configfile.xml b/spec/fixtures/test-configfile.xml
new file mode 100644 (file)
index 0000000..4ca15cd
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget android-packageName="io.cordova.hellocordova.android" id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0" xmlns:android="http://schemas.android.com/apk/res/android">
+    <name>Hello Cordova</name>
+    <description>
+        A sample Apache Cordova application that responds to the deviceready event.
+    </description>
+    <author email="dev@cordova.apache.org" href="http://cordova.io">
+        Apache Cordova Team
+    </author>
+    <content src="index.html" />
+    <access origin="*" />
+    <platform name="android">
+        <config-file parent="/manifest/application" target="AndroidManifest.xml">
+            <meta-data android:name="zoo" android:value="@string/kangaroo" />
+        </config-file>
+        <config-file target="AndroidManifest.xml" parent="/manifest/application" after="meta-data">
+            <activity android:name="com.foo.Bar" android:label="@string/app_name">
+                <intent-filter>
+                </intent-filter>
+            </activity>
+        </config-file>
+    </platform>
+</widget>
index f0cf8d9..e0af8a9 100644 (file)
@@ -168,17 +168,24 @@ function add_config_changes (config, should_increment) {
     var platform_config = self.platformJson.root;
 
     var config_munge;
-    var edit_config_changes = null;
+    var changes = [];
+
     if (config.getEditConfigs) {
-        edit_config_changes = config.getEditConfigs(self.platform);
+        var edit_config_changes = config.getEditConfigs(self.platform);
+        if (edit_config_changes) {
+            changes = changes.concat(edit_config_changes);
+        }
     }
 
-    if (!edit_config_changes || edit_config_changes.length === 0) {
-        // There are no edit-config changes to add, return here
-        return self;
-    } else {
-        var isConflictingInfo = is_conflicting(edit_config_changes, platform_config.config_munge, self, true /* always force overwrite other edit-config */);
+    if (config.getConfigFiles) {
+        var config_files_changes = config.getConfigFiles(self.platform);
+        if (config_files_changes) {
+            changes = changes.concat(config_files_changes);
+        }
+    }
 
+    if (changes && changes.length > 0) {
+        var isConflictingInfo = is_conflicting(changes, platform_config.config_munge, self, true /* always force overwrite other edit-config */);
         if (isConflictingInfo.conflictFound) {
             var conflict_munge;
             var conflict_file;
@@ -200,10 +207,10 @@ function add_config_changes (config, should_increment) {
                 }
             }
         }
-        // Add config.xml edit-config munges
-        config_munge = self.generate_config_xml_munge(config, edit_config_changes, 'config.xml');
     }
 
+    // Add config.xml edit-config and config-file munges
+    config_munge = self.generate_config_xml_munge(config, changes, 'config.xml');
     self = munge_helper(should_increment, self, platform_config, config_munge);
 
     // Move to installed/dependent_plugins
@@ -251,13 +258,11 @@ function reapply_global_munge () {
 // generate_plugin_config_munge
 // Generate the munge object from config.xml
 PlatformMunger.prototype.generate_config_xml_munge = generate_config_xml_munge;
-function generate_config_xml_munge (config, edit_config_changes, type) {
-
+function generate_config_xml_munge (config, config_changes, type) {
     var munge = { files: {} };
-    var changes = edit_config_changes;
     var id;
 
-    if (!changes) {
+    if (!config_changes) {
         return munge;
     }
 
@@ -267,13 +272,15 @@ function generate_config_xml_munge (config, edit_config_changes, type) {
         id = config.id;
     }
 
-    changes.forEach(function (change) {
+    config_changes.forEach(function (change) {
         change.xmls.forEach(function (xml) {
             // 1. stringify each xml
             var stringified = (new et.ElementTree(xml)).write({xml_declaration: false});
             // 2. add into munge
             if (change.mode) {
                 mungeutil.deep_add(munge, change.file, change.target, { xml: stringified, count: 1, mode: change.mode, id: id });
+            } else {
+                mungeutil.deep_add(munge, change.target, change.parent, { xml: stringified, count: 1, after: change.after });
             }
         });
     });
index ebaa2a3..e2c41bc 100644 (file)
@@ -554,6 +554,29 @@ ConfigParser.prototype = {
             return editConfig;
         });
     },
+
+    /* Get all config-file tags */
+    getConfigFiles: function (platform) {
+        var platform_tag = this.doc.find('./platform[@name="' + platform + '"]');
+        var platform_config_files = platform_tag ? platform_tag.findall('config-file') : [];
+
+        var config_files = this.doc.findall('config-file').concat(platform_config_files);
+
+        return config_files.map(function (tag) {
+            var configFile =
+                {
+                    target: tag.attrib['target'],
+                    parent: tag.attrib['parent'],
+                    after: tag.attrib['after'],
+                    xmls: tag.getchildren(),
+                    // To support demuxing via versions
+                    versions: tag.attrib['versions'],
+                    deviceTarget: tag.attrib['device-target']
+                };
+            return configFile;
+        });
+    },
+
     write: function () {
         fs.writeFileSync(this.path, this.doc.write({indent: 4}), 'utf-8');
     }