A Note on D-Bus API Versioning

In the code review cycles for some of the PWA project PRs I’ve put out, the question has been raised about the proper way to version D-Bus APIs, since I am adding a new D-Bus API to GNOME Web. I learned a couple things and thought I’d share in case it’s useful.

As D-Bus APIs evolve over time and new functionality is added or existing functionality is removed, in most cases you don’t have the luxury of ensuring that all clients are updated in lockstep, so it’s important to think about how existing clients can continue to work without modification, and how clients which are aware of the new functionality can take advantage of it. So there are two types of compatibility to worry about:

  1. Backwards compatible changes to the API, which are changes that do not cause existing client code to break. For example, if a method accepts a dictionary of options, each a string key mapped to a value, adding a new supported option key does not cause existing clients to stop working; they just won’t be able to take advantage of the new option. That’s assuming the behavior of the D-Bus service with the new option omitted is the same as it was before the new option was added.
  2. Backwards incompatible changes to the API, which are changes that would cause existing client code to break if it’s not updated. For example, changing the name of a method, changing the parameters of a method, or removing a method.

The de facto way to handle backwards compatible API changes, at least in xdg-desktop-portal as well as org.gnome.Mutter.ScreenCast, is to increment an integer Version property when such changes are made (in the portal code the property is not capitalized but the spec recommends capitalization). This allows clients to check at runtime what functionality is available, and only make use of new functionality when the running service has it. This is especially useful for Flatpaks since a Flatpak app needs to be able to run regardless of the version of xdg-desktop-portal or its backends installed on the host; a major benefit of Flatpaks is that they don’t have version requirements for software installed on the host system. This scheme seems to work pretty well for the portal code and its many clients. Here’s an example of how to check the available version of a portal interface in C code.

Per the D-Bus API Design Guidelines, the way to handle backwards incompatible API changes is to leave the existing interface as it is, continue to support it as before, and make a new interface with an incremented number on the end like com.example.MyService2 and use that in the service name, interface name, and object path. While the spec says to add a 1 to the end of the original service name, in practice that is often left off since com.example.MyService2 can just as well follow com.example.MyService as com.example.MyService1. An example of this is the interface org.gnome.ShellSearchProvider2 provided by gnome-shell.

That’s all for now, happy hacking