From cd6eee46a7405bc2365ada5ca7cd2daab01e06c0 Mon Sep 17 00:00:00 2001
From: Siteshwar Vashisht <siteshwar@gmail.com>
Date: Mon, 23 Apr 2012 01:18:01 +0200
Subject: Google Sync Bookmarks in rekonq!

- Added UI bits to configure Google Bookamrks Sync
- Implemented sync, 2-way merging local and remote bk
- Remember to not update local history while remotely
adding bookmarks
- Encode parameters of add bookmarks request while posting data.
- (adjam) fix compile warnings

This is the squashed commit of Situ's work on Google Bookmarks Sync
SQUASHED BY: adjam ;)

REVIEW: 104673
DIGEST: Google Bookmarks Sync
REVIEWED BY: adjam
---
 src/CMakeLists.txt                    |   3 +
 src/sync/googlesynchandler.cpp        | 437 ++++++++++++++++++++++++++++++++++
 src/sync/googlesynchandler.h          |  86 +++++++
 src/sync/sync_google_settings.ui      |  83 +++++++
 src/sync/sync_host_type.ui            |   7 +
 src/sync/syncassistant.cpp            |   3 +-
 src/sync/syncassistant.h              |   1 +
 src/sync/synccheckwidget.cpp          |   7 +
 src/sync/syncgooglesettingswidget.cpp |  60 +++++
 src/sync/syncgooglesettingswidget.h   |  52 ++++
 src/sync/synchosttypewidget.cpp       |   9 +-
 src/sync/syncmanager.cpp              |  18 +-
 12 files changed, 762 insertions(+), 4 deletions(-)
 create mode 100644 src/sync/googlesynchandler.cpp
 create mode 100644 src/sync/googlesynchandler.h
 create mode 100644 src/sync/sync_google_settings.ui
 create mode 100644 src/sync/syncgooglesettingswidget.cpp
 create mode 100644 src/sync/syncgooglesettingswidget.h

(limited to 'src')

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ac4fa87b..1180ad0d 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -99,6 +99,7 @@ SET( rekonq_KDEINIT_SRCS
     useragent/useragentwidget.cpp
     #----------------------------------------
     sync/ftpsynchandler.cpp
+    sync/googlesynchandler.cpp
     sync/syncassistant.cpp
     sync/synchandler.cpp
     sync/syncmanager.cpp
@@ -107,6 +108,7 @@ SET( rekonq_KDEINIT_SRCS
     sync/syncdatawidget.cpp
     sync/synchosttypewidget.cpp
     sync/syncftpsettingswidget.cpp
+    sync/syncgooglesettingswidget.cpp
 )
 
 
@@ -130,6 +132,7 @@ KDE4_ADD_UI_FILES( rekonq_KDEINIT_SRCS
     sync/sync_check.ui
     sync/sync_data.ui
     sync/sync_ftp_settings.ui
+    sync/sync_google_settings.ui
     sync/sync_host_type.ui
  )
 
diff --git a/src/sync/googlesynchandler.cpp b/src/sync/googlesynchandler.cpp
new file mode 100644
index 00000000..801b7b62
--- /dev/null
+++ b/src/sync/googlesynchandler.cpp
@@ -0,0 +1,437 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2012 by Siteshwar Vashisht <siteshwar at gmail dot com>
+* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program 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; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "googlesynchandler.h"
+#include "googlesynchandler.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "application.h"
+#include "bookmarkmanager.h"
+
+// KDE Includes
+#include <KStandardDirs>
+#include <klocalizedstring.h>
+#include <kbookmarkmanager.h>
+
+#include <QList>
+#include <QWebPage>
+#include <QWebFrame>
+#include <QWebElement>
+#include <QUrl>
+#include <QWebSettings>
+#include <QNetworkAccessManager>
+#include <QNetworkReply>
+#include <QDomDocument>
+
+
+GoogleSyncHandler::GoogleSyncHandler(QObject *parent)
+    : SyncHandler(parent)
+    , _mode(RECEIVE_CHANGES)
+    , _doLogin(false)
+    , _isSyncing(false)
+    , _reply(0)
+    , _requestCount(0)
+{
+    kDebug() << "Creating Google Bookmarks handler...";
+    _webPage.settings()->setAttribute(QWebSettings::AutoLoadImages, false);
+    _webPage.settings()->setAttribute(QWebSettings::PrivateBrowsingEnabled, true);
+    connect(&_webPage, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
+}
+
+
+void GoogleSyncHandler::initialLoadAndCheck()
+{
+    if (!ReKonfig::syncEnabled())
+    {
+        _firstTimeSynced = false;
+        return;
+    }
+
+    // Bookmarks
+    if (ReKonfig::syncBookmarks())
+    {
+        _mode = RECEIVE_CHANGES;
+        startLogin();
+    }
+
+    if (ReKonfig::syncHistory())
+    {
+        emit syncStatus(Rekonq::History, false, i18n("Not supported!"));
+    }
+
+    if (ReKonfig::syncHistory())
+    {
+        emit syncStatus(Rekonq::Passwords, false, i18n("Not supported!"));
+    }
+}
+
+
+bool GoogleSyncHandler::syncRelativeEnabled(bool check)
+{
+    if (!ReKonfig::syncEnabled())
+        return false;
+
+    if (!_firstTimeSynced)
+        return false;
+
+    return check;
+}
+
+
+// ---------------------------------------------------------------------------------------
+
+
+void GoogleSyncHandler::syncHistory()
+{
+    kDebug() << "Syncing history not supported!";
+    emit syncStatus(Rekonq::History, false, i18n("Syncing history not supported!"));
+    emit syncHistoryFinished(false);
+}
+
+
+void GoogleSyncHandler::syncPasswords()
+{
+    kDebug() << "Syncing passwords not supported!";
+    emit syncStatus(Rekonq::Passwords, false, i18n("Syncing passwords not supported!"));
+    emit syncPasswordsFinished(false);
+}
+
+
+void GoogleSyncHandler::syncBookmarks()
+{
+
+    if (_isSyncing)
+    {
+        kDebug() << "Sync already in progress!";
+        return;
+    }
+    _mode = SEND_CHANGES;
+    startLogin();
+}
+
+void GoogleSyncHandler::startLogin()
+{
+    if (ReKonfig::syncUser().isEmpty() || ReKonfig::syncPass().isEmpty())
+    {
+        kDebug() << "No username or password!";
+        emit syncStatus(Rekonq::Bookmarks, false, i18n("No username or password!"));
+        emit syncBookmarksFinished(false);
+        return;
+    }
+
+    _isSyncing = true;
+
+    _doLogin = true;
+
+    kDebug() << "Loading login page...";
+    _webPage.mainFrame()->load(QUrl("http://bookmarks.google.com/"));
+}
+
+//Loading a webpage finished, what action to take is decided based on url we have loaded.
+void GoogleSyncHandler::loadFinished(bool ok)
+{
+    kDebug() << "Load Finished" << ok;
+    if (!ok)
+    {
+        kDebug() << "Error loading: " << _webPage.mainFrame()->url();
+        emit syncStatus(Rekonq::Bookmarks, false, i18n( "Error loading: " + _webPage.mainFrame()->url().toEncoded()));
+
+        _isSyncing = false;
+        return;
+    }
+
+    kDebug() << _webPage.mainFrame()->url();
+    kDebug() << "Path : " << _webPage.mainFrame()->url().path();
+
+    QString path = _webPage.mainFrame()->url().path();
+
+    if (path == "/ServiceLogin" && _doLogin == true)
+    {
+        // Let's login to our Google account
+        QWebFrame *frame = _webPage.mainFrame();
+
+        QWebElement email = frame->findFirstElement("#Email");
+        QWebElement passwd = frame->findFirstElement("#Passwd");
+        QWebElement form = frame->findFirstElement("#gaia_loginform");
+
+
+
+        email.setAttribute("value",ReKonfig::syncUser());
+        passwd.setAttribute("value",ReKonfig::syncPass());
+        form.evaluateJavaScript("this.submit();");
+        emit syncStatus(Rekonq::Bookmarks, true, i18n("Signing in..."));
+
+        // Login only once
+        _doLogin = false;
+    }
+    else if (path == "/bookmarks/")
+    {
+        //We get to this page after succesful login, let's fetch the bookmark list in Xml format.
+        QNetworkAccessManager *qnam = _webPage.networkAccessManager();
+        QNetworkRequest request;
+        request.setUrl(QUrl("http://www.google.com/bookmarks/?output=xml"));
+        _reply = qnam->get(request);
+        emit syncStatus(Rekonq::Bookmarks, true, i18n("Fetching bookmarks from server..."));
+        connect(_reply, SIGNAL(finished()), this, SLOT(fetchingBookmarksFinished()));
+    }
+    else if (path == "/ServiceLoginAuth")
+    {
+        emit syncStatus(Rekonq::Bookmarks, false, i18n("Login failed!"));
+        _isSyncing = false;
+    }
+    else if (path == "/bookmarks/mark")
+    {
+        QWebFrame *frame = _webPage.mainFrame();
+
+        QString sigKey = frame->findFirstElement("input[name=sig]").attribute("value");
+        kDebug() << "Signature Key is : " << sigKey;
+
+        QNetworkAccessManager *qnam = _webPage.networkAccessManager();
+
+        if (!_bookmarksToDelete.isEmpty())
+        {
+
+            for (QSet<QString>::const_iterator iter=_bookmarksToDelete.constBegin(); iter != _bookmarksToDelete.end(); ++iter)
+            {
+                QNetworkRequest request;
+                request.setUrl(QUrl("https://www.google.com/bookmarks/mark?dlq=" + *iter + "&sig=" + sigKey));
+
+                kDebug() << "Delete url is : " << request.url();
+                QNetworkReply *r = qnam->get(request);
+                connect(r, SIGNAL(finished()), this, SLOT(updateBookmarkFinished()));
+                ++_requestCount;
+            }
+        }
+
+        if (!_bookmarksToAdd.isEmpty())
+        {
+            emit syncStatus(Rekonq::Bookmarks, true, i18n("Adding bookmarks on server..."));
+            for (QSet<KUrl>::const_iterator iter=_bookmarksToAdd.constBegin(); iter != _bookmarksToAdd.end(); ++iter)
+            {
+                KBookmark bookmark = rApp->bookmarkManager()->bookmarkForUrl(*iter);
+                QByteArray postData;
+                postData.append("bkmk=" + QUrl::toPercentEncoding(bookmark.url().url().toUtf8()));
+                postData.append("&title=" + QUrl::toPercentEncoding(bookmark.text().toUtf8()));
+                postData.append("&annotation=");
+                postData.append("&labels=");
+                postData.append("&prev=/lookup");
+                postData.append("&sig=" + sigKey.toUtf8());
+
+                QNetworkRequest request;
+                request.setUrl(QUrl("https://www.google.com/bookmarks/mark?sig=" + sigKey +"&btnA"));
+                request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
+                kDebug() << "Url: " << request.url();
+                kDebug() << "Post data is :" << postData;
+                QNetworkReply *r = qnam->post(request, postData);
+                connect(r, SIGNAL(finished()), this, SLOT(updateBookmarkFinished()));
+                ++_requestCount;
+            }
+        }
+
+        _bookmarksToDelete.clear();
+        _bookmarksToAdd.clear();
+
+    }
+    else if (path == "/Logout")
+    {
+        //Session finished
+        emit syncStatus(Rekonq::Bookmarks, true, i18n("Done!"));
+        emit syncBookmarksFinished(true);
+        _isSyncing = false;
+    }
+    else
+    {
+        kDebug() << "Unknown Response!";
+        _isSyncing = false;
+    }
+
+}
+
+//We received bookmarks stored on server in xml format, now take the action based on which mode we are in.
+void GoogleSyncHandler::fetchingBookmarksFinished()
+{
+    QString data = _reply->readAll();
+
+    QDomDocument doc("bookmarks");
+    doc.setContent(data);
+
+    QDomNodeList bookmarksOnServer = doc.elementsByTagName("bookmark");
+    emit syncStatus(Rekonq::Bookmarks, true, i18n("Reading bookmarks..."));
+
+    BookmarkManager *manager = rApp->bookmarkManager();
+    KBookmarkGroup root = manager->rootGroup();
+
+
+    if (_mode == RECEIVE_CHANGES)
+    {
+
+        for (int i=0; i<bookmarksOnServer.size(); ++i)
+        {
+
+            QString title = getChildElement(bookmarksOnServer.at(i),"title");
+            QString url = getChildElement(bookmarksOnServer.at(i),"url");
+
+            KBookmark bookmark = manager->bookmarkForUrl(KUrl(url));
+            if (bookmark.isNull())
+            {
+                //Add bookmark
+                kDebug() << "Add bookmark";
+                emit syncStatus(Rekonq::Bookmarks, true, i18n("Adding bookmark "));
+                root.addBookmark(title.isEmpty() ? url : title, KUrl(url));
+                manager->manager()->emitChanged(root);
+            }
+
+        }
+
+        // After receiving changes, we compare local bookmarks with Google bookmarks and if some bookmarks exist locally but not on Google Bookmarks, we add them.
+        checkToAddGB(root, bookmarksOnServer);
+
+        if (!_bookmarksToAdd.isEmpty())
+        {
+            kDebug() << "Getting sigkey";
+            _webPage.mainFrame()->load(QUrl("https://www.google.com/bookmarks/mark?op=add&hl=en"));
+        }
+        else
+        {
+            _webPage.mainFrame()->load(QUrl("https://accounts.google.com/Logout?hl=en"));
+            emit syncStatus(Rekonq::Bookmarks, true, i18n("Signing out..."));
+        }
+    }
+    else
+    {
+        checkToAddGB(root, bookmarksOnServer);
+        checkToDeleteGB(manager, bookmarksOnServer);
+
+        if (!_bookmarksToAdd.isEmpty() || !_bookmarksToDelete.isEmpty())
+        {
+            kDebug() << "Getting sigkey";
+            _webPage.mainFrame()->load(QUrl("https://www.google.com/bookmarks/mark?op=add&hl=en"));
+        }
+        else
+        {
+            _webPage.mainFrame()->load(QUrl("https://accounts.google.com/Logout?hl=en"));
+            emit syncStatus(Rekonq::Bookmarks, true, i18n("Signing out..."));
+        }
+    }
+
+    _reply->deleteLater();
+}
+
+//Get value of a child element of a dom node
+QString GoogleSyncHandler::getChildElement(const QDomNode &node, QString name)
+{
+    QDomNodeList nodes = node.childNodes();
+
+    for (int j=0; j<nodes.size(); ++j)
+    {
+        QDomElement element = nodes.at(j).toElement();
+
+        if (nodes.at(j).nodeName() == name)
+        {
+            //kDebug() << "Url : " << element.text();
+            return element.text();
+        }
+    }
+    return NULL;
+}
+
+//This method checks whether we have any other bookmarks than the ones which exist on the server
+void GoogleSyncHandler::checkToAddGB(const KBookmarkGroup &root, const QDomNodeList &bookmarksOnServer)
+{
+    KBookmark current = root.first();
+
+    while (!current.isNull())
+    {
+        kDebug() << "Checking Url to add on Google Bookmarks: " << current.url();
+        bool found = false;
+        for (int i=0; i < bookmarksOnServer.count(); ++i)
+        {
+            if (current.isGroup())
+            {
+                kDebug() << "Checking group" << current.text();
+                checkToAddGB(current.toGroup(), bookmarksOnServer);
+                //skip adding a blank in _bookmarksToAdd
+                found = true;
+                break;
+            }
+            else if (current.url().url() == getChildElement(bookmarksOnServer.at(i),"url"))
+            {
+                found = true;
+            }
+        }
+
+        if (!found)
+        {
+            kDebug() <<  "Adding to Google Bookmarks: " << current.url().url();
+            _bookmarksToAdd.insert(current.url());
+        }
+        current = root.next(current);
+    }
+}
+
+//Check whether we need to delete bookmarks while sending changes to Google Bookmarks
+void GoogleSyncHandler::checkToDeleteGB(BookmarkManager *manager, const QDomNodeList &bookmarksOnServer)
+{
+
+    for (int i=0; i < bookmarksOnServer.count(); ++i)
+    {
+        QString url = getChildElement(bookmarksOnServer.at(i),"url");
+
+        KBookmark result = manager->bookmarkForUrl(KUrl(url));
+        if (result.isNull())
+        {
+            kDebug() <<  "Deleting from Google Bookmarks: " << url;
+            _bookmarksToDelete.insert(getChildElement(bookmarksOnServer.at(i),"id"));
+        }
+    }
+
+}
+
+
+//Added or deleted a bookmark on server, check whether we succeed here, and logout when all requests are done!
+void GoogleSyncHandler::updateBookmarkFinished()
+{
+    --_requestCount;
+    QNetworkReply *reply = dynamic_cast<QNetworkReply*>(sender());
+    if (reply->error() != QNetworkReply::NoError)
+        kDebug() << "Network Error while adding bookmark to server, code is: " << reply->error();
+    else if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) != 302)
+        kDebug() << "Unexpected reply : " << reply->readAll();
+    else
+        kDebug() << "Success!";
+
+    if (_requestCount <= 0)
+    {
+        _webPage.mainFrame()->load(QUrl("https://accounts.google.com/Logout?hl=en"));
+        emit syncStatus(Rekonq::Bookmarks, true, i18n("Signing out..."));
+    }
+
+}
diff --git a/src/sync/googlesynchandler.h b/src/sync/googlesynchandler.h
new file mode 100644
index 00000000..2d70cfb7
--- /dev/null
+++ b/src/sync/googlesynchandler.h
@@ -0,0 +1,86 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2012 by Siteshwar Vashisht <siteshwar at gmail dot com>
+* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program 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; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 GOOGLE_SYNC_HANDLER_H
+#define GOOGLE_SYNC_HANDLER_H
+
+#include <QWebPage>
+
+// Local Includes
+#include "synchandler.h"
+
+// KDE Includes
+#include <KUrl>
+#include <KBookmarkGroup>
+
+// Forward Declarations
+class QNetworkReply;
+class BookmarkManager;
+
+class GoogleSyncHandler : public SyncHandler
+{
+    Q_OBJECT
+
+public:
+    GoogleSyncHandler(QObject *parent = 0);
+
+    void syncHistory();
+    void syncBookmarks();
+    void syncPasswords();
+
+    void initialLoadAndCheck();
+
+private Q_SLOTS:
+    void loadFinished(bool);
+    void fetchingBookmarksFinished();
+    void updateBookmarkFinished();
+
+Q_SIGNALS:
+    void syncBookmarksFinished(bool);
+    void syncHistoryFinished(bool);
+    void syncPasswordsFinished(bool);
+
+private:
+    bool syncRelativeEnabled(bool);
+    void startLogin();
+    void checkToAddGB(const KBookmarkGroup &root, const QDomNodeList &);
+    void checkToDeleteGB(BookmarkManager *, const QDomNodeList &);
+    QString getChildElement(const QDomNode &node, QString name);
+    void checkRequestCount();
+
+    enum {SEND_CHANGES, RECEIVE_CHANGES} _mode;
+    QUrl _remoteBookmarksUrl;
+    bool _doLogin;
+    bool _isSyncing;
+    QWebPage _webPage;
+    QNetworkReply *_reply;
+    QSet<KUrl> _bookmarksToAdd;
+    QSet<QString> _bookmarksToDelete;
+    unsigned int _requestCount;
+};
+
+#endif // GOOGLE_SYNC_HANDLER_H
diff --git a/src/sync/sync_google_settings.ui b/src/sync/sync_google_settings.ui
new file mode 100644
index 00000000..d23d083b
--- /dev/null
+++ b/src/sync/sync_google_settings.ui
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SyncGoogleSettings</class>
+ <widget class="QWidget" name="SyncGoogleSettings">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="googleGroupBox">
+     <property name="title">
+      <string>Google Account Settings</string>
+     </property>
+     <layout class="QFormLayout" name="formLayout">
+      <property name="fieldGrowthPolicy">
+       <enum>QFormLayout::ExpandingFieldsGrow</enum>
+      </property>
+      <item row="0" column="0">
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>Username:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="0" column="1">
+       <widget class="KLineEdit" name="kcfg_syncUser"/>
+      </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="label_3">
+        <property name="text">
+         <string>Password:</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="KLineEdit" name="kcfg_syncPass"/>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="infoLabel">
+     <property name="styleSheet">
+      <string notr="true">QLabel { color : red; }</string>
+     </property>
+     <property name="text">
+      <string>Only bookmarks will be synchronized.</string>
+     </property>
+     <property name="alignment">
+      <set>Qt::AlignCenter</set>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>124</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KLineEdit</class>
+   <extends>QLineEdit</extends>
+   <header>klineedit.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/sync/sync_host_type.ui b/src/sync/sync_host_type.ui
index 6eb875dc..ba96ab83 100644
--- a/src/sync/sync_host_type.ui
+++ b/src/sync/sync_host_type.ui
@@ -24,6 +24,13 @@
         </property>
        </widget>
       </item>
+      <item>
+       <widget class="QRadioButton" name="googleRadioButton">
+        <property name="text">
+         <string>Google Bookmarks</string>
+        </property>
+       </widget>
+      </item>
       <item>
        <widget class="QRadioButton" name="nullRadioButton">
         <property name="text">
diff --git a/src/sync/syncassistant.cpp b/src/sync/syncassistant.cpp
index 8688d7bc..0e51e7b7 100644
--- a/src/sync/syncassistant.cpp
+++ b/src/sync/syncassistant.cpp
@@ -34,7 +34,7 @@
 #include "synchosttypewidget.h"
 
 #include "syncftpsettingswidget.h"
-
+#include "syncgooglesettingswidget.h"
 
 SyncAssistant::SyncAssistant(QWidget *parent)
     : QWizard(parent)
@@ -44,5 +44,6 @@ SyncAssistant::SyncAssistant(QWidget *parent)
     setPage(Page_Data, new SyncDataWidget(this));
     setPage(Page_Type, new SyncHostTypeWidget(this));
     setPage(Page_FTP_Settings, new SyncFTPSettingsWidget(this));
+    setPage(Page_Google_Settings, new SyncGoogleSettingsWidget(this));
     setPage(Page_Check, new SyncCheckWidget(this));
 }
diff --git a/src/sync/syncassistant.h b/src/sync/syncassistant.h
index 01b9647f..9853cb2d 100644
--- a/src/sync/syncassistant.h
+++ b/src/sync/syncassistant.h
@@ -42,6 +42,7 @@ public:
         Page_Data,
         Page_Type,
         Page_FTP_Settings,
+	Page_Google_Settings,
         Page_Check
     };
 
diff --git a/src/sync/synccheckwidget.cpp b/src/sync/synccheckwidget.cpp
index 9dbf5fc3..27f19721 100644
--- a/src/sync/synccheckwidget.cpp
+++ b/src/sync/synccheckwidget.cpp
@@ -60,6 +60,11 @@ void SyncCheckWidget::initializePage()
         syncLabel->setText(i18n("FTP"));
         hostLabel->setText(ReKonfig::syncHost());
     }
+    else if (ReKonfig::syncType() == 1)
+    {
+        syncLabel->setText(i18n("Google"));
+        hostLabel->setText(ReKonfig::syncHost());
+    }
     else
     {
         syncLabel->setText(i18n("No sync"));
@@ -129,6 +134,8 @@ void SyncCheckWidget::initializePage()
 }
 
 
+
+
 void SyncCheckWidget::updateWidget(Rekonq::SyncData type, bool done, QString msg)
 {
     KIcon doneIcon(QL1S("dialog-ok-apply"));
diff --git a/src/sync/syncgooglesettingswidget.cpp b/src/sync/syncgooglesettingswidget.cpp
new file mode 100644
index 00000000..c927a741
--- /dev/null
+++ b/src/sync/syncgooglesettingswidget.cpp
@@ -0,0 +1,60 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+* Copyright (C) 2012 by Siteshwar Vashisht <siteshwar at gmail dot com>
+* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program 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; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "syncgooglesettingswidget.h"
+#include "syncgooglesettingswidget.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "syncassistant.h"
+
+
+SyncGoogleSettingsWidget::SyncGoogleSettingsWidget(QWidget *parent)
+    : QWizardPage(parent)
+{
+    setupUi(this);
+    kcfg_syncUser->setText(ReKonfig::syncUser());
+    kcfg_syncPass->setText(ReKonfig::syncPass());
+
+    kcfg_syncPass->setPasswordMode(true);
+}
+
+
+int SyncGoogleSettingsWidget::nextId() const
+{
+    // save
+    ReKonfig::setSyncHost("http://bookmarks.google.com/");
+    ReKonfig::setSyncUser(kcfg_syncUser->text());
+    ReKonfig::setSyncPass(kcfg_syncPass->text());
+
+    ReKonfig::setSyncHistory(false);
+    ReKonfig::setSyncPasswords(false);
+
+    return SyncAssistant::Page_Check;
+}
diff --git a/src/sync/syncgooglesettingswidget.h b/src/sync/syncgooglesettingswidget.h
new file mode 100644
index 00000000..25c55dba
--- /dev/null
+++ b/src/sync/syncgooglesettingswidget.h
@@ -0,0 +1,52 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2011 by Siteshwar Vashisht <siteshwar AT gmail.com> 
+* Copyright (C) 2011 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program 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; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program 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 SYNC_GOOGLE_SETTINGS_WIDGET_H
+#define SYNC_GOOGLE_SETTINGS_WIDGET_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// Ui Includes
+#include "ui_sync_google_settings.h"
+
+// Qt Includes
+#include <QWizardPage>
+
+
+class SyncGoogleSettingsWidget : public QWizardPage, private Ui::SyncGoogleSettings
+{
+    Q_OBJECT
+
+public:
+    SyncGoogleSettingsWidget(QWidget *parent = 0);
+
+    int nextId() const;
+};
+
+#endif // SYNC_GOOGLE_SETTINGS_WIDGET_H
diff --git a/src/sync/synchosttypewidget.cpp b/src/sync/synchosttypewidget.cpp
index 0810182e..32fd1f9f 100644
--- a/src/sync/synchosttypewidget.cpp
+++ b/src/sync/synchosttypewidget.cpp
@@ -42,6 +42,8 @@ SyncHostTypeWidget::SyncHostTypeWidget(QWidget *parent)
 
     if (ReKonfig::syncType() == 0)
         ftpRadioButton->setChecked(true);
+    else if(ReKonfig::syncType() == 1)
+        googleRadioButton->setChecked(true);	
     else
         nullRadioButton->setChecked(true);
 }
@@ -55,9 +57,14 @@ int SyncHostTypeWidget::nextId() const
         ReKonfig::setSyncType(0);
         return SyncAssistant::Page_FTP_Settings;
     }
+	else if (googleRadioButton->isChecked())
+	{
+		ReKonfig::setSyncType(1);
+		return SyncAssistant::Page_Google_Settings;
+	}
     else
     {
-        ReKonfig::setSyncType(1);
+        ReKonfig::setSyncType(2);
         return SyncAssistant::Page_Check;
     }
 
diff --git a/src/sync/syncmanager.cpp b/src/sync/syncmanager.cpp
index de14703c..29e76414 100644
--- a/src/sync/syncmanager.cpp
+++ b/src/sync/syncmanager.cpp
@@ -38,6 +38,7 @@
 
 #include "syncassistant.h"
 #include "ftpsynchandler.h"
+#include "googlesynchandler.h"
 
 // KDE Includes
 #include <klocalizedstring.h>
@@ -68,10 +69,23 @@ void SyncManager::loadSettings()
     if (ReKonfig::syncEnabled())
     {
         // reset syncer
-        if (_syncImplementation.isNull())
+        if (!_syncImplementation.isNull())
         {
-            // actually we have just FTP handler...
+            delete _syncImplementation.data();
+            _syncImplementation.clear();
+        }
+        
+        switch(ReKonfig::syncType())
+        {
+        case 0:
             _syncImplementation = new FTPSyncHandler(this);
+            break;
+        case 1:
+            _syncImplementation = new GoogleSyncHandler(this);
+            break;
+        default:
+            kDebug() << "/dev/null";
+            return;
         }
 
         _syncImplementation.data()->initialLoadAndCheck();
-- 
cgit v1.2.1