summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/WebCore/ChangeLog41
-rw-r--r--Source/WebCore/history/HistoryItem.h2
-rw-r--r--Source/WebCore/history/qt/HistoryItemQt.cpp265
-rw-r--r--Source/WebKit/qt/Api/qwebhistory.cpp54
-rw-r--r--Source/WebKit/qt/ChangeLog21
-rw-r--r--Source/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp112
6 files changed, 369 insertions, 126 deletions
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 3157b7a39..0b3e57c34 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,5 +1,46 @@
2013-01-16 Jocelyn Turcotte <jocelyn.turcotte@digia.com>
+ [Qt] Use the shared HistoryItem serialization for QWebHistory
+ https://bugs.webkit.org/show_bug.cgi?id=106671
+
+ Reviewed by Allan Sandfeld Jensen.
+
+ This allows a few things missing from the previous serialization code
+ to function while using commonly maintained code:
+ - The itemSequenceNumber and documentSequenceNumber that were needed
+ to properly restore same-document navigations
+ - The form data
+ - The navigation hierarchy mapping the frame tree
+
+ * history/HistoryItem.h:
+ (HistoryItem):
+ * history/qt/HistoryItemQt.cpp:
+ (QDataStreamCoder):
+ (WebCore):
+ (WebCore::QDataStreamCoder::QDataStreamCoder):
+ (WebCore::QDataStreamCoder::encodeBytes):
+ (WebCore::QDataStreamCoder::encodeBool):
+ (WebCore::QDataStreamCoder::encodeUInt32):
+ (WebCore::QDataStreamCoder::encodeUInt64):
+ (WebCore::QDataStreamCoder::encodeInt32):
+ (WebCore::QDataStreamCoder::encodeInt64):
+ (WebCore::QDataStreamCoder::encodeFloat):
+ (WebCore::QDataStreamCoder::encodeDouble):
+ (WebCore::QDataStreamCoder::encodeString):
+ (WebCore::QDataStreamCoder::decodeBytes):
+ (WebCore::QDataStreamCoder::decodeBool):
+ (WebCore::QDataStreamCoder::decodeUInt32):
+ (WebCore::QDataStreamCoder::decodeUInt64):
+ (WebCore::QDataStreamCoder::decodeInt32):
+ (WebCore::QDataStreamCoder::decodeInt64):
+ (WebCore::QDataStreamCoder::decodeFloat):
+ (WebCore::QDataStreamCoder::decodeDouble):
+ (WebCore::QDataStreamCoder::decodeString):
+ (WebCore::HistoryItem::restoreState):
+ (WebCore::WebCore::HistoryItem::saveState):
+
+2013-01-16 Jocelyn Turcotte <jocelyn.turcotte@digia.com>
+
[Qt] Crash in WebCore::CachedFrame::destroy
https://bugs.webkit.org/show_bug.cgi?id=104525
diff --git a/Source/WebCore/history/HistoryItem.h b/Source/WebCore/history/HistoryItem.h
index 2472aa3fa..79c43c939 100644
--- a/Source/WebCore/history/HistoryItem.h
+++ b/Source/WebCore/history/HistoryItem.h
@@ -201,7 +201,7 @@ public:
QVariant userData() const { return m_userData; }
void setUserData(const QVariant& userData) { m_userData = userData; }
- bool restoreState(QDataStream& buffer, int version);
+ static PassRefPtr<HistoryItem> restoreState(QDataStream& buffer, int version);
QDataStream& saveState(QDataStream& out, int version) const;
#endif
diff --git a/Source/WebCore/history/qt/HistoryItemQt.cpp b/Source/WebCore/history/qt/HistoryItemQt.cpp
index 5528eeb0c..5a54516f3 100644
--- a/Source/WebCore/history/qt/HistoryItemQt.cpp
+++ b/Source/WebCore/history/qt/HistoryItemQt.cpp
@@ -21,22 +21,13 @@
#include "HistoryItem.h"
#include "FormData.h"
+#include <wtf/Decoder.h>
+#include <wtf/Encoder.h>
#include <wtf/text/CString.h>
-static QDataStream& operator<<(QDataStream& stream, const WebCore::IntPoint& point)
-{
- stream << point.x() << point.y();
- return stream;
-}
+using namespace WTF;
-static QDataStream& operator>>(QDataStream& stream, WebCore::IntPoint& point)
-{
- int x, y;
- stream >> x >> y;
- point.setX(x);
- point.setY(y);
- return stream;
-}
+namespace WebCore {
static QDataStream& operator<<(QDataStream& stream, const String& str)
{
@@ -54,117 +45,190 @@ static QDataStream& operator>>(QDataStream& stream, String& str)
return stream;
}
-template<typename T>
-QDataStream& operator<<(QDataStream& stream, const Vector<T>& data)
+class QDataStreamCoder : public WTF::Encoder, public WTF::Decoder {
+public:
+ QDataStreamCoder(QDataStream&);
+
+private:
+ virtual void encodeBytes(const uint8_t*, size_t);
+ virtual void encodeBool(bool);
+ virtual void encodeUInt32(uint32_t);
+ virtual void encodeUInt64(uint64_t);
+ virtual void encodeInt32(int32_t);
+ virtual void encodeInt64(int64_t);
+ virtual void encodeFloat(float);
+ virtual void encodeDouble(double);
+ virtual void encodeString(const String&);
+
+ virtual bool decodeBytes(Vector<uint8_t>&);
+ virtual bool decodeBool(bool&);
+ virtual bool decodeUInt32(uint32_t&);
+ virtual bool decodeUInt64(uint64_t&);
+ virtual bool decodeInt32(int32_t&);
+ virtual bool decodeInt64(int64_t&);
+ virtual bool decodeFloat(float&);
+ virtual bool decodeDouble(double&);
+ virtual bool decodeString(String&);
+
+ QDataStream& m_stream;
+};
+
+QDataStreamCoder::QDataStreamCoder(QDataStream& stream)
+ : m_stream(stream)
{
- stream << qint64(data.size());
- foreach (const T& i, data)
- stream << i;
- return stream;
}
-template<typename T>
-QDataStream& operator>>(QDataStream& stream, Vector<T>& data)
+void QDataStreamCoder::encodeBytes(const uint8_t* bytes, size_t size)
{
- data.clear();
+ m_stream << qint64(size);
+ for (; size > 0; --size)
+ m_stream << bytes++;
+}
+
+void QDataStreamCoder::encodeBool(bool value)
+{
+ m_stream << value;
+}
+
+void QDataStreamCoder::encodeUInt32(uint32_t value)
+{
+ m_stream << value;
+}
+
+void QDataStreamCoder::encodeUInt64(uint64_t value)
+{
+ m_stream << static_cast<quint64>(value);
+}
+
+void QDataStreamCoder::encodeInt32(int32_t value)
+{
+ m_stream << value;
+}
+
+void QDataStreamCoder::encodeInt64(int64_t value)
+{
+ m_stream << static_cast<qint64>(value);
+}
+
+void QDataStreamCoder::encodeFloat(float value)
+{
+ m_stream << value;
+}
+
+void QDataStreamCoder::encodeDouble(double value)
+{
+ m_stream << value;
+}
+
+void QDataStreamCoder::encodeString(const String& value)
+{
+ m_stream << value;
+}
+
+bool QDataStreamCoder::decodeBytes(Vector<uint8_t>& out)
+{
+ out.clear();
qint64 count;
- T item;
- stream >> count;
- data.reserveCapacity(count);
+ uint8_t byte;
+ m_stream >> count;
+ out.reserveCapacity(count);
for (qint64 i = 0; i < count; ++i) {
- stream >> item;
- data.append(item);
+ m_stream >> byte;
+ out.append(byte);
}
- return stream;
+ return m_stream.status() == QDataStream::Ok;
}
-bool WebCore::HistoryItem::restoreState(QDataStream& in, int version)
+bool QDataStreamCoder::decodeBool(bool& out)
{
- // we only support version 1 for now
+ m_stream >> out;
+ return m_stream.status() == QDataStream::Ok;
+}
- if (version != 1)
- return false;
+bool QDataStreamCoder::decodeUInt32(uint32_t& out)
+{
+ m_stream >> out;
+ return m_stream.status() == QDataStream::Ok;
+}
- WTF::String url;
- WTF::String title;
- WTF::String altTitle;
- WTF::String orginalUrl;
- WTF::String referrer;
- WTF::String target;
- WTF::String parrent;
- double lastVisitedTime;
- bool validUserData;
- WTF::String parent;
- bool lastVisitWasHTTPNonGet;
- bool lastVisitWasFailure;
- bool isTargetItem;
- int visitCount;
- WTF::Vector<WTF::String> documentState;
- WebCore::IntPoint scrollPoint;
- qreal pageScaleFactor;
- WTF::Vector<int> weeklyVisitCounts;
- WTF::Vector<int> dailyVisitCounts;
- // bool loadFormdata;
- // WTF::String formContentType;
- // WTF::Vector<char> formData;
-
- in >> url >> title >> altTitle >> lastVisitedTime >> orginalUrl >> referrer >> target >> parent;
- in >> lastVisitWasHTTPNonGet >> lastVisitWasFailure >> isTargetItem >> visitCount >> documentState;
- in >> scrollPoint >> pageScaleFactor >> dailyVisitCounts >> weeklyVisitCounts;
- /*in >> loadFormdata;
- if (loadFormdata) {
- in >> formContentType >> formData;
- // direct assigned (!)
- m_formContentType = formContentType;
- m_formData = FormData::create(CString(formData));
- }*/
- // use setters
- adoptVisitCounts(dailyVisitCounts, weeklyVisitCounts);
- setScrollPoint(scrollPoint);
- setPageScaleFactor(pageScaleFactor);
- setDocumentState(documentState);
- setVisitCount(visitCount);
- setIsTargetItem(isTargetItem);
- setLastVisitWasFailure(lastVisitWasFailure);
- setLastVisitWasHTTPNonGet(lastVisitWasHTTPNonGet);
- setParent(parent);
- setTarget(target);
- setReferrer(referrer);
- setOriginalURLString(orginalUrl);
- setURLString(url);
- setLastVisitedTime(lastVisitedTime);
- setTitle(title);
- setAlternateTitle(altTitle);
+bool QDataStreamCoder::decodeUInt64(uint64_t& out)
+{
+ quint64 tmp;
+ m_stream >> tmp;
+ // quint64 is defined to "long long unsigned", incompatible with uint64_t defined as "long unsigned" on 64bits archs.
+ out = tmp;
+ return m_stream.status() == QDataStream::Ok;
+}
+
+bool QDataStreamCoder::decodeInt32(int32_t& out)
+{
+ m_stream >> out;
+ return m_stream.status() == QDataStream::Ok;
+}
+
+bool QDataStreamCoder::decodeInt64(int64_t& out)
+{
+ qint64 tmp;
+ m_stream >> tmp;
+ // qint64 is defined to "long long", incompatible with int64_t defined as "long" on 64bits archs.
+ out = tmp;
+ return m_stream.status() == QDataStream::Ok;
+}
+
+bool QDataStreamCoder::decodeFloat(float& out)
+{
+ m_stream >> out;
+ return m_stream.status() == QDataStream::Ok;
+}
+
+bool QDataStreamCoder::decodeDouble(double& out)
+{
+ m_stream >> out;
+ return m_stream.status() == QDataStream::Ok;
+}
+
+bool QDataStreamCoder::decodeString(String& out)
+{
+ m_stream >> out;
+ return m_stream.status() == QDataStream::Ok;
+}
+
+PassRefPtr<HistoryItem> HistoryItem::restoreState(QDataStream& in, int version)
+{
+ ASSERT(version == 2);
+
+ String url;
+ String title;
+ String originalURL;
+ in >> url >> title >> originalURL;
+
+ QDataStreamCoder decoder(in);
+ RefPtr<HistoryItem> item = decodeBackForwardTree(url, title, originalURL, decoder);
+ // decodeBackForwardTree has its own stream version. An incompatible input stream version will return null here.
+ if (!item)
+ return 0;
// at the end load userData
+ bool validUserData;
in >> validUserData;
if (validUserData) {
QVariant tmp;
in >> tmp;
- setUserData(tmp);
+ item->setUserData(tmp);
}
- return in.status() == QDataStream::Ok;
+ return item;
}
QDataStream& WebCore::HistoryItem::saveState(QDataStream& out, int version) const
{
- // we only support version 1 for now.
- if (version != 1)
- return out;
-
- out << urlString() << title() << alternateTitle() << lastVisitedTime();
- out << originalURLString() << referrer() << target() << parent();
- out << lastVisitWasHTTPNonGet() << lastVisitWasFailure() << isTargetItem();
- out << visitCount() << documentState() << scrollPoint();
- out << qreal(pageScaleFactor()) << dailyVisitCounts() << weeklyVisitCounts();
- /*if (m_formData) {
- out << true;
- out << formContentType();
- out << m_formData->flatten();
- } else {
- out << false;
- }*/
+ ASSERT(version == 2);
+
+ out << urlString() << title() << originalURLString();
+
+ QDataStreamCoder encoder(out);
+ encodeBackForwardTree(encoder);
+
// save user data
if (userData().isValid())
out << true << userData();
@@ -174,3 +238,4 @@ QDataStream& WebCore::HistoryItem::saveState(QDataStream& out, int version) cons
return out;
}
+} // namespace WebCore
diff --git a/Source/WebKit/qt/Api/qwebhistory.cpp b/Source/WebKit/qt/Api/qwebhistory.cpp
index a02083307..be0905eb7 100644
--- a/Source/WebKit/qt/Api/qwebhistory.cpp
+++ b/Source/WebKit/qt/Api/qwebhistory.cpp
@@ -35,10 +35,7 @@
#include <QSharedData>
#include <QDebug>
-enum {
- InitialHistoryVersion = 1,
- DefaultHistoryVersion = InitialHistoryVersion
-};
+static const int HistoryStreamVersion = 2;
/*!
\class QWebHistoryItem
@@ -496,7 +493,7 @@ QDataStream& operator<<(QDataStream& target, const QWebHistory& history)
{
QWebHistoryPrivate* d = history.d;
- int version = DefaultHistoryVersion;
+ int version = HistoryStreamVersion;
target << version;
target << history.count() << history.currentItemIndex();
@@ -521,29 +518,42 @@ QDataStream& operator<<(QDataStream& target, const QWebHistory& history)
QDataStream& operator>>(QDataStream& source, QWebHistory& history)
{
QWebHistoryPrivate* d = history.d;
+ // Clear first, to have the same behavior if our version doesn't match and if the HistoryItem's version doesn't.
+ history.clear();
+ // This version covers every field we serialize in qwebhistory.cpp and HistoryItemQt.cpp (like the HistoryItem::userData()).
+ // HistoryItem has its own version in the stream covering the work done in encodeBackForwardTree.
+ // If any of those two stream version changes, the effect should be the same and the QWebHistory should fail to restore.
int version;
-
source >> version;
+ if (version != HistoryStreamVersion) {
+ // We do not try to decode previous history stream versions.
+ // Make sure that our history is cleared and mark the rest of the stream as invalid.
+ ASSERT(history.count() == 1);
+ source.setStatus(QDataStream::ReadCorruptData);
+ return source;
+ }
- if (version == 1) {
- int count;
- int currentIndex;
- source >> count >> currentIndex;
-
- history.clear();
- // only if there are elements
- if (count) {
- // after clear() is new clear HistoryItem (at the end we had to remove it)
- WebCore::HistoryItem* nullItem = d->lst->currentItem();
- for (int i = 0; i < count; i++) {
- WTF::PassRefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create();
- item->restoreState(source, version);
- d->lst->addItem(item);
+ int count;
+ int currentIndex;
+ source >> count >> currentIndex;
+
+ // only if there are elements
+ if (count) {
+ // after clear() is new clear HistoryItem (at the end we had to remove it)
+ WebCore::HistoryItem* nullItem = d->lst->currentItem();
+ for (int i = 0; i < count; i++) {
+ WTF::RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::restoreState(source, version);
+ if (!item) {
+ // The HistoryItem internal version might have changed, do the same as when our own version change.
+ history.clear();
+ source.setStatus(QDataStream::ReadCorruptData);
+ return source;
}
- d->lst->removeItem(nullItem);
- history.goToItem(history.itemAt(currentIndex));
+ d->lst->addItem(item);
}
+ d->lst->removeItem(nullItem);
+ history.goToItem(history.itemAt(currentIndex));
}
d->page()->updateNavigationActions();
diff --git a/Source/WebKit/qt/ChangeLog b/Source/WebKit/qt/ChangeLog
index 291c43a24..012485d9a 100644
--- a/Source/WebKit/qt/ChangeLog
+++ b/Source/WebKit/qt/ChangeLog
@@ -1,5 +1,26 @@
2013-01-16 Jocelyn Turcotte <jocelyn.turcotte@digia.com>
+ [Qt] Use the shared HistoryItem serialization for QWebHistory
+ https://bugs.webkit.org/show_bug.cgi?id=106671
+
+ Reviewed by Allan Sandfeld Jensen.
+
+ Bump the serialization version and change the code to abort the
+ restore of a previous stream version rather than trying to keep the
+ support of restoring previous versions. This is mainly to simplify
+ things given that HistoryItem itself aborts in that case.
+
+ * Api/qwebhistory.cpp:
+ (operator<<):
+ (operator>>):
+ * tests/qwebhistory/tst_qwebhistory.cpp:
+ (tst_QWebHistory::serialize_2): Modify the test to cover same-document navigations.
+ (tst_QWebHistory::restoreIncompatibleVersion1): Add a previous version
+ hard-coded stream to verify that the deserialization doesn't hang or
+ crash.
+
+2013-01-16 Jocelyn Turcotte <jocelyn.turcotte@digia.com>
+
[Qt] Crash in WebCore::CachedFrame::destroy
https://bugs.webkit.org/show_bug.cgi?id=104525
diff --git a/Source/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp b/Source/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp
index 06c292908..4c839fec3 100644
--- a/Source/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp
+++ b/Source/WebKit/qt/tests/qwebhistory/tst_qwebhistory.cpp
@@ -65,6 +65,7 @@ private Q_SLOTS:
void popPushState_data();
void popPushState();
void clear();
+ void restoreIncompatibleVersion1();
private:
@@ -237,16 +238,20 @@ void tst_QWebHistory::serialize_2()
QDataStream save(&tmp, QIODevice::WriteOnly); //here data will be saved
QDataStream load(&tmp, QIODevice::ReadOnly); //from here data will be loaded
- int oldCurrentIndex = hist->currentItemIndex();
+ // Force a "same document" navigation.
+ frame->load(frame->url().toString() + QLatin1String("#dummyAnchor"));
+
+ int initialCurrentIndex = hist->currentItemIndex();
hist->back();
+ hist->back();
waitForLoadFinished.exec();
hist->back();
waitForLoadFinished.exec();
//check if current index was changed (make sure that it is not last item)
- QVERIFY(hist->currentItemIndex() != oldCurrentIndex);
+ QVERIFY(hist->currentItemIndex() != initialCurrentIndex);
//save current index
- oldCurrentIndex = hist->currentItemIndex();
+ int oldCurrentIndex = hist->currentItemIndex();
save << *hist;
QVERIFY(save.status() == QDataStream::Ok);
@@ -255,6 +260,13 @@ void tst_QWebHistory::serialize_2()
//check current index
QCOMPARE(hist->currentItemIndex(), oldCurrentIndex);
+
+ hist->forward();
+ waitForLoadFinished.exec();
+ hist->forward();
+ waitForLoadFinished.exec();
+ hist->forward();
+ QCOMPARE(hist->currentItemIndex(), initialCurrentIndex);
}
/**
@@ -414,5 +426,99 @@ void tst_QWebHistory::clear()
delete page2;
}
+// static void dumpCurrentVersion(QWebHistory* history)
+// {
+// QByteArray buffer;
+// saveHistory(history, &buffer);
+// printf(" static const char version1Dump[] = {");
+// for (int i = 0; i < buffer.size(); ++i) {
+// bool newLine = !(i % 15);
+// bool last = i == buffer.size() - 1;
+// printf("%s0x%.2x%s", newLine ? "\n " : "", (unsigned char)buffer[i], last ? "" : ", ");
+// }
+// printf("};\n");
+// }
+
+void tst_QWebHistory::restoreIncompatibleVersion1()
+{
+ // Uncomment this code to generate a dump similar to the one below with the current stream version.
+ // dumpCurrentVersion(hist);
+ static const char version1Dump[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65,
+ 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00,
+ 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x31, 0x00, 0x2e, 0x00, 0x68,
+ 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00,
+ 0x67, 0x00, 0x65, 0x00, 0x31, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00,
+ 0x2f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63,
+ 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00,
+ 0x31, 0x00, 0x2e, 0x00, 0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32,
+ 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65, 0x00,
+ 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f,
+ 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x68, 0x00,
+ 0x74, 0x00, 0x6d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67,
+ 0x00, 0x65, 0x00, 0x32, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f,
+ 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00,
+ 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x32,
+ 0x00, 0x2e, 0x00, 0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00,
+ 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73,
+ 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00,
+ 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x33, 0x00, 0x2e, 0x00, 0x68, 0x00, 0x74,
+ 0x00, 0x6d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00,
+ 0x65, 0x00, 0x33, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00,
+ 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65,
+ 0x00, 0x73, 0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x33, 0x00,
+ 0x2e, 0x00, 0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+ 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x71,
+ 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00,
+ 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x70,
+ 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x68, 0x00, 0x74, 0x00,
+ 0x6d, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65,
+ 0x00, 0x34, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72,
+ 0x00, 0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00,
+ 0x73, 0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x34, 0x00, 0x2e,
+ 0x00, 0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, 0x71, 0x00,
+ 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x73, 0x00, 0x6f,
+ 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x2f, 0x00, 0x70, 0x00,
+ 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x35, 0x00, 0x2e, 0x00, 0x68, 0x00, 0x74, 0x00, 0x6d,
+ 0x00, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00,
+ 0x35, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x32, 0x00, 0x71, 0x00, 0x72, 0x00, 0x63, 0x00, 0x3a, 0x00, 0x2f, 0x00, 0x72, 0x00,
+ 0x65, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x72, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73,
+ 0x00, 0x2f, 0x00, 0x70, 0x00, 0x61, 0x00, 0x67, 0x00, 0x65, 0x00, 0x35, 0x00, 0x2e, 0x00,
+ 0x68, 0x00, 0x74, 0x00, 0x6d, 0x00, 0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ QByteArray version1(version1Dump, sizeof(version1Dump));
+ QDataStream stream(&version1, QIODevice::ReadOnly);
+
+ // This should fail to load, the history should be cleared and the stream should be broken.
+ stream >> *hist;
+ QVERIFY(!hist->canGoBack());
+ QVERIFY(!hist->canGoForward());
+ QVERIFY(stream.status() == QDataStream::ReadCorruptData);
+}
+
QTEST_MAIN(tst_QWebHistory)
#include "tst_qwebhistory.moc"