Bug 25463 - Desktop Notifications API
Summary: Desktop Notifications API
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore JavaScript (show other bugs)
Version: 528+ (Nightly build)
Hardware: PC Windows XP
: P2 Normal
Assignee: John Gregg
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-04-28 17:11 PDT by John Gregg
Modified: 2009-08-12 09:20 PDT (History)
12 users (show)

See Also:


Attachments
Patch implementing proposed API for worker notifications (54.43 KB, patch)
2009-04-28 17:30 PDT, John Gregg
no flags Details | Formatted Diff | Diff
Revised patch for Notifications (54.27 KB, patch)
2009-05-06 16:04 PDT, John Gregg
no flags Details | Formatted Diff | Diff
Notifications API for DOMWindow and WorkerContext (68.82 KB, patch)
2009-05-20 17:13 PDT, John Gregg
no flags Details | Formatted Diff | Diff
Notifications Patch (67.09 KB, patch)
2009-05-21 15:09 PDT, John Gregg
mjs: review-
Details | Formatted Diff | Diff
Notifications API with Permissions API (69.77 KB, patch)
2009-05-27 23:53 PDT, John Gregg
no flags Details | Formatted Diff | Diff
Notifications API, WebCore only (45.58 KB, patch)
2009-06-22 10:58 PDT, John Gregg
no flags Details | Formatted Diff | Diff
Notifications API, WebCore only (55.35 KB, patch)
2009-06-22 15:45 PDT, John Gregg
mjs: review-
Details | Formatted Diff | Diff
Notifications API, WebCore only (88.88 KB, patch)
2009-07-06 18:10 PDT, John Gregg
no flags Details | Formatted Diff | Diff
Notifications API, Tests and DumpRenderTree hooks (54.10 KB, patch)
2009-07-06 18:10 PDT, John Gregg
mjs: review-
Details | Formatted Diff | Diff
Notifications API, V8 Bindings (20.59 KB, patch)
2009-07-06 18:11 PDT, John Gregg
no flags Details | Formatted Diff | Diff
Notifications API, Core & JSC Bindings (88.89 KB, patch)
2009-07-06 18:14 PDT, John Gregg
no flags Details | Formatted Diff | Diff
Notifications API, Core & JSC Bindings (88.62 KB, patch)
2009-07-06 18:18 PDT, John Gregg
mjs: review-
Details | Formatted Diff | Diff
Notifications API, combined Core and Tests (157.39 KB, patch)
2009-07-23 10:54 PDT, John Gregg
no flags Details | Formatted Diff | Diff
Notifications API, combined Core and Tests (156.50 KB, patch)
2009-07-23 10:58 PDT, John Gregg
mjs: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description John Gregg 2009-04-28 17:11:37 PDT
Working on a new feature enabling workers to pop up notifications UI.  Prototyping this in chromium, but WebKit needs the Javascript API (will be protected behind a compile time flag which is default off).
Comment 1 John Gregg 2009-04-28 17:30:46 PDT
Created attachment 29871 [details]
Patch implementing proposed API for worker notifications

Proposed patch which implements the Notification API for workers.  

It requires a container such as Chromium to inject a custom Notifications interface which exposes the supported methods, and a NotificationProvider which actually does the rendering work.  It's also all disabled by a compile time flag since it is a prototype.
Comment 2 Sam Weinig 2009-04-28 18:33:43 PDT
Can you please provide a link to the specification this is from?
Comment 3 John Gregg 2009-04-28 18:50:48 PDT
Sure.  The notifications API has been in & out of the HTML5 spec over the last 6 months or so; right now it is not in the spec but I am hoping to use a prototype implementation to motivate things again and arrive at a spec that makes the most sense.

I circulated the design doc for this particular code on WHATWG last month:
http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-March/019113.html
Comment 4 Sam Weinig 2009-04-28 18:56:39 PDT
Given that we don't support Persistent Workers it doesn't seem like there is that much of a compelling use case for these since window.open() works just fine.  Do we really want to give authors another way to annoy our users with popups?
Comment 5 John Gregg 2009-04-28 19:21:51 PDT
That's fair, although there is more to it than window.open(): the user agent can manage the screen space on the desktop by queueing, stacking, etc., or relay to a different notification platform (e.g., Growl) if the user wants.  I'm hoping letting people try out an experimental feature will reveal the compelling use cases.  And I certainly agree about popups, but I think it fits into the current popup permissions world we already have.

In any case, I want to clean up some style problems with my patch (apologies, this is my first experience with webkit), so allow me to try it again and in the meantime I'm happy to discuss the motivation for the feature.
Comment 6 David Levin 2009-04-29 09:25:46 PDT
When I think of notifications from an html page, here's some use cases without persistent workers:
1. Calendar notifications about appointments.  If you look at something like Google Calendar, right now they do an alert pop up which has several problems for me as a user.
2. Email notifications from a tab that has my email.
3. Potentially IM notifications from in browser im clients.
etc.

Now these notifications do have the potential for abuse, but that can be mitigated by having them only be work for something that is installed like widgets.
Comment 7 Sam Weinig 2009-04-29 12:03:50 PDT
Why not use the options string passed to window.open() to inform the app that this window should be of a different style? 
Comment 8 Timothy Hatcher 2009-04-30 15:33:11 PDT
I find it really odd this is tied to workers in any way. Why prevent normal web pages that don't use/need workers from using notifications? 
Comment 9 John Gregg 2009-04-30 15:36:29 PDT
Timothy: agreed.  'Headless' persistent workers is the motivation, and there are good reasons to use shared workers for things like calendar notifications (don't want multiple tabs open to the same app to duplicate each other), so starting there but I would like to make this to available to pages as well.
Comment 10 Alexey Proskuryakov 2009-04-30 23:40:34 PDT
My understanding is that persistent workers are still at early design stages, and they will certainly require a lot of new browser UI functionality.
Comment 11 John Gregg 2009-05-06 16:04:21 PDT
Created attachment 30072 [details]
Revised patch for Notifications

Here is a new version of the patch with some code review feedback addressed.
Comment 12 John Gregg 2009-05-20 17:12:15 PDT
About to submit a new patch, which makes the Notification API available to regular pages via DOMWindow as well as workers via WorkerContext.  

Still the only code being proposed to add to WebKit is an interface from Javascript up to a client provider which will implement the security policy and do the display; and plumbing for event callbacks on Notification objects. 
Comment 13 John Gregg 2009-05-20 17:13:26 PDT
Created attachment 30517 [details]
Notifications API for DOMWindow and WorkerContext
Comment 14 Sam Weinig 2009-05-20 22:19:01 PDT
I believe without a compelling use case, we should not have this feature in WebKit.  As I see it, if we don't have persistent workers (which we don't and don't even yet agree if they are good idea), it seems like every thing here could be achieved with a new parameter to the window.open() feature string.
Comment 15 John Gregg 2009-05-21 10:20:39 PDT
The use cases are pretty clear: calendar reminders / new email, etc.  Anything that wants to alert the user. 

Here's why I think it's different from window.open() from the WebKit perspective:
 - The semantics of the interface are to alert the user, not necessarily to open a window.  If the user is idle, or the desktop is cluttered with other notifications, the user agent might not open a window immediately but queue it instead.  
 - If the user's preferences are configured so that web-app notifications go to Growl, e.g., the result is not opening a window.  This I think is the real compelling use case: allow the browser to enable web applications to use external desktop notification engines according to user prefs.

Suppose we dropped the createHTMLNotification(URL) interface entirely, and just had createNotification(icon, title, text, onclick-link)?  That moves it pretty far from window.open().  Would that be a reasonable place to start exploring the use cases?  


Comment 16 Andrew Wilson 2009-05-21 13:18:35 PDT
(In reply to comment #14)
> I believe without a compelling use case, we should not have this feature in
> WebKit.  As I see it, if we don't have persistent workers (which we don't and
> don't even yet agree if they are good idea), it seems like every thing here
> could be achieved with a new parameter to the window.open() feature string.
> 
As John mentioned, one use case is for applications like Calendar that want to display notifications to the user that doesn't rely on alert(). For an example of other use cases/prior art, you can look at the HTML5 extension APIs that are provided by the Palm WebOS for their Pre devices, which expose similar functionality. 

We are trying to address two cases:

1) Applications that want to display notifications with rich HTML/dynamic javascript. One simple example would be a calendar meeting notification that displays "time until meeting" via a dynamic countdown. These would be styled differently from standard popup windows, and would likely have other behavior that differs from popups (be non-focusable so they cannot receive keyboard input).
2) Some platforms have an alternate non-HTML, non-interactive notification format which the user may wish to use - Growl on the Mac is one example of this. Alternatively, some platforms may not allow HTML popups - Palm and Android phones have a specific icon + text format that they can display in their notification bar, and Ubuntu requires that all well-behaved apps use their standard libnotify APIs for displaying notifications.

The suggestion of window.open() to address use case #1 is reasonable, but it does not address the capabilities detection case (how can a web application detect that a given platform supports HTML notifications, so it can fall back to non-HTML notifications)? It is not a reasonable fallback to display a regular popup window in that case (this would especially break for mobile platforms that don't really support non-full-screen windows).

Additionally, window.open() gives the web application no way to interface with non-HTML notification systems like Growl. So window.open(), by itself, is not sufficient.

Another alternative would be to have a single notifications API that takes both an HTML URL and a fallback text+icon if HTML notifications aren't supported:

createNotification(url, altIcon, altTitle, altText);

If you could clarify your concerns further we can try to address them - there are at least a half-dozen teams within Google that are interested in using this, and we've also gotten some good feedback externally as well, so if you are looking for more use cases we can certainly provide them.
Comment 17 Andrew Wilson 2009-05-21 13:33:25 PDT
Speaking of prior art, this is similar to some of the functionality being exposed via Mozilla Jetpack for Firefox:

https://jetpack.mozillalabs.com/api.html

It sounds like ultimately they are planning on supporting full HTML notifications as well.
Comment 18 John Gregg 2009-05-21 15:09:21 PDT
Created attachment 30562 [details]
Notifications Patch

minor refactor based on review feedback.
Comment 19 Maciej Stachowiak 2009-05-21 20:03:37 PDT
Comment on attachment 30562 [details]
Notifications Patch

The comments in the bug seem to show a lack of consensus as to whether we want this feature and whether the API is appropriate. These design issues should be hashed out (perhaps on the mailing list) before submitting a patch for code review. Marking r- for now pending further discussion and rough consensus.
Comment 20 John Gregg 2009-05-26 11:29:14 PDT
I do appreciate the concerns and I would be very happy to discuss the design issues, but putting this out on the mailing list a second time has not generated any discussion.  How can we get to a rough consensus?
Comment 21 John Gregg 2009-05-27 23:53:44 PDT
Created attachment 30728 [details]
Notifications API with Permissions API

Added the permissions API as discussed on webkit-dev.
Comment 22 Michael Nordman 2009-05-28 12:37:22 PDT
> // Callback methods for the provider when events occur regarding the notification.
> void display();

I think the naming convention for methods like these are something like callDisplayListener().

> ACCESSOR_SETTER(NotificationOndisplay) 
> ACCESSOR_GETTER(NotificationOndisplay)
> ACCESSOR_SETTER(NotificationOnerror) 
> ACCESSOR_GETTER(NotificationOnerror)
> ACCESSOR_SETTER(NotificationOnclose) 
> ACCESSOR_GETTER(NotificationOnclose)

This technique of v8 bindings for event handler results in more code bloat then we really like. We end up with distinct boiler plate functions for each event attribute. There is another available to us that involves looking up the event attribute by name, resulting in one getter/setter pair for all event attributes.

It be great if the code generator just generated this gunk without intervention... but until that glorious day.

You can see that technique in use in DOMWindow (which has a good number of events), and also in these patches out for review for the DOMAppliationCache...

// see V8DOMApplicationCacheCustom.cpp
http://codereview.chromium.org/113554  

// see v8_custom.h and CodeGeneratorV8.pm for the voodoo required
// to use this over the default code bloaty technique
http://codereview.chromium.org/115531

Comment 23 John Gregg 2009-05-28 13:03:33 PDT
Okay, thanks.  I couldn't find a good example in the code that bound event listeners in a way that worked for both document and worker contexts (which I want for notifications), but it looks like the ApplicationCache code does, so will convert to that style.
Comment 24 Michael Nordman 2009-05-28 13:19:15 PDT
Heads up... I actually haven't worker'ified the appcache bindings yet. It *wants* to eventually work in workers too, but i haven't actually done that yet. Maybe I can pick up the details of what you do in that context :)

Comment 25 Eric Seidel (no email) 2009-06-18 17:00:26 PDT
Comment on attachment 30728 [details]
Notifications API with Permissions API

I have no idea who can review this.  This does not add JSC bindings (perhaps intentionally), which means that this is useless to main-line webkit.

Why don't we just land this on a branch instead?
Comment 26 John Gregg 2009-06-18 17:32:01 PDT
FYI, Maciej and Weinig, who helped workthrough the design issues, have told me offline they will be looking at this patch soon.

But to address your other points, this patch is just plumbing.  Even in V8 it doesn't do the actual work, it just defines an interface for notifications.  I think that's valuable to have shared in WebKit rather than added on by each browser, especially as we drive for this to be spec'd officially. 

You'll see that the V8 bindings there are effectively pass-throughs into a NotificationProvider interface implemented by the containing browser, where the real work happens depending on the platform.  That said, I would be happy to add JSC bindings which also pass-through, but without a NotificationProvider it wouldn't do anything.  Also I'd rather do it as a follow-up given the suggestions that this patch is already unwieldy. :)
Comment 27 John Gregg 2009-06-22 10:58:12 PDT
Created attachment 31655 [details]
Notifications API, WebCore only

Uploading a smaller version of the patch which contains the WebCore pieces only, no bindings.  This patch has no effect without the ENABLE_NOTIFICATIONS flag.
Comment 28 John Gregg 2009-06-22 15:45:47 PDT
Created attachment 31683 [details]
Notifications API, WebCore only

The last patch dropped ChangeLogs accidentally.  Replacing.
Comment 29 Maciej Stachowiak 2009-06-23 20:30:44 PDT
Comment on attachment 31683 [details]
Notifications API, WebCore only

Thanks for the patch! This will be a neat feature. Review- for now, to address the following comments:


- Might be clearer to refer to the guard as ENABLE(NOTIFICATIONS)

> This change adds an (experimental) HTML notification API, being prototyped in Chromium.  It's protected by compile-time feature flag ENABLE_NOTIFICATIONS.


- It sure is awkward having classes named "Notification" and "Notificiations". Is there any way to make the latter name more distinct, perhaps "NotificationCenter"?


- I'd suggest renaming m_HTML to m_isHTML to make it more clear that it's a flag, not content.


- m_fields is a pretty poor data member name - it doesn't really clarify what it holds. Perhaps m_parameters would be better. But then I'd want it to also hold the HTML flag and optional URL, so that show() doesn't have to contain an if statement. It seems like those are really parameters controlling display too, right?


- In Notification::show(), it seems that nothing prevents the notification from being shown twice in a row, overwriting m_id. That seems bad.


- In Notification::cancel(), nothing checks if the notification is currently showing. Since m_id is an int, this could lead to closing an entirely different notification.


- Having an integer ID for tracking the open notification seems like poor design anyway. Why not an object? This would allow double-show and double-cancel problems mentioned above to be handled in a clean way. Perhaps even the Notification object itself could be passed to the NotificationProvider's show() and cancel().


- It looks to me like Notification::dispatchDisplayEvent, dispatchErrorEvent and dispatchCloseEvent will not dispatch to the built-in event listeners in the right order - they should come between the capture phase listeners and the bubble phase listeners.


- Even more seriously, the dispatchEvent, addEventListener and removeEventListener appear to be no-ops. That's not a correct implementation of the EventTarget interface.


- As far as I can tell, display(), close() and error() are never called. A comment implies they would be called by the NotificationProvider, but the Notification object is not passed to NotificationProvider, so how can they be?


- Not that this has any practical effect, but why is the Notification IDL interface in the "threads" module?

> module threads {


- These files are cited in the ChangeLog but are missing from the patch, I should add that these sound like they would be incomplete for either JSC or V8 bindings.

* bindings/v8/custom/V8NotificationsCustom.cpp: Added.
* bindings/js/JSWorkerContextCustom.cpp:


- It's not clear from the patch why the show() and cancel() methods on Notification need to be [Custom].


- NotificationProvider seems a bit backwards as a name - as I understand it, this isn't something that provides notifications, but rather provides the cabability of displaying them, so something like NotificationListener, NotificationSink, NotificationView, NotificationClient might be a good name.


- Will this patch even compile with ENABLE(NOTIFICATIONS) turned on, since the bindings code appears to be missing?


- This is sort of an API-level question, but why is there a two-step process to create a notification and then show it? Is there a use case for creating a notification, keeping it around, and then showing it later?


- I don't think it's necessary to explicitly call m_notifications.clear in the WorkerContext destructor.


- Will the test case provided actually pass without the missing JS bindings code?
Comment 30 Sam Weinig 2009-06-23 20:34:18 PDT
One thing I must add is that we should probably prefix the feature since it is not a standard, ie, WebKitNotification.
Comment 31 John Gregg 2009-06-24 11:52:46 PDT
Thanks for taking the time to look at the patch and provide all the review comments!  I'm working on another revision now, but wanted to respond to your comments:

> - Might be clearer to refer to the guard as ENABLE(NOTIFICATIONS)
Ok, will do.

> - It sure is awkward having classes named "Notification" and "Notificiations".
> Is there any way to make the latter name more distinct, perhaps
> "NotificationCenter"?
Fair enough.  Will change.

>- Not that this has any practical effect, but why is the Notification IDL
>interface in the "threads" module?
>> module threads {
Again, because I followed WorkerContext as my model to get started. :X  I'll change that.

>- It's not clear from the patch why the show() and cancel() methods on
>Notification need to be [Custom].
I'll check that.

> - I'd suggest renaming m_HTML to m_isHTML to make it more clear that it's a
> flag, not content.
> - m_fields is a pretty poor data member name - it doesn't really clarify what
> it holds. Perhaps m_parameters would be better. But then I'd want it to also
> hold the HTML flag and optional URL, so that show() doesn't have to contain an
> if statement. It seems like those are really parameters controlling display
> too, right?
I'm renaming it to NotificationContents, which I think better reflects the distinction: either the contents of the notification are in a remote URL, or they are right here in the object.  

> - In Notification::show(), it seems that nothing prevents the notification from
> being shown twice in a row, overwriting m_id. That seems bad.
> - In Notification::cancel(), nothing checks if the notification is currently
> showing. Since m_id is an int, this could lead to closing an entirely different
> notification.
> - Having an integer ID for tracking the open notification seems like poor
> design anyway. Why not an object? This would allow double-show and
> double-cancel problems mentioned above to be handled in a clean way. Perhaps
> even the Notification object itself could be passed to the
> NotificationProvider's show() and cancel().
I'm removing the int and adding an m_isShowing to deal with the double-check.  NotificationProvider::show() already does take the object; I will make NotificationProvider::cancel() take the object as well in order to get rid of the ID.

>- It looks to me like Notification::dispatchDisplayEvent, dispatchErrorEvent
>and dispatchCloseEvent will not dispatch to the built-in event listeners in the
>right order - they should come between the capture phase listeners and the
>bubble phase listeners.
This is the part I understand the least, however I followed the model of the way WorkerContext.onmessage events are dispatched.  Is it possible that is wrong also?

>- Even more seriously, the dispatchEvent, addEventListener and
>removeEventListener appear to be no-ops. That's not a correct implementation of
>the EventTarget interface.
Yes, apologies.  I guess I stubbed that out and never fixed it.  Will do.

>- As far as I can tell, display(), close() and error() are never called. A
>comment implies they would be called by the NotificationProvider, but the
>Notification object is not passed to NotificationProvider, so how can they be?
Actually the Notification object _is_ a parameter of NotificationProvider::show().  I think I will make it the only parameter to simplify that API.

>- This is sort of an API-level question, but why is there a two-step process to
>create a notification and then show it? Is there a use case for creating a
>notification, keeping it around, and then showing it later?
That wasn't the use case I had in mind; it was to allow registration of event listeners (ondisplay, onclose) before showing.  Sort of like XMLHttpRequest lets you set things up between creation and send(). 

>- NotificationProvider seems a bit backwards as a name - as I understand it,
>this isn't something that provides notifications, but rather provides the
>cabability of displaying them, so something like NotificationListener,
>NotificationSink, NotificationView, NotificationClient might be a good name.
I was thinking "the thing that provides actual notification of the user", i.e, not a provider of notification _objects_, but a provider of notification itself. :)  Would NotificationPlatform be reasonable?  NotificationDisplay?  NotificationDisplayProvider?  View would be okay but is sort of a loaded term at least in Chromium.

>- These files are cited in the ChangeLog but are missing from the patch, I
>should add that these sound like they would be incomplete for either JSC or V8
>bindings.
>* bindings/v8/custom/V8NotificationsCustom.cpp: Added.
>* bindings/js/JSWorkerContextCustom.cpp:
Yeah, the ChangeLog entry is from an earlier iteration.  Originally this was only on workers and for JS bindings I returned a stub, so for a moment it time it was complete.

>- Will this patch even compile with ENABLE(NOTIFICATIONS) turned on, since the
>bindings code appears to be missing?
>- Will the test case provided actually pass without the missing JS bindings
>code?
missing bindings... so basically the answer is no. The test case belongs with bindings, which are not in this patch. I completely understand it is lame to check in a chromium-only build flag, on the other hand, the feature requires browser-level changes in addition to bindings to be valuable.  So if the patch is unacceptable with a chromium-only build flag even as an intermediate step, I will add JS bindings now. If that can wait, it would be less code to maintain as the feature iterates.

>One thing I must add is that we should probably prefix the feature since it is
>not a standard, ie, WebKitNotification.
I'm okay with that.
Comment 32 John Gregg 2009-07-06 18:10:29 PDT
Created attachment 32340 [details]
Notifications API, WebCore only
Comment 33 John Gregg 2009-07-06 18:10:59 PDT
Created attachment 32341 [details]
Notifications API, Tests and DumpRenderTree hooks
Comment 34 John Gregg 2009-07-06 18:11:18 PDT
Created attachment 32342 [details]
Notifications API, V8 Bindings
Comment 35 John Gregg 2009-07-06 18:14:09 PDT
Created attachment 32343 [details]
Notifications API, Core & JSC Bindings
Comment 36 John Gregg 2009-07-06 18:18:59 PDT
Created attachment 32344 [details]
Notifications API, Core & JSC Bindings
Comment 37 Maciej Stachowiak 2009-07-15 21:39:00 PDT
Loking at this now. I'm a little confused as to why there are 3 different patches, but I guess I'll figure it out soon enough.
Comment 38 John Gregg 2009-07-17 10:56:06 PDT
Multiple patches was just to allow distributed reviews if it made sense.  I was going to suggest that a Chromium reviewer could look at the V8 stuff, although due to V8 churn since I uploaded it I have to revise that patch anyway, so I took it out of the queue for now.
Comment 39 Adam Barth 2009-07-17 11:03:59 PDT
> although
> due to V8 churn since I uploaded it I have to revise that patch anyway, so I
> took it out of the queue for now.

Yeah, sorry you got hit by the DOM wrapper refactoring.  Most of those APIs have moved to JSDOMWrapper from V8Proxy.
Comment 40 Maciej Stachowiak 2009-07-20 21:41:41 PDT
Comment on attachment 32344 [details]
Notifications API, Core & JSC Bindings

This is looking much better! I still have some comments that I think need addressing. The main substantive issue is the dispatch logic still being buggy in various ways, and I also think there is a lot of unnecessary use of custom bindings which could be manual. r- to address remaining issues. I suggested test case ideas that could verify correctness of event dispatch logic. I'd also be happy to help further by email or IRC, or I could even try to make full test cases showing the bugs if my descriptions are too vague. r- for remaining issues.

> Index: JavaScriptCore/ChangeLog
> ===================================================================
> --- JavaScriptCore/ChangeLog	(revision 45576)
> +++ JavaScriptCore/ChangeLog	(working copy)
> @@ -1,3 +1,15 @@
> +2009-07-06  John Gregg  <johnnyg@google.com>
> +
> +        Reviewed by NOBODY (OOPS!).
> +
> +        Desktop Notifications API
> +        https://bugs.webkit.org/show_bug.cgi?id=25463
> +
> +        Adds ENABLE_NOTIFICATION flag.
> +
> +        * Configurations/FeatureDefines.xcconfig:
> +        * wtf/Platform.h:
> +
>  2009-07-06  Ada Chan  <adachan@apple.com>
>  
>          Reviewed by Darin Adler and Mark Rowe.
> Index: JavaScriptCore/Configurations/FeatureDefines.xcconfig
> ===================================================================
> --- JavaScriptCore/Configurations/FeatureDefines.xcconfig	(revision 45574)
> +++ JavaScriptCore/Configurations/FeatureDefines.xcconfig	(working copy)
> @@ -37,6 +37,7 @@ ENABLE_FILTERS = ;
>  ENABLE_GEOLOCATION = ;
>  ENABLE_ICONDATABASE = ENABLE_ICONDATABASE;
>  ENABLE_JAVASCRIPT_DEBUGGER = ENABLE_JAVASCRIPT_DEBUGGER;
> +ENABLE_NOTIFICATIONS = ;
>  ENABLE_OFFLINE_WEB_APPLICATIONS = ENABLE_OFFLINE_WEB_APPLICATIONS;
>  ENABLE_SVG = ENABLE_SVG;
>  ENABLE_SVG_ANIMATION = ENABLE_SVG_ANIMATION;
> @@ -51,4 +52,4 @@ ENABLE_WORKERS = ENABLE_WORKERS;
>  ENABLE_XPATH = ENABLE_XPATH;
>  ENABLE_XSLT = ENABLE_XSLT;
>  
> -FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_DATABASE) $(ENABLE_DOM_STORAGE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XPATH) $(ENABLE_XSLT);
> +FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_DATABASE) $(ENABLE_DOM_STORAGE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XPATH) $(ENABLE_XSLT);
> Index: JavaScriptCore/wtf/Platform.h
> ===================================================================
> --- JavaScriptCore/wtf/Platform.h	(revision 45574)
> +++ JavaScriptCore/wtf/Platform.h	(working copy)
> @@ -514,6 +514,10 @@
>  #define ENABLE_GEOLOCATION 0
>  #endif
>  
> +#if !defined(ENABLE_NOTIFICATIONS)
> +#define ENABLE_NOTIFICATIONS 0
> +#endif
> +
>  #if !defined(ENABLE_TEXT_CARET)
>  #define ENABLE_TEXT_CARET 1
>  #endif
> Index: WebCore/ChangeLog
> ===================================================================
> --- WebCore/ChangeLog	(revision 45576)
> +++ WebCore/ChangeLog	(working copy)
> @@ -1,3 +1,105 @@
> +2009-07-06  John Gregg  <johnnyg@google.com>
> +
> +        Reviewed by NOBODY (OOPS!).
> +
> +        Desktop Notifications API
> +        https://bugs.webkit.org/show_bug.cgi?id=25463
> +
> +        Adds an implementation of desktop notifications, behind the compile-time
> +        flag ENABLE(NOTIFICATIONS).  This code simply relays calls on the JavaScript
> +        API through a NotificationProvider interface, which must provide the services
> +        to actually notify the user and manage the desktop.  This provider is injected
> +        into WebKit through the ChromeClient for normal page contexts and through the
> +        WorkerThread for worker contexts.
> +
> +        A permissions API is defined on a per-origin basis, which allows a web page
> +        to check if its origin is allowed to show desktop notifications, and to request
> +        permission for its origin.
> +
> +        * Configurations/FeatureDefines.xcconfig:
> +        * DerivedSources.cpp:
> +        * DerivedSources.make:
> +        * GNUmakefile.am:
> +        * WebCore.vcproj/WebCore.vcproj:
> +        * WebCore.vcproj/WebCoreCommon.vsprops:
> +        * WebCore.xcodeproj/project.pbxproj:
> +        * bindings/js/JSDOMWindowCustom.cpp:
> +        (WebCore::JSDOMWindow::notifications):
> +        * bindings/js/JSDesktopNotificationsCustom.cpp: Added.
> +        (WebCore::JSNotificationCenter::createHTMLNotification):
> +        (WebCore::JSNotificationCenter::createNotification):
> +        (WebCore::JSNotificationCenter::checkPermission):
> +        (WebCore::JSNotificationCenter::requestPermission):
> +        * loader/EmptyClients.h:
> +        (WebCore::EmptyChromeClient::notificationProvider):
> +        * notifications: Added.
> +        * notifications/Notification.cpp: Added.
> +        (WebCore::Notification::Notification):
> +        (WebCore::Notification::~Notification):
> +        (WebCore::Notification::show):
> +        (WebCore::Notification::cancel):
> +        (WebCore::Notification::dispatchDisplayEvent):
> +        (WebCore::Notification::dispatchErrorEvent):
> +        (WebCore::Notification::dispatchCloseEvent):
> +        (WebCore::Notification::addEventListener):
> +        (WebCore::Notification::removeEventListener):
> +        (WebCore::Notification::dispatchEvent):
> +        (WebCore::Notification::display):
> +        (WebCore::Notification::error):
> +        (WebCore::Notification::close):
> +        * notifications/Notification.h: Added.
> +        (WebCore::Notification::create):
> +        (WebCore::Notification::isHTML):
> +        (WebCore::Notification::url):
> +        (WebCore::Notification::contents):
> +        (WebCore::Notification::ondisplay):
> +        (WebCore::Notification::setOndisplay):
> +        (WebCore::Notification::onerror):
> +        (WebCore::Notification::setOnerror):
> +        (WebCore::Notification::onclose):
> +        (WebCore::Notification::setOnclose):
> +        (WebCore::Notification::scriptExecutionContext):
> +        (WebCore::Notification::refEventTarget):
> +        (WebCore::Notification::derefEventTarget):
> +        * notifications/Notification.idl: Added.
> +        * notifications/NotificationCenter.cpp: Added.
> +        (WebCore::NotificationCenter::NotificationCenter):
> +        (WebCore::NotificationCenter::checkPermission):
> +        (WebCore::NotificationCenter::requestPermission):
> +        * notifications/NotificationCenter.h: Added.
> +        (WebCore::NotificationCenter::create):
> +        (WebCore::NotificationCenter::createHTMLNotification):
> +        (WebCore::NotificationCenter::createNotification):
> +        (WebCore::NotificationCenter::context):
> +        (WebCore::NotificationCenter::provider):
> +        * notifications/NotificationCenter.idl: Added.
> +        * notifications/NotificationContents.h: Added.
> +        (WebCore::NotificationContents::NotificationContents):
> +        (WebCore::NotificationContents::icon):
> +        (WebCore::NotificationContents::title):
> +        (WebCore::NotificationContents::body):
> +        * notifications/NotificationProvider.h: Added.
> +        (WebCore::NotificationProvider::):
> +        (WebCore::NotificationProvider::~NotificationProvider):
> +        * page/Chrome.cpp:
> +        (WebCore::Chrome::notificationProvider):
> +        * page/Chrome.h:
> +        * page/ChromeClient.h:
> +        * page/DOMWindow.cpp:
> +        (WebCore::DOMWindow::clear):
> +        (WebCore::DOMWindow::webkitNotifications):
> +        * page/DOMWindow.h:
> +        * page/DOMWindow.idl:
> +        * page/Page.h:
> +        * workers/WorkerContext.cpp:
> +        (WebCore::WorkerContext::~WorkerContext):
> +        (WebCore::WorkerContext::webkitNotifications):
> +        * workers/WorkerContext.h:
> +        * workers/WorkerContext.idl:
> +        * workers/WorkerThread.h:
> +        (WebCore::WorkerThread::getNotificationProvider):
> +        (WebCore::WorkerThread::setNotificationProvider):
> +
>  2009-07-06  Eric Carlson  <eric.carlson@apple.com>
>  
>          Reviewed by Simon Fraser.
> Index: WebCore/DerivedSources.cpp
> ===================================================================
> --- WebCore/DerivedSources.cpp	(revision 45574)
> +++ WebCore/DerivedSources.cpp	(working copy)
> @@ -162,6 +162,8 @@
>  #include "JSNodeIterator.cpp"
>  #include "JSNodeList.cpp"
>  #include "JSNotation.cpp"
> +#include "JSNotificationCenter.cpp"
> +#include "JSNotification.cpp"
>  #include "JSOverflowEvent.cpp"
>  #include "JSPlugin.cpp"
>  #include "JSPluginArray.cpp"
> Index: WebCore/DerivedSources.make
> ===================================================================
> --- WebCore/DerivedSources.make	(revision 45574)
> +++ WebCore/DerivedSources.make	(working copy)
> @@ -34,6 +34,7 @@ VPATH = \
>      $(WebCore)/html \
>      $(WebCore)/inspector \
>      $(WebCore)/loader/appcache \
> +    $(WebCore)/notifications \
>      $(WebCore)/page \
>      $(WebCore)/plugins \
>      $(WebCore)/storage \
> @@ -188,6 +189,8 @@ DOM_CLASSES = \
>      NodeIterator \
>      NodeList \
>      Notation \
> +    Notification \
> +    NotificationCenter \
>      OverflowEvent \
>      Plugin \
>      PluginArray \
> @@ -678,7 +681,7 @@ endif
>  # JavaScript bindings
>  
>  GENERATE_BINDINGS = perl -I $(WebCore)/bindings/scripts $(WebCore)/bindings/scripts/generate-bindings.pl \
> -    --include dom --include html --include css --include page --include xml --include svg --outputDir .
> +    --include dom --include html --include css --include page --include notifications --include xml --include svg --outputDir .
>  
>  GENERATE_BINDINGS_SCRIPTS = \
>      bindings/scripts/CodeGenerator.pm \
> Index: WebCore/GNUmakefile.am
> ===================================================================
> --- WebCore/GNUmakefile.am	(revision 45574)
> +++ WebCore/GNUmakefile.am	(working copy)
> @@ -25,6 +25,7 @@ webcore_cppflags += \
>  	-I$(srcdir)/WebCore/loader/appcache \
>  	-I$(srcdir)/WebCore/loader/archive \
>  	-I$(srcdir)/WebCore/loader/icon \
> +	-I$(srcdir)/WebCore/notifications \
>  	-I$(srcdir)/WebCore/page \
>  	-I$(srcdir)/WebCore/page/animation \
>  	-I$(srcdir)/WebCore/platform \
> @@ -231,6 +232,8 @@ IDL_BINDINGS += \
>  	WebCore/html/VoidCallback.idl \
>  	WebCore/inspector/JavaScriptCallFrame.idl \
>  	WebCore/inspector/InspectorController.idl \
> +	WebCore/notifications/Notification.idl \
> +	WebCore/notifications/NotificationCenter.idl \
>  	WebCore/page/BarInfo.idl \
>  	WebCore/page/Console.idl \
>  	WebCore/page/Coordinates.idl \
> @@ -2428,6 +2431,24 @@ webcoregtk_sources += \
>  	WebCore/platform/gtk/GeolocationServiceGtk.h
>  endif # END ENABLE_GEOLOCATION
>  
> +# ----
> +# Notifications support
> +# ----
> +if ENABLE_NOTIFICATIONS
> +FEATURE_DEFINES_JAVASCRIPT += ENABLE_NOTIFICATIONS=1
> +
> +webcore_cppflags += \
> +	-DENABLE_NOTIFICATIONS=1
> +
> +webcore_sources += \
> +	WebCore/notifications/Notification.cpp \
> +	WebCore/notifications/Notification.h \
> +	WebCore/notifications/NotificationCenter.cpp \
> +	WebCore/notifications/NotificationCenter.h \
> +	WebCore/notifications/NotificationProvider.h \
> +	WebCore/notifications/NotificationContents.h
> +
> +endif # END ENABLE_NOTIFICATIONS
>  
>  # ----
>  # SVG Support
> Index: WebCore/Configurations/FeatureDefines.xcconfig
> ===================================================================
> --- WebCore/Configurations/FeatureDefines.xcconfig	(revision 45574)
> +++ WebCore/Configurations/FeatureDefines.xcconfig	(working copy)
> @@ -38,6 +38,7 @@ ENABLE_FILTERS = ;
>  ENABLE_GEOLOCATION = ;
>  ENABLE_ICONDATABASE = ENABLE_ICONDATABASE;
>  ENABLE_JAVASCRIPT_DEBUGGER = ENABLE_JAVASCRIPT_DEBUGGER;
> +ENABLE_NOTIFICATIONS = ;
>  ENABLE_OFFLINE_WEB_APPLICATIONS = ENABLE_OFFLINE_WEB_APPLICATIONS;
>  ENABLE_SVG = ENABLE_SVG;
>  ENABLE_SVG_ANIMATION = ENABLE_SVG_ANIMATION;
> @@ -52,4 +53,5 @@ ENABLE_WORKERS = ENABLE_WORKERS;
>  ENABLE_XPATH = ENABLE_XPATH;
>  ENABLE_XSLT = ENABLE_XSLT;
>  
> -FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DOM_STORAGE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XPATH) $(ENABLE_XSLT);
> +FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DOM_STORAGE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XPATH) $(ENABLE_XSLT);
> +
> Index: WebCore/WebCore.vcproj/WebCore.vcproj
> ===================================================================
> --- WebCore/WebCore.vcproj/WebCore.vcproj	(revision 45574)
> +++ WebCore/WebCore.vcproj/WebCore.vcproj	(working copy)
> @@ -67,7 +67,7 @@
>  			/>
>  			<Tool
>  				Name="VCPostBuildEventTool"
> -				CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\bindings&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\parser&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\runtime&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\masm&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\pcre&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\profiler&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wrec&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf\unicode&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf\unicode\icu&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\config.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitOutputDir)\obj\WebCore\DerivedSources\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\accessibility\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\accessibility\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\inspector\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\appcache\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\archive\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\archive\cf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\icon\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\history\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\history\cf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\html\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\css\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\animation\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\cf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\graphics\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\graphics\transforms\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\graphics\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\graphics\opentype\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\text\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\network\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\network\cf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\network\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\sql\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\cairo\cairo\src\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\bindings\js\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\page\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\page\animation\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\page\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\bridge\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\plugins\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\plugins\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\rendering\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\rendering\style\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\editing\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\dom\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\xml\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\svg\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\storage\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\workers\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\bindings\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\bindings&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\parser\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\parser&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\runtime\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\runtime&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\masm\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\masm&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\pcre\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\pcre&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\profiler&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\wrec\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wrec&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf\unicode&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf\unicode\icu&quot;&#x0D;&#x0A;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\bin\WebKit.resources\inspector&quot;&#x0D;&#x0A;xcopy /y /d /s /exclude:xcopy.excludes &quot;$(ProjectDir)\..\inspector\front-end\*&quot; &quot;$(WebKitOutputDir)\bin\WebKit.resources\inspector&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\bin\WebKit.resources\en.lproj&quot;&#x0D;&#x0A;xcopy /y /d /s /exclude:xcopy.excludes &quot;$(ProjectDir)\..\English.lproj\localizedStrings.js&quot; &quot;$(WebKitOutputDir)\bin\WebKit.resources\en.lproj&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"
> +				CommandLine="mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\bindings&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\parser&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\runtime&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\masm&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\pcre&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\profiler&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wrec&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf\unicode&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf\unicode\icu&quot;&#x0D;&#x0A;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\config.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(WebKitOutputDir)\obj\WebCore\DerivedSources\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\accessibility\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\accessibility\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\inspector\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\appcache\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\archive\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\archive\cf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\loader\icon\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\history\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\history\cf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\html\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\notifications\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\css\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\animation\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\cf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\graphics\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\graphics\transforms\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\graphics\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\graphics\opentype\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\text\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\network\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\network\cf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\network\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\sql\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\platform\cairo\cairo\src\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\bindings\js\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\page\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\page\animation\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\page\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\bridge\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\plugins\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\plugins\win\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\rendering\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\rendering\style\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\editing\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\dom\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\xml\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\svg\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\storage\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\workers\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\bindings\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\bindings&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\parser\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\parser&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\runtime\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\runtime&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\masm\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\masm&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\pcre\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\pcre&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\profiler\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\profiler&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\wrec\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wrec&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\wtf\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\wtf\unicode\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf\unicode&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)\..\ForwardingHeaders\wtf\unicode\icu\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore\ForwardingHeaders\wtf\unicode\icu&quot;&#x0D;&#x0A;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\bin\WebKit.resources\inspector&quot;&#x0D;&#x0A;xcopy /y /d /s /exclude:xcopy.excludes &quot;$(ProjectDir)\..\inspector\front-end\*&quot; &quot;$(WebKitOutputDir)\bin\WebKit.resources\inspector&quot;&#x0D;&#x0A;mkdir 2&gt;NUL &quot;$(WebKitOutputDir)\bin\WebKit.resources\en.lproj&quot;&#x0D;&#x0A;xcopy /y /d /s /exclude:xcopy.excludes &quot;$(ProjectDir)\..\English.lproj\localizedStrings.js&quot; &quot;$(WebKitOutputDir)\bin\WebKit.resources\en.lproj&quot;&#x0D;&#x0A;&#x0D;&#x0A;if exist &quot;$(WebKitOutputDir)\buildfailed&quot; del &quot;$(WebKitOutputDir)\buildfailed&quot;&#x0D;&#x0A;"
>  			/>
>  		</Configuration>
>  		<Configuration
> @@ -7190,6 +7190,102 @@
>  				>
>  			</File>
>  			<File
> +				RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSNotification.cpp"
> +				>
> +				<FileConfiguration
> +					Name="Debug|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +				<FileConfiguration
> +					Name="Release|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +				<FileConfiguration
> +					Name="Debug_Internal|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +				<FileConfiguration
> +					Name="Debug_Cairo|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +				<FileConfiguration
> +					Name="Release_Cairo|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +			</File>
> +			<File
> +				RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSNotification.h"
> +				>
> +			</File>
> +			<File
> +				RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSNotificationCenter.cpp"
> +				>
> +				<FileConfiguration
> +					Name="Debug|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +				<FileConfiguration
> +					Name="Release|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +				<FileConfiguration
> +					Name="Debug_Internal|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +				<FileConfiguration
> +					Name="Debug_Cairo|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +				<FileConfiguration
> +					Name="Release_Cairo|Win32"
> +					ExcludedFromBuild="true"
> +					>
> +					<Tool
> +						Name="VCCLCompilerTool"
> +					/>
> +				</FileConfiguration>
> +			</File>
> +			<File
> +				RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSNotificationCenter.h"
> +				>
> +			</File>
> +			<File
>  				RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSOverflowEvent.cpp"
>  				>
>  				<FileConfiguration
> @@ -23832,6 +23928,34 @@
>  			</File>
>  		</Filter>
>  		<Filter
> +			Name="notifications"
> +			>
> +			<File
> +				RelativePath="..\notifications\Notification.cpp"
> +				>
> +			</File>
> +			<File
> +				RelativePath="..\notifications\Notification.h"
> +				>
> +			</File>
> +			<File
> +				RelativePath="..\notifications\NotificationCenter.cpp"
> +				>
> +			</File>
> +			<File
> +				RelativePath="..\notifications\NotificationCenter.h"
> +				>
> +			</File>
> +			<File
> +				RelativePath="..\notifications\NotificationContents.h"
> +				>
> +			</File>
> +			<File
> +				RelativePath="..\notifications\NotificationProvider.h"
> +				>
> +			</File>
> +		</Filter>
> +		<Filter
>  			Name="editing"
>  			>
>  			<File
> @@ -28066,6 +28190,10 @@
>  					>
>  				</File>
>  				<File
> +					RelativePath="..\bindings\js\JSDesktopNotificationsCustom.cpp"
> +					>
> +				</File>
> +				<File
>  					RelativePath="..\bindings\js\JSDocumentCustom.cpp"
>  					>
>  				</File>
> Index: WebCore/WebCore.vcproj/WebCoreCommon.vsprops
> ===================================================================
> --- WebCore/WebCore.vcproj/WebCoreCommon.vsprops	(revision 45574)
> +++ WebCore/WebCore.vcproj/WebCoreCommon.vsprops	(working copy)
> @@ -7,7 +7,7 @@
>  	>
>  	<Tool
>  		Name="VCCLCompilerTool"
> -		AdditionalIncludeDirectories="&quot;$(ProjectDir)..\&quot;;&quot;$(ProjectDir)..&quot;;&quot;$(ProjectDir)..\accessibility&quot;;&quot;$(ProjectDir)..\accessibility\win&quot;;&quot;$(ProjectDir)..\bridge&quot;;&quot;$(ProjectDir)..\bridge\c&quot;;&quot;$(ProjectDir)..\css&quot;;&quot;$(ProjectDir)..\editing&quot;;&quot;$(ProjectDir)..\rendering&quot;;&quot;$(ProjectDir)..\rendering\style&quot;;&quot;$(ProjectDir)..\bindings\js&quot;;&quot;$(ProjectDir)..\dom&quot;;&quot;$(ProjectDir)..\dom\default&quot;;&quot;$(ProjectDir)..\history&quot;;&quot;$(ProjectDir)..\html&quot;;&quot;$(ProjectDir)..\inspector&quot;;&quot;$(ProjectDir)..\loader&quot;;&quot;$(ProjectDir)..\loader\appcache&quot;;&quot;$(ProjectDir)..\loader\archive&quot;;&quot;$(ProjectDir)..\loader\archive\cf&quot;;&quot;$(ProjectDir)..\loader\icon&quot;;&quot;$(ProjectDir)..\page&quot;;&quot;$(ProjectDir)..\page\animation&quot;;&quot;$(ProjectDir)..\page\win&quot;;&quot;$(ProjectDir)..\platform&quot;;&quot;$(ProjectDir)..\platform\animation&quot;;&quot;$(ProjectDir)..\platform\sql&quot;;&quot;$(ProjectDir)..\platform\win&quot;;&quot;$(ProjectDir)..\platform\network&quot;;&quot;$(ProjectDir)..\platform\network\win&quot;;&quot;$(ProjectDir)..\platform\cf&quot;;&quot;$(ProjectDir)..\platform\graphics&quot;;&quot;$(ProjectDir)..\platform\graphics\opentype&quot;;&quot;$(ProjectDir)..\platform\graphics\transforms&quot;;&quot;$(ProjectDir)..\platform\text&quot;;&quot;$(ProjectDir)..\platform\graphics\win&quot;;&quot;$(ProjectDir)..\xml&quot;;&quot;$(WebKitOutputDir)\obj\WebCore\DerivedSources&quot;;&quot;$(ProjectDir)..\plugins&quot;;&quot;$(ProjectDir)..\plugins\win&quot;;&quot;$(ProjectDir)..\svg\graphics&quot;;&quot;$(ProjectDir)..\svg\graphics\filters&quot;;&quot;$(ProjectDir)..\svg&quot;;&quot;$(ProjectDir)..\wml&quot;;&quot;$(ProjectDir)..\storage&quot;;&quot;$(ProjectDir)..\workers&quot;;&quot;$(WebKitOutputDir)\include&quot;;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(ProjectDir)..\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;&quot;$(WebKitLibrariesDir)\include\iconv&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\include\sqlite&quot;;&quot;$(WebKitLibrariesDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;;&quot;$(ProjectDir)..\svg\animation&quot;"
> +		AdditionalIncludeDirectories="&quot;$(ProjectDir)..\&quot;;&quot;$(ProjectDir)..&quot;;&quot;$(ProjectDir)..\accessibility&quot;;&quot;$(ProjectDir)..\accessibility\win&quot;;&quot;$(ProjectDir)..\bridge&quot;;&quot;$(ProjectDir)..\bridge\c&quot;;&quot;$(ProjectDir)..\css&quot;;&quot;$(ProjectDir)..\editing&quot;;&quot;$(ProjectDir)..\notifications&quot;;&quot;$(ProjectDir)..\rendering&quot;;&quot;$(ProjectDir)..\rendering\style&quot;;&quot;$(ProjectDir)..\bindings\js&quot;;&quot;$(ProjectDir)..\dom&quot;;&quot;$(ProjectDir)..\dom\default&quot;;&quot;$(ProjectDir)..\history&quot;;&quot;$(ProjectDir)..\html&quot;;&quot;$(ProjectDir)..\inspector&quot;;&quot;$(ProjectDir)..\loader&quot;;&quot;$(ProjectDir)..\loader\appcache&quot;;&quot;$(ProjectDir)..\loader\archive&quot;;&quot;$(ProjectDir)..\loader\archive\cf&quot;;&quot;$(ProjectDir)..\loader\icon&quot;;&quot;$(ProjectDir)..\page&quot;;&quot;$(ProjectDir)..\page\animation&quot;;&quot;$(ProjectDir)..\page\win&quot;;&quot;$(ProjectDir)..\platform&quot;;&quot;$(ProjectDir)..\platform\animation&quot;;&quot;$(ProjectDir)..\platform\sql&quot;;&quot;$(ProjectDir)..\platform\win&quot;;&quot;$(ProjectDir)..\platform\network&quot;;&quot;$(ProjectDir)..\platform\network\win&quot;;&quot;$(ProjectDir)..\platform\cf&quot;;&quot;$(ProjectDir)..\platform\graphics&quot;;&quot;$(ProjectDir)..\platform\graphics\opentype&quot;;&quot;$(ProjectDir)..\platform\graphics\transforms&quot;;&quot;$(ProjectDir)..\platform\text&quot;;&quot;$(ProjectDir)..\platform\graphics\win&quot;;&quot;$(ProjectDir)..\xml&quot;;&quot;$(WebKitOutputDir)\obj\WebCore\DerivedSources&quot;;&quot;$(ProjectDir)..\plugins&quot;;&quot;$(ProjectDir)..\plugins\win&quot;;&quot;$(ProjectDir)..\svg\graphics&quot;;&quot;$(ProjectDir)..\svg\graphics\filters&quot;;&quot;$(ProjectDir)..\svg&quot;;&quot;$(ProjectDir)..\wml&quot;;&quot;$(ProjectDir)..\storage&quot;;&quot;$(ProjectDir)..\workers&quot;;&quot;$(WebKitOutputDir)\include&quot;;&quot;$(WebKitOutputDir)\include\JavaScriptCore&quot;;&quot;$(ProjectDir)..\ForwardingHeaders&quot;;&quot;$(WebKitLibrariesDir)\include&quot;;&quot;$(WebKitLibrariesDir)\include\icu&quot;;&quot;$(WebKitLibrariesDir)\include\iconv&quot;;&quot;$(WebKitLibrariesDir)\include\pthreads&quot;;&quot;$(WebKitLibrariesDir)\include\sqlite&quot;;&quot;$(WebKitLibrariesDir)\include\JavaScriptCore&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders&quot;;&quot;$(WebKitLibrariesDir)\Include\CoreFoundation\OSXCompatibilityHeaders\GNUCompatibility&quot;;&quot;$(ProjectDir)..\svg\animation&quot;"
>  		PreprocessorDefinitions="__WIN32__;WEBCORE_CONTEXT_MENUS;ENABLE_DATABASE;ENABLE_DATAGRID;ENABLE_DOM_STORAGE;ENABLE_ICONDATABASE;ENABLE_OFFLINE_WEB_APPLICATIONS;ENABLE_SVG;ENABLE_SVG_ANIMATION;ENABLE_SVG_AS_IMAGE;ENABLE_SVG_FONTS;ENABLE_SVG_FOREIGN_OBJECT;ENABLE_SVG_USE;ENABLE_WORKERS;ENABLE_XPATH;ENABLE_XSLT"
>  		UsePrecompiledHeader="2"
>  		PrecompiledHeaderThrough="WebCorePrefix.h"
> Index: WebCore/WebCore.xcodeproj/project.pbxproj
> ===================================================================
> --- WebCore/WebCore.xcodeproj/project.pbxproj	(revision 45574)
> +++ WebCore/WebCore.xcodeproj/project.pbxproj	(working copy)
> @@ -614,6 +614,10 @@
>  		31C0FF4C0E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 31C0FF460E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.h */; };
>  		31C0FF4D0E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.mm in Sources */ = {isa = PBXBuildFile; fileRef = 31C0FF470E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.mm */; };
>  		31C0FF4E0E4CEFDD007D6FE5 /* DOMWebKitTransitionEventInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 31C0FF480E4CEFDD007D6FE5 /* DOMWebKitTransitionEventInternal.h */; };
> +		3390CA550FFC157B00921962 /* NotificationCenter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3390CA510FFC157B00921962 /* NotificationCenter.cpp */; };
> +		3390CA560FFC157B00921962 /* NotificationCenter.h in Headers */ = {isa = PBXBuildFile; fileRef = 3390CA520FFC157B00921962 /* NotificationCenter.h */; };
> +		3390CA570FFC157B00921962 /* NotificationCenter.idl in Resources */ = {isa = PBXBuildFile; fileRef = 3390CA530FFC157B00921962 /* NotificationCenter.idl */; };
> +		3390CA580FFC157B00921962 /* NotificationContents.h in Headers */ = {isa = PBXBuildFile; fileRef = 3390CA540FFC157B00921962 /* NotificationContents.h */; };
>  		371F4F400D25B9AF00ECE0D5 /* FontData.h in Headers */ = {isa = PBXBuildFile; fileRef = 371F4F3E0D25B9AF00ECE0D5 /* FontData.h */; settings = {ATTRIBUTES = (Private, ); }; };
>  		371F4F410D25B9AF00ECE0D5 /* FontData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 371F4F3F0D25B9AF00ECE0D5 /* FontData.cpp */; };
>  		371F4FFC0D25E7F300ECE0D5 /* SegmentedFontData.h in Headers */ = {isa = PBXBuildFile; fileRef = 371F4FFA0D25E7F300ECE0D5 /* SegmentedFontData.h */; };
> @@ -5542,6 +5546,14 @@
>  		31C0FF460E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMWebKitTransitionEvent.h; sourceTree = "<group>"; };
>  		31C0FF470E4CEFDD007D6FE5 /* DOMWebKitTransitionEvent.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMWebKitTransitionEvent.mm; sourceTree = "<group>"; };
>  		31C0FF480E4CEFDD007D6FE5 /* DOMWebKitTransitionEventInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMWebKitTransitionEventInternal.h; sourceTree = "<group>"; };
> +		333F704E0FB49CA2008E12A6 /* Notification.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Notification.idl; path = notifications/Notification.idl; sourceTree = "<group>"; };
> +		333F704F0FB49CA2008E12A6 /* Notification.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Notification.h; path = notifications/Notification.h; sourceTree = "<group>"; };
> +		333F70500FB49CA2008E12A6 /* Notification.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Notification.cpp; path = notifications/Notification.cpp; sourceTree = "<group>"; };
> +		333F70510FB49CA2008E12A6 /* NotificationProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotificationProvider.h; path = notifications/NotificationProvider.h; sourceTree = "<group>"; };
> +		3390CA510FFC157B00921962 /* NotificationCenter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NotificationCenter.cpp; path = notifications/NotificationCenter.cpp; sourceTree = "<group>"; };
> +		3390CA520FFC157B00921962 /* NotificationCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotificationCenter.h; path = notifications/NotificationCenter.h; sourceTree = "<group>"; };
> +		3390CA530FFC157B00921962 /* NotificationCenter.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = NotificationCenter.idl; path = notifications/NotificationCenter.idl; sourceTree = "<group>"; };
> +		3390CA540FFC157B00921962 /* NotificationContents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NotificationContents.h; path = notifications/NotificationContents.h; sourceTree = "<group>"; };
>  		371F4F3E0D25B9AF00ECE0D5 /* FontData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontData.h; sourceTree = "<group>"; };
>  		371F4F3F0D25B9AF00ECE0D5 /* FontData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontData.cpp; sourceTree = "<group>"; };
>  		371F4FFA0D25E7F300ECE0D5 /* SegmentedFontData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SegmentedFontData.h; sourceTree = "<group>"; };
> @@ -9414,6 +9426,7 @@
>  				93EEC1EC09C2877700C515D1 /* html */,
>  				1C81B94D0E9732D900266E07 /* inspector */,
>  				BCB16BFB0979C38700467741 /* loader */,
> +				333F703D0FB49C16008E12A6 /* notifications */,
>  				65BF02180974806300C43196 /* page */,
>  				BCF1A5BA097832090061A123 /* platform */,
>  				5DCF83690D59157800953BC6 /* plugins */,
> @@ -9884,6 +9897,21 @@
>  			name = animation;
>  			sourceTree = "<group>";
>  		};
> +		333F703D0FB49C16008E12A6 /* notifications */ = {
> +			isa = PBXGroup;
> +			children = (
> +				3390CA510FFC157B00921962 /* NotificationCenter.cpp */,
> +				3390CA520FFC157B00921962 /* NotificationCenter.h */,
> +				3390CA530FFC157B00921962 /* NotificationCenter.idl */,
> +				3390CA540FFC157B00921962 /* NotificationContents.h */,
> +				333F704E0FB49CA2008E12A6 /* Notification.idl */,
> +				333F704F0FB49CA2008E12A6 /* Notification.h */,
> +				333F70500FB49CA2008E12A6 /* Notification.cpp */,
> +				333F70510FB49CA2008E12A6 /* NotificationProvider.h */,
> +			);
> +			name = notifications;
> +			sourceTree = "<group>";
> +		};
>  		449195900FBE175B00D9F824 /* Exports */ = {
>  			isa = PBXGroup;
>  			children = (
> @@ -16917,6 +16945,8 @@
>  				BC77D16C0FF19F560070887B /* JSDataGridColumnList.h in Headers */,
>  				BCBCAE370FF19385000762AE /* DataGridDataSource.h in Headers */,
>  				BCBCAE3D0FF19399000762AE /* JSDataGridDataSource.h in Headers */,
> +				3390CA560FFC157B00921962 /* NotificationCenter.h in Headers */,
> +				3390CA580FFC157B00921962 /* NotificationContents.h in Headers */,
>  				C50D0E830FF4272900AC2644 /* StorageNamespace.h in Headers */,
>  				BC7DAAEF0FF9615D00CE0138 /* DOMDataGridDataSource.h in Headers */,
>  				B5A684220FFABE9800D24689 /* SQLiteFileSystem.h in Headers */,
> @@ -17028,6 +17058,7 @@
>  				BC77CDA30FEFEB530070887B /* HTMLDataGridCellElement.idl in Resources */,
>  				BC77CF990FF172420070887B /* DataGridColumnList.idl in Resources */,
>  				BC77CF9F0FF172B30070887B /* DataGridColumn.idl in Resources */,
> +				3390CA570FFC157B00921962 /* NotificationCenter.idl in Resources */,
>  			);
>  			runOnlyForDeploymentPostprocessing = 0;
>  		};
> @@ -18932,6 +18963,7 @@
>  				BCBCAE540FF1A29E000762AE /* JSHTMLDataGridElementCustom.cpp in Sources */,
>  				BC77D1FD0FF28D9B0070887B /* DataGridColumnList.cpp in Sources */,
>  				BC77D2390FF298080070887B /* DataGridColumn.cpp in Sources */,
> +				3390CA550FFC157B00921962 /* NotificationCenter.cpp in Sources */,
>  				C50D0E820FF4272900AC2644 /* StorageNamespace.cpp in Sources */,
>  				BC7DAAEE0FF9615D00CE0138 /* DOMDataGridDataSource.cpp in Sources */,
>  				B5A684240FFABEAA00D24689 /* SQLiteFileSystem.cpp in Sources */,
> Index: WebCore/bindings/js/JSDOMWindowCustom.cpp
> ===================================================================
> --- WebCore/bindings/js/JSDOMWindowCustom.cpp	(revision 45574)
> +++ WebCore/bindings/js/JSDOMWindowCustom.cpp	(working copy)
> @@ -44,6 +44,7 @@
>  #include "JSLocation.h"
>  #include "JSMessageChannelConstructor.h"
>  #include "JSMessagePort.h"
> +#include "JSNotificationCenter.h"
>  #include "JSOptionConstructor.h"
>  #include "JSWebKitCSSMatrixConstructor.h"
>  #include "JSWebKitPointConstructor.h"
> @@ -53,6 +54,7 @@
>  #include "Location.h"
>  #include "MediaPlayer.h"
>  #include "MessagePort.h"
> +#include "NotificationCenter.h"
>  #include "Page.h"
>  #include "PlatformScreen.h"
>  #include "RegisteredEventListener.h"
> @@ -374,6 +376,19 @@ JSValue JSDOMWindow::location(ExecState*
>      return jsLocation;
>  }
>  
> +#if ENABLE(NOTIFICATIONS)
> +JSValue JSDOMWindow::notifications(ExecState* exec) const
> +{
> +    NotificationCenter* notifications = impl()->notifications();
> +    if (DOMObject* wrapper = getCachedDOMObjectWrapper(exec->globalData(), notifications))
> +        return wrapper;
> +
> +    JSNotificationCenter* jsNotifications = new (exec) JSNotificationCenter(getDOMStructure<JSNotificationCenter>(exec, const_cast<JSDOMWindow*>(this)), notifications);
> +    cacheDOMObjectWrapper(exec->globalData(), notifications, jsNotifications);
> +    return jsNotifications;
> +}
> +#endif
> +

Why does this need to be a custom binding? Seems like this does basically the same thing that a manual binding would (except the manual binding would use toJS() instead of doing the wrapper conversion by hand).

> +
> +JSValue JSNotificationCenter::createHTMLNotification(ExecState* exec, const ArgList& args)
> +{
> +    ExceptionCode ec = 0;
> +    String url = args.at(0).toString(exec);
> +    JSValue value = toJS(exec, Notification::create(url, impl()->context(), ec, impl()->provider()));
> +    setDOMException(exec, ec);
> +    return value;
> +}

Why does this need to be a custom binding? Wouldn't it be simpler to give JSNotificationCenter a createHTMLNotification() method and let the bindings generator do the work? Also, it looks like this code will use "undefined" for url if the URL parameter is omitted, instead of an empty string as is the case with many other DOM APIs. Is that intentional?

> +
> +JSValue JSNotificationCenter::createNotification(ExecState* exec, const ArgList& args)
> +{
> +    ExceptionCode ec = 0;
> +    NotificationContents contents(args.at(0).toString(exec), args.at(1).toString(exec), args.at(2).toString(exec));
> +
> +
> +    JSValue value = toJS(exec, Notification::create(contents, impl()->context(), ec, impl()->provider()));
> +    setDOMException(exec, ec);
> +    return value;
> +}

Ditto the two issues above.

> +
> +JSValue JSNotificationCenter::checkPermission(ExecState* exec, const ArgList& args)
> +{
> +    return JSValue(exec, impl()->checkPermission());
> +}

Once again, not clear why this needs to be a custom binding.



> +Notification::~Notification() 
> +{
> +}

It's not necessary to explicitly define an empty constructor.

> +
> +void Notification::dispatchDisplayEvent() 
> +{   
> +    RefPtr<Event> event = Event::create("display", false, true);
> +
> +    if (m_onDisplayListener) {
> +        event->setTarget(this);
> +        event->setCurrentTarget(this);
> +        m_onDisplayListener->handleEvent(event.get(), true);
> +    }
> +
> +    ExceptionCode ec = 0;
> +    dispatchEvent(event.release(), ec);
> +    ASSERT(!ec);
> +}

I think all of the event dispatch has some bugs. The event flow should be like this:

1) All capturing event listeners -- ones registered with addEventListener's third argument (useCapture) set to true -- get to handle the event, in the order in which they were added.
2) All non-capturing event listeners, including built-in ones set via the attributes, get to handle the event in the order in which they were added.

This should happen whether or not the event is dispatched internally or by an explicit dispatchEvent() call from JS.

I believe you have at least four bugs here, I will describe them plus test cases that would catch them (which you should add).

A) For events dispatched internally, the built-in listener will be invoked *before* the capturing listeners (which we don't get to until handleEvent). This is wrong, capturing listeners need to fire first. You can test this by setting a capturing listener with addEventListener as well as one via the builtin (onerror, onclose, etc) DOM attributes. Then cause one of the events to be dispatched in a built-in way.

B) For events dispatched by calling dispatchEvent() directly, the built-in listeners will be skipped entirely. That's because they are only called by the special dispatchErrorEvent / dispatchCloseEvent etc functions, but those are not invoked when dispatchEvent is called directly.

C) Very minor - if you add a non-capturing listener with addEventListener, and then afterwards set a DOM property listener (say, by setting onerror) the addEventListener listener should fire first on a built-in dispatch, but with your code it will fire second.

D) You are not handling propagationStopped properly between the phases. You can observe this by setting a capturing and non-capturing listener, and calling stopPropagation in the capturing listener. 

There may be EventTarget subclasses that get this wrong. Node gets it right, although it also has logic to go up and down the DOM tree which is not necessary here. If you code it more like what Node does, starting with the line event->setEventPhase(Event::AT_TARGET) in Node::dispatchGenericEvent() up to right before the section of code handling the bubble phase, and if you make the attribute listeners work more like they would via Node::setAttributeEventListener(), then all four of the above bugs should go away.

We can file bugs on any other classes getting this wrong. Maybe we should eventually have some helper code for EventTarget classes that are standalone and not DOM nodes, to make it easier to get this right.

> +
> +void Notification::dispatchErrorEvent()
> +{  
> +    RefPtr<Event> event = Event::create(eventNames().errorEvent, false, true);
> +
> +    if (m_onErrorListener) {
> +        event->setTarget(this);
> +        event->setCurrentTarget(this);
> +        m_onErrorListener->handleEvent(event.get(), true);
> +    }
> +
> +    ExceptionCode ec = 0;
> +    dispatchEvent(event.release(), ec);
> +    ASSERT(!ec);
> +}
> +
> +void Notification::dispatchCloseEvent() 
> +{   
> +    RefPtr<Event> event = Event::create(eventNames().closeEvent, false, true);
> +
> +    if (m_onCloseListener) {
> +        event->setTarget(this);
> +        event->setCurrentTarget(this);
> +        m_onCloseListener->handleEvent(event.get(), true);
> +    }
> +
> +    ExceptionCode ec = 0;
> +    dispatchEvent(event.release(), ec);
> +    ASSERT(!ec);
> +
> +}

These two methods are buggy too, as cited above.

> +bool Notification::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
> +{
> +    RegisteredEventListenerVector listenersCopy = m_eventListeners;
> +    size_t size = listenersCopy.size();
> +    for (size_t i = 0; i < size; ++i) {
> +        RegisteredEventListener& r = *listenersCopy[i];
> +        if (r.eventType() == event->type() && !r.removed())
> +            r.listener()->handleEvent(event.get());
> +    }
> +
> +    return true;
> +}

And this too - notice how it ignores whether the listeners have useCapture set.

> +
> +void Notification::display()
> +{
> +    dispatchDisplayEvent();
> +}
> +
> +void Notification::error()
> +{
> +    dispatchErrorEvent();
> +}
> +
> +void Notification::close()
> +{
> +    dispatchCloseEvent();
> +}

These one-line wrappers don't seem to add much. Maybe there should be only one of display()/dispatchDisplayEvent() and the notification provider can call that.


I think NotificationDisplay or NotificationUI or something like that would be a better name than NotificationProvider, as discussed previously. Or maybe NotificationPresenter (since the job of this class from the point of view of the rest of the code) is to present notifications to the user.
Comment 41 Maciej Stachowiak 2009-07-20 21:43:56 PDT
Comment on attachment 32341 [details]
Notifications API, Tests and DumpRenderTree hooks

First of all, I suggest combining this with the other patch. Yes, it will make it overall a bit bigger, but it's a significant benefit to be able to land atomically with test cases. I don't see any problems with the code (well done!) but marking r- since this depends on the other patch, and since I suggest combining with it.
Comment 42 Maciej Stachowiak 2009-07-20 21:45:00 PDT
BTW if you can address this dispatch and custom listener issues, I can review the next round quickly. Just let me know when it's ready.
Comment 43 John Gregg 2009-07-23 10:54:25 PDT
Created attachment 33345 [details]
Notifications API, combined Core and Tests

New patch which addresses the feedback and combines the two pieces together.  V8 Bindings still pending in a separate patch.  One small addition to this patch allows the notification to inform its presenter when it's being destroyed, in order to detach it from future events.
Comment 44 John Gregg 2009-07-23 10:58:27 PDT
Created attachment 33346 [details]
Notifications API, combined Core and Tests

same patch as above without bogus svn:executable properties.
Comment 45 Maciej Stachowiak 2009-07-30 17:20:52 PDT
Looking at this patch now. Thanks for revising.
Comment 46 Andrew Wilson 2009-08-05 14:42:16 PDT
(In reply to comment #45)
> Looking at this patch now. Thanks for revising.

Do we have an ETA on the review (or even partial review comments you can post)? We'd like to land the patch this week if possible, so the earlier we can respond to comments the more likely this becomes.
Comment 47 Eric Seidel (no email) 2009-08-07 09:35:55 PDT
Comment on attachment 33346 [details]
Notifications API, combined Core and Tests

Seems like we need to separate out that *massive* command line into a helper script sooner rather than later.  Please consider filing a bug to do that.

\*.h&quot; &quot;$(WebKitOutputDir)\include\WebCore&quot;&#x0D;&#x0A;xcopy /y /d &quot;$(ProjectDir)..\notifications

Is it possible to break this up?  With 60 other patches in the queue, I simply don't have the stamina for this one.  Tempting me to r- it for size.

You'll have the best luck if you can engage an interested reviewer directly.  I'm not your man, but maybe you know someone else who is interested in seeing this added.
Comment 48 Andrew Wilson 2009-08-07 09:45:24 PDT
(In reply to comment #47)
> You'll have the best luck if you can engage an interested reviewer directly. 
> I'm not your man, but maybe you know someone else who is interested in seeing
> this added.

Maciej is already looking at this. Agreed that in retrospect this should have been broken up. If we can't bring this to a rapid conclusion (ostensibly we are very close after several rounds of reviews) we may need to do this. Depends on maciej's upcoming review comments.
Comment 49 John Gregg 2009-08-07 10:05:57 PDT
Please don't r- me for size!  The last set of patches *were* broken it up into pieces with all the test hooks separate from the main code but the review feedback was to combine them.
Comment 50 Eric Seidel (no email) 2009-08-07 12:26:48 PDT
I'm useless to you as a reviewer.  Please email your intended reviewers directly.
Comment 51 Maciej Stachowiak 2009-08-11 02:11:34 PDT
I have reviewed files JavaScriptCore/ChangeLog through WebCore/WebCore.xcodeproj/project.pbxproj (inclusive). Continuing...
Comment 52 Maciej Stachowiak 2009-08-11 02:13:54 PDT
Files through EmptyClients.h (inclusive) look fine.
Comment 53 Maciej Stachowiak 2009-08-11 02:19:11 PDT
Comment on attachment 33346 [details]
Notifications API, combined Core and Tests

Everything seems to be in order. The event handler logic in Notification.cpp in particular looks flawless this time. Kudos! And r=me.
Comment 54 Andrew Wilson 2009-08-11 13:23:25 PDT
Committed as r47056.
Comment 55 Eric Seidel (no email) 2009-08-11 14:18:17 PDT
The Windows buildbot is failing after this commit:
http://build.webkit.org/waterfall
I don't expect we need to roll this out, but someone needs to update the windows build system...
Comment 56 Andrew Wilson 2009-08-11 14:49:33 PDT
(In reply to comment #55)
> The Windows buildbot is failing after this commit:
> http://build.webkit.org/waterfall
> I don't expect we need to roll this out, but someone needs to update the
> windows build system...

Working through build issues now.  I guess I should not mark as resolved until build goes green :)
Comment 57 Andrew Wilson 2009-08-12 09:20:35 PDT
Build green now. Marking resolved.