<div class="gmail_quote">On Thu, Feb 9, 2012 at 9:53 AM, Jon Lee <span dir="ltr"><<a href="mailto:jonlee@apple.com" target="_blank">jonlee@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div style="word-wrap:break-word"><br><div><div><div>On Feb 8, 2012, at 5:41 PM, John Gregg wrote:</div><br><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">

<div style="word-wrap:break-word"><div>3. Use static functions on the notification constructor for permissions checks.<br>
<br>By moving them there, it allows us to remove window.webkitNotifications and the NotificationCenter class, cleaning up the API.<br></div></div></blockquote><div><br></div><div>I think that would be consistent with moving from a factory model to a constructor model.  The Feature-permissions effort was intended to create a common interface for handling permissions, but it may still be too far off and sticking with a scoped approach is more practical.  The only concern is that it is an implementation change that only partially reaches what has been spec'd, which might leave some continuing confusion among users of Notifications as to the authoritative version of the interface.</div>

</div></blockquote><div><br></div></div><div>Which missing aspects of the Feature permissions spec are you concerned about?</div></div></div></blockquote><div><br></div><div>I was only referring to the fact that the spec calls for a separate generic interface for permissions with a parameter that identifies the feature [FeaturePermissions.permissionLevel("notifications")], and in this case it would still be attached to the Notifications interface [Notifications.permissionLevel()].</div>

<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word">

<div>4. Adjust the permission functions.<br><br>WebKitNotification.permissionLevel() --> String<br>
<br>Similar to checkPermissions(), synchronous call. The name aligns with similar functionality in the DAP Feature Permissions spec [FEAT], but scoped specifically to Web Notifications. Returns one of three strings: "granted", "denied", and "default". This follows the current best practice from the WebApps WG where strings are being used instead of enums.<br>


<br>WebKitNotification.requestPermission(callback)<br><br>An asynchronous call, as it is currently. The callback specified includes one argument which represents the permission, similar to the return values in permissionLevel(). (Currently it is just a void callback.) If the user had already made a policy decision, then the callback is invoked immediately (with either "granted" or "denied"). Otherwise the UA may ask the user for permission, and the callback is invoked when the user makes a decision (cancelling the request does not invoke the callback). Any notifications posted in the meantime would be queued until then. Multiple calls to this function should just result in one visible request.<br>


</div></div></blockquote><div><br></div><div>This matches the FeaturePermissions spec with the exception of the decision as a parameter, which is reasonable though redundant since the current permission level is already easily read.  The queueing of notifications discussed later.</div>

</div></blockquote><div><br></div></div><div>It could work either way. But for me, it seems weird from a programming flow perspective to have to explicitly fetch the level again within the callback; I would expect the response to be included in some form as an argument.</div>

<div><br><blockquote type="cite"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word">

<div><br>5. Remove replaceId.</div><div><br></div><div>This could already be done by canceling a previous notification and posting a new one. The idea of replacing a notification with another one without alerting the user is a feature that we don't intend on supporting.</div>


</div></blockquote><div><br></div><div>Just so the use case is clear here, it is not equivalent to canceling and showing from the webapp's perspective, though it is to the browser.  The reason for replaceId is when the same application (e.g., Gmail) is open in multiple browser windows.  When a new message arrives, both tabs will discover this and lacking communication between them, attempt to show a notification.  But if both notifications are tagged as corresponding to the same real-world event, they are seamlessly merged and the user only sees one.</div>

</div></blockquote><div><br></div></div><div>But in this case, wouldn't the second notification just be ignored, instead of replacing the first notification?</div></div></div></blockquote><div><br></div><div>Ignored or replaced, you still need a way of tagging them.  I still think replacement is better, since it also gives you the benefit of the most recent information when it's something other than exact copies.  That brings up another use case when you do get frequent updates, say for chat notifications (one per incoming line of text, typically) - use a single replaceId for the chat session and just update it with the latest message. This can be done with cancel/show, but multiple chats or other notifications, the notifications would be constantly re-ordering and the end-user experience is not good.</div>

<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div>Also, does Chrome keep track of IDs that have been shown, even after the notification has been closed? For example, if one page gets the new email before the other, it posts a notification, the user clicks on that notification, and the page closes that notification _before_ the other page has had a chance to query Gmail's servers for new emails, does Chrome still remember that a notification of that ID was posted before?</div>

<div><br></div><div>Or does this only apply for notifications that are shown but not closed?</div></div></blockquote><div><br></div><div>The replacement logic in Chrome only applies for notifications that are still active (shown or in the display queue).  You are correct that there is a potential race condition that would allow the double show.  In practice (Gmail actually does this) I've never encountered this... I think Gmail's use of replaceId has probably saved me hundreds of duplicate notifications due to multiple tabs.</div>

<div><br></div><div>Overall my opinion on replaceId is that it's quite useful practically, and we already have real world examples of that usefulness. The argument against is it's too complicated?  I don't agree - chromium already does it, some platforms support it natively (e.g., Ubuntu NotifyOSD) and other user agents can easily do close+open internally if live-replacement is not practical.</div>

<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div style="word-wrap:break-word">

<div>6. Improve show() behavior.</div><div><br></div><div>
Calling show() when the site has been denied permission should call onerror(). If no decision was made, then the notification should remain queued, and only until after the user has decided should onshow() or onerror() be called. I also think show() can only be used once. Subsequent invocations should call onerror().</div>


</div></blockquote><div><br></div><div>The permission-denied behavior you want is as spec'd (error event).  The permission-unknown behavior you propose seems more difficult for authors, since at the point of calling show() it would be impossible to distinguish between being queued for space limitation and being queued waiting for permission.  If you limit this to the case where requestPermission() has already been called, as opposed to any permissionLevel=unknown state, that might make more sense.  We could even introduce a new constant for permissionLevel of "request-pending" which would make this easy to specify cleanly.</div>

</div></blockquote></div><br></div><div>I think authors should use available API. So those who choose not to use requestPermission() end up having to deal with that ambiguity. Also, why does that ambiguity need to be differentiated? How would a website change its behavior based on that knowledge?</div>
</div></blockquote><div><br></div><div>I assume permissions might change.  Maybe a user goes into their browser settings and reverts to the default permission.  The app doesn't know this and will continue showing notifications without knowing that these are queued up waiting for permission that hasn't been requested yet.  In the current design there is no ambiguity, because those show() calls will fail informing the app it needs to request permissions.</div>
<div><br></div><div>Adding the "request-pending" permission state separate from "unknown" (and queueing in the "request-pending" state only) would address that problem and allow for the deferred-show behavior you want.</div>
</div>