WebKit/win/WebNotificationCenter.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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 }