For the past few days I've been playing with a new, and rather interesting, mobile debugging tool called GapDebug. Currently in private beta, it will switch to an open beta around July 9th. You can sign up on the site to get notified when it becomes available.
I've begun work on trying to answer the questions I gathered concerning Cordova's FileSystem support. As I work through the questions I'm trying to build "real" samples to go along with the text. My first sample is a simple one, but I think it is pretty relevant for the types of things folks may do with Cordova and the file system - checking to see if a file exists locally and if not - fetching it.
A large majority of the questions I get about PhoneGap and Cordova revolve around the file system API. It has had some pretty significant updates recently but still remains one of the most difficult ones to use. I've been putting off really digging deep into those questions because many times they are incredibly specific to a particular user's application. And - honestly - they typically don't lend themselves to the type of quick questions I can answer during the day.
So with that in mind, I thought it might be fruitful to ask my readers about the API and how I can help make things a bit clearer - for both you and me. What I'm thinking is - can we come up with a list of basic questions, a FAQ perhaps, for just this API. It can't be something too precise to one particular application, but something that can apply to multiple users.
As an example: How do I download an asset to my application? That's a simple question, but it brings up the question of where you would download the asset and how you would actually use it later.
Of course, the big issue is that this particular API is an evolving one. Anything I do today will be outdated next year. But as most of my blog posts on the API are already over a year old, this would at least be a bit fresher. ;)
In order to organize this list, I'm going to start it in the blog entry. Use the comments to make suggestions, and as I see ones that I think make sense, I'll add them to the list. By the way, I know some of these are super trivial, but I figure it doesn't hurt to try to cover as much as possible.
File System FAQ
- When does it make sense to use the file system (versus LocalStorage or WebSQL)?
- How do I download an asset to my application?
- How do I use a file stored in the file system (both binary and text-based files)?
- How do I check to see if a file exists in a directory?
- Are there external tools that can check a device's file system?
- How do I check to see if a directory exists?
- How do I make a subdirectory where the parent directory may not exist?
- Are there any app store restrictions/guidelines for using the file system?
- For iOS, where can I store files so that they will be backed up to iCloud?
- How can I get metadata (size, updated) about a file?
A few months ago I launched a new GitHub repo (https://github.com/cfjedimaster/Cordova-Examples) as a way to try to collect my various Cordova examples together under one roof. I had planned to add to it regularly but - life - as you know - gets in the way. I've finally gotten around to adding another example, this one for the Media API.
About a month or two ago I noticed something odd with my Cordova tests. I'd fire off a call to the iOS simulator by doing
cordova emulate ios. The first time, it worked fine. But as I edited I noticed something odd. Subsequent calls to the emulator would end up in a blank screen in the emulator. If I watched carefully, I'd see my app load for a split second before going black.
I discovered something new last night, which was painful like all good learning tends to be. I'm building a Cordova application for a client that - like most hybrid apps - can be run via a local web server for most of the development process. This particular project involves a complex dynamic form process that isn't Cordova-related at all. Later on we'll be adding in barcode scanning but for the foreseeable future I'm running it as a simple web page.
My application makes multiple XHR requests to the client's server for various things, and in order to make that work I'm using CORS. I won't need CORS once I switch to a proper hybrid app. I could also use Ripple too. But again - I just don't need this now at this point in the development.
Everything was kosher until I began to lock down some of the calls to require a session variable. In all my Cordova apps before I relied on the fact that sessions (cookie-based sessions) "just work" when doing XHR. If your back end server responds with cookies, then your front end code will respect that and send them back on future requests. This enables session management to work on your server.
Except when I used CORS! I couldn't understand why I kept getting an error saying that an earlier session variable wasn't defined. Like any good developer, I opened up my dev tools and examined the cookies being sent back and forth in my calls. (And again, if you have no idea how that is done, speak up in the comments.) I noticed right away that the session cookies were not sticking. So what was the problem?
If you read the docs for XHR and CORS you discover this little gem:
The most interesting capability exposed by both XMLHttpRequest and Access Control is the ability to make "credentialed" requests that are cognizant of HTTP Cookies and HTTP Authentication information. By default, in cross-site XMLHttpRequest invocations, browsers will not send credentials. A specific flag has to be set on the XMLHttpRequest object when it is invoked.
In English, the cookies won't go back and forth. Raise your hand if you knew that. Now lower it you liar. ;) Luckily it is easy enough to fix with a flag in the XHR object. AngularJS exposes it as a property, withCredentials.
But you then may run into yet another issue. My CORS header on the server was using Access-Control-Allow-Origin with a value of *. Basically, anyone and everyone can hit me. When you enable credentials on XHR, this is no longer allowed. Basically the browser is saying, "Sorry, this server is just too promiscuous for me." So for now, I've simply specified my local dev server in the origin. Once I get further down the line I'll probably remove CORS completely as it won't be needed for Cordova.
So I know (think?) there is a significant portion of my audience who do not use Twitter, and for those of you who have avoided that trap (don't let anyone fool you, it is a trap), you may have missed me recently raving about the Ionic Framework. Briefly, Ionic is a way to work with Cordova/PhoneGap apps using Angular directives. It has an incredible collection of UI and UX controls that can be helpful to you. I'm still new to Angular and I've found their controls easy to use. I plan on blogging about this a bit more later, but I wanted to tell you about something else these folks created - ngCordova.
I'm just passing this along, but I think folks who are doing work in the mobile space and making use of tools like Cordova may find this useful: Code Injection Attacks on HTML5-based Mobile Apps. It is a bit long winded and repetitive, and also a bit out of date (it talks about PhoneGap and how it ships a set of core plugins, which hasn't been true since 3.0). It also makes some pretty odd statements like, apparently, the same HTML, CSS, and JS works the same across different platforms. Yeah, I'd love to live in that world. But despite that, it does make a good point about XSS and hybrid applications. Read it - digest it - and think about it.
Also be sure to read the recently released Security Guide for Cordova.
Over the holiday weekend Cordova 3.5.0 was released. You can read details about the update here: Apache Cordova 3.5.0. Another update was to the documentation, which now includes a What's Next guide that talks about what Cordova developers should learn, think about, and bookmark for future reference after they've learned the basics. I think this is an important piece of documentation and I'm happy to see it finally published. (Oh, and I may be a bit biased as I wrote the first draft. ;)
Also released is a new Security Guide for Cordova developers. Definitely check this out as well.
That's probably the longest title I ever used for a blog post. A PhoneGap user came to me recently with an interesting problem. His application was set to be portrait only. In case you weren't aware, you can lock orientation for an application using this config.xml value: