]> gitweb.stoutner.com Git - PrivacyBrowserPC.git/blobdiff - src/dialogs/CookiesDialog.cpp
Add durable cookie support.
[PrivacyBrowserPC.git] / src / dialogs / CookiesDialog.cpp
index b200891566a8ef8def175108394de306e1cda854..fa9679c457a4b4e58e906457cd367ca2ed577c30 100644 (file)
@@ -21,6 +21,7 @@
 #include "AddOrEditCookieDialog.h"
 #include "CookiesDialog.h"
 #include "ui_CookiesDialog.h"
+#include "databases/CookiesDatabase.h"
 
 // KDE Frameworks headers.
 #include <KLocalizedString>
@@ -117,30 +118,33 @@ CookiesDialog::CookiesDialog(std::list<QNetworkCookie> *originalCookieListPointe
     // Get a handle for the tree view.
     treeViewPointer = cookiesDialogUi.treeView;
 
-    // Initialize the standard item model.
-    standardItemModelPointer = new QStandardItemModel();
+    // Initialize the tree model.
+    treeModelPointer = new QStandardItemModel();
 
     // Set the column count.
-    standardItemModelPointer->setColumnCount(6);
-
-    // Set the header data.
-    standardItemModelPointer->setHeaderData(0, Qt::Horizontal, i18nc("The cookie Name header.", "Name"));
-    standardItemModelPointer->setHeaderData(1, Qt::Horizontal, i18nc("The cookie Path header.", "Path"));
-    standardItemModelPointer->setHeaderData(2, Qt::Horizontal, i18nc("The cookie Expiration Date header.", "Expiration Date"));
-    standardItemModelPointer->setHeaderData(3, Qt::Horizontal, i18nc("The cookie HTTP Only header.", "HTTP Only"));
-    standardItemModelPointer->setHeaderData(4, Qt::Horizontal, i18nc("The cookie Secure header.", "Secure"));
-    standardItemModelPointer->setHeaderData(5, Qt::Horizontal, i18nc("The cookie Value header.", "Value"));
-
-    // Set the header tool tips.
-    standardItemModelPointer->horizontalHeaderItem(0)->setToolTip(i18nc("The cookie Name tool tip.",
+    treeModelPointer->setColumnCount(7);
+
+    // Set the tree header data.
+    treeModelPointer->setHeaderData(0, Qt::Horizontal, i18nc("The cookie Name header.", "Name"));
+    treeModelPointer->setHeaderData(1, Qt::Horizontal, i18nc("The cookie Durable header.", "Durable"));
+    treeModelPointer->setHeaderData(2, Qt::Horizontal, i18nc("The cookie Path header.", "Path"));
+    treeModelPointer->setHeaderData(3, Qt::Horizontal, i18nc("The cookie Expiration Date header.", "Expiration Date"));
+    treeModelPointer->setHeaderData(4, Qt::Horizontal, i18nc("The cookie HTTP Only header.", "HTTP Only"));
+    treeModelPointer->setHeaderData(5, Qt::Horizontal, i18nc("The cookie Secure header.", "Secure"));
+    treeModelPointer->setHeaderData(6, Qt::Horizontal, i18nc("The cookie Value header.", "Value"));
+
+    // Set the tree header tool tips.
+    treeModelPointer->horizontalHeaderItem(0)->setToolTip(i18nc("The cookie Name tool tip.",
                                                                         "The name identifies the cookie.  Each cookie has a unique combination of domain, name, and path."));
-    standardItemModelPointer->horizontalHeaderItem(1)->setToolTip(i18nc("The cookie Path tool tip.", "Websites can restrict cookie access to subpath of their URL."));
-    standardItemModelPointer->horizontalHeaderItem(2)->setToolTip(i18nc("The cookie Expiration Date tool tip.",
+    treeModelPointer->horizontalHeaderItem(1)->setToolTip(i18nc("The cookie Durable tool tip",
+                                                                        "Durable cookies pursist across restarts, irrespective of the expiration date. All other cookies are deleted when Privacy Browser closes, irrespective of the expiration date."));
+    treeModelPointer->horizontalHeaderItem(2)->setToolTip(i18nc("The cookie Path tool tip.", "Websites can restrict cookie access to subpath of their URL."));
+    treeModelPointer->horizontalHeaderItem(3)->setToolTip(i18nc("The cookie Expiration Date tool tip.",
                                                                         "Cookies without an expiration date are known as session cookies and are expected to be deleted every time the browser closes."));
-    standardItemModelPointer->horizontalHeaderItem(3)->setToolTip(i18nc("The cookie HTTP Only tool tip.",
+    treeModelPointer->horizontalHeaderItem(4)->setToolTip(i18nc("The cookie HTTP Only tool tip.",
                                                                         "Restrict cookie access to HTTP (and HTTPS). This prevents JavaScript from accessing the cookie, which hardens it against cross-site scripting attacks."));
-    standardItemModelPointer->horizontalHeaderItem(4)->setToolTip(i18nc("The cookie Secure tool tip.", "Only allow the cookie to be transferred across HTTPS (as opposed to HTTP)."));
-    standardItemModelPointer->horizontalHeaderItem(5)->setToolTip(i18nc("The cookie Value tool tip.", "The value contains the cookie data."));
+    treeModelPointer->horizontalHeaderItem(5)->setToolTip(i18nc("The cookie Secure tool tip.", "Only allow the cookie to be transferred across HTTPS (as opposed to HTTP)."));
+    treeModelPointer->horizontalHeaderItem(6)->setToolTip(i18nc("The cookie Value tool tip.", "The value contains the cookie data."));
 
     // Sort the cookie list.
     cookieListPointer->sort(cookieSortPredicate);
@@ -148,10 +152,10 @@ CookiesDialog::CookiesDialog(std::list<QNetworkCookie> *originalCookieListPointe
     // Create the current domain string.
     QString currentDomainString = "";
 
-    // Create the current domain standard item pointer.
-    QStandardItem *currentDomainStandardItemPointer;
+    // Create the current domain item pointer.
+    QStandardItem *currentDomainItemPointer;
 
-    // Populate the VBoxLayout.
+    // Populate the cookie tree view.
     for (QNetworkCookie cookie : *cookieListPointer)
     {
         // Get the cookie domain.
@@ -160,72 +164,45 @@ CookiesDialog::CookiesDialog(std::list<QNetworkCookie> *originalCookieListPointe
         // Check to see if the cookie is a member of the current domain.
         if (cookieDomain != currentDomainString)  // Create a new domain in the tree.
         {
-            // Create a list for the domain standard items.
-            QList<QStandardItem*> domainStandardItemList;
-
-            // Create the new domain standard items.
-            QStandardItem *domainStandardItemPointer = new QStandardItem(cookieDomain);
-            QStandardItem *pathStandardItemPointer = new QStandardItem(QStringLiteral(""));
-            QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QStringLiteral(""));
-            QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QStringLiteral(""));
-            QStandardItem *isSecureStandardItemPointer = new QStandardItem(QStringLiteral(""));
-            QStandardItem *valueStandardItemPointer = new QStandardItem(QStringLiteral(""));
-
-            // Disable editing of the domain.
-            domainStandardItemPointer->setEditable(false);
-            pathStandardItemPointer->setEditable(false);
-            expirationDateStandardItemPointer->setEditable(false);
-            isHttpOnlyStandardItemPointer->setEditable(false);
-            isSecureStandardItemPointer->setEditable(false);
-            valueStandardItemPointer->setEditable(false);
-
-            // Populate the domain standard item list.
-            domainStandardItemList.append(domainStandardItemPointer);
-            domainStandardItemList.append(pathStandardItemPointer);
-            domainStandardItemList.append(expirationDateStandardItemPointer);
-            domainStandardItemList.append(isHttpOnlyStandardItemPointer);
-            domainStandardItemList.append(isSecureStandardItemPointer);
-            domainStandardItemList.append(valueStandardItemPointer);
+            // Create the domain name item.
+            QStandardItem *domainNameItemPointer = new QStandardItem(cookieDomain);
 
             // Add the domain to the tree.
-            standardItemModelPointer->invisibleRootItem()->appendRow(domainStandardItemList);
+            treeModelPointer->invisibleRootItem()->appendRow(domainNameItemPointer);
 
             // Update the current domain string.
             currentDomainString = cookieDomain;
 
-            // Update the current domain standard item pointer.
-            currentDomainStandardItemPointer = domainStandardItemPointer;
+            // Update the current domain item pointer.
+            currentDomainItemPointer = domainNameItemPointer;
         }
 
-        // Create a list for the cookie standard items.
-        QList<QStandardItem*> cookieStandardItemList;
-
-        // Create the cookie standard items.
-        QStandardItem *nameStandardItemPointer = new QStandardItem(QString(cookie.name()));
-        QStandardItem *pathStandardItemPointer = new QStandardItem(QString(cookie.path()));
-        QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
-        QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
-        QStandardItem *isSecureStandardItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
-        QStandardItem *valueStandardItemPointer = new QStandardItem(QString(cookie.value()));
-
-        // Disable editing of the cookie standard items.
-        nameStandardItemPointer->setEditable(false);
-        pathStandardItemPointer->setEditable(false);
-        expirationDateStandardItemPointer->setEditable(false);
-        isHttpOnlyStandardItemPointer->setEditable(false);
-        isSecureStandardItemPointer->setEditable(false);
-        valueStandardItemPointer->setEditable(false);
+        // Check to see if the cookie is durable.
+        bool isDurable = CookiesDatabase::isDurable(cookie);
+
+        // Create a list for the cookie items.
+        QList<QStandardItem*> cookieItemList;
+
+        // Create the cookie items.
+        QStandardItem *nameItemPointer = new QStandardItem(QString(cookie.name()));
+        QStandardItem *durableItemPointer = new QStandardItem(QString(isDurable ? i18n("yes") : i18n("no")));
+        QStandardItem *pathItemPointer = new QStandardItem(QString(cookie.path()));
+        QStandardItem *expirationDateItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
+        QStandardItem *isHttpOnlyItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
+        QStandardItem *isSecureItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
+        QStandardItem *valueItemPointer = new QStandardItem(QString(cookie.value()));
 
         // Populate the cookie standard item list.
-        cookieStandardItemList.append(nameStandardItemPointer);
-        cookieStandardItemList.append(pathStandardItemPointer);
-        cookieStandardItemList.append(expirationDateStandardItemPointer);
-        cookieStandardItemList.append(isHttpOnlyStandardItemPointer);
-        cookieStandardItemList.append(isSecureStandardItemPointer);
-        cookieStandardItemList.append(valueStandardItemPointer);
+        cookieItemList.append(nameItemPointer);
+        cookieItemList.append(durableItemPointer);
+        cookieItemList.append(pathItemPointer);
+        cookieItemList.append(expirationDateItemPointer);
+        cookieItemList.append(isHttpOnlyItemPointer);
+        cookieItemList.append(isSecureItemPointer);
+        cookieItemList.append(valueItemPointer);
 
         // Add the cookie to the tree.
-        currentDomainStandardItemPointer->appendRow(cookieStandardItemList);
+        currentDomainItemPointer->appendRow(cookieItemList);
     }
 
     // Auto resize the headers.
@@ -240,14 +217,17 @@ CookiesDialog::CookiesDialog(std::list<QNetworkCookie> *originalCookieListPointe
     // Indicate that all the rows are the same height, wich improves performance.
     treeViewPointer->setUniformRowHeights(true);
 
-    // Set the tree view model.
-    treeViewPointer->setModel(standardItemModelPointer);
+    // Disable editing.
+    treeViewPointer->setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+    // Set the tree model.
+    treeViewPointer->setModel(treeModelPointer);
 
-    // Get a handle for the tree view selection model.
-    treeViewSelectionModelPointer = treeViewPointer->selectionModel();
+    // Get a handle for the tree selection model.
+    treeSelectionModelPointer = treeViewPointer->selectionModel();
 
     // Listen for selection changes.
-    connect(treeViewSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi()));
+    connect(treeSelectionModelPointer, SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(updateUi()));
 
     // Get handles for the buttons.
     addCookieButtonPointer = cookiesDialogUi.addCookieButton;
@@ -297,7 +277,7 @@ CookiesDialog::CookiesDialog(std::list<QNetworkCookie> *originalCookieListPointe
     updateUi();
 };
 
-void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const
+void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie, const bool &isDurable) const
 {
     // Add the cookie to the cookie list and the cookie store.
     emit addCookie(cookie);
@@ -306,46 +286,22 @@ void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const
     QString newDomain = cookie.domain();
 
     // Check to see if the domain already exists in the model.
-    QList<QStandardItem*> currentDomainStandardItemList = standardItemModelPointer->findItems(newDomain);
+    QList<QStandardItem*> currentDomainItemList = treeModelPointer->findItems(newDomain);
 
-    // Create a domain standard item pointer.
-    QStandardItem *domainStandardItemPointer;
+    // Create a domain item pointer.
+    QStandardItem *domainNameItemPointer;
 
-    // Prepare the domain standard item pointer.
-    if (currentDomainStandardItemList.isEmpty())  // The domain doesn't currently exist in the tree.
+    // Prepare the domain item pointer.
+    if (currentDomainItemList.isEmpty())  // The domain doesn't currently exist in the tree.
     {
-        // Create a list for the domain standard items.
-        QList<QStandardItem*> domainStandardItemList;
-
-        // Create the new domain standard items.
-        domainStandardItemPointer = new QStandardItem(newDomain);
-        QStandardItem *pathStandardItemPointer = new QStandardItem(QStringLiteral(""));
-        QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QStringLiteral(""));
-        QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QStringLiteral(""));
-        QStandardItem *isSecureStandardItemPointer = new QStandardItem(QStringLiteral(""));
-        QStandardItem *valueStandardItemPointer = new QStandardItem(QStringLiteral(""));
-
-        // Disable editing of the domain.
-        domainStandardItemPointer->setEditable(false);
-        pathStandardItemPointer->setEditable(false);
-        expirationDateStandardItemPointer->setEditable(false);
-        isHttpOnlyStandardItemPointer->setEditable(false);
-        isSecureStandardItemPointer->setEditable(false);
-        valueStandardItemPointer->setEditable(false);
-
-        // Populate the domain standard item list.
-        domainStandardItemList.append(domainStandardItemPointer);
-        domainStandardItemList.append(pathStandardItemPointer);
-        domainStandardItemList.append(expirationDateStandardItemPointer);
-        domainStandardItemList.append(isHttpOnlyStandardItemPointer);
-        domainStandardItemList.append(isSecureStandardItemPointer);
-        domainStandardItemList.append(valueStandardItemPointer);
+        // Create the domain name item.
+        domainNameItemPointer = new QStandardItem(newDomain);
 
         // Create the insert domain row number.
         int insertDomainRowNumber = 0;
 
         // Get the number of domains in the tree.
-        int numberOfDomains = standardItemModelPointer->invisibleRootItem()->rowCount();
+        int numberOfDomains = treeModelPointer->invisibleRootItem()->rowCount();
 
         // Get the new domain strings.
         QString newDomainTopLevelDomain = newDomain.section('.', -1);
@@ -356,7 +312,7 @@ void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const
         for (int i = 0; i < numberOfDomains; ++i)
         {
             // Get the current domain strings.
-            QString currentDomain = standardItemModelPointer->invisibleRootItem()->child(i, 0)->index().data().toString();
+            QString currentDomain = treeModelPointer->invisibleRootItem()->child(i, 0)->index().data().toString();
             QString currentDomainTopLevelDomain = currentDomain.section('.', -1);
             QString currentDomainSecondLevelDomain = currentDomain.section('.', -2);
             QString currentDomainThirdLevelDomain = currentDomain.section('.', -3);
@@ -385,76 +341,85 @@ void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const
         }
 
         // Add the domain to the tree.
-        standardItemModelPointer->invisibleRootItem()->insertRow(insertDomainRowNumber, domainStandardItemList);
+        treeModelPointer->invisibleRootItem()->insertRow(insertDomainRowNumber, domainNameItemPointer);
     }
     else  // The domain already exists in the tree.
     {
         // Use the current domain standard item.
-        domainStandardItemPointer = currentDomainStandardItemList[0];
+        domainNameItemPointer = currentDomainItemList[0];
     }
 
     // Get strings for the new cookie name and path (used later in the placement of the row).
     QString newCookieName = QString(cookie.name());
     QString newCookiePath = QString(cookie.path());
 
-    // Create a list for the cookie standard items.
-    QList<QStandardItem*> cookieStandardItemList;
-
-    // Create the cookie standard items.
-    QStandardItem *nameStandardItemPointer = new QStandardItem(newCookieName);
-    QStandardItem *pathStandardItemPointer = new QStandardItem(newCookiePath);
-    QStandardItem *expirationDateStandardItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
-    QStandardItem *isHttpOnlyStandardItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
-    QStandardItem *isSecureStandardItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
-    QStandardItem *valueStandardItemPointer = new QStandardItem(QString(cookie.value()));
-
-    // Disable editing of the cookie standard items.
-    nameStandardItemPointer->setEditable(false);
-    pathStandardItemPointer->setEditable(false);
-    expirationDateStandardItemPointer->setEditable(false);
-    isHttpOnlyStandardItemPointer->setEditable(false);
-    isSecureStandardItemPointer->setEditable(false);
-    valueStandardItemPointer->setEditable(false);
-
-    // Populate the cookie standard item list.
-    cookieStandardItemList.append(nameStandardItemPointer);
-    cookieStandardItemList.append(pathStandardItemPointer);
-    cookieStandardItemList.append(expirationDateStandardItemPointer);
-    cookieStandardItemList.append(isHttpOnlyStandardItemPointer);
-    cookieStandardItemList.append(isSecureStandardItemPointer);
-    cookieStandardItemList.append(valueStandardItemPointer);
+    // Create a cookie item list.
+    QList<QStandardItem*> cookieItemList;
+
+    // Create the cookie items.
+    QStandardItem *nameItemPointer = new QStandardItem(newCookieName);
+    QStandardItem *durableItemPointer = new QStandardItem(QString(isDurable ? i18n("yes") : i18n("no")));
+    QStandardItem *pathItemPointer = new QStandardItem(newCookiePath);
+    QStandardItem *expirationDateItemPointer = new QStandardItem(QString(cookie.expirationDate().toString()));
+    QStandardItem *isHttpOnlyItemPointer = new QStandardItem(QString(cookie.isHttpOnly() ? i18n("yes") : i18n("no")));
+    QStandardItem *isSecureItemPointer = new QStandardItem(QString(cookie.isSecure() ? i18n("yes") : i18n("no")));
+    QStandardItem *valueItemPointer = new QStandardItem(QString(cookie.value()));
+
+    // Populate the cookie item list.
+    cookieItemList.append(nameItemPointer);
+    cookieItemList.append(durableItemPointer);
+    cookieItemList.append(pathItemPointer);
+    cookieItemList.append(expirationDateItemPointer);
+    cookieItemList.append(isHttpOnlyItemPointer);
+    cookieItemList.append(isSecureItemPointer);
+    cookieItemList.append(valueItemPointer);
 
     // Create the insert cookie row number.
     int insertCookieRowNumber = 0;
 
+    // Create the remove existing row tracker.
+    bool removeExistingRow = false;
+
     // Get the number of cookies in the domain.
-    int numberOfCookies = domainStandardItemPointer->rowCount();
+    int numberOfCookies = domainNameItemPointer->rowCount();
 
     // Iterate through the cookies for this domain.
     for (int i = 0; i < numberOfCookies; ++i)
     {
         // Get the current cookie name and path at the indicated row.
-        QString currentCookieName = domainStandardItemPointer->child(i, 0)->index().data().toString();
-        QString currentCookiePath = domainStandardItemPointer->child(i, 1)->index().data().toString();
+        QString currentCookieName = domainNameItemPointer->child(i, 0)->index().data().toString();
+        QString currentCookiePath = domainNameItemPointer->child(i, 2)->index().data().toString();
 
         // Check to see if the new cookie should be inserted after the current cookie.
-        if (newCookieName > currentCookieName)
+        if (newCookieName > currentCookieName)  // The new cookie name comes after the current cookie name.
         {
             // Insert the new cookie after the current cookie.
             insertCookieRowNumber = i + 1;
         }
-        else if ((newCookieName == currentCookieName) && (newCookiePath > currentCookiePath))
+        else if ((newCookieName == currentCookieName) && (newCookiePath > currentCookiePath))  // The names are the same, but the new cookie path comes after the current cookie path.
         {
             // Insert the new cookie after the current cookie.
             insertCookieRowNumber = i + 1;
         }
+        else if ((newCookieName == currentCookieName) && (newCookiePath == currentCookiePath))  // The cookies are the same.
+        {
+            // Remove the existing cookie in this row.
+            removeExistingRow = true;
+
+            // Insert the cookie in it's place.
+            insertCookieRowNumber = i;
+        }
     }
 
-    // Add the cookie to the tree.
-    domainStandardItemPointer->insertRow(insertCookieRowNumber, cookieStandardItemList);
+    // Remove the existing row if it is being edited.
+    if (removeExistingRow)
+        domainNameItemPointer->removeRow(insertCookieRowNumber);
+
+    // Add the cookie to the tree model.
+    domainNameItemPointer->insertRow(insertCookieRowNumber, cookieItemList);
 
     // Get the new cookie model index.
-    QModelIndex newCookieIndex = nameStandardItemPointer->index();
+    QModelIndex newCookieIndex = nameItemPointer->index();
 
     // Set the new cookie to be the current index.
     treeViewPointer->setCurrentIndex(newCookieIndex);
@@ -463,7 +428,7 @@ void CookiesDialog::addCookieFromDialog(const QNetworkCookie &cookie) const
     treeViewPointer->expand(newCookieIndex.parent());
 }
 
-void CookiesDialog::deleteCookie(const QModelIndex &modelIndex) const
+void CookiesDialog::deleteCookie(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const
 {
     // Create a partial cookie.
     QNetworkCookie partialCookie;
@@ -471,40 +436,69 @@ void CookiesDialog::deleteCookie(const QModelIndex &modelIndex) const
     // Populate the partial cookie from the current model index.
     partialCookie.setDomain(modelIndex.parent().siblingAtColumn(0).data().toString());
     partialCookie.setName(modelIndex.siblingAtColumn(0).data().toString().toUtf8());
-    partialCookie.setPath(modelIndex.siblingAtColumn(1).data().toString());
+    partialCookie.setPath(modelIndex.siblingAtColumn(2).data().toString());
 
     // Create a cookie to delete.
     QNetworkCookie cookieToDelete;
 
-    // Search for the partial cookie in the cookie list.
-    for (QNetworkCookie cookie : *cookieListPointer)
+    // Check if the cookie is durable.
+    bool isDurable = CookiesDatabase::isDurable(partialCookie);
+
+    // Only delete durable cookies if directed.
+    if (deleteDurableCookies || !isDurable)
     {
-        // Store the cookie to delete if it has the same identifier as the partial cookie.
-        if (cookie.hasSameIdentifier(partialCookie))
-            cookieToDelete = cookie;
+        // Search for the partial cookie in the cookie list.
+        for (QNetworkCookie cookie : *cookieListPointer)
+        {
+            // Store the cookie to delete if it has the same identifier as the partial cookie.
+            if (cookie.hasSameIdentifier(partialCookie))
+                cookieToDelete = cookie;
+        }
+
+        // Remove the cookie from the tree model.
+        treeModelPointer->removeRow(modelIndex.row(), modelIndex.parent());
+
+        // Delete the cookie from the cookie list and cookie store.
+        emit deleteCookie(cookieToDelete);
+
+        // Delete the cookie from the durable cookies database.
+        if (isDurable)
+            CookiesDatabase::deleteCookie(cookieToDelete);
     }
+}
 
-    // Remove the cookie from the tree view.
-    standardItemModelPointer->removeRow(modelIndex.row(), modelIndex.parent());
+void CookiesDialog::deleteDomain(const QModelIndex &modelIndex, const bool &deleteDurableCookies) const
+{
+    // Get the parent index.
+    QModelIndex parentIndex = modelIndex.parent();
 
-    // Delete the cookie from the cookie list and cookie store.
-    emit deleteCookie(cookieToDelete);
+    // Get the number of cookies in the domain.
+    int numberOfCookies = treeModelPointer->rowCount(modelIndex);
+
+    // Delete each child cookie, starting from the bottom.
+    for (int i = numberOfCookies; i > 0; --i)
+        deleteCookie(treeModelPointer->index(i-1, 0, modelIndex), deleteDurableCookies);
+
+    // Remove the domain if all the cookies have been deleted.
+    if (treeModelPointer->rowCount(modelIndex) == 0)
+        treeModelPointer->removeRow(modelIndex.row(), parentIndex);
 }
 
+
 void CookiesDialog::deleteCookieFromDialog(const QNetworkCookie &cookie) const
 {
     // Get the current model index.
-    QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex();
+    QModelIndex currentIndex = treeSelectionModelPointer->currentIndex();
 
     // Get the parent index.
     QModelIndex parentIndex = currentIndex.parent();
 
-    // Remove the cookie from the tree view.
-    standardItemModelPointer->removeRow(currentIndex.row(), parentIndex);
+    // Remove the cookie from the tree model.
+    treeModelPointer->removeRow(currentIndex.row(), parentIndex);
 
-    // Remove the domain from the tree view if its only cookie has been deleted.
-    if (standardItemModelPointer->rowCount(parentIndex) == 0)
-        standardItemModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
+    // Remove the domain from the tree model if its only cookie has been deleted.
+    if (treeModelPointer->rowCount(parentIndex) == 0)
+        treeModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
 
     // Delete the cookie from the cookie list and cookie store.
     emit deleteCookie(cookie);
@@ -519,7 +513,7 @@ void CookiesDialog::showAddCookieDialog() const
     addCookieDialogPointer->show();
 
     // Add the cookie if directed.
-    connect(addCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieFromDialog(QNetworkCookie)));
+    connect(addCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie, bool)), this, SLOT(addCookieFromDialog(QNetworkCookie, bool)));
 }
 
 void CookiesDialog::showDeleteAllMessageBox() const
@@ -536,6 +530,12 @@ void CookiesDialog::showDeleteAllMessageBox() const
     // Set the text.
     deleteAllCookiesMessageBox.setText(i18nc("Delete all cookies dialog text", "Delete all cookies?"));
 
+    // Create a delete durable cookies check box.
+    QCheckBox deleteDurableCookiesCheckBox(i18nc("Delete durable cookies check box", "Delete even if durable"));
+
+    // Add the check box to the dialog.
+    deleteAllCookiesMessageBox.setCheckBox(&deleteDurableCookiesCheckBox);
+
     // Set the standard buttons.
     deleteAllCookiesMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
 
@@ -548,27 +548,43 @@ void CookiesDialog::showDeleteAllMessageBox() const
     // Delete all cookies if instructed.
     if (returnValue == QMessageBox::Yes)
     {
-        // Delete all the cookies.
-        emit deleteAllCookies();
+        // Only delete durable cookies if requested.
+        if (deleteDurableCookiesCheckBox.isChecked())  // Delete everything.
+        {
+            // Delete all the cookies.
+            emit deleteAllCookies();
+
+            // Clear the tree model.
+            treeModelPointer->clear();
+
+            // Delete the durable cookies from the database.
+            CookiesDatabase::deleteAllCookies();
+
+            // Update the UI.
+            updateUi();
+        }
+        else  // Only delete cookies that are not durable.
+        {
+            // Get the root model index.
+            QModelIndex rootIndex = treeModelPointer->invisibleRootItem()->index();
 
-        // Clear the standard item model.
-        standardItemModelPointer->clear();
+            // Get the number of domains.
+            int numberOfDomains = treeModelPointer->rowCount(rootIndex);
 
-        // Update the UI.
-        updateUi();
+            // Delete each domain, starting from the bottom.
+            for (int i = numberOfDomains; i > 0; --i)
+                deleteDomain(treeModelPointer->index(i - 1, 0, rootIndex), deleteDurableCookiesCheckBox.isChecked());
+        }
     }
 }
 
 void CookiesDialog::showDeleteCookieMessageBox() const
 {
     // Get the current model index.
-    QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex();
-
-    // Get the parent model index.
-    QModelIndex parentIndex = currentIndex.parent();
+    QModelIndex currentIndex = treeSelectionModelPointer->currentIndex();
 
     // Determine if a domain is selected.
-    bool isDomain = standardItemModelPointer->hasChildren(currentIndex);
+    bool isDomain = treeModelPointer->hasChildren(currentIndex);
 
     // Instantiate a delete cookie message box.
     QMessageBox deleteCookieMessageBox;
@@ -576,26 +592,35 @@ void CookiesDialog::showDeleteCookieMessageBox() const
     // Set the icon.
     deleteCookieMessageBox.setIcon(QMessageBox::Warning);
 
-    if (isDomain)
+    // Create a delete durable cookies check box.
+    QCheckBox deleteDurableCookiesCheckBox(i18nc("Delete durable cookies check box", "Delete even if durable"));
+
+    if (isDomain)  // A domain is selected.
     {
         // Get the number of cookies.
-        int numberOfCookiesToDelete = standardItemModelPointer->rowCount(currentIndex);
+        int numberOfCookiesToDelete = treeModelPointer->rowCount(currentIndex);
 
         // Set the window title.
-        deleteCookieMessageBox.setWindowTitle(i18nc("Delete cookies dialog title", "Delete %1 Cookies", numberOfCookiesToDelete));
+        deleteCookieMessageBox.setWindowTitle(i18ncp("Delete cookies dialog title", "Delete %1 Cookie", "Delete 1% Cookies", numberOfCookiesToDelete));
 
         // Set the text.
-        deleteCookieMessageBox.setText(i18nc("Delete cookies dialog text", "Delete %1 cookies?", numberOfCookiesToDelete));
+        deleteCookieMessageBox.setText(i18ncp("Delete cookies dialog text", "Delete %1 cookie?", "Delete %1 cookies?", numberOfCookiesToDelete));
     }
-    else
+    else  // A single cookie is selected.
     {
         // Set the window title.
         deleteCookieMessageBox.setWindowTitle(i18nc("Delete cookie dialog title", "Delete 1 Cookie"));
 
         // Set the text.
         deleteCookieMessageBox.setText(i18nc("Delete cookie dialog text", "Delete 1 cookie?"));
+
+        // Check the box.
+        deleteDurableCookiesCheckBox.setChecked(true);
     }
 
+    // Add the check box to the dialog.
+    deleteCookieMessageBox.setCheckBox(&deleteDurableCookiesCheckBox);
+
     // Set the standard buttons.
     deleteCookieMessageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
 
@@ -611,27 +636,20 @@ void CookiesDialog::showDeleteCookieMessageBox() const
         // Delete the cookies according to the selection.
         if (isDomain)  // A domain is selected.
         {
-            // Get the number of cookies.
-            int numberOfCookies = standardItemModelPointer->rowCount(currentIndex);
-
-            // Delete each child cookie.
-            for (int i = 0; i < numberOfCookies; ++i)
-            {
-                // Delete the cookie for the first child.  Once this is deleted, the second child will become the first child.
-                deleteCookie(standardItemModelPointer->index(0, 0, currentIndex));
-            }
-
-            // Delete the domain from the tree view.
-            standardItemModelPointer->removeRow(currentIndex.row(), parentIndex);
+            // Delete the domain.
+            deleteDomain(currentIndex, deleteDurableCookiesCheckBox.isChecked());
         }
         else  // A single cookie is selected.
         {
+            // Get the parent model index.
+            QModelIndex parentIndex = currentIndex.parent();
+
             // Delete the cookie.
-            deleteCookie(currentIndex);
+            deleteCookie(currentIndex, deleteDurableCookiesCheckBox.isChecked());
 
             // Remove the domain row if its only cookie has been deleted.
-            if (standardItemModelPointer->rowCount(parentIndex) == 0)
-                standardItemModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
+            if (treeModelPointer->rowCount(parentIndex) == 0)
+                treeModelPointer->removeRow(parentIndex.row(), parentIndex.parent());
         }
     }
 }
@@ -639,7 +657,7 @@ void CookiesDialog::showDeleteCookieMessageBox() const
 void CookiesDialog::showEditCookieDialog() const
 {
     // Get the current model index.
-    QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex();
+    QModelIndex currentIndex = treeSelectionModelPointer->currentIndex();
 
     // Create a partial cookie.
     QNetworkCookie partialCookie;
@@ -647,7 +665,7 @@ void CookiesDialog::showEditCookieDialog() const
     // Populate the partial cookie from the current model index.
     partialCookie.setDomain(currentIndex.parent().siblingAtColumn(0).data().toString());
     partialCookie.setName(currentIndex.siblingAtColumn(0).data().toString().toUtf8());
-    partialCookie.setPath(currentIndex.siblingAtColumn(1).data().toString());
+    partialCookie.setPath(currentIndex.siblingAtColumn(2).data().toString());
 
     // Create a cookie to edit.
     QNetworkCookie cookieToEdit;
@@ -661,33 +679,33 @@ void CookiesDialog::showEditCookieDialog() const
     }
 
     // Instantiate an edit cookie dialog.
-    QDialog *editCookieDialogPointer = new AddOrEditCookieDialog(AddOrEditCookieDialog::EditCookie, &cookieToEdit);
+    QDialog *editCookieDialogPointer = new AddOrEditCookieDialog(AddOrEditCookieDialog::EditCookie, &cookieToEdit, currentIndex.siblingAtColumn(1).data().toString() == i18n("yes"));
 
     // Show the dialog.
     editCookieDialogPointer->show();
 
     // Process cookie events.
-    connect(editCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie)), this, SLOT(addCookieFromDialog(QNetworkCookie)));
+    connect(editCookieDialogPointer, SIGNAL(addCookie(QNetworkCookie, bool)), this, SLOT(addCookieFromDialog(QNetworkCookie, bool)));
     connect(editCookieDialogPointer, SIGNAL(deleteCookie(QNetworkCookie)), this, SLOT(deleteCookieFromDialog(QNetworkCookie)));
 }
 
 void CookiesDialog::updateUi() const
 {
     // Get the current index of the first column.
-    QModelIndex currentIndex = treeViewSelectionModelPointer->currentIndex().siblingAtColumn(0);
+    QModelIndex currentIndex = treeSelectionModelPointer->currentIndex().siblingAtColumn(0);
 
     // Set the status of the buttons.
-    editCookieButtonPointer->setEnabled(treeViewSelectionModelPointer->hasSelection() && !standardItemModelPointer->hasChildren(currentIndex));
-    deleteCookieButtonPointer->setEnabled(treeViewSelectionModelPointer->hasSelection());;
-    deleteAllButtonPointer->setEnabled(standardItemModelPointer->hasChildren(standardItemModelPointer->invisibleRootItem()->index()));
+    editCookieButtonPointer->setEnabled(treeSelectionModelPointer->hasSelection() && !treeModelPointer->hasChildren(currentIndex));
+    deleteCookieButtonPointer->setEnabled(treeSelectionModelPointer->hasSelection());;
+    deleteAllButtonPointer->setEnabled(treeModelPointer->hasChildren(treeModelPointer->invisibleRootItem()->index()));
 
     // Update the delete cookie button text.
     if (deleteCookieButtonPointer->isEnabled())  // The button is enabled.
     {
-        if (standardItemModelPointer->hasChildren(currentIndex))  // A domain is selected.
+        if (treeModelPointer->hasChildren(currentIndex))  // A domain is selected.
         {
             // Update the button text.
-            deleteCookieButtonPointer->setText(i18nc("Delete cookies button.", "&Delete %1 cookies", standardItemModelPointer->rowCount(currentIndex)));
+            deleteCookieButtonPointer->setText(i18ncp("Delete cookies button.", "&Delete %1 cookie", "&Delete %1 cookies", treeModelPointer->rowCount(currentIndex)));
         }
         else  // A single cookie is selected.
         {