Home | History | Annotate | Download | only in win
      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 
     55 WebNotificationCenter::WebNotificationCenter()
     56     : m_refCount(0)
     57     , d(new WebNotificationCenterPrivate)
     58 {
     59     gClassCount++;
     60     gClassNameCount.add("WebNotificationCenter");
     61 }
     62 
     63 WebNotificationCenter::~WebNotificationCenter()
     64 {
     65     gClassCount--;
     66     gClassNameCount.remove("WebNotificationCenter");
     67 }
     68 
     69 WebNotificationCenter* WebNotificationCenter::createInstance()
     70 {
     71     WebNotificationCenter* instance = new WebNotificationCenter();
     72     instance->AddRef();
     73     return instance;
     74 }
     75 
     76 // IUnknown -------------------------------------------------------------------
     77 
     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 
     92 ULONG STDMETHODCALLTYPE WebNotificationCenter::AddRef(void)
     93 {
     94     return ++m_refCount;
     95 }
     96 
     97 ULONG STDMETHODCALLTYPE WebNotificationCenter::Release(void)
     98 {
     99     ULONG newRef = --m_refCount;
    100     if (!newRef)
    101         delete(this);
    102 
    103     return newRef;
    104 }
    105 
    106 IWebNotificationCenter* WebNotificationCenter::defaultCenterInternal()
    107 {
    108     if (!m_defaultCenter)
    109         m_defaultCenter = WebNotificationCenter::createInstance();
    110     return m_defaultCenter;
    111 }
    112 
    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 
    135 HRESULT STDMETHODCALLTYPE WebNotificationCenter::defaultCenter(
    136     /* [retval][out] */ IWebNotificationCenter** center)
    137 {
    138     *center = defaultCenterInternal();
    139     (*center)->AddRef();
    140     return S_OK;
    141 }
    142 
    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 
    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 
    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 
    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