You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by er...@apache.org on 2020/12/26 06:31:35 UTC
[cordova-electron] branch master updated: breaking: add plugin
support (#175)
This is an automated email from the ASF dual-hosted git repository.
erisu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-electron.git
The following commit(s) were added to refs/heads/master by this push:
new 1fa798e breaking: add plugin support (#175)
1fa798e is described below
commit 1fa798e4c370a25c9267a2e2919a7b2afbdb9daf
Author: エリス <er...@users.noreply.github.com>
AuthorDate: Sat Dec 26 15:31:25 2020 +0900
breaking: add plugin support (#175)
* feat: add main icp handler for plugin communication
* feat: pass plugin dir path to uninstall step for framework
* feat: support framework un/install w/ package parser update
* feat: do not overwrite platform installed node_modules and package.json
* feat: update exec to support electron with browser fallback
* feat: add render to main connection layer with preloader
* feat: update cordova.js with exec changes
* chore: various fixes & lint correction
* test: updated use cases
* test: plugin support coverage w/ cleanup & fix
* fix: plugin uninstall & emit msg w/ coverage
* chore: lowered successful delinking loglevel to verbose
---
.eslintignore | 1 +
bin/templates/platform_www/cdv-electron-main.js | 19 +-
bin/templates/platform_www/cdv-electron-preload.js | 16 ++
cordova-js-src/exec.js | 110 +++++----
cordova-lib/cordova.js | 112 +++++----
lib/Api.js | 2 +-
lib/PackageJsonParser.js | 74 ++----
lib/handler.js | 113 ++++++++-
lib/parser.js | 5 +-
lib/prepare.js | 4 +-
.../test-app-with-electron-plugin/config.xml | 18 ++
.../test-app-with-electron-plugin/package.json | 22 ++
.../platforms/electron/config.xml | 18 ++
.../platforms/electron/cordova/Api.js | 24 ++
.../platforms/electron/cordova/defaults.xml | 21 ++
.../platforms/electron/cordova/version | 23 ++
.../platforms/electron/cordova/version.bat | 26 ++
.../platforms/electron/electron.json | 14 ++
.../platforms/electron/platform_www/config.xml | 22 ++
.../platforms/electron/www/config.xml | 18 ++
.../platforms/electron/www/cordova_plugins.js | 8 +
.../platforms/electron/www/package.json | 15 ++
.../plugins/cordova-plugin-device/package.json | 46 ++++
.../plugins/cordova-plugin-device/plugin.xml | 40 +++
.../cordova-plugin-device/src/electron/index.js | 22 ++
.../src/electron/package.json | 20 ++
.../plugins/cordova-plugin-device/www/device.js | 85 +++++++
.../test-app-with-electron-plugin/www/index.html | 34 +++
tests/spec/unit/lib/PackageJsonParser.spec.js | 118 ++-------
tests/spec/unit/lib/handler.spec.js | 270 ++++++++++++++++++++-
30 files changed, 1049 insertions(+), 271 deletions(-)
diff --git a/.eslintignore b/.eslintignore
index 170e18d..4c5b690 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,2 +1,3 @@
cordova-lib/cordova.js
bin/templates/platform_www/cordova.js
+tests/spec/fixtures/test-app-with-electron-plugin/
\ No newline at end of file
diff --git a/bin/templates/platform_www/cdv-electron-main.js b/bin/templates/platform_www/cdv-electron-main.js
index c8d4968..32f9258 100644
--- a/bin/templates/platform_www/cdv-electron-main.js
+++ b/bin/templates/platform_www/cdv-electron-main.js
@@ -19,11 +19,13 @@
const fs = require('fs');
const path = require('path');
+const { cordova } = require('./package.json');
// Module to control application life, browser window and tray.
const {
app,
BrowserWindow,
- protocol
+ protocol,
+ ipcMain
} = require('electron');
// Electron settings from .json file.
const cdvElectronSettings = require('./cdv-electron-settings.json');
@@ -70,6 +72,9 @@ function createWindow () {
}
const browserWindowOpts = Object.assign({}, cdvElectronSettings.browserWindow, { icon: appIcon });
+ browserWindowOpts.webPreferences.preload = path.join(app.getAppPath(), 'cdv-electron-preload.js');
+ browserWindowOpts.webPreferences.contextIsolation = true;
+
mainWindow = new BrowserWindow(browserWindowOpts);
// Load a local HTML file or a remote URL.
@@ -141,5 +146,17 @@ app.on('activate', () => {
}
});
+ipcMain.handle('cdv-plugin-exec', async (_, serviceName, action, ...args) => {
+ if (cordova && cordova.services && cordova.services[serviceName]) {
+ const plugin = require(cordova.services[serviceName]);
+
+ return plugin[action]
+ ? plugin[action](args)
+ : Promise.reject(new Error(`The action "${action}" for the requested plugin service "${serviceName}" does not exist.`));
+ } else {
+ return Promise.reject(new Error(`The requested plugin service "${serviceName}" does not exist have native support.`));
+ }
+});
+
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
diff --git a/bin/templates/platform_www/cdv-electron-preload.js b/bin/templates/platform_www/cdv-electron-preload.js
new file mode 100644
index 0000000..704085e
--- /dev/null
+++ b/bin/templates/platform_www/cdv-electron-preload.js
@@ -0,0 +1,16 @@
+const { contextBridge, ipcRenderer } = require('electron');
+const { cordova } = require('./package.json');
+
+contextBridge.exposeInMainWorld('_cdvElectronIpc', {
+ exec: (success, error, serviceName, action, args) => {
+ return ipcRenderer.invoke('cdv-plugin-exec', serviceName, action, args)
+ .then(
+ success,
+ error
+ );
+ },
+
+ hasService: (serviceName) => cordova &&
+ cordova.services &&
+ cordova.services[serviceName]
+});
diff --git a/cordova-js-src/exec.js b/cordova-js-src/exec.js
index 6d21761..1a91e6c 100644
--- a/cordova-js-src/exec.js
+++ b/cordova-js-src/exec.js
@@ -39,65 +39,71 @@ const execProxy = require('cordova/exec/proxy');
* @param {String[]} [args] Zero or more arguments to pass to the method
*/
module.exports = function (success, fail, service, action, args) {
- var proxy = execProxy.get(service, action);
+ if (window._cdvElectronIpc.hasService(service)) {
+ // Electron based plugin support
+ window._cdvElectronIpc.exec(success, fail, service, action, args);
+ } else {
+ // Fall back for browser based plugin support...
+ const proxy = execProxy.get(service, action);
- args = args || [];
+ args = args || [];
- if (proxy) {
- var callbackId = service + cordova.callbackId++;
+ if (proxy) {
+ var callbackId = service + cordova.callbackId++;
- if (typeof success === 'function' || typeof fail === 'function') {
- cordova.callbacks[callbackId] = { success: success, fail: fail };
- }
- try {
- // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
- // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
- var onSuccess = function (result, callbackOptions) {
- callbackOptions = callbackOptions || {};
- var callbackStatus;
- // covering both undefined and null.
- // strict null comparison was causing callbackStatus to be undefined
- // and then no callback was called because of the check in cordova.callbackFromNative
- // see CB-8996 Mobilespec app hang on windows
- if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
- callbackStatus = callbackOptions.status;
- } else {
- callbackStatus = cordova.callbackStatus.OK;
- }
- cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
- {
+ if (typeof success === 'function' || typeof fail === 'function') {
+ cordova.callbacks[callbackId] = { success: success, fail: fail };
+ }
+ try {
+ // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
+ // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
+ var onSuccess = function (result, callbackOptions) {
+ callbackOptions = callbackOptions || {};
+ var callbackStatus;
+ // covering both undefined and null.
+ // strict null comparison was causing callbackStatus to be undefined
+ // and then no callback was called because of the check in cordova.callbackFromNative
+ // see CB-8996 Mobilespec app hang on windows
+ if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+ callbackStatus = callbackOptions.status;
+ } else {
+ callbackStatus = cordova.callbackStatus.OK;
+ }
+ cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
+ {
+ status: callbackStatus,
+ message: result,
+ keepCallback: callbackOptions.keepCallback || false
+ });
+ };
+ var onError = function (err, callbackOptions) {
+ callbackOptions = callbackOptions || {};
+ var callbackStatus;
+ // covering both undefined and null.
+ // strict null comparison was causing callbackStatus to be undefined
+ // and then no callback was called because of the check in cordova.callbackFromNative
+ // note: status can be 0
+ if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+ callbackStatus = callbackOptions.status;
+ } else {
+ callbackStatus = cordova.callbackStatus.OK;
+ }
+ cordova.callbackError(callbackOptions.callbackId || callbackId, {
status: callbackStatus,
- message: result,
+ message: err,
keepCallback: callbackOptions.keepCallback || false
});
- };
- var onError = function (err, callbackOptions) {
- callbackOptions = callbackOptions || {};
- var callbackStatus;
- // covering both undefined and null.
- // strict null comparison was causing callbackStatus to be undefined
- // and then no callback was called because of the check in cordova.callbackFromNative
- // note: status can be 0
- if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
- callbackStatus = callbackOptions.status;
- } else {
- callbackStatus = cordova.callbackStatus.OK;
- }
- cordova.callbackError(callbackOptions.callbackId || callbackId, {
- status: callbackStatus,
- message: err,
- keepCallback: callbackOptions.keepCallback || false
- });
- };
- proxy(onSuccess, onError, args);
- } catch (e) {
- console.log('Exception calling native with command :: ' + service + ' :: ' + action + ' ::exception=' + e);
- }
- } else {
- console.log('Error: exec proxy not found for :: ' + service + ' :: ' + action);
+ };
+ proxy(onSuccess, onError, args);
+ } catch (e) {
+ console.log('Exception calling native with command :: ' + service + ' :: ' + action + ' ::exception=' + e);
+ }
+ } else {
+ console.log('Error: exec proxy not found for :: ' + service + ' :: ' + action);
- if (typeof fail === 'function') {
- fail('Missing Command Error');
+ if (typeof fail === 'function') {
+ fail('Missing Command Error');
+ }
}
}
};
diff --git a/cordova-lib/cordova.js b/cordova-lib/cordova.js
index 4a3a4c1..12474a5 100644
--- a/cordova-lib/cordova.js
+++ b/cordova-lib/cordova.js
@@ -1,5 +1,5 @@
// Platform: electron
-// 538a985db128858c0a0eb4dd40fb9c8e5433fc94
+// d66ee158a971168ea9619a1bc854055582ba0e84
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
@@ -962,65 +962,71 @@ const execProxy = require('cordova/exec/proxy');
* @param {String[]} [args] Zero or more arguments to pass to the method
*/
module.exports = function (success, fail, service, action, args) {
- var proxy = execProxy.get(service, action);
+ if (window._cdvElectronIpc.hasService(service)) {
+ // Electron based plugin support
+ window._cdvElectronIpc.exec(success, fail, service, action, args);
+ } else {
+ // Fall back for browser based plugin support...
+ const proxy = execProxy.get(service, action);
- args = args || [];
+ args = args || [];
- if (proxy) {
- var callbackId = service + cordova.callbackId++;
+ if (proxy) {
+ var callbackId = service + cordova.callbackId++;
- if (typeof success === 'function' || typeof fail === 'function') {
- cordova.callbacks[callbackId] = { success: success, fail: fail };
- }
- try {
- // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
- // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
- var onSuccess = function (result, callbackOptions) {
- callbackOptions = callbackOptions || {};
- var callbackStatus;
- // covering both undefined and null.
- // strict null comparison was causing callbackStatus to be undefined
- // and then no callback was called because of the check in cordova.callbackFromNative
- // see CB-8996 Mobilespec app hang on windows
- if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
- callbackStatus = callbackOptions.status;
- } else {
- callbackStatus = cordova.callbackStatus.OK;
- }
- cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
- {
+ if (typeof success === 'function' || typeof fail === 'function') {
+ cordova.callbacks[callbackId] = { success: success, fail: fail };
+ }
+ try {
+ // callbackOptions param represents additional optional parameters command could pass back, like keepCallback or
+ // custom callbackId, for example {callbackId: id, keepCallback: true, status: cordova.callbackStatus.JSON_EXCEPTION }
+ var onSuccess = function (result, callbackOptions) {
+ callbackOptions = callbackOptions || {};
+ var callbackStatus;
+ // covering both undefined and null.
+ // strict null comparison was causing callbackStatus to be undefined
+ // and then no callback was called because of the check in cordova.callbackFromNative
+ // see CB-8996 Mobilespec app hang on windows
+ if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+ callbackStatus = callbackOptions.status;
+ } else {
+ callbackStatus = cordova.callbackStatus.OK;
+ }
+ cordova.callbackSuccess(callbackOptions.callbackId || callbackId,
+ {
+ status: callbackStatus,
+ message: result,
+ keepCallback: callbackOptions.keepCallback || false
+ });
+ };
+ var onError = function (err, callbackOptions) {
+ callbackOptions = callbackOptions || {};
+ var callbackStatus;
+ // covering both undefined and null.
+ // strict null comparison was causing callbackStatus to be undefined
+ // and then no callback was called because of the check in cordova.callbackFromNative
+ // note: status can be 0
+ if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
+ callbackStatus = callbackOptions.status;
+ } else {
+ callbackStatus = cordova.callbackStatus.OK;
+ }
+ cordova.callbackError(callbackOptions.callbackId || callbackId, {
status: callbackStatus,
- message: result,
+ message: err,
keepCallback: callbackOptions.keepCallback || false
});
- };
- var onError = function (err, callbackOptions) {
- callbackOptions = callbackOptions || {};
- var callbackStatus;
- // covering both undefined and null.
- // strict null comparison was causing callbackStatus to be undefined
- // and then no callback was called because of the check in cordova.callbackFromNative
- // note: status can be 0
- if (callbackOptions.status !== undefined && callbackOptions.status !== null) {
- callbackStatus = callbackOptions.status;
- } else {
- callbackStatus = cordova.callbackStatus.OK;
- }
- cordova.callbackError(callbackOptions.callbackId || callbackId, {
- status: callbackStatus,
- message: err,
- keepCallback: callbackOptions.keepCallback || false
- });
- };
- proxy(onSuccess, onError, args);
- } catch (e) {
- console.log('Exception calling native with command :: ' + service + ' :: ' + action + ' ::exception=' + e);
- }
- } else {
- console.log('Error: exec proxy not found for :: ' + service + ' :: ' + action);
+ };
+ proxy(onSuccess, onError, args);
+ } catch (e) {
+ console.log('Exception calling native with command :: ' + service + ' :: ' + action + ' ::exception=' + e);
+ }
+ } else {
+ console.log('Error: exec proxy not found for :: ' + service + ' :: ' + action);
- if (typeof fail === 'function') {
- fail('Missing Command Error');
+ if (typeof fail === 'function') {
+ fail('Missing Command Error');
+ }
}
}
};
diff --git a/lib/Api.js b/lib/Api.js
index 57e0d23..62e0a34 100644
--- a/lib/Api.js
+++ b/lib/Api.js
@@ -232,7 +232,7 @@ class Api {
if (['asset', 'js-module'].indexOf(type) > -1) {
return installer.uninstall(item, wwwDest, plugin_id);
} else {
- return installer.uninstall(item, this.root, plugin_id, options, project);
+ return installer.uninstall(item, plugin_dir, this.root, plugin_id, options, project);
}
}
};
diff --git a/lib/PackageJsonParser.js b/lib/PackageJsonParser.js
index 9bebeff..ec866bb 100644
--- a/lib/PackageJsonParser.js
+++ b/lib/PackageJsonParser.js
@@ -19,67 +19,29 @@
const fs = require('fs-extra');
const path = require('path');
-const { events } = require('cordova-common');
const { getPackageJson } = require('./util');
class PackageJsonParser {
constructor (wwwDir, projectRootDir) {
+ // Electron App Package
this.path = path.join(wwwDir, 'package.json');
+ fs.ensureFileSync(this.path);
+ this.package = JSON.parse(fs.readFileSync(this.path, 'utf8') || '{}');
+
+ // Force settings that are not allowed to change.
+ this.package.main = 'cdv-electron-main.js';
+
this.www = wwwDir;
this.projectRootDir = projectRootDir;
- this.package = {
- main: 'cdv-electron-main.js'
- };
}
- configure (config, projectPackageJson) {
+ configure (config) {
if (config) {
this.package.name = config.packageName() || 'io.cordova.hellocordova';
this.package.displayName = config.name() || 'HelloCordova';
this.package.version = config.version() || '1.0.0';
this.package.description = config.description() || 'A sample Apache Cordova application that responds to the deviceready event.';
- if (projectPackageJson.dependencies) {
- const cordovaDependencies = [];
- const droppedPackages = [];
-
- for (const [npmPackage, npmPackageValue] of Object.entries(projectPackageJson.dependencies)) {
- if (/^cordova(?!-plugin)-/.test(npmPackage)) {
- cordovaDependencies.push(npmPackage);
- }
-
- // Format FilePath Based Dependencies
- if (npmPackageValue.startsWith('file:..')) {
- const relativePath = npmPackageValue.split('file:')[1];
- const absolutePath = path.resolve(this.projectRootDir, relativePath);
-
- if (fs.pathExistsSync(absolutePath)) {
- projectPackageJson.dependencies[npmPackage] = `file:${absolutePath}`;
- } else {
- droppedPackages.push(npmPackage);
- }
- }
- }
-
- // If Cordova dependencies are detected in "dependencies" of "package.json" warn for potential app package bloating
- if (cordovaDependencies.length) {
- events.emit('warn', '[Cordova Electron] The built package size may be larger than necessary. Please run with --verbose for more details.');
-
- events.emit('verbose', `[Cordova Electron] The following Cordova package(s) were detected as "dependencies" in the projects "package.json" file.
-\t- ${cordovaDependencies.join('\n\t- ')}
-
-It is recommended that all Cordova packages are defined as "devDependencies" in the "package.json" file. It is safe to move them manually.
-Packages defined as a dependency will be bundled with the application and can increase the built application's size.
-`);
- }
-
- if (droppedPackages.length) {
- events.emit('warn', `[Cordova Electron] The following local npm dependencies could not be located and will not be deployed to the Electron app:\n\t${droppedPackages.join('\n\t- ')}`);
- }
-
- this.package.dependencies = projectPackageJson.dependencies;
- }
-
this.configureHomepage(config);
this.configureLicense(config);
@@ -96,16 +58,30 @@ Packages defined as a dependency will be bundled with the application and can in
return this;
}
+ static _orderObject (obj) {
+ const ordered = {};
+ Object.keys(obj).sort().forEach(key => {
+ ordered[key] = obj[key];
+ });
+ return ordered;
+ }
+
enableDevTools (enable = false) {
- if (enable) {
- const pkgJson = getPackageJson();
- const devToolsDependency = 'electron-devtools-installer';
+ const pkgJson = getPackageJson();
+ const devToolsDependency = 'electron-devtools-installer';
+ if (enable) {
if (!this.package.dependencies) {
this.package.dependencies = {};
}
this.package.dependencies[devToolsDependency] = pkgJson.dependencies[devToolsDependency];
+ this.package.dependencies = PackageJsonParser._orderObject(this.package.dependencies);
+ } else if (
+ this.package.dependencies &&
+ this.package.dependencies[devToolsDependency]
+ ) {
+ delete this.package.dependencies[devToolsDependency];
}
return this;
diff --git a/lib/handler.js b/lib/handler.js
index a1275c6..ffa9e80 100644
--- a/lib/handler.js
+++ b/lib/handler.js
@@ -19,14 +19,16 @@
const path = require('path');
const fs = require('fs-extra');
+const execa = require('execa');
const { events } = require('cordova-common');
+const { _orderObject } = require('./PackageJsonParser');
+const { deepMerge } = require('./util');
module.exports = {
www_dir: (project_dir) => path.join(project_dir, 'www'),
package_name: (project_dir) => {
// this method should the id from root config.xml => <widget id=xxx
// return common.package_name(project_dir, this.www_dir(project_dir));
- // console.log('package_name called with ' + project_dir);
let pkgName = 'io.cordova.hellocordova';
const widget_id_regex = /(?:<widget\s+id=['"])(\S+)(?:['"])/;
const configPath = path.join(project_dir, 'config.xml');
@@ -79,7 +81,7 @@ module.exports = {
// common.copyFile(plugin_dir, obj.src, project_dir, dest);
events.emit('verbose', 'source-file.install is not supported for electron');
},
- uninstall: (obj, project_dir, plugin_id, options) => {
+ uninstall: (obj, plugin_dir, project_dir, plugin_id, options) => {
// var dest = path.join(obj.targetDir, path.basename(obj.src));
// common.removeFile(project_dir, dest);
events.emit('verbose', 'source-file.uninstall is not supported for electron');
@@ -89,7 +91,7 @@ module.exports = {
install: (obj, plugin_dir, project_dir, plugin_id, options) => {
events.emit('verbose', 'header-file.install is not supported for electron');
},
- uninstall: (obj, project_dir, plugin_id, options) => {
+ uninstall: (obj, plugin_dir, project_dir, plugin_id, options) => {
events.emit('verbose', 'header-file.uninstall is not supported for electron');
}
},
@@ -97,23 +99,118 @@ module.exports = {
install: (obj, plugin_dir, project_dir, plugin_id, options) => {
events.emit('verbose', 'resource-file.install is not supported for electron');
},
- uninstall: (obj, project_dir, plugin_id, options) => {
+ uninstall: (obj, plugin_dir, project_dir, plugin_id, options) => {
events.emit('verbose', 'resource-file.uninstall is not supported for electron');
}
},
framework: {
install: (obj, plugin_dir, project_dir, plugin_id, options) => {
- events.emit('verbose', 'framework.install is not supported for electron');
+ const electronPluginSrc = path.resolve(plugin_dir, obj.src);
+
+ if (!fs.existsSync(electronPluginSrc)) {
+ events.emit(
+ 'warn',
+ '[Cordova Electron] The defined "framework" source path does not exist and can not be installed.'
+ );
+ return;
+ }
+
+ const wwwDir = path.join(project_dir, 'www');
+
+ execa('npm', ['install', electronPluginSrc], {
+ cwd: wwwDir
+ });
+
+ const appPackageFile = path.join(wwwDir, 'package.json');
+ let appPackage = JSON.parse(fs.readFileSync(appPackageFile, 'utf8'));
+ const pluginPackage = JSON.parse(fs.readFileSync(path.join(electronPluginSrc, 'package.json'), 'utf8'));
+
+ if (!pluginPackage.cordova || !pluginPackage.cordova.serviceName) {
+ return;
+ }
+
+ const serviceName = pluginPackage.cordova.serviceName;
+
+ if (
+ appPackage.cordova &&
+ appPackage.cordova.services &&
+ appPackage.cordova.services[serviceName]
+ ) {
+ events.emit(
+ 'warn',
+ `[Cordova Electron] The service name "${serviceName}" is already taken by "${appPackage.cordova.services[serviceName]}" and can not be redeclared.`
+ );
+ return;
+ }
+
+ const appendingData = {
+ cordova: {
+ services: {
+ [serviceName]: pluginPackage.name
+ }
+ }
+ };
+
+ appPackage = deepMerge(appPackage, appendingData);
+
+ appPackage.cordova.services = _orderObject(appPackage.cordova.services);
+ fs.writeFileSync(
+ appPackageFile,
+ JSON.stringify(appPackage, null, 2),
+ 'utf8'
+ );
},
- uninstall: (obj, project_dir, plugin_id, options) => {
- events.emit('verbose', 'framework.uninstall is not supported for electron');
+ uninstall: (obj, plugin_dir, project_dir, plugin_id, options) => {
+ const electronPluginPackageFile = path.resolve(plugin_dir, obj.src, 'package.json');
+ const electronPluginPackage = JSON.parse(
+ fs.readFileSync(electronPluginPackageFile, 'utf8')
+ );
+
+ const electronPluginName = electronPluginPackage.name;
+ const wwwDir = path.join(project_dir, 'www');
+
+ console.log(electronPluginPackageFile);
+ console.log(electronPluginName);
+
+ execa('npm', ['uninstall', electronPluginName], {
+ cwd: wwwDir
+ });
+
+ const appPackageFile = path.join(wwwDir, 'package.json');
+ const appPackage = JSON.parse(fs.readFileSync(appPackageFile, 'utf8'));
+
+ if (
+ appPackage &&
+ appPackage.cordova &&
+ appPackage.cordova.services
+ ) {
+ let hasUpdatedPackage = false;
+ Object.keys(appPackage.cordova.services).forEach(serviceName => {
+ if (appPackage.cordova.services[serviceName] === electronPluginName) {
+ delete appPackage.cordova.services[serviceName];
+ hasUpdatedPackage = true;
+ events.emit(
+ 'verbose',
+ `[Cordova Electron] The service name "${serviceName}" was delinked.`
+ );
+ }
+ });
+
+ if (hasUpdatedPackage) {
+ fs.writeFileSync(
+ appPackageFile,
+ JSON.stringify(appPackage, null, 2),
+ 'utf8'
+ );
+ }
+ }
}
},
'lib-file': {
install: (obj, plugin_dir, project_dir, plugin_id, options) => {
events.emit('verbose', 'lib-file.install is not supported for electron');
},
- uninstall: (obj, project_dir, plugin_id, options) => {
+ uninstall: (obj, plugin_dir, project_dir, plugin_id, options) => {
events.emit('verbose', 'lib-file.uninstall is not supported for electron');
}
},
diff --git a/lib/parser.js b/lib/parser.js
index 4ee2ba2..8905699 100644
--- a/lib/parser.js
+++ b/lib/parser.js
@@ -65,7 +65,10 @@ class Parser {
// targetDir points to electron/www
const targetDir = path.relative(cordovaProject.root, my_www);
events.emit('verbose', `Merging and updating files from [${sourceDirs.join(', ')}] to ${targetDir}`);
- FileUpdater.mergeAndUpdateDir(sourceDirs, targetDir, { rootDir: cordovaProject.root }, logFileOp);
+ FileUpdater.mergeAndUpdateDir(sourceDirs, targetDir, {
+ rootDir: cordovaProject.root,
+ exclude: ['node_modules', 'package.json']
+ }, logFileOp);
}
config_xml () {
diff --git a/lib/prepare.js b/lib/prepare.js
index db46af0..3eb499c 100644
--- a/lib/prepare.js
+++ b/lib/prepare.js
@@ -72,10 +72,8 @@ module.exports.prepare = function (cordovaProject, options) {
.write();
}
- const projectPackageJson = JSON.parse(fs.readFileSync(path.join(cordovaProject.root, 'package.json'), 'utf8'));
-
(new PackageJsonParser(this.locations.www, cordovaProject.root))
- .configure(this.config, projectPackageJson)
+ .configure(this.config)
.enableDevTools(options && options.options && !options.options.release)
.write();
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/config.xml b/tests/spec/fixtures/test-app-with-electron-plugin/config.xml
new file mode 100644
index 0000000..ab176fd
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/config.xml
@@ -0,0 +1,18 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="org.apache.cordovaTestApp" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>cordovaTestApp</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="*" />
+ <allow-intent href="http://*/*" />
+ <allow-intent href="https://*/*" />
+ <allow-intent href="tel:*" />
+ <allow-intent href="sms:*" />
+ <allow-intent href="mailto:*" />
+ <allow-intent href="geo:*" />
+</widget>
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/package.json b/tests/spec/fixtures/test-app-with-electron-plugin/package.json
new file mode 100644
index 0000000..db9b021
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "org.apache.cordovaTestApp",
+ "displayName": "cordovaTestApp",
+ "version": "1.0.0",
+ "description": "A sample Apache Cordova application that responds to the deviceready event.",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "ecosystem:cordova"
+ ],
+ "author": "Apache Cordova Team",
+ "license": "Apache-2.0",
+ "devDependencies": {},
+ "cordova": {
+ "plugins": {},
+ "platforms": [
+ "electron"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/config.xml b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/config.xml
new file mode 100644
index 0000000..ab176fd
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/config.xml
@@ -0,0 +1,18 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="org.apache.cordovaTestApp" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>cordovaTestApp</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="*" />
+ <allow-intent href="http://*/*" />
+ <allow-intent href="https://*/*" />
+ <allow-intent href="tel:*" />
+ <allow-intent href="sms:*" />
+ <allow-intent href="mailto:*" />
+ <allow-intent href="geo:*" />
+</widget>
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/Api.js b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/Api.js
new file mode 100644
index 0000000..175ff23
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/Api.js
@@ -0,0 +1,24 @@
+/*
+ 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.
+*/
+
+try {
+ module.exports = require('cordova-electron');
+} catch (error) {
+ module.exports = require('../../../lib/Api');
+}
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/defaults.xml b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/defaults.xml
new file mode 100644
index 0000000..2dee32a
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/defaults.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<widget id="io.cordova.hellocordova" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+</widget>
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/version b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/version
new file mode 100755
index 0000000..bbb52c6
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/version
@@ -0,0 +1,23 @@
+#!/usr/bin/env node
+
+/*
+ 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.
+*/
+
+const Api = require('./Api');
+console.log(Api.version());
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/version.bat b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/version.bat
new file mode 100644
index 0000000..2e69f1c
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/cordova/version.bat
@@ -0,0 +1,26 @@
+:: 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.
+
+@ECHO OFF
+SET script_path="%~dp0version"
+IF EXIST %script_path% (
+ node %script_path% %*
+) ELSE (
+ ECHO.
+ ECHO ERROR: Could not find 'version' script in 'cordova' folder, aborting...>&2
+ EXIT /B 1
+)
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/electron.json b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/electron.json
new file mode 100644
index 0000000..16b00cc
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/electron.json
@@ -0,0 +1,14 @@
+{
+ "prepare_queue": {
+ "installed": [],
+ "uninstalled": []
+ },
+ "config_munge": {
+ "files": {}
+ },
+ "installed_plugins": {},
+ "dependent_plugins": {},
+ "modules": [],
+ "plugin_metadata": {
+ }
+}
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/platform_www/config.xml b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/platform_www/config.xml
new file mode 100644
index 0000000..63d4646
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/platform_www/config.xml
@@ -0,0 +1,22 @@
+<?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.
+-->
+<widget xmlns="http://www.w3.org/ns/widgets">
+
+</widget>
\ No newline at end of file
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/www/config.xml b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/www/config.xml
new file mode 100644
index 0000000..ab176fd
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/www/config.xml
@@ -0,0 +1,18 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget id="org.apache.cordovaTestApp" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>cordovaTestApp</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="*" />
+ <allow-intent href="http://*/*" />
+ <allow-intent href="https://*/*" />
+ <allow-intent href="tel:*" />
+ <allow-intent href="sms:*" />
+ <allow-intent href="mailto:*" />
+ <allow-intent href="geo:*" />
+</widget>
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/www/cordova_plugins.js b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/www/cordova_plugins.js
new file mode 100644
index 0000000..46ddcee
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/www/cordova_plugins.js
@@ -0,0 +1,8 @@
+cordova.define('cordova/plugin_list', function (require, exports, module) {
+ module.exports = [];
+
+ module.exports.metadata =
+ // TOP OF METADATA
+ {}
+ // BOTTOM OF METADATA
+ });
\ No newline at end of file
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/www/package.json b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/www/package.json
new file mode 100644
index 0000000..2e6d6b1
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/platforms/electron/www/package.json
@@ -0,0 +1,15 @@
+{
+ "main": "cdv-electron-main.js",
+ "name": "org.apache.cordovaTestApp",
+ "displayName": "test-app-with-electron-plugin",
+ "version": "1.0.0",
+ "description": "A sample Apache Cordova application that responds to the deviceready event.",
+ "homepage": "http://cordova.io",
+ "license": "Apache-2.0",
+ "author": {
+ "name": "Apache Cordova Team",
+ "email": "dev@cordova.apache.org"
+ },
+ "dependencies": {},
+ "cordova": {}
+}
\ No newline at end of file
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/package.json b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/package.json
new file mode 100644
index 0000000..0b59744
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "cordova-plugin-device",
+ "version": "2.0.4-dev",
+ "description": "Cordova Device Plugin",
+ "types": "./types/index.d.ts",
+ "cordova": {
+ "id": "cordova-plugin-device",
+ "platforms": [
+ "android",
+ "ios",
+ "windows",
+ "browser",
+ "osx"
+ ]
+ },
+ "repository": "github:apache/cordova-plugin-device",
+ "bugs": "https://github.com/apache/cordova-plugin-device/issues",
+ "keywords": [
+ "cordova",
+ "device",
+ "ecosystem:cordova",
+ "cordova-android",
+ "cordova-electron",
+ "cordova-ios",
+ "cordova-windows",
+ "cordova-browser",
+ "cordova-osx"
+ ],
+ "scripts": {
+ "test": "npm run lint",
+ "lint": "eslint ."
+ },
+ "author": "Apache Software Foundation",
+ "license": "Apache-2.0",
+ "engines": {
+ "cordovaDependencies": {
+ "3.0.0": {
+ "cordova": ">100",
+ "cordova-electron": ">=3.0.0"
+ }
+ }
+ },
+ "devDependencies": {
+ "@cordova/eslint-config": "^3.0.0"
+ }
+}
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/plugin.xml b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/plugin.xml
new file mode 100644
index 0000000..2dcfb6f
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/plugin.xml
@@ -0,0 +1,40 @@
+<?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.
+-->
+
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+ id="cordova-plugin-device"
+ version="2.0.4-dev">
+ <name>Device</name>
+ <description>Cordova Mock Device Plugin for Electron Testing</description>
+ <license>Apache 2.0</license>
+ <keywords>cordova,device</keywords>
+
+ <engines>
+ <engine name="cordova-electron" version=">=3.0.0" />
+ </engines>
+
+ <js-module src="www/device.js" name="device">
+ <clobbers target="device" />
+ </js-module>
+
+ <platform name="electron">
+ <framework src="src/electron" />
+ </platform>
+</plugin>
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/src/electron/index.js b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/src/electron/index.js
new file mode 100644
index 0000000..4303399
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/src/electron/index.js
@@ -0,0 +1,22 @@
+const { system, osInfo } = require('systeminformation');
+
+module.exports = {
+ getDeviceInfo: async () => {
+ try {
+ const { manufacturer, model, uuid } = await system();
+ const { platform, distro, codename, build } = await osInfo();
+
+ return {
+ manufacturer,
+ model,
+ platform: platform === 'darwin' ? codename : distro,
+ version: build,
+ uuid,
+ // cordova: ''
+ isVirtual: false
+ };
+ } catch (e) {
+ console.log(e);
+ }
+ }
+};
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/src/electron/package.json b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/src/electron/package.json
new file mode 100644
index 0000000..d3b235f
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/src/electron/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "cordova-plugin-device-electron",
+ "version": "1.0.0",
+ "description": "Electron Native Supprot for Cordova Device Plugin",
+ "main": "index.js",
+ "keywords": [
+ "cordova",
+ "electron",
+ "device",
+ "native"
+ ],
+ "author": "Apache Software Foundation",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "systeminformation": "^4.27.9"
+ },
+ "cordova": {
+ "serviceName": "Device"
+ }
+}
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/www/device.js b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/www/device.js
new file mode 100644
index 0000000..8bb2aa6
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/plugins/cordova-plugin-device/www/device.js
@@ -0,0 +1,85 @@
+/*
+ *
+ * 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 argscheck = require('cordova/argscheck');
+var channel = require('cordova/channel');
+var exec = require('cordova/exec');
+var cordova = require('cordova');
+
+channel.createSticky('onCordovaInfoReady');
+// Tell cordova channel to wait on the CordovaInfoReady event
+channel.waitForInitialization('onCordovaInfoReady');
+
+/**
+ * This represents the mobile device, and provides properties for inspecting the model, version, UUID of the
+ * phone, etc.
+ * @constructor
+ */
+function Device () {
+ this.available = false;
+ this.platform = null;
+ this.version = null;
+ this.uuid = null;
+ this.cordova = null;
+ this.model = null;
+ this.manufacturer = null;
+ this.isVirtual = null;
+ this.serial = null;
+
+ var me = this;
+
+ channel.onCordovaReady.subscribe(function () {
+ me.getInfo(
+ function (info) {
+ // ignoring info.cordova returning from native, we should use value from cordova.version defined in cordova.js
+ // TODO: CB-5105 native implementations should not return info.cordova
+ var buildLabel = cordova.version;
+ me.available = true;
+ me.platform = info.platform;
+ me.version = info.version;
+ me.uuid = info.uuid;
+ me.cordova = buildLabel;
+ me.model = info.model;
+ me.isVirtual = info.isVirtual;
+ me.manufacturer = info.manufacturer || 'unknown';
+ me.serial = info.serial || 'unknown';
+ channel.onCordovaInfoReady.fire();
+ },
+ function (e) {
+ me.available = false;
+ console.error('[ERROR] Error initializing cordova-plugin-device: ' + e);
+ }
+ );
+ });
+}
+
+/**
+ * Get device info
+ *
+ * @param {Function} successCallback The function to call when the heading data is available
+ * @param {Function} errorCallback The function to call when there is an error getting the heading data. (OPTIONAL)
+ */
+Device.prototype.getInfo = function (successCallback, errorCallback) {
+ argscheck.checkArgs('fF', 'Device.getInfo', arguments);
+ exec(successCallback, errorCallback, 'Device', 'getDeviceInfo', []);
+};
+
+module.exports = new Device();
diff --git a/tests/spec/fixtures/test-app-with-electron-plugin/www/index.html b/tests/spec/fixtures/test-app-with-electron-plugin/www/index.html
new file mode 100644
index 0000000..c144cf0
--- /dev/null
+++ b/tests/spec/fixtures/test-app-with-electron-plugin/www/index.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+ 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.
+-->
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
+ <meta name="format-detection" content="telephone=no">
+ <meta name="msapplication-tap-highlight" content="no">
+ <meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
+ <meta name="color-scheme" content="light dark">
+ <title>Hello World</title>
+ </head>
+ <body>
+ <div class="app"></div>
+ <script src="cordova.js"></script>
+ </body>
+</html>
diff --git a/tests/spec/unit/lib/PackageJsonParser.spec.js b/tests/spec/unit/lib/PackageJsonParser.spec.js
index fb21b8f..8f02b4b 100644
--- a/tests/spec/unit/lib/PackageJsonParser.spec.js
+++ b/tests/spec/unit/lib/PackageJsonParser.spec.js
@@ -66,6 +66,10 @@ describe('PackageJsonParser class', () => {
spyOn(events, 'emit');
});
+ afterAll(() => {
+ fs.removeSync('mock');
+ });
+
it('should have been constructed with initial values.', () => {
expect(packageJsonParser).toBeDefined();
expect(packageJsonParser.path).toEqual(path.join(locations.www, 'package.json'));
@@ -91,6 +95,18 @@ describe('PackageJsonParser class', () => {
expect(packageJsonParser.package.dependencies).not.toBeDefined();
});
+ it('should remove dev tools extension when enable argument = false.', () => {
+ packageJsonParser.package.dependencies = packageJsonParser.package.dependencies || {
+ 'electron-devtools-installer': '1.0.0' // test
+ };
+ // Ensure mock was set, this is acting as if it was set before.
+ expect(packageJsonParser.package.dependencies['electron-devtools-installer']).toBeDefined();
+ // This should remove the mock
+ packageJsonParser.enableDevTools(false);
+ // the dependency should have been removed.
+ expect(packageJsonParser.package.dependencies['electron-devtools-installer']).not.toBeDefined();
+ });
+
it('should not add dev tools extension when enable argument = undefined.', () => {
packageJsonParser.enableDevTools();
// the package object should be the same as it was initialized
@@ -121,10 +137,6 @@ describe('PackageJsonParser class', () => {
displayName: 'HelloCordova',
version: '1.0.0',
description: 'A sample Apache Cordova application that responds to the deviceready event.',
- dependencies: {
- 'cordova-electron': '^1.0.0',
- 'cordova-plugin-camera': '^1.0.0'
- },
homepage: 'https://cordova.io',
license: 'Apache-2.0',
author: 'Apache Cordova Team'
@@ -142,10 +154,6 @@ describe('PackageJsonParser class', () => {
displayName: 'HelloWorld',
version: '1.1.1',
description: 'A sample Apache Cordova application.',
- dependencies: {
- 'cordova-electron': '^1.0.0',
- 'cordova-plugin-camera': '^1.0.0'
- },
homepage: 'http://cordova.io',
license: 'Apache 2.0 License',
author: { name: 'Cordova Team', email: 'dev@cordova.com' }
@@ -154,30 +162,6 @@ describe('PackageJsonParser class', () => {
expect(packageJsonParser.package).toEqual(packageJsonObj);
});
- it('should warn when any of the dependencies contain cordova-* is defined but not for cordova-plugin-*.', () => {
- packageJsonParser.configure(cfg, defaultMockProjectPackageJson);
-
- expect(events.emit).toHaveBeenCalledWith(
- 'warn',
- jasmine.stringMatching(/^\[Cordova Electron\] The built package size/)
- );
-
- expect(events.emit).toHaveBeenCalledWith(
- 'verbose',
- jasmine.stringMatching(/The following Cordova package\(s\) were detected/)
- );
-
- expect(events.emit).toHaveBeenCalledWith(
- 'verbose',
- jasmine.stringMatching(/cordova-electron/)
- );
-
- expect(events.emit).not.toHaveBeenCalledWith(
- 'verbose',
- jasmine.stringMatching(/cordova-plugin-camera/)
- );
- });
-
it('should set default author when missing but author email is defined.', () => {
packageJsonParser.configure(cfgNoAuthorCustomEmail, defaultMockProjectPackageJson);
expect(packageJsonParser.package.author).toEqual({
@@ -186,76 +170,6 @@ describe('PackageJsonParser class', () => {
});
});
- it('should not warn when any cordova-* packages are defined as devDependency.', () => {
- // Fix defaultMockProjectPackageJson where cordova-* is devDependency
- const mockProjectPackageJson = Object.assign({}, defaultMockProjectPackageJson);
- mockProjectPackageJson.devDependencies = Object.assign({}, defaultMockProjectPackageJson.dependencies);
- mockProjectPackageJson.dependencies = { foobar: '1.0.0' }; // setting a non "cordova-" dependency
-
- packageJsonParser.configure(cfg, mockProjectPackageJson);
-
- expect(events.emit).not.toHaveBeenCalled();
- });
-
- it('should skip configuring the Electron app\'s dependencies when the Cordova project\'s package.json dependencies are not set.', () => {
- const mockProjectPackageJson = Object.assign({}, defaultMockProjectPackageJson);
- mockProjectPackageJson.dependencies = {};
-
- packageJsonParser.configure(cfg, mockProjectPackageJson);
-
- expect(events.emit).not.toHaveBeenCalled();
- });
-
- it('should skip preparing npm packages that already contain absolute paths.', () => {
- const mockProjectPackageJson = Object.assign({}, defaultMockProjectPackageJson);
- mockProjectPackageJson.dependencies = { foobar: 'file:/tmp/foobar.tar.gz' };
-
- packageJsonParser.configure(cfg, mockProjectPackageJson);
-
- expect(events.emit).not.toHaveBeenCalled();
- });
-
- it('should convert npm packages that contain relative path to be absolute paths.', () => {
- const mockProjectPackageJson = Object.assign({}, defaultMockProjectPackageJson);
- mockProjectPackageJson.dependencies = { foobar: 'file:../tmp/foobar.tar.gz' };
-
- spyOn(fs, 'pathExistsSync').and.returnValue(true);
-
- packageJsonParser.configure(cfg, mockProjectPackageJson);
-
- expect(events.emit).not.toHaveBeenCalled();
- });
-
- it('should warn that an npm packages will be dropped when the absolute path could not be found.', () => {
- const mockProjectPackageJson = Object.assign({}, defaultMockProjectPackageJson);
- mockProjectPackageJson.dependencies = { foobar: 'file:../tmp/foobar.tar.gz' };
-
- spyOn(fs, 'pathExistsSync').and.returnValue(false);
-
- packageJsonParser.configure(cfg, mockProjectPackageJson);
-
- expect(events.emit).toHaveBeenCalledWith(
- 'warn',
- jasmine.stringMatching(/^\[Cordova Electron\] The following local npm dependencies could not be located and will not be deployed/)
- );
-
- expect(events.emit).toHaveBeenCalledWith(
- 'warn',
- jasmine.stringMatching(/foobar/)
- );
- });
-
- it('should not set package dependencies when project dependencies is missing.', () => {
- const mockProjectPackageJson = Object.assign({}, defaultMockProjectPackageJson);
- mockProjectPackageJson.devDependencies = Object.assign({}, defaultMockProjectPackageJson.dependencies);
- delete mockProjectPackageJson.dependencies;
-
- packageJsonParser.configure(cfg, mockProjectPackageJson);
-
- expect(events.emit).not.toHaveBeenCalled();
- expect(packageJsonParser.package.dependencies).not.toBeDefined();
- });
-
it('should write something.', () => {
spyOn(fs, 'writeFileSync').and.returnValue(true);
packageJsonParser.write();
diff --git a/tests/spec/unit/lib/handler.spec.js b/tests/spec/unit/lib/handler.spec.js
index 8b08b7e..3ab405e 100644
--- a/tests/spec/unit/lib/handler.spec.js
+++ b/tests/spec/unit/lib/handler.spec.js
@@ -23,6 +23,9 @@ const { events } = require('cordova-common');
const rewire = require('rewire');
const rootDir = path.resolve(__dirname, '../../../..');
+const fixturesDir = path.join(rootDir, 'tests/spec/fixtures');
+const tmpDir = path.join(rootDir, 'temp');
+const testProjectDir = path.join(tmpDir, 'testapp');
const handler = rewire(path.join(rootDir, 'lib/handler'));
@@ -170,6 +173,272 @@ describe('Handler export', () => {
});
});
+ describe('framework method', () => {
+ const frameworkInstallMockObject = {
+ itemType: 'framework',
+ type: undefined,
+ parent: undefined,
+ custom: false,
+ embed: false,
+ src: 'src/electron',
+ spec: undefined,
+ weak: false,
+ versions: undefined,
+ targetDir: undefined,
+ deviceTarget: undefined,
+ arch: undefined,
+ implementation: undefined
+ };
+
+ const frameworkInstallPluginId = 'cordova-plugin-device';
+ const frameworkInstallElectronPluginId = `${frameworkInstallPluginId}-electron`;
+ const frameworkInstallPluginDir = path.join(testProjectDir, `plugins/${frameworkInstallPluginId}`);
+ const frameworkInstallProjectDir = path.join(testProjectDir, 'platforms/electron');
+ const frameworkInstallProjectAppPackageFile = path.join(frameworkInstallProjectDir, 'www/package.json');
+ const frameworkInstallPluginPackageFile = path.join(frameworkInstallPluginDir, 'src/electron/package.json');
+
+ beforeEach(() => {
+ fs.ensureDirSync(tmpDir);
+ fs.copySync(path.resolve(fixturesDir, 'test-app-with-electron-plugin'), testProjectDir);
+
+ spyOn(events, 'emit');
+ });
+
+ afterEach(() => {
+ fs.removeSync(tmpDir);
+ });
+
+ describe('framework.install', () => {
+ it('should not install framework when the source path does not exist.', async () => {
+ const execaSpy = jasmine.createSpy('execa');
+ handler.__set__('execa', execaSpy);
+
+ spyOn(fs, 'existsSync').and.returnValue(false);
+
+ await handler.framework.install(
+ frameworkInstallMockObject,
+ frameworkInstallPluginDir,
+ frameworkInstallProjectDir,
+ frameworkInstallPluginId
+ );
+
+ expect(events.emit).toHaveBeenCalledWith(
+ 'warn',
+ '[Cordova Electron] The defined "framework" source path does not exist and can not be installed.'
+ );
+ events.emit.calls.reset();
+ });
+
+ it('should update the electron app package when service is registered', async () => {
+ const execaSpy = jasmine.createSpy('execa');
+ handler.__set__('execa', execaSpy);
+
+ // Mock npm install by updating the App's package.json
+ const appPackage = JSON.parse(
+ fs.readFileSync(frameworkInstallProjectAppPackageFile, 'utf8')
+ );
+
+ appPackage.dependencies[frameworkInstallElectronPluginId] = path.relative(
+ frameworkInstallProjectAppPackageFile,
+ path.join(frameworkInstallPluginDir, 'src/electron')
+ );
+
+ fs.writeFileSync(
+ frameworkInstallProjectAppPackageFile,
+ JSON.stringify(appPackage, null, 2),
+ 'utf8'
+ );
+
+ await handler.framework.install(
+ frameworkInstallMockObject,
+ frameworkInstallPluginDir,
+ frameworkInstallProjectDir,
+ frameworkInstallPluginId
+ );
+
+ // Validate that device plugin's service is registered.
+ const validateAppPackage = JSON.parse(fs.readFileSync(frameworkInstallProjectAppPackageFile, 'utf8'));
+ const test = validateAppPackage && validateAppPackage.cordova && validateAppPackage.cordova.services && validateAppPackage.cordova.services.Device;
+ expect(test).toBe(frameworkInstallElectronPluginId);
+ });
+
+ it('should not update the electron app package when there are no registered service', async () => {
+ const execaSpy = jasmine.createSpy('execa').and.returnValue({
+ stdout: frameworkInstallElectronPluginId
+ });
+ handler.__set__('execa', execaSpy);
+
+ // Mock npm install by updating the App's package.json
+ const appPackage = JSON.parse(
+ fs.readFileSync(frameworkInstallProjectAppPackageFile, 'utf8')
+ );
+
+ appPackage.dependencies[frameworkInstallElectronPluginId] = path.relative(
+ frameworkInstallProjectAppPackageFile,
+ path.join(frameworkInstallPluginDir, 'src/electron')
+ );
+
+ fs.writeFileSync(
+ frameworkInstallProjectAppPackageFile,
+ JSON.stringify(appPackage, null, 2),
+ 'utf8'
+ );
+
+ const pluginPackage = JSON.parse(fs.readFileSync(frameworkInstallPluginPackageFile, 'utf8'));
+ delete pluginPackage.cordova;
+
+ fs.writeFileSync(
+ frameworkInstallPluginPackageFile,
+ JSON.stringify(pluginPackage, null, 2),
+ 'utf8'
+ );
+
+ await handler.framework.install(
+ frameworkInstallMockObject,
+ frameworkInstallPluginDir,
+ frameworkInstallProjectDir,
+ frameworkInstallPluginId
+ );
+
+ // Validate that device plugin's service is registered.
+ const validateAppPackage = JSON.parse(fs.readFileSync(frameworkInstallProjectAppPackageFile, 'utf8'));
+ const test = validateAppPackage && validateAppPackage.cordova && validateAppPackage.cordova.services && validateAppPackage.cordova.services.Device;
+ expect(test).not.toBe(frameworkInstallElectronPluginId);
+ });
+
+ it('should warn when there are conflicting service name between more then one plugin', async () => {
+ const execaSpy = jasmine.createSpy('execa').and.returnValue({
+ stdout: frameworkInstallElectronPluginId
+ });
+ handler.__set__('execa', execaSpy);
+
+ // Mock npm install by updating the App's package.json
+ const appPackage = JSON.parse(
+ fs.readFileSync(frameworkInstallProjectAppPackageFile, 'utf8')
+ );
+
+ appPackage.dependencies[frameworkInstallElectronPluginId] = path.relative(
+ frameworkInstallProjectAppPackageFile,
+ path.join(frameworkInstallPluginDir, 'src/electron')
+ );
+
+ // fake some other device service already registered
+ appPackage.cordova = appPackage.cordova || {};
+ appPackage.cordova.services = appPackage.cordova.services || {
+ Device: 'cordova-plugin-device-electron'
+ };
+
+ fs.writeFileSync(
+ frameworkInstallProjectAppPackageFile,
+ JSON.stringify(appPackage, null, 2),
+ 'utf8'
+ );
+
+ await handler.framework.install(
+ frameworkInstallMockObject,
+ frameworkInstallPluginDir,
+ frameworkInstallProjectDir,
+ frameworkInstallPluginId
+ );
+
+ expect(events.emit).toHaveBeenCalledWith(
+ 'warn',
+ '[Cordova Electron] The service name "Device" is already taken by "cordova-plugin-device-electron" and can not be redeclared.'
+ );
+ events.emit.calls.reset();
+ });
+ });
+
+ describe('framework.uninstall', () => {
+ it('should delink service name if defined', async () => {
+ const execaSpy = jasmine.createSpy('execa');
+ handler.__set__('execa', execaSpy);
+
+ // Mock npm install by updating the App's package.json
+ const appPackage = JSON.parse(
+ fs.readFileSync(frameworkInstallProjectAppPackageFile, 'utf8')
+ );
+
+ appPackage.dependencies[frameworkInstallElectronPluginId] = path.relative(
+ frameworkInstallProjectAppPackageFile,
+ path.join(frameworkInstallPluginDir, 'src/electron')
+ );
+
+ // fake some other device service already registered
+ appPackage.cordova = appPackage.cordova || {};
+ appPackage.cordova.services = appPackage.cordova.services || {
+ Device: 'cordova-plugin-device-electron'
+ };
+
+ fs.writeFileSync(
+ frameworkInstallProjectAppPackageFile,
+ JSON.stringify(appPackage, null, 2),
+ 'utf8'
+ );
+
+ await handler.framework.uninstall(
+ frameworkInstallMockObject,
+ frameworkInstallPluginDir,
+ frameworkInstallProjectDir
+ );
+
+ expect(events.emit).toHaveBeenCalledWith(
+ 'verbose',
+ '[Cordova Electron] The service name "Device" was delinked.'
+ );
+ events.emit.calls.reset();
+ });
+
+ it('should not delink service name if defined by another plugin', async () => {
+ const execaSpy = jasmine.createSpy('execa');
+ handler.__set__('execa', execaSpy);
+
+ // Mock npm install by updating the App's package.json
+ const appPackage = JSON.parse(
+ fs.readFileSync(frameworkInstallProjectAppPackageFile, 'utf8')
+ );
+
+ appPackage.dependencies[frameworkInstallElectronPluginId] = path.relative(
+ frameworkInstallProjectAppPackageFile,
+ path.join(frameworkInstallPluginDir, 'src/electron')
+ );
+
+ // fake some other device service already registered
+ appPackage.cordova = appPackage.cordova || {};
+ appPackage.cordova.services = appPackage.cordova.services || {
+ Device: 'some-other-package'
+ };
+
+ fs.writeFileSync(
+ frameworkInstallProjectAppPackageFile,
+ JSON.stringify(appPackage, null, 2),
+ 'utf8'
+ );
+
+ await handler.framework.uninstall(
+ frameworkInstallMockObject,
+ frameworkInstallPluginDir,
+ frameworkInstallProjectDir
+ );
+
+ expect(events.emit).not.toHaveBeenCalled();
+ });
+
+ it('should not delink service name when not defined', async () => {
+ const execaSpy = jasmine.createSpy('execa');
+ handler.__set__('execa', execaSpy);
+
+ await handler.framework.uninstall(
+ frameworkInstallMockObject,
+ frameworkInstallPluginDir,
+ frameworkInstallProjectDir
+ );
+
+ expect(events.emit).not.toHaveBeenCalled();
+ });
+ });
+ });
+
describe('Unsupported Handlers', () => {
it('should emit that the install and uninstall methods are not supported for X types.', () => {
spyOn(events, 'emit');
@@ -179,7 +448,6 @@ describe('Handler export', () => {
'source-file',
'header-file',
'resource-file',
- 'framework',
'lib-file'
].forEach(type => {
for (const method of ['install', 'uninstall']) {
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org