Tuesday 9 December 2014

Web Intents/Activities are dead, but they could bring more life to the web

If you are creating an awesome e-mail app, you have a big problem. When meeting e-mails show up in your users' inboxes from their bosses and colleagues' calendars, they will expect some kind of integration with a calendar. You'd better integrate with a calendar, or create your own!

And integrating with only one calendar app is not enough. Oh no. You will alienate most of your users by doing that. Do you know how many calendar apps are out there? I sure don't, but OMG there must be a shitload of them!

Any.do Cal? You cannot simply afford to waste even half a week's time to improve the experience of 20 users instead of working on the loading animation. So you don't even consider supporting it.

In the end you'll only support the big guys.

This effect ends unbalancing the popularity of apps in the internet (by making the most popular apps be integrated with more stuff, which in turn makes them more popular). It also increases vendor lock-in and software duplication because it's just easier, more secure, and less trouble-prone to just develop an entire suite of related apps so they integrate well together than to integrate with dozens of third-party apps.

And you'd better pray that nobody new comes along and makes an app that becomes really popular.

This is the problem which Web Intents / Web Activities attempt to fix.

This is something which needs to have a universal browser support so web app developers can start registering their intents/activities. Unfortunately, the standardization effort seems to have been dropped by both Mozilla and Google, experimental support was removed from Chrome, and isn't even available on Firefox other than for the Firefox OS platform and Firefox for Android powered apps. A sad outcome for such wonderful tech.

Intents or Activities?

Did you notice I keep referring to this as "Intents/Activities"? The reason for that is that there are two competing defunct specs.

Google was working on standardizing Web Intents through the Web Intents Task Force, and even had (it's been removed) an experimental, prefixed WebKitIntent in their Chrome browser.

Mozilla needed something like Android's Intent on their Firefox OS platform, so they started standardizing Web Activities. They now provide a prefixed MozActivity in that same platform, and it's the standard way of doing Intents there. However, no support is present on the Firefox browser on the desktop.

A look at the dead APIs: Google's Web Intents

The Web Intents spec defines the relationship between a "Client" and a "Service". The client is the page which "Invokes" other webapps' Services, and the Service is a page which is "Registered" as capable to do some actions to some MIME types.

When the Client Invokes the service, the browser allows the user to Select what app they want to use to perform the action (which is something like "edit", "view" or "crop" but in URL form) on their data. There are a bunch of action URLs you can use, based on "http://webintents.org". It smells weird to me to use URLs as names for things, but it could be a good idea.

When The Service is Invoked, its page will be loaded up just like any other page, but have a window.intent Intent object available so they can look at what action, type and data the Client has passed him in this Invocation, and provide an adequate Response to send the Client when the user is done.

These examples are taken from the spec.

Below is an example which shows you how to register a Web Intents service for other apps to use:

[...]
<intent action="http://webintents.org/edit" type="text/uri-list image/*"></intent>
<script>
  window.addEventListener("load", function() {
    if (window.intent) {
      setImageContentURI(window.intent.data);
    }
  }, false);

  document.getElementById('save-button').addEventListener("click", function() {
    window.intent.postResult(getImageDataURI(...));
  }, false);
</script>

It's simple really, you only need to add one or more <intent> tags to your HTML describing the services you provide, and some Java Scripts to handle the case where the page is loaded as a service, and talk back to the intent user.

Here is how you use a Web Intent on some other page to allow the user to edit a photo you have somewhere.

document.getElementById('edit-photo').addEventListener("click", function() {
  var intent = new Intent({"action":"http://webintents.org/edit",
                           "type":"image/jpeg",
                           "data":getImageDataBlob(...)});
  navigator.startActivity(intent, imageEdited);
}, false);

function imageEdited(data) {
  document.getElementById('image').src = data;
}

As you can see, the intent type is a URL referring to the kind of action the intent is supposed to achieve. I can see this being unhelpful in many ways (by encouraging companies to create their own taxonomies of actions, for example).

All in all, it seems like a good proposal API, and I see no good reason it stopped being specified. I literally could not find it why it stopped, nor whether it stopped permanently.

A look at the dead APIs: Mozilla's Web Activities

Mozilla has developed Web Activities for their Firefox OS platform, and it shows.

An Activity is handled by a Handler, which is an App (mostly a Firefox OS concept) which Registers in its manifest which kinds of Activities it can handle, and what pages handle them.

When registering a handler, you can specify filters (an example of this is the type filter, which filters by mime type), and also a disposition (which defines how the application is displayed) and a returnValue boolean, which indicates if this activity handler will return a value or not.

They used a field in Firefox OS's app manifest file to announce what kind of activities your application can handle and where are the HTML files where these activities are handled.

The examples below were taken from MDN.

Here is how you can register your app as an activity handler in your app manifest:

{
  // Other App Manifest related stuff

  // Activity registration
  "activities": {

    // The name of the activity to handle (here "pick")
    "pick": {
      "href": "./pick.html",
      "disposition": "inline",
      "filters": {
        "type": ["image/*","image/jpeg","image/png"]
      },
      "returnValue": true
    }
  }
}

Here is how you handle an activity. You listen to a message (which is like an event, but is buffered for you so you can't miss it by adding a handler only after it was sent).

navigator.mozSetMessageHandler('activity', function(activityRequest) {
  var option = activityRequest.source;

  if (option.name === "pick") {
    // Do something to handle the activity
  }
});

And here is how you ask the Browser to somehow give you a JPEG. Pretty clean, no?

var activity = new MozActivity({
  // Ask for the "pick" activity
  name: "pick",

  // Provide the data required by the filters of the activity
  data: {
    type: "image/jpeg"
  }
});

activity.onsuccess = function() {
  var picture = this.result;
  console.log("A picture has been retrieved");
};

activity.onerror = function() {
  console.log(this.error);
};

A look at the dead APIs: comparison

I like how the Mozilla spec limits the activity types to a manageable count and how it lets you define if you wish to open a new window or open an overlay.

I also prefer Mozilla's client API. It seems much more familiar to just create an Activity and listen to events on that instance, like we do with XmlHTTPRequest and Web Workers.

On the other hand, I like how the Google spec allows a much, much simpler implementation of the Service.

Both have their pros and cons, and I hope they merge the two specs together somehow, and create an amazing shiny unicorn of love and butterflies!

Closing thoughts

Intents/Activities are already present in the mobile app world, and connect our mobile apps seamlessly and beautifully. In the desktop, it seems like fans of putting files somewhere and use them later have taken over everything and barf at gorgeous and intuitive workflows.

These APIs are seriously cool and extremely beneficial for both developers and users. Unfortunately it's not good businesses which want users to only use their stuff. It's definitely not good for Google, Apple nor Microsoft who have a lot of apps and want them integrated together in a closed ecosystem to increase vendor lock-in. And this means that 3 out of the 4 significant browser vendors are simply not interested in pushing this forward. They'd best snuff this out.

We already have closed walled-garden versions of Intents in Microsoft Office/Outlook, Adobe Creative Suite, and on Google apps (like the cool integration between Gmail and Google Drive). These weren't created to benefit the users, but instead to increase vendor lock-in.

This would make the web a significantly better place by giving a chance to smaller independent developers. They will do their integration more easily and concentrate on what their app does best, while easily connecting their app to a web-sized ecosystem of shite they could never dream of supporting otherwise.

If one of these specs was released, implemented and used by webdevs worldwide it would make the web a lot better, but it's pretty much dead. I would very much like them to be alive. I would very much like browser vendors to bridge Web Intents / Web Activities with similar APIs like Elementary OS's Contractor or Android's Intents so everyone can finally work seamlessly with web apps and native apps. I want to upload my e-mail attachments on Dropbox or to Google Keep all the time, and it's a bother. It doesn't have to be.

No comments:

Post a Comment