Home | History | Annotate | Download | only in Api
      1 /*
      2     Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      3 
      4     This library is free software; you can redistribute it and/or
      5     modify it under the terms of the GNU Library General Public
      6     License as published by the Free Software Foundation; either
      7     version 2 of the License, or (at your option) any later version.
      8 
      9     This library is distributed in the hope that it will be useful,
     10     but WITHOUT ANY WARRANTY; without even the implied warranty of
     11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12     Library General Public License for more details.
     13 
     14     You should have received a copy of the GNU Library General Public License
     15     along with this library; see the file COPYING.LIB.  If not, write to
     16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17     Boston, MA 02110-1301, USA.
     18 */
     19 
     20 #include "config.h"
     21 #include "qwebhistory.h"
     22 #include "qwebhistory_p.h"
     23 #include "qwebframe_p.h"
     24 
     25 #include "BackForwardListImpl.h"
     26 #include "IconDatabaseBase.h"
     27 #include "Image.h"
     28 #include "IntSize.h"
     29 #include "KURL.h"
     30 #include "Page.h"
     31 #include "PageGroup.h"
     32 #include "PlatformString.h"
     33 
     34 #include <QSharedData>
     35 #include <QDebug>
     36 
     37 enum {
     38     InitialHistoryVersion = 1,
     39     DefaultHistoryVersion = InitialHistoryVersion
     40 };
     41 
     42 /*!
     43   \class QWebHistoryItem
     44   \since 4.4
     45   \brief The QWebHistoryItem class represents one item in the history of a QWebPage
     46 
     47   \inmodule QtWebKit
     48 
     49   Each QWebHistoryItem instance represents an entry in the history stack of a Web page,
     50   containing information about the page, its location, and when it was last visited.
     51 
     52   The following table shows the properties of the page held by the history item, and
     53   the functions used to access them.
     54 
     55   \table
     56   \header \o Function      \o Description
     57   \row    \o title()       \o The page title.
     58   \row    \o url()         \o The location of the page.
     59   \row    \o originalUrl() \o The URL used to access the page.
     60   \row    \o lastVisited() \o The date and time of the user's last visit to the page.
     61   \row    \o icon()        \o The icon associated with the page that was provided by the server.
     62   \row    \o userData()    \o The user specific data that was stored with the history item.
     63   \endtable
     64 
     65   \note QWebHistoryItem objects are value based, but \e{explicitly shared}. Changing
     66   a QWebHistoryItem instance by calling setUserData() will change all copies of that
     67   instance.
     68 
     69   \sa QWebHistory, QWebPage::history(), QWebHistoryInterface
     70 */
     71 
     72 /*!
     73   Constructs a history item from \a other. The new item and \a other
     74   will share their data, and modifying either this item or \a other will
     75   modify both instances.
     76 */
     77 QWebHistoryItem::QWebHistoryItem(const QWebHistoryItem &other)
     78     : d(other.d)
     79 {
     80 }
     81 
     82 /*!
     83   Assigns the \a other history item to this. This item and \a other
     84   will share their data, and modifying either this item or \a other will
     85   modify both instances.
     86 */
     87 QWebHistoryItem &QWebHistoryItem::operator=(const QWebHistoryItem &other)
     88 {
     89     d = other.d;
     90     return *this;
     91 }
     92 
     93 /*!
     94   Destroys the history item.
     95 */
     96 QWebHistoryItem::~QWebHistoryItem()
     97 {
     98 }
     99 
    100 /*!
    101  Returns the original URL associated with the history item.
    102 
    103  \sa url()
    104 */
    105 QUrl QWebHistoryItem::originalUrl() const
    106 {
    107     if (d->item)
    108         return d->item->originalURL();
    109     return QUrl();
    110 }
    111 
    112 
    113 /*!
    114  Returns the URL associated with the history item.
    115 
    116  \sa originalUrl(), title(), lastVisited()
    117 */
    118 QUrl QWebHistoryItem::url() const
    119 {
    120     if (d->item)
    121         return d->item->url();
    122     return QUrl();
    123 }
    124 
    125 
    126 /*!
    127  Returns the title of the page associated with the history item.
    128 
    129  \sa icon(), url(), lastVisited()
    130 */
    131 QString QWebHistoryItem::title() const
    132 {
    133     if (d->item)
    134         return d->item->title();
    135     return QString();
    136 }
    137 
    138 
    139 /*!
    140  Returns the date and time that the page associated with the item was last visited.
    141 
    142  \sa title(), icon(), url()
    143 */
    144 QDateTime QWebHistoryItem::lastVisited() const
    145 {
    146     //FIXME : this will be wrong unless we correctly set lastVisitedTime ourselves
    147     if (d->item)
    148         return QDateTime::fromTime_t((uint)d->item->lastVisitedTime());
    149     return QDateTime();
    150 }
    151 
    152 
    153 /*!
    154  Returns the icon associated with the history item.
    155 
    156  \sa title(), url(), lastVisited()
    157 */
    158 QIcon QWebHistoryItem::icon() const
    159 {
    160     if (d->item)
    161         return *WebCore::iconDatabase().synchronousIconForPageURL(d->item->url(), WebCore::IntSize(16, 16))->nativeImageForCurrentFrame();
    162 
    163     return QIcon();
    164 }
    165 
    166 /*!
    167   \since 4.5
    168   Returns the user specific data that was stored with the history item.
    169 
    170   \sa setUserData()
    171 */
    172 QVariant QWebHistoryItem::userData() const
    173 {
    174     if (d->item)
    175         return d->item->userData();
    176     return QVariant();
    177 }
    178 
    179 /*!
    180   \since 4.5
    181 
    182  Stores user specific data \a userData with the history item.
    183 
    184  \note All copies of this item will be modified.
    185 
    186  \sa userData()
    187 */
    188 void QWebHistoryItem::setUserData(const QVariant& userData)
    189 {
    190     if (d->item)
    191         d->item->setUserData(userData);
    192 }
    193 
    194 /*!*
    195   \internal
    196 */
    197 QWebHistoryItem::QWebHistoryItem(QWebHistoryItemPrivate *priv)
    198 {
    199     d = priv;
    200 }
    201 
    202 /*!
    203     \since 4.5
    204     Returns whether this is a valid history item.
    205 */
    206 bool QWebHistoryItem::isValid() const
    207 {
    208     return d->item;
    209 }
    210 
    211 /*!
    212   \class QWebHistory
    213   \since 4.4
    214   \brief The QWebHistory class represents the history of a QWebPage
    215 
    216   \inmodule QtWebKit
    217 
    218   Each QWebPage instance contains a history of visited pages that can be accessed
    219   by QWebPage::history(). QWebHistory represents this history and makes it possible
    220   to navigate it.
    221 
    222   The history uses the concept of a \e{current item}, dividing the pages visited
    223   into those that can be visited by navigating \e back and \e forward using the
    224   back() and forward() functions. The current item can be obtained by calling
    225   currentItem(), and an arbitrary item in the history can be made the current
    226   item by passing it to goToItem().
    227 
    228   A list of items describing the pages that can be visited by going back can be
    229   obtained by calling the backItems() function; similarly, items describing the
    230   pages ahead of the current page can be obtained with the forwardItems() function.
    231   The total list of items is obtained with the items() function.
    232 
    233   Just as with containers, functions are available to examine the history in terms
    234   of a list. Arbitrary items in the history can be obtained with itemAt(), the total
    235   number of items is given by count(), and the history can be cleared with the
    236   clear() function.
    237 
    238   QWebHistory's state can be saved to a QDataStream using the >> operator and loaded
    239   by using the << operator.
    240 
    241   \sa QWebHistoryItem, QWebHistoryInterface, QWebPage
    242 */
    243 
    244 
    245 QWebHistory::QWebHistory()
    246     : d(0)
    247 {
    248 }
    249 
    250 QWebHistory::~QWebHistory()
    251 {
    252     delete d;
    253 }
    254 
    255 /*!
    256   Clears the history.
    257 
    258   \sa count(), items()
    259 */
    260 void QWebHistory::clear()
    261 {
    262     //shortcut to private BackForwardListImpl
    263     WebCore::BackForwardListImpl* lst = d->lst;
    264 
    265     //clear visited links
    266     WebCore::Page* page = static_cast<WebCore::BackForwardListImpl*>(lst)->page();
    267     if (page && page->groupPtr())
    268         page->groupPtr()->removeVisitedLinks();
    269 
    270     //if count() == 0 then just return
    271     if (!lst->entries().size())
    272         return;
    273 
    274     RefPtr<WebCore::HistoryItem> current = lst->currentItem();
    275     int capacity = lst->capacity();
    276     lst->setCapacity(0);
    277 
    278     lst->setCapacity(capacity);   //revert capacity
    279     lst->addItem(current.get());  //insert old current item
    280     lst->goToItem(current.get()); //and set it as current again
    281 
    282     d->page()->updateNavigationActions();
    283 }
    284 
    285 /*!
    286   Returns a list of all items currently in the history.
    287 
    288   \sa count(), clear()
    289 */
    290 QList<QWebHistoryItem> QWebHistory::items() const
    291 {
    292     const WebCore::HistoryItemVector &items = d->lst->entries();
    293 
    294     QList<QWebHistoryItem> ret;
    295     for (unsigned i = 0; i < items.size(); ++i) {
    296         QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get());
    297         ret.append(QWebHistoryItem(priv));
    298     }
    299     return ret;
    300 }
    301 
    302 /*!
    303   Returns the list of items in the backwards history list.
    304   At most \a maxItems entries are returned.
    305 
    306   \sa forwardItems()
    307 */
    308 QList<QWebHistoryItem> QWebHistory::backItems(int maxItems) const
    309 {
    310     WebCore::HistoryItemVector items(maxItems);
    311     d->lst->backListWithLimit(maxItems, items);
    312 
    313     QList<QWebHistoryItem> ret;
    314     for (unsigned i = 0; i < items.size(); ++i) {
    315         QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get());
    316         ret.append(QWebHistoryItem(priv));
    317     }
    318     return ret;
    319 }
    320 
    321 /*!
    322   Returns the list of items in the forward history list.
    323   At most \a maxItems entries are returned.
    324 
    325   \sa backItems()
    326 */
    327 QList<QWebHistoryItem> QWebHistory::forwardItems(int maxItems) const
    328 {
    329     WebCore::HistoryItemVector items(maxItems);
    330     d->lst->forwardListWithLimit(maxItems, items);
    331 
    332     QList<QWebHistoryItem> ret;
    333     for (unsigned i = 0; i < items.size(); ++i) {
    334         QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(items[i].get());
    335         ret.append(QWebHistoryItem(priv));
    336     }
    337     return ret;
    338 }
    339 
    340 /*!
    341   Returns true if there is an item preceding the current item in the history;
    342   otherwise returns false.
    343 
    344   \sa canGoForward()
    345 */
    346 bool QWebHistory::canGoBack() const
    347 {
    348     return d->lst->backListCount() > 0;
    349 }
    350 
    351 /*!
    352   Returns true if we have an item to go forward to; otherwise returns false.
    353 
    354   \sa canGoBack()
    355 */
    356 bool QWebHistory::canGoForward() const
    357 {
    358     return d->lst->forwardListCount() > 0;
    359 }
    360 
    361 /*!
    362   Set the current item to be the previous item in the history and goes to the
    363   corresponding page; i.e., goes back one history item.
    364 
    365   \sa forward(), goToItem()
    366 */
    367 void QWebHistory::back()
    368 {
    369     if (canGoBack()) {
    370         WebCore::Page* page = static_cast<WebCore::BackForwardListImpl*>(d->lst)->page();
    371         page->goToItem(d->lst->backItem(), WebCore::FrameLoadTypeIndexedBackForward);
    372     }
    373 }
    374 
    375 /*!
    376   Sets the current item to be the next item in the history and goes to the
    377   corresponding page; i.e., goes forward one history item.
    378 
    379   \sa back(), goToItem()
    380 */
    381 void QWebHistory::forward()
    382 {
    383     if (canGoForward()) {
    384         WebCore::Page* page = static_cast<WebCore::BackForwardListImpl*>(d->lst)->page();
    385         page->goToItem(d->lst->forwardItem(), WebCore::FrameLoadTypeIndexedBackForward);
    386     }
    387 }
    388 
    389 /*!
    390   Sets the current item to be the specified \a item in the history and goes to the page.
    391 
    392   \sa back(), forward()
    393 */
    394 void QWebHistory::goToItem(const QWebHistoryItem &item)
    395 {
    396     WebCore::Page* page = static_cast<WebCore::BackForwardListImpl*>(d->lst)->page();
    397     page->goToItem(item.d->item, WebCore::FrameLoadTypeIndexedBackForward);
    398 }
    399 
    400 /*!
    401   Returns the item before the current item in the history.
    402 */
    403 QWebHistoryItem QWebHistory::backItem() const
    404 {
    405     WebCore::HistoryItem *i = d->lst->backItem();
    406     QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i);
    407     return QWebHistoryItem(priv);
    408 }
    409 
    410 /*!
    411   Returns the current item in the history.
    412 */
    413 QWebHistoryItem QWebHistory::currentItem() const
    414 {
    415     WebCore::HistoryItem *i = d->lst->currentItem();
    416     QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i);
    417     return QWebHistoryItem(priv);
    418 }
    419 
    420 /*!
    421   Returns the item after the current item in the history.
    422 */
    423 QWebHistoryItem QWebHistory::forwardItem() const
    424 {
    425     WebCore::HistoryItem *i = d->lst->forwardItem();
    426     QWebHistoryItemPrivate *priv = new QWebHistoryItemPrivate(i);
    427     return QWebHistoryItem(priv);
    428 }
    429 
    430 /*!
    431   \since 4.5
    432   Returns the index of the current item in history.
    433 */
    434 int QWebHistory::currentItemIndex() const
    435 {
    436     return d->lst->backListCount();
    437 }
    438 
    439 /*!
    440   Returns the item at index \a i in the history.
    441 */
    442 QWebHistoryItem QWebHistory::itemAt(int i) const
    443 {
    444     QWebHistoryItemPrivate *priv;
    445     if (i < 0 || i >= count())
    446         priv = new QWebHistoryItemPrivate(0);
    447     else {
    448         WebCore::HistoryItem *item = d->lst->entries()[i].get();
    449         priv = new QWebHistoryItemPrivate(item);
    450     }
    451     return QWebHistoryItem(priv);
    452 }
    453 
    454 /*!
    455     Returns the total number of items in the history.
    456 */
    457 int QWebHistory::count() const
    458 {
    459     return d->lst->entries().size();
    460 }
    461 
    462 /*!
    463   \since 4.5
    464   Returns the maximum number of items in the history.
    465 
    466   \sa setMaximumItemCount()
    467 */
    468 int QWebHistory::maximumItemCount() const
    469 {
    470     return d->lst->capacity();
    471 }
    472 
    473 /*!
    474   \since 4.5
    475   Sets the maximum number of items in the history to \a count.
    476 
    477   \sa maximumItemCount()
    478 */
    479 void QWebHistory::setMaximumItemCount(int count)
    480 {
    481     d->lst->setCapacity(count);
    482 }
    483 
    484 /*!
    485   \since 4.6
    486   \fn QDataStream& operator<<(QDataStream& stream, const QWebHistory& history)
    487   \relates QWebHistory
    488 
    489   \brief The operator<< function streams a history into a data stream.
    490 
    491   It saves the \a history into the specified \a stream.
    492 */
    493 
    494 QDataStream& operator<<(QDataStream& target, const QWebHistory& history)
    495 {
    496     QWebHistoryPrivate* d = history.d;
    497 
    498     int version = DefaultHistoryVersion;
    499 
    500     target << version;
    501     target << history.count() << history.currentItemIndex();
    502 
    503     const WebCore::HistoryItemVector &items = d->lst->entries();
    504     for (unsigned i = 0; i < items.size(); i++)
    505         items[i].get()->saveState(target, version);
    506 
    507     return target;
    508 }
    509 
    510 /*!
    511   \fn QDataStream& operator>>(QDataStream& stream, QWebHistory& history)
    512   \relates QWebHistory
    513   \since 4.6
    514 
    515   \brief The operator>> function loads a history from a data stream.
    516 
    517   Loads a QWebHistory from the specified \a stream into the given \a history.
    518 */
    519 
    520 QDataStream& operator>>(QDataStream& source, QWebHistory& history)
    521 {
    522     QWebHistoryPrivate* d = history.d;
    523 
    524     int version;
    525 
    526     source >> version;
    527 
    528     if (version == 1) {
    529         int count;
    530         int currentIndex;
    531         source >> count >> currentIndex;
    532 
    533         history.clear();
    534         // only if there are elements
    535         if (count) {
    536             // after clear() is new clear HistoryItem (at the end we had to remove it)
    537             WebCore::HistoryItem* nullItem = d->lst->currentItem();
    538             for (int i = 0; i < count; i++) {
    539                 WTF::PassRefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create();
    540                 item->restoreState(source, version);
    541                 d->lst->addItem(item);
    542             }
    543             d->lst->removeItem(nullItem);
    544             // Update the HistoryController.
    545             static_cast<WebCore::BackForwardListImpl*>(history.d->lst)->page()->mainFrame()->loader()->history()->setCurrentItem(history.d->lst->entries()[currentIndex].get());
    546             history.goToItem(history.itemAt(currentIndex));
    547         }
    548     }
    549 
    550     d->page()->updateNavigationActions();
    551 
    552     return source;
    553 }
    554 
    555 QWebPagePrivate* QWebHistoryPrivate::page()
    556 {
    557     return QWebFramePrivate::kit(static_cast<WebCore::BackForwardListImpl*>(lst)->page()->mainFrame())->page()->handle();
    558 }
    559 
    560 WebCore::HistoryItem* QWebHistoryItemPrivate::core(const QWebHistoryItem* q)
    561 {
    562     return q->d->item;
    563 }
    564