-1

I want to load an external javascript (without jquery or others) into my Corodova/Phonegapp app (Visual Studio 2015, Cordova CLI 6.1.1) when the app is actually ready and online (I check that in the original code, but did not enter it in the example below). Ultimately this external javascript will be the google maps javascript api. However since I ran into some problems I first tryed with my own little javascript file (external_file.js).

While debugging I can see that the <script src="https://myhost/external_file.js"></script> tag is writen into the original code of my app, but I can not access the loaded code (function external_function() is not available ). I tryed with the ripple emulator as well as with my android 5.1.1 device.

All my functions work on a "normal" html file without cordova. Also when I try to load the javascript file locally (from scripts/external_file.js) I can access the functions located inside the file.

I search quite some time for a solution, but did not find anything usefull:

I know that there is the cordova-plugin-googlemaps to load the native environment. Let's just say I do not want to do that for now. If there is no other solution I will have to...

Since my functions work with a "normal" html file and I can also load a local script file corretly, I think I forgot to set something correctly to be able to execute the external code.

I set the Content-Security-Policy to

<meta http-equiv="Content-Security-Policy" content="default-src: 'self' https://myhost https://maps.google.com 'unsafe-inline' 'unsafe-eval'">
<meta http-equiv="Content-Security-Policy" content="script-src: 'self' https://myhost https://maps.google.com 'unsafe-inline' 'unsafe-eval'">

I also entered the cordova-plugin-whitelist parameters

<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
<access origin="https://*.googleapis.com" />
<access origin="https://myhost" />
<access origin="*" />
<allow-navigation href="https://*.googleapis.com" />
<allow-navigation href="https://myhost" />
<allow-navigation href="*" />
<allow-intent href="https://*.googleapis.com" />
<allow-intent href="https://myhost" />
<allow-intent href="*" />

But somehow that does not seem to work, too.

Does anyone have a solution to be able to execute the code after loading the external file?

Later the google maps javascript api needs to be asyncron, but that's a nother issue then.


index.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">

    <meta name="format-detection" content="telephone=no">
    <meta name="msapplication-tap-highlight" content="no">
    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
    <!-- Enable all requests, inline styles, and eval() -->
    <meta http-equiv="Content-Security-Policy" content="default-src: 'self' https://myhost https://maps.google.com 'unsafe-inline' 'unsafe-eval'">
    <meta http-equiv="Content-Security-Policy" content="script-src: 'self' https://myhost https://maps.google.com 'unsafe-inline' 'unsafe-eval'">
    <link rel="stylesheet" type="text/css" href="css/index.css">
    <title>Testapp</title>
</head>
<body>
    <div class="app">
        <h1>Testapp</h1>
        <button id="loadexternal_button">load external file</button> &nbsp;
        <button id="isloaded_button">is loaded?</button>
        <div id="map"></div>
    </div>
    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript" src="scripts/platformOverrides.js"></script>
    <script type="text/javascript" src="scripts/index.js"></script>
</body>
</html>

index.css

.app {
    background-color:white;
}

#map{
    height: 400px;
    width: 400px;
    border:1px solid white;
}

index.js

(function () {
    "use strict";

    function onDeviceReady() {
        
        // Event Listener for Buttons: https://stackoverflow.com/a/31892530/2381164
        document.getElementById('isloaded_button').addEventListener('click', function () { checkLoadedFile(); }, false);
        document.getElementById('loadexternal_button').addEventListener('click', function () { loadJS('https://myhost/external_file.js', hasloaded(), document.body);
    }, false);
    };

    // https://stackoverflow.com/a/950146/2381164
    function loadJS(url, implementationCode, location) {

        var scriptTag = document.createElement('script');
        scriptTag.src = url;

        scriptTag.onload = implementationCode;
        scriptTag.onreadystatechange = implementationCode;

        location.appendChild(scriptTag);
    };

    // Change color of div when script is loaded
    function hasloaded() {
        var mapElement = document.getElementById('map');
        mapElement.setAttribute('style', 'border:1px solid yellow');
    }
    // Change background-color of div when file is loaded propperly
    function checkLoadedFile() {
        var mapElement = document.getElementById('map');

        if (typeof external_function === 'function') {
            mapElement.setAttribute('style', 'background-color: green;');
        } else {
            mapElement.setAttribute('style', 'background-color: red;');
        }
    }
    // Load when App is ready
    document.addEventListener('deviceready', onDeviceReady.bind(this), false);
})();

external_file.js

function external_function() {
    var mapElement = document.getElementById('map');
    mapElement.setAttribute('style', 'background-color: orange;');
}
Holger
  • 53
  • 1
  • 9

1 Answers1

2

This is the security policy meta i am currently using:

<meta http-equiv="Content-Security-Policy" content="default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval; media-src *">

It currently accepts everything I throw at it! ...please keep in mind that using

content="default-src *;

is not 100% safe as it will run scripts from any location (local or online), but as long as you have

script-src 'self'

in your security meta... the problems you are currently facing while executing external scripts should be a thing of the past!

Really Nice Code
  • 1,144
  • 1
  • 13
  • 22
  • I also noticed that VS adds a `Content-Security-Policy` of its own (which I missed bevore). I had to delete that line, too (see 2nd meta information in index.html) – Holger Jul 06 '17 at 04:57
  • They may look similar but from my experience, they behave differently for some reason. Try adding `content="default-src *;` in your meta and let me know if it was successful. If you are still experiencing problems then you could use the **PLAN B** method, which is basically creating a separate .html page and adding all of the external script links to that page... then embed the external .html page into your main application via an iFrame. If you are still experiencing problems then you may have to try using the cordova inAppBrowser plugin.. then load the page with your google api through that. – Really Nice Code Jul 06 '17 at 14:14
  • I got it running. THX. As mentioned in my previous comment, I also forgot to delete the default line in my html file. – Holger Jul 11 '17 at 10:15