diff --git a/README.md b/README.md index 1f70345..1468dcb 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,8 @@ _Note: the name of this event, i.e. `cancel` instead of something like `beforecl For abuse prevention purposes, this event only fires if the page has received user activation. Furthermore, once it fires for one `CloseWatcher` instance, it will not fire again for any `CloseWatcher` instances until the page again gets user activation. This ensures that if the user sends a close signal twice in a row without any intervening user activation, the signal definitely goes through, destroying the `CloseWatcher`. +_Currently the Esc key itself counts as user activation, so on desktop platforms where that is the close signal, this clause has no effect. That is, there is always a recent user activation and so `cancel` will always be fired. See discussion in [#7](https://github.com/WICG/close-watcher/issues/7) about whether this is a good or bad thing._ + Note that the `cancel` event is not fired when the user navigates away from the page: i.e., it has no overlap with `beforeunload`. `beforeunload` remains the best way to confirm a page unload, with `cancel` only used for confirming a close signal. If called from within transient user activation, `watcher.signalClosed()` also invokes `cancel` event handlers, which would trigger event listeners like the above example code. If called without user activation, then it skips straight to the `close` event. diff --git a/spec.bs b/spec.bs index c2bf81a..0ed42e0 100644 --- a/spec.bs +++ b/spec.bs @@ -148,13 +148,20 @@ A close watcher is a [=struct=] with the following [=struct/it
@@ -224,10 +231,13 @@ Objects implementing the {{CloseWatcher}} interface must support the signal close on a {{CloseWatcher}} |closeWatcher|: 1. If |closeWatcher|'s [=CloseWatcher/is active=] is false, then return. + 1. If |closeWatcher|'s [=CloseWatcher/firing cancel event=] is true, then return. 1. Let |window| be |closeWatcher|'s [=relevant global object=]. 1. If |window|'s [=associated Document=] is [=Document/fully active=], and |window|'s [=timestamp of last activation used for close watchers=] does not equal |window|'s last activation timestamp, then: - 1. Let |shouldContinue| be the result of [=firing an event=] named {{CloseWatcher/cancel}} at |closeWatcher|, with the {{Event/cancelable}} attribute initialized to true. 1. Set |window|'s [=timestamp of last activation used for close watchers=] to |window|'s last activation timestamp. + 1. Set |closeWatcher|'s [=CloseWatcher/firing cancel event=] to true. + 1. Let |shouldContinue| be the result of [=firing an event=] named {{CloseWatcher/cancel}} at |closeWatcher|, with the {{Event/cancelable}} attribute initialized to true. + 1. Set |closeWatcher|'s [=CloseWatcher/firing cancel event=] to false. 1. If |shouldContinue| is false, then return. 1. If |window|'s [=associated Document=] is [=Document/fully active=], then [=fire an event=] named {{CloseWatcher/close}} at |closeWatcher|. 1. Set |closeWatcher|'s [=CloseWatcher/is active=] to false. @@ -248,12 +258,12 @@ Update HTML's In the {{HTMLDialogElement/showModal()}} steps, after adding |subject| to the [=top layer=], append the following step: - 1. If we [=can create a developer-controlled close watcher=] given |subject|'s [=Node/node document=], then [=stack/push=] a new [=close watcher=] on |subject|'s [=Node/node document=]'s [=close watcher stack=], with its [=struct/items=] set as follows: + 1. If the result of [=checking if we can create a developer-controlled close watcher=] given |subject|'s [=relevant global object=] is true, then [=stack/push=] a new [=close watcher=] on |subject|'s [=Node/node document=]'s [=close watcher stack=], with its [=struct/items=] set as follows: * [=close watcher/close action=] being to [=cancel the dialog=] |subject| * [=close watcher/is still valid=] steps being to return true if |subject|'s [=Node/node document=] is blocked by the modal dialog |subject|, and return false otherwise * [=close watcher/blocks further developer-controlled close watchers=] being true -
If we [=cannot create a developer-controlled close watcher=], then this modal dialog will not respond to [=close signals=]. The {{HTMLDialogElement/showModal()}} method proceeds without any exception or other indication of this, although the browser could [=report a warning to the console=]. +
If we cannot create a developer-controlled close watcher, then this modal dialog will not respond to [=close signals=]. The {{HTMLDialogElement/showModal()}} method proceeds without any exception or other indication of this, although the browser could [=report a warning to the console=]. Replace the "Canceling dialogs" section entirely with the following definition. (The previous prose about providing a user interface to cancel such dialogs, and the task-queuing, is now handled by the infrastructure in [[#close-signals]].)