Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

openwebapps API feedback

42 views
Skip to first unread message

Fabrice Desré

unread,
Jan 6, 2012, 3:22:37 PM1/6/12
to dev-w...@lists.mozilla.org, dev-pl...@lists.mozilla.org
Since about a year, people in Labs and Mobile have been experimenting
with an API to provide first class apps management through the DOM.

We landed some support for this in m-c (bound to navigator.mozApps) that
we use for b2g, but we'd like to get more feedback on the API.

I posted an updated IDL here:
https://etherpad.mozilla.org/openwebapps-api

Comments welcome!

Fabrice
--
Fabrice Desré
b2g Team
Mozilla Corporation

Ian Bicking

unread,
Jan 6, 2012, 5:45:43 PM1/6/12
to dev-pl...@lists.mozilla.org, dev-w...@lists.mozilla.org
On Fri, Jan 6, 2012 at 2:22 PM, Fabrice Desré <fab...@mozilla.com> wrote:

> I posted an updated IDL here:
> https://etherpad.mozilla.org/**openwebapps-api<https://etherpad.mozilla.org/openwebapps-api>
>
>
I have posted several comments in the document. I'll copy the document
below with my comments, as the etherpad might be a tricky place for
discussion (and if it's better that this discussion take place here then
probably we should remove these comments from the IDL):


[scriptable, uuid(e0c271cb-266b-48c9-a7e4-96590b445c26)]
interface mozIDOMApplicationRegistryError : nsISupports
{
const unsigned short DENIED = 1;
const unsigned short PERMISSION_DENIED = 2;
const unsigned short MANIFEST_URL_ERROR = 3;
const unsigned short NETWORK_ERROR = 4;
const unsigned short MANIFEST_PARSE_ERROR = 5;
const unsigned short INVALID_MANIFEST = 6;

readonly attribute short code;
};

[scriptable, uuid(a7da98ab-26da-4db2-9cd1-cb759fd4b436)]
interface mozIDOMApplicationOp : nsISupports
{
attribute nsIDOMEventListener onsuccess;
attribute nsIDOMEventListener onerror;

/**
* type and value depends on the operation :
* - mozIDOMApplicationRegistryError when onerror is fired
* - mozIDOMApplication[] for enumerate and enumerateAll
*/
readonly attribute jsval result;
}

[scriptable, uuid(a6856a3d-dece-43ce-89b9-72dba07f4246)]
interface mozIDOMApplication : nsISupports
{
// ianb: I think we're missing the URL where the manifest was retrieved
from
readonly attribute jsval manifest;
readonly attribute jsval parameters;
readonly attribute DOMString origin;
readonly attribute DOMString installOrigin;
readonly attribute unsigned long installTime;

/**
* launch a webapp. Behavior is application dependant.
*/
mozIDOMApplicationOp launch();

/**
* This call is only accessible to privileged callers.
*/
// ianb: Presumably the only way to detect the success of this is
mozApps.onuninstall
mozIDOMApplicationOp uninstall();

// ianb: There's no good way to refresh the manifest if it has been
updated on the server. You can reinstall, copying parameters, but this
seems relatively heavyweight, and updating should be "safe"; that is, it is
not truly a reinstallation, it is simply respecting how the application has
described itself.
// ianb: Allowing refresh distinct from reinstallation would also imply
that installTime wouldn't be updated, and so there would not be a clear
indication of when the application was last changed.

// ianb: I think we should include methods here to add and invalidate
receipts, again distinct from reinstallation. Adding a receipt would
append to the receipts (never overwrite). Invalidating a receipt could
remove the receipt, or leave it in place but in an invalid state (i.e.,
leave a record that the receipt existed). I think both would be
reasonable, but for an invalid state we'd need a way to note that in the
receipt. Noting something in the receipt is difficult because it is a
signed object. Also to invalidate a receipt we'd need to identify it; but
since it is a string (as a byproduct of the signature process) we could
identify it by string.
// ianb: So, I might propose: addReceipt() and invalidateReceipt().
Presumably they'd take onsuccess and onerror callbacks, though potentially
if there was some global onupdate handler that could be used to handle this
(though managing the onupdate handler for multiple consumers could become
tricky).
};

[scriptable, uuid(ac63c0ba-1f33-4e3e-b9aa-6a3243a9adba)]
interface mozIDOMApplicationRegistry : nsISupports
{
/**
* Install a web app. onerror can be used to report errors,
* and oninstall if the caller is privileged.
*
* @param manifestUrl : the URL of the webapps manifest
* @param parameters : An opaque jsval used to carry eg. payment
information
*/
// ianb: In a bug we discussed specifically allowing receipts, like
install('http://...', {receipts: ['xxx']}, and then having a receipts
attribute of the application. This is largely equivalent (except
app.parameters.receipts becomes app.receipts), but makes it clear where to
find receipts and how to handle them. Also arguably you should not delete
existing receipts by simply reinstalling and omiting the current receipts.
mozIDOMApplicationOp install(in DOMString manifestUrl,
[optional] in jsval parameters);

/**
* Enumerate apps : either return itself if caller is an app, or
* apps installed from a store if caller is a store
*
*/
// ianb: The particular case where an app wants to retrieve its own
manifest is an important one; it's how an app checks its receipts, and
checks if data is updated, as well as simply the installation status of an
application. Folding it in with a list of apps for the store case adds
complexity here, and I think obscures the utility.
// ianb: Also the indirection of onsuccess makes me uncomfortable, and
makes it hard for different pieces of reusable code to work together (e.g.,
if they clobber each other's onsuccess callbacks). I much prefer the
callback as a parameter, and the separation of amInstalled and
getInstalledBy (regardless of the names).
mozIDOMApplicationOp enumerate();

/**
* Enumerate all apps installed from all stores.
* Only usable by privileged callers.
*
*/
mozIDOMApplicationOp enumerateAll();

/**
* event listener to get notified of application installs. Only settable
by
* privileged callers
*/
// ianb: I assume oninstall(app) is called, with the newly created
mozIDOMApplication object, and that it is called after installation and
cannot be cancelled (and similarly for onuninstall).
// ianb: Note if this is the only way to see if an installation (or
uninstallation) is successful, then if only privileged callers can access
it then it inhibits unprivileged stores and all self-installing apps from
seeing the status of their calls to install or uninstall.
// ianb: Generally it seems like anything returned by enumerate() should
show up in these events.
// ianb: A singular attribute makes this harder to use in libraries or
otherwise abstract. Note that this is not like XMLHttpRequest, which is
instantiated and so relatively private, instead it is one attribute shared
by everyone.
attribute nsIDOMEventListener oninstall;

/**
* event listener to get notified of application uninstalls. Only
settable by
* privileged callers
*/
attribute nsIDOMEventListener onuninstall;
};

Ian Bicking

unread,
Jan 9, 2012, 6:09:14 PM1/9/12
to dev-pl...@lists.mozilla.org, dev-w...@lists.mozilla.org
A few more thoughts, specifically about the removal of callbacks in this
proposal:

One fairly simple use case is for an application to (a) check that it is
installed (if not, ask for installation), (b) check that its manifest is up
to date (if not, ask for reinstallation) and (c) at least look at the
receipt (I'll leave out verification, as it's a separate concern).

Here's what it would look like in this original API:

var manifestUrl = '/manifest.webapp';

function afterInstalled(app) {
... some stuff you'd do once you've confirmed everything
... you might use app.manifest.installData.receipts here, to verify
}

function failure(reason) {
... do something in case of an unresolvable failure
}

navigator.mozApps.amInstalled(function (app) {
if (! app) {
navigator.mozApps.install(manifestUrl, null, afterInstall, function ()
{failure('User rejected installation');});
return;
}
// You might know the version of the manifest, e.g., hardcode it via a
template, but
// for this stand-alone example we'll fetch it via XHR
var req = new XMLHttpRequest();
req.open('GET', manifestUrl);
req.onreadystatechange = function () {
if (req.readyState != 4) {
return;
}
if (req.status != 200) {
failure('Manifest missing');
return;
}
manifest = JSON.parse(req.responseText);
// Arguably in addition to version, you should be checking that the
manifest URL is what you expected
if (manifest.version != app.manifest.version) {
navigator.mozApps.install(manifestUrl, null, afterInstall, function
() {failure('Manifest update failed (denied?)');});
return;
}
afterInstall(app);
};
}, function () {failure('Could not call amInstalled');});



Here is the same functionality using this new API:


// keep manifestUrl, failure

function afterInstall(app) {
navigator.mozApps.onsuccess = null;
... and then the rest of the stuff
}

var appOrigin = location.protocol + '//' + location.host;

var expectVersion = null;

navigator.mozApps.onsuccess = function (apps) {
if (! apps.length) {
navigator.mozApps.install(manifestUrl);
checkInstall();
return;
}
var app = null;
for (var i=0; i<apps.length; i++) {
if (apps[i].origin == appOrigin) {
// Just hope there's no normalization errors here...
// if you are confident this can't be a store, then you could be sure
that so long as apps.length == 1, that apps[0] is this app
app = apps[i];
break;
}
}
if (! app) {
navigator.mozApps.install(manifestUrl);
checkInstall();
}
var req = new XMLHttpRequest();
req.open('GET', manifestUrl);
req.onreadystatechange = function () {
if (req.readyState != 4) {
return;
}
if (req.status != 200) {
failure('Manifest missing');
return;
}
manifest = JSON.parse(req.responseText);
// Arguably in addition to version, you should be checking that the
manifest URL is what you expected
if (manifest.version != app.manifest.version) {
expectVersion = app.manifest.version;
navigator.mozApps.install(manifestUrl);
checkInstall();
return;
}
afterInstall(app);
};
};

navigator.mozApps.enumerate();

navigator.mozApps.onerror = function (error) {
// Not sure if the error has useful text, and I'm not sure how to
interpret all the different codes (e.g., DENIED vs. PERMISSION_DENIED?)
failure(error.toString());
};

// OK, so this does the basic app checking, *except* afterInstall isn't
called in a number of cases
// for this we need one of two approaches that I can see. This one works
even with the API as documented
// (from what I can tell):

function checkInstall() {
var maxTime = 30*1000; // give it 30 seconds to succeed, otherwise we
consider it a failure
var start = new Date().getTime();
var timer = null;
var checker = function () {
if (new Date().getTime() - start > maxTime) {
failure('installation denied');
return;
}
navigator.mozApps.enumerate();
timer = setTimeout(checker, 500);
}
navigator.mozApps.onsuccess = function (apps) {
for (var i=0; i<apps.length; i++) {
// Again, if you are certain this can't be a store, and so apps[0]
(if it exists) must be this app, you can skip this test
if (apps[i].origin == appOrigin) {
if (expectVersion && apps[i].manifest.version != expectVersion) {
// We're doing an update, and the update still hasn't gone through
break;
}
clearTimeout(timer);
afterInstall(apps[i]);
return;
}
}
// Since nothing is ready yet, checker() will try again soon
};
checker();
}

// Another option, which the IDL suggests might not be allowed, but could
be allowed, is for an app to use the oninstall
// event to see the update. It seems reasonable (and useful) that the app
could see an event when the app itself is installed or uninstalled
// (but would not see events for other apps)

function checkInstall() {
var timer = setTimeout(function () {
failure("Installation canceled or otherwise didn't go through");
}, 30*1000);
navigator.mozApps.oninstall = function (app) {
if (app.origin == appOrigin) {
if (expectedVersion && expectedVersion != app.manifest.version) {
// A stale installation? Not sure what that would mean, but it's
not success
return;
}
navigator.mozApps.oninstall = null;
clearTimeout(timer);
afterInstall(app);
}
};
}


--------

My personal conclusion is that onsuccess and onerror is much more
convoluted when implementing basic logic, than using simple callbacks. And
arguably instead of setting and unsetting onsuccess, onerror, and
oninstall, I should have been nesting and reseting those attributes, like:

oldOnSuccess = navigator.mozApps.onsuccess;
navigator.mozApps.onsuccess = function (apps) {
... my stuff...
oldOnSuccess(apps);
};
// and after done:
navigator.mozApps.onsuccess = oldOnSuccess;
// Hah, only not! Because maybe someone else overwrote onsuccess in the
meantime!

Doing this in each place would have made the code a bit longer and more
complicated, and it's not at all clear that the behavior in that case is
correct - onsuccess is a return value that is either expected or not, it's
not something that can be nested really.


I'm not sure what is the motivation of using this pattern (as opposed to
the original callback style), except perhaps to be more "DOM-like"? Global
attributes for events are not common in DOM APIs that I've seen.
window.onerror is one example, but that only seems useful for general error
reporting (a kind of last resort error catcher), it's not something I see
widely used. DOM level 0 events use this pattern, but they are much more
"eventy" than this code, and of course we have a new and better way to
actually do these (addEventListener). XMLHttpRequest at first looks like
it uses this pattern, but XMLHttpRequest objects are instantiated locally,
they do not have global handlers, rendering them very different in practice
(and almost trivially translatable to and from a callback style).

Other new APIs do use a callback style, like geolocation, and notifications
(https://developer.mozilla.org/en/DOM/notification) use the XHR approach
that avoid global handlers. Storage events are global, but at least use
addEventListener (and the core API is synchronous). IndexDB like XHR uses
locally instantiated objects. So I'm really not seeing any parallel
between this API and other DOM APIs, nor do I know what problem this is
fixing when compared to the original API. Another approach would be to
create an enumeration object, and an installation progress object, but
that's going to add a lot more surface area to the API.

Another simple pattern that the original API supports is present in
https://apps.mozillalabs.com/appdir/ - when you hit "install" and it
successfully installs then the button is changed to reflect the successful
installation. You'd have to do something very similar to checkInstall to
support this with this new API. The button confirmation, though a useful
bit of UI (and notably present in, e.g., the Android Market), is also a
similar issue to receipt management and handling what happens when you get
multiple overlapping installations - i.e., how can a store confirm that a
purchase completed successfully when it is deciding whether to complete or
revert the transaction.




On Fri, Jan 6, 2012 at 4:45 PM, Ian Bicking <ia...@mozilla.com> wrote:

> On Fri, Jan 6, 2012 at 2:22 PM, Fabrice Desré <fab...@mozilla.com> wrote:
>
>> I posted an updated IDL here:
>> https://etherpad.mozilla.org/openwebapps-api
>>
>>

Ian Bicking

unread,
Jan 9, 2012, 8:32:47 PM1/9/12
to dev-pl...@lists.mozilla.org, dev-w...@lists.mozilla.org
And then some general API concerns I have, that I'd like to discuss (more
about functionality that I think is missing, rather than what is described
in the IDL):

1. Receipt management, and permission to manage receipts.

Right now the only way to update installData (or receipts, or whatever else
we call the data associated with an installation) is to call install()
again with new data. That means that (using the original API) a simple act
like adding a receipt becomes kind of complicated and error-prone (the use
case I have in mind here is something like an in-app purchase, where we're
adding additional receipts that represent new purchases):

var receiptToAdd = 'signed receipt';
var appToAddTo = 'http://origin.domain';

navigator.mozApps.mgmt.getInstalledBy(function (apps) {
for (var i=0; i<apps.length; i++) {
if (apps[i].origin == appToAddTo) {
var installData = apps[i].installData || {};
installData.receipts = installData.receipts || [];
installData.receipts.push(receiptToAdd);
// manifest_url doesn't exist in either version of the API, but
definitely seems like it should
navigator.mozApps.install(apps[i].manifest_url, installData, function
() {
// confirm on server that receipt was accepted
}, function () {
// tell server receipt was rejected
});
return;
}
}
// tell server receipt was rejected
});


The server itself might want to actually time out, so that if confirmation
is not received the receipt is made invalid and refunded (e.g., if the
browser crashes or is closed somewhere in the middle of this). The failure
calls are then just faster confirmations of a failure, but ultimately we
can't be they encompass all the failure cases. Similarly success might be
fleeting, and the store might have to reinstall the receipt later if it was
lost (e.g., was saved on a computer that crashed without persisting and
syncing the receipt). But at least this lets the store quickly inform the
user (e.g., through email) that the purchase was made or was cancelled.
The store should still be ready to confirm the receipts and resolve
problems of missing receipts later.

My concern though is that this is not a very safe operation. There is
certainly a race condition between the time the app is retrieved and the
time it is re-saved; if someone else is adding a receipt then that might
get wiped. But more concerning is why we should trust a store to do this
at all. There are at least two entities that have access to the
application: the store where it was originally purchased, and the
application itself. But you can also imagine "switching" stores, which
does not necessarily make the original receipts invalid (they represent
purchases that may still be valid). The receipts really belong to the
user, and while they might not be valid and it is the prerogative of the
application to respect or even pay attention to the receipts, it feels like
receipts should not be so easily overwritten.

One option would be to always append receipts, so that install() could
never delete anything. Another option (noted in my inline comments) would
be to have a method specifically to append receipts. (If it was a method
like navigator.mozApps.addReceipt(origin, receipt) then, for better or
worse, we could allow other stores than the original installing store to
add receipts.) In either case this leaves no way to invalidate receipts,
so yet another method would be required for that. If we look into the
receipt itself we could see if the caller can reasonably be trusted to
remove the receipt (e.g., only the app or the originating store can
invalidate a receipt). We could also choose (entirely on the preference of
the user agent) to keep invalidated receipts (e.g., perhaps in an
.invalidReceipts property of apps), or throw them away. Keeping them would
mostly be interesting leave some record for the user to look at all the
account activity for the app.



2. Updating the manifest

The manifest, present at a particular URL, should reasonably be seen as
describing the application as deployed on the server. Servers get updated
on their own schedule, and old versions of applications are typically not
supported. As such I think we should make a best-effort attempt at keeping
the manifest up to date, while also ensuring that the application record is
always available (even if the manifest disappears). Developers who really
want to force an update (e.g., to test their changes) can still use
mozApps.install().

It's not clear what the behavior should be when a store or app tries to
reinstall an already-installed application. This forces an update of the
manifest, but that should happen eventually on its own anyway. install()
can also update the installData (or receipts, or whatever), but maybe (at
least with receipts) we can make that "safe" (so that it requires no user
confirmation - certainly I can see no way that we can meaningfully show the
user what reinstallation would mean, so I don't know what the user could
intelligently confirm). I am inclined to suggest that reinstallation
should always be allowed, without confirmation, unless it would changed the
installOrigin (and we can intelligently tell a user what changing
installOrigin means). In turn, we need to design other parts of the
installation process to facilitate no-confirmation reinstallation.



3. Permissions

(This is getting a little more speculative.)

It seems like giving apps permissions is something we at least want to
think about. I don't think we have really established goals here, but I
think what I suggest in 2 has some implications. Specifically, we can't
put required permissions in an application manifest, because we can't
(without confirmation) give an application new permissions if it's added to
the manifest.

Rather I think we should put a list of requested permissions in the
manifest. This allows us to ask, all at once, for a bunch of permissions,
and makes it somewhat more reliable that an application will get the full
set of permissions (e.g., that a user won't simply not notice some
permission requests). We might also not even allow the application access
to other permissions not requested (as a kind of protection against XSS).
But if the permissions listed in the manifest indicate only permission
requests, then we can update them in the background and ask the user at a
different time if they want to grant the permissions. Compared to
Android-style permission grants we also keep the application from creating
an ultimatum where the user must either cancel the entire use of the
application, or give it everything it wants.

I also think that in the presence of sync it would not be responsible to do
installation and the granting of permissions at the same time - granting
permission to my home computer webcam is not the same as my phone camera,
for instance, and I would expect to be asked about it on a per-device
basis. I don't think however that we need to actually install (with
confirmation) each application on each device.



I think this concludes my API notes/thoughts.

Benjamin Smedberg

unread,
Jan 10, 2012, 10:43:20 AM1/10/12
to Fabrice Desré, dev-pl...@lists.mozilla.org
On 1/3/2012 6:16 PM, Fabrice Desré wrote:
> Since about a year, people in Labs and Mobile have been experimenting
> with an API to provide first class apps management through the DOM.
>
> We landed some support for this in m-c (bound to navigator.mozApps) that
> we use for b2g, but we'd like to get feedback on the API.
>
> I posted an updated IDL here:
> https://etherpad.mozilla.org/openwebapps-api
>
> Comments welcome!
I'm primarily concerned that we're treating webapps as a hugely
different thing than "a website loaded in your browser". For instance,
today the news is about "www.cuttherope.ie". Which, after you play a few
levels, says: "To play this [level], come back in Internet Explorer 9
and pin the game to your taksbar!". Even if you remove the reference to
IE, I really don't want sites dictating to me whether I must use their
app in my browser, in an app tab, or separately "installed".

I don't think we should be exposing an API which allows a website/app to
check whether the user has in fact "installed" the app, rather than just
opening it in their browser (either as a regular tab or a pinned tab).
Obviously we will need to support receipt management in either case, so
probably the notion of "do I have a receipt" and "what is the
installation status" should probably be separate.

--BDS

Andreas Gal

unread,
Jan 10, 2012, 11:07:52 AM1/10/12
to Benjamin Smedberg, Mike Hanson, Fabrice Desré, dev-platform
> I'm primarily concerned that we're treating webapps as a hugely different thing than "a website loaded in your browser". For instance, today the news is about "www.cuttherope.ie". Which, after you play a few levels, says: "To play this [level], come back in Internet Explorer 9 and pin the game to your taksbar!". Even if you remove the reference to IE, I really don't want sites dictating to me whether I must use their app in my browser, in an app tab, or separately "installed".
>
> I don't think we should be exposing an API which allows a website/app to check whether the user has in fact "installed" the app, rather than just opening it in their browser (either as a regular tab or a pinned tab). Obviously we will need to support receipt management in either case, so probably the notion of "do I have a receipt" and "what is the installation status" should probably be separate.
>

This is a really interesting perspective, and not something I have thought about before. Why would a site want to know whether its installed or not, receipts for paid apps aside? All the obvious differences in app behavior should be detected based on capabilities, not based on installed/not-installed (e.g. fullscreen or not fullscreen). I think I could be convinced to drop self-detection (stores will still need to enumerate installed apps obviously). Mike, what do you think?

Andreas

Fabrice Desré

unread,
Jan 10, 2012, 11:41:06 AM1/10/12
to Andreas Gal, Mike Hanson, Benjamin Smedberg, dev-platform
Thanks Benjamin for commenting on this. We'll discuss this tomorrow
since the apps team is having a work week in MV, and we'll take this
input in consideration.

On 01/10/2012 08:07 AM, Andreas Gal wrote:

> This is a really interesting perspective, and not something I have
> thought about before. Why would a site want to know whether its
> installed or not, receipts for paid apps aside? All the obvious
> differences in app behavior should be detected based on capabilities,
> not based on installed/not-installed (e.g. fullscreen or not
> fullscreen). I think I could be convinced to drop self-detection (stores
> will still need to enumerate installed apps obviously). Mike, what do
> you think?

Not speaking on Mike's behalf, but the only use case I heard of for the
amInstalled() functionality is that websites could use it to show an
"Install" button if the app is not installed.

Fabrice
--
Fabrice Desré
WebAPI Team
Mozilla Corporation

Mounir Lamouri

unread,
Jan 10, 2012, 12:50:23 PM1/10/12
to dev-pl...@lists.mozilla.org
On 01/06/2012 09:22 PM, Fabrice Desré wrote:
> Since about a year, people in Labs and Mobile have been experimenting
> with an API to provide first class apps management through the DOM.
>
> We landed some support for this in m-c (bound to navigator.mozApps) that
> we use for b2g, but we'd like to get more feedback on the API.
>
> I posted an updated IDL here:
> https://etherpad.mozilla.org/openwebapps-api

First of all, thank you for working on that: I've heard you did an
awesome job! :)

Regarding the comments, you will find a few random ones below.

You shouldn't use mozIDOMApplicationRegistryError with an integer as a
code error but you should use a string instead. Basically, you should
have an interface inheriting from DOMError [1] and .name will contain
the error name. Constants integer are considered bad.
DOMError isn't implemented yet in Gecko [2] so you might want to open a
bug and make it dependent on [2]. Though, using a string instead of an
integer is something you should do even if we don't have DOMError
implemented yet.

I don't really like the name 'mozIDOMApplicationOp'. Usually,
abbreviating words (especially for an interface) isn't a good idea. In
addition, the pattern you seem to use is very close to the requests
objects in IndexedDB or WebSMS. You should probably renamed the
interface [mozIDOM]ApplicationRequest. Also, for consistency, you should
change this interface to make it more like the request objects in the
mentioned APIs:
First of all, you need a |readonly attribute DOMString readyState| that
gives the current state and a |readonly attribute DOMError? error| that
returns the error object (or null if there is no error).
In addition, you should make sure that |result| is returning null until
the success event is fired. With that configuration, |result| should be
null if the error event fired and have a value if the success event
fired. Opposite thing for |error|. You don't want |result| to return an
error object as you API seems to say.

Some interfaces seem to need to inherit from nsIDOMEventTarget:
mozIDOMApplicationRegistry and mozIDOMApplicationOp if nothing changes.

It seems that the API doesn't allow an application to know when it is
uninstalled. Wouldn't that be useful to have applications cleaning there
stuff like cache, configuration files, etc. when they are uninstalled?

Should we have an enumerate method that is fully async? That means it
returns one value and you have to ask for the next one asynchronously?
That a bit harder to use but it prevents returning a huge array. Depends
on how big we believe the array is going to weight in memory I guess.

A note for later: I think it's better to show interfaces in an WebIDL
format to review them because our IDL format is missing some features
like "this attribute can be null" (with '?') and |jsval| is obfuscating
the API because it's not clear what it is actually representing. You are
also required to inherit from nsISupports which adds useless noise.

[1]
http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-domerror
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=705640

Thanks,
--
Mounir

Henri Sivonen

unread,
Jan 11, 2012, 5:13:05 AM1/11/12
to dev-pl...@lists.mozilla.org
On Tue, Jan 10, 2012 at 6:41 PM, Fabrice Desré <fab...@mozilla.com> wrote:
> Not speaking on Mike's behalf, but the only use case I heard of for the
> amInstalled() functionality is that websites could use it to show an
> "Install" button if the app is not installed.

Why isn't app installation after navigating to an app fully a browser
chrome-level thing? We already support pinning anything as an app tab.
Given that there are legacy Web apps that don't know about an
installation API but can already be pinned by initiating the pinning
action from browser chrome, how is it an improvement to get apps
themselves to use an API to make them part of the UI flow?

Do we assume that users don't grok UI that's not inside the content
area of the browser?

I really don't want Web apps that aren't "installed" to be able to
refuse to function or to be able to nag about installation when I have
just navigated to them in the traditional way.

--
Henri Sivonen
hsiv...@iki.fi
http://hsivonen.iki.fi/

Andreas Gal

unread,
Jan 11, 2012, 8:34:34 AM1/11/12
to Henri Sivonen, dev-platform, Alex Limi

Limi (cc'ed) had objections to that. This was definitely part of the initial design. When chrome sees a manifest and we haven't asked to install it yet, we pop up a dialog. I think Limi's concerns were that this is an interaction the user didn't initiate. Limi, can you fill in the details here? I think you had some additional arguments as well. I am not saying that I agree with Limi 100% on this one, just saying there are a couple reasons and arguments we should hear out :)

Andreas
> _______________________________________________
> dev-platform mailing list
> dev-pl...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-platform

Henri Sivonen

unread,
Jan 11, 2012, 8:51:20 AM1/11/12
to Andreas Gal, dev-platform, Alex Limi
On Wed, Jan 11, 2012 at 3:34 PM, Andreas Gal <g...@mozilla.com> wrote:
> When chrome sees a manifest and we haven't asked to install it yet, we pop up a dialog.

A dialog would be pretty disruptive. I was thinking of some indicator
near the location bar indicating the current page is installable.
Kinda like sites used to be able to declaratively indicate that they
were subscribable (via RSS).

Andreas Gal

unread,
Jan 11, 2012, 8:54:24 AM1/11/12
to Henri Sivonen, dev-platform, Alex Limi

Yeah, my original thinking was a door hanger, and Limi didn't like that. I raised the same alternative you are proposing, some indicator in the URL bar people can click on to install, but Limi countered that thats something people are unlikely to see. You want to go to page X and you are starring at the content as its loaded. You don't care too much about some indicator or icon somewhere up in Chrome code at this moment, so you are unlikely to discover it. He used RSS as an example of what actually is pretty poor design I think. My memory is spotty, lets let Limi speak for himself :)

Andreas

Jesper Kristensen

unread,
Jan 11, 2012, 1:12:58 PM1/11/12
to
Den 11-01-2012 14:51, Henri Sivonen skrev:
> On Wed, Jan 11, 2012 at 3:34 PM, Andreas Gal<g...@mozilla.com> wrote:
>> When chrome sees a manifest and we haven't asked to install it yet, we pop up a dialog.
>
> A dialog would be pretty disruptive. I was thinking of some indicator
> near the location bar indicating the current page is installable.
> Kinda like sites used to be able to declaratively indicate that they
> were subscribable (via RSS).
>

It sounds similar to
http://blogs.msdn.com/b/ie/archive/2011/10/20/connect-your-web-site-to-your-windows-8-app.aspx

Mike Hanson

unread,
Jan 11, 2012, 2:24:38 PM1/11/12
to Andreas Gal, Fabrice Desré, Benjamin Smedberg, dev-platform
Pardon for slowness, catching up inbetween work week sessions.

I see three use cases for an app finding out whether it's installed:

* To retrieve install-time metadata (which Ben properly notes could be separated from the "am I installed" question)

* To find out whether the manifest that the user agent has is out of date (which could be addressed through UA features - the UA could use page-level metadata to retrieve the manifest and detect changes)

* To guide the user to an installation flow, and not pester them if it's already installed. I hadn't really thought that much about the using-this-for-evil possibilities, and you raise a good point - the use of this bit by malicious apps would be annoying.

I think if we don't allow self-discovery, we need to make sure the UA's self-install flow is really smooth - the earliest attempts at detecting-an-app-and-prompting-for-install were quite annoying. The potential abuse does give me pause on exposing this to content. (and later posts in this thread seem to confirm that point).

m

On Jan 10, 2012, at 8:07 AM, Andreas Gal wrote:

>> I'm primarily concerned that we're treating webapps as a hugely different thing than "a website loaded in your browser". For instance, today the news is about "www.cuttherope.ie". Which, after you play a few levels, says: "To play this [level], come back in Internet Explorer 9 and pin the game to your taksbar!". Even if you remove the reference to IE, I really don't want sites dictating to me whether I must use their app in my browser, in an app tab, or separately "installed".
>>
>> I don't think we should be exposing an API which allows a website/app to check whether the user has in fact "installed" the app, rather than just opening it in their browser (either as a regular tab or a pinned tab). Obviously we will need to support receipt management in either case, so probably the notion of "do I have a receipt" and "what is the installation status" should probably be separate.
>>
>
> This is a really interesting perspective, and not something I have thought about before. Why would a site want to know whether its installed or not, receipts for paid apps aside? All the obvious differences in app behavior should be detected based on capabilities, not based on installed/not-installed (e.g. fullscreen or not fullscreen). I think I could be convinced to drop self-detection (stores will still need to enumerate installed apps obviously). Mike, what do you think?
>
> Andreas

0 new messages