Changeset 61121 in webkit


Ignore:
Timestamp:
Jun 14, 2010 7:09:46 AM (14 years ago)
Author:
yael.aharon@nokia.com
Message:

[Qt] Platform plugin support for Notifications UI
https://bugs.webkit.org/show_bug.cgi?id=40005

Reviewed by Kenneth Rohde Christiansen.

WebCore:

To avoid race condition when GC is run during shutdown,
disconnect the Notification from the NotificationPresenter
when the presenter deletes itself.
This cannot be tested by a layout test, the race condition happens only
when GC is run during shutdown. It can be tested manually by loading
manually any notification test and closing the browser.

  • notifications/Notification.cpp:

(WebCore::Notification::~Notification):

  • notifications/Notification.h:

(WebCore::Notification::detachPresenter):

WebKit/qt:

Add an interface to the platform plugin to display notifications.
Implemented the notification in the example platform plugin.
This interface is enabled by default, but could be turned off with
a build flag. The platform plugin should control its own lifecycle,
so now the close timer applies only when using the QSystemTrayIcon.
That's because QSystemTrayIcon does not inform its caller when it
is closed.

Changed the way NotificationPresenterClientQt is deleted because it
is being accessed when GC is deleting the Notification objects.
NotificationPresenterClientQt is now detaching itself from the
Notifications before it is deleted.

  • Api/qwebkitplatformplugin.h:

(QWebNotificationPresenter::QWebNotificationPresenter):
(QWebNotificationPresenter::~QWebNotificationPresenter):
(QWebKitPlatformPlugin::):

  • WebCoreSupport/NotificationPresenterClientQt.cpp:

(WebCore::NotificationIconWrapper::NotificationIconWrapper):
(WebCore::NotificationIconWrapper::title):
(WebCore::NotificationIconWrapper::message):
(WebCore::NotificationIconWrapper::iconData):
(WebCore::NotificationPresenterClientQt::~NotificationPresenterClientQt):
(WebCore::NotificationIconWrapper::notificationClosed):
(WebCore::NotificationPresenterClientQt::displayNotification):
(WebCore::NotificationPresenterClientQt::cancel):
(WebCore::NotificationPresenterClientQt::notificationForWrapper):
(WebCore::NotificationPresenterClientQt::removeReplacedNotificationFromQueue):
(WebCore::NotificationPresenterClientQt::detachNotification):

  • WebCoreSupport/NotificationPresenterClientQt.h:
  • WebCoreSupport/QtPlatformPlugin.cpp:

(WebCore::QtPlatformPlugin::createNotificationPresenter):

  • WebCoreSupport/QtPlatformPlugin.h:
  • examples/platformplugin/WebNotificationPresenter.cpp: Added.

(WebNotificationWidget::WebNotificationWidget):
(WebNotificationWidget::~WebNotificationWidget):
(WebNotificationWidget::showNotification):
(WebNotificationWidget::event):

  • examples/platformplugin/WebNotificationPresenter.h: Added.

(WebNotificationPresenter::WebNotificationPresenter):
(WebNotificationPresenter::~WebNotificationPresenter):
(WebNotificationPresenter::showNotification):

  • examples/platformplugin/WebPlugin.cpp:

(WebPlugin::supportsExtension):

  • examples/platformplugin/WebPlugin.h:

(WebPlugin::createNotificationPresenter):

  • examples/platformplugin/platformplugin.pro:
  • examples/platformplugin/qwebkitplatformplugin.h:

(QWebNotificationPresenter::QWebNotificationPresenter):
(QWebNotificationPresenter::~QWebNotificationPresenter):
(QWebKitPlatformPlugin::):

Location:
trunk
Files:
2 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r61120 r61121  
     12010-06-13  Yael Aharon  <yael.aharon@nokia.com>
     2
     3        Reviewed by Kenneth Rohde Christiansen.
     4
     5        [Qt] Platform plugin support for Notifications UI
     6        https://bugs.webkit.org/show_bug.cgi?id=40005
     7
     8        To avoid race condition when GC is run during shutdown,
     9        disconnect the Notification from the NotificationPresenter
     10        when the presenter deletes itself.
     11        This cannot be tested by a layout test, the race condition happens only
     12        when GC is run during shutdown. It can be tested manually by loading
     13        manually any notification test and closing the browser.
     14
     15        * notifications/Notification.cpp:
     16        (WebCore::Notification::~Notification):
     17        * notifications/Notification.h:
     18        (WebCore::Notification::detachPresenter):
     19
    1202010-06-08  Marcus Bulach  <bulach@chromium.org>
    221
  • trunk/WebCore/notifications/Notification.cpp

    r60960 r61121  
    9191        cancel();
    9292    }
    93     m_presenter->notificationObjectDestroyed(this);
     93    if (m_presenter)
     94        m_presenter->notificationObjectDestroyed(this);
    9495}
    9596
  • trunk/WebCore/notifications/Notification.h

    r60960 r61121  
    9393        void releaseIconData() { m_iconData = 0; }
    9494
     95        // Called if the presenter is deleted before the notification is GC'd
     96        void detachPresenter() { m_presenter = 0; }
     97
    9598        virtual void didReceiveResponse(const ResourceResponse&);
    9699        virtual void didReceiveData(const char* data, int lengthReceived);
     
    120123        String m_replaceId;
    121124
    122 
    123125        enum NotificationState {
    124126            Idle = 0,
  • trunk/WebKit/qt/Api/qwebkitplatformplugin.h

    r60593 r61121  
    5959};
    6060
     61class QWebNotificationData
     62{
     63public:
     64    virtual const QString title() const = 0;
     65    virtual const QString message() const = 0;
     66    virtual const QByteArray iconData() const = 0;
     67};
     68
     69class QWebNotificationPresenter : public QObject
     70{
     71    Q_OBJECT
     72public:
     73    QWebNotificationPresenter() {}
     74    virtual ~QWebNotificationPresenter() {}
     75
     76    virtual void showNotification(const QWebNotificationData*) = 0;
     77   
     78Q_SIGNALS:
     79    void notificationClosed();
     80};
     81
    6182class QWebKitPlatformPlugin
    6283{
     
    6586
    6687    enum Extension {
    67         MultipleSelections
     88        MultipleSelections,
     89        Notifications
    6890    };
    6991
    7092    virtual bool supportsExtension(Extension extension) const = 0;
    7193    virtual QWebSelectMethod* createSelectInputMethod() const = 0;
     94    virtual QWebNotificationPresenter* createNotificationPresenter() const = 0;
    7295
    7396};
    7497
    75 Q_DECLARE_INTERFACE(QWebKitPlatformPlugin, "com.nokia.Qt.WebKit.PlatformPlugin/1.1");
     98Q_DECLARE_INTERFACE(QWebKitPlatformPlugin, "com.nokia.Qt.WebKit.PlatformPlugin/1.2");
    7699
    77100#endif // QWEBKITPLATFORMPLUGIN_H
  • trunk/WebKit/qt/ChangeLog

    r61117 r61121  
     12010-06-13  Yael Aharon  <yael.aharon@nokia.com>
     2
     3        Reviewed by Kenneth Rohde Christiansen.
     4
     5        [Qt] Platform plugin support for Notifications UI
     6        https://bugs.webkit.org/show_bug.cgi?id=40005
     7
     8        Add an interface to the platform plugin to display notifications.
     9        Implemented the notification in the example platform plugin.
     10        This interface is enabled by default, but could be turned off with
     11        a build flag. The platform plugin should control its own lifecycle,
     12        so now the close timer applies only when using the QSystemTrayIcon.
     13        That's because QSystemTrayIcon does not inform its caller when it
     14        is closed.
     15
     16        Changed the way NotificationPresenterClientQt is deleted because it
     17        is being accessed when GC is deleting the Notification objects.
     18        NotificationPresenterClientQt is now detaching itself from the
     19        Notifications before it is deleted.
     20
     21        * Api/qwebkitplatformplugin.h:
     22        (QWebNotificationPresenter::QWebNotificationPresenter):
     23        (QWebNotificationPresenter::~QWebNotificationPresenter):
     24        (QWebKitPlatformPlugin::):
     25        * WebCoreSupport/NotificationPresenterClientQt.cpp:
     26        (WebCore::NotificationIconWrapper::NotificationIconWrapper):
     27        (WebCore::NotificationIconWrapper::title):
     28        (WebCore::NotificationIconWrapper::message):
     29        (WebCore::NotificationIconWrapper::iconData):
     30        (WebCore::NotificationPresenterClientQt::~NotificationPresenterClientQt):
     31        (WebCore::NotificationIconWrapper::notificationClosed):
     32        (WebCore::NotificationPresenterClientQt::displayNotification):
     33        (WebCore::NotificationPresenterClientQt::cancel):
     34        (WebCore::NotificationPresenterClientQt::notificationForWrapper):
     35        (WebCore::NotificationPresenterClientQt::removeReplacedNotificationFromQueue):
     36        (WebCore::NotificationPresenterClientQt::detachNotification):
     37        * WebCoreSupport/NotificationPresenterClientQt.h:
     38        * WebCoreSupport/QtPlatformPlugin.cpp:
     39        (WebCore::QtPlatformPlugin::createNotificationPresenter):
     40        * WebCoreSupport/QtPlatformPlugin.h:
     41        * examples/platformplugin/WebNotificationPresenter.cpp: Added.
     42        (WebNotificationWidget::WebNotificationWidget):
     43        (WebNotificationWidget::~WebNotificationWidget):
     44        (WebNotificationWidget::showNotification):
     45        (WebNotificationWidget::event):
     46        * examples/platformplugin/WebNotificationPresenter.h: Added.
     47        (WebNotificationPresenter::WebNotificationPresenter):
     48        (WebNotificationPresenter::~WebNotificationPresenter):
     49        (WebNotificationPresenter::showNotification):
     50        * examples/platformplugin/WebPlugin.cpp:
     51        (WebPlugin::supportsExtension):
     52        * examples/platformplugin/WebPlugin.h:
     53        (WebPlugin::createNotificationPresenter):
     54        * examples/platformplugin/platformplugin.pro:
     55        * examples/platformplugin/qwebkitplatformplugin.h:
     56        (QWebNotificationPresenter::QWebNotificationPresenter):
     57        (QWebNotificationPresenter::~QWebNotificationPresenter):
     58        (QWebKitPlatformPlugin::):
     59
    1602010-06-14  Mahesh Kulkarni  <mahesh.kulkarni@nokia.com>
    261
  • trunk/WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.cpp

    r60981 r61121  
    3737#include "EventNames.h"
    3838#include "KURL.h"
     39#include "QtPlatformPlugin.h"
    3940#include "SecurityOrigin.h"
    4041
     
    6768    m_notificationIcon = 0;
    6869#endif
    69     m_closeTimer.startOneShot(notificationTimeout);
     70    m_presenter = 0;
    7071}
    7172
     
    7980}
    8081
     82const QString NotificationIconWrapper::title() const
     83{
     84    Notification* notification = NotificationPresenterClientQt::notificationPresenter()->notificationForWrapper(this);
     85    if (notification)
     86        return notification->contents().title();
     87    return QString();
     88}
     89
     90const QString NotificationIconWrapper::message() const
     91{
     92    Notification* notification = NotificationPresenterClientQt::notificationPresenter()->notificationForWrapper(this);
     93    if (notification)
     94        return notification->contents().body();
     95    return QString();
     96}
     97
     98const QByteArray NotificationIconWrapper::iconData() const
     99{
     100    Notification* notification = NotificationPresenterClientQt::notificationPresenter()->notificationForWrapper(this);
     101    QByteArray iconData;
     102    if (notification) {
     103        if (notification->iconData())
     104            iconData = QByteArray::fromRawData(notification->iconData()->data(), notification->iconData()->size());
     105    }
     106    return iconData;
     107}
     108
    81109NotificationPresenterClientQt::NotificationPresenterClientQt() : m_clientCount(0)
    82110{
     111}
     112
     113NotificationPresenterClientQt::~NotificationPresenterClientQt()
     114{
     115    while (!m_notifications.isEmpty()) {
     116        NotificationsQueue::Iterator iter = m_notifications.begin();
     117        detachNotification(iter.key());
     118    }
    83119}
    84120
     
    90126        delete this;
    91127    }
     128}
     129
     130void NotificationIconWrapper::notificationClosed()
     131{
     132    NotificationPresenterClientQt::notificationPresenter()->cancel(this);
    92133}
    93134
     
    124165    }
    125166
     167    if (m_platformPlugin.plugin() && m_platformPlugin.plugin()->supportsExtension(QWebKitPlatformPlugin::Notifications))
     168        wrapper->m_presenter = m_platformPlugin.createNotificationPresenter();
     169
     170    if (!wrapper->m_presenter) {
    126171#ifndef QT_NO_SYSTEMTRAYICON
    127     QPixmap pixmap;
    128     if (bytes.length() && pixmap.loadFromData(bytes)) {
    129         QIcon icon(pixmap);
    130         wrapper->m_notificationIcon = new QSystemTrayIcon(icon);
    131     } else
    132         wrapper->m_notificationIcon = new QSystemTrayIcon();
     172        wrapper->m_closeTimer.startOneShot(notificationTimeout);
     173        QPixmap pixmap;
     174        if (bytes.length() && pixmap.loadFromData(bytes)) {
     175            QIcon icon(pixmap);
     176            wrapper->m_notificationIcon = new QSystemTrayIcon(icon);
     177        } else
     178            wrapper->m_notificationIcon = new QSystemTrayIcon();
    133179#endif
     180    }
    134181
    135182    sendEvent(notification, "display");
     
    138185    if (m_notifications.find(notification) == m_notifications.end())
    139186        return;
     187
     188    if (wrapper->m_presenter) {
     189        wrapper->connect(wrapper->m_presenter.get(), SIGNAL(notificationClosed()), wrapper, SLOT(notificationClosed()), Qt::QueuedConnection);
     190        wrapper->m_presenter->showNotification(wrapper);
     191        return;
     192    }
    140193
    141194#ifndef QT_NO_SYSTEMTRAYICON
     
    157210    if (iter != m_notifications.end()) {
    158211        sendEvent(notification, eventNames().closeEvent);
    159         delete m_notifications.take(notification);
    160         notification->unsetPendingActivity(notification);
     212        detachNotification(notification);
    161213    }
    162214}
     
    164216void NotificationPresenterClientQt::cancel(NotificationIconWrapper* wrapper)
    165217{
    166     NotificationsQueue::Iterator end = m_notifications.end();
    167     NotificationsQueue::Iterator iter = m_notifications.begin();
     218    Notification* notification = notificationForWrapper(wrapper);
     219    if (notification)
     220        cancel(notification);
     221}
     222
     223Notification* NotificationPresenterClientQt::notificationForWrapper(const NotificationIconWrapper* wrapper) const
     224{
     225    NotificationsQueue::ConstIterator end = m_notifications.end();
     226    NotificationsQueue::ConstIterator iter = m_notifications.begin();
    168227    while (iter != end && iter.value() != wrapper)
    169228        iter++;
    170229    if (iter != end)
    171         cancel(iter.key());
     230        return iter.key();
     231    return 0;
    172232}
    173233
     
    253313            dumpReplacedIdText(oldNotification);
    254314        sendEvent(oldNotification, eventNames().closeEvent);
    255         delete m_notifications.take(oldNotification);
    256         oldNotification->unsetPendingActivity(oldNotification);
    257     }
     315        detachNotification(oldNotification);
     316    }
     317}
     318
     319void NotificationPresenterClientQt::detachNotification(Notification* notification)
     320{
     321    delete m_notifications.take(notification);
     322    notification->detachPresenter();
     323    notification->unsetPendingActivity(notification);
    258324}
    259325
  • trunk/WebKit/qt/WebCoreSupport/NotificationPresenterClientQt.h

    r60566 r61121  
    3535#include "Notification.h"
    3636#include "NotificationPresenter.h"
     37#include "QtPlatformPlugin.h"
    3738#include "Timer.h"
     39
     40#include "qwebkitplatformplugin.h"
    3841
    3942#include <QMultiHash>
    4043#include <QSystemTrayIcon>
    41 
    42 #if ENABLE(NOTIFICATIONS)
    4344
    4445namespace WebCore {
     
    4748class KURL;
    4849
    49 class NotificationIconWrapper {
     50class NotificationIconWrapper : public QObject, public QWebNotificationData {
     51    Q_OBJECT
    5052public:
    5153    NotificationIconWrapper();
    5254    ~NotificationIconWrapper();
     55
    5356    void close();
    5457    void close(Timer<NotificationIconWrapper>*);
     58    const QString title() const;
     59    const QString message() const;
     60    const QByteArray iconData() const;
     61
     62public Q_SLOTS:
     63    void notificationClosed();
     64
     65public:
    5566#ifndef QT_NO_SYSTEMTRAYICON
    5667    OwnPtr<QSystemTrayIcon> m_notificationIcon;
    5768#endif
     69
     70    OwnPtr<QWebNotificationPresenter> m_presenter;
    5871    Timer<NotificationIconWrapper> m_closeTimer;
    5972};
     73
     74#if ENABLE(NOTIFICATIONS)
    6075
    6176typedef QHash <Notification*, NotificationIconWrapper*> NotificationsQueue;
     
    6479public:
    6580    NotificationPresenterClientQt();
    66     ~NotificationPresenterClientQt() {}
     81    ~NotificationPresenterClientQt();
    6782
    6883    /* WebCore::NotificationPresenter interface */
     
    85100    static NotificationPresenterClientQt* notificationPresenter();
    86101
     102    Notification* notificationForWrapper(const NotificationIconWrapper*) const;
     103
    87104private:
    88105    void sendEvent(Notification*, const AtomicString& eventName);
    89106    void displayNotification(Notification*, const QByteArray&);
    90107    void removeReplacedNotificationFromQueue(Notification*);
     108    void detachNotification(Notification*);
    91109    void dumpReplacedIdText(Notification*);
    92110    void dumpShowText(Notification*);
     
    96114    NotificationsQueue m_notifications;
    97115    QObject* m_receiver;
     116    QtPlatformPlugin m_platformPlugin;
    98117};
     118
     119#endif
    99120
    100121}
    101122
    102123#endif
    103 #endif
  • trunk/WebKit/qt/WebCoreSupport/QtPlatformPlugin.cpp

    r60593 r61121  
    158158}
    159159
     160
     161QWebNotificationPresenter* QtPlatformPlugin::createNotificationPresenter()
     162{
     163    QWebKitPlatformPlugin* p = plugin();
     164    if (!p)
     165        return 0;
     166    return p->createNotificationPresenter();
    160167}
     168
     169}
  • trunk/WebKit/qt/WebCoreSupport/QtPlatformPlugin.h

    r60593 r61121  
    2828class QWebSelectMethod;
    2929class QWebKitPlatformPlugin;
     30class QWebNotificationPresenter;
    3031
    3132namespace WebCore {
     
    5354
    5455    QtAbstractWebPopup* createSelectInputMethod();
     56    QWebNotificationPresenter* createNotificationPresenter();
     57
     58    QWebKitPlatformPlugin* plugin();
    5559
    5660private:
     
    6064    bool load();
    6165    bool load(const QString& file);
    62 
    63     QWebKitPlatformPlugin* plugin();
    6466};
    6567
  • trunk/WebKit/qt/examples/platformplugin/WebPlugin.cpp

    r60285 r61121  
    211211bool WebPlugin::supportsExtension(Extension extension) const
    212212{
    213     return extension == MultipleSelections;
     213    if (extension == MultipleSelections)
     214        return true;
     215    if (extension == Notifications)
     216#if ENABLE_NOTIFICATIONS
     217        return true;
     218#else
     219        return false;
     220#endif
     221    return false;
    214222}
    215223
  • trunk/WebKit/qt/examples/platformplugin/WebPlugin.h

    r60285 r61121  
    2222
    2323#include "qwebkitplatformplugin.h"
     24#include "WebNotificationPresenter.h"
    2425
    2526#include <QDialog>
     
    8990    virtual QWebSelectMethod* createSelectInputMethod() const { return new WebPopup(); }
    9091    virtual bool supportsExtension(Extension extension) const;
     92    virtual QWebNotificationPresenter* createNotificationPresenter() const {
     93        return new WebNotificationPresenter();
     94    }
    9195};
    9296
    93 
    94 
    9597#endif // WEBPLUGIN_H
  • trunk/WebKit/qt/examples/platformplugin/platformplugin.pro

    r60285 r61121  
    77
    88SOURCES += \
    9     WebPlugin.cpp
     9    WebPlugin.cpp \
     10    WebNotificationPresenter.cpp
    1011
    1112HEADERS += \
    1213    WebPlugin.h \
    13     qwebkitplatformplugin.h
     14    qwebkitplatformplugin.h \
     15    WebNotificationPresenter.h
     16
     17!contains(DEFINES, ENABLE_NOTIFICATIONS=.): DEFINES += ENABLE_NOTIFICATIONS=1
  • trunk/WebKit/qt/examples/platformplugin/qwebkitplatformplugin.h

    r60593 r61121  
    5959};
    6060
     61class QWebNotificationData
     62{
     63public:
     64    virtual const QString title() const = 0;
     65    virtual const QString message() const = 0;
     66    virtual const QByteArray iconData() const = 0;
     67};
     68
     69class QWebNotificationPresenter : public QObject
     70{
     71    Q_OBJECT
     72public:
     73    QWebNotificationPresenter() {}
     74    virtual ~QWebNotificationPresenter() {}
     75
     76    virtual void showNotification(const QWebNotificationData*) = 0;
     77   
     78Q_SIGNALS:
     79    void notificationClosed();
     80};
     81
    6182class QWebKitPlatformPlugin
    6283{
     
    6586
    6687    enum Extension {
    67         MultipleSelections
     88        MultipleSelections,
     89        Notifications
    6890    };
    6991
    7092    virtual bool supportsExtension(Extension extension) const = 0;
    7193    virtual QWebSelectMethod* createSelectInputMethod() const = 0;
     94    virtual QWebNotificationPresenter* createNotificationPresenter() const = 0;
    7295
    7396};
    7497
    75 Q_DECLARE_INTERFACE(QWebKitPlatformPlugin, "com.nokia.Qt.WebKit.PlatformPlugin/1.1");
     98Q_DECLARE_INTERFACE(QWebKitPlatformPlugin, "com.nokia.Qt.WebKit.PlatformPlugin/1.2");
    7699
    77100#endif // QWEBKITPLATFORMPLUGIN_H
Note: See TracChangeset for help on using the changeset viewer.