Techno Barje

Arretetoi.la - La Géolocalisation Horodaté!

http://arretetoi.la/

Cette application web va vous permettre de récupérer une liste de restaurants le long d’un trajet en voiture. D’abord, vous indiquez votre lieu de départ, d’arrivée ainsi que l’heure à laquelle vous comptez partir. Tout ceci pour obtenir une liste de restaurants chaudement recommandés par Dismoiou.fr. Jusque là, rien de révolutionnaire! Mais la particularité de ce service est d’afficher des adresses uniquement autour des villes que vous allez croiser autour des horaires de repas. Ainsi, si vous faites Paris-Marseille en partant à 8h, le site vous proposera de déjeuner près de lyon, car vous devrez y être autour de midi!

Arretetoi.la est un service à la fois géolocalisé mais surtout horodaté!

Les site marche aussi bien sur ordinateur que sur téléphone. La version sur ordinateur vous permettra de préparer un parcours et d’estimer où vous pourriez manger. Tandis que la version mobile vous permettra de mettre à jour l’estimation en fonction de votre progression. En effet, votre téléphone pourra transmettre votre position exacte et mettre à jour la zone de déjeuner/diner.
Voici un aperçu de la version ordinateur:

Indication des lieux de départ/arrivée ainsi que l’heure de départ Votre trajet horodaté Lieu où vous serez à midi ou 20h, avec les restaurants recommandés

La version mobile:

Indication de votre lieu d’arrivée, le reste se remplit automatiquement Liste des restaurants recommandés autour de midi ou 20h Affichage du restaurant sélectionné sur une carte avec votre trajet

Enfin, notez que vous pouvez ajouter cette application à votre écran d’accueil sur iphone et android. Ainsi que sur ordinateur avec le navigateur chrome via le chrome web store.

Google Maps Hacks Part2 - Cool Function to Power Up Route, Directions

Another day, another library!
This new library brings some usefull functions and one of them is just awesome :)
Start with these usefull functions:

  • return the distance between two points,
  • retrieve the a point at a given distance between two another,
  • compute the square box with a given size around a point

And the awesome function allows you to find the point at a given duration on a direction computed by google maps API. For example, you may retrieve the precive point where you are going to be after 1hour driving on the road from Paris to Berlin!
For more information, I suggest you to check at the README available on github: https://github.com/ochameau/google-map-api-path-tools

As usual, source code is available under LGPL Licence.

UIWebView Secrets - Part3 - How to Properly Call ObjectiveC From Javascript

Let’s change the subject: this time no more talks about memory but always on UIWebView component. When we use this component for something else than just displaying webpages, like building UI with HTML, Javascript, … We often want to call Javascript functions from objective C and the opposite.

Call Javascript function from Objective-C:

The first move is easily done with the following piece of code:

  // In your Javascript files:
    function myJavascriptFunction () {
    
      // Do whatever your want!
    
    }
  
  // -----------------------------------
  
  // And in your Objective-C code:
  // Call Javascript function from Objective-C:
    [webview stringByEvaluatingJavaScriptFromString:@"myJavascriptFunction()"];



Call Objective-C function from Javascript:

But calling objective-c from a Javascript function is not easy as Iphone SDK doesn’t offer any native way to do this! So we have to use any king of hack to do this …
The most known, used and buggy practice is to register a UIWebViewDelegate on your web view and « catch-and-immediatly-cancel » a location change done in javascript.

(a very extremely plenty much advised practice!)

  // In Objective-C
  - someFunctionOnInit {
    
    webView = [[UIWebView alloc] init];
    // Register the UIWebViewDelegate in order to shouldStartLoadWithRequest to be called (next function)
    webView.delegate = self;  
    
  }
  
  // This function is called on all location change :
  - (BOOL)webView:(UIWebView *)webView2 
          shouldStartLoadWithRequest:(NSURLRequest *)request 
          navigationType:(UIWebViewNavigationType)navigationType {
    
    // Intercept custom location change, URL begins with "js-call:"
    if ([[[request URL] absoluteString] hasPrefix:@"js-call:"]) {
      
      // Extract the selector name from the URL
      NSArray *components = [requestString componentsSeparatedByString:@":"];
      NSString *function = [components objectAtIndex:1];
      
      // Call the given selector
      [self performSelector:NSSelectorFromString(functionName)];
      
      // Cancel the location change
      return NO;
    }
    
    // Accept this location change
    return YES;
    
  }
  
  - (void)myObjectiveCFunction {
    
    // Do whatever you want!
   
  }

  // -----------------------------------
  
  // Now in your javascript simply do this to call your objective-c function:
  // /!\ But for those who just read title and code, take care, this is a buggy practice /!\\n  window.location = "js-call:myObjectiveCFunction";



What’s wrong with UIWebViewDelegate, shouldStartLoadWithRequest and location change ?

There is weird but apprehensible bugs with this practice:
a lot of javascript/html stuff get broken when we cancel a location change:

  • All setInterval and setTimeout immediatly stop on location change
  • Every innerHTML won’t work after a canceled location change!
  • You may get other really weird bugs, really hard to diagnose …

Sample application highlighting these bugs

Key files of this example:

  • MyWebview.m: Objective-c part, that inherit from UIWebView. Set the UIWebViewDelegate and catch requests in shouldStartLoadWithRequest selector.
  • NativeBridge.js: Tiny javascript library in order to change the location and offer a way to send arguments and receive a response.
  • webview-script.js: Test case script, that highlight these bugs.

In webview-script.js: InnerHTML stop working whereas textContent continues to …

  document.getElementById("count").innerHTML = i;
  document.getElementById("count2").textContent = i;


But we can’t charge Apple on this bug. I mean we try to load another location in the document we are working on! The webview component may start doing stuff before the delegate call, which cancel the load …
We have to find alternative way to communicate with the native code!

Better way to call Objective-C

The only thing we have to change is in Javascript code. Instead of changing the document location, we create an IFrame and set its location to a value that trigger the shouldStartLoadWithRequest method.
And voilà!

  var iframe = document.createElement("IFRAME");
  iframe.setAttribute("src", "js-frame:myObjectiveCFunction";
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;

Here is another sample application, with exactly the same structures and test file.
But this time you are going to see innerHTML and setTimeout working! Again, this demo contains a library (NativeBridge.js) that allow to send arguments to native code and get back a result in javascript asynchronously, with a callback function.

Best practice example!



Free Objective-C<->Javascript library

Finally I provide the communication library under LGPL licence so it can ease your work on iphone platform! As I know that it’s really not easy ;-)

The code is full of comment, so you may easily use and tweak it!

Github repo

UIWebView Secrets - Part2 - Leaks on Release

Continue on iphone with leaks around UIWebView! Here is another big one with no apparent solution. When we try to release a UIWebView component, very few memory is freed. So any application using this object to display webpages is going to crash quickly with Low memory exception :(


I think this memory usage graph gives an idea on how big is this new king of leak: memory usage

  1. Create a UIWebView
  2. Load http://www.google.com/
  3. Release the webview (UIWebView dealloc is correctly called!)
    Look how so few memory is freed :/

Test Application

The leak is all but tiny! Before the loading of the webpage, the application was using 630kB of memory, and after the release of the UIWebview, 1150kB! So we have a 500KB leak in order to simply display the home of Google.com!

This time, I didn’t manage to find any hack to solve this bug.
So if you have any tips to fix this, don’t hesitate to post a comment!

I’ve tried a lot of differents hacks to free more memory (or use less), like:

  // Setup the webview to disable some fancy effect on phone number, but doesn't change anything on memory released ...
  webview.dataDetectorTypes = UIDataDetectorTypeNone;
  webview.allowsInlineMediaPlayback = NO;

or

  // Remove and disable all URL Cache, but doesn't seem to affect the memory
  [[NSURLCache sharedURLCache] removeAllCachedResponses];
  [[NSURLCache sharedURLCache] setDiskCapacity:0];
  [[NSURLCache sharedURLCache] setMemoryCapacity:0];

or

  // Remove all credential on release, but memory used doesn't move!
  NSURLCredentialStorage *credentialsStorage = [NSURLCredentialStorage sharedCredentialStorage];
  NSDictionary *allCredentials = [credentialsStorage allCredentials];
  for (NSURLProtectionSpace *protectionSpace in allCredentials) {
    NSDictionary *credentials = [credentialsStorage credentialsForProtectionSpace:protectionSpace];
    for (NSString *credentialKey in credentials) {
      [credentialsStorage removeCredential:[credentials objectForKey:credentialKey] forProtectionSpace:protectionSpace];
    }
  }

or

  // Cleanup the HTML document by removing all content
  // This time, this hack free some additional memory on some websites, mainly big ones with a lot of content
  [webview stringByEvaluatingJavaScriptFromString:@"document.body.innerHTML='';"];



But I never reach complete release of memory used by the web component :(

UIWebView Secrets - Part1 - Memory Leaks on Xmlhttprequest

My first blog post on iphone subject reveal a big memory bug when using UIWebView component. This is the (only one) component to display some HTML content in an iphone interface. UIWebView object has a lot of differents issues and I’m going to highlight the biggest of them. Actually, all XMLHttpRequests used in javascript code are fully leaking!!! I mean when you do a request that retrieve 100ko of data, your memory used grow up for 100ko! This bug is not always active, but almost always. In fact the trigger to enable it is to simply open one link in your UIWebView. For example, clicking on a <a> link.

But let’s look at a memory usage graph while we execute this simple test application: memory usage graph

  1. Create the UIWebView object
  2. Load a local HTML test file
  3. Execute 3 XMLHttpRequest to google.com, notice how the memory is freed three times after each request!
  4. Trigger the leak by opening a page that redirect back to our test file
  5. Execute the same 3 XMLHttpRequest and look how much memory is used and totally leaked :/
  6. We clean the HTML document with document.body.innerHTML=”; (sometimes free some memory, when we have a lot of DOM objects)
  7. release the UIWebView (almost no memory freed, next post is going to analyse that)

Test Application


So, to sum up, usually, when you execute this Javascript in a UIWebView:

  var xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
      // Do whatever you want with the result
      
    }
  };
  xmlhttp.open("GET", "http://your.domain/your.request/...", true);
  xmlhttp.send();

Your are going to have a big memory usage and leak a lot of data!

But there is a hack to solve this problem: revert what is done when you open a link.
In fact, the key property which leads to this leak is the WebKitCacheModelPreferenceKey application setting. And when you open a link in a UIWebView, this property is automatically set to the value "1". So, the solution is to set it back to 0 everytime you open a link. You may easily do this by adding a UIWebViewDelegate to your UIWebView :

- (void)webViewDidFinishLoad:(UIWebView *)webView {
  [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"];
}

So are you going to have much less crash due to "Low Memory" :)

CSS animation+CSS transform+SVG Powered by Firefox = Kaleidoscope

kaleidoscope result
The amazing power of web technologies like CSS, HTML and SVG comes when you mix them all together! The arrival of the new mozilla specific CSS property -moz-element totally unleashed the power of CSS animation/transition when it comes to doing graphical effects. And I’m pretty sure that we may go even more futher by using others standards like HTML and SVG …
In order to show you how simple and powerfull these technologies mix can be, I’ve add two extra features on top of this kaleidoscope:

  • The first one, use a video instead of an image: Video Kaleidoscope
  • The second one allow you to specify a custom image by select or drag’n drop: Custom image

I find these two features quite powerfull, and what’s totally awesome is how simple they are: only 3 lines of HTML in the first case, tens lines of javascript in the second one!

Kaleidoscope demo

Need Firefox 4 Beta 6 or a nightly!

Finally, you may look at this tutorial that explain point by point how to achieve a Kaleidoscope by mixing -moz-element+SVG+CSS animations and transform:

Kaleidoscope tutorial

Jsctypes + Win32api + Jetpack = Jetintray

JSCtypes! What a powerfull tool, that allows to call native libraries with our simple Javascript.
Jetpack! What a powerfull tool, that allows to build reliably javascript applications, with unittests, memory profiling, web IDE, …
And WinAPI … a giant C library still in production in 2010 that allows to do very various things on Windows platform.

Mix all that and you get:

JetInTray

A jetpack API for adding Tray icons on windows via jsctypes and on linux with a binary xpcom component (I didn’t had time to work on a jsctypes version).
You may checkout this jetpack package directly from github.
Or if you want to learn jsctypes I suggest you to look at files in lib directory and to read my two previous posts on jsctypes.

  • I explained on the first one how to start playing with jsctypes, how to create C-structures and call functions.
  • Then I showed in the second post, how to create a JS callback passed to the native library as a function pointer.



That said, I wanted to highlight some underground hacks around win32api! In WinAPI, there is no addEventListener/setEventCallback/addActionListener/… In fact, there is the well known WndProc messages function, that receives absolutely all event of the application!! (Yes for real!) We define this function as a static function named WndProc. But in Jsctypes case, that’s impossible to define a static function, we can only create function pointers. That’s where comes the not so known hack which allow to register dynamically such event listener.

  • First we have to define our listener function following the WinAPI datatypes
    Components.utils.import("resource://gre/modules/ctypes.jsm");
    var libs = {};
    libs.user32 = ctypes.open("user32.dll");
    
    // Define the function pointer type
    var WindowProcType = 
      ctypes.FunctionType(ctypes.stdcall_abi, ctypes.int,
        [ctypes.voidptr_t, ctypes.int32_t, ctypes.int32_t, ctypes.int32_t]).ptr;
    
    // Bind a usefull API function
    var DefWindowProc = libs.user32.declare("DefWindowProcA", ctypes.winapi_abi, ctypes.int,
        ctypes.voidptr_t, ctypes.int32_t, ctypes.int32_t, ctypes.int32_t);
    
    // Set our javascript callback
    function windowProcJSCallback(hWnd, uMsg, wParam, lParam) {
      
      // ... do something smart with this event!
      
      // You HAVE TO call this api function when you don't known how to handle an event
      // or your apply is going to crash or do nothing
      return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    
    // Retrieve a C function pointer for our Javascript callback
    var WindowProcPointer = WindowProcType(windowProcJSCallback);
    
  • Then we may fill a WNDCLASS structure with our fresh function pointer. This structure is used to create a new window class that use it own WndProc (not the default static function). See msdn doc for more information.
    var WNDCLASS = 
      ctypes.StructType("WNDCLASS",
        [
          { style  : ctypes.uint32_t },
          { lpfnWndProc  : WindowProcType }, // here is our function pointer!
          { cbClsExtra  : ctypes.int32_t },
          { cbWndExtra  : ctypes.int32_t },
          { hInstance  : ctypes.voidptr_t },
          { hIcon  : ctypes.voidptr_t },
          { hCursor  : ctypes.voidptr_t },
          { hbrBackground  : ctypes.voidptr_t },
          { lpszMenuName  : ctypes.char.ptr },
          { lpszClassName  : ctypes.char.ptr }
        ]);
    var wndclass = WNDCLASS();
    wndclass.lpszClassName = ctypes.char.array()("class-custom-wndproc");
    wndclass.lpfnWndProc = WindowProcType(windowProcCallback);   // <---- here it is!
    RegisterClass(wndclass.address());
    
  • After that we may create a hidden window that is created only to catch events.
    var CreateWindowEx = 
      libs.user32.declare( "CreateWindowExA", ctypes.winapi_abi, ctypes.voidptr_t,
          ctypes.long,
          ctypes.char.ptr,
          ctypes.char.ptr,
          ctypes.int,
          ctypes.int,
          ctypes.int,
          ctypes.int,
          ctypes.int,
          ctypes.voidptr_t,
          ctypes.voidptr_t,
          ctypes.voidptr_t,
          ctypes.voidptr_t
        );
    var HWND_MESSAGE = -3; // This is the code for message-only window
                          // http://msdn.microsoft.com/en-us/library/ms632599%28VS.85%29.aspx#message_only
    var win = CreateWindowEx(
        0, wndclass.lpszClassName,
        ctypes.char.array()("messages-only-window"),
        0, 0, 0, 0, 0,
        ctypes.voidptr_t(HWND_MESSAGE), null, null, null);
    
  • Finally, we only have to bind this window to any component which dispatch messages/events in order to receive them in our windowProcJSCallback callback. That’s it!

Jsctypes Unleashed

As bugs 573066 and 585175 are fixed and available in last Firefox nightlies, we can now use JSCtypes at full power!

Thanks to dwitte for quick fixes!

That means :

  • Complex C-struct usage,
  • The possibility to define a JS callback seen by C library as a function pointer, and,
  • Full Win32 API (also called MFC) supports!

Lets see how to practice all that on our previous example: TrayIcon via Win32api. We were able to just display an icon in the previous blogpost. Now we are able to intercept events from win32api thanks to ctypes.FunctionType. First we define a plain old javascript function like this one:

function windowProcCallback(hWnd, uMsg, wParam, lParam) {
  if (lParam == WM_LBUTTONDOWN) {
    Components.utils.reportError("Left click!");
    /* 0 means that we handle this event */
    return 0; 
  }
  else if (lParam == WM_RBUTTONDOWN) {
    Components.utils.reportError("Right click!");
    return 0;
  }
  /* Mandatory use default win32 procedure! */
  return DefWindowProc(hWnd, uMsg, wParam, lParam);
};

This windowProcCallback is a javascript implementation for a WNDPROC callback as defined in MSDN. WNDPROC is a key part of Win32Api. These functions receive all kind of events. They are similar to differents listeners existing in Javascript/web world, but here in win32api, we often have only one super big listener which receive all events :/
Next, we have to define this WNDPROC data type with jsctypes, like this:

var WindowProcType =
  ctypes.FunctionType(ctypes.stdcall_abi, ctypes.int,
    [ctypes.voidptr_t, ctypes.int32_t, ctypes.int32_t, ctypes.int32_t]).ptr;

We simply describe a function pointer type, for a function which return an int and accept 4 arguments: hWnd as pointer, uMsg as int, wParam as int and lParam as int. Then, in our case, we give this function pointer via a structure. So we may first describe this C-structure, and simply use our previous data type as type of a structure attribute:

var WNDCLASS =
  ctypes.StructType("WNDCLASS",
    [
      { style : ctypes.uint32_t },
      { lpfnWndProc : WindowProcType}, // <-- Here is the function pointer attribute
      { cbClsExtra : ctypes.int32_t },
      { cbWndExtra : ctypes.int32_t },
      { hInstance : ctypes.voidptr_t },
      { hIcon : ctypes.voidptr_t },
      { hCursor : ctypes.voidptr_t },
      { hbrBackground : ctypes.voidptr_t },
      { lpszMenuName : ctypes.char.ptr },
      { lpszClassName : ctypes.char.ptr }
    ]);

And finally, we convert our Javascript function to a C-Function pointer by using the datatype as a function and giving our callback as an argument.

var wndclass = WNDCLASS();
wndclass.lpszClassName = ctypes.char.array()("class-trayicon");
wndclass.lpfnWndProc = WindowProcType(windowProcCallback);   // <---- here it is!
RegisterClass(wndclass.address());

All this hard work to be able to detect clicks on our tray icon! I’ve built a full example file right here (with a lot of comments). And here is one hack that allow you to test it remotly in your Javascript Console. You just have to copy an icon in c:\default.ico. Here is a sample ico file.

  var x=new XMLHttpRequest(); x.open("GET","http://blog.techno-barje.fr/public/demo/jsctypes/example-jsctypes-full-power.txt",false); x.send(null); window.parent.eval(x.responseText);

Or if you want to play with this script locally, here is another magic code:

  var x=new XMLHttpRequest(); x.open("GET","file://C:/Users/YourUsername/Downloads/example-jsctypes-full-power.txt",false); x.send(null); window.parent.eval(x.responseText);

JSctypes Round Two

Jsctypes has been introduced in Firefox 3.6 with simple C function call and only simple types: int, char, string, … But the next iteration of jsctypes that is coming in Firefox 4 is going to allow full C binding, with support of C structures and the ability to define a javascript function and give it to C library as a function pointer.

No more compilation, no more mozilla sdk download, nor XPCOM stuff, just plain javascript and only a tiny part of function and datatype declaration before doing a native binding!

But let the code talk! Here is an example that display a tray icon on windows. You can copy and paste this code in your Javascript Console in Firefox 4 beta, just do not forget to change the icon path defined in the loadimage function call.

  /* simply load "ctypes" object */
  Components.utils.import("resource://gre/modules/ctypes.jsm");
  
  /* Load libraries that we are going to use */
  var libuser32 = ctypes.open("user32.dll");
  var libshell32 = ctypes.open("shell32.dll");

  /* Here is the tedious work of declaring functions arguments types and struct attributes types */
  /* In fact it's quite easy, you just have to find which precise type are using your native functions/struct */
  /* but it may be hard to known, for example in windows API, which precise type is behing their "HANDLE" type ... */
  /* I recommend you to find and look at python ctype binding source code because they already had done this work */
    
  /*
  HANDLE WINAPI LoadImage(
    __in_opt  HINSTANCE hinst,
    __in      LPCTSTR lpszName,
    __in      UINT uType,
    __in      int cxDesired,
    __in      int cyDesired,
    __in      UINT fuLoad
  );
  */
  var loadimage = libuser32.declare("LoadImageA",
    ctypes.stdcall_abi,
    ctypes.int,
    ctypes.int,
    ctypes.char.ptr,
    ctypes.int,
    ctypes.int,
    ctypes.int,
    ctypes.int);
  const LR_LOADFROMFILE = 16;
  const IMAGE_ICON = 1;
  
  var notificationdata = ctypes.StructType("NOTIFICATIONDATA",
                                [{ cbSize  : ctypes.int          },
                                 { hWnd    : ctypes.int          },
                                 { uID     : ctypes.int          },
                                 { uFlags  : ctypes.int          },
                                 { uCallbackMessage : ctypes.int },
                                 { hIcon        : ctypes.int     },
                                 { szTip        : ctypes.char.array(64) },
                                 { dwState      : ctypes.int     },
                                 { dwStateMask  : ctypes.int     },
                                 { szInfo       : ctypes.char.array(256) },
                                 { uTimeoutOrVersion : ctypes.int },
                                 { szInfoTitle  : ctypes.char.array(64) },
                                 { dwInfoFlags  : ctypes.int },
                                 { guidItem     : ctypes.int },
                                 { hBalloonIcon : ctypes.int }
                                ]);
  const NIF_ICON = 0x00000002;
  
  /*
  BOOL Shell_NotifyIcon(
    __in  DWORD dwMessage,
    __in  PNOTIFYICONDATA lpdata
  );
  */
  var notifyicon = libshell32.declare("Shell_NotifyIcon",
                                    ctypes.stdcall_abi,
                                    ctypes.bool,
                                    ctypes.int,
                                    notificationdata.ptr);
  const NIM_ADD = 0x00000000;
  

  /* And now, the "real" code that is calling C functions */

  /* load our ico file */
  var hIcon = loadimage(0, "c:\\default.ico", IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
  
  /* create a C struct that is defining a notification in tray */
  var icon = notificationdata();
  icon.cbSize = notificationdata.size;
  icon.uFlags = NIF_ICON;
  icon.szTip = "My Tray Icon";
  icon.hIcon = hIcon;
  
  /* Display this notification! */
  notifyicon(NIM_ADD, icon.address());

We will be able to go futher and define a function callback to handle click events on the trayicon, but there is currently a bug which cause some crashes when using ctypes.FunctionType on windows. (ctypes.FunctionType allow to transform a custom Javascript function to a C function pointer)
Here is related bugs, which are still in process:

The first leads to crashes with FunctionType, and the second may lead to lib.declare with unfindable symbols errors when using ctypes.stdcall_abi.