[Merge] lp:~mardy/webbrowser-app/add-onlineaccount-support-for-container2 into lp:webbrowser-app

Alberto Mardegan alberto.mardegan at canonical.com
Mon Jun 2 11:20:25 UTC 2014


I changed the test name, and replied to your comment about the SQL connection name.

Diff comments:

> === modified file 'debian/control'
> --- debian/control	2014-05-02 05:45:21 +0000
> +++ debian/control	2014-05-30 12:37:47 +0000
> @@ -51,9 +51,12 @@
>  Multi-Arch: foreign
>  Depends: ${misc:Depends},
>           ${shlibs:Depends},
> +         libqt5webkit5-qmlwebkitplugin, 
> +         qtdeclarative5-accounts-plugin,
> +         qtdeclarative5-qtquick2-plugin (>= 5.2),
>           unity-webapps-qml,
> -         libqt5webkit5-qmlwebkitplugin, 
>           webbrowser-app (= ${binary:Version}),
> +Suggests: qtdeclarative5-online-accounts-client0.1 (>= 0.3),
>  Description: Ubuntu web applications container
>   A lightweight webapps container tailored for Ubuntu, based on the Webkit
>   rendering engine and using the Ubuntu UI components.
> 
> === modified file 'src/app/browserapplication.cpp'
> --- src/app/browserapplication.cpp	2014-05-21 08:01:42 +0000
> +++ src/app/browserapplication.cpp	2014-05-30 12:37:47 +0000
> @@ -122,6 +122,9 @@
>      if (!isRunningInstalled()) {
>          m_engine->addImportPath(UbuntuBrowserImportsDirectory());
>      }
> +
> +    qmlEngineCreated(m_engine);
> +
>      QQmlContext* context = m_engine->rootContext();
>      m_component = new QQmlComponent(m_engine);
>      m_component->loadUrl(QUrl::fromLocalFile(UbuntuBrowserDirectory() + "/" + qmlFileSubPath));
> @@ -141,6 +144,9 @@
>      return true;
>  }
>  
> +void BrowserApplication::qmlEngineCreated(QQmlEngine*)
> +{}
> +
>  int BrowserApplication::run()
>  {
>      Q_ASSERT(m_window != 0);
> 
> === modified file 'src/app/browserapplication.h'
> --- src/app/browserapplication.h	2014-04-10 14:47:53 +0000
> +++ src/app/browserapplication.h	2014-05-30 12:37:47 +0000
> @@ -49,6 +49,8 @@
>      virtual void printUsage() const = 0;
>      QList<QUrl> urls() const;
>  
> +    virtual void qmlEngineCreated(QQmlEngine*);
> +
>      QStringList m_arguments;
>      QQmlEngine* m_engine;
>      QQuickWindow* m_window;
> 
> === added file 'src/app/webcontainer/AccountsPage.qml'
> --- src/app/webcontainer/AccountsPage.qml	1970-01-01 00:00:00 +0000
> +++ src/app/webcontainer/AccountsPage.qml	2014-05-30 12:37:47 +0000
> @@ -0,0 +1,73 @@
> +/*
> + * Copyright 2013-2014 Canonical Ltd.
> + *
> + * This file is part of webbrowser-app.
> + *
> + * webbrowser-app is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * webbrowser-app is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +import QtQuick 2.0
> +import Ubuntu.Components 0.1
> +import webcontainer.private 0.1
> +
> +Page {
> +    id: accountsPage
> +
> +    property alias accountProvider: accountsLogin.accountProvider
> +    property alias applicationName: accountsLogin.applicationName
> +    property var webappCookieStore: null
> +
> +    signal done()
> +
> +    visible: false
> +    anchors.fill: parent
> +
> +    AccountsLoginPage {
> +        id: accountsLogin
> +
> +        anchors.fill: parent
> +
> +        QtObject {
> +            id: internal
> +            function onMoved(result) {
> +                webappCookieStore.moved.disconnect(internal.onMoved)
> +                if (!result) {
> +                    console.error("Unable to move cookies")
> +                }
> +                accountsPage.done()
> +            }
> +        }
> +
> +        onDone: {
> +            if (!accountsPage.visible)
> +                return
> +            if (!credentialsId) {
> +                accountsPage.done()
> +                return
> +            }
> +
> +            if (webappCookieStore) {
> +                var instance = onlineAccountStoreComponent.createObject(accountsLogin, {accountId: credentialsId})
> +                webappCookieStore.moved.connect(internal.onMoved)
> +                webappCookieStore.moveFrom(instance)
> +            } else {
> +                accountsPage.done()
> +            }
> +        }
> +    }
> +
> +    Component {
> +        id: onlineAccountStoreComponent
> +        OnlineAccountsCookieStore { }
> +    }
> +}
> 
> === modified file 'src/app/webcontainer/CMakeLists.txt'
> --- src/app/webcontainer/CMakeLists.txt	2014-04-03 12:01:59 +0000
> +++ src/app/webcontainer/CMakeLists.txt	2014-05-30 12:37:47 +0000
> @@ -9,7 +9,11 @@
>  set(WEBAPP_CONTAINER webapp-container)
>  
>  set(WEBAPP_CONTAINER_SRC
> +    chrome-cookie-store.cpp
> +    cookie-store.cpp
> +    online-accounts-cookie-store.cpp
>      webapp-container.cpp
> +    webkit-cookie-store.cpp
>      session-utils.cpp
>      url-pattern-utils.cpp
>  )
> @@ -18,7 +22,7 @@
>  
>  target_link_libraries(${WEBAPP_CONTAINER} ${COMMONLIB})
>  
> -qt5_use_modules(${WEBAPP_CONTAINER} Core Widgets Quick)
> +qt5_use_modules(${WEBAPP_CONTAINER} Core Widgets Quick Sql DBus)
>  
>  install(TARGETS ${WEBAPP_CONTAINER}
>          RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
> 
> === added file 'src/app/webcontainer/chrome-cookie-store.cpp'
> --- src/app/webcontainer/chrome-cookie-store.cpp	1970-01-01 00:00:00 +0000
> +++ src/app/webcontainer/chrome-cookie-store.cpp	2014-05-30 12:37:47 +0000
> @@ -0,0 +1,220 @@
> +/*
> + * Copyright 2014 Canonical Ltd.
> + *
> + * This file is part of webbrowser-app.
> + *
> + * webbrowser-app is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * webbrowser-app is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "chrome-cookie-store.h"
> +
> +#include <QDebug>
> +#include <QFileInfo>
> +#include <QNetworkCookie>
> +#include <QSqlError>
> +#include <QSqlQuery>
> +#include <QStandardPaths>
> +
> +static int connectionCounter = 0;
> +
> +static qint64 dateTimeToChrome(const QDateTime &time)
> +{
> +    /* Chrome uses Mon Jan 01 00:00:00 UTC 1601 as the epoch, hence the
> +     * magic number */
> +    return (time.toMSecsSinceEpoch() + 11644473600000) * 1000;
> +}
> +
> +static QDateTime dateTimeFromChrome(qint64 chromeTimeStamp)
> +{
> +    qint64 msecsSinceEpoch = chromeTimeStamp / 1000 - 11644473600000;
> +    return QDateTime::fromMSecsSinceEpoch(msecsSinceEpoch);
> +}
> +
> +ChromeCookieStore::ChromeCookieStore(QObject* parent):
> +    CookieStore(parent)
> +{
> +    QString connectionName =
> +        QString("chromeCookieStore-%1").arg(connectionCounter++);

The unique name is just to make the class do the right thing, in case it's reused in other projects: if it's instantiated multiple times, it should still work correctly.
Note that the connection name does not exit from process boundaries, so it's not a problem for two processes to have a connection with the same name.

> +    m_db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
> +}
> +
> +Cookies ChromeCookieStore::doGetCookies()
> +{
> +    Cookies cookies;
> +    m_db.setDatabaseName(getFullDbPathName());
> +
> +    if (Q_UNLIKELY(!m_db.open())) {
> +        qCritical() << "Could not open cookie database:" << getFullDbPathName()
> +            << m_db.lastError();
> +        return cookies;
> +    }
> +
> +    QSqlQuery q(m_db);
> +    q.exec("SELECT host_key, name, value, path, expires_utc, secure, httponly, has_expires FROM cookies;");
> +
> +    while (q.next()) {
> +        /* Build the cookie string from its parts */
> +        QNetworkCookie cookie(q.value(1).toString().toUtf8(),
> +                              q.value(2).toString().toUtf8());
> +        cookie.setSecure(q.value(5).toBool());
> +        cookie.setHttpOnly(q.value(6).toBool());
> +        if (q.value(7).toBool()) {
> +            QDateTime expires = dateTimeFromChrome(q.value(4).toULongLong());
> +            cookie.setExpirationDate(expires);
> +        }
> +        cookie.setDomain(q.value(0).toString());
> +        cookie.setPath(q.value(3).toString());
> +        cookies.append(cookie.toRawForm());
> +    }
> +
> +    m_db.close();
> +    return cookies;
> +}
> +
> +QDateTime ChromeCookieStore::lastUpdateTimeStamp() const
> +{
> +    QFileInfo dbFileInfo(getFullDbPathName());
> +    return dbFileInfo.lastModified();
> +}
> +
> +bool ChromeCookieStore::createDb()
> +{
> +    if (Q_UNLIKELY(!m_db.transaction())) return false;
> +
> +    QSqlQuery q(m_db);
> +    bool ok;
> +    ok = q.exec("CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY,"
> +                "value LONGVARCHAR)");
> +    if (Q_UNLIKELY(!ok)) {
> +        m_db.rollback();
> +        return false;
> +    }
> +
> +    ok = q.exec("CREATE TABLE cookies (creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,"
> +                "host_key TEXT NOT NULL,"
> +                "name TEXT NOT NULL,"
> +                "value TEXT NOT NULL,"
> +                "path TEXT NOT NULL,"
> +                "expires_utc INTEGER NOT NULL,"
> +                "secure INTEGER NOT NULL,"
> +                "httponly INTEGER NOT NULL,"
> +                "last_access_utc INTEGER NOT NULL,"
> +                "has_expires INTEGER NOT NULL DEFAULT 1,"
> +                "persistent INTEGER NOT NULL DEFAULT 1,"
> +                "priority INTEGER NOT NULL DEFAULT 1,"
> +                "encrypted_value BLOB DEFAULT '')");
> +    if (Q_UNLIKELY(!ok)) {
> +        m_db.rollback();
> +        return false;
> +    }
> +
> +    ok = q.exec("CREATE INDEX domain ON cookies(host_key)");
> +    if (Q_UNLIKELY(!ok)) {
> +        m_db.rollback();
> +        return false;
> +    }
> +
> +    ok = q.exec("INSERT INTO meta (key, value) VALUES ('version', '7')");
> +    if (Q_UNLIKELY(!ok)) {
> +        m_db.rollback();
> +        return false;
> +    }
> +
> +    ok = q.exec("INSERT INTO meta (key, value) VALUES ('last_compatible_version', '5')");
> +    if (Q_UNLIKELY(!ok)) {
> +        m_db.rollback();
> +        return false;
> +    }
> +
> +    return m_db.commit();
> +}
> +
> +bool ChromeCookieStore::doSetCookies(const Cookies& cookies)
> +{
> +    m_db.setDatabaseName(getFullDbPathName());
> +
> +    if (!m_db.open()) {
> +        qCritical() << "Could not open cookie database:" <<
> +            getFullDbPathName() << m_db.lastError().text();
> +        return false;
> +    }
> +
> +    QSqlQuery q(m_db);
> +    // Check whether the table already exists
> +    q.exec("SELECT name FROM sqlite_master WHERE type='table' AND name='cookies'");
> +    if (!q.next() && !createDb()) {
> +        qCritical() << "Could not create cookie database:" <<
> +            getFullDbPathName() << m_db.lastError().text();
> +        return false;
> +    }
> +
> +    QList<QNetworkCookie> parsedCookies;
> +
> +    Q_FOREACH(const QByteArray &cookie, cookies) {
> +        parsedCookies.append(QNetworkCookie::parseCookies(cookie));
> +    }
> +
> +    q.prepare("INSERT INTO cookies (creation_utc,"
> +              "host_key, name, value, path,"
> +              "expires_utc, secure, httponly, last_access_utc,"
> +              "has_expires, persistent, priority, encrypted_value) "
> +              "VALUES (:creation_utc,"
> +              ":host_key, :name, :value, :path,"
> +              ":expires_utc, :secure, :httponly, :last_access_utc,"
> +              ":has_expires, :persistent, :priority, :encrypted_value)");
> +    Q_FOREACH(const QNetworkCookie &cookie, parsedCookies) {
> +        q.bindValue(":creation_utc",
> +                    dateTimeToChrome(QDateTime::currentDateTimeUtc()));
> +        q.bindValue(":host_key", cookie.domain());
> +        q.bindValue(":name", cookie.name());
> +        q.bindValue(":value", cookie.value());
> +        q.bindValue(":path", cookie.path());
> +        q.bindValue(":expires_utc",
> +                    dateTimeToChrome(cookie.expirationDate().toUTC()));
> +        q.bindValue(":secure", cookie.isSecure());
> +        q.bindValue(":httponly", cookie.isHttpOnly());
> +        q.bindValue(":last_access_utc",
> +                    dateTimeToChrome(QDateTime::currentDateTimeUtc()));
> +        q.bindValue(":has_expires", cookie.expirationDate().isValid());
> +        q.bindValue(":persistent", true);
> +        q.bindValue(":priority", 1);
> +        q.bindValue(":encrypted_value", 1);
> +        q.exec();
> +    }
> +
> +    m_db.close();
> +
> +    return true;
> +}
> +
> +QString ChromeCookieStore::getFullDbPathName() const
> +{
> +    return dbPath().startsWith('/') ? dbPath() :
> +        QStandardPaths::standardLocations(QStandardPaths::HomeLocation)[0] + "/" + dbPath();
> +}
> +
> +void ChromeCookieStore::setDbPath(const QString &path)
> +{
> +    // If path is a URL, strip the initial "file://"
> +    QString normalizedPath = path.startsWith("file://") ? path.mid(7) : path;
> +
> +    if (normalizedPath != m_dbPath) {
> +        m_dbPath = normalizedPath;
> +        Q_EMIT dbPathChanged();
> +    }
> +}
> +
> +QString ChromeCookieStore::dbPath () const
> +{
> +    return m_dbPath;
> +}
> 
> === added file 'src/app/webcontainer/chrome-cookie-store.h'
> --- src/app/webcontainer/chrome-cookie-store.h	1970-01-01 00:00:00 +0000
> +++ src/app/webcontainer/chrome-cookie-store.h	2014-05-30 12:37:47 +0000
> @@ -0,0 +1,54 @@
> +/*
> + * Copyright 2014 Canonical Ltd.
> + *
> + * This file is part of webbrowser-app.
> + *
> + * webbrowser-app is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * webbrowser-app is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef CHROME_COOKIE_STORE_H
> +#define CHROME_COOKIE_STORE_H
> +
> +#include "cookie-store.h"
> +
> +#include <QSqlDatabase>
> +
> +class ChromeCookieStore : public CookieStore
> +{
> +    Q_OBJECT
> +    Q_PROPERTY(QString dbPath READ dbPath WRITE setDbPath NOTIFY dbPathChanged)
> +
> +public:
> +    ChromeCookieStore(QObject* parent = 0);
> +
> +    void setDbPath(const QString& path);
> +    QString dbPath() const;
> +
> +    QDateTime lastUpdateTimeStamp() const Q_DECL_OVERRIDE;
> +
> +Q_SIGNALS:
> +    void dbPathChanged();
> +
> +private:
> +    virtual Cookies doGetCookies() Q_DECL_OVERRIDE;
> +    virtual bool doSetCookies(const Cookies& cookies) Q_DECL_OVERRIDE;
> +
> +    QString getFullDbPathName() const;
> +    bool createDb();
> +
> +private:
> +    QString m_dbPath;
> +    QSqlDatabase m_db;
> +};
> +
> +#endif // CHROME_COOKIE_STORE_H
> 
> === renamed file 'src/app/webcontainer/cookiestore.cpp' => 'src/app/webcontainer/cookie-store.cpp'
> --- src/app/webcontainer/cookiestore.cpp	2014-01-27 22:58:55 +0000
> +++ src/app/webcontainer/cookie-store.cpp	2014-05-30 12:37:47 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright 2013 Canonical Ltd.
> + * Copyright 2014 Canonical Ltd.
>   *
>   * This file is part of webbrowser-app.
>   *
> @@ -18,10 +18,10 @@
>  
>  #include <QDebug>
>  
> -#include "cookiestore.h"
> +#include "cookie-store.h"
>  
> -CookieStore::CookieStore(QObject *parent)
> -    : QObject(parent)
> +CookieStore::CookieStore(QObject* parent):
> +    QObject(parent)
>  {
>      qRegisterMetaType<Cookies>("Cookies");
>  }
> @@ -31,19 +31,26 @@
>      return doGetCookies();
>  }
>  
> -void CookieStore::setCookies(Cookies cookies)
> +bool CookieStore::setCookies(const Cookies& cookies)
>  {
> -    doSetCookies(cookies);
> +    if (doSetCookies(cookies)) {
> +        Q_EMIT cookiesChanged();
> +        return true;
> +    } else {
> +        return false;
> +    }
>  }
>  
>  Cookies CookieStore::doGetCookies()
>  {
> +    Q_UNIMPLEMENTED();
>      return Cookies();
>  }
>  
> -void CookieStore::doSetCookies(Cookies cookies)
> +bool CookieStore::doSetCookies(const Cookies& cookies)
>  {
>      Q_UNUSED(cookies);
> +    Q_UNIMPLEMENTED();
>  }
>  
>  QDateTime CookieStore::lastUpdateTimeStamp() const
> @@ -51,33 +58,32 @@
>      return _lastUpdateTimeStamp;
>  }
>  
> -void CookieStore::updateLastUpdateTimestamp(const QDateTime & timestamp)
> +void CookieStore::updateLastUpdateTimestamp(const QDateTime& timestamp)
>  {
>      _lastUpdateTimeStamp = timestamp;
>  }
>  
> -void CookieStore::moveFrom(CookieStore *store)
> +void CookieStore::moveFrom(CookieStore* store)
>  {
> -    if (! store)
> +    if (Q_UNLIKELY(!store))
>          return;
>  
> -    Cookies cookies =
> -            store->cookies();
> -
> -    QDateTime lastRemoteCookieUpdate =
> -            store->lastUpdateTimeStamp();
> -
> -    QDateTime lastLocalCookieUpdate =
> -            lastUpdateTimeStamp();
> -
> -    if (lastRemoteCookieUpdate.isValid()
> -            && lastLocalCookieUpdate.isValid()
> -            && (lastRemoteCookieUpdate < lastLocalCookieUpdate))
> +    Cookies cookies = store->cookies();
> +
> +    QDateTime lastRemoteCookieUpdate = store->lastUpdateTimeStamp();
> +    QDateTime lastLocalCookieUpdate = lastUpdateTimeStamp();
> +
> +    if (lastRemoteCookieUpdate.isValid() &&
> +        lastLocalCookieUpdate.isValid() &&
> +        (lastRemoteCookieUpdate < lastLocalCookieUpdate))
>      {
>          Q_EMIT moved(false);
>          return;
>      }
>  
> -    setCookies(cookies);
> +    if (setCookies(cookies)) {
> +        Q_EMIT moved(true);
> +    } else {
> +        Q_EMIT moved(false);
> +    }
>  }
> -
> 
> === renamed file 'src/app/webcontainer/cookiestore.h' => 'src/app/webcontainer/cookie-store.h'
> --- src/app/webcontainer/cookiestore.h	2014-01-27 22:58:55 +0000
> +++ src/app/webcontainer/cookie-store.h	2014-05-30 12:37:47 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright 2013 Canonical Ltd.
> + * Copyright 2014 Canonical Ltd.
>   *
>   * This file is part of webbrowser-app.
>   *
> @@ -16,62 +16,50 @@
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> -#ifndef __COOKIESTORE_H__
> -#define __COOKIESTORE_H__
> +#ifndef __COOKIE_STORE_H__
> +#define __COOKIE_STORE_H__
>  
> +#include <QByteArray>
> +#include <QDateTime>
> +#include <QList>
>  #include <QObject>
> -#include <QtCore/QList>
> -#include <QtCore/QString>
> -#include <QDateTime>
> -#include <QString>
> -#include <QMap>
>  
> -typedef QMap<QString, QString> Cookies;
> +typedef QList<QByteArray> Cookies;
>  Q_DECLARE_METATYPE(Cookies);
>  
>  
>  class CookieStore : public QObject
>  {
>      Q_OBJECT
> -    Q_PROPERTY(Cookies cookies READ \
> -               cookies WRITE setCookies \
> +    Q_PROPERTY(Cookies cookies READ cookies WRITE setCookies \
>                 NOTIFY cookiesChanged)
> -    Q_PROPERTY(QDateTime lastUpdateTimeStamp \
> -               READ lastUpdateTimeStamp \
> +    Q_PROPERTY(QDateTime lastUpdateTimeStamp READ lastUpdateTimeStamp \
>                 NOTIFY lastUpdateTimeStampChanged)
>  
>  public:
> -
> -    CookieStore(QObject *parent = 0);
> -
> +    CookieStore(QObject* parent = 0);
> +
> +    bool setCookies(const Cookies& cookies);
>      Cookies cookies();
> -    void setCookies(Cookies);
>  
>      virtual QDateTime lastUpdateTimeStamp() const;
>  
> -    Q_INVOKABLE void moveFrom (CookieStore * store);
> +    Q_INVOKABLE void moveFrom(CookieStore* store);
>  
>  Q_SIGNALS:
> -
>      void moved(bool);
>      void cookiesChanged();
>      void lastUpdateTimeStampChanged();
>  
>  protected:
> -
> -    void updateLastUpdateTimestamp(const QDateTime & timestamp);
> -
> +    void updateLastUpdateTimestamp(const QDateTime& timestamp);
>  
>  private:
> -
>      virtual Cookies doGetCookies();
> -    virtual void doSetCookies(Cookies);
> +    virtual bool doSetCookies(const Cookies& Cookies);
>  
>  private:
> -
>      QDateTime _lastUpdateTimeStamp;
>  };
>  
> -
> -#endif // __COOKIESTORE_H__
> -
> +#endif // __COOKIE_STORE_H__
> 
> === renamed file 'src/app/webcontainer/onlineaccountscookiestore.cpp' => 'src/app/webcontainer/online-accounts-cookie-store.cpp'
> --- src/app/webcontainer/onlineaccountscookiestore.cpp	2014-01-27 22:58:55 +0000
> +++ src/app/webcontainer/online-accounts-cookie-store.cpp	2014-05-30 12:37:47 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright 2013 Canonical Ltd.
> + * Copyright 2013-2014 Canonical Ltd.
>   *
>   * This file is part of webbrowser-app.
>   *
> @@ -16,7 +16,7 @@
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> -#include "onlineaccountscookiestore.h"
> +#include "online-accounts-cookie-store.h"
>  
>  #include <QList>
>  #include <QVariant>
> @@ -44,15 +44,12 @@
>  #   define ONLINE_ACCOUNTS_COOKIE_STORE_METHOD "cookiesForIdentity"
>  #endif
>  
> -class OnlineAccountsCookieStorePrivate : public QObject
> +class OnlineAccountsCookieStorePrivate
>  {
> -    Q_OBJECT
> -
>  public:
> -    OnlineAccountsCookieStorePrivate (QObject * parent = 0)
> -        : QObject(parent),
> -          _id (0),
> -          m_connection (QDBusConnection::sessionBus())
> +    OnlineAccountsCookieStorePrivate():
> +        _id(0),
> +        m_connection(QDBusConnection::sessionBus())
>      {}
>  
>      quint32 _id;
> @@ -135,9 +132,8 @@
>      return qdbus_cast<Cookies>(arguments.front());
>  }
>  
> -void OnlineAccountsCookieStore::doSetCookies(Cookies cookies)
> +bool OnlineAccountsCookieStore::doSetCookies(const Cookies& cookies)
>  {
>      Q_UNUSED(cookies);
> +    return false;
>  }
> -
> -#include "onlineaccountscookiestore.moc"
> 
> === renamed file 'src/app/webcontainer/onlineaccountscookiestore.h' => 'src/app/webcontainer/online-accounts-cookie-store.h'
> --- src/app/webcontainer/onlineaccountscookiestore.h	2014-01-27 22:58:55 +0000
> +++ src/app/webcontainer/online-accounts-cookie-store.h	2014-05-30 12:37:47 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright 2013 Canonical Ltd.
> + * Copyright 2013-2014 Canonical Ltd.
>   *
>   * This file is part of webbrowser-app.
>   *
> @@ -16,10 +16,10 @@
>   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
>   */
>  
> -#ifndef ONLINEACCOUNTSCOOKIESTORE_H
> -#define ONLINEACCOUNTSCOOKIESTORE_H
> +#ifndef ONLINE_ACCOUNTS_COOKIE_STORE_H
> +#define ONLINE_ACCOUNTS_COOKIE_STORE_H
>  
> -#include "cookiestore.h"
> +#include "cookie-store.h"
>  
>  class OnlineAccountsCookieStorePrivate;
>  
> @@ -45,7 +45,7 @@
>  private:
>  
>      virtual Cookies doGetCookies() Q_DECL_OVERRIDE;
> -    virtual void doSetCookies(Cookies) Q_DECL_OVERRIDE;
> +    virtual bool doSetCookies(const Cookies& cookies) Q_DECL_OVERRIDE;
>  
>  
>  private:
> @@ -54,4 +54,4 @@
>      Q_DECLARE_PRIVATE(OnlineAccountsCookieStore)
>  };
>  
> -#endif // ONLINEACCOUNTSCOOKIESTORE_H
> +#endif // ONLINE_ACCOUNTS_COOKIE_STORE_H
> 
> === removed file 'src/app/webcontainer/sqlitecookiestore.cpp'
> --- src/app/webcontainer/sqlitecookiestore.cpp	2014-02-07 16:44:50 +0000
> +++ src/app/webcontainer/sqlitecookiestore.cpp	1970-01-01 00:00:00 +0000
> @@ -1,99 +0,0 @@
> -/*
> - * Copyright 2013 Canonical Ltd.
> - *
> - * This file is part of webbrowser-app.
> - *
> - * webbrowser-app is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; version 3.
> - *
> - * webbrowser-app is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#include "sqlitecookiestore.h"
> -
> -#include <QSqlDatabase>
> -#include <QSqlError>
> -#include <QSqlQuery>
> -#include <QFileInfo>
> -#include <QStandardPaths>
> -#include <QDebug>
> -
> -
> -SqliteCookieStore::SqliteCookieStore(QObject *parent)
> -    : CookieStore(parent)
> -{}
> -
> -Cookies SqliteCookieStore::doGetCookies()
> -{
> -    return Cookies();
> -}
> -
> -QDateTime SqliteCookieStore::lastUpdateTimeStamp() const
> -{
> -    QFileInfo dbFileInfo(getFullDbPathName ());
> -    return dbFileInfo.lastModified();
> -}
> -
> -void SqliteCookieStore::doSetCookies(Cookies cookies)
> -{
> -    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
> -    db.setDatabaseName (getFullDbPathName ());
> -
> -    if ( ! db.open())
> -    {
> -        qCritical() << "Could not open cookie database: " << getFullDbPathName() << db.lastError();
> -        Q_EMIT moved(false);
> -        return;
> -    }
> -
> -    QSqlQuery q(db);
> -    q.exec("CREATE TABLE IF NOT EXISTS cookies "
> -           "(cookieId VARCHAR PRIMARY KEY, cookie BLOB)");
> -    q.exec ("DELETE FROM cookies;");
> -
> -    q.prepare("INSERT INTO cookies (cookieId, cookie) "
> -              "VALUES (:cookieId, :cookie)");
> -
> -    for (Cookies::const_iterator it = cookies.constBegin();
> -         it != cookies.constEnd();
> -         ++it)
> -    {
> -        q.bindValue(":cookieId", it.key());
> -        q.bindValue(":cookie", it.value());
> -
> -        if ( ! q.exec())
> -        {
> -            qWarning() << "Couldn't insert cookie into DB"
> -                       << it.key();
> -       }
> -    }
> -
> -    Q_EMIT moved(true);
> -}
> -
> -QString SqliteCookieStore::getFullDbPathName() const
> -{
> -    return QStandardPaths::standardLocations(QStandardPaths::HomeLocation)[0] + "/" + dbPath();
> -}
> -
> -void SqliteCookieStore::setDbPath(const QString &path)
> -{
> -    if (path != m_dbPath)
> -    {
> -        m_dbPath = path;
> -        Q_EMIT dbPathChanged();
> -    }
> -}
> -
> -QString SqliteCookieStore::dbPath () const
> -{
> -    return m_dbPath;
> -}
> -
> 
> === removed file 'src/app/webcontainer/sqlitecookiestore.h'
> --- src/app/webcontainer/sqlitecookiestore.h	2014-01-27 22:58:55 +0000
> +++ src/app/webcontainer/sqlitecookiestore.h	1970-01-01 00:00:00 +0000
> @@ -1,58 +0,0 @@
> -/*
> - * Copyright 2013 Canonical Ltd.
> - *
> - * This file is part of webbrowser-app.
> - *
> - * webbrowser-app is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published by
> - * the Free Software Foundation; version 3.
> - *
> - * webbrowser-app is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public License
> - * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> - */
> -
> -#ifndef SQLITECOOKIESTORE_H
> -#define SQLITECOOKIESTORE_H
> -
> -#include "cookiestore.h"
> -#include <QString>
> -
> -
> -class SqliteCookieStore : public CookieStore
> -{
> -    Q_OBJECT
> -    Q_PROPERTY(QString dbPath READ dbPath WRITE setDbPath NOTIFY dbPathChanged)
> -
> -
> -public:
> -    SqliteCookieStore(QObject *parent = 0);
> -
> -    void setDbPath (const QString & path);
> -    QString dbPath () const;
> -
> -    QDateTime lastUpdateTimeStamp() const Q_DECL_OVERRIDE;
> -
> -
> -Q_SIGNALS:
> -
> -    void dbPathChanged();
> -
> -
> -private:
> -
> -    virtual Cookies doGetCookies() Q_DECL_OVERRIDE;
> -    virtual void doSetCookies(Cookies) Q_DECL_OVERRIDE;
> -
> -    QString getFullDbPathName() const;
> -
> -
> -private:
> -    QString m_dbPath;
> -};
> -
> -#endif // SQLITECOOKIESTORE_H
> 
> === modified file 'src/app/webcontainer/webapp-container.cpp'
> --- src/app/webcontainer/webapp-container.cpp	2014-05-08 16:51:08 +0000
> +++ src/app/webcontainer/webapp-container.cpp	2014-05-30 12:37:47 +0000
> @@ -19,8 +19,11 @@
>  #include "config.h"
>  #include "webapp-container.h"
>  
> +#include "chrome-cookie-store.h"
> +#include "online-accounts-cookie-store.h"
>  #include "session-utils.h"
>  #include "url-pattern-utils.h"
> +#include "webkit-cookie-store.h"
>  
>  // Qt
>  #include <QtCore/QCoreApplication>
> @@ -30,14 +33,17 @@
>  #include <QtCore/QtGlobal>
>  #include <QtCore/QRegularExpression>
>  #include <QtCore/QTextStream>
> -#include <QtQuick/QQuickWindow>
>  #include <QtQml/QQmlComponent>
>  #include <QtQml/QQmlContext>
>  #include <QtQml/QQmlEngine>
> +#include <QtQml>
> +#include <QtQuick/QQuickWindow>
>  
>  #include <QStandardPaths>
>  #include <QSettings>
>  
> +static const char privateModuleUri[] = "webcontainer.private";
> +
>  namespace
>  {
>  
> @@ -103,6 +109,7 @@
>          m_window->setProperty("webappName", m_webappName);
>          m_window->setProperty("backForwardButtonsVisible", m_backForwardButtonsVisible);
>          m_window->setProperty("addressBarVisible", m_addressBarVisible);
> +        m_window->setProperty("accountProvider", m_accountProvider);
>  
>          qDebug() << "Using" << (m_withOxide ? "Oxide" : "QtWebkit") << "as the web engine backend";
>          m_window->setProperty("oxide", m_withOxide);
> @@ -134,6 +141,18 @@
>      }
>  }
>  
> +void WebappContainer::qmlEngineCreated(QQmlEngine* engine)
> +{
> +    if (engine) {
> +        qmlRegisterType<ChromeCookieStore>(privateModuleUri, 0, 1,
> +                                           "ChromeCookieStore");
> +        qmlRegisterType<WebkitCookieStore>(privateModuleUri, 0, 1,
> +                                           "WebkitCookieStore");
> +        qmlRegisterType<OnlineAccountsCookieStore>(privateModuleUri, 0, 1,
> +                                                   "OnlineAccountsCookieStore");
> +    }
> +}
> +
>  void WebappContainer::printUsage() const
>  {
>      QTextStream out(stdout);
> @@ -147,6 +166,7 @@
>         " [--webapp=name]"
>         " [--webappModelSearchPath=PATH]"
>         " [--webappUrlPatterns=URL_PATTERNS]"
> +       " [--accountProvider=PROVIDER_NAME]"
>         " [--enable-back-forward]"
>         " [--enable-addressbar]"
>         " [--store-session-cookies]"
> @@ -162,6 +182,7 @@
>      out << "  --webapp=name                       try to match the webapp by name with an installed integration script" << endl;
>      out << "  --webappModelSearchPath=PATH        alter the search path for installed webapps and set it to PATH. PATH can be an absolute or path relative to CWD" << endl;
>      out << "  --webappUrlPatterns=URL_PATTERNS    list of comma-separated url patterns (wildcard based) that the webapp is allowed to navigate to" << endl;
> +    out << "  --accountProvider=PROVIDER_NAME     Online account provider for the application if the application is to reuse a local account." << endl;
>      out << "  --store-session-cookies             store session cookies on disk" << endl;
>      out << "Chrome options (if none specified, no chrome is shown by default):" << endl;
>      out << "  --enable-back-forward               enable the display of the back and forward buttons" << endl;
> @@ -190,6 +211,8 @@
>                  QStringList includePatterns = tail.split(URL_PATTERN_SEPARATOR);
>                  m_webappUrlPatterns = UrlPatternUtils::filterAndTransformUrlPatterns(includePatterns);
>              }
> +        } else if (argument.startsWith("--accountProvider=")) {
> +            m_accountProvider = argument.split("--accountProvider=")[1];
>          } else if (argument == "--store-session-cookies") {
>              m_storeSessionCookies = true;
>          } else if (argument == "--enable-back-forward") {
> 
> === modified file 'src/app/webcontainer/webapp-container.h'
> --- src/app/webcontainer/webapp-container.h	2014-05-08 16:51:08 +0000
> +++ src/app/webcontainer/webapp-container.h	2014-05-30 12:37:47 +0000
> @@ -34,6 +34,9 @@
>  
>      bool initialize();
>  
> +protected:
> +    void qmlEngineCreated(QQmlEngine *);
> +
>  private:
>      virtual void printUsage() const;
>      void parseCommandLine();
> @@ -44,6 +47,7 @@
>      QString m_webappName;
>      QString m_webappModelSearchPath;
>      QStringList m_webappUrlPatterns;
> +    QString m_accountProvider;
>      bool m_withOxide;
>      bool m_storeSessionCookies;
>      bool m_backForwardButtonsVisible;
> 
> === modified file 'src/app/webcontainer/webapp-container.qml'
> --- src/app/webcontainer/webapp-container.qml	2014-04-22 15:35:16 +0000
> +++ src/app/webcontainer/webapp-container.qml	2014-05-30 12:37:47 +0000
> @@ -1,5 +1,5 @@
>  /*
> - * Copyright 2013 Canonical Ltd.
> + * Copyright 2013-2014 Canonical Ltd.
>   *
>   * This file is part of webbrowser-app.
>   *
> @@ -19,22 +19,27 @@
>  import QtQuick 2.0
>  import QtQuick.Window 2.0
>  import Ubuntu.Components 0.1
> +import Ubuntu.Components.Extras.Browser 0.2
> +import webcontainer.private 0.1
>  
>  Window {
> +    id: root
>      objectName: "webappContainer"
>  
> -    property alias developerExtrasEnabled: browser.developerExtrasEnabled
> -
> -    property alias backForwardButtonsVisible: browser.backForwardButtonsVisible
> -    property alias addressBarVisible: browser.addressBarVisible
> -
> -    property alias url: browser.url
> -    property alias webappName: browser.webappName
> -    property alias webappModelSearchPath: browser.webappModelSearchPath
> -    property alias webappUrlPatterns: browser.webappUrlPatterns
> -    property alias oxide: browser.oxide
> -
> -    contentOrientation: browser.screenOrientation
> +    property bool developerExtrasEnabled: false
> +
> +    property bool backForwardButtonsVisible: true
> +    property bool addressBarVisible: true
> +
> +    property string url: ""
> +    property string webappName: ""
> +    property string webappModelSearchPath: ""
> +    property var webappUrlPatterns
> +    property bool oxide: false
> +    property string accountProvider: ""
> +    property var __webappCookieStore: null
> +
> +    contentOrientation: Screen.orientation
>  
>      width: 800
>      height: 600
> @@ -42,24 +47,107 @@
>      title: {
>          if (typeof(webappName) === 'string' && webappName.length !== 0) {
>              return webappName
> -        } else if (browser.title) {
> +        } else if (webappPageComponentLoader.item &&
> +                   webappPageComponentLoader.item.title) {
>              // TRANSLATORS: %1 refers to the current page’s title
> -            return i18n.tr("%1 - Ubuntu Web Browser").arg(browser.title)
> +            return i18n.tr("%1 - Ubuntu Web Browser").arg(webappPageComponentLoader.item.title)
>          } else {
>              return i18n.tr("Ubuntu Web Browser")
>          }
>      }
>  
> -    WebApp {
> -        id: browser
> -
> -        property int screenOrientation: Screen.orientation
> -
> -        chromeless: !backForwardButtonsVisible && !addressBarVisible
> -        webbrowserWindow: webbrowserWindowProxy
> -
> -        anchors.fill: parent
> -
> -        Component.onCompleted: i18n.domain = "webbrowser-app"
> +    Loader {
> +        id: webappPageComponentLoader
> +        anchors.fill: parent
> +    }
> +
> +    Component {
> +        id: webappPageComponent
> +
> +        WebApp {
> +            id: browser
> +            addressBarVisible: root.addressBarVisible
> +            backForwardButtonsVisible: root.backForwardButtonsVisible
> +            developerExtrasEnabled: root.developerExtrasEnabled
> +            oxide: root.oxide
> +            url: root.url
> +            webappModelSearchPath: root.webappModelSearchPath
> +            webappName: root.webappName
> +            webappUrlPatterns: root.webappUrlPatterns
> +
> +            anchors.fill: parent
> +
> +            chromeless: !backForwardButtonsVisible && !addressBarVisible
> +            webbrowserWindow: webbrowserWindowProxy
> +
> +            Component.onCompleted: i18n.domain = "webbrowser-app"
> +        }
> +    }
> +
> +    Loader {
> +        id: accountsPageComponentLoader
> +        anchors.fill: parent
> +        onStatusChanged: {
> +            if (status == Loader.Error) {
> +                // Happens on the desktop, if Ubuntu.OnlineAccounts.Client
> +                // can't be imported
> +                loadWebAppView()
> +            } else if (status == Loader.Ready) {
> +                item.visible = true
> +            }
> +        }
> +    }
> +
> +    Connections {
> +        target: accountsPageComponentLoader.item
> +        onDone: loadWebAppView()
> +    }
> +
> +    Component {
> +        id: webkitCookieStoreComponent
> +        WebkitCookieStore {
> +            dbPath: dataLocation + "/.QtWebKit/cookies.db"
> +        }
> +    }
> +
> +    Component {
> +        id: chromeCookieStoreComponent
> +        ChromeCookieStore {
> +            dbPath: dataLocation + "/cookies.sqlite"
> +        }
> +    }
> +
> +    Component.onCompleted: updateCurrentView()
> +
> +    onAccountProviderChanged: updateCurrentView();
> +
> +    function updateCurrentView() {
> +        // check if we are to display the login view
> +        // or directly switch to the webapp view
> +        if (accountProvider.length !== 0) {
> +            loadLoginView();
> +        } else {
> +            loadWebAppView();
> +        }
> +    }
> +
> +    function loadLoginView() {
> +        if (!__webappCookieStore) {
> +            var cookieStoreComponent =
> +                oxide ? chromeCookieStoreComponent : webkitCookieStoreComponent
> +            __webappCookieStore = cookieStoreComponent.createObject(this)
> +        }
> +        accountsPageComponentLoader.setSource("AccountsPage.qml", {
> +            "accountProvider": accountProvider,
> +            "applicationName": Qt.application.name,
> +            "webappCookieStore": __webappCookieStore
> +        })
> +    }
> +
> +    function loadWebAppView() {
> +        webappPageComponentLoader.sourceComponent = webappPageComponent;
> +        if (accountsPageComponentLoader.item)
> +            accountsPageComponentLoader.item.visible = false;
> +        webappPageComponentLoader.item.visible = true;
>      }
>  }
> 
> === added file 'src/app/webcontainer/webkit-cookie-store.cpp'
> --- src/app/webcontainer/webkit-cookie-store.cpp	1970-01-01 00:00:00 +0000
> +++ src/app/webcontainer/webkit-cookie-store.cpp	2014-05-30 12:37:47 +0000
> @@ -0,0 +1,119 @@
> +/*
> + * Copyright 2014 Canonical Ltd.
> + *
> + * This file is part of webbrowser-app.
> + *
> + * webbrowser-app is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * webbrowser-app is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "webkit-cookie-store.h"
> +
> +#include <QDebug>
> +#include <QFileInfo>
> +#include <QNetworkCookie>
> +#include <QSqlError>
> +#include <QSqlQuery>
> +#include <QStandardPaths>
> +
> +static int connectionCounter = 0;
> +
> +WebkitCookieStore::WebkitCookieStore(QObject* parent):
> +    CookieStore(parent)
> +{
> +    QString connectionName =
> +        QString("webkitCookieStore-%1").arg(connectionCounter++);
> +    m_db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
> +}
> +
> +Cookies WebkitCookieStore::doGetCookies()
> +{
> +    Cookies cookies;
> +    m_db.setDatabaseName(getFullDbPathName());
> +
> +    if (!m_db.open()) {
> +        qCritical() << "Could not open cookie database:" << getFullDbPathName() << m_db.lastError();
> +        return cookies;
> +    }
> +
> +    QSqlQuery q(m_db);
> +    q.exec("SELECT cookie FROM cookies;");
> +
> +    while (q.next()) {
> +        cookies.append(q.value(0).toString().toUtf8());
> +    }
> +
> +    m_db.close();
> +    return cookies;
> +}
> +
> +QDateTime WebkitCookieStore::lastUpdateTimeStamp() const
> +{
> +    QFileInfo dbFileInfo(getFullDbPathName());
> +    return dbFileInfo.lastModified();
> +}
> +
> +bool WebkitCookieStore::doSetCookies(const Cookies& cookies)
> +{
> +    m_db.setDatabaseName(getFullDbPathName());
> +
> +    if (!m_db.open()) {
> +        qCritical() << "Could not open cookie database:" << getFullDbPathName() << m_db.lastError();
> +        return false;
> +    }
> +
> +    QSqlQuery q(m_db);
> +    q.exec("CREATE TABLE IF NOT EXISTS cookies "
> +           "(cookieId VARCHAR PRIMARY KEY, cookie BLOB)");
> +    q.exec ("DELETE FROM cookies;");
> +
> +    q.prepare("INSERT INTO cookies (cookieId, cookie) "
> +              "VALUES (:cookieId, :cookie)");
> +
> +    Q_FOREACH(const QByteArray& cookie, cookies) {
> +        /* The unique key is the hostname + the cookie name */
> +        QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie);
> +        if (parsed.isEmpty()) continue;
> +
> +        const QNetworkCookie& c = parsed.first();
> +        q.bindValue(":cookieId", c.domain() + c.name());
> +        q.bindValue(":cookie", cookie);
> +
> +        if (!q.exec()) {
> +            qWarning() << "Couldn't insert cookie into DB" << cookie;
> +        }
> +    }
> +
> +    m_db.close();
> +
> +    return true;
> +}
> +
> +QString WebkitCookieStore::getFullDbPathName() const
> +{
> +    return dbPath().startsWith('/') ? dbPath() :
> +        QStandardPaths::standardLocations(QStandardPaths::HomeLocation)[0] + "/" + dbPath();
> +}
> +
> +void WebkitCookieStore::setDbPath(const QString& path)
> +{
> +    if (path != m_dbPath) {
> +        m_dbPath = path;
> +        Q_EMIT dbPathChanged();
> +    }
> +}
> +
> +QString WebkitCookieStore::dbPath() const
> +{
> +    return m_dbPath;
> +}
> +
> 
> === added file 'src/app/webcontainer/webkit-cookie-store.h'
> --- src/app/webcontainer/webkit-cookie-store.h	1970-01-01 00:00:00 +0000
> +++ src/app/webcontainer/webkit-cookie-store.h	2014-05-30 12:37:47 +0000
> @@ -0,0 +1,53 @@
> +/*
> + * Copyright 2014 Canonical Ltd.
> + *
> + * This file is part of webbrowser-app.
> + *
> + * webbrowser-app is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * webbrowser-app is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef WEBKIT_COOKIE_STORE_H
> +#define WEBKIT_COOKIE_STORE_H
> +
> +#include "cookie-store.h"
> +
> +#include <QSqlDatabase>
> +
> +class WebkitCookieStore : public CookieStore
> +{
> +    Q_OBJECT
> +    Q_PROPERTY(QString dbPath READ dbPath WRITE setDbPath NOTIFY dbPathChanged)
> +
> +public:
> +    WebkitCookieStore(QObject* parent = 0);
> +
> +    void setDbPath(const QString& path);
> +    QString dbPath() const;
> +
> +    QDateTime lastUpdateTimeStamp() const Q_DECL_OVERRIDE;
> +
> +Q_SIGNALS:
> +    void dbPathChanged();
> +
> +private:
> +    virtual Cookies doGetCookies() Q_DECL_OVERRIDE;
> +    virtual bool doSetCookies(const Cookies& cookies) Q_DECL_OVERRIDE;
> +
> +    QString getFullDbPathName() const;
> +
> +private:
> +    QString m_dbPath;
> +    QSqlDatabase m_db;
> +};
> +
> +#endif // WEBKIT_COOKIE_STORE_H
> 
> === modified file 'tests/unittests/CMakeLists.txt'
> --- tests/unittests/CMakeLists.txt	2014-04-03 12:54:12 +0000
> +++ tests/unittests/CMakeLists.txt	2014-05-30 12:37:47 +0000
> @@ -10,3 +10,4 @@
>  add_subdirectory(tabs-model)
>  add_subdirectory(bookmarks-model)
>  add_subdirectory(container-url-patterns)
> +add_subdirectory(cookie-store)
> 
> === added directory 'tests/unittests/cookie-store'
> === added file 'tests/unittests/cookie-store/CMakeLists.txt'
> --- tests/unittests/cookie-store/CMakeLists.txt	1970-01-01 00:00:00 +0000
> +++ tests/unittests/cookie-store/CMakeLists.txt	2014-05-30 12:37:47 +0000
> @@ -0,0 +1,11 @@
> +set(TEST tst_CookieStoreTest)
> +set(SOURCES
> +    ${webapp-container_SOURCE_DIR}/chrome-cookie-store.cpp
> +    ${webapp-container_SOURCE_DIR}/cookie-store.cpp
> +    ${webapp-container_SOURCE_DIR}/webkit-cookie-store.cpp
> +    tst_CookieStore.cpp
> +)
> +add_executable(${TEST} ${SOURCES})
> +include_directories(${webapp-container_SOURCE_DIR})
> +qt5_use_modules(${TEST} Core Network Sql Test)
> +add_test(${TEST} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} -xunitxml -o ${TEST}.xml)
> 
> === added file 'tests/unittests/cookie-store/tst_CookieStore.cpp'
> --- tests/unittests/cookie-store/tst_CookieStore.cpp	1970-01-01 00:00:00 +0000
> +++ tests/unittests/cookie-store/tst_CookieStore.cpp	2014-05-30 12:37:47 +0000
> @@ -0,0 +1,189 @@
> +/*
> + * Copyright 2014 Canonical Ltd.
> + *
> + * This file is part of webbrowser-app.
> + *
> + * webbrowser-app is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 3.
> + *
> + * webbrowser-app is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +// Qt
> +#include <QtCore/QDir>
> +#include <QtCore/QSet>
> +#include <QtCore/QTemporaryDir>
> +#include <QtNetwork/QNetworkCookie>
> +#include <QtTest/QSignalSpy>
> +#include <QtTest/QtTest>
> +
> +// local
> +#include "chrome-cookie-store.h"
> +#include "webkit-cookie-store.h"
> +
> +uint qHash(const QNetworkCookie &cookie, uint seed)
> +{
> +    return qHash(cookie.toRawForm(), seed);
> +}
> +
> +class CookieStoreTest : public QObject
> +{
> +    Q_OBJECT
> +
> +private Q_SLOTS:
> +    void testChromeProperties();
> +    void testWebkitProperties();
> +
> +    void testChromeReadWrite_data() { setupCookieData(); }
> +    void testWebkitReadWrite_data() { setupCookieData(); }
> +    void testChromeReadWrite();
> +    void testWebkitReadWrite();
> +
> +    void testMoving_data() { setupCookieData(); }
> +    void testMoving();
> +
> +private:
> +    void setupCookieData();
> +    QSet<QNetworkCookie> parseCookies(const Cookies &rawCookies);
> +};
> +
> +QSet<QNetworkCookie>
> +CookieStoreTest::parseCookies(const Cookies &rawCookies)
> +{
> +    QList<QNetworkCookie> cookies;
> +    Q_FOREACH(const QByteArray &rawCookie, rawCookies) {
> +        cookies.append(QNetworkCookie::parseCookies(rawCookie));
> +    }
> +    return cookies.toSet();
> +}
> +
> +void CookieStoreTest::testChromeProperties()
> +{
> +    QTemporaryDir tmpDir;
> +    QVERIFY(tmpDir.isValid());
> +    QTemporaryDir tmpDir2;
> +    QVERIFY(tmpDir2.isValid());
> +
> +    ChromeCookieStore store;
> +    QSignalSpy dbPathChanged(&store, SIGNAL(dbPathChanged()));
> +
> +    store.setProperty("dbPath", tmpDir.path());
> +    QCOMPARE(dbPathChanged.count(), 1);
> +    QCOMPARE(store.property("dbPath").toString(), tmpDir.path());
> +    dbPathChanged.clear();
> +
> +    store.setProperty("dbPath", "file://" + tmpDir2.path());
> +    QCOMPARE(dbPathChanged.count(), 1);
> +    QCOMPARE(store.property("dbPath").toString(), tmpDir2.path());
> +
> +    QVERIFY(store.property("cookies").value<Cookies>().isEmpty());
> +}
> +
> +void CookieStoreTest::testWebkitProperties()
> +{
> +    QTemporaryDir tmpDir;
> +    QVERIFY(tmpDir.isValid());
> +
> +    WebkitCookieStore store;
> +    QSignalSpy dbPathChanged(&store, SIGNAL(dbPathChanged()));
> +
> +    store.setProperty("dbPath", tmpDir.path());
> +    QCOMPARE(dbPathChanged.count(), 1);
> +    QCOMPARE(store.property("dbPath").toString(), tmpDir.path());
> +
> +    QVERIFY(store.property("cookies").value<Cookies>().isEmpty());
> +}
> +
> +void CookieStoreTest::setupCookieData()
> +{
> +    QTest::addColumn<Cookies>("cookies");
> +
> +    Cookies cookies;
> +
> +    cookies << "LSID=DQAAAKEaem_vYg; Domain=docs.foo.com; Path=/accounts; "
> +        "Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly";
> +    QTest::newRow("Single cookie") << cookies;
> +
> +    cookies.clear();
> +    cookies << "LSID=DQAAAKEaem_vYg; Domain=docs.foo.com; Path=/accounts; "
> +        "Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly";
> +    cookies << "HSID=AYQEVnDKrdst; Domain=.foo.com; Path=/; "
> +        "Expires=Wed, 13 Jan 2021 22:23:01 GMT; HttpOnly";
> +    cookies << "SSID=Ap4PGTEq; Domain=foo.com; Path=/; "
> +        "Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure";
> +    cookies << "made_write_conn=1295214458; Path=/; Domain=.example.com";
> +    QTest::newRow("Few cookies") << cookies;
> +}
> +
> +void CookieStoreTest::testChromeReadWrite()
> +{
> +    QFETCH(Cookies, cookies);
> +
> +    QTemporaryDir tmpDir;
> +    QVERIFY(tmpDir.isValid());
> +    QDir testDir(tmpDir.path());
> +
> +    ChromeCookieStore store;
> +    QSignalSpy cookiesChanged(&store, SIGNAL(cookiesChanged()));
> +    store.setDbPath(testDir.filePath("cookies.db"));
> +
> +    QCOMPARE(cookiesChanged.count(), 0);
> +    store.setProperty("cookies", QVariant::fromValue(cookies));
> +    QCOMPARE(cookiesChanged.count(), 1);
> +    Cookies readCookies = store.property("cookies").value<Cookies>();
> +    QCOMPARE(parseCookies(readCookies), parseCookies(cookies));
> +}
> +
> +void CookieStoreTest::testWebkitReadWrite()
> +{
> +    QFETCH(Cookies, cookies);
> +
> +    QTemporaryDir tmpDir;
> +    QVERIFY(tmpDir.isValid());
> +    QDir testDir(tmpDir.path());
> +
> +    WebkitCookieStore store;
> +    QSignalSpy cookiesChanged(&store, SIGNAL(cookiesChanged()));
> +    store.setDbPath(testDir.filePath("cookies.db"));
> +
> +    QCOMPARE(cookiesChanged.count(), 0);
> +    store.setProperty("cookies", QVariant::fromValue(cookies));
> +    QCOMPARE(cookiesChanged.count(), 1);
> +    Cookies readCookies = store.property("cookies").value<Cookies>();
> +    QCOMPARE(parseCookies(readCookies), parseCookies(cookies));
> +}
> +
> +void CookieStoreTest::testMoving()
> +{
> +    QFETCH(Cookies, cookies);
> +
> +    QTemporaryDir tmpDir;
> +    QVERIFY(tmpDir.isValid());
> +    QDir testDir(tmpDir.path());
> +
> +    WebkitCookieStore webkitStore;
> +    webkitStore.setDbPath(testDir.filePath("webkit.db"));
> +    webkitStore.setProperty("cookies", QVariant::fromValue(cookies));
> +
> +    ChromeCookieStore chromeStore;
> +    chromeStore.setDbPath(testDir.filePath("chrome.db"));
> +
> +    QSignalSpy moved(&chromeStore, SIGNAL(moved(bool)));
> +    chromeStore.moveFrom(&webkitStore);
> +
> +    QCOMPARE(moved.count(), 1);
> +    QCOMPARE(moved.at(0).at(0).toBool(), true);
> +
> +    Cookies movedCookies = chromeStore.property("cookies").value<Cookies>();
> +    QCOMPARE(parseCookies(movedCookies), parseCookies(cookies));
> +}
> +
> +QTEST_MAIN(CookieStoreTest)
> +#include "tst_CookieStore.moc"
> 


-- 
https://code.launchpad.net/~mardy/webbrowser-app/add-onlineaccount-support-for-container2/+merge/211701
Your team Ubuntu Phablet Team is subscribed to branch lp:webbrowser-app.



More information about the Ubuntu-reviews mailing list