<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.4.5">Jekyll</generator><link href="https://alastaircoote.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://alastaircoote.github.io/" rel="alternate" type="text/html" /><updated>2017-08-08T03:13:38+00:00</updated><id>https://alastaircoote.github.io/</id><title type="html">alastaircoote.github.io</title><subtitle>Mobile Developer with @gdnmobilelab</subtitle><entry><title type="html">Structuring the project, and communicating with a WKWebView</title><link href="https://alastaircoote.github.io/wkwebview-communication/" rel="alternate" type="text/html" title="Structuring the project, and communicating with a WKWebView" /><published>2017-07-19T00:00:00+00:00</published><updated>2017-07-19T00:00:00+00:00</updated><id>https://alastaircoote.github.io/wkwebview-communication</id><content type="html" xml:base="https://alastaircoote.github.io/wkwebview-communication/">&lt;p&gt;I’ve made some relatively boring progress lately - primarily in splitting the code up properly into discrete projects, so that people will be able to pick and choose their level of integration. Right now I’m expecting it to look like this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;ServiceWorker&lt;/strong&gt;: the actual JS environment code executes in. Basically a wrapper around JavascriptCore that provides some of the stuff it doesn’t, like &lt;code class=&quot;highlighter-rouge&quot;&gt;setTimeout&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;fetch&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;importScripts&lt;/code&gt;. It also provides stubs for things like &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceWorkerRegistration&lt;/code&gt;, but leaves the implementation up to the user.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;ServiceWorkerContainer&lt;/strong&gt;: …which is an implementation of &lt;code class=&quot;highlighter-rouge&quot;&gt;ServiceWorkerRegistration&lt;/code&gt; and the like. Basically it’s the glue that joins service workers together, and provides the bridge to…&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SWWebView&lt;/strong&gt;: the actual component people will use in their apps. As the name implies, I’m hoping I can get this as near as possible to a drop-in replacement for &lt;code class=&quot;highlighter-rouge&quot;&gt;WKWebView&lt;/code&gt;, allowing people to augment their existing apps relatively easily. But if they don’t already have an app…&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;I dunno what I’ll call it&lt;/strong&gt;: A wrapper around SWWebView that will basically create a full navigation stack for an app. This part will be particularly complex as it moves completely outside of the Service Worker API itself.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Anyway. To more immediate concerns&lt;/p&gt;

&lt;h2 id=&quot;communicating-with-a-wkwebview&quot;&gt;Communicating with a WKWebView&lt;/h2&gt;

&lt;p&gt;My initial hack version used &lt;code class=&quot;highlighter-rouge&quot;&gt;WKScriptMessageHandler&lt;/code&gt; to allow webviews to send messages back to the app, then used &lt;code class=&quot;highlighter-rouge&quot;&gt;evaluateJavaScript&lt;/code&gt; to send responses back. This had quite a few problems:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The send and receive are totally disconnected. So I had to manually store unresolved promises in an array and pass the array index through to the native code… then send that index back with the response. The whole thing was kind of a mess, not least because I needed to keep very close track of any errors so that I didn’t have an ever-ballooning array.&lt;/li&gt;
  &lt;li&gt;It didn’t work with &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;iframe&amp;gt;&lt;/code&gt;s. &lt;code class=&quot;highlighter-rouge&quot;&gt;evaluateJavascript&lt;/code&gt; doesn’t let you target which frame you want to execute the script in, so it always goes to the top-most frame. From there we’d have to (somehow) find a reference to the correct frame and pass the message down.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, iOS 11 brings us a new API to play with: &lt;a href=&quot;https://developer.apple.com/documentation/webkit/wkurlschemehandler?changes=latest_minor&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;WKURLSchemeHandler&lt;/code&gt;&lt;/a&gt;. It let us register a custom URL scheme, then receive any incoming requests for that scheme and send whatever we want back. It’s actually how we’ll power the &lt;code class=&quot;highlighter-rouge&quot;&gt;fetch&lt;/code&gt; event, too - but it can also serve as a method of communication. Being an HTTP call, we can pair request and response very easily in the browser. And the response will go to whatever frame send the request automatically. I’m sure there is a performance overhead in adding this HTTP/JSON overhead, but we don’t use these calls &lt;em&gt;that&lt;/em&gt; much, so I’m optimistic the switch will be worth it.&lt;/p&gt;</content><author><name></name></author><summary type="html">I’ve made some relatively boring progress lately - primarily in splitting the code up properly into discrete projects, so that people will be able to pick and choose their level of integration. Right now I’m expecting it to look like this:</summary></entry><entry><title type="html">URLSession and GZip</title><link href="https://alastaircoote.github.io/urlsession-and-gzip/" rel="alternate" type="text/html" title="URLSession and GZip" /><published>2017-07-19T00:00:00+00:00</published><updated>2017-07-19T00:00:00+00:00</updated><id>https://alastaircoote.github.io/urlsession-and-gzip</id><content type="html" xml:base="https://alastaircoote.github.io/urlsession-and-gzip/">&lt;p&gt;Another short entry, just to make a search engine indexable note about something I’ve discovered. It appears that when using &lt;code class=&quot;highlighter-rouge&quot;&gt;URLSession&lt;/code&gt; in iOS, there is no way to stop the OS from decompression gzipped content. Normally you’d want it to do this, but in my case I would actually prefer to preserve the gzipped body on disk. Worse, having the gunzipped body means that the &lt;code class=&quot;highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; header is no longer accurate, and when you’re using SQLite 3’s blob streaming functions (which I am, more on that later) you need to know the length upfront.&lt;/p&gt;

&lt;p&gt;Long story short, I have no answer on accessing the gzipped body. It doesn’t seem to be possible, at least not right now. But there is some good news: &lt;code class=&quot;highlighter-rouge&quot;&gt;URLSessionTask&lt;/code&gt; has a property named &lt;code class=&quot;highlighter-rouge&quot;&gt;countOfBytesExpectedToReceive&lt;/code&gt;, which is accurate for gunzipped content. So, in my Fetch implementation I’m now rewriting headers as they are passed to JS - removing the &lt;code class=&quot;highlighter-rouge&quot;&gt;Content-Encoding&lt;/code&gt; header and rewriting the &lt;code class=&quot;highlighter-rouge&quot;&gt;Content-Length&lt;/code&gt; one. Not great. But better than nothing.&lt;/p&gt;</content><author><name></name></author><summary type="html">Another short entry, just to make a search engine indexable note about something I’ve discovered. It appears that when using URLSession in iOS, there is no way to stop the OS from decompression gzipped content. Normally you’d want it to do this, but in my case I would actually prefer to preserve the gzipped body on disk. Worse, having the gunzipped body means that the Content-Length header is no longer accurate, and when you’re using SQLite 3’s blob streaming functions (which I am, more on that later) you need to know the length upfront.</summary></entry><entry><title type="html">URLSession, willPerformHTTPRedirection and timeouts</title><link href="https://alastaircoote.github.io/fetch/" rel="alternate" type="text/html" title="URLSession, willPerformHTTPRedirection and timeouts" /><published>2017-07-14T00:00:00+00:00</published><updated>2017-07-14T00:00:00+00:00</updated><id>https://alastaircoote.github.io/fetch</id><content type="html" xml:base="https://alastaircoote.github.io/fetch/">&lt;p&gt;Erk. It’s been a month since I started this thing and I haven’t updated it in a while. I’ve been busy on other stuff at the lab, but have been plugging away at bits and pieces when I can find the time. Lately, I’ve been trying to replicate the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API&quot;&gt;Fetch API&lt;/a&gt; in iOS. The first hacky version kind of sidestepped the details of the API and just downloaded whole files into memory, but we want to be a little smarter than that, since we might be downloading multi-megabyte files into our cache, or something like that.&lt;/p&gt;

&lt;p&gt;But anyway, more on that when it’s actually done. In the meantime, a very quick note about an infurating bug I (think I) stumbled upon. The Fetch API has a &lt;code class=&quot;highlighter-rouge&quot;&gt;redirect&lt;/code&gt; attribute that lets you control whether your request follows redirects or not. iOS’s &lt;code class=&quot;highlighter-rouge&quot;&gt;URLSessionTaskDelegate&lt;/code&gt; has a method called &lt;code class=&quot;highlighter-rouge&quot;&gt;willPerformHTTPRedirection&lt;/code&gt; that lets you control this, via an asynchronous completion handler - you either pass the new, redirected request to it, or pass nothing - if you pass nothing it’ll just return the unredirected response.&lt;/p&gt;

&lt;p&gt;Expect it won’t always. The first time you run it, it will. The second time it just hangs until the request times out. You might be able to imagine how confusing this was when running my test suite. It appears someone has already &lt;a href=&quot;http://www.openradar.me/31284156&quot;&gt;filed a bug report&lt;/a&gt; but in the meantime I have the Fetch implementation manually setting the &lt;code class=&quot;highlighter-rouge&quot;&gt;URLRequest.CachePolicy&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;reloadIgnoringLocalCacheData&lt;/code&gt; when &lt;code class=&quot;highlighter-rouge&quot;&gt;redirect&lt;/code&gt; is set to manual, which seems to restore the behaviour we expect, even if it isn’t using the cache.&lt;/p&gt;

&lt;p&gt;Anyway, hopefully someone will stumble across this post when they put some of these terms into Google and save themselves some of the time I wasted working out what was going on here!&lt;/p&gt;</content><author><name></name></author><summary type="html">Erk. It’s been a month since I started this thing and I haven’t updated it in a while. I’ve been busy on other stuff at the lab, but have been plugging away at bits and pieces when I can find the time. Lately, I’ve been trying to replicate the Fetch API in iOS. The first hacky version kind of sidestepped the details of the API and just downloaded whole files into memory, but we want to be a little smarter than that, since we might be downloading multi-megabyte files into our cache, or something like that.</summary></entry><entry><title type="html">UNNotificationServiceExtension and memory</title><link href="https://alastaircoote.github.io/notification-service/" rel="alternate" type="text/html" title="UNNotificationServiceExtension and memory" /><published>2017-06-16T00:00:00+00:00</published><updated>2017-06-16T00:00:00+00:00</updated><id>https://alastaircoote.github.io/notification-service</id><content type="html" xml:base="https://alastaircoote.github.io/notification-service/">&lt;p&gt;As previously noted, my hacky attempt at making a service worker implementation really came undone when it tried to handle push messages. UNNotificationServiceExtension has a hard memory limit, and if your code hits that limit it’ll immediately terminate the process without letting you change the content of a notification. Not great.&lt;/p&gt;

&lt;p&gt;So I’ve been trying to find a way around this. Testing the limit is very difficult, because you can’t use the service extension with a local notification - it has to be a remote one. So I’ve upgraded my phone to the iOS 11 beta (more fool me) and created a tiny test app that sends HTTP calls to a service that’ll send me a remote notification. Then, it checks to see if the UNNotificationServiceExtension successfully manipulated the content of the notification or not. &lt;em&gt;Then&lt;/em&gt;, in the extension itself, I’m spinning up a JSContext, and executing code inside it that creates a &lt;code class=&quot;highlighter-rouge&quot;&gt;Uint8Array&lt;/code&gt; of ever increasing size, until it reaches a point where the extension crashes.&lt;/p&gt;

&lt;p&gt;My initial tests showed that it reached this around the 900KB mark. Not awful (at least it runs), but really not great either, as this is an entirely empty JSContext, and I still need to populate it with the various worker APIs we depend on, which will take up more and more memory. Worse, it turns out that iOS doesn’t close the extension when it has processed a notification - it keeps it alive for some amount of time (I have no idea how long) to process a second notification, should it arrive. There was some kind of garbage collection issue that meant the JSContexts were not being collected, so when a second notification arrived the extension tried to make a &lt;em&gt;second&lt;/em&gt; JSContext and crashed immediately.&lt;/p&gt;

&lt;p&gt;Not good at all. But, with garbage collection on my mind (which we can’t control in Swift), I tried something - recreated the extension in Objective C. And, somehow, the amount of memory it could use kept ticking up and up, reaching 10MB. Great news, but I immediately had nightmares of having to make the entire library in Objective C, which I don’t know well at all. But to my surprise, pulling in my ServiceWorker Swift module into the Objective C extension worked, and without decreasing the memory limit.&lt;/p&gt;

&lt;p&gt;I don’t really understand why this works, and I’m waiting to trip up on something major, but for now I’m making the bulk of the code in Swift, and then going to Objective C to write my (pretty small) notification extension code. I already ran into one issue - if I don’t unassign the exceptionHandler of the JSContext it has the same issue as the Swift version - so I’ll have to be vigilant and run this test app on a regular basis to make sure I’m not making any references that lead to the JSContext sticking around. But overall, good news - it looks like we’ll be able to process push messages.&lt;/p&gt;</content><author><name></name></author><summary type="html">As previously noted, my hacky attempt at making a service worker implementation really came undone when it tried to handle push messages. UNNotificationServiceExtension has a hard memory limit, and if your code hits that limit it’ll immediately terminate the process without letting you change the content of a notification. Not great.</summary></entry><entry><title type="html">importScripts()</title><link href="https://alastaircoote.github.io/importscripts/" rel="alternate" type="text/html" title="importScripts()" /><published>2017-06-15T00:00:00+00:00</published><updated>2017-06-15T00:00:00+00:00</updated><id>https://alastaircoote.github.io/importscripts</id><content type="html" xml:base="https://alastaircoote.github.io/importscripts/">&lt;p&gt;Issue number one. I totally ignored importScripts() functionality when first hacking around with this because it didn’t seem necessary, but if I want to end up with something spec-compliant, it’s pretty crucial (the Google SW toolbox uses it, for one). importScripts is weird. But after reading the spec and a number of GitHub comments I think I’ve nailed the functionality down. This is how I’m going to implement it, anyway…&lt;/p&gt;

&lt;p&gt;I had assumed &lt;code class=&quot;highlighter-rouge&quot;&gt;importScripts&lt;/code&gt; was similar to the ES6 &lt;code class=&quot;highlighter-rouge&quot;&gt;import&lt;/code&gt; command, but it really isn’t. For one, it adds whatever you’ve imported directly into the global scope of the worker - no fancy modules or static dependency trees here. It can also be run at any point in the code - not just at the root level of the file, but inside a function, in response to an event… it’s tricky.&lt;/p&gt;

&lt;p&gt;It also has an odd relationship with caching - when you importScripts() a file it is added to a special cache collection for each worker and any future loads will go directly to the cache before trying the network (AFAIK it also ignores any headers etc too). In fact, current browser implementations will &lt;em&gt;never&lt;/em&gt; check those files again, unless the main service worker file is changed. There are lots of hacks out there involving adding file hashes to your worker file and all sorts of nonsense like that, but fortunately browsers are changing their behaviour to &lt;a href=&quot;https://github.com/w3c/ServiceWorker/issues/839&quot;&gt;check both the worker JS and imported JS when updating&lt;/a&gt;. So we’ll reflect that, with a process that goes something like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Download and store worker JS, along with HTTP headers&lt;/li&gt;
  &lt;li&gt;Whenever &lt;code class=&quot;highlighter-rouge&quot;&gt;importScripts()&lt;/code&gt; is run, store JS and headers for each import&lt;/li&gt;
  &lt;li&gt;When updating the worker, first try the worker URL, using &lt;code class=&quot;highlighter-rouge&quot;&gt;If-None-Match&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;If-Modified-Since&lt;/code&gt;
    &lt;ul&gt;
      &lt;li&gt;If it’s changed:
        &lt;ul&gt;
          &lt;li&gt;Treat this as a new worker, ignore the old import cache entirely&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;If not changed:
        &lt;ul&gt;
          &lt;li&gt;Check each import URL with the same HTTP header checks. If any have changed, treat as new worker. If not, end the update.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ve been storing the JS contents inside the SQLite database I’ve been using for all app data (I tried Core Data, but… no), but I’m wondering if it makes more sense to just store them on disk. Again, I’m motivated by minimising memory usage in the Notification Service Extension - if I could remove the SQLite dependency in that environment (which won’t be trying to update or anything like that, just start, fire push event, and shut down) that would be great. Right now I’m thinking I might get that extension working before anything else, as it’ll inform quite a few of the decisions I’ll make further down the line.&lt;/p&gt;</content><author><name></name></author><summary type="html">Issue number one. I totally ignored importScripts() functionality when first hacking around with this because it didn’t seem necessary, but if I want to end up with something spec-compliant, it’s pretty crucial (the Google SW toolbox uses it, for one). importScripts is weird. But after reading the spec and a number of GitHub comments I think I’ve nailed the functionality down. This is how I’m going to implement it, anyway…</summary></entry><entry><title type="html">A development blog.</title><link href="https://alastaircoote.github.io/reboot/" rel="alternate" type="text/html" title="A development blog." /><published>2017-06-14T00:00:00+00:00</published><updated>2017-06-14T00:00:00+00:00</updated><id>https://alastaircoote.github.io/reboot</id><content type="html" xml:base="https://alastaircoote.github.io/reboot/">&lt;p&gt;Hello. I’m trying a new thing here, a semi-regular blog detailing the work I’m doing on a specific project. Namely, &lt;a href=&quot;https://github.com/gdnmobilelab/hybrid&quot;&gt;Hybrid&lt;/a&gt;, my attempt at implementing Service Workers inside an iOS app. Normally we write up all our Lab projects &lt;a href=&quot;https://medium.com/the-guardian-mobile-innovation-lab&quot;&gt;on Medium&lt;/a&gt;, but waiting until I’m finished before detailing everything isn’t going to work here - there’s just too much going on.&lt;/p&gt;

&lt;p&gt;It’s for me more than it is for you - I’ve been reading through my old code and struggling to remember why I made some of the decisions I did. The usual answer to that is “write more comments in your code”, and that’s fair, but it doesn’t capture the overall thinking that you’re doing about a project while you write it. But hopefully this will also be a way for people to discover more about this project as I chug along with it. Updates will be sporadic, as this isn’t the main project I’m working on at the lab right now, but whenever I have some free time I’ll be piecing it together.&lt;/p&gt;

&lt;h3 id=&quot;whats-the-current-status-of-the-project&quot;&gt;What’s the current status of the project?&lt;/h3&gt;

&lt;p&gt;Messy. It started off as a hacky experiment and sort of ballooned out from there, so the code is awful. But it is live in the App Store as the Guardian Mobile Innovation Lab app, and it does indeed download, register and load Service Workers (using JavascriptCore) and allow you to do things like post messages from the (WK)Webview your content is in, and even receive notifications. But like I said, it’s an utter mess. So I’m rebooting it. That doesn’t mean I’m rewriting all the code from scratch, just that I’m starting a new project, then copy and pasting in various bits and pieces as I need. I’ve got a few aims with this reboot:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Organised code.&lt;/strong&gt; Hybrid was also my first decently-sized Swift/iOS project, so I wasn’t too clued in on the best ways to structure a project. Right now, all the code sits inside one project, and I intend to change that. Partially for my own sanity, but also so that specific portions of the code, like the Service Worker implementation (separate from any UI-facing webview stuff) could possibly be separated out and embedded into an existing app at some point.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Tests.&lt;/strong&gt; I started with the best of intentions, and created a test suite. But then deadlines appeared and I rushed, and now half of them don’t even pass, to say nothing of the vast amounts of code that have no tests at all. That came back to bite me when we did use the app to experiment with &lt;a href=&quot;https://medium.com/the-guardian-mobile-innovation-lab/live-now-from-your-lock-screen-532133e22419&quot;&gt;live video notifications&lt;/a&gt;, as it turned out the published version of the app didn’t let me update a cached worker. I don’t want to do that again.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Use new functionality in iOS11.&lt;/strong&gt; One of the hackiest parts of the current project is how it actually serves content. In order to implement the Cache API and the fetch event, it actually creates a new local web server for every domain, and points the web view to it. That’s wasteful, and also has enough security implications to worry me deeply. iOS11 introduces the ability to register a protocol with WKWebView and manually provide data in response to requests, which will be much, much cleaner.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Make a ServiceWorker implementation that’s as tiny as possible.&lt;/strong&gt; One difference between iOS and the web APIs that I’m going to struggle to solve is that the contents of an iOS notification are decided by the server and presented immediately, wheras on the web you use the Push API to send data, then construct the notification inside the worker. iOS 10 introduced &lt;a href=&quot;https://developer.apple.com/documentation/usernotifications/unnotificationserviceextension&quot;&gt;Notification Service Extensions&lt;/a&gt;, which allow you to intercept the notification before it’s shown and alter the content. &lt;em&gt;But&lt;/em&gt;, they have very, very tight memory requirements. Right now, just trying to spin up a worker is enough to cause it to hit the memory limit and terminate the process. But the Service Worker implementation uses third party frameworks like PromiseKit and FMDB, and I’m hoping that if I can strip all that out, it might be lean enough to execute in. It probably won’t be, but a small worker implementation also lends itself to having something that other apps can embed, so it’ll still be worth it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyway, stay tuned.&lt;/p&gt;</content><author><name></name></author><summary type="html">Hello. I’m trying a new thing here, a semi-regular blog detailing the work I’m doing on a specific project. Namely, Hybrid, my attempt at implementing Service Workers inside an iOS app. Normally we write up all our Lab projects on Medium, but waiting until I’m finished before detailing everything isn’t going to work here - there’s just too much going on.</summary></entry></feed>