tizen beta release
[profile/ivi/webkit-efl.git] / Source / WebCore / notifications / Notification.cpp
1 /*
2  * Copyright (C) 2009 Google Inc. All rights reserved.
3  * Copyright (C) 2009, 2011 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33
34 #if ENABLE(NOTIFICATIONS)
35
36 #include "Notification.h"
37
38 #include "Document.h"
39 #include "EventNames.h"
40 #include "NotificationCenter.h"
41 #include "NotificationContents.h"
42 #include "NotificationPresenter.h"
43 #include "ResourceRequest.h"
44 #include "ResourceResponse.h"
45 #include "ThreadableLoader.h"
46 #include "WorkerContext.h"
47
48 namespace WebCore {
49
50 Notification::Notification()
51     : ActiveDOMObject(0, this)
52 {
53 }
54
55 Notification::Notification(const KURL& url, ScriptExecutionContext* context, ExceptionCode& ec, PassRefPtr<NotificationCenter> provider)
56     : ActiveDOMObject(context, this)
57     , m_isHTML(true)
58     , m_state(Idle)
59     , m_notificationCenter(provider)
60 {
61     ASSERT(m_notificationCenter->presenter());
62     if (m_notificationCenter->presenter()->checkPermission(context) != NotificationPresenter::PermissionAllowed) {
63         ec = SECURITY_ERR;
64         return;
65     }
66
67     if (url.isEmpty() || !url.isValid()) {
68         ec = SYNTAX_ERR;
69         return;
70     }
71
72     m_notificationURL = url;
73 }
74
75 Notification::Notification(const NotificationContents& contents, ScriptExecutionContext* context, ExceptionCode& ec, PassRefPtr<NotificationCenter> provider)
76     : ActiveDOMObject(context, this)
77     , m_isHTML(false)
78     , m_contents(contents)
79     , m_state(Idle)
80     , m_notificationCenter(provider)
81 {
82     ASSERT(m_notificationCenter->presenter());
83     if (m_notificationCenter->presenter()->checkPermission(context) != NotificationPresenter::PermissionAllowed) {
84         ec = SECURITY_ERR;
85         return;
86     }
87
88     if (!contents.icon.isEmpty() && !contents.icon.isValid()) {
89         ec = SYNTAX_ERR;
90         return;
91     }
92 }
93
94 Notification::~Notification() 
95 {
96     if (m_state == Loading) {
97         ASSERT_NOT_REACHED();
98         cancel();
99     }
100 }
101
102 PassRefPtr<Notification> Notification::create(const KURL& url, ScriptExecutionContext* context, ExceptionCode& ec, PassRefPtr<NotificationCenter> provider) 
103
104     return adoptRef(new Notification(url, context, ec, provider));
105 }
106
107 PassRefPtr<Notification> Notification::create(const NotificationContents& contents, ScriptExecutionContext* context, ExceptionCode& ec, PassRefPtr<NotificationCenter> provider) 
108
109     return adoptRef(new Notification(contents, context, ec, provider));
110 }
111
112 const AtomicString& Notification::interfaceName() const
113 {
114     return eventNames().interfaceForNotification;
115 }
116
117 void Notification::show() 
118 {
119 #if PLATFORM(QT)
120     if (iconURL().isEmpty()) {
121         // Set the state before actually showing, because
122         // handling of ondisplay may rely on that.
123         if (m_state == Idle) {
124             m_state = Showing;
125             if (m_notificationCenter->presenter())
126                 m_notificationCenter->presenter()->show(this);
127         }
128     } else
129         startLoading();
130 #else
131     // prevent double-showing
132     if (m_state == Idle && m_notificationCenter->presenter() && m_notificationCenter->presenter()->show(this))
133         m_state = Showing;
134 #endif
135 }
136
137 void Notification::cancel() 
138 {
139     switch (m_state) {
140     case Idle:
141         break;
142     case Loading:
143         m_state = Cancelled;
144         stopLoading();
145         break;
146     case Showing:
147         if (m_notificationCenter->presenter())
148             m_notificationCenter->presenter()->cancel(this);
149         break;
150     case Cancelled:
151         break;
152     }
153 }
154
155 EventTargetData* Notification::eventTargetData()
156 {
157     return &m_eventTargetData;
158 }
159
160 EventTargetData* Notification::ensureEventTargetData()
161 {
162     return &m_eventTargetData;
163 }
164
165 void Notification::contextDestroyed()
166 {
167     ActiveDOMObject::contextDestroyed();
168     if (m_notificationCenter->presenter())
169         m_notificationCenter->presenter()->notificationObjectDestroyed(this);
170 }
171
172 void Notification::startLoading()
173 {
174     if (m_state != Idle)
175         return;
176     setPendingActivity(this);
177     m_state = Loading;
178     ThreadableLoaderOptions options;
179     options.sendLoadCallbacks = DoNotSendCallbacks;
180     options.sniffContent = DoNotSniffContent;
181     options.preflightPolicy = ConsiderPreflight;
182     options.allowCredentials = AllowStoredCredentials;
183     options.crossOriginRequestPolicy = AllowCrossOriginRequests;
184     m_loader = ThreadableLoader::create(scriptExecutionContext(), this, ResourceRequest(iconURL()), options);
185 }
186
187 void Notification::stopLoading()
188 {
189     m_iconData = 0;
190     RefPtr<ThreadableLoader> protect(m_loader);
191     m_loader->cancel();
192 }
193
194 void Notification::didReceiveResponse(unsigned long, const ResourceResponse& response)
195 {
196     int status = response.httpStatusCode();
197     if (status && (status < 200 || status > 299)) {
198         stopLoading();
199         return;
200     }
201     m_iconData = SharedBuffer::create();
202 }
203
204 void Notification::didReceiveData(const char* data, int dataLength)
205 {
206     m_iconData->append(data, dataLength);
207 }
208
209 void Notification::didFinishLoading(unsigned long, double)
210 {
211     finishLoading();
212 }
213
214 void Notification::didFail(const ResourceError&)
215 {
216     finishLoading();
217 }
218
219 void Notification::didFailRedirectCheck()
220 {
221     finishLoading();
222 }
223
224 void Notification::finishLoading()
225 {
226     if (m_state == Loading) {
227         if (m_notificationCenter->presenter() && m_notificationCenter->presenter()->show(this))
228             m_state = Showing;
229     }
230     unsetPendingActivity(this);
231 }
232
233 } // namespace WebCore
234
235 #endif // ENABLE(NOTIFICATIONS)