When developing a mobile app using Cordova or PhoneGap, the browser target platform can really speed up your development. You could serve the HTML files directly using cordova serve, but the browser platform, while being almost as fast, is much closer to the Android / IOS environments your app will eventually find itself in. It also has access to the Cordova APIs.

My general workflow is that I keep cordova run browser running in a terminal window (this will initially start a new instance of chrome), and periodically run cordova prepare browser as I’m developing. This last step packages up the “app”, along with the cordova.js bits, for the browser platform.

However, if your app contacts an external API or server at any point, for example with jQuery.ajax(), you will be greeted by the following error:

XMLHttpRequest cannot load http://some.api.com/api/endpoint. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8000' is therefore not allowed
access.

In short, your chrome browser is (wisely) refusing to access that outside resource (the API or server) for security reasons. If your browser did not do this, an attacker could quite easily access web services using your identity!

Reading up about this issue in the context of Cordova / PhoneGap, you’ll find the common solution to be either to modify the server that you’re accessing to allow explicitly this sort of cross-origin access, or to setup a proxy if the former is not possible. Often the former is indeed not possible (in my case, the app is talking to a hardware router API), but the latter is just way too much unnecessary effort.

The easy (but good) fix

Recall that cordova starts up a new instance of chrome which is only used to access your app. The app is completely under your control, so the risk of foul play by a third party is significantly reduced. Instead of setting up proxies, or changing servers, we could just instruct this special instance of chrome to ignore its cross-origin rules!

It took me a while to track this down, so here you go: Edit browser.js in yourapp/platforms/browser/cordova/node_modules/cordova-serve/src and change just the chromeArgs line so it looks like the one in the snippet below (you’re just adding the –disable-web-security argument):

1
2
3
4
function getBrowser(target, dataDir) {
    dataDir = dataDir || 'temp_chrome_user_data_dir_for_cordova';

    var chromeArgs = ' --user-data-dir=/tmp/' + dataDir + ' --disable-web-security';

Now make 100% sure that all of your Cordova chrome instances are stopped. The next time you do cordova run browser, note that the chrome window that appears has a yellow bar warning you about web security:

chrome-disable-web-security-warning.jpg

Only the special chrome instances started up by Cordova for apps where you have applied the above fix will have web-security disabled. By all means take note of the yellow warning, but also do enjoy all of your Cordova app requests successfully contacting the outside world!