apache / cordova-plugin-file

Apache Cordova File Plugin
https://cordova.apache.org/
Apache License 2.0
741 stars 756 forks source link

Electron platform - 'Missing Command Error' on API calls #334

Open ZhennanWu opened 4 years ago

ZhennanWu commented 4 years ago

Bug Report

Problem

What is expected to happen?

File APIs working normally and return a valid Entry or a valid error code.

What does actually happen?

When invoking any api, it will throw

FileError {code: "Missing Command Error", message: undefined}

with

Error: exec proxy not found for :: File :: $TheAPIYouInvoked

Environment, Platform, Device

cordova.platformId = 'electron' Linux x64, Ubuntu 18.04

Checklist

Suspected Cause

Tracing the error output, I suspect this is caused by inconsistencies in platform detection strategy?

Eg: In src/browser/FileProxy.js and www/resolveLocalFileSystemURI.js

//In src/browser/FileProxy.js

    // For chrome we don't need to implement proxy methods
    // All functionality can be accessed natively.
    if (require('./isChrome')()) {
        var pathsPrefix = {
            // Read-only directory where the application is installed.
            applicationDirectory: location.origin + '/', // eslint-disable-line no-undef
            // Where to put app-specific data files.
            dataDirectory: 'filesystem:file:///persistent/',
            // Cached files that should survive app restarts.
            // Apps should not rely on the OS to delete files in here.
            cacheDirectory: 'filesystem:file:///temporary/'
        };

        exports.requestAllPaths = function (successCallback) {
            successCallback(pathsPrefix);
        };

        require('cordova/exec/proxy').add('File', module.exports);
        return;
    }
//In www/resolveLocalFileSystemURI.js

    // For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
    function checkBrowser () {
        if (cordova.platformId === 'browser' && require('./isChrome')()) { // eslint-disable-line no-undef
            module.exports.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL;
            return true;
        }
        return false;
    }
    if (checkBrowser()) {
        return;
    }

In src/browser/FileProxy.js, it assumes Electron have all the native APIs. So it choose to register nothing in the execProxy of Cordova. Meanwhile, other modules consider Electron not qualified (cordova.platformId !== 'browser') and overrides its methods.

Fixing Attempt

I've hacked src/browser/FileProxy.js to ensure it uses a consistent platform detection logic

//In src/browser/FileProxy.js

    // For chrome we don't need to implement proxy methods
    // All functionality can be accessed natively.
    if (cordova.platformId === 'browser' && require('./isChrome')()) { // FIX HERE

        //..........

        require('cordova/exec/proxy').add('File', module.exports);
        return;
    }

And at least the API call is OK. No more Error: exec proxy not found for :: File ::

Is there anyone who can confirm this issue? I'm not familiar with Cordova platform thus quite unsure about this fix.

flojug commented 4 years ago

When doing that I had some errors later when I tried to retrieve the files with a "img.src=...".

I replaced the both tests by the following and it seems to work :

if (((cordova.platformId === 'browser') || (cordova.platformId === 'electron')) && require('./isChrome')()) { ... }

J-Gann commented 4 years ago

@ZhennanWu Thanks a lot, works for me!

flojug commented 4 years ago

cordova.platformId = 'electron' Linux x64, Debian 10

My app is running well on iOS, Android, Chrome browser.

It downloads images from a remote server and then uses them in a canvas.

1/ With if (cordova.platformId === "browser" && require('./isChrome')()) { in

FileProxy.js
requestFileSystem.js
requestFileSystem.js
$ rm -rf ~/.config/Electron
$ cordova run electron --nobuild

The download of images is OK. In my code I have :

img = new Image();
img.onload = imageLoaded;
img.src = filepaths.shift();  

which results in : GET file:///persistent//forms/form_200065_victime_0.png net::ERR_FILE_NOT_FOUND

2/ If I replace if (cordova.platformId === "browser" && require('./isChrome')()) { with if (((cordova.platformId === "browser") || (cordova.platformId === "electron")) && require('./isChrome')()) { in

FileProxy.js
requestFileSystem.js
requestFileSystem.js

(i.e use Chrome layer for manipulation of files in Electron)

Then

$ rm -rf ~/.config/Electron
$ cordova run electron --nobuild

Everything is working fine.

zorn-v commented 4 years ago

https://github.com/apache/cordova-plugin-file/pull/371

BenLaKnet commented 9 months ago

Hi,

I have an issue with this plugin on electron.

file:///www/res/languages/fr-FR.json cordova.js:1025 Error: exec proxy not found for :: File :: resolveLocalFileSystemURI objTraductions.js:75 FileSystem Error

I tried to include a json file with translations. It is running very well with android and iOS, but it does not work with electron.

I modified files as you mentionned but it is not running too.