Saturday, April 14, 2012

Debugging a PhoneGap App

At Stix, we've been porting our web client to PhoneGap over the past 4 months. True to the focus principle of the Lean Startup approach, we've been focusing on iOS as the target.

While we've had to work at several obstacles, like graphic performance and responsiveness, the biggest challenge by far was debugging. We have gotten used to working with the awesome WebKit Web Inspector (A.K.A Chrome Developer Tools), with conditional breakpoints, DOM and CSS inspection, and the console. Switching to working with an iOS device or simulator, these capabilities were sorely missed. Here is a brief overview of our current debugging approach.


Yes, you can run a PhoneGap app in Chrome. There are few obstacles to overcome, but it's definitely worth it.

The first obstacle is that Chrome has a relatively restrictive cross-origin policy. Even the simplest PhoneGap apps will run into problems trying to include js and css files from the file:/// protocol, not to mention trying to access a server. Fortunately, Chrome has a "--disable-web-security" command line switch to shut all this protection down. Be warned! shutting down web security makes your browser extremely vulnerable to attack, even when browsing respectable and secure websites. Do not use a security-disabled browser for anything other than running your own code. My recommendation is to create a new shortcut (I think we use a command file on the Mac, but I don't have it with me to check now) which runs Chrome with both a "--disable-web-security" and a "--user-data-dir=/Users/unsafeChromeProfile" (or some other folder, say "C:\unsafeChromeProfile" on Windows). Name the shortcut properly ("Unsafe Chrome") and don't use it for anything else.

The second obstacle is that none of the PhoneGap APIs will work in Chrome. The solution is of course to use stubs. We have a simple utility function isPhoneGap() which checks whether we are in a PhoneGap webview or in Chrome, which we use to decide whether to use the PhoneGap API or some stub alternative.


Weinre (we pronounce it "winery") is an incredibly useful tool which makes most of the WebKit Web Inspector available over the network. It's short for Web Inspector Remote. We use the Mac installed version, and it allows us to inspect the DOM, CSS, view console.log output and run commands from the console. If you're running on an iOS device or simulator, make sure you white-list the server address in your app's PhoneGap.plist file (we whitelist "*" in development, just make you remove it before packaging an ipa). Debugging in Chrome is much easier and friendlier, but once every couple of hundred lines of code you'll get a bug that only happens on a device, and then weinre is your friend to figure out what's going wrong.

Catching Exceptions

This is probably the trickiest part. When running from Chrome we can make use of the life-saving debugger. In that case, you want to make sure you set your debugging mode to "pause on uncaught exceptions", and make sure you don't catch any exceptions which aren't part of the normal flow. However, when running on the device or simulator, there is no debugger available (oh, how I wish there was). In that case, you want to wrap as much of your code as possible with try..catch blocks that would let you know that you had an exception, plus all the information you can gather about it, by printing it to console output (which is visible in Xcode and in weinre). I've spent some time writing a utility that systematically wraps each method of each of our classes with such a block (we use Backbone.js for classes, but the same wrapping could be applied to other class systems). If someone is interested I can try to extract it from our infra and share it, but it's relatively new so don't expect too much of it. I hope I'll find the time at some point to clean it up and open-source it.

The problem is that the iOS webkit used in PhoneGap does not seem to be very informative in the exceptions it passes to catch blocks. It does not provide a stack property, or even a file name and line number describing where the exception was thrown. All you get is a message describing the type of error, and even that message is usually quite general (e.g. "undefined is not an object" in an error where Chrome provides the much more helpful "Cannot run 'destroy' method of undefined"). What we did is extend the systematic wrapper above to manually maintain a string-array description of the current stack so we can print it when we catch an exception. We still can't get the specific line number, but it narrows it down to the function where the error occurred. If you keep your functions short (and it's generally a mark of good design if you do), this can go along way to identify where the bug is (remember, this is only for bugs that you can't reproduce in Chrome, otherwise you're much better off using the web inspector's debugger).

I don't know what the performance cost of all this wrapping is, but it's quite easy to make sure you only do it in your development and testing environments.

I hope this helps others struggling with the same challenges. I'll try to come back to this post and update as we learn more, but the easiest way to make sure this post becomes a useful resource, is for you readers to contribute your own perspective and/or raise any questions you may have in the comments. I promise to take the time to respond.

Sunday, May 23, 2010

Multiple Accounts in a Single Browser

Most popular web 2.0 services, whether they provide webmail (e.g. Gmail, Yahoo Mail), social networking (e.g. Facebook, LinkedIn), microblogging (e.g. Twitter, Tumblr), or anything else, use cookies to keep you signed in from visit to visit.
This is very convenient, and saves you the trouble of having to log in every time you go to their website. Almost of them fail to support keeping more than one account logged in at time from the same computer. This is somewhat understandable, since they don't want a user to remain logged in while others are using the computer (which is why they have that 'Remember me' checkbox, which you really shouldn't check when logging in from a public computer). However, what about those of us who actually know what we're doing, and want override this behaviour? What if I have more than one Gmail account, or Twitter account, and I want to use them without having to log in again every time I switch accounts? And what if I really do trust my wife, but still want to keep separate Facebook accounts? For a long while, I used multiple browsers for this. I would log into my personal mailbox from Firefox, and into my work mailbox from Opera, or Chrome, or whatever. It solves the biggest issue (each browser remains logged in, and you can view both accounts simultaneously), but it's not an ideal solution, because I didn't get to use my browser of choice, I was still limited to 3-4 accounts of every web service, and I had to remember which account is logged in at which browser.
Fortunately, there's a much more elegant solution, if your browser of preference is Firefox or Chrome (I haven't researched others), and that is why I am writing this post:

Easily Access Multiple Accounts in Firefox

  1. Run Firefox once with the -ProfileManager command line switch. You can simply edit the shortcut you're already using, and add "-ProfileManager" at the end of the command:
  2. Create however many profiles you want to use, and give them meaningful names, such as '', 'dad', etc.
  3. Create a separate shortcut for each profile you want to use:
    1. Decide which profile you want as your main profile. This profile is the one where external links will be opened (for example if someone sends you a link in Skype). For the shortcut of this profile, simply add the command line switch "-P", followed by the profile name (make sure there's a space between the switch and the profile name):
    2. For each additional profile shortcut, also add the switch "-no-remote". This tells Firefox to ignore that profile when looking for a browser to open external links, and this is the trick which allows you to have multiple profiles open at the same time:

Easily Access Multiple Accounts in Google Chrome or Chromium

  1. For every profile, except your main profile, create a directory. These directories can be placed anywhere and can be named anything, but I recommend using meaningful names. I will use "C:\ChromeProfiles\Buck" as an example.
  2. Create a shortcut for each profile you want to use:
    1. For your main profile you can use your existing shortcut, without any changes. I believe Chrome will use this one to open external links (for example if someone sends you a link in Skype), but I'm a Firefox user myself and haven't tested this.
    2. For each additional profile, add the command line switch "--user-data-dir=", followed by the path to the directory you created for it (no space between the switch and the path):

Sunday, November 8, 2009

My Barking Mad Neighbour

An elderly neighbour of ours, recently deceased, used to be very upset with us for keeping a large dog (Daisy's medium, actually). I guess he wasn't very mentally stable, because besides yelling at us how wrong it is to keep such a vicious dog (she never did anything but bark), he would also frequently bark back at her - quite impressively.
We were a little concerned at the time that he might do something about it (from complaining to our landlord to trying to hurt Daisy), and somewhat relieved when he moved out (apparently to a home for the elderly).
I just now realised that he may have sometime witnessed a dog doing something very vicious, and that it would explain his extreme reaction to being barked at. I suddenly don't dislike him anymore.

Friday, October 17, 2008

Final (hopefully) Gmail RTL update

I've just received an update from users in Australia that the 'Right-to left editing support' option appears in their settings page.
Thank you Google! (finally)

I believe this completely and finally resolves the issue, so hopefully I won't be writing about it anymore. I'd just like to say how satisfying it is to see a positive change influenced by the voice of the people.

If anyone still has problems with this, drop me a line.

Friday, September 19, 2008

Gmail RTL update

I've received several reports from Gmail users that they now have the RTL/LTR buttons in the English interface. So far all reports came from users located in Israel's IP-address space, and I have been unable to see the buttons when using Gmail from the UK (Google Mail as it calls itself there), so my current conclusion is that the visibility of the buttons is dependent on the user's IP address.

There is currently no official word from Google on the subject, as far as I can see, so my theory is still to be verified (feel free to share your own experience if it adds to my observations either way). However, if my understanding is correct this should solve the problem for the great majority of relevant users for the great majority of the time (I'm assuming here that IP addresses in Arab/Persian/etc. speaking areas also have access to the buttons).
I imagine the limitation stems from the desire not to further complicate Gmail's settings pages.

The only thing missing now is a back-door to activate the feature when using Gmail from other countries. I could suggest a html tag along the lines of:

Google, if you please?

Wednesday, August 20, 2008

Why write a blog?

My CEO has challenged me to explain why I keep a blog. He says he just doesn't get why most people write blogs - where do we get the presumption to think we have something so interesting to say we feel compelled to broadcast it to the world?

My first line of defence was that I have no such presumption and I don't mean to 'broadcast' my thoughts to anyone. The blog, I claimed, was just somewhere I can dump text, and then I'm able to refer people to it instead of having to repeat myself.

While this is rather true for a couple of posts (writing RTL and my name's spelling), it's a load of bull when it comes to anything else I've written.
I've realised long ago that I do have some pretty big presumptions about what I have to say to the world and about how much it would (or should) interest people.

I simply want to be heard. To feel that I'm being listened to. I like the attention.
It's a very basic human need, so I guess it's no surprise there are so many bloggers out there. As long as you don't expect people to read it, I see nothing wrong with it.

Yisrael, if you read this far, perhaps you could spare the time to read through the 'How Do You See the World?' post (it's the bottom-most one). I'd like to hear your answers.

Sunday, July 27, 2008

The Lemma of Infinite Formality

"For any statement, as trivial as it may be, there exists a finite set of more trivial statements, from which it can be derived."