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 #pragma warning(push, 0) 32 #include <WebCore/COMPtr.h> 33 #include <WebCore/PlatformString.h> 34 #include <WebCore/StringHash.h> 35 #include <wtf/HashMap.h> 36 #include <wtf/HashTraits.h> 37 #include <wtf/Vector.h> 38 #pragma warning(pop) 39 #include <tchar.h> 40 #include <utility> 41 42 using namespace WebCore; 43 44 typedef std::pair<COMPtr<IUnknown>, COMPtr<IWebNotificationObserver> > ObjectObserverPair; 45 typedef Vector<ObjectObserverPair> ObjectObserverList; 46 typedef ObjectObserverList::iterator ObserverListIterator; 47 typedef HashMap<String, ObjectObserverList> MappedObservers; 48 49 struct WebNotificationCenterPrivate { 50 MappedObservers m_mappedObservers; 51 }; 52 53 // WebNotificationCenter ---------------------------------------------------------------- 54 55 IWebNotificationCenter* WebNotificationCenter::m_defaultCenter = 0; 56 57 WebNotificationCenter::WebNotificationCenter() 58 : m_refCount(0) 59 , d(new WebNotificationCenterPrivate) 60 { 61 gClassCount++; 62 gClassNameCount.add("WebNotificationCenter"); 63 } 64 65 WebNotificationCenter::~WebNotificationCenter() 66 { 67 gClassCount--; 68 gClassNameCount.remove("WebNotificationCenter"); 69 } 70 71 WebNotificationCenter* WebNotificationCenter::createInstance() 72 { 73 WebNotificationCenter* instance = new WebNotificationCenter(); 74 instance->AddRef(); 75 return instance; 76 } 77 78 // IUnknown ------------------------------------------------------------------- 79 80 HRESULT STDMETHODCALLTYPE WebNotificationCenter::QueryInterface(REFIID riid, void** ppvObject) 81 { 82 *ppvObject = 0; 83 if (IsEqualGUID(riid, IID_IUnknown)) 84 *ppvObject = static_cast<IWebNotificationCenter*>(this); 85 else if (IsEqualGUID(riid, IID_IWebNotificationCenter)) 86 *ppvObject = static_cast<IWebNotificationCenter*>(this); 87 else 88 return E_NOINTERFACE; 89 90 AddRef(); 91 return S_OK; 92 } 93 94 ULONG STDMETHODCALLTYPE WebNotificationCenter::AddRef(void) 95 { 96 return ++m_refCount; 97 } 98 99 ULONG STDMETHODCALLTYPE WebNotificationCenter::Release(void) 100 { 101 ULONG newRef = --m_refCount; 102 if (!newRef) 103 delete(this); 104 105 return newRef; 106 } 107 108 IWebNotificationCenter* WebNotificationCenter::defaultCenterInternal() 109 { 110 if (!m_defaultCenter) 111 m_defaultCenter = WebNotificationCenter::createInstance(); 112 return m_defaultCenter; 113 } 114 115 void WebNotificationCenter::postNotificationInternal(IWebNotification* notification, BSTR notificationName, IUnknown* anObject) 116 { 117 String name(notificationName, SysStringLen(notificationName)); 118 MappedObservers::iterator it = d->m_mappedObservers.find(name); 119 if (it == d->m_mappedObservers.end()) 120 return; 121 122 // Intentionally make a copy of the list to avoid the possibility of errors 123 // from a mutation of the list in the onNotify callback. 124 ObjectObserverList list = it->second; 125 126 ObserverListIterator end = list.end(); 127 for (ObserverListIterator it2 = list.begin(); it2 != end; ++it2) { 128 IUnknown* observedObject = it2->first.get(); 129 IWebNotificationObserver* observer = it2->second.get(); 130 if (!observedObject || !anObject || observedObject == anObject) 131 observer->onNotify(notification); 132 } 133 } 134 135 // IWebNotificationCenter ----------------------------------------------------- 136 137 HRESULT STDMETHODCALLTYPE WebNotificationCenter::defaultCenter( 138 /* [retval][out] */ IWebNotificationCenter** center) 139 { 140 *center = defaultCenterInternal(); 141 (*center)->AddRef(); 142 return S_OK; 143 } 144 145 HRESULT STDMETHODCALLTYPE WebNotificationCenter::addObserver( 146 /* [in] */ IWebNotificationObserver* observer, 147 /* [in] */ BSTR notificationName, 148 /* [in] */ IUnknown* anObject) 149 { 150 String name(notificationName, SysStringLen(notificationName)); 151 MappedObservers::iterator it = d->m_mappedObservers.find(name); 152 if (it != d->m_mappedObservers.end()) 153 it->second.append(ObjectObserverPair(anObject, observer)); 154 else { 155 ObjectObserverList list; 156 list.append(ObjectObserverPair(anObject, observer)); 157 d->m_mappedObservers.add(name, list); 158 } 159 160 return S_OK; 161 } 162 163 HRESULT STDMETHODCALLTYPE WebNotificationCenter::postNotification( 164 /* [in] */ IWebNotification* notification) 165 { 166 BSTR name; 167 HRESULT hr = notification->name(&name); 168 if (FAILED(hr)) 169 return hr; 170 171 COMPtr<IUnknown> obj; 172 hr = notification->getObject(&obj); 173 if (FAILED(hr)) 174 return hr; 175 176 postNotificationInternal(notification, name, obj.get()); 177 SysFreeString(name); 178 179 return hr; 180 } 181 182 HRESULT STDMETHODCALLTYPE WebNotificationCenter::postNotificationName( 183 /* [in] */ BSTR notificationName, 184 /* [in] */ IUnknown* anObject, 185 /* [optional][in] */ IPropertyBag* userInfo) 186 { 187 COMPtr<WebNotification> notification(AdoptCOM, WebNotification::createInstance(notificationName, anObject, userInfo)); 188 postNotificationInternal(notification.get(), notificationName, anObject); 189 return S_OK; 190 } 191 192 HRESULT STDMETHODCALLTYPE WebNotificationCenter::removeObserver( 193 /* [in] */ IWebNotificationObserver* anObserver, 194 /* [in] */ BSTR notificationName, 195 /* [optional][in] */ IUnknown* anObject) 196 { 197 String name(notificationName, SysStringLen(notificationName)); 198 MappedObservers::iterator it = d->m_mappedObservers.find(name); 199 if (it == d->m_mappedObservers.end()) 200 return E_FAIL; 201 202 ObjectObserverList& observerList = it->second; 203 ObserverListIterator end = observerList.end(); 204 205 int i = 0; 206 for (ObserverListIterator it2 = observerList.begin(); it2 != end; ++it2, ++i) { 207 IUnknown* observedObject = it2->first.get(); 208 IWebNotificationObserver* observer = it2->second.get(); 209 if (observer == anObserver && (!anObject || anObject == observedObject)) { 210 observerList.remove(i); 211 break; 212 } 213 } 214 215 if (observerList.isEmpty()) 216 d->m_mappedObservers.remove(name); 217 218 return S_OK; 219 } 220