initial import
[vuplus_webkit] / Source / WebKit / win / WebNotificationCenter.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "WebKitDLL.h"
28 #include "WebNotificationCenter.h"
29
30 #include "WebNotification.h"
31 #include <WebCore/COMPtr.h>
32 #include <WebCore/PlatformString.h>
33 #include <wtf/HashMap.h>
34 #include <wtf/HashTraits.h>
35 #include <wtf/PassOwnPtr.h>
36 #include <wtf/Vector.h>
37 #include <wtf/text/StringHash.h>
38 #include <utility>
39 #include <wchar.h>
40
41 using namespace WebCore;
42
43 typedef std::pair<COMPtr<IUnknown>, COMPtr<IWebNotificationObserver> > ObjectObserverPair;
44 typedef Vector<ObjectObserverPair> ObjectObserverList;
45 typedef ObjectObserverList::iterator ObserverListIterator;
46 typedef HashMap<String, ObjectObserverList> MappedObservers;
47
48 struct WebNotificationCenterPrivate {
49     MappedObservers m_mappedObservers;
50 };
51
52 // WebNotificationCenter ----------------------------------------------------------------
53
54 IWebNotificationCenter* WebNotificationCenter::m_defaultCenter = 0;
55
56 WebNotificationCenter::WebNotificationCenter()
57     : m_refCount(0)
58     , d(adoptPtr(new WebNotificationCenterPrivate))
59 {
60     gClassCount++;
61     gClassNameCount.add("WebNotificationCenter");
62 }
63
64 WebNotificationCenter::~WebNotificationCenter()
65 {
66     gClassCount--;
67     gClassNameCount.remove("WebNotificationCenter");
68 }
69
70 WebNotificationCenter* WebNotificationCenter::createInstance()
71 {
72     WebNotificationCenter* instance = new WebNotificationCenter();
73     instance->AddRef();
74     return instance;
75 }
76
77 // IUnknown -------------------------------------------------------------------
78
79 HRESULT STDMETHODCALLTYPE WebNotificationCenter::QueryInterface(REFIID riid, void** ppvObject)
80 {
81     *ppvObject = 0;
82     if (IsEqualGUID(riid, IID_IUnknown))
83         *ppvObject = static_cast<IWebNotificationCenter*>(this);
84     else if (IsEqualGUID(riid, IID_IWebNotificationCenter))
85         *ppvObject = static_cast<IWebNotificationCenter*>(this);
86     else
87         return E_NOINTERFACE;
88
89     AddRef();
90     return S_OK;
91 }
92
93 ULONG STDMETHODCALLTYPE WebNotificationCenter::AddRef(void)
94 {
95     return ++m_refCount;
96 }
97
98 ULONG STDMETHODCALLTYPE WebNotificationCenter::Release(void)
99 {
100     ULONG newRef = --m_refCount;
101     if (!newRef)
102         delete(this);
103
104     return newRef;
105 }
106
107 IWebNotificationCenter* WebNotificationCenter::defaultCenterInternal()
108 {
109     if (!m_defaultCenter)
110         m_defaultCenter = WebNotificationCenter::createInstance();
111     return m_defaultCenter;
112 }
113
114 void WebNotificationCenter::postNotificationInternal(IWebNotification* notification, BSTR notificationName, IUnknown* anObject)
115 {
116     String name(notificationName, SysStringLen(notificationName));
117     MappedObservers::iterator it = d->m_mappedObservers.find(name);
118     if (it == d->m_mappedObservers.end())
119         return;
120
121     // Intentionally make a copy of the list to avoid the possibility of errors
122     // from a mutation of the list in the onNotify callback.
123     ObjectObserverList list = it->second;
124
125     ObserverListIterator end = list.end();
126     for (ObserverListIterator it2 = list.begin(); it2 != end; ++it2) {
127         IUnknown* observedObject = it2->first.get();
128         IWebNotificationObserver* observer = it2->second.get();
129         if (!observedObject || !anObject || observedObject == anObject)
130             observer->onNotify(notification);
131     }
132 }
133
134 // IWebNotificationCenter -----------------------------------------------------
135
136 HRESULT STDMETHODCALLTYPE WebNotificationCenter::defaultCenter( 
137     /* [retval][out] */ IWebNotificationCenter** center)
138 {
139     *center = defaultCenterInternal();
140     (*center)->AddRef();
141     return S_OK;
142 }
143
144 HRESULT STDMETHODCALLTYPE WebNotificationCenter::addObserver( 
145     /* [in] */ IWebNotificationObserver* observer,
146     /* [in] */ BSTR notificationName,
147     /* [in] */ IUnknown* anObject)
148 {
149     String name(notificationName, SysStringLen(notificationName));
150     MappedObservers::iterator it = d->m_mappedObservers.find(name);
151     if (it != d->m_mappedObservers.end())
152         it->second.append(ObjectObserverPair(anObject, observer));
153     else {
154         ObjectObserverList list;
155         list.append(ObjectObserverPair(anObject, observer));
156         d->m_mappedObservers.add(name, list);
157     }
158
159     return S_OK;
160 }
161
162 HRESULT STDMETHODCALLTYPE WebNotificationCenter::postNotification( 
163     /* [in] */ IWebNotification* notification)
164 {
165     BSTR name;
166     HRESULT hr = notification->name(&name);
167     if (FAILED(hr))
168         return hr;
169
170     COMPtr<IUnknown> obj;
171     hr = notification->getObject(&obj);
172     if (FAILED(hr))
173         return hr;
174
175     postNotificationInternal(notification, name, obj.get());
176     SysFreeString(name);
177
178     return hr;
179 }
180
181 HRESULT STDMETHODCALLTYPE WebNotificationCenter::postNotificationName( 
182     /* [in] */ BSTR notificationName,
183     /* [in] */ IUnknown* anObject,
184     /* [optional][in] */ IPropertyBag* userInfo)
185 {
186     COMPtr<WebNotification> notification(AdoptCOM, WebNotification::createInstance(notificationName, anObject, userInfo));
187     postNotificationInternal(notification.get(), notificationName, anObject);
188     return S_OK;
189 }
190
191 HRESULT STDMETHODCALLTYPE WebNotificationCenter::removeObserver( 
192     /* [in] */ IWebNotificationObserver* anObserver,
193     /* [in] */ BSTR notificationName,
194     /* [optional][in] */ IUnknown* anObject)
195 {
196     String name(notificationName, SysStringLen(notificationName));
197     MappedObservers::iterator it = d->m_mappedObservers.find(name);
198     if (it == d->m_mappedObservers.end())
199         return E_FAIL;
200
201     ObjectObserverList& observerList = it->second;
202     ObserverListIterator end = observerList.end();
203
204     int i = 0;
205     for (ObserverListIterator it2 = observerList.begin(); it2 != end; ++it2, ++i) {
206         IUnknown* observedObject = it2->first.get();
207         IWebNotificationObserver* observer = it2->second.get();
208         if (observer == anObserver && (!anObject || anObject == observedObject)) {
209             observerList.remove(i);
210             break;
211         }
212     }
213
214     if (observerList.isEmpty())
215         d->m_mappedObservers.remove(name);
216
217     return S_OK;
218 }