Home | History | Annotate | Download | only in notifications
      1 /*
      2  * Copyright (C) 2009 Google Inc. All rights reserved.
      3  * Copyright (C) 2009 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 #include "NotificationCenter.h"
     38 #include "NotificationContents.h"
     39 
     40 #include "Document.h"
     41 #include "EventNames.h"
     42 #include "ResourceRequest.h"
     43 #include "ResourceResponse.h"
     44 #include "ThreadableLoader.h"
     45 #include "WorkerContext.h"
     46 
     47 namespace WebCore {
     48 
     49 Notification::Notification(const KURL& url, ScriptExecutionContext* context, ExceptionCode& ec, PassRefPtr<NotificationCenter> provider)
     50     : ActiveDOMObject(context, this)
     51     , m_isHTML(true)
     52     , m_state(Idle)
     53     , m_notificationCenter(provider)
     54 {
     55     ASSERT(m_notificationCenter->presenter());
     56     if (m_notificationCenter->presenter()->checkPermission(context) != NotificationPresenter::PermissionAllowed) {
     57         ec = SECURITY_ERR;
     58         return;
     59     }
     60 
     61     if (url.isEmpty() || !url.isValid()) {
     62         ec = SYNTAX_ERR;
     63         return;
     64     }
     65 
     66     m_notificationURL = url;
     67 }
     68 
     69 Notification::Notification(const NotificationContents& contents, ScriptExecutionContext* context, ExceptionCode& ec, PassRefPtr<NotificationCenter> provider)
     70     : ActiveDOMObject(context, this)
     71     , m_isHTML(false)
     72     , m_contents(contents)
     73     , m_state(Idle)
     74     , m_notificationCenter(provider)
     75 {
     76     ASSERT(m_notificationCenter->presenter());
     77     if (m_notificationCenter->presenter()->checkPermission(context) != NotificationPresenter::PermissionAllowed) {
     78         ec = SECURITY_ERR;
     79         return;
     80     }
     81 
     82     if (!contents.icon().isEmpty() && !contents.icon().isValid()) {
     83         ec = SYNTAX_ERR;
     84         return;
     85     }
     86 }
     87 
     88 Notification::~Notification()
     89 {
     90     if (m_state == Loading) {
     91         ASSERT_NOT_REACHED();
     92         cancel();
     93     }
     94 }
     95 
     96 PassRefPtr<Notification> Notification::create(const KURL& url, ScriptExecutionContext* context, ExceptionCode& ec, PassRefPtr<NotificationCenter> provider)
     97 {
     98     return adoptRef(new Notification(url, context, ec, provider));
     99 }
    100 
    101 PassRefPtr<Notification> Notification::create(const NotificationContents& contents, ScriptExecutionContext* context, ExceptionCode& ec, PassRefPtr<NotificationCenter> provider)
    102 {
    103     return adoptRef(new Notification(contents, context, ec, provider));
    104 }
    105 
    106 void Notification::show()
    107 {
    108 #if PLATFORM(QT)
    109     if (iconURL().isEmpty()) {
    110         // Set the state before actually showing, because
    111         // handling of ondisplay may rely on that.
    112         if (m_state == Idle) {
    113             m_state = Showing;
    114             if (m_notificationCenter->presenter())
    115                 m_notificationCenter->presenter()->show(this);
    116         }
    117     } else
    118         startLoading();
    119 #else
    120     // prevent double-showing
    121     if (m_state == Idle && m_notificationCenter->presenter() && m_notificationCenter->presenter()->show(this))
    122         m_state = Showing;
    123 #endif
    124 }
    125 
    126 void Notification::cancel()
    127 {
    128     switch (m_state) {
    129     case Idle:
    130         break;
    131     case Loading:
    132         m_state = Cancelled;
    133         stopLoading();
    134         break;
    135     case Showing:
    136         if (m_notificationCenter->presenter())
    137             m_notificationCenter->presenter()->cancel(this);
    138         break;
    139     case Cancelled:
    140         break;
    141     }
    142 }
    143 
    144 EventTargetData* Notification::eventTargetData()
    145 {
    146     return &m_eventTargetData;
    147 }
    148 
    149 EventTargetData* Notification::ensureEventTargetData()
    150 {
    151     return &m_eventTargetData;
    152 }
    153 
    154 void Notification::contextDestroyed()
    155 {
    156     ActiveDOMObject::contextDestroyed();
    157     if (m_notificationCenter->presenter())
    158         m_notificationCenter->presenter()->notificationObjectDestroyed(this);
    159 }
    160 
    161 void Notification::startLoading()
    162 {
    163     if (m_state != Idle)
    164         return;
    165     setPendingActivity(this);
    166     m_state = Loading;
    167     ThreadableLoaderOptions options;
    168     options.sendLoadCallbacks = false;
    169     options.sniffContent = false;
    170     options.forcePreflight = false;
    171     options.allowCredentials = AllowStoredCredentials;
    172     options.crossOriginRequestPolicy = AllowCrossOriginRequests;
    173     m_loader = ThreadableLoader::create(scriptExecutionContext(), this, ResourceRequest(iconURL()), options);
    174 }
    175 
    176 void Notification::stopLoading()
    177 {
    178     m_iconData = 0;
    179     RefPtr<ThreadableLoader> protect(m_loader);
    180     m_loader->cancel();
    181 }
    182 
    183 void Notification::didReceiveResponse(const ResourceResponse& response)
    184 {
    185     int status = response.httpStatusCode();
    186     if (status && (status < 200 || status > 299)) {
    187         stopLoading();
    188         return;
    189     }
    190     m_iconData = SharedBuffer::create();
    191 }
    192 
    193 void Notification::didReceiveData(const char* data, int dataLength)
    194 {
    195     m_iconData->append(data, dataLength);
    196 }
    197 
    198 void Notification::didFinishLoading(unsigned long, double)
    199 {
    200     finishLoading();
    201 }
    202 
    203 void Notification::didFail(const ResourceError&)
    204 {
    205     finishLoading();
    206 }
    207 
    208 void Notification::didFailRedirectCheck()
    209 {
    210     finishLoading();
    211 }
    212 
    213 void Notification::didReceiveAuthenticationCancellation(const ResourceResponse&)
    214 {
    215     finishLoading();
    216 }
    217 
    218 void Notification::finishLoading()
    219 {
    220     if (m_state == Loading) {
    221         if (m_notificationCenter->presenter() && m_notificationCenter->presenter()->show(this))
    222             m_state = Showing;
    223     }
    224     unsetPendingActivity(this);
    225 }
    226 
    227 } // namespace WebCore
    228 
    229 #endif // ENABLE(NOTIFICATIONS)
    230