|
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 } |