2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "WebKitDLL.h"
28 #include "WebNotificationCenter.h"
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>
41 using namespace WebCore;
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;
48 struct WebNotificationCenterPrivate {
49 MappedObservers m_mappedObservers;
52 // WebNotificationCenter ----------------------------------------------------------------
54 IWebNotificationCenter* WebNotificationCenter::m_defaultCenter = 0;
56 WebNotificationCenter::WebNotificationCenter()
58 , d(adoptPtr(new WebNotificationCenterPrivate))
61 gClassNameCount.add("WebNotificationCenter");
64 WebNotificationCenter::~WebNotificationCenter()
67 gClassNameCount.remove("WebNotificationCenter");
70 WebNotificationCenter* WebNotificationCenter::createInstance()
72 WebNotificationCenter* instance = new WebNotificationCenter();
77 // IUnknown -------------------------------------------------------------------
79 HRESULT STDMETHODCALLTYPE WebNotificationCenter::QueryInterface(REFIID riid, void** ppvObject)
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);
93 ULONG STDMETHODCALLTYPE WebNotificationCenter::AddRef(void)
98 ULONG STDMETHODCALLTYPE WebNotificationCenter::Release(void)
100 ULONG newRef = --m_refCount;
107 IWebNotificationCenter* WebNotificationCenter::defaultCenterInternal()
109 if (!m_defaultCenter)
110 m_defaultCenter = WebNotificationCenter::createInstance();
111 return m_defaultCenter;
114 void WebNotificationCenter::postNotificationInternal(IWebNotification* notification, BSTR notificationName, IUnknown* anObject)
116 String name(notificationName, SysStringLen(notificationName));
117 MappedObservers::iterator it = d->m_mappedObservers.find(name);
118 if (it == d->m_mappedObservers.end())
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;
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);
134 // IWebNotificationCenter -----------------------------------------------------
136 HRESULT STDMETHODCALLTYPE WebNotificationCenter::defaultCenter(
137 /* [retval][out] */ IWebNotificationCenter** center)
139 *center = defaultCenterInternal();
144 HRESULT STDMETHODCALLTYPE WebNotificationCenter::addObserver(
145 /* [in] */ IWebNotificationObserver* observer,
146 /* [in] */ BSTR notificationName,
147 /* [in] */ IUnknown* anObject)
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));
154 ObjectObserverList list;
155 list.append(ObjectObserverPair(anObject, observer));
156 d->m_mappedObservers.add(name, list);
162 HRESULT STDMETHODCALLTYPE WebNotificationCenter::postNotification(
163 /* [in] */ IWebNotification* notification)
166 HRESULT hr = notification->name(&name);
170 COMPtr<IUnknown> obj;
171 hr = notification->getObject(&obj);
175 postNotificationInternal(notification, name, obj.get());
181 HRESULT STDMETHODCALLTYPE WebNotificationCenter::postNotificationName(
182 /* [in] */ BSTR notificationName,
183 /* [in] */ IUnknown* anObject,
184 /* [optional][in] */ IPropertyBag* userInfo)
186 COMPtr<WebNotification> notification(AdoptCOM, WebNotification::createInstance(notificationName, anObject, userInfo));
187 postNotificationInternal(notification.get(), notificationName, anObject);
191 HRESULT STDMETHODCALLTYPE WebNotificationCenter::removeObserver(
192 /* [in] */ IWebNotificationObserver* anObserver,
193 /* [in] */ BSTR notificationName,
194 /* [optional][in] */ IUnknown* anObject)
196 String name(notificationName, SysStringLen(notificationName));
197 MappedObservers::iterator it = d->m_mappedObservers.find(name);
198 if (it == d->m_mappedObservers.end())
201 ObjectObserverList& observerList = it->second;
202 ObserverListIterator end = observerList.end();
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);
214 if (observerList.isEmpty())
215 d->m_mappedObservers.remove(name);