<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Techno Barje</title>
  <link href="http://techno-barje.fr/atom.xml" rel="self"/>
  <link href="http://techno-barje.fr/"/>
  <updated>2011-11-17T17:29:22+00:00</updated>
  <id>http://techno-barje.fr/</id>
  <author>
    <name>Alexandre Poirot</name>
    
  </author>

  
  <entry>
    <title>Jetpack localization using YAML format</title>
    <link href="http://techno-barje.fr/post/2011/11/17/jetpack-localization-yaml/"/>
    <updated>2011-11-17T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2011/11/17/jetpack-localization-yaml</id>
    <content type="html">&lt;p&gt;In &lt;a href=&quot;http://techno-barje.fr/post/2011/10/31/jetpack-localization/&quot;&gt;a previous post&lt;/a&gt;, I&amp;#8217;ve described my first proposal for localization support in jetpack addons. I&amp;#8217;ve decided to change locale files format for &lt;a href=&quot;http://en.wikipedia.org/wiki/YAML&quot;&gt;YAML&lt;/a&gt; instead of JSON. During MozCamp event, folks helped me identifying some pitfalls with JSON:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No multiline string support.&lt;/strong&gt; Firefox parser allows multiline but it is not officialy supported! So that it will disallow third party tools to work properly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No easy way to add comments.&lt;/strong&gt; It is mandatory for localizers to have context description in comments next to keys to translate. As there is no way to add comments in JSON, it will end up complexifying a lot locale format.&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;Example&lt;/h1&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;French locale file in YAML format&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;21&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;22&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;yaml&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# You can add comments with `#`&#8230;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;Hello %s&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;Bonjour %s&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;# almost &#8230;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;hello_key&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;l-Scalar-Plain&quot;&gt;Bonjour %s&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# wherever you want!&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# For multiline, you need to indent your string with spaces&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;multiline&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s&quot;&gt;&amp;quot;Bonjour&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;   &lt;span class=&quot;s&quot;&gt;%s&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Plural forms.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# we use a nested object with attributes that depends on the target language&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# in english, we only have &amp;#39;one&amp;#39; (for 1) and &amp;#39;other&amp;#39; (for everything but 1)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# in french, it is the same except that &amp;#39;one&amp;#39; match 0 and 1&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# in some language like Polish, there is 4 forms and 6 in arabic&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# So that having a structured format like YAML,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# help us writing these translations!&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;l-Scalar-Plain&quot;&gt;pluralString&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;%s&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;telechargement&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;l-Scalar-Plain&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p-Indicator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;%s&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;telechargements&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# I need to enclode these strings with `&amp;quot;` because of %. See note after.&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;Addon code&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Get a reference to `_` gettext method with:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;l10n&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// These three forms end up returning the same string.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// We can still use a locale string in code, or use a key.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// And multiline string gets its `\n` removed. (there is a way to keep them)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello %s&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_key&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;multiline&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Example of non-naive l10n feature, plurals:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pluralString&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;0 telechargement&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pluralString&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1 telechargement&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pluralString&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;10 telechargements&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h1&gt;Advantages of YAML&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multiline strings are supported nicely / easy to read.&lt;/strong&gt; You do not need to add a final &lt;code&gt;\&lt;/code&gt; on all lines. As mulitiline is easier, localizers can use them more often and it will surely improve readability of locale files!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Structured data format.&lt;/strong&gt; we can use this power whenever it is needed. For example, when we need to implement complex l10n features like plural forms or any feature that goes beyond simple 1-1 localization. The cool thing if we compare to JSON is that even if we define structures, we keep a really simple format with no noise (like {, }, &amp;#8220;, &amp;#8230;).&lt;/li&gt;
&lt;/ul&gt;


&lt;br/&gt; 


&lt;p&gt;As nothing comes without any issues, here is what I&amp;#8217;ve found around YAML:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This format is not a Web standard. I don&amp;#8217;t think it makes much sense to avoid using it because of that. We are clearly missing a standardized format for localization in the web world.&lt;/li&gt;
&lt;li&gt;You may hit some issues when you do not enclose your strings with &lt;code&gt;&quot;&lt;/code&gt; or &lt;code&gt;&#8217;&lt;/code&gt;. For example, you can&amp;#8217;t start a string with &lt;code&gt;%&lt;/code&gt;, nor having a &lt;code&gt;:&lt;/code&gt; in middle of your string without enclosing it.&lt;/li&gt;
&lt;li&gt;Even if YAML is not a web standard, it has been formaly specified. And unfortunately, a handy feature becomes a pitfall for our purpose! Some strings are automatically converted. &lt;code&gt;Yes&lt;/code&gt;, &lt;code&gt;True&lt;/code&gt;, &lt;code&gt;False&lt;/code&gt;, &amp;#8230; are automatically converted to a boolean value. We can work around this in multiple ways, either by documenting it, or modifying the parser. The same solution apply here, you need to enclose your string with quotes.&lt;/li&gt;
&lt;/ul&gt;


&lt;br/&gt;&lt;br/&gt;


&lt;p&gt;Again, feedback is welcomed on &lt;a href=&quot;https://groups.google.com/group/mozilla-labs-jetpack/t/da50c6dac33b445b&quot;&gt;this group thread&lt;/a&gt; and you can follow this work in &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=691782&quot;&gt;bug 691782&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Jetpack localization</title>
    <link href="http://techno-barje.fr/post/2011/10/31/jetpack-localization/"/>
    <updated>2011-10-31T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2011/10/31/jetpack-localization</id>
    <content type="html">&lt;p&gt;I&amp;#8217;m going to describe the first proposal of localization support for Jetpack.
This approach uses gettext pattern and json files for locales.
It is the first step of multiple iterations. This one only allows retrieving localized string in javascript code.
We are going to give ways to translate files, mainly HTML files, through another iteration.
And we are about to offer an online tool to ease addon localization (like babelzilla website).&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s start by looking at a concrete example, then I&amp;#8217;ll justify our different choices.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;French locale file&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello %s&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Bonjour %s&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_user&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Bonjour %s&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;Addon code&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Retrieve a dynamic reference to `_` gettext method with:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;l10n&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Then print to the console a localized string:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello %s&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// =&amp;gt; Prints &amp;quot;Bonjour alex&amp;quot; in french.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;// Or, if we don&amp;#39;t want to use localized string in addon code:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hello_user&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;alex&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Why gettext?&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;It gives a way to automatically fetch localizable strings or ids from source code
by searching for &lt;code&gt;_(  )&lt;/code&gt; pattern.&lt;/li&gt;
&lt;li&gt;It allows to use either strings or IDs as value to translate.
It is obviously better to use IDs. Because locales will broke
each time addon developer fix a typo in the main language hard coded in the code.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;But we should not forget that the high level APIs is trying to
simplify addon development. So that it has to be really easy to translate a simple
addon that has only 2 JS files and less than 50 lines of code!
And the simple fact to mandatory require a locale file for the default language
appears like a big burden for such small addon.&lt;/p&gt;

&lt;p&gt;Having said that, I&amp;#8217;m really happy that gettext approach doesn&amp;#8217;t discourage, nor
makes it harder to use IDs, and so, if an addon developer build a big addon
or just want to take more time to use better pratice, he still can do it, easily!&lt;/p&gt;

&lt;h2&gt;Why JSON for locales?&lt;/h2&gt;

&lt;p&gt;We could have used properties files, like XUL addons. But this format has some
limitations that are not compatible with gettext pattern. Keys can&amp;#8217;t contain spaces
and are limited to ASCII or something alike, so that we can&amp;#8217;t put text in a key.&lt;/p&gt;

&lt;p&gt;So instead of using yet another specific format, I&amp;#8217;m suggesting here to use JSON.
JSON is really easy to parse and generate from both client and server side,
and I&amp;#8217;m convinced that it is simple enough to be edited with a text editor.
On top of that we can build a small web application to ease localization.&lt;/p&gt;

&lt;p&gt;In my very first proposal, I used a complex JSON object with nested attributes.
But it ends up complexifying the whole story without real advantage.
So I&amp;#8217;m suggesting now to use the most simple JSON file we can require:
one big object with keys being strings or id to translate and values being translated strings.
Then we will be able to use JSON features to implement complex localization features,
like plurals handling. So that values may be an array of plurals forms.&lt;/p&gt;

&lt;h2&gt;The big picture&lt;/h2&gt;

&lt;p&gt;Everything starts with one addon developer or one of its contributor.
If one of them want to make the addon localizable, they have to use this new localization module.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;js&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;l10n&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;There is already multiple choices that has been made here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;_&lt;/code&gt; is not a &lt;em&gt;magic global&lt;/em&gt;. We need to explicitely require it.
This choice will simplify compatibility with other CommonJS environnements, like NodeJS.&lt;/li&gt;
&lt;li&gt;The name of the module itself is &lt;code&gt;l10n&lt;/code&gt; instead of &lt;code&gt;localization&lt;/code&gt; in order to ease the use of it.&lt;/li&gt;
&lt;li&gt;This module expose &lt;code&gt;_&lt;/code&gt; function on &lt;code&gt;get&lt;/code&gt; attribute in order to be able to
expose another methods. I&amp;#8217;m quite confident we will need some functions for plurals or files localization.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Then, they need to use &lt;code&gt;_&lt;/code&gt; on localizable strings:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;js&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;context-menu&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nx&quot;&gt;cm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My Menu Item&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;URLContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;*.mozilla.org&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now, they have two choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use a string written in their prefered language, like here.
So that they don&amp;#8217;t have to create a locale file.&lt;/li&gt;
&lt;li&gt;use an ID. Instead of &lt;code&gt;_(&quot;My Menu Item&quot;)&lt;/code&gt;, we will use: &lt;code&gt;_(&quot;contextMenuLabel&quot;)&lt;/code&gt;.
But it forces to create a localization file in order to map &lt;code&gt;contextMenuLabel&lt;/code&gt; to &lt;code&gt;My Menu Item&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Then, either a developer or a localizer can generate or modify locales files.
Each jetpack package can have its own &lt;code&gt;locale&lt;/code&gt; folder.
This folder contains one JSON file per supported language.
Here is how looks like a jetpack addon:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;* my-addon/
  * package.json   # manifest file with addon name, description, version, &#8230;
  * data/          # folder for all static files
    * images, 
    * html files, 
    * &#8230;
  * lib /          # folder that contains all JS modules:
    * main.js      # main module to execute on startup
    * my-module.js # custom module that may use localization module
    * &#8230;
  * locale/       # our main interest!
    * en-US.json
    * fr-FR.json
    * en-GB.json
    * &#8230;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The next iteration will add a new feature to our command line tool,
that is going to generate or update a locale file for a given language by fetching localization strings from source code.
For example, the following command will generate &lt;code&gt;my-addon/locale/fr-FR.json&lt;/code&gt; file:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sh&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cfx fetch-locales fr-FR
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;my-addon/locale/fr-FR.json&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Menu Item&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Menu Item&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Finally, we need to replace right side values with the localized strings:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;javascript&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;s2&quot;&gt;&amp;quot;My Menu Item&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Mon menu&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;And build the final addon XPI file with:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;&lt;/span&gt;&lt;/figcaption&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;sh&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;cfx xpi
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Any kind of feedback would be highly appreciated on &lt;a href=&quot;https://groups.google.com/group/mozilla-labs-jetpack/t/da50c6dac33b445b&quot;&gt;this group thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to follow this work,
subscribe to &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=691782&quot;&gt;bug 691782&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Jetpack runner</title>
    <link href="http://techno-barje.fr/post/2011/03/31/Jetpack-runner/"/>
    <updated>2011-03-31T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2011/03/31/Jetpack-runner</id>
    <content type="html">&lt;p&gt;Here is the very first release of Jetpack runner. This firefox extension built
on top of the Addon SDK is a personal project that aim to ease development of
firefox extension using the SDK. It is a great exhibit of SDK capabilities as
we can now develop such tool using the SDK itself! For now, to create an addon
you need to go thought a python application that only has a command line
interface: &lt;img src=&quot;http://techno-barje.fr/public/jetpack_runner/cfx.jpg&quot; alt=&quot;cfx.jpg&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;cfx&quot; /&gt; This is painfull to install
and even more annoying to use on Windows as there is no really decent command
line interface. Finally, if we compare to chrome extensions, we only need
chrome to build an addon! This leads me to build a Firefox extension, that can
be really easy to install in Firefox and allow to build really cool interfaces
to create, run and test your addons.&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;h2&gt;Jetpack runner features:&lt;/h2&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/jetpack_runner/jr.png&quot; alt=&quot;jr.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; title=&quot;jr.png, mar. 2011&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download and install SDK automatically&lt;/li&gt;
&lt;li&gt;Create addon from templates&lt;/li&gt;
&lt;li&gt;Run an addon&lt;/li&gt;
&lt;li&gt;Execute unit-tests&lt;/li&gt;
&lt;li&gt;Generate firefox extension XPI file or xulrunner application package&lt;/li&gt;
&lt;li&gt;You can run these either in current firefox instance or run them in a new
one&lt;/li&gt;
&lt;li&gt;We can execute a package as a firefox extension or as a xulrunner
application&lt;/li&gt;
&lt;/ul&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;h2&gt;Jetpack runner first steps:&lt;/h2&gt;


&lt;p&gt;On extension installation, a tab opens automatically on &amp;quot;jetpack:&amp;quot; url, the
main jetpack runner interface. That allow to download and install a precise SDK
release: &lt;img src=&quot;http://techno-barje.fr/public/jetpack_runner/jr-first-run.jpg&quot; alt=&quot;jr-first-run.jpg&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;jr-first-run.jpg, mar. 2011&quot; /&gt; Then it displays a list of packages provided
by addon SDK. &amp;quot;addon-sdk&amp;quot; is the main package to play with. &lt;img src=&quot;http://techno-barje.fr/public/jetpack_runner/jr-packages.jpg&quot; alt=&quot;jr-packages.jpg&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;jr-packages.jpg, mar. 2011&quot; /&gt; After
clicking on &amp;quot;Create addon&amp;quot; button, you would easily create a new one by filling
obvious form and selecting a template addon: &lt;img src=&quot;http://techno-barje.fr/public/jetpack_runner/jr-templates.jpg&quot; alt=&quot;jr-templates.jpg&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;jr-templates.jpg, mar. 2011&quot; /&gt; And
then, you end up on your newly created addon package page, where you can run
it, execute unit tests or download as a firefox extension XPI file: &lt;img src=&quot;http://techno-barje.fr/public/jetpack_runner/jr-addon.jpg&quot; alt=&quot;jr-addon.jpg&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;jr-addon.jpg, mar. 2011&quot; /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;h2&gt;Jetpack runner!!!&lt;/h2&gt;


&lt;p&gt;Last but not least, here is a link to install it or to checkout the
source.&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;&lt;b&gt;Firefox Extension:&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;http://techno-barje.fr/public/jetpack_runner/jetpack-runner-0.1.1.xpi&quot;&gt;jetpack-runner-0.1.1.xpi&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;&lt;b&gt;Source code:&lt;/b&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/ochameau/jetpack-runner&quot;&gt;Github project&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Arretetoi.la - la g&#233;olocalisation horodat&#233;!</title>
    <link href="http://techno-barje.fr/post/2011/01/08/Arretetoi.la-geolocalisation-horodate/"/>
    <updated>2011-01-08T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2011/01/08/Arretetoi.la-geolocalisation-horodate</id>
    <content type="html">&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://arretetoi.la/&quot; style=&quot;font-size: 2em;&quot;&gt;http://arretetoi.la/&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/arretetoila/icon_128.png&quot; style=&quot;float: right;&quot; /&gt; Cette
application web va vous permettre de r&amp;#233;cup&amp;#233;rer une liste de restaurants le long
d&amp;#8217;un trajet en voiture. D&amp;#8217;abord, vous indiquez votre lieu de d&amp;#233;part, d&amp;#8217;arriv&amp;#233;e
ainsi que l&amp;#8217;heure &amp;#224; laquelle vous comptez partir. Tout ceci pour obtenir une
liste de restaurants chaudement recommand&amp;#233;s par &lt;a href=&quot;http://dismoiou.fr/&quot;&gt;Dismoiou.fr&lt;/a&gt;. Jusque l&amp;#224;, rien de r&amp;#233;volutionnaire! Mais
la particularit&amp;#233; de ce service est d&amp;#8217;afficher des adresses uniquement autour
des villes que vous allez croiser autour des horaires de repas. Ainsi, si vous
faites Paris-Marseille en partant &amp;#224; 8h, le site vous proposera de d&amp;#233;jeuner pr&amp;#232;s
de lyon, car vous devrez y &amp;#234;tre autour de midi!&lt;/p&gt;

&lt;p style=&quot;font-size: 1.2em; text-align: center&quot;&gt;&lt;strong&gt;Arretetoi.la est un
service &amp;#224; la fois g&amp;#233;olocalis&amp;#233; mais surtout horodat&amp;#233;!&lt;/strong&gt;&lt;/p&gt;


&lt;p&gt;Les site marche aussi bien sur ordinateur que sur t&amp;#233;l&amp;#233;phone. La version sur
ordinateur vous permettra de pr&amp;#233;parer un parcours et d&amp;#8217;estimer o&amp;#249; vous pourriez
manger. Tandis que la version mobile vous permettra de mettre &amp;#224; jour
l&amp;#8217;estimation en fonction de votre progression. En effet, votre t&amp;#233;l&amp;#233;phone pourra
transmettre votre position exacte et mettre &amp;#224; jour la zone de
d&amp;#233;jeuner/diner.&lt;br /&gt;
Voici un aper&amp;#231;u de la version ordinateur:&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;Indication des lieux de d&amp;#233;part/arriv&amp;#233;e ainsi que
l&amp;#8217;heure de d&amp;#233;part &lt;img src=&quot;http://techno-barje.fr/public/arretetoila/desktop-1.png&quot; style=&quot;display: block; margin: auto;&quot; /&gt; Votre trajet horodat&amp;#233; &lt;img src=&quot;http://techno-barje.fr/public/arretetoila/desktop-2.png&quot; style=&quot;display: block; margin: auto;&quot; /&gt;
Lieu o&amp;#249; vous serez &amp;#224; midi ou 20h, avec les restaurants recommand&amp;#233;s &lt;img src=&quot;http://techno-barje.fr/public/arretetoila/desktop-3.png&quot; style=&quot;display: block; margin: auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;La version mobile:&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;Indication de votre lieu d&amp;#8217;arriv&amp;#233;e, le reste se
remplit automatiquement &lt;img src=&quot;http://techno-barje.fr/public/arretetoila/mobile-1.png&quot; style=&quot;display: block; margin: auto;&quot; /&gt; Liste des restaurants recommand&amp;#233;s autour de
midi ou 20h &lt;img src=&quot;http://techno-barje.fr/public/arretetoila/mobile-2.png&quot; style=&quot;display: block; margin: auto;&quot; /&gt; Affichage du restaurant s&amp;#233;lectionn&amp;#233; sur une
carte avec votre trajet &lt;img src=&quot;http://techno-barje.fr/public/arretetoila/mobile-3.png&quot; style=&quot;display: block; margin: auto;&quot; /&gt;&lt;/p&gt;


&lt;p&gt;Enfin, notez que vous pouvez ajouter cette application &amp;#224; votre &amp;#233;cran d&amp;#8217;accueil
sur iphone et android. Ainsi que sur ordinateur avec le navigateur chrome via
le &lt;a href=&quot;https://chrome.google.com/webstore/detail/dmjmddodainnogedepioklhnhdmebfhk&quot;&gt;chrome
web store&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Google maps hacks part2 - cool function to power up route, directions</title>
    <link href="http://techno-barje.fr/post/2010/11/04/Google-maps-hacks-part2-cool-function-to-power-up-route-directions/"/>
    <updated>2010-11-04T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/11/04/Google-maps-hacks-part2-cool-function-to-power-up-route-directions</id>
    <content type="html">&lt;p&gt;Another day, another library!&lt;br /&gt;
This new library brings some usefull functions and one of them is just awesome
:)&lt;br /&gt;
Start with these usefull functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;return the distance between two points,&lt;/li&gt;
&lt;li&gt;retrieve the a point at a given distance between two another,&lt;/li&gt;
&lt;li&gt;compute the square box with a given size around a point&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;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!&lt;br /&gt;
For more information, I suggest you to check at the README available on github:
&lt;a href=&quot;https://github.com/ochameau/google-map-api-path-tools&quot;&gt;https://github.com/ochameau/google-map-api-path-tools&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;As usual, source code is available under LGPL Licence.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Google maps hacks part1 - auto-suggest location in &lt;input></title>
    <link href="http://techno-barje.fr/post/2010/11/04/Google-maps-hacks-part1-auto-suggest-location-in/"/>
    <updated>2010-11-04T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/11/04/Google-maps-hacks-part1-auto-suggest-location-in</id>
    <content type="html">&lt;p&gt;As I&amp;#8217;m hacking around Google Maps API, I tried to write some libraries around
it in order to ease futher developments around this very cool API! The first
library brings auto-suggest in html inputs, so users can see a dynamic list of
cities name when they start typing in a form :)&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;Here is the source code of it, licenced under LGPL:&lt;br /&gt;
&lt;a href=&quot;https://github.com/ochameau/google-map-api-suggest&quot;&gt;https://github.com/ochameau/google-map-api-suggest&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;And what users may expect: &lt;img src=&quot;http://techno-barje.fr/public/gmaps/gmapi-suggest-sc1.png&quot; alt=&quot;gmapi-suggest-sc1.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;gmapi-suggest-sc1.png, nov. 2010&quot; /&gt; &lt;img src=&quot;http://techno-barje.fr/public/gmaps/gmapi-suggest-sc2.png&quot; alt=&quot;gmapi-suggest-sc2.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;gmapi-suggest-sc2.png, nov. 2010&quot; /&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>UIWebView secrets - part3 - How to properly call ObjectiveC from Javascript</title>
    <link href="http://techno-barje.fr/post/2010/10/06/UIWebView-secrets-part3-How-to-properly-call-ObjectiveC-from-Javascript/"/>
    <updated>2010-10-06T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/10/06/UIWebView-secrets-part3-How-to-properly-call-ObjectiveC-from-Javascript</id>
    <content type="html">&lt;p&gt;Let&amp;#8217;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, &amp;#8230; We often want
to call Javascript functions from objective C and the opposite.&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;h2&gt;Call Javascript function from Objective-C:&lt;/h2&gt;


&lt;p&gt;The first move is easily done with the following piece of code:&lt;/p&gt;

&lt;pre&gt;
  // In your Javascript files:
    function myJavascriptFunction () {
    
      // Do whatever your want!
    
    }
  
  // &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
  
  // And in your Objective-C code:
  // Call Javascript function from Objective-C:
    [webview stringByEvaluatingJavaScriptFromString:@&amp;quot;myJavascriptFunction()&amp;quot;];
&lt;/pre&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;h2&gt;Call Objective-C function from Javascript:&lt;/h2&gt;


&lt;p&gt;But calling objective-c from a Javascript function is not easy as Iphone SDK
doesn&amp;#8217;t offer any native way to do this! So we have to use any king of hack to
do this &amp;#8230;&lt;br /&gt;
The most known, used &lt;ins&gt;and buggy&lt;/ins&gt;&amp;#160;practice is to register a
&lt;em&gt;UIWebViewDelegate&lt;/em&gt; on your web view and &amp;#171; catch-and-immediatly-cancel &amp;#187;
a location change done in javascript.&lt;/p&gt;

&lt;p style=&quot;text-align:right&quot;&gt;(a &lt;a href=&quot;http://stackoverflow.com/questions/3275093/call-objective-c-method-from-javascript-with-parameter&quot;&gt;
very&lt;/a&gt; &lt;a href=&quot;http://stackoverflow.com/questions/243459/uiwebview-expose-objective-c-to-javascript&quot;&gt;
extremely&lt;/a&gt; &lt;a href=&quot;http://stackoverflow.com/questions/2767902/what-are-some-methods-to-debug-javascript-inside-of-a-uiwebview&quot;&gt;
plenty&lt;/a&gt; &lt;a href=&quot;http://tetontech.wordpress.com/2008/08/14/calling-objective-c-from-javascript-in-an-iphone-uiwebview/&quot;&gt;
much&lt;/a&gt; &lt;a href=&quot;http://www.iphonedevsdk.com/forum/iphone-sdk-development/14501-javascript-interaction-uiwebview-app.html&quot;&gt;
advised&lt;/a&gt; practice!)&lt;/p&gt;


&lt;pre&gt;
  // 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 &amp;quot;js-call:&amp;quot;
    if ([[[request URL] absoluteString] hasPrefix:@&amp;quot;js-call:&amp;quot;]) {
      
      // Extract the selector name from the URL
      NSArray *components = [requestString componentsSeparatedByString:@&amp;quot;:&amp;quot;];
      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!
   
  }

  // &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;
  
  // 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 /!&#92;n  window.location = &amp;quot;js-call:myObjectiveCFunction&amp;quot;;

&lt;/pre&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;h2&gt;What&amp;#8217;s wrong with UIWebViewDelegate, shouldStartLoadWithRequest and
location change ?&lt;/h2&gt;


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

&lt;ul&gt;
&lt;li&gt;All setInterval and setTimeout immediatly stop on location change&lt;/li&gt;
&lt;li&gt;Every innerHTML won&amp;#8217;t work after a canceled location change!&lt;/li&gt;
&lt;li&gt;You may get other really weird bugs, really hard to diagnose &amp;#8230;&lt;/li&gt;
&lt;/ul&gt;


&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://techno-barje.fr/public/iphone-sdk/NativeBridge/NativeBridge-bug.zip&quot; style=&quot;font-size:2em&quot;&gt;Sample application highlighting these bugs&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;Key files of this example:&lt;/p&gt;

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


&lt;p&gt;In webview-script.js: InnerHTML stop working whereas textContent continues to
&amp;#8230;&lt;/p&gt;

&lt;pre&gt;
  document.getElementById(&amp;quot;count&amp;quot;).innerHTML = i;
  document.getElementById(&amp;quot;count2&amp;quot;).textContent = i;
&lt;/pre&gt;


&lt;br /&gt;


&lt;p&gt;But we can&amp;#8217;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 &amp;#8230;&lt;br /&gt;
We have to find alternative way to communicate with the native code!&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;h2&gt;Better way to call Objective-C&lt;/h2&gt;


&lt;p&gt;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.&lt;br /&gt;
And voil&amp;#224;!&lt;/p&gt;

&lt;pre&gt;
  var iframe = document.createElement(&amp;quot;IFRAME&amp;quot;);
  iframe.setAttribute(&amp;quot;src&amp;quot;, &amp;quot;js-frame:myObjectiveCFunction&amp;quot;;
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;
&lt;/pre&gt;


&lt;p&gt;Here is another sample application, with exactly the same structures and test
file.&lt;br /&gt;
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.&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://techno-barje.fr/public/iphone-sdk/NativeBridge/NativeBridge-non-buggy.zip&quot; style=&quot;font-size:2em;&quot;&gt;Best practice example!&lt;/a&gt;&lt;/p&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;h2&gt;Free Objective-C&amp;lt;-&amp;gt;Javascript library&lt;/h2&gt;


&lt;p&gt;Finally I provide the communication library under LGPL licence so it can ease
your work on iphone platform! As I know that it&amp;#8217;s really not easy ;-)&lt;br /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/ochameau/NativeBridge/blob/master/MyWebView.m&quot; style=&quot;font-weight:bold;&quot;&gt;MyWebView.m&lt;/a&gt;: ObjectiveC part,&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://github.com/ochameau/NativeBridge/blob/master/NativeBridge.js&quot; style=&quot;font-weight:bold;&quot;&gt;NativeBridge.js&lt;/a&gt;: Javascript side.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The code is full of comment, so you may easily use and tweak it!&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://github.com/ochameau/NativeBridge&quot;&gt;Github repo&lt;/a&gt;&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>UIWebView secrets - part2 - leaks on release</title>
    <link href="http://techno-barje.fr/post/2010/10/04/UIWebView-secrets-part2-leaks-on-release/"/>
    <updated>2010-10-04T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/10/04/UIWebView-secrets-part2-leaks-on-release</id>
    <content type="html">&lt;p&gt;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 :(&lt;/p&gt;


&lt;br /&gt;


&lt;p&gt;I think this memory usage graph gives an idea on how big is this new king of
leak: &lt;img src=&quot;http://techno-barje.fr/public/iphone-sdk/profile-uiwebview-leak-onrelease.png&quot; alt=&quot;memory usage&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;memory usage&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a UIWebView&lt;/li&gt;
&lt;li&gt;Load http://www.google.com/&lt;/li&gt;
&lt;li&gt;Release the webview (UIWebView dealloc is correctly called!)&lt;br /&gt;
Look how so few memory is freed :/&lt;/li&gt;
&lt;/ol&gt;


&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://techno-barje.fr/public/iphone-sdk/UIWebViewLeaks2.zip&quot;&gt;Test Application&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;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!&lt;/p&gt;


&lt;p&gt;This time, I didn&amp;#8217;t manage to find any hack to solve this bug.&lt;br /&gt;
So if you have any tips to fix this, don&amp;#8217;t hesitate to post a comment!&lt;/p&gt;


&lt;p&gt;I&amp;#8217;ve tried a lot of differents hacks to free more memory (or use less), like:&lt;/p&gt;

&lt;pre&gt;
  // Setup the webview to disable some fancy effect on phone number, but doesn&#8217;t change anything on memory released &#8230;
  webview.dataDetectorTypes = UIDataDetectorTypeNone;
  webview.allowsInlineMediaPlayback = NO;
&lt;/pre&gt;


&lt;p&gt;or&lt;/p&gt;

&lt;pre&gt;
  // Remove and disable all URL Cache, but doesn&#8217;t seem to affect the memory
  [[NSURLCache sharedURLCache] removeAllCachedResponses];
  [[NSURLCache sharedURLCache] setDiskCapacity:0];
  [[NSURLCache sharedURLCache] setMemoryCapacity:0];
&lt;/pre&gt;


&lt;p&gt;or&lt;/p&gt;

&lt;pre&gt;
  // Remove all credential on release, but memory used doesn&#8217;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];
    }
  }
&lt;/pre&gt;


&lt;p&gt;or&lt;/p&gt;

&lt;pre&gt;
  // 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:@&amp;quot;document.body.innerHTML=&#8221;;&amp;quot;];
&lt;/pre&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;p&gt;But I never reach complete release of memory used by the web component :(&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>UIWebView secrets - part1 - memory leaks on xmlhttprequest</title>
    <link href="http://techno-barje.fr/post/2010/10/04/UIWebView-secrets-part1-memory-leaks-on-xmlhttprequest/"/>
    <updated>2010-10-04T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/10/04/UIWebView-secrets-part1-memory-leaks-on-xmlhttprequest</id>
    <content type="html">&lt;p&gt;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&amp;#8217;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 &amp;lt;a&amp;gt; link.&lt;/p&gt;


&lt;p&gt;But let&amp;#8217;s look at a memory usage graph while we execute this &lt;a href=&quot;http://techno-barje.fr/public/iphone-sdk/UIWebViewLeaks.zip&quot;&gt;simple test application&lt;/a&gt;: &lt;img src=&quot;http://techno-barje.fr/public/iphone-sdk/profile-xmlhttprequest-0-then-1-labeled.png&quot; alt=&quot;memory usage graph&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;memory usage graph&quot; /&gt;&lt;/p&gt;


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


&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://techno-barje.fr/public/iphone-sdk/UIWebViewLeaks.zip&quot;&gt;Test Application&lt;/a&gt;&lt;/p&gt;


&lt;br /&gt;


&lt;p&gt;So, to sum up, usually, when you execute this Javascript in a UIWebView:&lt;/p&gt;

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


&lt;p&gt;Your are going to have a big memory usage and leak a lot of data!&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


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


&lt;pre&gt;
- (void)webViewDidFinishLoad:(UIWebView *)webView {
  [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@&amp;quot;WebKitCacheModelPreferenceKey&amp;quot;];
}
&lt;/pre&gt;


&lt;p&gt;So are you going to have much less crash due to &amp;quot;Low Memory&amp;quot; :)&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>CSS animation+CSS transform+SVG powered by Firefox = Kaleidoscope</title>
    <link href="http://techno-barje.fr/post/2010/09/27/CSS-animationCSS-transformSVG-powered-by-Firefox-Kaleidoscope/"/>
    <updated>2010-09-27T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/09/27/CSS-animationCSS-transformSVG-powered-by-Firefox-Kaleidoscope</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;http://techno-barje.fr/public/kaleidoscope/kaleidoscope-tutorial.html&quot; style=&quot;font-size: 1em&quot;&gt;&lt;img src=&quot;http://techno-barje.fr/public/kaleidoscope/kaleidoscope.jpg&quot; alt=&quot;kaleidoscope result&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;kaleidoscope result&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
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
&lt;em&gt;-moz-element&lt;/em&gt; totally unleashed the power of CSS animation/transition
when it comes to doing graphical effects. And I&amp;#8217;m pretty sure that we may go
even more futher by using others standards like HTML and SVG &amp;#8230;&lt;br /&gt;
In order to show you how simple and powerfull these technologies mix can be,
I&amp;#8217;ve add two extra features on top of this kaleidoscope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first one, use a video instead of an image: Video Kaleidoscope&lt;/li&gt;
&lt;li&gt;The second one allow you to specify a custom image by select or drag&amp;#8217;n
drop: Custom image&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;I find these two features quite powerfull, and what&amp;#8217;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!&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://techno-barje.fr/public/kaleidoscope/kaleidoscope-demo.html&quot; style=&quot;font-size: 1em&quot;&gt;Kaleidoscope demo&lt;/a&gt;&lt;/p&gt;


&lt;p style=&quot;text-align: right&quot;&gt;Need &lt;a href=&quot;http://www.mozilla.com/fr/firefox/all-beta.html&quot;&gt;Firefox 4 Beta 6&lt;/a&gt; or a
nightly!&lt;br /&gt;&lt;/p&gt;


&lt;p&gt;Finally, you may look at this tutorial that explain point by point how to
achieve a Kaleidoscope by mixing &lt;em&gt;-moz-element+SVG+CSS animations and
transform&lt;/em&gt;:&lt;br /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://techno-barje.fr/public/kaleidoscope/kaleidoscope-tutorial.html&quot; style=&quot;font-size: 1em&quot;&gt;Kaleidoscope tutorial&lt;/a&gt;&lt;/p&gt;

</content>
  </entry>
  
  <entry>
    <title>jsctypes + win32api + jetpack = jetintray</title>
    <link href="http://techno-barje.fr/post/2010/08/27/jsctypes-win32api-jetpack-jetintray/"/>
    <updated>2010-08-27T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/08/27/jsctypes-win32api-jetpack-jetintray</id>
    <content type="html">&lt;p&gt;&lt;a href=&quot;https://wiki.mozilla.org/Jsctypes/api&quot;&gt;JSCtypes&lt;/a&gt;! What a powerfull
tool, that allows to call native libraries with our simple Javascript.&lt;br /&gt;
&lt;a href=&quot;https://jetpack.mozillalabs.com/&quot;&gt;Jetpack&lt;/a&gt;! What a powerfull tool,
that allows to build reliably javascript applications, with unittests, memory
profiling, web IDE, &amp;#8230;&lt;br /&gt;
And &lt;a href=&quot;http://en.wikipedia.org/wiki/Windows_API&quot;&gt;WinAPI&lt;/a&gt; &amp;#8230; a giant C
library still in production in 2010 that allows to do very various things on
Windows platform.&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;Mix all that and you get:&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://github.com/ochameau/jetintray&quot; style=&quot;font-size: 2em;&quot;&gt;JetInTray&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;A jetpack API for adding Tray icons on windows via jsctypes and on linux with a
binary xpcom component (I didn&amp;#8217;t had time to work on a jsctypes version).&lt;br /&gt;
You may checkout this jetpack package directly from &lt;a href=&quot;http://github.com/ochameau/jetintray&quot;&gt;github&lt;/a&gt;.&lt;br /&gt;
Or if you want to learn jsctypes I suggest you to look at files in &lt;em&gt;lib&lt;/em&gt;
directory and to read my two previous posts on jsctypes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I explained on the &lt;a href=&quot;http://blog.techno-barje.fr/post/2010/08/06/JSctypes-reboot&quot;&gt;first one&lt;/a&gt; how
to start playing with jsctypes, how to create C-structures and call
functions.&lt;/li&gt;
&lt;li&gt;Then I showed in the &lt;a href=&quot;http://blog.techno-barje.fr/post/2010/08/24/jsctypes-unleashed&quot;&gt;second
post&lt;/a&gt;, how to create a JS callback passed to the native library as a
function pointer.&lt;/li&gt;
&lt;/ul&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;p&gt;That said, I wanted to highlight some underground hacks around win32api! In
WinAPI, there is no addEventListener/setEventCallback/addActionListener/&amp;#8230; In
fact, there is the well known &lt;a href=&quot;http://www.toymaker.info/Games/html/wndproc.html&quot;&gt;WndProc messages
function&lt;/a&gt;, that receives absolutely all event of the application!! (Yes for
real!) We define this function as a static function named &lt;em&gt;WndProc&lt;/em&gt;. But
in Jsctypes case, that&amp;#8217;s impossible to define a static function, we can only
create function pointers. That&amp;#8217;s where comes &lt;strong&gt;the&lt;/strong&gt; not so known
hack which allow to register dynamically such event listener.&lt;br /&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First we have to define our listener function following the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms633573.aspx&quot;&gt;WinAPI datatypes&lt;/a&gt;
&lt;pre&gt;
Components.utils.import(&amp;quot;resource://gre/modules/ctypes.jsm&amp;quot;);
var libs = {};
libs.user32 = ctypes.open(&amp;quot;user32.dll&amp;quot;);

// 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(&amp;quot;DefWindowProcA&amp;quot;, 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) {
  
  // &#8230; do something smart with this event!
  
  // You HAVE TO call this api function when you don&#8217;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);
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Then we may fill a WNDCLASS structure with our fresh function pointer. This
structure is used to create a new &lt;em&gt;window class&lt;/em&gt; that use it own WndProc
(not the default static function). See &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms633586%28VS.85%29.aspx&quot;&gt;msdn doc&lt;/a&gt;
for more information.
&lt;pre&gt;
var WNDCLASS = 
  ctypes.StructType(&amp;quot;WNDCLASS&amp;quot;,
    [
      { 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()(&amp;quot;class-custom-wndproc&amp;quot;);
wndclass.lpfnWndProc = WindowProcType(windowProcCallback);   // &amp;lt;&#8212;- here it is!
RegisterClass(wndclass.address());
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;After that we may create a hidden window that is created only to catch
events.
&lt;pre&gt;
var CreateWindowEx = 
  libs.user32.declare( &amp;quot;CreateWindowExA&amp;quot;, 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()(&amp;quot;messages-only-window&amp;quot;),
    0, 0, 0, 0, 0,
    ctypes.voidptr_t(HWND_MESSAGE), null, null, null);
&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Finally, we only have to bind this window to any component which dispatch
messages/events in order to receive them in our &lt;em&gt;windowProcJSCallback&lt;/em&gt;
callback. That&amp;#8217;s it!&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>jsctypes unleashed</title>
    <link href="http://techno-barje.fr/post/2010/08/24/jsctypes-unleashed/"/>
    <updated>2010-08-24T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/08/24/jsctypes-unleashed</id>
    <content type="html">&lt;p&gt;As bugs &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=573066&quot; hreflang=&quot;en&quot;&gt;573066&lt;/a&gt; and &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=585175&quot; hreflang=&quot;en&quot;&gt;585175&lt;/a&gt;
are fixed and available in last Firefox &lt;a href=&quot;http://nightly.mozilla.org/&quot; hreflang=&quot;en&quot;&gt;nightlies&lt;/a&gt;, we can now use JSCtypes at full power!&lt;br /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: right&quot;&gt;&lt;em&gt;Thanks to &lt;a href=&quot;http://blog.mozilla.com/dwitte/&quot; hreflang=&quot;en&quot;&gt;dwitte&lt;/a&gt; for quick
fixes!&lt;/em&gt;&lt;/p&gt;


&lt;p&gt;That means :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex C-struct usage,&lt;/li&gt;
&lt;li&gt;The possibility to define a JS callback seen by C library as a function
pointer, and,&lt;/li&gt;
&lt;li&gt;Full Win32 API (also called MFC) supports!&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Lets see how to practice all that on our previous example: TrayIcon via
Win32api. We were able to &lt;em&gt;just&lt;/em&gt; display an icon in the &lt;a href=&quot;http://techno-barje.fr/post/2010/08/06/JSctypes-reboot&quot;&gt;previous blogpost&lt;/a&gt;. Now we are able to
intercept events from win32api thanks to ctypes.FunctionType. First we define a
plain old javascript function like this one:&lt;/p&gt;

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


&lt;p&gt;This &lt;em&gt;windowProcCallback&lt;/em&gt; is a javascript implementation for a WNDPROC
callback as &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx&quot; hreflang=&quot;en&quot;&gt;defined in MSDN&lt;/a&gt;. 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 :/&lt;br /&gt;
Next, we have to define this WNDPROC data type with jsctypes, like this:&lt;/p&gt;

&lt;pre&gt;
var WindowProcType =
  ctypes.FunctionType(ctypes.stdcall_abi, ctypes.int,
    [ctypes.voidptr_t, ctypes.int32_t, ctypes.int32_t, ctypes.int32_t]).ptr;
&lt;/pre&gt;


&lt;p&gt;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:&lt;/p&gt;

&lt;pre&gt;
var WNDCLASS =
  ctypes.StructType(&amp;quot;WNDCLASS&amp;quot;,
    [
      { style : ctypes.uint32_t },
      { lpfnWndProc : WindowProcType}, // &amp;lt;&#8211; 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 }
    ]);
&lt;/pre&gt;


&lt;p&gt;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.&lt;/p&gt;

&lt;pre&gt;
var wndclass = WNDCLASS();
wndclass.lpszClassName = ctypes.char.array()(&amp;quot;class-trayicon&amp;quot;);
wndclass.lpfnWndProc = WindowProcType(windowProcCallback);   // &amp;lt;&#8212;- here it is!
RegisterClass(wndclass.address());
&lt;/pre&gt;


&lt;p&gt;All this hard work to be able to detect clicks on our tray icon! I&amp;#8217;ve built a
full example file &lt;a href=&quot;http://techno-barje.fr/public/demo/jsctypes/example-jsctypes-full-power.txt&quot;&gt;right here&lt;/a&gt; (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 &lt;a href=&quot;http://techno-barje.fr/public/demo/jsctypes/default.ico&quot;&gt;ico file&lt;/a&gt;.&lt;/p&gt;

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


&lt;p&gt;Or if you want to play with this script locally, here is another magic code:&lt;/p&gt;

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

</content>
  </entry>
  
  <entry>
    <title>JSctypes round two</title>
    <link href="http://techno-barje.fr/post/2010/08/06/JSctypes-reboot/"/>
    <updated>2010-08-06T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/08/06/JSctypes-reboot</id>
    <content type="html">&lt;p&gt;Jsctypes has been introduced in Firefox 3.6 with simple C function call and
only simple types: int, char, string, &amp;#8230; 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.&lt;/p&gt;


&lt;p&gt;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!&lt;/p&gt;


&lt;p&gt;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.&lt;/p&gt;


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

  /* Here is the tedious work of declaring functions arguments types and struct attributes types */
  /* In fact it&#8217;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 &amp;quot;HANDLE&amp;quot; type &#8230; */
  /* 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(&amp;quot;LoadImageA&amp;quot;,
    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(&amp;quot;NOTIFICATIONDATA&amp;quot;,
                                [{ 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(&amp;quot;Shell_NotifyIcon&amp;quot;,
                                    ctypes.stdcall_abi,
                                    ctypes.bool,
                                    ctypes.int,
                                    notificationdata.ptr);
  const NIM_ADD = 0x00000000;
  

  /* And now, the &amp;quot;real&amp;quot; code that is calling C functions */

  /* load our ico file */
  var hIcon = loadimage(0, &amp;quot;c:&#92;default.ico&amp;quot;, 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 = &amp;quot;My Tray Icon&amp;quot;;
  icon.hIcon = hIcon;
  
  /* Display this notification! */
  notifyicon(NIM_ADD, icon.address());

&lt;/pre&gt;


&lt;p&gt;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)&lt;br /&gt;
Here is related bugs, which are still in process:&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=573066&quot; hreflang=&quot;en&quot;&gt;Bug 573066 - Fix ctypes stdcall closure tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=585175&quot; hreflang=&quot;en&quot;&gt;Bug 585175 - Don&amp;#8217;t automangle ctypes stdcall symbols for WINAPI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The first leads to crashes with FunctionType, and the second may lead to
lib.declare with unfindable symbols errors when using ctypes.stdcall_abi.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Freemonkeys</title>
    <link href="http://techno-barje.fr/post/2010/02/12/Freemonkeys/"/>
    <updated>2010-02-12T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2010/02/12/Freemonkeys</id>
    <content type="html">&lt;p style=&quot;text-align:center&quot;&gt;&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/46873&quot; style=&quot;font-size: 2em;&quot;&gt;Freemonkeys&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;Yet another mozilla powered project! This time, a graphical unit tests
editor/executer which enables you to spellcast an army of monkeys always happy
to work hard on your projects and find bugs for free! &lt;img src=&quot;http://techno-barje.fr/public/demo/fm/asserts.png&quot; alt=&quot;asserts.png&quot; style=&quot;margin: 0 auto; display: block; border: 2px solid black; max-width: 300px; max-height: 300px&quot; title=&quot;asserts.png, f&amp;#233;v. 2010&quot; /&gt;&lt;br /&gt;
&lt;strong&gt;Here is what they can do:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launch any Mozilla application: Firefox, Thunderbird and any xulrunner
app,&lt;/li&gt;
&lt;li&gt;Use an empty profile for each test execution, or an existing one,&lt;/li&gt;
&lt;li&gt;Speak fluently &amp;quot;assert&amp;quot; language: isTrue, isFalse, isDefined, equals, &amp;#8230;
etc,&lt;/li&gt;
&lt;li&gt;Report you in real time test execution directly in your test source
code,&lt;/li&gt;
&lt;li&gt;They are always ready to work. You don&amp;#8217;t need to restart Freemonkeys on
each test execution, nor on your application reboot. Freemonkeys is an
independant xulrunner app, which launch yours and then controls it remotly with
a network connexion,&lt;/li&gt;
&lt;li&gt;Spot easily any window, any tab and any DOM element with usefull
distinctive parameters: XPath, windows attributes, zIndex order, &amp;#8230; etc,&lt;/li&gt;
&lt;li&gt;Offer a way to facilitate node identification by simply clicking on it, and
seeing in real time what are selected node parameters,&lt;/li&gt;
&lt;li&gt;They are able to write down some debug messages, inspect javascript objects
with DOM Inspector, take screenshots of any elements,&lt;/li&gt;
&lt;li&gt;Ease you some kind of tests, by providing you a simple HTTP webserver in
order to simulate some websites answers,&lt;/li&gt;
&lt;li&gt;They are not narrow-minded to synchronous tests but offers an assert
library and some usefull API embracing asynchronous execution of your
code!&lt;/li&gt;
&lt;/ul&gt;


&lt;br /&gt;


&lt;p&gt;Now let&amp;#8217;s highlight some of these cool features &amp;#8230;&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;h2&gt;Node selection&lt;/h2&gt;


&lt;p&gt;Here I was overing the tip of the day image. Freemonkeys spot it by
highlighting it in red and show me all parameters which are going to be used to
find this node later:&lt;br /&gt;
&lt;img src=&quot;http://techno-barje.fr/public/demo/fm/inspector.png&quot; alt=&quot;inspector.png&quot; title=&quot;inspector.png, f&amp;#233;v. 2010&quot; /&gt; You just have to click on it to get back to test
editor and have all javascript code needed to get a reference to this node,
something like this:&lt;/p&gt;

&lt;pre&gt;
var top = windows.getRegistered(&amp;quot;firefox-window&amp;quot;, &amp;quot;topmost&amp;quot;);
var tab = top.tabs.current;
var element = elements.xpath(tab, &amp;quot;id(&#8216;frame&#8217;)/tbody[1]/tr[5]/td[1]/table[1]/tbody[1]/tr[1]/td[1]/table[1]/tbody[1]/tr[1]/td[1]/img[1]&amp;quot;);
&lt;/pre&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;h2&gt;Elements screenshots&lt;/h2&gt;


&lt;br /&gt;


&lt;p&gt;Simply write:&lt;/p&gt;

&lt;pre&gt;
element.screenshot();
&lt;/pre&gt;


&lt;p&gt;And get a screenshot directly in the test editor:&lt;br /&gt;
&lt;img src=&quot;http://techno-barje.fr/public/demo/fm/element.screenshot.png&quot; alt=&quot;element.screenshot.png&quot; title=&quot;element.screenshot.png, f&amp;#233;v. 2010&quot; /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;h2&gt;Live test execution reporting&lt;/h2&gt;


&lt;br /&gt;


&lt;p&gt;Your monkeys report each assert status in the test editor, allowing you to keep
the focus on test writing and not losing time by switching from your app to
your terminal, then to your code editor, your terminal and your app &amp;#8230; etc,
etc. &lt;img src=&quot;http://techno-barje.fr/public/demo/fm/asserts.png&quot; alt=&quot;asserts.png&quot; style=&quot;margin: 0 auto; display: block; border: 2px solid black; margin: 5px;&quot; title=&quot;asserts.png, f&amp;#233;v. 2010&quot; /&gt; &lt;img src=&quot;http://techno-barje.fr/public/demo/fm/debug-msg.png&quot; alt=&quot;debug-msg.png&quot; title=&quot;debug-msg.png, f&amp;#233;v. 2010&quot; /&gt;&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;h2&gt;HTTP API&lt;/h2&gt;


&lt;br /&gt;


&lt;pre&gt;
// Get a reference to a firefox tab
var top = windows.getRegistered(&amp;quot;firefox-window&amp;quot;, &amp;quot;topmost&amp;quot;);
var tab = top.tabs.current;

// Start an HTTP server on port 81
http.start(&amp;quot;81&amp;quot;);

// A successfull test
// Create an assert objet which is going to wait for a request on root path of our http server
var test = http.assertGetRequest(&amp;quot;/&amp;quot;);
// Open this page in the tab
tab.open(&amp;quot;http://localhost:81/&amp;quot;);
// Now wait for this request
test.wait();

// The same test but with a non-existant page on our local server, so a failing test!
var test = http.assertGetRequest(&amp;quot;/&amp;quot;);
tab.open(&amp;quot;http://localhost:81/foo&amp;quot;);
test.wait();
&lt;/pre&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;h2&gt;Asynchronous tests&lt;/h2&gt;


&lt;br /&gt;


&lt;pre&gt;
// A usefull function which allow you to block test execution for an amount of time in ms
wait.during(1000);

// The simpliest asynchronous test
wait.forTrue(function () {
  return true;
});

// Another, which is going to pass after 3s, with this setTimeout
var v=true;
wait.setTimeout(function() {
  v=false;
},3000);
wait.forFalse(function () {
  return v;
});

// Finally, a test which will pass when the test function is going to be called ten times
// (wait for the anonymous function returns 10)
var i=0;
wait.forEquals(function () {
  return i++;;
}, 10);
&lt;/pre&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;h1&gt;How to get it ?&lt;/h1&gt;


&lt;p&gt;Source code is available on github: &lt;a href=&quot;http://github.com/ochameau/freemonkeys&quot;&gt;http://github.com/ochameau/freemonkeys&lt;/a&gt;
(LGPL licence)&lt;br /&gt;
If you are on windows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download this package: &lt;a href=&quot;http://github.com/downloads/ochameau/freemonkeys/freemonkeys-0.1-win.zip&quot;&gt;freemonkeys-0.1-win.zip&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Extract this zip file somewhere&lt;/li&gt;
&lt;li&gt;Launch freemonkeys.exe&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;And for linux and mac:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download this one: &lt;a href=&quot;http://github.com/downloads/ochameau/freemonkeys/freemonkeys-0.1.zip&quot;&gt;freemonkeys-0.1.zip&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Extract it somewhere&lt;/li&gt;
&lt;li&gt;If you don&amp;#8217;t have xulrunner, download it from &lt;a href=&quot;http://releases.mozilla.org/pub/mozilla.org/xulrunner/releases/1.9.2rc1/runtimes/&quot;&gt;
here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Finally, launch Freemonkeys with this command:
&lt;pre&gt;
/path/to/your/xulrunner/dir/xulrunner /path/to/freemonkeys/application.ini
&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Session per tab in Firefox</title>
    <link href="http://techno-barje.fr/post/2009/12/05/Session-per-tab-in-Firefox/"/>
    <updated>2009-12-05T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2009/12/05/Session-per-tab-in-Firefox</id>
    <content type="html">&lt;p&gt;The brand new version of Yoono, &lt;a href=&quot;http://www.yoono.com&quot;&gt;Yoono7&lt;/a&gt;
brings a &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=117222&quot;&gt;long-awaited&lt;/a&gt; Firefox
feature: the possibility to sign-in on the same website with multiple accounts
in different tabs or windows.&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;Althought this new feature is a big technical challenge, for the end user, it&amp;#8217;s
really simple and non-intrusive! This feature only add one simple &amp;quot;profile&amp;quot;
selector on the left of the URL bar : &lt;img src=&quot;http://techno-barje.fr/public/accounts/urlbar-global.png&quot; alt=&quot;urlbar-global.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;urlbar-global.png, d&amp;#233;c. 2009&quot; /&gt; This
is the default status of the selector, it simply says that the current firefox
behavior is &amp;quot;as before&amp;quot;, using the same global session for all tabs.&lt;br /&gt;
Let&amp;#8217;s look it when we enable session per tab on different profiles : &lt;img src=&quot;http://techno-barje.fr/public/accounts/urlbar-gmail.png&quot; alt=&quot;urlbar-gmail.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;urlbar-gmail.png, d&amp;#233;c. 2009&quot; /&gt;
&lt;img src=&quot;http://techno-barje.fr/public/accounts/urlbar-facebook.png&quot; alt=&quot;urlbar-facebook.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;urlbar-facebook.png, d&amp;#233;c. 2009&quot; /&gt; &lt;img src=&quot;http://techno-barje.fr/public/accounts/urlbar-witter.png&quot; alt=&quot;urlbar-witter.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;urlbar-witter.png, d&amp;#233;c. 2009&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When you start the browser, open a bookmark, do a search or enter manually
an URL, your request is loaded with the default global session (ie &amp;quot;as
before&amp;quot;). But when you select a profile with this selector, the current tab is
reloaded in order to use one specific totally independant session. Futhermore,
if this website open a new tab or window, or if you click on a link, the new
tab, window or webpage is going to use the same specific session.&lt;/p&gt;


&lt;br /&gt;


&lt;p&gt;But let&amp;#8217;s see how to use this feature from the beginning.&lt;/p&gt;

&lt;ol&gt;
&lt;li style=&quot;clear:both&quot;&gt;&lt;img src=&quot;http://techno-barje.fr/public/accounts/perso-add.png&quot; alt=&quot;perso-add.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; title=&quot;perso-add.png, d&amp;#233;c. 2009&quot; /&gt; &lt;img src=&quot;http://techno-barje.fr/public/accounts/default-menu.png&quot; alt=&quot;default-menu.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; title=&quot;default-menu.png, d&amp;#233;c. 2009&quot; /&gt; First, we create one session linked to a
personnal account. In this example I take gmail, but it can be any website :
twitter, facebook, flickr, &amp;#8230; whatever! To do so we click on the profile
selector and get menu on the left and we click on &amp;quot;+ new profiles&amp;quot; and get the
right&amp;#8217;s one.&lt;/li&gt;
&lt;li style=&quot;clear:both&quot;&gt;We are redirected to the homepage URL, where we must
sign-in for this personnal account: poirot.alex. &lt;img src=&quot;http://techno-barje.fr/public/accounts/perso-signin.png&quot; alt=&quot;perso-signin.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;perso-signin.png, d&amp;#233;c. 2009&quot; /&gt;&lt;br /&gt;
And we are now signed in for this &amp;quot;Personnal gmail&amp;quot; session : &lt;img src=&quot;http://techno-barje.fr/public/accounts/private-signed.png&quot; alt=&quot;private-signed.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;private-signed.png, d&amp;#233;c. 2009&quot; /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li style=&quot;clear:both&quot;&gt;&lt;img src=&quot;http://techno-barje.fr/public/accounts/add-pro.png&quot; alt=&quot;add-pro.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; title=&quot;add-pro.png, d&amp;#233;c. 2009&quot; /&gt; Then, we do the same for one professional account:
yoono.test.&lt;br /&gt;
&lt;img src=&quot;http://techno-barje.fr/public/accounts/header-pro-signin.png&quot; alt=&quot;header-pro-signin.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;header-pro-signin.png, d&amp;#233;c. 2009&quot; /&gt;&lt;br /&gt;
&lt;img src=&quot;http://techno-barje.fr/public/accounts/header-pro-signed.png&quot; alt=&quot;header-pro-signed.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;header-pro-signed.png, d&amp;#233;c. 2009&quot; /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li style=&quot;clear:both&quot;&gt;&lt;img src=&quot;http://techno-barje.fr/public/accounts/home-private.png&quot; alt=&quot;home-private.png&quot; style=&quot;float: right; margin: 0 0 1em 1em;&quot; title=&quot;home-private.png, d&amp;#233;c. 2009&quot; /&gt; Later, we can reopen one of these sessions
directly to the homepage with the profile selector and get automatically signed
in. The &amp;quot;switch to&amp;quot; link doesn&amp;#8217;t go to the homepage and only reload the current
tab with the selected session (very usefull for Facebook connect, sharing,
&amp;#8230;). &lt;img src=&quot;http://techno-barje.fr/public/accounts/private-signed.png&quot; alt=&quot;private-signed.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;private-signed.png, d&amp;#233;c. 2009&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;br /&gt;


&lt;p style=&quot;text-align: center;font-weight: bold; font-size: 1.2em&quot;&gt;So we can
open as many different account in multiple tabs or windows!&lt;/p&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;h2&gt;Important note:&lt;/h2&gt;


&lt;p&gt;The current version of Yoono7 doesn&amp;#8217;t allow custom profile creation. The only
profiles you can use is the ones automatically created for each account
registered in the yoono&amp;#8217;s sidebar. But watch for the next minor releases of
Yoono7, we are going to ship all this very soon!&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;h2&gt;Another demo of this feature in video:&lt;/h2&gt;


&lt;div class=&quot;external-media&quot; style=&quot;margin: 1em auto; text-align: center;&quot;&gt;
&lt;object type=&quot;application/x-shockwave-flash&quot; data=&quot;http://www.youtube.com/v/V51S6BxTPiw&amp;amp;hl=en_US&amp;amp;fs=1&quot; width=&quot;480&quot; height=&quot;385&quot;&gt;&lt;param name=&quot;movie&quot; value=&quot;http://www.youtube.com/v/V51S6BxTPiw&amp;amp;hl=en_US&amp;amp;fs=1&quot; /&gt;
&lt;param name=&quot;wmode&quot; value=&quot;transparent&quot; /&gt;&lt;/object&gt;&lt;/div&gt;

</content>
  </entry>
  
  <entry>
    <title>Mozilla memory profiling, part 2: a working tool</title>
    <link href="http://techno-barje.fr/post/2009/11/26/Mozilla-memory-profiling-part-2/"/>
    <updated>2009-11-26T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2009/11/26/Mozilla-memory-profiling-part-2</id>
    <content type="html">&lt;p&gt;Here is another part of my work on memory analysis in Mozilla :&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://techno-barje.fr/public/another-profiler/another-profiler_techno-barje.fr.xpi&quot; style=&quot;font-size: 2em;&quot;&gt;another-profiler_techno-barje.fr.xpi&lt;/a&gt;&lt;/p&gt;


&lt;br /&gt;


&lt;p&gt;This new version of &amp;quot;Another memory profiler&amp;quot; is now an effective tool, which
display a lot of information about all objects living in your Firefox instance!
By &lt;em&gt;all&lt;/em&gt; I mean not only website javascript objects, but all objects
used by Firefox in its windows, sidebars, extensions, all tabs, iframes, etc.
The previous version allowed you only to select one component : a DOM
window(website, sub-iframe or any XUL window), a XPCOM service or a JS Module
:&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/another-profiler/another-components-list.png&quot; alt=&quot;another-components-list.png&quot; style=&quot;margin: 0 auto; display: block; border: 1px solid black&quot; title=&quot;another-components-list.png, nov. 2009&quot; /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-weight: bold&quot;&gt;Component selection&lt;/div&gt;


&lt;br /&gt;


&lt;p&gt;Now you can get a report about currently living objects : the ones that are
still used because there is at least one reference to each of them. This report
first display all javascript files involved in your component :&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/another-profiler/another-lines-browser.png&quot; alt=&quot;another-lines-browser.png&quot; style=&quot;margin: 0 auto; display: block; border: 1px solid black&quot; title=&quot;another-lines-browser.png, nov. 2009&quot; /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-weight: bold&quot;&gt;File selection&lt;/div&gt;


&lt;br /&gt;


&lt;p&gt;By selecting one file, you are seeing the number of living object sorted by
there instantiation line :&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/another-profiler/another-objects-browser.png&quot; alt=&quot;another-objects-browser.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;another-objects-browser.png, nov. 2009&quot; /&gt;&lt;/p&gt;

&lt;div style=&quot;text-align: center; font-weight: bold&quot;&gt;Living objects
information&lt;/div&gt;


&lt;br /&gt;


&lt;p&gt;Finally, this tool display objects counts for each line sorted by there type.
But Javascript is not a strongly typed language, so it&amp;#8217;s not really easy to
sort its objects by a type! That&amp;#8217;s why there are several way to describe a JS
object :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define a JS object by its attributes, like Atul Varma is doing in &lt;a href=&quot;http://www.toolness.com/wp/?p=709&quot;&gt;its current work&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;By its JS Prototype name, very usefull &amp;quot;typing&amp;quot; when you are using
Prototype and build Object-Oriented JS,&lt;/li&gt;
&lt;li&gt;We are facing some specialized objects like all DOM objects :
HTMLFormElement, HTMLDivElement, &amp;#8230;&lt;/li&gt;
&lt;li&gt;And finally all native types, like Array, String, Date, RegExp, &amp;#8230;
etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;p&gt;Finally, let&amp;#8217;s see how to make this extension work :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;First&lt;/strong&gt; It contains a binary component which is only built
for Firefox 3.5 and 3.6 for Windows and Linux-32.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secondly&lt;/strong&gt; The memory profiling component is a patched
version of the Mozilla Jetpack&amp;#8217;s one, so take care to disable Jetpack, before
testing this!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Then&lt;/strong&gt; In order to get the maximum information about your
living JS object, I strongly encourage you to set these two prefs to false :
&lt;pre&gt;
javascript.options.jit.content = false
javascript.options.jit.chrome = false
&lt;/pre&gt;
(That&amp;#8217;s because Tracemonkey optimise loops and seems to embed empty stack frame
information on these loop&amp;#8217;s execution &amp;#8230;)&lt;/li&gt;
&lt;li&gt;That being said, you just have to install this extension &lt;a href=&quot;http://techno-barje.fr/public/another-profiler/another-profiler_techno-barje.fr.xpi&quot;&gt;another-profiler_techno-barje.fr.xpi&lt;/a&gt;,
go to your Tools menu and click on &amp;quot;Open another memory profiler&amp;quot;.&lt;/li&gt;
&lt;/ul&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;p&gt;&lt;strong&gt;Come back for the next post for some more explanation on displayed
results with simple scripts examples.&lt;/strong&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Firefox Everywhere</title>
    <link href="http://techno-barje.fr/post/2009/11/23/Firefox-Everywhere/"/>
    <updated>2009-11-23T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2009/11/23/Firefox-Everywhere</id>
    <content type="html">&lt;p&gt;After &lt;a href=&quot;http://techno-barje.fr/post/2009/11/06/Yoono-Desktop-Portable&quot;&gt;Yoono Desktop
Portable&lt;/a&gt;, here is Firefox Everywhere : a customized Firefox package which
can be executed on any OS : Windows, Linux, MacOS and with a shared profile
directory allowing you to travel with all your Firefox data on a usb stick!&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;Check out this surf session starting on Windows,
&lt;img src=&quot;http://techno-barje.fr/public/firefox-portable/firefox-portable-win.png&quot; alt=&quot;firefox-portable-win.png&quot; style=&quot;margin: 0 auto; display: block; border: 1px solid black;&quot; title=&quot;firefox-portable-win.png, nov. 2009&quot; /&gt; Then on Linux, &lt;img src=&quot;http://techno-barje.fr/public/firefox-portable/firefox-portable-linux.png&quot; alt=&quot;firefox-portable-linux.png&quot; style=&quot;margin: 0 auto; display: block; border: 1px solid black;&quot; title=&quot;firefox-portable-linux.png, nov. 2009&quot; /&gt; And finally on a Mac! &lt;img src=&quot;http://techno-barje.fr/public/firefox-portable/firefox-portable-mac.png&quot; alt=&quot;firefox-portable-mac.png&quot; style=&quot;margin: 0 auto; display: block; border: 1px solid black&quot; title=&quot;firefox-portable-mac.png, nov. 2009&quot; /&gt;&lt;/p&gt;


&lt;p style=&quot;text-align: center;font-size: 1.2em;&quot;&gt;FirefoxEverywhere&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Download:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;http://bit.ly/firefox-portable-all&quot;&gt;Full edition&lt;/a&gt; (69MB)
which works with all OS&lt;/li&gt;
&lt;li&gt;or the &lt;a href=&quot;http://bit.ly/firefox-portable-win&quot;&gt;Windows only
version&lt;/a&gt; (13MB)&lt;/li&gt;
&lt;li&gt;or the &lt;a href=&quot;http://bit.ly/firefox-portable-mac&quot;&gt;MacOs only version&lt;/a&gt;
(26MB)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;strong&gt;Tips:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;ins&gt;Don&amp;#8217;t forget to properly disconnect your usb stick, or your profile
may explode!&lt;/ins&gt;&lt;/li&gt;
&lt;li&gt;This version is based on Firefox 3.6 branch in order to gain startup
performance improvements of this incoming version! So don&amp;#8217;t be afraid to have a
browser named Namoroka instead of Firefox.&lt;/li&gt;
&lt;li&gt;On Windows, execute: launch-windows.exe&lt;/li&gt;
&lt;li&gt;On MacOS, launch-macos.command&lt;/li&gt;
&lt;li&gt;On Linux, either launch-linux-64.sh or launch-linux.sh(for 32bits)&lt;/li&gt;
&lt;/ul&gt;

</content>
  </entry>
  
  <entry>
    <title>Mozilla memory profiling</title>
    <link href="http://techno-barje.fr/post/2009/11/16/Mozilla-memory-profiling/"/>
    <updated>2009-11-16T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2009/11/16/Mozilla-memory-profiling</id>
    <content type="html">&lt;p&gt;As a Mozilla hacker, extension developer and Javascript expert, I&amp;#8217;ve been
really exited to see the &lt;a href=&quot;http://www.toolness.com/wp/?p=709&quot;&gt;current
work of Atul Varma&lt;/a&gt; on memory profiling in Firefox! It&amp;#8217;s naturally the next
step of tool to build after &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/9954&quot;&gt;XUL Profiler&lt;/a&gt;, which
track CPU consumption and Javascript functions calls.&lt;br /&gt;
So, instead of waiting for web developers to describe their future new &amp;quot;memory&amp;quot;
firebug tab :), I&amp;#8217;ve searched what information we can retrieve from JS API. And
I&amp;#8217;ve not limited my scope to web content but I take all Browser objects into
account.&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;First I&amp;#8217;ve tried to find a meaningful parent for &lt;strong&gt;every&lt;/strong&gt; living
object.&lt;br /&gt;
In the Mozilla planet we may face with three main types of parents :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;window : chrome (browser.xul, popups, jsconsole, sidebars, &amp;#8230;) or content
(websites,popups,iframes)&lt;/li&gt;
&lt;li&gt;xpcom services&lt;/li&gt;
&lt;li&gt;JS modules&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;(But there is also XBL, sandboxes and some others strange things like
&amp;quot;Block&amp;quot;)&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;Here is the first result of this work :&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://techno-barje.fr/public/another-profiler_techno-barje.fr-1.0.xpi&quot; style=&quot;font-size: 2em;&quot;&gt;another-profiler_techno-barje.fr-1.0.xpi&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;This extension need &lt;a href=&quot;https://addons.mozilla.org/fr/firefox/addon/12025&quot;&gt;Jetpack 0.6+&lt;/a&gt;.&lt;/strong&gt;
It adds a &amp;quot;Open another memory profiler&amp;quot; item in Tools menu and display all
living windows, xpcoms and modules. Then when you select one of them, it
displays the simplest profiling ever: number of js objects group by C++ native
class. I&amp;#8217;ll show you in the next blog post how to display a better
profiling!&lt;br /&gt;
&lt;img src=&quot;http://techno-barje.fr/public/another-profiler-1.0.png&quot; alt=&quot;another-profiler-1.0.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;another-profiler-1.0.png, nov. 2009&quot; /&gt; But for now, I&amp;#8217;m going to show you all
the code needed to make this first version.&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;p&gt;For the living windows, there is a lot of cases, but it&amp;#8217;s simple :&lt;/p&gt;

&lt;pre&gt;
// Get the list of absolutery ALL windows living in a Firefox session, stored as a Tree
function getAllWindows() {
  var windows = [];
  
  // Begin by iterating over all top chrome windows (browser, jsconsole, dominspector, etc.)
  var wm = Components.classes[&amp;quot;@mozilla.org/appshell/window-mediator;1&amp;quot;]
          .getService(Components.interfaces.nsIWindowMediator);
  var enumerator = wm.getXULWindowEnumerator(null);
  while(enumerator.hasMoreElements()) {
    var win = enumerator.getNext();
    if (win instanceof Components.interfaces.nsIXULWindow) {
      // Search for all children windows (sidebar, content, iframes, &#8230;)
      parseDocshell(win.docShell);
   }
  }

  function getWindowByDocShell(docShell) {
    if (!(docShell instanceof Components.interfaces.nsIInterfaceRequestor))
      return;
    return docShell.getInterface(Components.interfaces.nsIDOMWindow);
  }
  function parseDocshell(docShell) {
    if (!docShell) return;
    var domWindow = getWindowByDocShell(docShell);
    
    var topWindow = {
          type  : &amp;quot;window&amp;quot;,
          name  : domWindow.document.title,
          href  : domWindow.location.href,
          object: domWindow,
          children: []
        };
    windows.push(topWindow);
    
    var topWindows = [topWindow];
    
    var treeItemType = Components.interfaces.nsIDocShellTreeItem.typeAll;
    // From inspector@mozilla.org inspector.js appendContainedDocuments
    // Load all the window&#8217;s content docShells
    var containedDocShells = docShell.getDocShellEnumerator(treeItemType,
                                      Components.interfaces.nsIDocShell.ENUMERATE_FORWARDS);
    while (containedDocShells.hasMoreElements())
    {
      var childShell = containedDocShells.getNext().QueryInterface(Components.interfaces.nsIDocShell);
      
      if (childShell == docShell) {
        // It&#8217;s the current topWindow
        continue;
      }
      
      var childDOMWindow = getWindowByDocShell(childShell);
      if (!childDOMWindow) continue;
      var parent;
      for(var i=0; i&amp;lt;topWindows.length; i++) {
        if (topWindows[i].object == childDOMWindow.parent) {
          parent = topWindows[i];
          break;
        }
      }
      var newWindow = {
        type  : &amp;quot;window&amp;quot;,
        name  : childDOMWindow.document.title,
        href  : childDOMWindow.location.href,
        object: childDOMWindow,
        children : []
      };
      topWindows.push(newWindow);
      if (parent)
        parent.children.push(newWindow);
      else
        topWindow.children.push(newWindow);
    }
    delete topWindows;
  }
  
  // Finally, don&#8217;t forget *the* hidden window, it&#8217;s a big one used by many extensions!
  var hiddenWindow = Components.classes[&amp;quot;@mozilla.org/appshell/appShellService;1&amp;quot;]
         .getService(Components.interfaces.nsIAppShellService)
         .hiddenWindow;
  if (hiddenWindow instanceof Components.interfaces.nsIXULWindow) {
    parseDocshell(hiddenWindow.docShell);
  }
  
  return windows;
}
&lt;/pre&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;p&gt;For XPCOM services, it&amp;#8217;s shorter, but it&amp;#8217; an unknown practice :&lt;/p&gt;

&lt;pre&gt;
// Get the list of all XPCOM services (not the xpcom objects, only services) in a Firefox session
function getAllXPCOMServices() {
  var instanciatedServices = [];
  var serviceManager=Components.manager.QueryInterface(Components.interfaces.nsIServiceManager);
  var supports = Components.interfaces.nsISupports;
  for(var cl in Components.classes) {
    try {
      if (serviceManager.isServiceInstantiated(Components.classes[cl],supports)) {
        var service=Components.classes[cl].getService(supports);
        if (service.wrappedJSObject) {
          // Get the global object
          service=service.wrappedJSObject.__parent__;
          if (!service)
            service=Components.classes[cl].getService(supports).__parent__;
          instanciatedServices.push({
            type   : &amp;quot;xpcom&amp;quot;,
            name   : cl,
            object : service
          });
        }
      }
    } catch(e) {
      // serviceManager.isServiceInstantiated is throwing if there is no instance &#8230;
    }
  }
  return instanciatedServices;
}
&lt;/pre&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;p&gt;But for JS Modules, I&amp;#8217;ve not found any way to get those &amp;#8230;&lt;br /&gt;
The only solution I&amp;#8217;ve got was to do a quick profiling and identify them :&lt;/p&gt;

&lt;pre&gt;
function searchJSModules () {
  var jsmodules = [];
  
  var roots=getGCRoots();
  for(var r in roots) {
    var id = roots[r];
    var info = getObjectInfo(id);
    var properties = getObjectProperties(id);
    /*
    // We can also identify XPCOM by reading global NSGetModule function
    var nsgetmodule = getObjectProperty(id,&amp;quot;NSGetModule&amp;quot;).NSGetModule;
    if (nsgetmodule) {
      print (&amp;quot; &#8211;&amp;gt; is an XPCOM&amp;quot;);
      print (&amp;quot; &#8211;&amp;gt; defined in : &amp;quot;+getObjectInfo(nsgetmodule).filename);
      continue;
    }
    */
    // See if the current object has a EXPORTED_SYMBOLS object
    // We suppose every JS Module has one &#8230;
    var exportedsymbols = getObjectProperty(id,&amp;quot;EXPORTED_SYMBOLS&amp;quot;).EXPORTED_SYMBOLS;
    if (!exportedsymbols) continue;
    
    // Then search for the first declared function
    // Which will allow us to get the file of this module!
    
    // Begin to search in EXPORTED_SYMBOLS
    var symbols = getObjectProperties(exportedsymbols);
    var filename;
    for(var i in symbols) {
      var s = getObjectProperty(id,symbols[i])[symbols[i]];
      var inf = getObjectInfo(s);
      if (!inf) continue;
      if (inf.nativeClass==&amp;quot;Function&amp;quot; &amp;amp;&amp;amp; inf.filename) {
        filename=inf.filename;
        break;
      } else if (inf.nativeClass=&amp;quot;Object&amp;quot;) {
        var subprops = getObjectProperties(s);
        for(var j in subprops) {
          var subs = subprops[j];
          var subinf = getObjectInfo(subs);
          if (!subinf) continue;
          if (subinf.nativeClass==&amp;quot;Function&amp;quot; &amp;amp;&amp;amp; subinf.filename) {
            filename = subinf.filename;
            break;
          }
        }
        if (filename) break;
      }
    }
    if (!filename) {
      // Unable to found a function in exported_symbols objects
      // now try to find a function defined in global context
      var table = getObjectTable();
      var count=0;
      for (var subid in table) {
        var subinf = getObjectInfo(parseInt(subid));
        if (subinf &amp;amp;&amp;amp; subinf.parent == id &amp;amp;&amp;amp; subinf.nativeClass==&amp;quot;Function&amp;quot; &amp;amp;&amp;amp; subinf.filename) {
          filename = subinf.filename;
          break;
        }
      }
    }
    if (filename) {
      var file = filename;
      var res = filename.match(/\/([^\/]+\/[^\/]+\/[^\/]+&#46;\w+)$/);
      if (res)
        file = decodeURIComponent(res[1]);
      jsmodules.push({
        type  : &amp;quot;jsmodule&amp;quot;,
        name  : file,
        file  : filename,
        object: id
      });
    } else {
      // we were unable to find any function, we may try to search deeper
    }
  }
  
  return JSON.stringify(jsmodules);
}

function getAllJSModules() {
  var factory = Components.classes[&amp;quot;@labs.mozilla.com/jetpackdi;1&amp;quot;]
               .createInstance(Components.interfaces.nsIJetpack);
  var endpoint = factory.get();
  var json = endpoint.profileMemory(searchJSModules.toSource()+&amp;quot;
searchJSModules()&amp;quot;, &amp;quot;find-jsmodules.js&amp;quot;, 1, null);
  return JSON.parse(json);
}
&lt;/pre&gt;


&lt;br /&gt;


&lt;br /&gt;


&lt;p&gt;Finally, here is the function which retrieve objects counts for one parent. It
use the Jetpack memory profiler XPCOM.&lt;/p&gt;

&lt;pre&gt;
function profileFunction() {
  var namedObjects=getNamedObjects();
  
  // namedObjects[&amp;quot;parent&amp;quot;] is null &#8230; why ?!
  var parent;
  for(var i in namedObjects) {
    if (i==&amp;quot;parent&amp;quot;) {
      parent = parseInt(namedObjects[i]);
    }
  }
  
  // Remove web content windows js wrapper
  var inf = getObjectInfo(parent);
  if (inf &amp;amp;&amp;amp; inf.nativeClass==&amp;quot;XPCSafeJSObjectWrapper&amp;quot;) {
    parent = inf.wrappedObject;
  }
  
  var children = {};
  
  // Check every JS object
  var table = getObjectTable();
  for(var i in table) {
    var info = getObjectInfo(parseInt(i));
    
    // Search if this one is related to the selected parent
    // ie walk throught all parents in order to find if the current object is a descendant of selected parent
    if ( info.parent != parent ) {
      var parentMatch = false;
      var p = info.parent;
      while(true) {
        var subinfo = getObjectInfo(p);
        if (!subinfo) break;
        
        if ( subinfo.id == parent || subinfo.parent == parent ) {
          // Answer= Yes
          parentMatch = true;
          break;
        }
        
        // Walk throught encapsulated objects
        if (subinfo.outerObject &amp;amp;&amp;amp; subinfo.outerObject!=p) {
          p = subinfo.outerObject;
          continue;
        }
        
        p = subinfo.parent;
      }
      // Answer= Yes
      if (!parentMatch) continue;
    }
    
    if (!children[info.nativeClass])
      children[info.nativeClass] = 0;
    children[info.nativeClass]++;
  }
  
  return JSON.stringify(children);
}
function profileParent(parent) {
  var factory = Components.classes[&amp;quot;@labs.mozilla.com/jetpackdi;1&amp;quot;]
               .createInstance(Components.interfaces.nsIJetpack);
  var endpoint = factory.get();
  var json = endpoint.profileMemory(profileFunction.toSource()+&amp;quot;
profileFunction()&amp;quot;, &amp;quot;profile.js&amp;quot;, 1, {parent: parent});
  return JSON.parse(json);
}
&lt;/pre&gt;


&lt;p style=&quot;text-align: right&quot;&gt;&lt;a href=&quot;https://wiki.mozilla.org/Labs/Jetpack/Binary_Components#Memory_Profiling&quot;&gt;More
information&lt;/a&gt;&lt;/p&gt;


&lt;br /&gt;


&lt;p&gt;Come back for the next blog post to get the 2.0 version :)&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Hackability test : Google Chrome vs Mozilla Firefox (with Jetpack)</title>
    <link href="http://techno-barje.fr/post/2009/11/10/Google-Chrome-vs-Mozilla-Firefox%28with-Jetpack%29/"/>
    <updated>2009-11-10T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2009/11/10/Google-Chrome-vs-Mozilla-Firefox(with-Jetpack)</id>
    <content type="html">&lt;p&gt;Here is a small summary of what we are able to extend in Chrome and
Firefox(with Jetpack).&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;br /&gt;


&lt;h1&gt;How to add a new item in context menu (right click menu)&lt;/h1&gt;


&lt;p&gt;&lt;strong&gt;In Chrome&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You just can&amp;#8217;t, &lt;a href=&quot;http://www.google.com/support/forum/p/Chrome/thread?tid=375371626e2ba749&amp;amp;hl=en&quot;&gt;
see here&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;In Firefox, with Jetpack&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;
jetpack.future.import(&amp;quot;menu&amp;quot;);
jetpack.future.import(&amp;quot;selection&amp;quot;);

jetpack.menu.context.page.add(function(context)({
   label: &amp;quot;My context menu item&amp;quot;,
   command: function(target) {
     
     // Do something fun with this selection
     jetpack.notifications.show( &amp;quot;Current selection : &amp;quot;+jetpack.selection.text );
     
   }
 }));
&lt;/pre&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/jetpack-context.png&quot; alt=&quot;jetpack-context.png&quot; style=&quot;margin: 0 auto; display: block; border: 1px solid black&quot; title=&quot;jetpack-context.png, nov. 2009&quot; /&gt; &lt;a href=&quot;https://wiki.mozilla.org/Labs/Jetpack/JEP/14&quot;&gt;A lot more information
here&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;br /&gt;


&lt;h1&gt;How to add a sidebar ?&lt;/h1&gt;


&lt;p&gt;&lt;strong&gt;In Chrome&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You just can&amp;#8217;t, it&amp;#8217;s a well known limitation, but nobody say it loud.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;In Firefox, with Jetpack&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;
jetpack.future.import(&amp;quot;slideBar&amp;quot;);
jetpack.slideBar.append({
   url: &amp;quot;about:blank&amp;quot;,
   width: 220,
   persist: true,
   autoReload: false,
   onReady: function(slide){

     // Do something fun with this sidebar
     var doc = slide.contentDocument;
     doc.body.innerHTML=&amp;quot;Hello world from techno-barje!&amp;quot;

   }
 });
&lt;/pre&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/jetpack-slidebar.png&quot; alt=&quot;jetpack-slidebar.png&quot; style=&quot;margin: 0 auto; display: block; border: 1px solid black&quot; title=&quot;jetpack-slidebar.png, nov. 2009&quot; /&gt; &lt;a href=&quot;https://wiki.mozilla.org/Labs/Jetpack/JEP/16&quot;&gt;More details here&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;br /&gt;


&lt;h1&gt;How to have settings and display them to users ?&lt;/h1&gt;


&lt;p&gt;&lt;strong&gt;In Chrome&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You have to add custom menu somewhere, as you want. So each extension may
display a different way to fill up their settings &amp;#8230;&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;In Firefox, with Jetpack&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;
var manifest = {
  settings: [
    {
      name: &amp;quot;twitter&amp;quot;,
      type: &amp;quot;group&amp;quot;,
      label: &amp;quot;Twitter&amp;quot;,
      settings: [
        { name: &amp;quot;username&amp;quot;, type: &amp;quot;text&amp;quot;, label: &amp;quot;Username&amp;quot; },
        { name: &amp;quot;password&amp;quot;, type: &amp;quot;password&amp;quot;, label: &amp;quot;Password&amp;quot; }
      ]
    },
    {
      name: &amp;quot;facebook&amp;quot;,
      type: &amp;quot;group&amp;quot;,
      label: &amp;quot;Facebook&amp;quot;,
      settings: [
        { name: &amp;quot;username&amp;quot;, type: &amp;quot;text&amp;quot;, label: &amp;quot;Username&amp;quot;, default: &amp;quot;jdoe&amp;quot; },
        { name: &amp;quot;password&amp;quot;, type: &amp;quot;password&amp;quot;, label: &amp;quot;Secret&amp;quot; }
      ]
    },
    { name: &amp;quot;music&amp;quot;, type: &amp;quot;boolean&amp;quot;, label: &amp;quot;Music&amp;quot;, default: true },
    { name: &amp;quot;volume&amp;quot;, type: &amp;quot;range&amp;quot;, label: &amp;quot;Volume&amp;quot;, min: 0, max: 10, default: 5 },
    { name: &amp;quot;size&amp;quot;, type: &amp;quot;number&amp;quot;, label: &amp;quot;Size&amp;quot; },
    { name: &amp;quot;mood&amp;quot;, type: &amp;quot;member&amp;quot;, label: &amp;quot;Mood&amp;quot;, set: [&amp;quot;happy&amp;quot;, &amp;quot;sad&amp;quot;, &amp;quot;nonchalant&amp;quot;] }
  ]
};
&lt;/pre&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/jetpack-settings.png&quot; alt=&quot;jetpack-settings.png&quot; style=&quot;margin: 0 auto; display: block; border: 1px solid black&quot; title=&quot;jetpack-settings.png, nov. 2009&quot; /&gt; &lt;a href=&quot;https://wiki.mozilla.org/Labs/Jetpack/JEP/24&quot;&gt;Full planned API&lt;/a&gt;(work in
progress)&lt;br /&gt;
&lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=511764&quot;&gt;You can track
progress here&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://mykzilla.org/jetpack/settings-test.html&quot;&gt;Jetpack demo
here&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;br /&gt;


&lt;h1&gt;How to display a system notification (or something like) ?&lt;/h1&gt;


&lt;p&gt;&lt;strong&gt;In Chrome&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You may display a custom HTML popup, but you will have to handle youself
display/hide of this popup, his style and each extension will have his
notification system &amp;#8230;&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;In Firefox, with Jetpack&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;
jetpack.notifications.show({title: &#8216;hai2u&#8217;, body: &#8216;o hai.&#8217;, icon: &#8216;http://www.mozilla.org/favicon.ico&#8217;}); 
&lt;/pre&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/jetpack-notifications.png&quot; alt=&quot;jetpack-notifications.png&quot; style=&quot;margin: 0 auto; display: block; border: 1px solid black&quot; title=&quot;jetpack-notifications.png, nov. 2009&quot; /&gt; &lt;a href=&quot;https://jetpack.mozillalabs.com/api.html&quot;&gt;More info here&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;

&lt;br /&gt;


&lt;br /&gt;

</content>
  </entry>
  
  <entry>
    <title>Yoono Desktop Portable</title>
    <link href="http://techno-barje.fr/post/2009/11/06/Yoono-Desktop-Portable/"/>
    <updated>2009-11-06T00:00:00+00:00</updated>
    <id>http://techno-barje.fr/post/2009/11/06/Yoono-Desktop-Portable</id>
    <content type="html">&lt;p&gt;Here is a new Yoono feature that really need some emphasis!&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;a href=&quot;http://blog.yoono.com/2009/10/get-yoono-desktop-to-go/&quot; style=&quot;font-size: 1.5em&quot;&gt;Yoono Desktop Portable&lt;/a&gt;&lt;/p&gt;


&lt;p&gt;This new version allows you to launch the Yoono&amp;#8217;s social network aggregation
tool directly from a usb key. And the most important point is that your profile
is saved on it, so no personal data is saved in the computer you&amp;#8217;re using and
all your settings and socials updates travel with you.&lt;br /&gt;
The icing on the cake is that it&amp;#8217;s even more &amp;quot;portable&amp;quot; than just that! You can
even launch this application on Windows &lt;ins&gt;AND&lt;/ins&gt; MacOS!!!&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;Only two steps to test this :&lt;/strong&gt;&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt;Unzip &lt;a href=&quot;http://cache.yoono.com/download/desktop/yoono-desktop-portable.zip&quot;&gt;yoono-desktop-portable.zip&lt;/a&gt;
somewhere on a usbkey&lt;/li&gt;
&lt;li&gt;On windows, launch &lt;em&gt;&amp;quot;Yoono Desktop Portable.exe&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;On macos, launch &lt;em&gt;&amp;quot;Yoono Desktop Portable&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;&lt;img src=&quot;http://techno-barje.fr/public/YoonoDesktopShort.png&quot; alt=&quot;YoonoDesktopShort.png&quot; style=&quot;margin: 0 auto; display: block;&quot; title=&quot;YoonoDesktopShort.png, nov. 2009&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The only drawback is usb drive read/write performance. Depending on drive
model Yoono Desktop appears to take long time to load. But we are going to gain
a huge speed up with &lt;a href=&quot;http://autonome.wordpress.com/tag/performance/&quot;&gt;current work&lt;/a&gt; on mozilla
platform about startup performance. So don&amp;#8217;t forget to check out yoono desktop
portable when Firefox 3.6 is out! (release planned before the end of the
year)&lt;/p&gt;

</content>
  </entry>
  
</feed>

