Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: webkit/glue/glue_serialize.cc

Issue 14985014: Introduce content::PageState (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add comments to the top of page_state.h Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "webkit/glue/glue_serialize.h"
6
7 #include <string>
8
9 #include "base/pickle.h"
10 #include "base/utf_string_conversions.h"
11 #include "googleurl/src/gurl.h"
12 #include "third_party/WebKit/Source/Platform/chromium/public/WebData.h"
13 #include "third_party/WebKit/Source/Platform/chromium/public/WebHTTPBody.h"
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebPoint.h"
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h"
16 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h"
17 #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h"
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptVa lue.h"
20 #include "ui/gfx/screen.h"
21 #include "webkit/base/file_path_string_conversions.h"
22
23 using WebKit::WebData;
24 using WebKit::WebHistoryItem;
25 using WebKit::WebHTTPBody;
26 using WebKit::WebPoint;
27 using WebKit::WebSerializedScriptValue;
28 using WebKit::WebString;
29 using WebKit::WebUChar;
30 using WebKit::WebVector;
31
32 namespace webkit_glue {
33
34 namespace {
35
36 enum IncludeFormData {
37 NEVER_INCLUDE_FORM_DATA,
38 INCLUDE_FORM_DATA_WITHOUT_PASSWORDS,
39 ALWAYS_INCLUDE_FORM_DATA
40 };
41
42 struct SerializeObject {
43 SerializeObject() : version(0) {}
44 SerializeObject(const char* data, int len)
45 : pickle(data, len), version(0) { iter = PickleIterator(pickle); }
46
47 std::string GetAsString() {
48 return std::string(static_cast<const char*>(pickle.data()), pickle.size());
49 }
50
51 Pickle pickle;
52 mutable PickleIterator iter;
53 mutable int version;
54 };
55
56 // TODO(mpcomplete): obsolete versions 1 and 2 after 1/1/2008.
57 // Version ID used in reading/writing history items.
58 // 1: Initial revision.
59 // 2: Added case for NULL string versus "". Version 2 code can read Version 1
60 // data, but not vice versa.
61 // 3: Version 2 was broken, it stored number of WebUChars, not number of bytes.
62 // This version checks and reads v1 and v2 correctly.
63 // 4: Adds support for storing FormData::identifier().
64 // 5: Adds support for empty FormData
65 // 6: Adds support for documentSequenceNumbers
66 // 7: Adds support for stateObject
67 // 8: Adds support for file range and modification time
68 // 9: Adds support for itemSequenceNumbers
69 // 10: Adds support for blob
70 // 11: Adds support for pageScaleFactor
71 // 12: Adds support for hasPasswordData in HTTP body
72 // 13: Adds support for URL (FileSystem URL)
73 // 14: Adds list of referenced files, version written only for first item.
74 // Should be const, but unit tests may modify it.
75 //
76 // NOTE: If the version is -1, then the pickle contains only a URL string.
77 // See CreateHistoryStateForURL.
78 //
79 int kVersion = 14;
80
81 // A bunch of convenience functions to read/write to SerializeObjects.
82 // The serializers assume the input data is in the correct format and so does
83 // no error checking.
84 void WriteData(const void* data, int length, SerializeObject* obj) {
85 obj->pickle.WriteData(static_cast<const char*>(data), length);
86 }
87
88 void ReadData(const SerializeObject* obj, const void** data, int* length) {
89 const char* tmp;
90 if (obj->pickle.ReadData(&obj->iter, &tmp, length)) {
91 *data = tmp;
92 } else {
93 *data = NULL;
94 *length = 0;
95 }
96 }
97
98 bool ReadBytes(const SerializeObject* obj, const void** data, int length) {
99 const char *tmp;
100 if (!obj->pickle.ReadBytes(&obj->iter, &tmp, length))
101 return false;
102 *data = tmp;
103 return true;
104 }
105
106 void WriteInteger(int data, SerializeObject* obj) {
107 obj->pickle.WriteInt(data);
108 }
109
110 int ReadInteger(const SerializeObject* obj) {
111 int tmp;
112 if (obj->pickle.ReadInt(&obj->iter, &tmp))
113 return tmp;
114 return 0;
115 }
116
117 void ConsumeInteger(const SerializeObject* obj) {
118 int unused ALLOW_UNUSED = ReadInteger(obj);
119 }
120
121 void WriteInteger64(int64 data, SerializeObject* obj) {
122 obj->pickle.WriteInt64(data);
123 }
124
125 int64 ReadInteger64(const SerializeObject* obj) {
126 int64 tmp = 0;
127 obj->pickle.ReadInt64(&obj->iter, &tmp);
128 return tmp;
129 }
130
131 void WriteReal(double data, SerializeObject* obj) {
132 WriteData(&data, sizeof(double), obj);
133 }
134
135 double ReadReal(const SerializeObject* obj) {
136 const void* tmp = NULL;
137 int length = 0;
138 double value = 0.0;
139 ReadData(obj, &tmp, &length);
140 if (tmp && length >= static_cast<int>(sizeof(double))) {
141 // Use memcpy, as tmp may not be correctly aligned.
142 memcpy(&value, tmp, sizeof(double));
143 }
144 return value;
145 }
146
147 void WriteBoolean(bool data, SerializeObject* obj) {
148 obj->pickle.WriteInt(data ? 1 : 0);
149 }
150
151 bool ReadBoolean(const SerializeObject* obj) {
152 bool tmp;
153 if (obj->pickle.ReadBool(&obj->iter, &tmp))
154 return tmp;
155 return false;
156 }
157
158 void WriteGURL(const GURL& url, SerializeObject* obj) {
159 obj->pickle.WriteString(url.possibly_invalid_spec());
160 }
161
162 GURL ReadGURL(const SerializeObject* obj) {
163 std::string spec;
164 if (obj->pickle.ReadString(&obj->iter, &spec))
165 return GURL(spec);
166 return GURL();
167 }
168
169 // Read/WriteString pickle the WebString as <int length><WebUChar* data>.
170 // If length == -1, then the WebString itself is NULL (WebString()).
171 // Otherwise the length is the number of WebUChars (not bytes) in the WebString.
172 void WriteString(const WebString& str, SerializeObject* obj) {
173 switch (kVersion) {
174 case 1:
175 // Version 1 writes <length in bytes><string data>.
176 // It saves WebString() and "" as "".
177 obj->pickle.WriteInt(str.length() * sizeof(WebUChar));
178 obj->pickle.WriteBytes(str.data(), str.length() * sizeof(WebUChar));
179 break;
180 case 2:
181 // Version 2 writes <length in WebUChar><string data>.
182 // It uses -1 in the length field to mean WebString().
183 if (str.isNull()) {
184 obj->pickle.WriteInt(-1);
185 } else {
186 obj->pickle.WriteInt(str.length());
187 obj->pickle.WriteBytes(str.data(),
188 str.length() * sizeof(WebUChar));
189 }
190 break;
191 default:
192 // Version 3+ writes <length in bytes><string data>.
193 // It uses -1 in the length field to mean WebString().
194 if (str.isNull()) {
195 obj->pickle.WriteInt(-1);
196 } else {
197 obj->pickle.WriteInt(str.length() * sizeof(WebUChar));
198 obj->pickle.WriteBytes(str.data(),
199 str.length() * sizeof(WebUChar));
200 }
201 break;
202 }
203 }
204
205 // This reads a serialized WebString from obj. If a string can't be read,
206 // WebString() is returned.
207 const WebUChar* ReadStringNoCopy(const SerializeObject* obj, int* num_chars) {
208 int length;
209
210 // Versions 1, 2, and 3 all start with an integer.
211 if (!obj->pickle.ReadInt(&obj->iter, &length))
212 return NULL;
213
214 // Starting with version 2, -1 means WebString().
215 if (length == -1)
216 return NULL;
217
218 // In version 2, the length field was the length in WebUChars.
219 // In version 1 and 3 it is the length in bytes.
220 int bytes = length;
221 if (obj->version == 2)
222 bytes *= sizeof(WebUChar);
223
224 const void* data;
225 if (!ReadBytes(obj, &data, bytes))
226 return NULL;
227
228 if (num_chars)
229 *num_chars = bytes / sizeof(WebUChar);
230 return static_cast<const WebUChar*>(data);
231 }
232
233 WebString ReadString(const SerializeObject* obj) {
234 int num_chars;
235 const WebUChar* chars = ReadStringNoCopy(obj, &num_chars);
236 return chars ? WebString(chars, num_chars) : WebString();
237 }
238
239 void ConsumeString(const SerializeObject* obj) {
240 const WebUChar* unused ALLOW_UNUSED = ReadStringNoCopy(obj, NULL);
241 }
242
243 // Writes a Vector of Strings into a SerializeObject for serialization.
244 void WriteStringVector(
245 const WebVector<WebString>& data, SerializeObject* obj) {
246 WriteInteger(static_cast<int>(data.size()), obj);
247 for (size_t i = 0, c = data.size(); i < c; ++i) {
248 unsigned ui = static_cast<unsigned>(i); // sigh
249 WriteString(data[ui], obj);
250 }
251 }
252
253 WebVector<WebString> ReadStringVector(const SerializeObject* obj) {
254 int num_elements = ReadInteger(obj);
255 WebVector<WebString> result(static_cast<size_t>(num_elements));
256 for (int i = 0; i < num_elements; ++i)
257 result[i] = ReadString(obj);
258 return result;
259 }
260
261 void ConsumeStringVector(const SerializeObject* obj) {
262 int num_elements = ReadInteger(obj);
263 for (int i = 0; i < num_elements; ++i)
264 ConsumeString(obj);
265 }
266
267 // Writes a FormData object into a SerializeObject for serialization.
268 void WriteFormData(const WebHTTPBody& http_body, SerializeObject* obj) {
269 WriteBoolean(!http_body.isNull(), obj);
270
271 if (http_body.isNull())
272 return;
273
274 WriteInteger(static_cast<int>(http_body.elementCount()), obj);
275 WebHTTPBody::Element element;
276 for (size_t i = 0; http_body.elementAt(i, element); ++i) {
277 WriteInteger(element.type, obj);
278 if (element.type == WebHTTPBody::Element::TypeData) {
279 WriteData(element.data.data(), static_cast<int>(element.data.size()),
280 obj);
281 } else if (element.type == WebHTTPBody::Element::TypeFile) {
282 WriteString(element.filePath, obj);
283 WriteInteger64(element.fileStart, obj);
284 WriteInteger64(element.fileLength, obj);
285 WriteReal(element.modificationTime, obj);
286 } else if (element.type == WebHTTPBody::Element::TypeURL) {
287 WriteGURL(element.url, obj);
288 WriteInteger64(element.fileStart, obj);
289 WriteInteger64(element.fileLength, obj);
290 WriteReal(element.modificationTime, obj);
291 } else {
292 WriteGURL(element.url, obj);
293 }
294 }
295 WriteInteger64(http_body.identifier(), obj);
296 WriteBoolean(http_body.containsPasswordData(), obj);
297 }
298
299 WebHTTPBody ReadFormData(const SerializeObject* obj) {
300 // In newer versions, an initial boolean indicates if we have form data.
301 if (obj->version >= 5 && !ReadBoolean(obj))
302 return WebHTTPBody();
303
304 // In older versions, 0 elements implied no form data.
305 int num_elements = ReadInteger(obj);
306 if (num_elements == 0 && obj->version < 5)
307 return WebHTTPBody();
308
309 WebHTTPBody http_body;
310 http_body.initialize();
311
312 for (int i = 0; i < num_elements; ++i) {
313 int type = ReadInteger(obj);
314 if (type == WebHTTPBody::Element::TypeData) {
315 const void* data;
316 int length = -1;
317 ReadData(obj, &data, &length);
318 if (length >= 0)
319 http_body.appendData(WebData(static_cast<const char*>(data), length));
320 } else if (type == WebHTTPBody::Element::TypeFile) {
321 WebString file_path = ReadString(obj);
322 long long file_start = 0;
323 long long file_length = -1;
324 double modification_time = 0.0;
325 if (obj->version >= 8) {
326 file_start = ReadInteger64(obj);
327 file_length = ReadInteger64(obj);
328 modification_time = ReadReal(obj);
329 }
330 http_body.appendFileRange(file_path, file_start, file_length,
331 modification_time);
332 } else if (type == WebHTTPBody::Element::TypeURL) {
333 GURL url = ReadGURL(obj);
334 long long file_start = 0;
335 long long file_length = -1;
336 double modification_time = 0.0;
337 file_start = ReadInteger64(obj);
338 file_length = ReadInteger64(obj);
339 modification_time = ReadReal(obj);
340 http_body.appendURLRange(url, file_start, file_length,
341 modification_time);
342 } else if (obj->version >= 10) {
343 GURL blob_url = ReadGURL(obj);
344 http_body.appendBlob(blob_url);
345 }
346 }
347 if (obj->version >= 4)
348 http_body.setIdentifier(ReadInteger64(obj));
349
350 if (obj->version >= 12)
351 http_body.setContainsPasswordData(ReadBoolean(obj));
352
353 return http_body;
354 }
355
356 // Writes the HistoryItem data into the SerializeObject object for
357 // serialization.
358 void WriteHistoryItem(
359 const WebHistoryItem& item, SerializeObject* obj, bool is_top) {
360 // WARNING: This data may be persisted for later use. As such, care must be
361 // taken when changing the serialized format. If a new field needs to be
362 // written, only adding at the end will make it easier to deal with loading
363 // older versions. Similarly, this should NOT save fields with sensitive
364 // data, such as password fields.
365
366 if (kVersion >= 14) {
367 if (is_top) {
368 WriteInteger(kVersion, obj);
369
370 // Insert the list of referenced files, so they can be extracted easily
371 // from the serialized data (avoiding the need to call into Blink again).
372 WriteStringVector(item.getReferencedFilePaths(), obj);
373 }
374 } else {
375 WriteInteger(kVersion, obj);
376 }
377
378 WriteString(item.urlString(), obj);
379 WriteString(item.originalURLString(), obj);
380 WriteString(item.target(), obj);
381 WriteString(item.parent(), obj);
382 WriteString(item.title(), obj);
383 WriteString(item.alternateTitle(), obj);
384 WriteReal(item.lastVisitedTime(), obj);
385 WriteInteger(item.scrollOffset().x, obj);
386 WriteInteger(item.scrollOffset().y, obj);
387 WriteBoolean(item.isTargetItem(), obj);
388 WriteInteger(item.visitCount(), obj);
389 WriteString(item.referrer(), obj);
390
391 WriteStringVector(item.documentState(), obj);
392
393 if (kVersion >= 11)
394 WriteReal(item.pageScaleFactor(), obj);
395 if (kVersion >= 9)
396 WriteInteger64(item.itemSequenceNumber(), obj);
397 if (kVersion >= 6)
398 WriteInteger64(item.documentSequenceNumber(), obj);
399 if (kVersion >= 7) {
400 bool has_state_object = !item.stateObject().isNull();
401 WriteBoolean(has_state_object, obj);
402 if (has_state_object)
403 WriteString(item.stateObject().toString(), obj);
404 }
405
406 WriteFormData(item.httpBody(), obj);
407 WriteString(item.httpContentType(), obj);
408 if (kVersion < 14)
409 WriteString(item.referrer(), obj);
410
411 // Subitems
412 const WebVector<WebHistoryItem>& children = item.children();
413 WriteInteger(static_cast<int>(children.size()), obj);
414 for (size_t i = 0, c = children.size(); i < c; ++i)
415 WriteHistoryItem(children[i], obj, false);
416 }
417
418 // Creates a new HistoryItem tree based on the serialized string.
419 // Assumes the data is in the format returned by WriteHistoryItem.
420 WebHistoryItem ReadHistoryItem(
421 const SerializeObject* obj,
422 IncludeFormData include_form_data,
423 bool include_scroll_offset,
424 bool is_top) {
425 if (is_top) {
426 obj->version = ReadInteger(obj);
427
428 if (obj->version == -1) {
429 GURL url = ReadGURL(obj);
430 WebHistoryItem item;
431 item.initialize();
432 item.setURLString(WebString::fromUTF8(url.possibly_invalid_spec()));
433 return item;
434 }
435
436 if (obj->version > kVersion || obj->version < 1)
437 return WebHistoryItem();
438
439 if (obj->version >= 14)
440 ConsumeStringVector(obj); // Skip over list of referenced files.
441 } else if (obj->version < 14) {
442 ConsumeInteger(obj); // Skip over redundant version field.
443 }
444
445 WebHistoryItem item;
446 item.initialize();
447
448 item.setURLString(ReadString(obj));
449 item.setOriginalURLString(ReadString(obj));
450 item.setTarget(ReadString(obj));
451 item.setParent(ReadString(obj));
452 item.setTitle(ReadString(obj));
453 item.setAlternateTitle(ReadString(obj));
454 item.setLastVisitedTime(ReadReal(obj));
455
456 int x = ReadInteger(obj);
457 int y = ReadInteger(obj);
458 if (include_scroll_offset)
459 item.setScrollOffset(WebPoint(x, y));
460
461 item.setIsTargetItem(ReadBoolean(obj));
462 item.setVisitCount(ReadInteger(obj));
463 item.setReferrer(ReadString(obj));
464
465 item.setDocumentState(ReadStringVector(obj));
466
467 if (obj->version >= 11)
468 item.setPageScaleFactor(ReadReal(obj));
469 if (obj->version >= 9)
470 item.setItemSequenceNumber(ReadInteger64(obj));
471 if (obj->version >= 6)
472 item.setDocumentSequenceNumber(ReadInteger64(obj));
473 if (obj->version >= 7) {
474 bool has_state_object = ReadBoolean(obj);
475 if (has_state_object) {
476 item.setStateObject(
477 WebSerializedScriptValue::fromString(ReadString(obj)));
478 }
479 }
480
481 // The extra referrer string is read for backwards compat.
482 const WebHTTPBody& http_body = ReadFormData(obj);
483 const WebString& http_content_type = ReadString(obj);
484
485 if (obj->version < 14)
486 ConsumeString(obj); // Skip unused referrer string.
487
488 if (include_form_data == ALWAYS_INCLUDE_FORM_DATA ||
489 (include_form_data == INCLUDE_FORM_DATA_WITHOUT_PASSWORDS &&
490 !http_body.isNull() && !http_body.containsPasswordData())) {
491 // Include the full HTTP body.
492 item.setHTTPBody(http_body);
493 item.setHTTPContentType(http_content_type);
494 } else if (!http_body.isNull()) {
495 // Don't include the data in the HTTP body, but include its identifier. This
496 // enables fetching data from the cache.
497 WebHTTPBody empty_http_body;
498 empty_http_body.initialize();
499 empty_http_body.setIdentifier(http_body.identifier());
500 item.setHTTPBody(empty_http_body);
501 }
502
503 #if defined(OS_ANDROID)
504 if (obj->version == 11) {
505 // Now-unused values that shipped in this version of Chrome for Android when
506 // it was on a private branch.
507 ReadReal(obj);
508 ReadBoolean(obj);
509
510 // In this version, pageScaleFactor included deviceScaleFactor and scroll
511 // offsets were premultiplied by pageScaleFactor.
512 if (item.pageScaleFactor()) {
513 if (include_scroll_offset)
514 item.setScrollOffset(
515 WebPoint(item.scrollOffset().x / item.pageScaleFactor(),
516 item.scrollOffset().y / item.pageScaleFactor()));
517 item.setPageScaleFactor(item.pageScaleFactor() /
518 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay()
519 .device_scale_factor());
520 }
521 }
522 #endif
523
524 // Subitems
525 int num_children = ReadInteger(obj);
526 for (int i = 0; i < num_children; ++i)
527 item.appendToChildren(ReadHistoryItem(obj,
528 include_form_data,
529 include_scroll_offset,
530 false));
531
532 return item;
533 }
534
535 // Reconstruct a HistoryItem from a string, using our JSON Value deserializer.
536 // This assumes that the given serialized string has all the required key,value
537 // pairs, and does minimal error checking. The form data of the post is restored
538 // if |include_form_data| is |ALWAYS_INCLUDE_FORM_DATA| or if the data doesn't
539 // contain passwords and |include_form_data| is
540 // |INCLUDE_FORM_DATA_WITHOUT_PASSWORDS|. Otherwise the form data is empty. If
541 // |include_scroll_offset| is true, the scroll offset is restored.
542 WebHistoryItem HistoryItemFromString(
543 const std::string& serialized_item,
544 IncludeFormData include_form_data,
545 bool include_scroll_offset) {
546 if (serialized_item.empty())
547 return WebHistoryItem();
548
549 SerializeObject obj(serialized_item.data(),
550 static_cast<int>(serialized_item.length()));
551 return ReadHistoryItem(&obj, include_form_data, include_scroll_offset, true);
552 }
553
554 void ToFilePathVector(const WebVector<WebString>& input,
555 std::vector<base::FilePath>* output) {
556 for (size_t i = 0; i < input.size(); ++i)
557 output->push_back(webkit_base::WebStringToFilePath(input[i]));
558 }
559
560 } // namespace
561
562 // Serialize a HistoryItem to a string, using our JSON Value serializer.
563 std::string HistoryItemToString(const WebHistoryItem& item) {
564 if (item.isNull())
565 return std::string();
566
567 SerializeObject obj;
568 WriteHistoryItem(item, &obj, true);
569 return obj.GetAsString();
570 }
571
572 WebHistoryItem HistoryItemFromString(const std::string& serialized_item) {
573 return HistoryItemFromString(serialized_item, ALWAYS_INCLUDE_FORM_DATA, true);
574 }
575
576 std::vector<base::FilePath> FilePathsFromHistoryState(
577 const std::string& content_state) {
578 // TODO(darin): We should avoid using the WebKit API here, so that we do not
579 // need to have WebKit initialized before calling this method.
580
581 std::vector<base::FilePath> result;
582
583 // In newer versions of the format, the set of referenced files is computed
584 // at serialization time.
585 SerializeObject obj(content_state.data(),
586 static_cast<int>(content_state.length()));
587 obj.version = ReadInteger(&obj);
588
589 if (obj.version > kVersion || obj.version < 1)
590 return result;
591
592 if (obj.version >= 14) {
593 ToFilePathVector(ReadStringVector(&obj), &result);
594 } else {
595 // TODO(darin): Delete this code path after we branch for M29.
596 const WebHistoryItem& item =
597 HistoryItemFromString(content_state, ALWAYS_INCLUDE_FORM_DATA, true);
598 if (!item.isNull())
599 ToFilePathVector(item.getReferencedFilePaths(), &result);
600 }
601 return result;
602 }
603
604 // For testing purposes only.
605 void HistoryItemToVersionedString(const WebHistoryItem& item, int version,
606 std::string* serialized_item) {
607 if (item.isNull()) {
608 serialized_item->clear();
609 return;
610 }
611
612 // Temporarily change the version.
613 int real_version = kVersion;
614 kVersion = version;
615
616 SerializeObject obj;
617 WriteHistoryItem(item, &obj, true);
618 *serialized_item = obj.GetAsString();
619
620 kVersion = real_version;
621 }
622
623 int HistoryItemCurrentVersion() {
624 return kVersion;
625 }
626
627 std::string RemovePasswordDataFromHistoryState(
628 const std::string& content_state) {
629 // TODO(darin): We should avoid using the WebKit API here, so that we do not
630 // need to have WebKit initialized before calling this method.
631 const WebHistoryItem& item =
632 HistoryItemFromString(
633 content_state, INCLUDE_FORM_DATA_WITHOUT_PASSWORDS, true);
634 if (item.isNull()) {
635 // Couldn't parse the string, return an empty string.
636 return std::string();
637 }
638
639 return HistoryItemToString(item);
640 }
641
642 std::string RemoveScrollOffsetFromHistoryState(
643 const std::string& content_state) {
644 // TODO(darin): We should avoid using the WebKit API here, so that we do not
645 // need to have WebKit initialized before calling this method.
646 const WebHistoryItem& item =
647 HistoryItemFromString(content_state, ALWAYS_INCLUDE_FORM_DATA, false);
648 if (item.isNull()) {
649 // Couldn't parse the string, return an empty string.
650 return std::string();
651 }
652
653 return HistoryItemToString(item);
654 }
655
656 std::string CreateHistoryStateForURL(const GURL& url) {
657 // We avoid using the WebKit API here, so that we do not need to have WebKit
658 // initialized before calling this method. Instead, we write a simple
659 // serialization of the given URL with a dummy version number of -1. This
660 // will be interpreted by ReadHistoryItem as a request to create a default
661 // WebHistoryItem.
662 SerializeObject obj;
663 WriteInteger(-1, &obj);
664 WriteGURL(url, &obj);
665 return obj.GetAsString();
666 }
667
668 } // namespace webkit_glue
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698