• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
WebNotificationCenter()57 WebNotificationCenter::WebNotificationCenter()
58     : m_refCount(0)
59     , d(new WebNotificationCenterPrivate)
60 {
61     gClassCount++;
62     gClassNameCount.add("WebNotificationCenter");
63 }
64 
~WebNotificationCenter()65 WebNotificationCenter::~WebNotificationCenter()
66 {
67     gClassCount--;
68     gClassNameCount.remove("WebNotificationCenter");
69 }
70 
createInstance()71 WebNotificationCenter* WebNotificationCenter::createInstance()
72 {
73     WebNotificationCenter* instance = new WebNotificationCenter();
74     instance->AddRef();
75     return instance;
76 }
77 
78 // IUnknown -------------------------------------------------------------------
79 
QueryInterface(REFIID riid,void ** ppvObject)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 
AddRef(void)94 ULONG STDMETHODCALLTYPE WebNotificationCenter::AddRef(void)
95 {
96     return ++m_refCount;
97 }
98 
Release(void)99 ULONG STDMETHODCALLTYPE WebNotificationCenter::Release(void)
100 {
101     ULONG newRef = --m_refCount;
102     if (!newRef)
103         delete(this);
104 
105     return newRef;
106 }
107 
defaultCenterInternal()108 IWebNotificationCenter* WebNotificationCenter::defaultCenterInternal()
109 {
110     if (!m_defaultCenter)
111         m_defaultCenter = WebNotificationCenter::createInstance();
112     return m_defaultCenter;
113 }
114 
postNotificationInternal(IWebNotification * notification,BSTR notificationName,IUnknown * anObject)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 
defaultCenter(IWebNotificationCenter ** center)137 HRESULT STDMETHODCALLTYPE WebNotificationCenter::defaultCenter(
138     /* [retval][out] */ IWebNotificationCenter** center)
139 {
140     *center = defaultCenterInternal();
141     (*center)->AddRef();
142     return S_OK;
143 }
144 
addObserver(IWebNotificationObserver * observer,BSTR notificationName,IUnknown * anObject)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 
postNotification(IWebNotification * notification)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 
postNotificationName(BSTR notificationName,IUnknown * anObject,IPropertyBag * userInfo)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 
removeObserver(IWebNotificationObserver * anObserver,BSTR notificationName,IUnknown * anObject)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