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

  <title><![CDATA[Nathan de Vries]]></title>
  <link href="http://atnan.com/atom.xml" rel="self"/>
  <link href="http://atnan.com/"/>
  <updated>2014-11-23T21:08:42-08:00</updated>
  <id>http://atnan.com/</id>
  <author>
    <name><![CDATA[Nathan de Vries]]></name>
    
  </author>

  
  <entry>
    <title type="html"><![CDATA[Modern privileged helper tools using SMJobBless + XPC]]></title>
    <link href="http://atnan.com/blog/2012/02/29/modern-privileged-helper-tools-using-smjobbless-plus-xpc/"/>
    <updated>2012-02-29T16:23:00-08:00</updated>
    <id>http://atnan.com/blog/2012/02/29/modern-privileged-helper-tools-using-smjobbless-plus-xpc</id>
    <content type="html"><![CDATA[<p>If you&#8217;ve ever needed to run a privileged task from a Mac application, you&#8217;ll probably be familiar with Apple&#8217;s <a href="https://developer.apple.com/library/mac/samplecode/BetterAuthorizationSample/Introduction/Intro.html">BetterAuthorizationSample</a> &amp; <a href="https://developer.apple.com/library/mac/#samplecode/SMJobBless/Introduction/Intro.html">SMJobBless</a> sample code.</p>

<p>Unfortunately neither project really showcases a modern, sane, secure way of adding a priveleged helper tool to your application.</p>

<!--more-->


<h2>BetterAuthorizationSample</h2>

<p>With BetterAuthorizationSample (BAS), your application includes an installer tool and a helper tool within the application bundle. Your application then jumps through the following hoops to use the helper tool:</p>

<ol>
<li>Your application runs the installer tool as root via <code>AuthorizationExecuteWithPrivileges()</code>, specifying the helper tool as an argument.</li>
<li>Installer tool copies the helper tool into <code>/Library/PrivilegedHelperTools</code>.</li>
<li>Installer tool creates a <code>launchd.plist</code> file for the helper tool in <code>/Library/LaunchDaemons</code>. The <code>launchd.plist</code> file specifies the path to the tool and that it should be launched when a connection is made to a UNIX domain socket located at <code>/var/run/&lt;application bundle ID&gt;.socket</code>.</li>
<li>Installer tool executes <code>launchctl load -w &lt;path to helper tool launchd.plist&gt;</code>.</li>
</ol>


<p>At this point your application can connect to the socket at <code>/var/run/&lt;application bundle ID&gt;.socket</code> and start sending commands to the privileged helper tool. Your application might ask the helper tool to &#8220;open TCP port 80&#8221;, to which the helper tool might respond with &#8220;here&#8217;s the descriptor that I opened&#8221;.</p>

<p>Note that while the BAS sample code&#8217;s README claims that it&#8217;s &#8220;the recommended way to access privileged functionality from a non-privileged application on Mac OS X&#8221;, that&#8217;s no longer the case. <code>AuthorizationExecuteWithPrivileges()</code> was deprecated in in Mac OS X v10.7, and has been replaced with <code>SMJobBless()</code>.</p>

<h2>SMJobBless</h2>

<p>Introduced in Mac OS X v10.6&#8217;s Service Management framework, the <code>SMJobBless()</code> API provides a more modern, secure replacement for the <code>AuthorizationExecuteWithPrivileges()</code> technique used in the BAS sample. Improvements include:</p>

<ol>
<li>The installer tool is unnecessary, so there&#8217;s fewer moving parts.</li>
<li>The helper tool &amp; <code>launchd.plist</code> are automatically copied into correct system folders and registered with <code>launchd</code>.</li>
<li>A trust relationship is established between the application and helper tool via code-signing identities. This means that the helper tool can only be used by explicitely identified applications.</li>
<li>Subsequent calls to <code>SMJobBless()</code> will check the version of your helper tool and automatically upgrade it if necessary.</li>
</ol>


<p>The SMJobBless sample code does a good job of outlining registration &amp; execution of a privileged helper tool, but unlike the BAS sample it does include any form of inter-process communication (IPC) between the application and helper tool. Most developers combine the UNIX domain socket communication code from the BAS sample with the SMJobBless sample code and call it a day.</p>

<p>But surely there&#8217;s a more modern IPC mechanism than defining your own custom command protocol over raw UNIX domain sockets?</p>

<h2>XPC</h2>

<p>Apple introduced the XPC services API in Mac OS X v10.7, providing a modern, lightweight IPC mechanism integrated with GCD and <code>launchd</code>. The typical way of using XPC is by embedding lightweight helper tools in your application (called &#8220;XPC services&#8221;), which perform work on behalf of your application.</p>

<p>Sound familiar? That&#8217;s exactly what we&#8217;re after.</p>

<p>So if XPC helps us create these &#8220;lightweight helper tool&#8221; bundles, can we simply run an XPC service in a privileged context? Apparently not:</p>

<blockquote><p>Elevating a [XPC] service’s privileges to root is not supported. Further, an XPC service is private, and is available only to the main application that contains it.</p><footer><strong>Apple</strong> <cite><a href='https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingXPCServices.html'>Daemons and Services Programming Guide</a></cite></footer></blockquote>


<p>So XPC services are out if your helper needs elevated privileges, but that doesn&#8217;t mean we can&#8217;t use the XPC APIs independently of XPC services.</p>

<p>A quick look at the XPC APIs for creating an XPC connection reveals this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='c'><span class='line'><span class="kt">xpc_connection_t</span> <span class="nf">xpc_connection_create_mach_service</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">dispatch_queue_t</span> <span class="n">targetq</span><span class="p">,</span> <span class="kt">uint64_t</span> <span class="n">flags</span><span class="p">);</span>
</span></code></pre></td></tr></table></div></figure>


<p>By registering a Mach service (instead of a UNIX domain socket as per the BAS sample code) with <code>launchd</code> (see <code>man launchd.plist(5)</code>), we can connect to it from our application using <code>xpc_connection_create_mach_service()</code>. Neat!</p>

<h2>SMJobBless + XPC</h2>

<p>To demonstrate how this works, I&#8217;ve modified the SMJobBless sample code and added XPC-based IPC support which you can <a href="https://github.com/atnan/SMJobBlessXPC">find on Github</a>.</p>

<p>The initial revision is the original SMJobBless sample code, so you can see all the modifications I&#8217;ve made by looking at the commit history.</p>

<h2>Summing Up</h2>

<p>Neither SMJobBless or BetterAuthorizationSample provide the full picture of how you would create a privileged helper tool and communicate with it from your application. SMJobBlessXPC is a step in the right direction.</p>

<p>Let me know if you have any suggestions for improvements.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Avoiding duplicate symbol errors during linking by removing classes from static libraries]]></title>
    <link href="http://atnan.com/blog/2012/01/12/avoiding-duplicate-symbol-errors-during-linking-by-removing-classes-from-static-libraries/"/>
    <updated>2012-01-12T10:34:00-08:00</updated>
    <id>http://atnan.com/blog/2012/01/12/avoiding-duplicate-symbol-errors-during-linking-by-removing-classes-from-static-libraries</id>
    <content type="html"><![CDATA[<p>If you&#8217;re using a static library in your project and specifying the <code>-all_load</code> flag to ensure files containing Objective-C categories are loaded correctly, you&#8217;ll likely experience &#8220;duplicate symbol&#8221; errors at link time if the static library includes the same classes used in your project or another library.</p>

<!--more-->


<p>e.g. A third party has provided you with a static library (<code>libProprietary.a</code>) which uses <a href="https://github.com/robbiehanson/KissXML">KissXML</a> internally for parsing &amp; generating XML. You also have an internal static library (<code>libBitsAndBobs.a</code>) which also uses <code>KissXML</code>. If you use both libraries, you&#8217;ll get duplicate symbol errors for all the <code>KissXML</code> classes (<code>DDXMLDocument</code>, <code>DDXMLElement</code> &amp; <code>DDXMLNode</code>).</p>

<p>A brutish yet simple workaround is to remove the offending classes from one of the libraries, so I&#8217;ll show you how it&#8217;s done.</p>

<p>Firstly, we need to see if the static library is a &#8220;fat file&#8221;, which means it contains code for multiple architectures. You&#8217;ll find most iOS static libraries are fat files, since they need to work both on the device (<code>armv6</code>/<code>armv7</code>) and in the Simulator (<code>i386</code>).</p>

<pre><code>$ lipo -info libProprietary.a
Architectures in the fat file: libProprietary.a are: armv6 i386
</code></pre>

<p>As you can see, we have a fat file on our hands.</p>

<p>The tools we&#8217;ll be using require us to split the static library into seperate files for each architecture if it&#8217;s a fat file. To do that, we&#8217;ll use <code>lipo</code> again.</p>

<pre><code>$ lipo -thin armv6 libProprietary.a -output libProprietary-armv6.a
</code></pre>

<p>We can now use <code>ar</code> to peek inside one of these thin archive files, listing the included object files.</p>

<pre><code>$ ar -t libProprietary-armv6.a
__.SYMDEF SORTED
FOOBar.o
DDXMLDocument.o
DDXMLElement.o
DDXMLElementAdditions.o
DDXMLNode.o
</code></pre>

<p>As expected, in addition to the <code>FOOBar.o</code> file containing code specific to <code>libProprietary.a</code>, we also have object files for each of the classes defined in the <code>KissXML</code> project. To delete those, we&#8217;ll need to unpack the object files from the archive, delete the object files we don&#8217;t want, and repack the archive.</p>

<p>First, the extraction:</p>

<pre><code>$ mkdir libProprietary-armv6
$ cd libProprietary-armv6
$ ar -x ../libProprietary-armv6.a
</code></pre>

<p>We now have a directory containing the contents of the archive:</p>

<pre><code>$ ls -1
DDXMLDocument.o
DDXMLElement.o
DDXMLElementAdditions.o
DDXMLNode.o
FOOBar.o
__.SYMDEF SORTED
</code></pre>

<p>Simply remove the <code>KissXML</code> related object files and repack the archive like so:</p>

<pre><code>$ rm DDXML*.o
$ libtool  -static *.o -output ../libProprietary-armv6.a
</code></pre>

<p>And to confirm we&#8217;ve successfully removed the correct object files from our archive, we can list the contents again:</p>

<pre><code>$ ar -t ../libProprietary-armv6.a
__.SYMDEF SORTED
FOOBar.o
</code></pre>

<p>So far we&#8217;ve only stripped the <code>armv6</code> archive, so we need to repeat the process for the <code>i386</code> archive:</p>

<pre><code>$ lipo -thin i386 libProprietary.a -output libProprietary-i386.a
$ mkdir libProprietary-i386 &amp;&amp; cd libProprietary-i386
$ ar -x ../libProprietary-i386.a
$ rm DDXML*.o
$ libtool  -static *.o -output ../libProprietary-i386.a
</code></pre>

<p>Now for the final step, we recombine the thin files into a fat file again:</p>

<pre><code>lipo -create libProprietary-armv6.a libProprietary-i386.a -output libProprietary-noKissXML.a
</code></pre>

<p>If you&#8217;ve done everything correctly you can now replace <code>libProprietary.a</code> with <code>libProprietary-noKissXML.a</code> and you won&#8217;t have any more duplicate symbol errors.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Enabling Remote Debugging via Private APIs in Mobile&nbsp;Safari]]></title>
    <link href="http://atnan.com/blog/2011/11/17/enabling-remote-debugging-via-private-apis-in-mobile-safari/"/>
    <updated>2011-11-17T20:03:00-08:00</updated>
    <id>http://atnan.com/blog/2011/11/17/enabling-remote-debugging-via-private-apis-in-mobile-safari</id>
    <content type="html"><![CDATA[<p>The WebKit Web Inspector in Safari &amp; Chrome is part of every decent web developer&#8217;s toolkit, but unfortunately it&#8217;s unavailable in Mobile&nbsp;Safari.</p>

<p>Or is it?</p>

<!--more-->


<p>While I was researching my previous article on <a href="http://atnan.com/blog/2011/11/03/enabling-and-using-webgl-on-ios/">enabling WebGL on iOS via private WebKit APIs</a>, another API caught my eye while I was <code>class-dump</code>ing the private <code>WebKit.framework</code>.</p>

<figure class='code'><figcaption><span>Private WebView API</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@interface</span> <span class="nc">WebView</span> <span class="nl">(WebPrivate)</span>
</span><span class='line'><span class="p">+</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">_enableRemoteInspector</span><span class="p">;</span>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>


<p>I did a little bit of research and found an article by Pavel Feldman (<a href="https://twitter.com/repenaxa">@repenaxa</a>) on the Surfin&#8217; Safari blog about <a href="http://www.webkit.org/blog/1620/webkit-remote-debugging/">WebKit&#8217;s remote debugging feature</a>. This private <code>+[WebView _enableRemoteInspector]</code> API enables those same features in mobile WebKit.</p>

<p><strong>Note: </strong> This API is available as of iOS 5.0. To use it, you&#8217;ll need a copy of Xcode with the iOS 5.0 SDK. You&#8217;ll also need to make sure that if you&#8217;ve got the iOS 4.0 SDK installed alongside the iOS 5.0 SDK, that you&#8217;ve selected iOS 5.0 in the iPhone Simulator via the <code>Hardware → Version</code> menu. Hat tip to Phil Oye (<a href="https://twitter.com/philoye">@philoye</a>) for pointing that out.</p>

<h2>Enabling remote debugging in a <code>UIWebView</code></h2>

<p>To see if I could get it working, I checked out a copy of my <a href="https://github.com/atnan/UIWebViewWebGL">UIWebViewWebGL</a> project, and called the private API in <code>application:didFinishLaunchingWithOptions</code>:</p>

<figure class='code'><figcaption><span>Enabling the remote inspector on launch</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">-</span> <span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nf">application:</span><span class="p">(</span><span class="bp">UIApplication</span> <span class="o">*</span><span class="p">)</span><span class="nv">application</span> <span class="nf">didFinishLaunchingWithOptions:</span><span class="p">(</span><span class="bp">NSDictionary</span> <span class="o">*</span><span class="p">)</span><span class="nv">launchOptions</span> <span class="p">{</span>
</span><span class='line'>  <span class="c1">// ...Snipped...</span>
</span><span class='line'>  <span class="p">[</span><span class="n">NSClassFromString</span><span class="p">(</span><span class="s">@&quot;WebView&quot;</span><span class="p">)</span> <span class="n">_enableRemoteInspector</span><span class="p">];</span>
</span><span class='line'>  <span class="c1">// ...Snipped...</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>The Surfin&#8217; Safari article said the remote debugger runs on port <code>9222</code>, but connecting to <code>http://localhost:9222</code> while the app was running in the simulator didn&#8217;t seem to work.</p>

<p>Using <code>lsof</code> showed that <code>UIWebViewWebGL.app</code> was actually listening on port <code>9999</code>:</p>

<pre><code>$ sudo lsof -i TCP -a -p $(pidof UIWebViewWebGL) -P
COMMAND    PID   USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
UIWebView 3748 nathan    9u  IPv6 0xffffff800fa25d80      0t0  TCP localhost:9999 (LISTEN)
UIWebView 3748 nathan   13u  IPv6 0xffffff80111ba340      0t0  TCP localhost:9999-&gt;localhost:52483 (ESTABLISHED)
</code></pre>

<p>Now when I pointed my browser at <code>http://localhost:9999</code>, it worked!</p>

<p><img class="center" src="http://atnan.com/downloads/WebKit_Remote_Debugger.png"></p>

<p>Logging <code>document.location.href</code> in the web inspector console shows I&#8217;m successfully inspecting the web content from <code>UIWebViewWebGL.app</code> running in the iPhone Simulator.</p>

<p>Huzzah!</p>

<h2>Enabling remote debugging in Mobile Safari</h2>

<p>Enabling the web inspector in an embedded <code>UIWebView</code> is handy, but what about content running in Mobile Safari?</p>

<p>To do that, we need to call the <code>+[WebView _enableRemoteInspector]</code> API from within the Mobile Safari app. The easiest way to do that is by launching Mobile Safari in the iPhone Simulator, and then use <code>gdb</code> to attach to it and call the private API.</p>

<figure class='code'><figcaption><span>Script to enable the remote inspector in Mobile Safari</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">MobileSafari_PID</span><span class="o">=</span><span class="k">$(</span>ps x <span class="p">|</span> grep <span class="s2">&quot;MobileSafari&quot;</span> <span class="p">|</span> grep -v grep <span class="p">|</span> awk <span class="s1">&#39;{ print $1 }&#39;</span><span class="k">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="o">[</span> <span class="s2">&quot;$MobileSafari_PID&quot;</span> <span class="o">==</span> <span class="s2">&quot;&quot;</span> <span class="o">]</span><span class="p">;</span> <span class="k">then</span>
</span><span class='line'>  <span class="nb">echo</span> <span class="s2">&quot;Mobile Safari.app must be running in the Simulator to enable the remote inspector.&quot;</span>
</span><span class='line'><span class="k">else</span>
</span><span class='line'>
</span><span class='line'>  cat <span class="s">&lt;&lt;EOM | gdb -quiet &gt; /dev/null</span>
</span><span class='line'><span class="s">  attach $MobileSafari_PID</span>
</span><span class='line'><span class="s">  p (void *)[WebView _enableRemoteInspector]</span>
</span><span class='line'><span class="s">  detach</span>
</span><span class='line'><span class="s">EOM</span>
</span><span class='line'>
</span><span class='line'><span class="k">fi</span>
</span></code></pre></td></tr></table></div></figure>


<p>Browsing to <code>http://localhost:9999</code> will show an index page listing the URL of each tab open in Mobile Safari. This allows you to have a remote inspector open for each tab in Mobile Safari.</p>

<h2>Summing Up</h2>

<p>I haven&#8217;t used the remote inspector in anger yet, but so far it&#8217;s been incredibly useful.</p>

<p>Note that you can&#8217;t use <code>gdb</code> to inject code on a device, so enabling remote debugging in Mobile Safari is limited to the Simulator. Hopefully Apple will provide the option to enable it, much like the debug console in <code>Settings → Safari → Advanced → Debug Console</code>.</p>

<p><strike>In the meantime, you can load your web content in an embedded UIWebView.</strike> Enabling the remote inspector on a <code>UIWebView</code> in an app running on the device doesn&#8217;t seem to work. Using <code>nmap</code> shows that my iPhone only has port <code>62078</code> open for OTA syncing, so it&#8217;s likely there&#8217;s a firewall preventing connections to the remote inspector port.</p>

<hr />


<p>Have something to say? <a href="http://news.ycombinator.com/item?id=3195128">Discuss on Hacker News</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[iOS vs. Android ICS: Hardware Accelerated Graphics Pipelines]]></title>
    <link href="http://atnan.com/blog/2011/11/10/ios-vs-android-ics-hardware-accelerated-graphics-pipelines/"/>
    <updated>2011-11-10T02:56:00-08:00</updated>
    <id>http://atnan.com/blog/2011/11/10/ios-vs-android-ics-hardware-accelerated-graphics-pipelines</id>
    <content type="html"><![CDATA[<p><img class="right" src="http://atnan.com/downloads/iOSExplodedLayers.png"></p>

<p>Earlier this year, <a href="http://flipboard.com/">Flipboard</a> developer Charles Ying (<a href="http://twitter.com/charlietuna">@charlietuna</a>) fairly &amp; accurately criticised Android&#8217;s immature graphics pipeline &amp; subsequent poor drawing performance.</p>

<blockquote><p>Android’s UX architecture needs work. UI compositing and the view system are both primarily done in software. Garbage collection and async operations frequently block UI rendering.</p><footer><strong>Charles Ying</strong> <cite><a href='http://www.satine.org/archives/2011/01/01/the-care-and-feeding-of-the-android-gpu/'>The Care and Feeding of the Android GPU</a></cite></footer></blockquote>


<p>It sparked a wildfire of <a href="http://www.satine.org/archives/2011/01/01/the-care-and-feeding-of-the-android-gpu/#comments">comments on the article</a>, <a href="http://news.ycombinator.com/item?id=2061722">Hacker News</a>, and a <a href="http://daringfireball.net/linked/2011/01/04/hacker-news-ying">writeup by John Gruber</a>, who like many others found amusement in the <a href="http://news.ycombinator.com/item?id=2062098">defensive comments</a> of Jonathan Rockway (<a href="https://twitter.com/jrockway">@jrockway</a>) and other Android apologists. Rockway later <a href="http://news.ycombinator.com/item?id=2062846">admitted to turning off animations entirely</a>, adding to the amusement.</p>

<p>Setting aside the arguments of people who seem content with hands over their eyes and fingers in their ears, Charles had a point. Technically, Android&#8217;s architecture was inferior, and it had a measurable effect on the user experience.</p>

<p>Things have come a long way since then, so I think it&#8217;s only fair to take another look at Android&#8217;s graphics pipeline to see if the issues have been addressed.</p>

<!--more-->


<h2>A short disclaimer</h2>

<p>I write software exclusively for iOS, so you should consider what follows to be biased, at least by observation. I lack insight into the technical depths of Android development, however I like to think I&#8217;ve made an attempt over the years to keep abreast of Android technologies &amp; platform capability.</p>

<h2>Google Developer Day Sydney</h2>

<p>One of the ways I keep up to date with Android is to attend <a href="http://www.google.com/events/developerday">Google Developer Days</a>. At these events, a subset of content from <a href="http://www.google.com/events/io/2011/">Google I/O</a> is shown in various cities around the world.</p>

<p>At the most recent <a href="http://www.google.com/events/developerday/2011/sydney/agenda/session_2003.html">GDD Sydney</a>, Ankur Kotwal (<a href="https://twitter.com/ankurkotwal">@ankurkotwal</a>) gave a talk on <a href="http://www.google.com/events/developerday/2011/sydney/agenda/session_2003.html">High-performance graphics for Android</a> which is the catalyst for this article. I&#8217;m not sure if Ankur&#8217;s slides are online, but they&#8217;re near identical to the slides from Romain Guy&#8217;s (<a href="https://twitter.com/romainguy">@romainguy</a>) <a href="http://www.slideshare.net/romainguy/google-io-2011-android-accelerated-rendering">Google I/O 2011 talk on Android Accelerated Rendering</a>.</p>

<h2>Android pre-3.0, the problem restated</h2>

<p>As Charles pointed out in his article, the 2D primitives (lines, boxes, text, gradients, images etc.) used to compose a view in an Android app prior to 3.0 are drawn/rasterised on the CPU by the <a href="http://en.wikipedia.org/wiki/Skia_Graphics_Engine">Skia graphics engine</a>. The contents of each view are then combined/composited by the GPU before being displayed on the screen.</p>

<p>Drawing on the CPU isn&#8217;t the problem, though. Quartz 2D / Core Graphics — Skia&#8217;s equivalent on iOS — performs the majority of rasterisation on the CPU too.</p>

<p>So if the issue isn&#8217;t drawing on the CPU, what is? It&#8217;s that on Android pre-3.0, <em>the view hierarchy is redrawn on the CPU on each tick of the render loop if any view changes</em>.</p>

<p>Scroll a list? Redraw. Pinch &amp; zoom? Redraw.</p>

<p>That&#8217;s fine, if you can keep up.</p>

<p>You need to be able to draw on the CPU &amp; copy the pixels to the GPU quickly enough that you don&#8217;t lag behind the display rate of 60hz.</p>

<p>Android phones can this <em>just</em> fast enough, most of the time, so this solution is considered &#8220;good enough&#8221; by Google. Start running Android on a bigger screen with more pixels, and you&#8217;ve got yourself a pipeline problem. TVs &amp; tablets mean bigger screens.</p>

<p>The problem is illustrated quite clearly in a chart from Romain Guy&#8217;s <a href="http://www.slideshare.net/romainguy/google-io-2011-android-accelerated-rendering">Google I/O 2011 talk on Android Accelerated Rendering</a> comparing pixel count and memcpy performance on the HTC G1, HTC Droid, Google Nexus One, Google Nexus S &amp; Motorola&#8217;s XOOM tablet:</p>

<p><img class="center" src="http://atnan.com/downloads/Android_Fillrate.png"></p>

<p>Interestingly, both the HTC Droid &amp; Nexus One didn&#8217;t <em>quite</em> have enough memory bandwidth available to transfer screen-sized pixel buffers to the GPU. The Nexus S gained some speed, but the Motorola XOOM made it clear that something had to change.</p>

<h2>The Solution</h2>

<p>When you&#8217;re scrolling a list, the pixels of the views within the list aren&#8217;t <em>changing</em>, they&#8217;re simply <em>moving</em>. The GPU already has the pixels of each view in the form of textures, so why not move the texture instead?</p>

<p>This is exactly what iOS does, and is why it&#8217;s never suffered any consequences of CPU-based rasterisation.</p>

<p>In the case of scrolling a list we&#8217;re simply moving a view, but views can also be scaled, rotated, clipped, made translucent, transformed in 2D or 3D space, or even have pixel shaders applied to them. All these things (and others!) can be done to a view&#8217;s contents without needing to redraw &amp; send a new texture to the GPU.</p>

<p>You can find out more about this works on iOS in the <a href="http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html">View Drawing Cycle</a> section of the <a href="http://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Introduction/Introduction.html">View Programming Guide for iOS</a>.</p>

<h2>Android Catches Up</h2>

<p>Android 3.0 (Honeycomb) <a href="http://android-developers.blogspot.com/2011/03/android-30-hardware-acceleration.html">bridged the gap</a> between the iOS &amp; Android rendering architecture, allowing developers targeting API level 11+ on tablets to opt-in to the new hardware accelerated pipeline.</p>

<p>Android 4.0 (Ice Cream Sandwich) <a href="http://android-developers.blogspot.com/2011/11/android-40-graphics-and-animations.html">has done the same</a>, bringing the hardware accelerated pipeline to phones and turning it on by default for all applications built against Android API level 14.</p>

<h2>Android Goes One Step Further</h2>

<p>Rather than simply generating a CPU-rasterised bitmap ready for the GPU, the Skia 2D drawing APIs generate an ordered list of operations. Each view maintains a list of those operations in a <code>DisplayList</code>. Android 3.0 introduced a new OpenGL-ES Skia backend, which takes each of those <code>DisplayList</code>s and runs the operations on the GPU. Pretty neat!</p>

<p>This technique of keeping an ordered list of drawing operations is similar to PDF&#8217;s object graph:</p>

<blockquote><p>&#8230;each page in a PDF document has a page content stream—an ordered list of drawing operations that describes how to render the page-content when it is drawn.</p><footer><strong>David Gelphman, Bunny Laden</strong> <cite><a href='http://books.google.com.au/books?id=StdwgT34RCwC&lpg=PA398&dq=%22each%20page%20in%20a%20PDF%20document%20has%20a%20page%20content%20stream%E2%80%94an%20ordered%20list%20of%20drawing%20operations%20that%20describes%20how%20to%20render%20the%20page-content%20when%20it%20is%20drawn.%22&pg=PA398#v=onepage&q=%22each%20page%20in%20a%20PDF%20document%20has%20a%20page%20content%20stream%E2%80%94an%20ordered%20list%20of%20drawing%20operations%20that%20describes%20how%20to%20render%20the%20page-content%20when%20it%20is%20drawn.%22&f=false'>Programming With Quartz: 2D and PDF Graphics in Mac OS X</a></cite></footer></blockquote>


<p>Some of you may have noticed that quote&#8217;s from a book on Mac OS X&#8217;s Quartz framework. Here&#8217;s why:</p>

<blockquote><p>Quartz&#8217;s internal imaging model correlates well with the PDF object graph, making it easy to output PDF to multiple devices.</p><footer><strong>Mike Paquette (Quartz Engineer at Apple)</strong> <cite><a href='http://developers.slashdot.org/comments.pl?sid=75257&cid=6734612'>Slashdot</a></cite></footer></blockquote>


<p>i.e. Quartz &amp; Skia have a similar internal model.</p>

<p>In fact, Apple released something similar to Skia&#8217;s OpenGL backend called Quartz 2D Extreme in Mac OS X 10.4 (renamed QuartzGL in 10.5), but never ported the technology to iOS.</p>

<p>I&#8217;d always thought QuartzGL wasn&#8217;t ported due to lacklustre performance, based on Matt Gallagher&#8217;s <a href="http://cocoawithlove.com/2011/03/mac-quartzgl-2d-drawing-on-graphics.html">article comparing Quartz &amp; QuartzGL performance on Mac OS X</a>. However, it seems Google&#8217;s results have been rather positive, as can be seen in this chart from Romain Guy&#8217;s <a href="http://www.slideshare.net/romainguy/google-io-2011-android-accelerated-rendering">Google I/O 2011 talk on Android Accelerated Rendering</a>:</p>

<p><img class="center" src="http://atnan.com/downloads/SkiaGL_Performance.png"></p>

<p>These results seems rather impressive!</p>

<h2>Conclusion</h2>

<p>The changes to Android&#8217;s rendering pipeline in 3.0 &amp; 4.0 bring it into the same league as iOS &amp; Windows Phone 7. Hopefully the migration 2.x to 4.x is smooth, given the minor incompatibilities between Skia&#8217;s CPU &amp; GPU backends.</p>

<p>It&#8217;ll be interesting to see whether Apple decides to provide a GPU rasterisation backend to Quartz 2D / Core Graphics on iOS. It doesn&#8217;t seem to be a pain point, but you never know.</p>

<p>I&#8217;ll definitely be keeping my eye on the Nexus Prime. If they&#8217;re any good, I may need to stop spectating from the edges and get my hands dirty.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Amazing response to my iOS webGL hack]]></title>
    <link href="http://atnan.com/blog/2011/11/07/amazing-response-to-my-ios-webgl-hack/"/>
    <updated>2011-11-07T18:35:00-08:00</updated>
    <id>http://atnan.com/blog/2011/11/07/amazing-response-to-my-ios-webgl-hack</id>
    <content type="html"><![CDATA[<p>Holy cow, I didn&#8217;t anticipate how well my article on <a href="http://atnan.com/blog/2011/11/03/enabling-and-using-webgl-on-ios/">enabling &amp; using WebGL on iOS</a> would be received! The article has been <a href="https://twitter.com/search?q=http%3A%2F%2Fatnan.com%2Fblog%2F2011%2F11%2F03%2Fenabling-and-using-webgl-on-ios%2F">retweeted over 200 times on Twitter</a>, and soared to 2nd place on Hacker News with a <a href="http://news.ycombinator.com/item?id=3190261">bunch of great feedback &amp; comments</a>.</p>

<!--more-->


<p>Even more incredible is how quickly creative folks have taken the idea and run with it. <a href="http://ciid.dk/consulting/people/marcin-ignac/">Marcin Ignac</a> (<a href="https://twitter.com/marcinignac">@marcinignac</a>) &amp; <a href="http://ciid.dk/consulting/people/david-gauthier/">David Gauthier</a> from the <a href="http://ciid.dk">Copenhagen Institute of Interaction Design</a> built a gesture-driven WebGL-enabled browser called <a href="https://github.com/gauthiier/GoWebGL">GoWebGL</a>, and put together a demo video showcasing WebGL on an iPad 2:</p>

<iframe src="http://player.vimeo.com/video/31644717" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>


<p>The framerates are slow at times which seems to justify Apple&#8217;s tentative rollout of WebGL, however the potential is excitingly clear!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Blaine "Runtimes Wizard" Garst Retiring after 21 years at Apple]]></title>
    <link href="http://atnan.com/blog/2011/11/04/blaine-runtimes-wizard-garst-retiring-after-21-years-at-apple/"/>
    <updated>2011-11-04T16:31:00-07:00</updated>
    <id>http://atnan.com/blog/2011/11/04/blaine-runtimes-wizard-garst-retiring-after-21-years-at-apple</id>
    <content type="html"><![CDATA[<p>Some of you might follow Chris Parker (<a href="https://twitter.com/ctp">@ctp</a>) &amp; Robert Marini (<a href="https://twitter.com/wisequark">@wisequark</a>) on Twitter, and may have noticed them mention that Blaine Garst is retiring tomorrow after <em>21 years &amp; 4 months at Apple</em> and <em>6 years at NeXT</em>.</p>

<!--more-->


<p>Others won&#8217;t know who Blaine Garst is, despite being exposed — at least indirectly — to the phenomenal body of work he&#8217;s been responsible for at both NeXT and Apple.</p>

<p>You only need to look at the lineage of his accomplishments to get an impression of the dent he&#8217;s made on the universe:</p>

<blockquote><p>1971 PLATO user, bit-mapped graphics, chat rooms, dogfights<br/>1974 University High School, Math & Science award<br/>1974 exposed to UNIX by Greg Chesson<br/>1976 University of Illinois, BA Economics<br/>1977 UCLA MS degree requirements met, Bell Labs<br/>1981 first person to boot UNIX on 11/782 dual processor<br/>1984 Manager System V R2.2 (?), 1st dual processor support<br/>1986 purchased VFS/NFS for System V Release 3 (?)<br/>1987 co-architect of SVR4 as part of 20% purchase of Sun<br/>1988 On &#8220;Phase-3&#8221; team when/where &#8220;Spring&#8221; named/derived<br/>1989 &#8220;Fizix&#8221; nanokernel built on Cheriton&#8217;s &#8220;door&#8221; IPC idea, 20x cost to do remote vs local procedure call<br/>1990 NeXT Computer, Inc.<br/>1991 Objective-C Protocols, &#8220;ripped-off&#8221; in Java as Interfaces<br/>1992 Foundation: &#8220;Distributed Objects&#8221;, retain/release, NSLock, NSRunloop, NSTimer, NSThread, &#8230; <br/>1993 Direct Embedding Fast Elliptical Encryption<br/>1994 &#8220;Foundation&#8221; on HPUX, Solaris, DEC, &#8230;<br/>1996 JavaBridge - Java subclassing of ObjC<br/>1998 two-GC cycle recovery in JavaBridge<br/>2003 @try&#8230;, @synchronized<br/>2007 ObjC2: GC, for..in, @properties, &#8230;<br/>2008 Blocks C,ObjC,C++; TLC: 10^6 alloc+recovery/sec/core<br/>2009 n-GC cycle recovery (generalization of 2-GC)</p><footer><strong>Blain Garst</strong> <cite><a href='http://www.linkedin.com/pub/blaine-garst/0/28/808,'>LinkedIn Profile</a></cite></footer></blockquote>


<p>Humbling.</p>

<hr />


<p>Have something to say? <a href="http://news.ycombinator.com/item?id=3195128">Discuss on Hacker News</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Enabling &amp; Using WebGL on iOS]]></title>
    <link href="http://atnan.com/blog/2011/11/03/enabling-and-using-webgl-on-ios/"/>
    <updated>2011-11-03T14:40:00-07:00</updated>
    <id>http://atnan.com/blog/2011/11/03/enabling-and-using-webgl-on-ios</id>
    <content type="html"><![CDATA[<h2>Background</h2>

<p>I&#8217;ve become a lot more interested in WebGL lately, and remembered reading <a href="http://news.ycombinator.com/item?id=2661757">on Hacker News</a> a while back that WebGL would be available in iOS 5 as part of the iAd framework.</p>

<blockquote><p>WebGL will not be publicly available in iOS 5. It will only be available to iAd developers.</p><footer><strong>Chris Marrin, WebKit Engineer</strong> <cite><a href='https://www.khronos.org/webgl/public-mailing-list/archives/1106/msg00036.html'>Public WebGL Mailing List</a></cite></footer></blockquote>


<p>When iOS 5.0 went GM, I decided to knock up a quick WebGL demo to see what was involved &amp; how well it performed.</p>

<p>Unfortunately it didn&#8217;t run at all — creating a <code>webgl-experimental</code> context via the canvas element&#8217;s <code>getContext()</code> API would fail.</p>

<!--more-->


<h2>Breakthrough</h2>

<p>I shot through a tweet to <a href="https://twitter.com/graouts">Antoine Quint</a> (iAd JS/iOS software engineer at Apple), asking for confirmation of Chris Marrin&#8217;s email:</p>

<blockquote><p>Chris Marrin suggested that WebGL would be available in iAds as of iOS 5.0. Is that actually the case?</p><footer><strong>Nathan de Vries</strong> <cite><a href='https://twitter.com/atnan/status/128396256610492416'>Twitter</a></cite></footer></blockquote>


<p>To which he replied:</p>

<blockquote><p>WebGL has been supported for iAds since iOS 4.2.</p><footer><strong>Antoine Quint</strong> <cite><a href='https://twitter.com/graouts/status/128474954743287808'>Twitter</a></cite></footer></blockquote>


<p>That&#8217;s even better news than I had anticipated! However, it still doesn&#8217;t explain why I&#8217;m unable to create a WebGL context.</p>

<p>With a little bit more prompting, I got to the bottom of why <code>HTMLCanvasElement</code> was returning <code>null</code> when I called <code>getContext("experimental-webgl")</code>:</p>

<blockquote><p>You also need to have &#8220;uses-webgl&#8221; in your ad&#8217;s plist. Sorry, forgot about that.</p><footer><strong>Antoine Quint</strong> <cite><a href='https://twitter.com/graouts/status/129055741125464064'>Twitter</a></cite></footer></blockquote>


<p>The <code>uses-webgl</code> setting is completely undocumented, but it certainly works!</p>

<h2>Demo iAd WebGL Project</h2>

<p>I&#8217;ve put together a <a href="https://github.com/atnan/WebGL.ad">demo WebGL iAd project</a> that can simply be dragged into the Simulator or synced to your device via iTunes.</p>

<p>Drag the <code>WebGL.ad</code> directory into the iOS Simulator &amp; the built-in <code>iAd Tester</code> app will launch. You&#8217;ll see a banner at the bottom, which when tapped will bring up the WebGL demo:</p>

<p><img class="center" src="http://atnan.com/downloads/iAd_WebGL.png"></p>

<p>If you&#8217;re having difficulties getting the iAd running, take a look at the <a href="https://developer.apple.com/library/iad/#documentation/UserExperience/Conceptual/iAdJSProgGuide/CreatingAdsTutorial/CreatingAdsTutorial.html#//apple_ref/doc/uid/TP40010301-CH12-SW22">Testing on the iOS Simulator</a> and <a href="https://developer.apple.com/library/iad/#documentation/UserExperience/Conceptual/iAdJSProgGuide/CreatingAdsTutorial/CreatingAdsTutorial.html#//apple_ref/doc/uid/TP40010301-CH12-SW22">Testing on the Device</a> sections of the <a href="https://developer.apple.com/library/iad/documentation/UserExperience/Conceptual/iAdJSProgGuide/Introduction/Introduction.html">iAd JS Programming Guide</a>.</p>

<h2>Do standard <code>UIWebView</code>s (secretly) support WebGL?</h2>

<p>So if the iAd framework is using a <code>UIWebView</code>, perhaps we can get the same behaviour in our own web views?</p>

<p>Looking at the output of <code>ps</code> while running <code>iAd Tester</code> in the iOS Simulator, you&#8217;ll notice an app called <code>AdSheet</code> running. Using <code>otool</code>, we can see what private frameworks it&#8217;s linked against:</p>

<pre><code>otool -L /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk//Applications/AdSheet.app/AdSheet | grep PrivateFrameworks
  /System/Library/PrivateFrameworks/iAdCore.framework/iAdCore (compatibility version 1.0.0, current version 1.0.0)
  /System/Library/PrivateFrameworks/SpringBoardServices.framework/SpringBoardServices (compatibility version 1.0.0, current version 1.0.0)
</code></pre>

<p><code>iAdCore.framework</code> looks interesting. Let&#8217;s take a look for WebGL-related functionality using <code>class-dump</code>:</p>

<pre><code>class-dump /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/System/Library/PrivateFrameworks/iAdCore.framework/iAdCore
</code></pre>

<p>Searching through the output, it&#8217;s pretty clear that we&#8217;ve found what we&#8217;re after:</p>

<figure class='code'><figcaption><span>Relevant subset of class-dump output, revealing the private ADWebView class</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@interface</span> <span class="nc">ADWebView</span> : <span class="bp">UIWebView</span> <span class="p">{</span>
</span><span class='line'>    <span class="kt">BOOL</span> <span class="n">_webGLEnabled</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="k">@property</span><span class="p">(</span><span class="k">nonatomic</span><span class="p">)</span> <span class="kt">BOOL</span> <span class="n">webGLEnabled</span><span class="p">;</span> <span class="c1">// @synthesize webGLEnabled=_webGLEnabled;</span>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Turns out we can simply link against the private <code>iAdCore.framework</code>, and use <code>ADWebView</code>s instead of <code>UIWebView</code>s. Here&#8217;s an implementation which does just that:</p>

<figure class='code'><figcaption><span>Create an ADWebView, enable WebGL & load HTLM containing WebGL</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="k">@implementation</span> <span class="nc">WGLAppDelegate</span>
</span><span class='line'><span class="p">-</span> <span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nf">application:</span><span class="p">(</span><span class="bp">UIApplication</span> <span class="o">*</span><span class="p">)</span><span class="nv">application</span> <span class="nf">didFinishLaunchingWithOptions:</span><span class="p">(</span><span class="bp">NSDictionary</span> <span class="o">*</span><span class="p">)</span><span class="nv">launchOptions</span> <span class="p">{</span>
</span><span class='line'>  <span class="kt">Class</span> <span class="n">ADWebView</span> <span class="o">=</span> <span class="n">NSClassFromString</span><span class="p">(</span><span class="s">@&quot;ADWebView&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="bp">UIWebView</span><span class="o">*</span> <span class="n">webView</span> <span class="o">=</span> <span class="p">(</span><span class="bp">UIWebView</span> <span class="o">*</span><span class="p">)[[[</span><span class="n">ADWebView</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithFrame</span><span class="p">:</span><span class="nb">self</span><span class="p">.</span><span class="n">window</span><span class="p">.</span><span class="n">bounds</span><span class="p">]</span> <span class="n">autorelease</span><span class="p">];</span>
</span><span class='line'>  <span class="p">[</span><span class="n">webView</span> <span class="nl">setWebGLEnabled</span><span class="p">:</span><span class="nb">YES</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>  <span class="bp">NSString</span><span class="o">*</span> <span class="n">htmlPath</span> <span class="o">=</span> <span class="p">[[</span><span class="bp">NSBundle</span> <span class="n">mainBundle</span><span class="p">]</span> <span class="nl">pathForResource</span><span class="p">:</span><span class="s">@&quot;WebGL&quot;</span> <span class="nl">ofType</span><span class="p">:</span><span class="s">@&quot;html&quot;</span><span class="p">];</span>
</span><span class='line'>  <span class="bp">NSURLRequest</span><span class="o">*</span> <span class="n">request</span> <span class="o">=</span> <span class="p">[</span><span class="bp">NSURLRequest</span> <span class="nl">requestWithURL</span><span class="p">:[</span><span class="bp">NSURL</span> <span class="nl">fileURLWithPath</span><span class="p">:</span><span class="n">htmlPath</span><span class="p">]];</span>
</span><span class='line'>  <span class="p">[</span><span class="n">webView</span> <span class="nl">loadRequest</span><span class="p">:</span><span class="n">request</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>  <span class="bp">UIViewController</span><span class="o">*</span> <span class="n">viewController</span> <span class="o">=</span> <span class="p">[[[</span><span class="bp">UIViewController</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">]</span> <span class="n">autorelease</span><span class="p">];</span>
</span><span class='line'>  <span class="n">viewController</span><span class="p">.</span><span class="n">view</span> <span class="o">=</span> <span class="n">webView</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nb">self</span><span class="p">.</span><span class="n">window</span><span class="p">.</span><span class="n">rootViewController</span> <span class="o">=</span> <span class="n">viewController</span><span class="p">;</span>
</span><span class='line'>  <span class="p">[</span><span class="nb">self</span><span class="p">.</span><span class="n">window</span> <span class="n">makeKeyAndVisible</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="k">@end</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Is <code>ADWebView</code> really doing that much?</h2>

<p>Perhaps we can get rid of <code>ADWebView</code> altogether &amp; just implement whatever <code>-[ADWebView setWebGLEnabled:]</code> is doing in our own custom <code>UIWebView</code> subclass. We&#8217;re still going to be calling private APIs, but at least we won&#8217;t need to link against private frameworks.</p>

<p>To reproduce <code>-[ADWebView setWebGLEnabled:]</code>, we&#8217;ll need to disassemble it using <code>otool -tVv</code>, or install <code>objdump</code> via Homebrew &amp; use <code>gobjdump -d</code>. Here&#8217;s the bit we&#8217;re interested in:</p>

<figure class='code'><figcaption><span>Disassembly of -[ADWebView setWebGLEnabled:]</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
</pre></td><td class='code'><pre><code class='objdump'><span class='line'><span class="mh">0005aba3</span> <span class="p">&lt;</span><span class="nf">-[ADWebView setWebGLEnabled:]</span><span class="p">&gt;:</span>
</span><span class='line'><span class="x">   5aba3:       55                      push   %ebp</span>
</span><span class='line'><span class="x">   5aba4:       89 e5                   mov    %esp,%ebp</span>
</span><span class='line'><span class="x">   5aba6:       56                      push   %esi</span>
</span><span class='line'><span class="x">   5aba7:       83 ec 24                sub    $0x24,%esp</span>
</span><span class='line'><span class="x">   5abaa:       e8 00 00 00 00          call   5abaf &lt;-[ADWebView setWebGLEnabled:]+0xc&gt;</span>
</span><span class='line'><span class="x">   5abaf:       59                      pop    %ecx</span>
</span><span class='line'><span class="x">   5abb0:       8b b1 89 e4 04 00       mov    0x4e489(%ecx),%esi</span>
</span><span class='line'><span class="x">   5abb6:       8a 45 10                mov    0x10(%ebp),%al</span>
</span><span class='line'><span class="x">   5abb9:       8b 55 08                mov    0x8(%ebp),%edx</span>
</span><span class='line'><span class="x">   5abbc:       88 04 32                mov    %al,(%edx,%esi,1)</span>
</span><span class='line'><span class="x">   5abbf:       8b b1 d5 65 03 00       mov    0x365d5(%ecx),%esi</span>
</span><span class='line'><span class="x">   5abc5:       89 75 e0                mov    %esi,-0x20(%ebp)</span>
</span><span class='line'><span class="x">   5abc8:       c7 45 e4 00 00 00 42    movl   $0x42000000,-0x1c(%ebp)</span>
</span><span class='line'><span class="x">   5abcf:       c7 45 e8 00 00 00 00    movl   $0x0,-0x18(%ebp)</span>
</span><span class='line'><span class="x">   5abd6:       8d b1 50 00 00 00       lea    0x50(%ecx),%esi</span>
</span><span class='line'><span class="x">   5abdc:       89 75 ec                mov    %esi,-0x14(%ebp)</span>
</span><span class='line'><span class="x">   5abdf:       8d 89 c1 d9 04 00       lea    0x4d9c1(%ecx),%ecx</span>
</span><span class='line'><span class="x">   5abe5:       89 4d f0                mov    %ecx,-0x10(%ebp)</span>
</span><span class='line'><span class="x">   5abe8:       89 55 f4                mov    %edx,-0xc(%ebp)</span>
</span><span class='line'><span class="x">   5abeb:       88 45 f8                mov    %al,-0x8(%ebp)</span>
</span><span class='line'><span class="x">   5abee:       8d 45 e0                lea    -0x20(%ebp),%eax</span>
</span><span class='line'><span class="x">   5abf1:       89 04 24                mov    %eax,(%esp)</span>
</span><span class='line'><span class="x">   5abf4:       e8 d7 45 00 00          call   5f1d0 &lt;_WebThreadRun$stub&gt;</span>
</span><span class='line'><span class="x">   5abf9:       83 c4 24                add    $0x24,%esp</span>
</span><span class='line'><span class="x">   5abfc:       5e                      pop    %esi</span>
</span><span class='line'><span class="x">   5abfd:       5d                      pop    %ebp</span>
</span><span class='line'><span class="x">   5abfe:       c3                      ret    </span>
</span><span class='line'>
</span><span class='line'><span class="mh">0005abff</span> <span class="p">&lt;</span><span class="nf">___29-[ADWebView setWebGLEnabled:]_block_invoke_0</span><span class="p">&gt;:</span>
</span><span class='line'><span class="x">   5abff:       55                      push   %ebp</span>
</span><span class='line'><span class="x">   5ac00:       89 e5                   mov    %esp,%ebp</span>
</span><span class='line'><span class="x">   5ac02:       57                      push   %edi</span>
</span><span class='line'><span class="x">   5ac03:       56                      push   %esi</span>
</span><span class='line'><span class="x">   5ac04:       83 ec 10                sub    $0x10,%esp</span>
</span><span class='line'><span class="x">   5ac07:       e8 00 00 00 00          call   5ac0c &lt;___29-[ADWebView setWebGLEnabled:]_block_invoke_0+0xd&gt;</span>
</span><span class='line'><span class="x">   5ac0c:       5e                      pop    %esi</span>
</span><span class='line'><span class="x">   5ac0d:       8b 7d 08                mov    0x8(%ebp),%edi</span>
</span><span class='line'><span class="x">   5ac10:       8b 47 14                mov    0x14(%edi),%eax</span>
</span><span class='line'><span class="x">   5ac13:       8b 8e 54 66 04 00       mov    0x46654(%esi),%ecx</span>
</span><span class='line'><span class="x">   5ac19:       89 4c 24 04             mov    %ecx,0x4(%esp)</span>
</span><span class='line'><span class="x">   5ac1d:       89 04 24                mov    %eax,(%esp)</span>
</span><span class='line'><span class="x">   5ac20:       e8 a7 46 00 00          call   5f2cc &lt;_objc_msgSend$stub&gt;</span>
</span><span class='line'><span class="x">   5ac25:       8b 8e 50 66 04 00       mov    0x46650(%esi),%ecx</span>
</span><span class='line'><span class="x">   5ac2b:       89 4c 24 04             mov    %ecx,0x4(%esp)</span>
</span><span class='line'><span class="x">   5ac2f:       89 04 24                mov    %eax,(%esp)</span>
</span><span class='line'><span class="x">   5ac32:       e8 95 46 00 00          call   5f2cc &lt;_objc_msgSend$stub&gt;</span>
</span><span class='line'><span class="x">   5ac37:       0f be 57 18             movsbl 0x18(%edi),%edx</span>
</span><span class='line'><span class="x">   5ac3b:       8b 8e 94 6a 04 00       mov    0x46a94(%esi),%ecx</span>
</span><span class='line'><span class="x">   5ac41:       89 54 24 08             mov    %edx,0x8(%esp)</span>
</span><span class='line'><span class="x">   5ac45:       89 4c 24 04             mov    %ecx,0x4(%esp)</span>
</span><span class='line'><span class="x">   5ac49:       89 04 24                mov    %eax,(%esp)</span>
</span><span class='line'><span class="x">   5ac4c:       e8 7b 46 00 00          call   5f2cc &lt;_objc_msgSend$stub&gt;</span>
</span><span class='line'><span class="x">   5ac51:       83 c4 10                add    $0x10,%esp</span>
</span><span class='line'><span class="x">   5ac54:       5e                      pop    %esi</span>
</span><span class='line'><span class="x">   5ac55:       5f                      pop    %edi</span>
</span><span class='line'><span class="x">   5ac56:       5d                      pop    %ebp</span>
</span><span class='line'><span class="x">   5ac57:       c3                      ret    </span>
</span><span class='line'><span class="x">   5ac58:       0f 1f 84 00 00 00 00    nopl   0x0(%eax,%eax,1)</span>
</span><span class='line'><span class="x">   5ac5f:       00</span>
</span></code></pre></td></tr></table></div></figure>


<p>I won&#8217;t go into detail about how to read the disassembly, but hopefully you&#8217;ll be able to see that at <code>5abf4</code> we&#8217;re running a block of code on what seems to be the <code>UIWebView</code>&#8217;s dedicated web thread (<code>_WebThreadRun$stub</code>). The block itself seems to be making 3 consecutive Objective-C method calls (<code>_objc_msgSend$stub</code>) at <code>5ac20</code>, <code>5ac32</code> &amp; <code>5ac4c</code>.</p>

<p>By running the previous snippet where we were linking against the private <code>iAdCore</code> framework and using <code>ADWebView</code>, we can set a symbolic breakpoint on <code>___29-[ADWebView setWebGLEnabled:]_block_invoke_0</code> and see what the values of the <code>$eax</code> &amp; <code>$ecx</code> registers are prior to calling <code>objc_msgSend</code>. Look at the <a href="http://www.opensource.apple.com/source/objc4/objc4-493.9/runtime/Messengers.subproj/objc-msg-simulator-i386.s">i386 ABI for <code>objc_msgSend()</code></a>, and you&#8217;ll note that these registers correspond to the receiver (<code>$eax</code>) of the message and the selector (<code>$ecx</code>) being called.</p>

<p>Stepping through, we see:</p>

<ul>
<li>At <code>5ac20</code>, <code>$eax</code> is an instance of <code>ADWebView</code>, and <code>$ecx</code> is <code>_browserView</code>.</li>
<li>At <code>5ac32</code>, <code>$eax</code> is an instance of <code>UIWebDocumentView</code> and <code>$ecx</code> is <code>webView</code>.</li>
<li>At <code>5ac4c</code>, <code>$eax</code> is an instance of <code>WebView</code> and <code>$ecx</code> is <code>_setWebGLEnabled:</code>.</li>
</ul>


<p>From this, we can piece together our re-implementation of <code>-[ADWebView setWebGLEnabled:]</code>:</p>

<figure class='code'><figcaption><span>Re-implementation of -[ADWebView setWebGLEnabled:]</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='objective-c'><span class='line'><span class="p">-</span> <span class="p">(</span><span class="kt">void</span><span class="p">)</span><span class="nf">setWebGLEnabled:</span><span class="p">(</span><span class="kt">BOOL</span><span class="p">)</span><span class="nv">enableWebGL</span> <span class="p">{</span>
</span><span class='line'>  <span class="n">UIWebDocumentView</span><span class="o">*</span> <span class="n">webDocumentView</span> <span class="o">=</span> <span class="p">[</span><span class="nb">self</span> <span class="n">_browserView</span><span class="p">];</span>
</span><span class='line'>  <span class="n">WebView</span><span class="o">*</span> <span class="n">backingWebView</span> <span class="o">=</span> <span class="p">[</span><span class="n">webDocumentView</span> <span class="n">webView</span><span class="p">];</span>
</span><span class='line'>  <span class="p">[</span><span class="n">backingWebView</span> <span class="nl">_setWebGLEnabled</span><span class="p">:</span><span class="n">enableWebGL</span><span class="p">];</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>I&#8217;ve put together an Xcode project demoing the results of this, which you can <a href="https://github.com/atnan/UIWebViewWebGL">find on Github</a>.</p>

<h2>Summing Up</h2>

<p>Apple are clearly working towards supporting WebGL in a more general sense, as can be seen in their support for it in iAds.</p>

<p>Instead of whinging about it only being available in iAds, I&#8217;ve demonstrated that it&#8217;s possible to take advantage of WebGL using standard embedded web views (albeit using private APIs).</p>

<p>This will let developers track the progress of Apple&#8217;s commitment to WebGL, and skate to where the puck is going to be.</p>

<p>I&#8217;m really looking forward to seeing what you all come up with!</p>

<hr />


<p>Have something to say? <a href="http://news.ycombinator.com/item?id=3195128">Discuss on Hacker News</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Apple's App Store Submission Process & Java Verified]]></title>
    <link href="http://atnan.com/blog/2009/08/09/apples-app-store-submission-process-and-java-verified/"/>
    <updated>2009-08-09T20:29:00-07:00</updated>
    <id>http://atnan.com/blog/2009/08/09/apples-app-store-submission-process-and-java-verified</id>
    <content type="html"><![CDATA[<p>There&#8217;s a lot of discussion going on at the moment about Apple&#8217;s App Store submission process and the role that carriers play in vetting applications. When the App Store was announced, I naïvely believed that Apple had successfully cut out the carrier middleman responsible for crippling every other mobile development platform. Unfortunately, the carrier protectionist oligopoly lives on, albeit on a slightly smaller scale.</p>

<!--more-->


<p>But it&#8217;s not all doom and gloom. I see two major issues:</p>

<ol>
<li>Carriers are barring applications they deem disruptive to their business</li>
<li>The submissions process is completely opaque</li>
</ol>


<p>If history is anything to go by, the first issue is going to be very difficult to resolve directly. It&#8217;s the second issue I think we&#8217;re in a position to easily fix.</p>

<p>First, I think it would be productive to look at the J2ME platform.</p>

<p>One of the biggest issues that&#8217;s plagued J2ME has been greedy carriers standing in the way of developers trying to bring their applications to market (ring any bells?). To access run-of-the-mill features like the address book, networking or GPS APIs you need to sign your application. Problem is, certificates from well known CAs like Verisign are stripped from carrier-branded phones in favour of carrier issued certificates. Many carriers run their own developer program to facilitate code-signing of applications that will run on their network.</p>

<p>The industry&#8217;s &#8220;answer&#8221; to this problem was to come up with <a href="http://javaverified.com">Java Verified</a>, a process that allows developers to submit their applications to one of a handful of &#8220;Authorized Test Houses&#8221; and pay around $300USD to have it taken through a standard test procedure. If it passes, you get a signed application which will run on most carriers and devices. If it fails, you pay again for the privilege of having it retested. Also note that you&#8217;re paying to have your application tested on a specific device of your choosing, so if you&#8217;d like your application tested on multiple devices, you pay per device.</p>

<p>Disregarding the fact that the Java Verified process will leave you thousands of dollars poorer once you&#8217;ve released a few versions of your application to a handful of devices, it&#8217;s quite similar to Apple&#8217;s verification process. You submit your application, it gets tested according to a criteria that carriers are happy with, and if your application passes you&#8217;re good to go.</p>

<p><em>BUT</em>, there&#8217;s one minor difference; the Java Verified testing houses are all following the same open, standard test script. It&#8217;s called the <a href="http://javaverified.com/graphics/PDF/UTC_3_0_FINAL.pdf">Unified Testing Criteria (PDF)</a>, and it&#8217;s made available to developers so that they know how their applications are being scrutinised by the testers.</p>

<p>I think Java Verified&#8217;s Unified Testing Criteria would form a great basis for a similar document to be written for the App Store submission process. It would cover areas like:</p>

<ul>
<li>High-level APIs being used (GPS, address book etc.), how frequently they&#8217;re used, and whether or not they remove user data (address book entries etc.)</li>
<li>Remote content used in the application. Where does it come from? Is it interpreted and/or executed to change the behaviour of the application? Could it contain offensive content? Does the application&#8217;s rating take into account mature content?</li>
<li>Data usage over 3G, including a clear set of quantitative guidelines that take into account what carriers deem appropriate on their networks</li>
<li>Rights to publish content, either through ownership, licensing or fair use</li>
<li>Use of advertising</li>
<li>Whether or not behaviour, usage and metrics about the user are recorded</li>
<li>Stability, performance, memory, network and battery usage tests</li>
<li>Adherence to the Human Interface Guidelines (HIG)</li>
<li>Handling of memory warnings</li>
<li>Handling of registered URL schemes</li>
<li>Ability to run during a call or tethering</li>
<li>Ability to handle lack of network access or network delays</li>
<li>Appropriate use of the keychain for secure storage</li>
</ul>


<p>The document would likely take the form of a questionnaire, with a clear definition of pass/fail conditions for the various questions. If a developer filled out the questionnaire and received a clear pass but Apple&#8217;s testing produced a fail, the difference between their questionnaires would form the basis for productive communication to resolve the issues and allow for resubmission. The document would evolve over time, hopefully reaching a point where if you filled out the questionnaire yourself and got a pass, you&#8217;re almost guaranteed to get through the submission process.</p>

<p>I really think this would make a world of difference, and wouldn&#8217;t require any drastic changes for Apple other than a little bit more open documentation of the existing process.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[My Feed URLs Have Changed]]></title>
    <link href="http://atnan.com/blog/2009/07/29/my-feed-urls-have-changed/"/>
    <updated>2009-07-29T14:00:00-07:00</updated>
    <id>http://atnan.com/blog/2009/07/29/my-feed-urls-have-changed</id>
    <content type="html"><![CDATA[<p>With Google&#8217;s acquisition of Feedburner, I&#8217;ve been locked out of my Feedburner account. Since Google doesn&#8217;t seem to be providing any level of support for the relocation process, I&#8217;ve been forced to recreate my feeds. If you&#8217;re subscribed to the article feed (<a href="http://feeds.feedburner.com/atnan">http://feeds.feedburner.com/atnan</a>) or comments feed (<a href="http://feeds.feedburner.com/atnan-comments">http://feeds.feedburner.com/atnan-comments</a>), you should point your feed reader to these new feed URLs:</p>

<ul>
<li><a href="http://feeds.feedburner.com/atnan-articles">http://feeds.feedburner.com/atnan-articles</a></li>
<li><a href="http://feeds.feedburner.com/atnan-all-comments">http://feeds.feedburner.com/atnan-all-comments</a></li>
</ul>


<p>Sorry for any inconvenience &#8211; I know I&#8217;ve found it a bit of a pain when other blogs have changed their feed URLs on me!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Enabling Verbose Push Notification Service (APNS) Logs]]></title>
    <link href="http://atnan.com/blog/2009/07/27/enabling-verbose-push-notification-service-apns-logs/"/>
    <updated>2009-07-27T23:19:00-07:00</updated>
    <id>http://atnan.com/blog/2009/07/27/enabling-verbose-push-notification-service-apns-logs</id>
    <content type="html"><![CDATA[<p>Those of you who are developing iPhone applications that utilise Apple&#8217;s Push Notification Service (APNS) will understand that sometimes it feels like a bit of a black hole. Fortunately, Matt Drance (Apple&#8217;s Application Frameworks Evangelist) has made a device configuration profile available which enables verbose logging in &#8220;apsd&#8221;, the daemon that runs on devices and is responsible for connecting to the APNS servers and retrieving push notifications.</p>

<!--more-->


<p>You can grab a copy of the configuration profile <a href="http://atnan.com/downloads/APNsLogging.mobileconfig">directly from my site</a>, or by visiting the <a href="https://devforums.apple.com/message/58759">original thread</a> Matt attached the file to on Apple&#8217;s developer forums.</p>

<p>To install the profile on your device, you can point Mobile&nbsp;Safari directly at the file on my site, email the file to your device, or install it via the iPhone Configuration Utility. For those of you who are unfamiliar with <code>*.mobileconfig</code> files, you should read Apple&#8217;s <a href="http://manuals.info.apple.com/en_US/Enterprise_Deployment_Guide.pdf">Enterprise Deployment Guide</a> which provides much more detailed instructions.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Running Two or More Versions of Xcode for Stable/Beta iPhone Development]]></title>
    <link href="http://atnan.com/blog/2009/07/10/running-two-or-more-versions-of-xcode-for-stable-beta-iphone-development/"/>
    <updated>2009-07-10T15:14:00-07:00</updated>
    <id>http://atnan.com/blog/2009/07/10/running-two-or-more-versions-of-xcode-for-stable-beta-iphone-development</id>
    <content type="html"><![CDATA[<p>This is a simple but useful tip for people like myself who want to stay up to date with the latest beta releases of the iPhone SDK, but who also rely on having a stable version of the SDK installed for things like deploying to the App Store, reproducing bugs from in-the-wild, or client work that doesn&#8217;t take advantage of any new SDK features.</p>

<!--more-->


<p>The first time I grabbed a beta version of the SDK, all I did was hit the install button and let it do its thing. However, if you don&#8217;t change any of the default install settings, you&#8217;ll quickly find that the beta SDK has been installed straight over the top of your stable version of the SDK.</p>

<p>The solution is to install two copies of Xcode and the SDK; the stable version goes in <code>/Developer</code>, and the beta version goes in <code>/Developer-Beta</code>.</p>

<p>If you&#8217;ve already installed a beta version of the SDK in <code>/Developer</code>, you&#8217;ll need to remove it. To do this, you should run the following from the command line:</p>

<pre><code>$ sudo /Developer/Library/uninstall-devtools --mode=all
</code></pre>

<p>You can then proceed to install the stable SDK in <code>/Developer</code> and the beta in <code>/Developer Beta</code>. If you ever need to blow away your beta copy of Xcode and the SDK, you should run the same command as above but from the beta directory instead:</p>

<pre><code>$ sudo /Developer Beta/Library/uninstall-devtools --mode=all
</code></pre>

<p>Finally, to launch Xcode with the stable SDK you run <code>/Developer/Applications/Xcode.app</code> and to launch Xcode with the beta SDK, run <code>/Developer-Beta/Applications/Xcode.app</code>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Configuring Multiple CalDAV/Google Calendars on iOS 3.0]]></title>
    <link href="http://atnan.com/blog/2009/06/19/configuring-multiple-caldav-google-calendars-on-ios-3-dot-0/"/>
    <updated>2009-06-19T13:03:00-07:00</updated>
    <id>http://atnan.com/blog/2009/06/19/configuring-multiple-caldav-google-calendars-on-ios-3-dot-0</id>
    <content type="html"><![CDATA[<p>One of the cool features of Leopard was the addition of CalDAV support to iCal, which allows you to read/write/edit/delete calendars hosted by third parties like Google Calendar. Similar functionality was available on the iPhone, but only via Apple&#8217;s MobileMe service. That&#8217;s changed with iPhone OS 3.0.</p>

<p>If you&#8217;ve configured a bunch of CalDAV calendars in iCal, unfortunately they&#8217;re synced to the iPhone as read-only calendars which is a real pain. In lieu of a fix by Apple, we&#8217;ll need to remove the iCal CalDAV accounts from the iTunes calendar sync list, and configure them on the iPhone itself.</p>

<p>To set up a new CalDAV account, you&#8217;ll need to navigate through the following screens on your iPhone:</p>

<p><code>Settings</code> → <code>Mail, Contacts, Calendars</code> → <code>Add Account...</code> → <code>Other</code> → <code>Add CalDAV Account...</code></p>

<p>Once you&#8217;re there, you&#8217;ll be presented with a dialogue that lets you enter a CalDAV server, username, password and description. This dialogue is incredibly misleading, because the &#8220;server&#8221; field will not only accept a hostname like &#8220;www.google.com&#8221;, but also a full CalDAV URL like <code>https://www.google.com/calendar/dav/&lt;CALENDAR_ID&gt;/user</code>. If you&#8217;re using Google Calendar with only one calendar, enter your Google Calendar credentials like the following example:</p>

<p><img class="center" src="http://atnan.com/downloads/Standard_Google_Account.png"></p>

<p>If you&#8217;ve got multiple CalDAV calendars, it starts to get a little bit hairier. Initially, I emailed myself a list of my CalDAV URLs (4 in total) and used the new copy-paste features to manually configure each account using the previous instructions, only instead of using &#8220;www.google.com&#8221; in the server field, I pasted the entire CalDAV URL instead. As you can imagine, this is incredibly tedious.</p>

<p>Fortunately Apple also released a new version of the iPhone Configuration Utility (ICU), which is a really handy tool for creating iPhone configuration bundles for deployment in enterprise environments. Among other things, this new version allows you to configure CalDAV accounts. If you haven&#8217;t already, you should grab a copy of ICU <a href="http://support.apple.com/downloads/iPhone_Configuration_Utility_2_0_for_Mac_OS_X">for Mac OS X</a> or <a href="http://support.apple.com/downloads/iPhone_Configuration_Utility_2_0_for_Windows">Windows</a>.</p>

<p>Launch ICU, create a new configuration profile, and open the CalDAV pane. For each CalDAV calendar you want to configure, you&#8217;re going to want to fill it in like this:</p>

<p><img class="center" src="http://atnan.com/downloads/iPhone_Configuration_Utility.png"></p>

<p>If you&#8217;re looking at the Principal URL field and wondering what <CAL_ID> is, you&#8217;ll find it in the calendar settings page of Google Calendar under Calendar Address (it should look like an email address).</p>

<p>Once you&#8217;ve entered all your CalDAV accounts, plug in your iPhone, select it in ICU and open the Configuration Profiles tab. You should see the configuration profile you just created, with an &#8220;Install&#8221; button next to it. Hit the &#8220;Install&#8221; button.</p>

<p>You iPhone should show a screen like this:</p>

<p><img class="center" src="http://atnan.com/downloads/Install_Profile.png"></p>

<p>If you hit &#8220;More Details&#8221;, you&#8217;ll see the CalDAV calendars listed:</p>

<p><img class="center" src="http://atnan.com/downloads/Install_Profile_More_Details.png"></p>

<p>Hit &#8220;Install&#8221;, confirm, and open up the Calendar App to see if everything works as expected. You should be able to create, edit and delete calendar entries in your CalDAV accounts, and have them update in iCal / Google Calendar. If you ever want to add a new CalDAV calendar, I think you need to remove the configuration via the iPhone Configuration Utility and re-install the edited configuration bundle.</p>

<p>Hopefully it doesn&#8217;t take too long for Apple to make the CalDAV integration between iCal and the iPhone more seamless.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Enabling Internet Tethering via Optus/Virgin/Vodafone/Telstra on iOS 3.0]]></title>
    <link href="http://atnan.com/blog/2009/04/04/enabling-internet-tethering-via-optus-virgin-vodafone-telstra-on-ios-3-dot-0/"/>
    <updated>2009-04-04T18:21:00-07:00</updated>
    <id>http://atnan.com/blog/2009/04/04/enabling-internet-tethering-via-optus-virgin-vodafone-telstra-on-ios-3-dot-0</id>
    <content type="html"><![CDATA[<p><strong>UPDATE:</strong> Due to changes in the public release of iTunes 8.2, you will now need to quit iTunes and run a command in your Terminal before proceeding with the instructions below. The command is: &#8220;defaults write com.apple.iTunes carrier-testing -bool TRUE&#8221;.</p>

<p><strong>UPDATE:</strong> I&#8217;ve downloaded the Telstra and Vodafone bundles and made similar modifications, so they&#8217;re now available in the guide. If you&#8217;re using Telstra/Vodafone and my modified settings bundles work, please let me know in the comments as I&#8217;m unable to test it myself.</p>

<p>The following instructions are intended for members of the <a href="http://developer.apple.com/">Apple Developer Connection</a> (ADC), running an iPhone with a developer version of the iPhone OS 3.0 software. This guide also only provides Australian carrier settings for Telstra, Vodafone and Optus (plus resellers like Virgin), but if you follow the link to Crunchgear in the first step there are instructions on downloading and modifying the carrier setting bundles.</p>

<ol>
<li>Download <a href="http://atnan.com/downloads/Telstra_au.ipcc.zip">Telstra_au.ipcc</a>, <a href="http://atnan.com/downloads/Vodafone_au.ipcc.zip">Vodafone_au.ipcc</a> or <a href="http://atnan.com/downloads/Optus_au.ipcc.zip">Optus_au.ipcc</a>, which were created as per the <a href="http://www.crunchgear.com/2009/03/19/how-to-enable-tethering-under-iphone-firmware-30/">AT&amp;T instructions on Crunchgear</a> (note that the file should have an &#8220;.ipcc&#8221; extension, not &#8220;.zip&#8221;. If your downloaded file has a &#8220;.zip&#8221; extension, unzip it to produce a &#8220;Carrier_au.ipcc&#8221; file)</li>
<li>Open iTunes</li>
<li>Plug in your iPhone</li>
<li>Select you iPhone under devices</li>
<li>In the Summary tab, ⌥-click (option-click) the &#8220;Check for Update&#8221; button</li>
<li>Select the previously downloaded <code>Telstra_au.ipcc</code>, <code>Vodafone_au.ipcc</code> or <code>Optus_au.ipcc</code> file and click &#8220;Open&#8221;</li>
<li>Once the settings have been copied, disconnect your iPhone</li>
<li>Restart your iPhone</li>
<li>Open the Settings application on your iPhone, and navigate to General, then Network, and finally Internet Tethering</li>
<li>Turn Internet Tethering on. At this point, tethering is now possible via USB when your iPhone is plugged in. If you&#8217;d like to use Bluetooth, continue reading</li>
<li>You will be prompted to turn bluetooth on if it&#8217;s not on already. Select yes if prompted</li>
<li>On your laptop, turn on bluetooth and open the Bluetooth Preference pane</li>
<li>Click &#8220;Set Up New Device&#8230;&#8221;, which will open the Bluetooth Setup Assistant</li>
<li>Select &#8220;Mobile Phone&#8221; as the Device Type</li>
<li>Select your iPhone from the device list</li>
<li>A number should appear on your laptop, and your iPhone should prompt you for a pin</li>
<li>Enter the pin from your laptop into your iPhone</li>
<li>Once paired, make sure you keep &#8220;Use device as network port&#8221; selected</li>
<li>In the Bluetooth Preference Pane, make sure &#8220;Show Bluetooth status in the menu bar&#8221; is selected, since it makes things easier for starting and stopping tethering</li>
<li>Click the Bluetooth icon in your status bar, where you should now see your iPhone under devices</li>
<li>Click on the menu item for your device, and select &#8220;Connect to Network&#8221;</li>
<li>On your iPhone, you should now notice that the top of the screen has a blue bar titled &#8220;Internet Tethering&#8221;</li>
<li>You can now use the Internet!</li>
<li>As an optional extra, you can open Network Preferences and rename the two new network devices to &#8220;iPhone USB&#8221; and &#8220;iPhone Bluetooth&#8221;</li>
</ol>


<p>Not really a difficult process, but it can be a bit fiddly. Downloading my preconfigured files also saves mucking around in Property List Editor, which most people will attest is a bit of a pain.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA["Chunked" Transfer-Encoding Support in Apache/Passenger]]></title>
    <link href="http://atnan.com/blog/2009/04/04/chunked-transfer-encoding-support-in-apache-passenger/"/>
    <updated>2009-04-04T15:53:00-07:00</updated>
    <id>http://atnan.com/blog/2009/04/04/chunked-transfer-encoding-support-in-apache-passenger</id>
    <content type="html"><![CDATA[<p>I wrote an article last year about <a href="http://atnan.com/blog/2008/08/08/transfer-encoding-chunked-or-chunky-http/">the lack of Apache support for HTTP requests with the &#8220;Transfer-Encoding: chunked&#8221;</a>. Of course, this problem really only affects those of us who use Apache modules that were developed against the Apache 1.3 API (pre-HTTP 1.1). One such module was <a href="http://www.modrails.com">Phusion Passenger</a> — also known as <code>mod_rails</code> — which I was using at the time to provide a web service to J2ME MIDlets and an iPhone application (among other things). To get around the lack of support, I presented a solution involving the use of <code>mod_proxy</code> to buffer the chunked request and rewrite it as a new request before passing it to the non-HTTP 1.1 compliant backend.</p>

<p>Thankfully as of two days ago, that hack is no longer required if you&#8217;re using Passenger.</p>

<p>Hongli Lai (the lead developer of Phusion Passenger) has <a href="http://github.com/FooBarWidget/passenger/commit/5038157db90d2cd12c65d29154774c98a9e6a0b7">checked in a change</a> that enables support for chunked transfer-encoding, which means no more dreaded <code>HTTP/1.1 411
Length Required</code> responses. So the fix is checked into the tree, and <a href="http://code.google.com/p/phusion-passenger/issues/detail?id=114">according to the bug report</a> will be made available in the next release of the Passenger gem — version 2.1.4.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Configuring Apache to accept chunked HTTP requests from J2ME (CLDC and MIDP)]]></title>
    <link href="http://atnan.com/blog/2008/11/28/configuring-apache-to-accept-chunked-http-requests-from-j2me-cldc-and-midp/"/>
    <updated>2008-11-28T22:25:00-08:00</updated>
    <id>http://atnan.com/blog/2008/11/28/configuring-apache-to-accept-chunked-http-requests-from-j2me-cldc-and-midp</id>
    <content type="html"><![CDATA[<p>A few months ago, I <a href="http://atnan.com/blog/2008/08/08/transfer-encoding-chunked-or-chunky-http/">wrote an article</a> describing a solution for accepting chunked HTTP requests made by J2ME devices to non-HTTP 1.1 compliant servers unable to accept such requests (Mongrel, Lighttpd, Nginx etc.).</p>

<p>One of the commenters was concerned that J2ME developers suffering from this problem might find it difficult to find my article since I didn&#8217;t really mention J2ME MIDlets much at all. So, if you&#8217;re a J2ME developer suffering from problems like those described <a href="http://forums.sun.com/thread.jspa?threadID=5326661">here</a>, <a href="http://www.ruby-forum.com/topic/142852">here</a> or <a href="http://forums.sun.com/thread.jspa?threadID=5251115">here</a>&#8230;check out the <a href="http://atnan.com/blog/2008/08/08/transfer-encoding-chunked-or-chunky-http/">original article</a> for a simple solution.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Issues with CoreFoundation chunked requests (iPhoneOS 2.x / OS 10.5.x) and Apache / mod_proxy]]></title>
    <link href="http://atnan.com/blog/2008/11/28/issues-with-corefoundation-chunked-requests-and-Apache-mod_proxy/"/>
    <updated>2008-11-28T22:06:00-08:00</updated>
    <id>http://atnan.com/blog/2008/11/28/issues-with-corefoundation-chunked-requests-and-Apache-mod_proxy</id>
    <content type="html"><![CDATA[<p>A comment was made in <a href="http://atnan.com/blog/2008/10/16/memory-issues-with-nsmutableurlrequests-sethttpbody-method-in-iphoneos-2-dot-1/">my previous article</a>, stating that the &#8220;c&#8221; of &#8220;chunked&#8221; in the <code>Transfer-Encoding: chunked</code> header is similarly capitalised in Mac OS 10.5.5, which means that the flaw in Apache&#8217;s <code>mod_proxy</code> is exposed by more than just the iPhone.</p>

<p>So if you&#8217;re trying to do chunked HTTP POST requests using the CFNetwork stack, make sure your Apache configuration can deal with the chunked header:</p>

<pre><code>RequestHeader edit Transfer-Encoding Chunked chunked early
</code></pre>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Memory issues with NSMutableURLRequest's setHTTPBody: method in iPhoneOS 2.1]]></title>
    <link href="http://atnan.com/blog/2008/10/16/memory-issues-with-nsmutableurlrequests-sethttpbody-method-in-iphoneos-2-dot-1/"/>
    <updated>2008-10-16T20:04:00-07:00</updated>
    <id>http://atnan.com/blog/2008/10/16/memory-issues-with-nsmutableurlrequests-sethttpbody-method-in-iphoneos-2-dot-1</id>
    <content type="html"><![CDATA[<p>The iPhone developers at my work have been tearing their hair out over the last few days, trying to resolve the last few memory issues in our iPhone application before we send it off for approval by Apple. One of the problem areas they&#8217;ve noticed is when a photo is uploaded to our service via HTTP POST (both from the camera and otherwise).</p>

<p>Not sure who had the bright idea, but one of the developers decided to try passing in the HTTP body as an <code>NSInputStream</code> (via <code>-[NSMutableURLRequest setHTTPBodyStream:]</code>), rather than as <code>NSMutableData</code> (via <code>-[NSMutableURLRequest setHTTPBody:]</code>). Magically, this seems to have solved the memory leak issues.</p>

<p>Unfortunately, it created another issue.</p>

<p>You might remember that 3 months ago I <a href="http://atnan.com/blog/2008/08/08/transfer-encoding-chunked-or-chunky-http/">wrote an article</a> on how much of a pain in the arse it was to accept HTTP POST requests from user agents specifying a <code>Transfer-Encoding</code> HTTP header value of <code>chunked</code> (resulting in a POST request with no <code>Content-Length</code> header). In that article, I proposed a solution using Apache 2 and <a href="http://httpd.apache.org/docs/2.0/mod/mod_proxy.html">mod_proxy</a>&#8217;s <code>proxy-sendcl</code> option to get things working again. This worked fine for our J2ME clients, but when our iPhone application started blowing chunks at us, our server crapped out with the dreaded 500 error I thought I&#8217;d fixed for good:</p>

<pre><code>Chunked Transfer-Encoding is not supported
</code></pre>

<p>After whipping out <a href="http://www.wireshark.org">Wireshark</a>, we realised that there was a tiny difference between between what our J2ME client was doing and what the iPhone was doing.</p>

<p>This is the header the J2ME app was sending:</p>

<pre><code>Transfer-Encoding: chunked
</code></pre>

<p>And this is the header the iPhone was sending:</p>

<pre><code>Transfer-Encoding: Chunked
</code></pre>

<p>As much as I&#8217;d like to think the different casing of <code>chunked</code> and <code>Chunked</code> wouldn&#8217;t affect the behaviour of <a href="http://httpd.apache.org/docs/2.0/mod/mod_proxy.html">mod_proxy</a>, it seems it does. Fortunately, we can work around this problem too by using Apache&#8217;s <a href="http://httpd.apache.org/docs/2.0/mod/mod_headers.html">mod_headers</a> module. This allows us to do the following:</p>

<pre><code>RequestHeader edit Transfer-Encoding Chunked chunked early
</code></pre>

<p>When combined with the solution from my previous article, this leaves us with the following complete solution:</p>

<figure class='code'><figcaption><span>Apache configuration to reconstitute &#8220;chunked&#8221; HTTP requests</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
</pre></td><td class='code'><pre><code class='text'><span class='line'>ProxyRequests Off
</span><span class='line'>
</span><span class='line'>&lt;Proxy http://localhost:81&gt;
</span><span class='line'>  Order deny,allow
</span><span class='line'>  Allow from all
</span><span class='line'>&lt;/Proxy&gt;
</span><span class='line'>
</span><span class='line'>Listen 80
</span><span class='line'>
</span><span class='line'>&lt;VirtualHost *:80&gt;
</span><span class='line'>
</span><span class='line'>  RequestHeader edit Transfer-Encoding Chunked chunked early
</span><span class='line'>
</span><span class='line'>  SetEnv proxy-sendcl 1
</span><span class='line'>  ProxyPass / http://localhost:81/
</span><span class='line'>  ProxyPassReverse / http://localhost:81/
</span><span class='line'>  ProxyPreserveHost On
</span><span class='line'>  ProxyVia Full
</span><span class='line'>
</span><span class='line'>  &lt;Directory proxy:*&gt;
</span><span class='line'>    Order deny,allow
</span><span class='line'>    Allow from all
</span><span class='line'>  &lt;/Directory&gt;
</span><span class='line'>
</span><span class='line'>&lt;/VirtualHost&gt;
</span><span class='line'>
</span><span class='line'>Listen 81
</span><span class='line'>
</span><span class='line'>&lt;VirtualHost *:81&gt;
</span><span class='line'>  ServerName ooboontoo
</span><span class='line'>  DocumentRoot /path/to/my/rails/root/public
</span><span class='line'>  RailsEnv development
</span><span class='line'>&lt;/VirtualHost&gt;
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA["Transfer-Encoding: chunked", or, Chunky HTPP!]]></title>
    <link href="http://atnan.com/blog/2008/08/08/transfer-encoding-chunked-or-chunky-http/"/>
    <updated>2008-08-08T11:44:00-07:00</updated>
    <id>http://atnan.com/blog/2008/08/08/transfer-encoding-chunked-or-chunky-http</id>
    <content type="html"><![CDATA[<p>Providing a web service for a bunch of browsers is a relatively straightforward affair. It&#8217;s really only once you jump out of the back-end and into the front-end side of things where issues like browser incompatibilities start to become a problem. Thankfully, I feel like I&#8217;m in the position where I think I&#8217;ve got my head wrapped around what&#8217;s involved in providing solutions to these problems.</p>

<p>And then mobile phones came along.</p>

<p>The service I&#8217;m working on at the moment is consumed by a bunch of clients, including but not limited to web browsers, WAP browsers, the Flash player, iPhones, J2ME devices. It&#8217;s the last one that&#8217;s causing headaches at the moment.</p>

<p>You see, despite the fact that HTTP/1.1 is about 9 years old, not all web servers support the features that were introduced. The particular one I&#8217;m talking about is <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1">chunked tranfer encoding</a>, but I&#8217;m sure there are many others.</p>

<p>To give you a general idea, the HTTP implementations on many mobile handsets will decide to use a chunked transfer encoding if the payload of a PUT/POST request is over an arbitrary threshold. This causes issues with servers like <a href="http://nginx.net">Nginx</a>, <a href="http://www.lighttpd.net">Lighttpd</a>, <a href="http://mongrel.rubyforge.org%22>Mongrel&#8221;>Mongrel</a> and <a href="http://code.macournoyer.com/thin">Thin</a>, since most of those assume that an incoming HTTP request with a payload will also include a <code>Content-Length</code> header.</p>

<p>Well guess what? As of 9 years ago, that hasn&#8217;t been the case.</p>

<p><img class="center" src="http://atnan.com/downloads/chunky_bacon.png"></p>

<p>Take a look at this request:</p>

<figure class='code'><figcaption><span>HTTP request specifying &#8220;chunked&#8221; transfer encoding</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='text'><span class='line'>POST /search.json HTTP/1.1
</span><span class='line'>User-Agent: curl/7.16.4 (i486-pc-linux-gnu) libcurl/7.16.4 OpenSSL/0.9.8e zlib/1.2.3.3 libidn/1.0
</span><span class='line'>Host: ooboontoo
</span><span class='line'>Accept: */*
</span><span class='line'>Transfer-Encoding: chunked
</span><span class='line'>Content-Type: multipart/form-data; boundary=----------------------------ab5090ac7869
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>92
</span><span class='line'>------------------------------ab5090ac7869
</span><span class='line'>Content-Disposition: form-data; name=&quot;query&quot;
</span><span class='line'>
</span><span class='line'>zoooom
</span><span class='line'>------------------------------ab5090ac7869--
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>0
</span></code></pre></td></tr></table></div></figure>


<p>Notice anything? If not, try and find a <code>Content-Length</code> header. Pre-HTTP/1.1 you&#8217;d expect to get an <code>HTTP 411</code> error (length required), but after HTTP/1.1 it&#8217;s pretty clear what the HTTP/1.1 applications are obliged to do:</p>

<blockquote><p>All HTTP/1.1 applications that receive entities MUST accept the &#8220;chunked&#8221; transfer-coding (section 3.6), thus allowing this mechanism to be used for messages when the message length cannot be determined in advance.</p><footer><strong>Fielding, et al.</strong> <cite><a href='http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1'>Internet RFC 2616 HTTP/1.1: Protocol Parameters</a></cite></footer></blockquote>


<p>That&#8217;s why I find it so surprising that hacks are involved in allowing mobile clients to POST/PUT to what I&#8217;d traditionally thought of as HTTP/1.1 compliant web servers.</p>

<p>But anyway, you want to see the solution right?</p>

<p>Well, our initial solution involved <a href="http://geraldkaszuba.com" rel="friend met co-worker colleague">Gerald Kaszuba</a> writing a little web server in Python which went by the name of &#8220;Dechunker&#8221;. You can imagine what it did, but we quickly found that while it was the simplest way to avoid the problem, it also meant that over time we would end up needing to implement the functionality that was already available in most other web servers. Servers like <a href="http://httpd.apache.org">Apache2</a> and <a href="http://www.lighttpd.net">Lighttpd</a> have become incredibly hardened over the years, and we&#8217;re not going to achieve that overnight.</p>

<p>So I then took another look at <a href="http://httpd.apache.org">Apache2</a>, knowing that some modules do support chunked transfer encoding while others don&#8217;t. What I discovered was that Apache&#8217;s <a href="http://httpd.apache.org/docs/2.0/mod/mod_proxy.html">mod_proxy</a> module could be used in front of anything that doesn&#8217;t support chunked encoding, since it can be configured to &#8220;dechunk&#8221; requests before passing them to a backend.</p>

<p>It looks a little something like this:</p>

<figure class='code'><figcaption><span>Apache configuration to reconstitute &#8220;chunked&#8221; HTTP requests</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
</pre></td><td class='code'><pre><code class='text'><span class='line'>ProxyRequests Off
</span><span class='line'>
</span><span class='line'>&lt;Proxy http://localhost:81&gt;
</span><span class='line'>  Order deny,allow
</span><span class='line'>  Allow from all
</span><span class='line'>&lt;/Proxy&gt;
</span><span class='line'>
</span><span class='line'>&lt;VirtualHost *:80&gt;
</span><span class='line'>  SetEnv proxy-sendcl 1
</span><span class='line'>  ProxyPass / http://localhost:81/
</span><span class='line'>  ProxyPassReverse / http://localhost:81/
</span><span class='line'>  ProxyPreserveHost On
</span><span class='line'>  ProxyVia Full
</span><span class='line'>
</span><span class='line'>  &lt;Directory proxy:*&gt;
</span><span class='line'>    Order deny,allow
</span><span class='line'>    Allow from all
</span><span class='line'>  &lt;/Directory&gt;
</span><span class='line'>
</span><span class='line'>&lt;/VirtualHost&gt;
</span><span class='line'>
</span><span class='line'>Listen 81
</span><span class='line'>
</span><span class='line'>&lt;VirtualHost *:81&gt;
</span><span class='line'>  ServerName ooboontoo
</span><span class='line'>  DocumentRoot /path/to/my/rails/root/public
</span><span class='line'>  RailsEnv development
</span><span class='line'>&lt;/VirtualHost&gt;
</span></code></pre></td></tr></table></div></figure>


<p>As you can see I&#8217;ve got <a href="http://httpd.apache.org">Apache2</a> listening on port 80, which uses the <code>proxy-sendcl</code> environment variable available in <a href="http://httpd.apache.org/docs/2.0/mod/mod_proxy.html">mod_proxy</a> to repack the HTTP body and add a <code>Content-Length</code> header to the request. This request is then passed back to a virtual host running on port 81, which is configured to use <a href="http://www.modrails.com">Phusion Passenger</a>.</p>

<p>Turns out it&#8217;s pretty simple, and from what I&#8217;ve seen there haven&#8217;t been any negative performance impacts by proxying all requests. It&#8217;s not a permanent solution, and as soon as <a href="http://www.modrails.com">Phusion Passenger</a> fixes the <a href="http://code.google.com/p/phusion-passenger/issues/detail?id=114">chunked encoding bug</a>, I&#8217;ll drop <a href="http://httpd.apache.org/docs/2.0/mod/mod_proxy.html">mod_proxy</a> from our configuration.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[ActiveRecord Model Serialisation]]></title>
    <link href="http://atnan.com/blog/2008/04/08/activerecord-model-serialisation/"/>
    <updated>2008-04-08T15:35:00-07:00</updated>
    <id>http://atnan.com/blog/2008/04/08/activerecord-model-serialisation</id>
    <content type="html"><![CDATA[<p>I&#8217;ve been working on a JSON API for mobile clients recently, and in doing so I&#8217;ve realised how much you need to repeat serialisation options throughout Rails applications despite options generally being model specific.</p>

<p>This little patch solves that problem by allowing you to decorate your Rails models with model-wide serialisation options, like so:</p>

<figure class='code'><figcaption><span>ActiveRecord model with class-level serialisation options defined</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">Article</span> <span class="o">&lt;</span> <span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span>
</span><span class='line'>  <span class="n">has_many</span> <span class="ss">:comments</span>
</span><span class='line'>  <span class="n">serialization_options</span> <span class="ss">:include</span> <span class="o">=&gt;</span> <span class="ss">:comments</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This means that whenever you call <code>to_json</code> or <code>to_xml</code> on an instance of <code>Article</code>, you&#8217;ll get the comment association thrown in for you. You&#8217;ll find you can clean up your Controllers and remove explicit calling of <code>to_json</code>, which previously would have looked like this:</p>

<figure class='code'><figcaption><span>Defining serialisation options every time to_json is called</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">respond_to</span> <span class="k">do</span> <span class="o">|</span><span class="nb">format</span><span class="o">|</span>
</span><span class='line'>  <span class="nb">format</span><span class="o">.</span><span class="n">json</span> <span class="ss">:json</span> <span class="o">=&gt;</span> <span class="vi">@article</span><span class="o">.</span><span class="n">to_json</span> <span class="ss">:include</span> <span class="o">=&gt;</span> <span class="ss">:comments</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>But can now be change to this:</p>

<figure class='code'><figcaption><span>No longer any need to specify the options</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">respond_to</span> <span class="k">do</span> <span class="o">|</span><span class="nb">format</span><span class="o">|</span>
</span><span class='line'>  <span class="nb">format</span><span class="o">.</span><span class="n">json</span> <span class="ss">:json</span> <span class="o">=&gt;</span> <span class="vi">@article</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>While it&#8217;s very simple, some people might find it useful. If you do, chuck this in your <code>/lib</code> directory and require it in <code>RAILS_ROOT/config/environment.rb</code>.</p>

<figure class='code'><figcaption><span>Allow class-level definition of serialisation options</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">module</span> <span class="nn">SerializationOptions</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">serialization_options</span><span class="p">(</span><span class="n">options</span> <span class="o">=</span> <span class="p">{})</span>
</span><span class='line'>    <span class="n">class_inheritable_accessor</span> <span class="ss">:serialization_options</span>
</span><span class='line'>    <span class="nb">self</span><span class="o">.</span><span class="n">serialization_options</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">dup</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:extend</span><span class="p">,</span> <span class="no">SerializationOptions</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ActiveRecord</span><span class="o">::</span><span class="no">Serialization</span><span class="o">::</span><span class="no">Serializer</span>
</span><span class='line'>  <span class="n">alias_method</span> <span class="ss">:old_initialize</span><span class="p">,</span> <span class="ss">:initialize</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">record</span><span class="p">,</span> <span class="n">options</span> <span class="o">=</span> <span class="p">{})</span>
</span><span class='line'>    <span class="k">if</span> <span class="n">record</span><span class="o">.</span><span class="n">respond_to?</span> <span class="ss">:serialization_options</span>
</span><span class='line'>      <span class="n">options</span> <span class="o">=</span> <span class="n">record</span><span class="o">.</span><span class="n">serialization_options</span><span class="o">.</span><span class="n">merge</span><span class="p">(</span><span class="n">options</span><span class="p">)</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>    <span class="n">old_initialize</span><span class="p">(</span><span class="n">record</span><span class="p">,</span> <span class="n">options</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Andy Clarke Announces the "CSS Eleven" at Web Directions South 2007]]></title>
    <link href="http://atnan.com/blog/2007/09/27/andy-clarke-announces-the-css-eleven-wd07/"/>
    <updated>2007-09-27T13:42:00-07:00</updated>
    <id>http://atnan.com/blog/2007/09/27/andy-clarke-announces-the-css-eleven-wd07</id>
    <content type="html"><![CDATA[<p>The opening session at Web Directions South was given to Andy Clarke, who proceeded to wrap it up with an announcement of a group put together to tackle the recent issues regarding submission of proposals and recommendations to the W3C. The eleven involved are:</p>

<ul>
<li>Cameron Adams</li>
<li>Jina Bolton</li>
<li>Mark Boulton</li>
<li>Dan Cederholm</li>
<li>Andy Clarke</li>
<li>Jeff Croft</li>
<li>Aaron Gustafson</li>
<li>Jon Hicks</li>
<li>Roger Johansson</li>
<li>Richard Rutter</li>
<li>Jonathon Snook</li>
</ul>


<p>From what was explained, their aim is to work through the CSS specifications and give feedback and examples for some of the more difficult issues, and then provide a body of work to the W3C and/or browser vendors with the hope that it things along a little faster than is currently the case. More details are sure to appear on the <a href="http://www.csseleven.com/">CSS Eleven</a> website.</p>

<p>Here&#8217;s a snap of his slide:</p>

<p><img class="center" src="http://atnan.com/downloads/CSS-Eleven-Announcement.jpg"></p>
]]></content>
  </entry>
  
</feed>
