Extensions Infrastructure Work



Hey guys, it's Jasper.

As part of my work on SweetTooth[0], I'm planning on a bunch of
changes to make the user experience for installing, enabling and
disabling extensions better. Unfortunately, I'm gonna have to break
some stuff unless someone can come up with a clever hack. These
changes are not set in stone, but they're what I'm hacking on
currently, and I'd like to discuss them to make sure I'm on the right
track. Extension developers, I'm talking to you:

  * I want live extension enabling and disabling. The user experience
is "click a button on extensions.gnome3.org, it takes effect
immediately".

  * I want to make it safer and more usable for developers to import
code and assets their extension directory.

  * I want extensions to be smart about their dependencies. For
instance, the systemMonitor extension depends on an introspectable
GTop, which AFAIK is unreleased, and hasn't been packaged in F15. The
only clue users have that something has gone wrong is the Errors tab
in the LookingGlass.

Unfortunately, in order to do these things, I need your cooperation.
I'm going to break some stuff, and I'd like your involvement so that I
don't make a wrong decision which means another API break. I'd rather
break it all at once and do things right.

Let's tackle item 1:

== Enabling and Disabling ==

I'm going to remove the main() method, and replace it with a new system.

You still require one function: init(). It does everything the main()
function usually does, except it cannot change *any* Shell state. This
is here so that you can set up anything you need to, like gettext
silly shell actors. It's guaranteed to be called at most once per
shell session.

So, what's used to change the Shell UI? We introduce two new methods:
enable() and disable(). Here's some simple rules:

  * The Shell will call init(), and then enable() if your extension is
enabled when the shell starts up.

  * The Shell may then call disable() and enable() again during the
same session, but it should never call init() more than once, ever.

  * The Shell will not call disable() if your extension is disabled at startup.

  * Right now the Shell calls init() even for disabled extensions at
startup, but I may change that so that it calls init(), then enable()
at first enable. The simplest solution is to not rely on init() coming
at the start of the Shell session.

For those of you who would like something a bit more object-oriented,
you're in luck: init() can also return a state object. All that
requires is functions named "enable" and "disable" on that object, the
type doesn't matter nor do any other fields. The shell won't touch
that object except for calling 'enable()' or 'disable()' on it. If you
don't return anything (or return a false-y object), it's assumed that
enabl() and disable() are on the moduie itself. Here's a simple code
example: For lack of better terms, I'm calling these extensions
"stateful", and the module ones "stateless", even though that's a huge
lie: both have state.

Starting with an improved version of the stock "Hello, World!"
extension in the old system[1], we can build a new extension in one of
two ways:

  1. We can simply rename the main() function to init(), and move the
line of code that adds the actor to the Shell to a new enable()
method, and add a disable() method that does the reverse.[2]

  2. Or we can make the extension return an object that has enable()
and disable() functions.[3]

If you want your extension to be compatible for old versions of the
shell, thankfully, it's very easy: just write a main() that calls
init(), then enable(). For the extensions website, I may allow
so-called "legacy" extensions with a special method that restarts the
Shell, but it would break the user-experience a bit, and it's extra
code that I don't think would get used.

Checking out the code samples, you may notice an argument called
"helper". That's a cliff-hanger for next time, when I want to talk
about items 2 and 3. I'd like your feedback on the information I'd
provided so far, and any questions on SweetTooth, the web site, or the
modifications I'm making would be extremely appreciated.

  Jasper

[0] http://live.gnome.org/GnomeShell/SweetTooth
[1] http://magcius.mecheye.net/shell/SweetTooth/Code/HelloWorld-Old/extension.js
[2] http://magcius.mecheye.net/shell/SweetTooth/Code/HelloWorld-Stateless/extension.js
[3] http://magcius.mecheye.net/shell/SweetTooth/Code/HelloWorld-Stateful/extension.js


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]