1/*
2 * Copyright (C) 2009 Google 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 are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "WebDesktopNotificationsDelegate.h"
33#include "WebSecurityOrigin.h"
34#include "WebView.h"
35#include <WebCore/BString.h>
36#include <WebCore/Document.h>
37#include <WebCore/KURL.h>
38
39#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
40
41using namespace WebCore;
42
43class NotificationCOMWrapper : public IWebDesktopNotification {
44public:
45    static NotificationCOMWrapper* create(Notification* inner) { return new NotificationCOMWrapper(inner); }
46
47    // IUnknown
48    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
49    virtual ULONG STDMETHODCALLTYPE AddRef();
50    virtual ULONG STDMETHODCALLTYPE Release();
51
52    // IWebDesktopNotification
53    HRESULT STDMETHODCALLTYPE isHTML(BOOL* result);
54    HRESULT STDMETHODCALLTYPE contentsURL(BSTR* result);
55    HRESULT STDMETHODCALLTYPE iconURL(BSTR* result);
56    HRESULT STDMETHODCALLTYPE title(BSTR* result);
57    HRESULT STDMETHODCALLTYPE text(BSTR* result);
58    HRESULT STDMETHODCALLTYPE notifyDisplay();
59    HRESULT STDMETHODCALLTYPE notifyError();
60    HRESULT STDMETHODCALLTYPE notifyClose(BOOL xplicit);
61
62private:
63    NotificationCOMWrapper(Notification* inner) : m_refCount(1), m_inner(inner) {}
64
65    int m_refCount;
66    Notification* m_inner;
67};
68
69HRESULT STDMETHODCALLTYPE NotificationCOMWrapper::QueryInterface(REFIID riid, void** ppvObject)
70{
71    *ppvObject = 0;
72    if (IsEqualGUID(riid, IID_IUnknown))
73        *ppvObject = static_cast<NotificationCOMWrapper*>(this);
74    else if (IsEqualGUID(riid, IID_IWebDesktopNotification))
75        *ppvObject = static_cast<NotificationCOMWrapper*>(this);
76    else
77        return E_NOINTERFACE;
78
79    AddRef();
80    return S_OK;
81}
82
83ULONG STDMETHODCALLTYPE NotificationCOMWrapper::AddRef()
84{
85    return ++m_refCount;
86}
87
88ULONG STDMETHODCALLTYPE NotificationCOMWrapper::Release()
89{
90    ULONG newRef = --m_refCount;
91    if (!newRef)
92        delete(this);
93    return newRef;
94}
95
96HRESULT STDMETHODCALLTYPE NotificationCOMWrapper::isHTML(BOOL* result)
97{
98    *result = m_inner->isHTML();
99    return S_OK;
100}
101
102HRESULT STDMETHODCALLTYPE NotificationCOMWrapper::contentsURL(BSTR* result)
103{
104    *result = BString(m_inner->url()).release();
105    return S_OK;
106}
107
108HRESULT STDMETHODCALLTYPE NotificationCOMWrapper::iconURL(BSTR* result)
109{
110    *result = BString(m_inner->contents().icon()).release();
111    return S_OK;
112}
113
114HRESULT STDMETHODCALLTYPE NotificationCOMWrapper::title(BSTR* result)
115{
116    *result = BString(m_inner->contents().title()).release();
117    return S_OK;
118}
119
120HRESULT STDMETHODCALLTYPE NotificationCOMWrapper::text(BSTR* result)
121{
122    *result = BString(m_inner->contents().body()).release();
123    return S_OK;
124}
125
126HRESULT STDMETHODCALLTYPE NotificationCOMWrapper::notifyDisplay()
127{
128    m_inner->dispatchDisplayEvent();
129    return S_OK;
130}
131
132HRESULT STDMETHODCALLTYPE NotificationCOMWrapper::notifyError()
133{
134    m_inner->dispatchErrorEvent();
135    return S_OK;
136}
137
138HRESULT STDMETHODCALLTYPE NotificationCOMWrapper::notifyClose(BOOL xplicit)
139{
140    m_inner->dispatchCloseEvent();
141    return S_OK;
142}
143
144WebDesktopNotificationsDelegate::WebDesktopNotificationsDelegate(WebView* webView)
145    : m_webView(webView)
146{
147}
148
149bool WebDesktopNotificationsDelegate::show(Notification* object)
150{
151    if (hasNotificationDelegate())
152        notificationDelegate()->showDesktopNotification(NotificationCOMWrapper::create(object));
153    return true;
154}
155
156void WebDesktopNotificationsDelegate::cancel(Notification* object)
157{
158    if (hasNotificationDelegate())
159        notificationDelegate()->cancelDesktopNotification(NotificationCOMWrapper::create(object));
160}
161
162void WebDesktopNotificationsDelegate::notificationObjectDestroyed(Notification* object)
163{
164    if (hasNotificationDelegate())
165        notificationDelegate()->notificationDestroyed(NotificationCOMWrapper::create(object));
166}
167
168void WebDesktopNotificationsDelegate::notificationControllerDestroyed()
169{
170}
171
172void WebDesktopNotificationsDelegate::requestPermission(SecurityOrigin* origin, PassRefPtr<VoidCallback> callback)
173{
174    BString org(origin->toString());
175    if (hasNotificationDelegate())
176        notificationDelegate()->requestNotificationPermission(org);
177}
178
179void WebDesktopNotificationsDelegate::requestPermission(SecurityOrigin*, PassRefPtr<NotificationPermissionCallback>)
180{
181}
182
183void WebDesktopNotificationsDelegate::cancelRequestsForPermission(ScriptExecutionContext* context)
184{
185}
186
187NotificationClient::Permission WebDesktopNotificationsDelegate::checkPermission(const KURL& url)
188{
189    int out = 0;
190    BString org(SecurityOrigin::create(url)->toString());
191    if (hasNotificationDelegate())
192        notificationDelegate()->checkNotificationPermission(org, &out);
193    return (NotificationClient::Permission) out;
194}
195
196bool WebDesktopNotificationsDelegate::hasNotificationDelegate()
197{
198    COMPtr<IWebUIDelegate> ui;
199    m_webView->uiDelegate(&ui);
200
201    COMPtr<IWebUIDelegate2> ui2;
202    return SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegate2, (void**) &ui2));
203}
204
205COMPtr<IWebDesktopNotificationsDelegate> WebDesktopNotificationsDelegate::notificationDelegate()
206{
207    COMPtr<IWebUIDelegate> ui;
208    m_webView->uiDelegate(&ui);
209
210    COMPtr<IWebUIDelegate2> ui2;
211    COMPtr<IWebDesktopNotificationsDelegate> delegate;
212    if (SUCCEEDED(ui->QueryInterface(IID_IWebUIDelegate2, (void**) &ui2)))
213        ui2->desktopNotificationsDelegate(&delegate);
214
215    return delegate;
216}
217
218#endif // ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
219