Search code examples
c++qtqtwebkitqwebpage

How to customize "Notification Web API" in the QT


I'm creating a simple browser using QtWebkit, I managed to add support for Notification Web API it, using QWebPage::setFeaturePermission.

Example:

function notifyMe() {
    if (Notification.permission === "granted") {
        var notification = new Notification("Hi there!");
    } else if (Notification.permission !== "denied") {
        Notification.requestPermission(function(permission) {
            if (permission === "granted") {
                var notification = new Notification("Hi there!");
            }
        });
    }
}

<button onclick="notifyMe();">Notify me</button>

My code:

QObject::connect(page,
    SIGNAL(featurePermissionRequested(QWebFrame*, QWebPage::Feature)), this,
    SLOT(featurePermissionRequested(QWebFrame*,QWebPage::Feature))
);

...

void Form::featurePermissionRequested(QWebFrame* frame, QWebPage::Feature feature) {
    switch (feature) {
        case QWebPage::Notifications:
            qDebug() << "Notification";
            page->setFeaturePermission(frame, feature, QWebPage::PermissionGrantedByUser);
        break;
        case QWebPage::Geolocation:
            qDebug() << "GEO";
        break;
        default:
            qDebug() << "Unknown feature";
    }
}

Every time I click on the "Notify me" button the following message appears on the desktop:

Desktop Notification

It is possible to customize the notifications in QT? In other words, leave similar to the GoogleChrome or Firefox, like this:

Web Notification


Solution

  • To customize Notifications Web API in QtWebkit you must use the "Webkit plugins", in other words create a plugin and put in the qtdir/plugins/webkit.

    Note: For create plugin is needed <QtWebKit/QWebKitPlatformPlugin> class

    Create the plugin:

    • Create a project in QtCreator
    • In .pro file use (example src.pro):

      TARGET = $$qtLibraryTarget(mywebkitplugin)
      TEMPLATE = lib
      CONFIG += plugin
      
      HEADERS += $$[QT_INSTALL_HEADERS]/QtWebKit/qwebkitplatformplugin.h \
          mywebkitplugin.h
      
      SOURCES += \
          mywebkitplugin.cpp
      
      Release:DESTDIR     = $$PWD/bin/release
      Release:UI_DIR      = $${DESTDIR}/.ui
      Release:MOC_DIR     = $${DESTDIR}/.moc
      Release:RCC_DIR     = $${DESTDIR}/.rcc
      Release:OBJECTS_DIR = $${DESTDIR}/.obj
      
      Debug:DESTDIR       = $$PWD/bin/debug
      Debug:UI_DIR        = $${DESTDIR}/.ui
      Debug:MOC_DIR       = $${DESTDIR}/.moc
      Debug:RCC_DIR       = $${DESTDIR}/.rcc
      Debug:OBJECTS_DIR   = $${DESTDIR}/.obj
      
    • Create mywebkitplugin.h

      #ifndef MYWEBKITPLUGIN_H
      #define MYWEBKITPLUGIN_H
      
      #include <QtWebKit/QWebKitPlatformPlugin>
      
      class MyWebKitPlugin : public QObject, public QWebKitPlatformPlugin
      {
          Q_OBJECT
          Q_INTERFACES(QWebKitPlatformPlugin)
      
      #if QT_VERSION >= 0x050000
          Q_PLUGIN_METADATA(IID "org.qtwebkit.QtWebKit.QtWebPlugin")
      #endif
      
      public:
          explicit MyWebKitPlugin();
          ~MyWebKitPlugin();
      
          bool supportsExtension(Extension ext) const;
          QObject* createExtension(Extension ext) const;
      };
      
      #endif // MYWEBKITPLUGIN_H
      
    • Create mywebkitplugin.cpp

      #include "mywebkitplugin.h"
      #include "notification/notification.h"
      
      MyWebKitPlugin::MyWebKitPlugin()
      {
      }
      
      MyWebKitPlugin::~MyWebKitPlugin()
      {
      }
      
      bool MyWebKitPlugin::supportsExtension(Extension ext) const
      {
          return ext == Notifications;
      }
      
      QObject* MyWebKitPlugin::createExtension(Extension ext) const
      {
          switch (ext) {
              case Notifications:
                  return new Notification();
      
              default:
                  return 0;
          }
      }
      
      //for QT-4.8
      #if QT_VERSION < 0x050000
      Q_EXPORT_PLUGIN2(webkitplugin, MyWebKitPlugin);
      #endif
      
    • Create notification folder

    • In notification folder put notification class:

      notification.h

      #ifndef NOTIFICATION_H
      #define NOTIFICATION_H
      
      #include <QtWebKit/QWebKitPlatformPlugin>
      
      class Notification : public QWebNotificationPresenter
      {
          Q_OBJECT
      
      public:
          explicit Notification();
          ~Notification();
      
          void showNotification(const QWebNotificationData* data);
      
      signals:
          void notificationClosed();
          void notificationClicked();
      };
      
      #endif // NOTIFICATION_H
      

      notification.cpp

      #include "notification.h"
      #include <QDebug>
      
      Notification::Notification() : QWebNotificationPresenter()
      {
          qDebug() << "Create: Notification";
      }
      
      Notification::~Notification()
      {
          qDebug() << "Delete: this (Notification)";
      }
      
      void Notification::showNotification(const QWebNotificationData* data)
      {
          qDebug() << "title:" << data->title();
          qDebug() << "icon:" << data->iconUrl();
          qDebug() << "message:" << data->message();
          qDebug() << "opener page:" << data->openerPageUrl();
      }
      

    For create your notification customized change Notification::showNotification(const QWebNotificationData* data) content and use QWebNotificationData* data for get data from JavaScript API.

    • Create notification.pri (included in src.pro):

      QT += network
      
      HEADERS += \
          $$PWD/notification.h
      
      SOURCES += \
          $$PWD/notification.cpp
      
    • Add notification.pri in src.pro:

      include($$PWD/notification/notification.pri)
      

    Compiling/build:

    • Open src.pro in QtCreator
    • Click in Build (in Release Mode) (or use Ctrl+B) button (don't click in Run button, don't use Ctrl+R)
    • Close src.pro
    • Go to the folder that is located the src.pro
    • (If release mode) Open bin/release folder
    • (If debug mode) Open bin/debug folder
    • (If release mode) Copy mywebkitplugin.dll to QtDir/plugins/webkit/mywebkitplugin.dll (eg with mingw: C:/qt/qt5.4/mingw/plugin/webkit/mywebkitplugin.dll)
    • (If debug mode) Copy mywebkitplugind.dll to QtDir/plugins/webkit/mywebkitplugind.dll (eg with mingw: C:/qt/qt5.4/mingw/plugin/webkit/mywebkitplugind.dll)
    • If webkit folder does not exist, create it.
    • Open your project with QWebView and test Notification Web API.

    When running a project that uses QWebView, it will automatically load the dll (no needs extras configurations in your project) and will "replace" the default Notifications (QtWebkit in Windows uses SystemTrayIcon for show Notification Web API) for your "custom widget".

    Folder structure for plugin projetct:

    mywebkitplugin
    ├── `src.pro`
    ├── mywebkitplugin.h
    ├── mywebkitplugin.cpp
    └── notification
        ├── notification.h
        ├── notification.cpp
        └── `notification.pri`