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