1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/glue_serialize.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/pickle.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebHTTPBody.h"
1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptValue.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h"
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/webkit_glue.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebData;
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebHistoryItem;
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebHTTPBody;
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebPoint;
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebSerializedScriptValue;
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebString;
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebUChar;
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebVector;
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace webkit_glue {
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct SerializeObject {
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SerializeObject() : iter(NULL) {}
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SerializeObject(const char* data, int len) : pickle(data, len), iter(NULL) {}
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string GetAsString() {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return std::string(static_cast<const char*>(pickle.data()), pickle.size());
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Pickle pickle;
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  mutable void* iter;
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  mutable int version;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(mpcomplete): obsolete versions 1 and 2 after 1/1/2008.
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Version ID used in reading/writing history items.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 1: Initial revision.
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 2: Added case for NULL string versus "". Version 2 code can read Version 1
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//    data, but not vice versa.
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 3: Version 2 was broken, it stored number of WebUChars, not number of bytes.
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//    This version checks and reads v1 and v2 correctly.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 4: Adds support for storing FormData::identifier().
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 5: Adds support for empty FormData
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 6: Adds support for documentSequenceNumbers
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 7: Adds support for stateObject
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 8: Adds support for file range and modification time
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 9: Adds support for itemSequenceNumbers
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// 10: Adds support for blob
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Should be const, but unit tests may modify it.
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// NOTE: If the version is -1, then the pickle contains only a URL string.
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// See CreateHistoryStateForURL.
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint kVersion = 10;
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// A bunch of convenience functions to read/write to SerializeObjects.
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The serializers assume the input data is in the correct format and so does
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// no error checking.
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline void WriteData(const void* data, int length, SerializeObject* obj) {
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.WriteData(static_cast<const char*>(data), length);
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline void ReadData(const SerializeObject* obj, const void** data,
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     int* length) {
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* tmp = NULL;
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.ReadData(&obj->iter, &tmp, length);
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *data = tmp;
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline bool ReadBytes(const SerializeObject* obj, const void** data,
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     int length) {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char *tmp;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!obj->pickle.ReadBytes(&obj->iter, &tmp, length))
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *data = tmp;
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline void WriteInteger(int data, SerializeObject* obj) {
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.WriteInt(data);
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline int ReadInteger(const SerializeObject* obj) {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int tmp = 0;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.ReadInt(&obj->iter, &tmp);
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return tmp;
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline void WriteInteger64(int64 data, SerializeObject* obj) {
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.WriteInt64(data);
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline int64 ReadInteger64(const SerializeObject* obj) {
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int64 tmp = 0;
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.ReadInt64(&obj->iter, &tmp);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return tmp;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline void WriteReal(double data, SerializeObject* obj) {
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteData(&data, sizeof(double), obj);
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline double ReadReal(const SerializeObject* obj) {
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const void* tmp = NULL;
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int length = 0;
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ReadData(obj, &tmp, &length);
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (tmp && length > 0 && length >= static_cast<int>(sizeof(0.0)))
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return *static_cast<const double*>(tmp);
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return 0.0;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline void WriteBoolean(bool data, SerializeObject* obj) {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.WriteInt(data ? 1 : 0);
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline bool ReadBoolean(const SerializeObject* obj) {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool tmp = false;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.ReadBool(&obj->iter, &tmp);
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return tmp;
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline void WriteGURL(const GURL& url, SerializeObject* obj) {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.WriteString(url.possibly_invalid_spec());
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline GURL ReadGURL(const SerializeObject* obj) {
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string spec;
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->pickle.ReadString(&obj->iter, &spec);
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GURL(spec);
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Read/WriteString pickle the WebString as <int length><WebUChar* data>.
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// If length == -1, then the WebString itself is NULL (WebString()).
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Otherwise the length is the number of WebUChars (not bytes) in the WebString.
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline void WriteString(const WebString& str, SerializeObject* obj) {
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (kVersion) {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case 1:
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Version 1 writes <length in bytes><string data>.
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // It saves WebString() and "" as "".
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      obj->pickle.WriteInt(str.length() * sizeof(WebUChar));
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      obj->pickle.WriteBytes(str.data(), str.length() * sizeof(WebUChar));
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case 2:
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Version 2 writes <length in WebUChar><string data>.
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // It uses -1 in the length field to mean WebString().
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (str.isNull()) {
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        obj->pickle.WriteInt(-1);
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        obj->pickle.WriteInt(str.length());
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        obj->pickle.WriteBytes(str.data(),
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               str.length() * sizeof(WebUChar));
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Version 3+ writes <length in bytes><string data>.
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // It uses -1 in the length field to mean WebString().
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (str.isNull()) {
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        obj->pickle.WriteInt(-1);
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        obj->pickle.WriteInt(str.length() * sizeof(WebUChar));
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        obj->pickle.WriteBytes(str.data(),
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               str.length() * sizeof(WebUChar));
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This reads a serialized WebString from obj. If a string can't be read,
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WebString() is returned.
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochinline WebString ReadString(const SerializeObject* obj) {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int length;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Versions 1, 2, and 3 all start with an integer.
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!obj->pickle.ReadInt(&obj->iter, &length))
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WebString();
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Starting with version 2, -1 means WebString().
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (length == -1)
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WebString();
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // In version 2, the length field was the length in WebUChars.
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // In version 1 and 3 it is the length in bytes.
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  int bytes = length;
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (obj->version == 2)
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bytes *= sizeof(WebUChar);
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const void* data;
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ReadBytes(obj, &data, bytes))
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WebString();
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return WebString(static_cast<const WebUChar*>(data),
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   bytes / sizeof(WebUChar));
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Writes a Vector of Strings into a SerializeObject for serialization.
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void WriteStringVector(
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const WebVector<WebString>& data, SerializeObject* obj) {
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteInteger(static_cast<int>(data.size()), obj);
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0, c = data.size(); i < c; ++i) {
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    unsigned ui = static_cast<unsigned>(i);  // sigh
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteString(data[ui], obj);
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic WebVector<WebString> ReadStringVector(const SerializeObject* obj) {
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int num_elements = ReadInteger(obj);
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebVector<WebString> result(static_cast<size_t>(num_elements));
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < num_elements; ++i)
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    result[i] = ReadString(obj);
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return result;
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Writes a FormData object into a SerializeObject for serialization.
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void WriteFormData(const WebHTTPBody& http_body, SerializeObject* obj) {
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteBoolean(!http_body.isNull(), obj);
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (http_body.isNull())
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteInteger(static_cast<int>(http_body.elementCount()), obj);
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebHTTPBody::Element element;
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; http_body.elementAt(i, element); ++i) {
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteInteger(element.type, obj);
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (element.type == WebHTTPBody::Element::TypeData) {
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WriteData(element.data.data(), static_cast<int>(element.data.size()),
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                obj);
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else if (element.type == WebHTTPBody::Element::TypeFile) {
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WriteString(element.filePath, obj);
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WriteInteger64(element.fileStart, obj);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WriteInteger64(element.fileLength, obj);
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      WriteReal(element.modificationTime, obj);
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else {
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      WriteGURL(element.blobURL, obj);
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteInteger64(http_body.identifier(), obj);
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic WebHTTPBody ReadFormData(const SerializeObject* obj) {
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // In newer versions, an initial boolean indicates if we have form data.
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (obj->version >= 5 && !ReadBoolean(obj))
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WebHTTPBody();
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // In older versions, 0 elements implied no form data.
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int num_elements = ReadInteger(obj);
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (num_elements == 0 && obj->version < 5)
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WebHTTPBody();
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebHTTPBody http_body;
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  http_body.initialize();
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < num_elements; ++i) {
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int type = ReadInteger(obj);
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (type == WebHTTPBody::Element::TypeData) {
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const void* data;
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int length = -1;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ReadData(obj, &data, &length);
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (length >= 0)
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        http_body.appendData(WebData(static_cast<const char*>(data), length));
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else if (type == WebHTTPBody::Element::TypeFile) {
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WebString file_path = ReadString(obj);
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      long long file_start = 0;
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      long long file_length = -1;
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      double modification_time = 0.0;
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (obj->version >= 8) {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        file_start = ReadInteger64(obj);
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        file_length = ReadInteger64(obj);
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        modification_time = ReadReal(obj);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      http_body.appendFileRange(file_path, file_start, file_length,
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                modification_time);
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    } else if (obj->version >= 10) {
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      GURL blob_url = ReadGURL(obj);
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      http_body.appendBlob(blob_url);
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (obj->version >= 4)
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    http_body.setIdentifier(ReadInteger64(obj));
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return http_body;
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Writes the HistoryItem data into the SerializeObject object for
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// serialization.
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void WriteHistoryItem(
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const WebHistoryItem& item, SerializeObject* obj) {
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WARNING: This data may be persisted for later use. As such, care must be
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // taken when changing the serialized format. If a new field needs to be
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // written, only adding at the end will make it easier to deal with loading
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // older versions. Similarly, this should NOT save fields with sensitive
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // data, such as password fields.
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteInteger(kVersion, obj);
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteString(item.urlString(), obj);
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteString(item.originalURLString(), obj);
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteString(item.target(), obj);
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteString(item.parent(), obj);
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteString(item.title(), obj);
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteString(item.alternateTitle(), obj);
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteReal(item.lastVisitedTime(), obj);
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteInteger(item.scrollOffset().x, obj);
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteInteger(item.scrollOffset().y, obj);
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteBoolean(item.isTargetItem(), obj);
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteInteger(item.visitCount(), obj);
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteString(item.referrer(), obj);
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteStringVector(item.documentState(), obj);
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (kVersion >= 9)
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteInteger64(item.itemSequenceNumber(), obj);
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (kVersion >= 6)
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteInteger64(item.documentSequenceNumber(), obj);
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (kVersion >= 7) {
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool has_state_object = !item.stateObject().isNull();
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteBoolean(has_state_object, obj);
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (has_state_object)
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      WriteString(item.stateObject().toString(), obj);
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Yes, the referrer is written twice.  This is for backwards
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // compatibility with the format.
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteFormData(item.httpBody(), obj);
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteString(item.httpContentType(), obj);
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteString(item.referrer(), obj);
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Subitems
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const WebVector<WebHistoryItem>& children = item.children();
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteInteger(static_cast<int>(children.size()), obj);
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0, c = children.size(); i < c; ++i)
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WriteHistoryItem(children[i], obj);
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Creates a new HistoryItem tree based on the serialized string.
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Assumes the data is in the format returned by WriteHistoryItem.
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic WebHistoryItem ReadHistoryItem(
34621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const SerializeObject* obj,
34721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bool include_form_data,
34821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bool include_scroll_offset) {
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // See note in WriteHistoryItem. on this.
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  obj->version = ReadInteger(obj);
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (obj->version == -1) {
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL url = ReadGURL(obj);
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WebHistoryItem item;
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    item.initialize();
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    item.setURLString(WebString::fromUTF8(url.possibly_invalid_spec()));
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return item;
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (obj->version > kVersion || obj->version < 1)
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WebHistoryItem();
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WebHistoryItem item;
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.initialize();
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setURLString(ReadString(obj));
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setOriginalURLString(ReadString(obj));
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setTarget(ReadString(obj));
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setParent(ReadString(obj));
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setTitle(ReadString(obj));
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setAlternateTitle(ReadString(obj));
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setLastVisitedTime(ReadReal(obj));
37321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int x = ReadInteger(obj);
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int y = ReadInteger(obj);
37621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (include_scroll_offset)
37721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    item.setScrollOffset(WebPoint(x, y));
37821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setIsTargetItem(ReadBoolean(obj));
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setVisitCount(ReadInteger(obj));
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setReferrer(ReadString(obj));
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  item.setDocumentState(ReadStringVector(obj));
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (obj->version >= 9)
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    item.setItemSequenceNumber(ReadInteger64(obj));
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (obj->version >= 6)
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    item.setDocumentSequenceNumber(ReadInteger64(obj));
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (obj->version >= 7) {
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool has_state_object = ReadBoolean(obj);
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (has_state_object) {
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      item.setStateObject(
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          WebSerializedScriptValue::fromString(ReadString(obj)));
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The extra referrer string is read for backwards compat.
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const WebHTTPBody& http_body = ReadFormData(obj);
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const WebString& http_content_type = ReadString(obj);
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ALLOW_UNUSED const WebString& unused_referrer = ReadString(obj);
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (include_form_data) {
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    item.setHTTPBody(http_body);
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    item.setHTTPContentType(http_content_type);
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Subitems
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int num_children = ReadInteger(obj);
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < num_children; ++i)
40921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    item.appendToChildren(ReadHistoryItem(obj,
41021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                          include_form_data,
41121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                          include_scroll_offset));
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return item;
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Serialize a HistoryItem to a string, using our JSON Value serializer.
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string HistoryItemToString(const WebHistoryItem& item) {
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (item.isNull())
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return std::string();
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SerializeObject obj;
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteHistoryItem(item, &obj);
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return obj.GetAsString();
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Reconstruct a HistoryItem from a string, using our JSON Value deserializer.
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This assumes that the given serialized string has all the required key,value
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// pairs, and does minimal error checking. If |include_form_data| is true,
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the form data from a post is restored, otherwise the form data is empty.
43021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// If |include_scroll_offset| is true, the scroll offset is restored.
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic WebHistoryItem HistoryItemFromString(
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& serialized_item,
43321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bool include_form_data,
43421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bool include_scroll_offset) {
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (serialized_item.empty())
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return WebHistoryItem();
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SerializeObject obj(serialized_item.data(),
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                      static_cast<int>(serialized_item.length()));
44021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return ReadHistoryItem(&obj, include_form_data, include_scroll_offset);
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebHistoryItem HistoryItemFromString(
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::string& serialized_item) {
44521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return HistoryItemFromString(serialized_item, true, true);
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// For testing purposes only.
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryItemToVersionedString(const WebHistoryItem& item, int version,
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                  std::string* serialized_item) {
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (item.isNull()) {
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    serialized_item->clear();
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Temporarily change the version.
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int real_version = kVersion;
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kVersion = version;
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SerializeObject obj;
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteHistoryItem(item, &obj);
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *serialized_item = obj.GetAsString();
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  kVersion = real_version;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string CreateHistoryStateForURL(const GURL& url) {
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We avoid using the WebKit API here, so that we do not need to have WebKit
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // initialized before calling this method.  Instead, we write a simple
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // serialization of the given URL with a dummy version number of -1.  This
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // will be interpreted by ReadHistoryItem as a request to create a default
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WebHistoryItem.
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SerializeObject obj;
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteInteger(-1, &obj);
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WriteGURL(url, &obj);
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return obj.GetAsString();
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string RemoveFormDataFromHistoryState(const std::string& content_state) {
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(darin): We should avoid using the WebKit API here, so that we do not
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // need to have WebKit initialized before calling this method.
48221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const WebHistoryItem& item =
48321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      HistoryItemFromString(content_state, false, true);
48421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (item.isNull()) {
48521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Couldn't parse the string, return an empty string.
48621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return std::string();
48721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
48821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
48921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return HistoryItemToString(item);
49021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
49121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
49221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstd::string RemoveScrollOffsetFromHistoryState(
49321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const std::string& content_state) {
49421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // TODO(darin): We should avoid using the WebKit API here, so that we do not
49521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // need to have WebKit initialized before calling this method.
49621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const WebHistoryItem& item =
49721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      HistoryItemFromString(content_state, true, false);
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (item.isNull()) {
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Couldn't parse the string, return an empty string.
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return std::string();
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return HistoryItemToString(item);
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace webkit_glue
507