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