diff options
-rw-r--r-- | webkit/glue/glue_serialize.cc | 174 |
1 files changed, 117 insertions, 57 deletions
diff --git a/webkit/glue/glue_serialize.cc b/webkit/glue/glue_serialize.cc index e7d1fa1..1b5edbd 100644 --- a/webkit/glue/glue_serialize.cc +++ b/webkit/glue/glue_serialize.cc @@ -70,22 +70,22 @@ struct SerializeObject { // 11: Adds support for pageScaleFactor // 12: Adds support for hasPasswordData in HTTP body // 13: Adds support for URL (FileSystem URL) +// 14: Adds list of referenced files, version written only for first item. // Should be const, but unit tests may modify it. // // NOTE: If the version is -1, then the pickle contains only a URL string. // See CreateHistoryStateForURL. // -int kVersion = 13; +int kVersion = 14; // A bunch of convenience functions to read/write to SerializeObjects. // The serializers assume the input data is in the correct format and so does // no error checking. -inline void WriteData(const void* data, int length, SerializeObject* obj) { +void WriteData(const void* data, int length, SerializeObject* obj) { obj->pickle.WriteData(static_cast<const char*>(data), length); } -inline void ReadData(const SerializeObject* obj, const void** data, - int* length) { +void ReadData(const SerializeObject* obj, const void** data, int* length) { const char* tmp; if (obj->pickle.ReadData(&obj->iter, &tmp, length)) { *data = tmp; @@ -95,8 +95,7 @@ inline void ReadData(const SerializeObject* obj, const void** data, } } -inline bool ReadBytes(const SerializeObject* obj, const void** data, - int length) { +bool ReadBytes(const SerializeObject* obj, const void** data, int length) { const char *tmp; if (!obj->pickle.ReadBytes(&obj->iter, &tmp, length)) return false; @@ -104,32 +103,36 @@ inline bool ReadBytes(const SerializeObject* obj, const void** data, return true; } -inline void WriteInteger(int data, SerializeObject* obj) { +void WriteInteger(int data, SerializeObject* obj) { obj->pickle.WriteInt(data); } -inline int ReadInteger(const SerializeObject* obj) { +int ReadInteger(const SerializeObject* obj) { int tmp; if (obj->pickle.ReadInt(&obj->iter, &tmp)) return tmp; return 0; } -inline void WriteInteger64(int64 data, SerializeObject* obj) { +void ConsumeInteger(const SerializeObject* obj) { + int unused ALLOW_UNUSED = ReadInteger(obj); +} + +void WriteInteger64(int64 data, SerializeObject* obj) { obj->pickle.WriteInt64(data); } -inline int64 ReadInteger64(const SerializeObject* obj) { +int64 ReadInteger64(const SerializeObject* obj) { int64 tmp = 0; obj->pickle.ReadInt64(&obj->iter, &tmp); return tmp; } -inline void WriteReal(double data, SerializeObject* obj) { +void WriteReal(double data, SerializeObject* obj) { WriteData(&data, sizeof(double), obj); } -inline double ReadReal(const SerializeObject* obj) { +double ReadReal(const SerializeObject* obj) { const void* tmp = NULL; int length = 0; double value = 0.0; @@ -141,22 +144,22 @@ inline double ReadReal(const SerializeObject* obj) { return value; } -inline void WriteBoolean(bool data, SerializeObject* obj) { +void WriteBoolean(bool data, SerializeObject* obj) { obj->pickle.WriteInt(data ? 1 : 0); } -inline bool ReadBoolean(const SerializeObject* obj) { +bool ReadBoolean(const SerializeObject* obj) { bool tmp; if (obj->pickle.ReadBool(&obj->iter, &tmp)) return tmp; return false; } -inline void WriteGURL(const GURL& url, SerializeObject* obj) { +void WriteGURL(const GURL& url, SerializeObject* obj) { obj->pickle.WriteString(url.possibly_invalid_spec()); } -inline GURL ReadGURL(const SerializeObject* obj) { +GURL ReadGURL(const SerializeObject* obj) { std::string spec; if (obj->pickle.ReadString(&obj->iter, &spec)) return GURL(spec); @@ -166,7 +169,7 @@ inline GURL ReadGURL(const SerializeObject* obj) { // Read/WriteString pickle the WebString as <int length><WebUChar* data>. // If length == -1, then the WebString itself is NULL (WebString()). // Otherwise the length is the number of WebUChars (not bytes) in the WebString. -inline void WriteString(const WebString& str, SerializeObject* obj) { +void WriteString(const WebString& str, SerializeObject* obj) { switch (kVersion) { case 1: // Version 1 writes <length in bytes><string data>. @@ -201,16 +204,16 @@ inline void WriteString(const WebString& str, SerializeObject* obj) { // This reads a serialized WebString from obj. If a string can't be read, // WebString() is returned. -inline WebString ReadString(const SerializeObject* obj) { +const WebUChar* ReadStringNoCopy(const SerializeObject* obj, int* num_chars) { int length; // Versions 1, 2, and 3 all start with an integer. if (!obj->pickle.ReadInt(&obj->iter, &length)) - return WebString(); + return NULL; // Starting with version 2, -1 means WebString(). if (length == -1) - return WebString(); + return NULL; // In version 2, the length field was the length in WebUChars. // In version 1 and 3 it is the length in bytes. @@ -220,9 +223,21 @@ inline WebString ReadString(const SerializeObject* obj) { const void* data; if (!ReadBytes(obj, &data, bytes)) - return WebString(); - return WebString(static_cast<const WebUChar*>(data), - bytes / sizeof(WebUChar)); + return NULL; + + if (num_chars) + *num_chars = bytes / sizeof(WebUChar); + return static_cast<const WebUChar*>(data); +} + +WebString ReadString(const SerializeObject* obj) { + int num_chars; + const WebUChar* chars = ReadStringNoCopy(obj, &num_chars); + return chars ? WebString(chars, num_chars) : WebString(); +} + +void ConsumeString(const SerializeObject* obj) { + const WebUChar* unused ALLOW_UNUSED = ReadStringNoCopy(obj, NULL); } // Writes a Vector of Strings into a SerializeObject for serialization. @@ -243,6 +258,12 @@ WebVector<WebString> ReadStringVector(const SerializeObject* obj) { return result; } +void ConsumeStringVector(const SerializeObject* obj) { + int num_elements = ReadInteger(obj); + for (int i = 0; i < num_elements; ++i) + ConsumeString(obj); +} + // Writes a FormData object into a SerializeObject for serialization. void WriteFormData(const WebHTTPBody& http_body, SerializeObject* obj) { WriteBoolean(!http_body.isNull(), obj); @@ -335,13 +356,25 @@ WebHTTPBody ReadFormData(const SerializeObject* obj) { // Writes the HistoryItem data into the SerializeObject object for // serialization. void WriteHistoryItem( - const WebHistoryItem& item, SerializeObject* obj) { + const WebHistoryItem& item, SerializeObject* obj, bool is_top) { // WARNING: This data may be persisted for later use. As such, care must be // taken when changing the serialized format. If a new field needs to be // written, only adding at the end will make it easier to deal with loading // older versions. Similarly, this should NOT save fields with sensitive // data, such as password fields. - WriteInteger(kVersion, obj); + + if (kVersion >= 14) { + if (is_top) { + WriteInteger(kVersion, obj); + + // Insert the list of referenced files, so they can be extracted easily + // from the serialized data (avoiding the need to call into Blink again). + WriteStringVector(item.getReferencedFilePaths(), obj); + } + } else { + WriteInteger(kVersion, obj); + } + WriteString(item.urlString(), obj); WriteString(item.originalURLString(), obj); WriteString(item.target(), obj); @@ -370,17 +403,16 @@ void WriteHistoryItem( WriteString(item.stateObject().toString(), obj); } - // Yes, the referrer is written twice. This is for backwards - // compatibility with the format. WriteFormData(item.httpBody(), obj); WriteString(item.httpContentType(), obj); - WriteString(item.referrer(), obj); + if (kVersion < 14) + WriteString(item.referrer(), obj); // Subitems const WebVector<WebHistoryItem>& children = item.children(); WriteInteger(static_cast<int>(children.size()), obj); for (size_t i = 0, c = children.size(); i < c; ++i) - WriteHistoryItem(children[i], obj); + WriteHistoryItem(children[i], obj, false); } // Creates a new HistoryItem tree based on the serialized string. @@ -388,20 +420,27 @@ void WriteHistoryItem( WebHistoryItem ReadHistoryItem( const SerializeObject* obj, IncludeFormData include_form_data, - bool include_scroll_offset) { - // See note in WriteHistoryItem. on this. - obj->version = ReadInteger(obj); - - if (obj->version == -1) { - GURL url = ReadGURL(obj); - WebHistoryItem item; - item.initialize(); - item.setURLString(WebString::fromUTF8(url.possibly_invalid_spec())); - return item; - } + bool include_scroll_offset, + bool is_top) { + if (is_top) { + obj->version = ReadInteger(obj); - if (obj->version > kVersion || obj->version < 1) - return WebHistoryItem(); + if (obj->version == -1) { + GURL url = ReadGURL(obj); + WebHistoryItem item; + item.initialize(); + item.setURLString(WebString::fromUTF8(url.possibly_invalid_spec())); + return item; + } + + if (obj->version > kVersion || obj->version < 1) + return WebHistoryItem(); + + if (obj->version >= 14) + ConsumeStringVector(obj); // Skip over list of referenced files. + } else if (obj->version < 14) { + ConsumeInteger(obj); // Skip over redundant version field. + } WebHistoryItem item; item.initialize(); @@ -442,7 +481,10 @@ WebHistoryItem ReadHistoryItem( // The extra referrer string is read for backwards compat. const WebHTTPBody& http_body = ReadFormData(obj); const WebString& http_content_type = ReadString(obj); - ALLOW_UNUSED const WebString& unused_referrer = ReadString(obj); + + if (obj->version < 14) + ConsumeString(obj); // Skip unused referrer string. + if (include_form_data == ALWAYS_INCLUDE_FORM_DATA || (include_form_data == INCLUDE_FORM_DATA_WITHOUT_PASSWORDS && !http_body.isNull() && !http_body.containsPasswordData())) { @@ -484,7 +526,8 @@ WebHistoryItem ReadHistoryItem( for (int i = 0; i < num_children; ++i) item.appendToChildren(ReadHistoryItem(obj, include_form_data, - include_scroll_offset)); + include_scroll_offset, + false)); return item; } @@ -505,7 +548,13 @@ WebHistoryItem HistoryItemFromString( SerializeObject obj(serialized_item.data(), static_cast<int>(serialized_item.length())); - return ReadHistoryItem(&obj, include_form_data, include_scroll_offset); + return ReadHistoryItem(&obj, include_form_data, include_scroll_offset, true); +} + +void ToFilePathVector(const WebVector<WebString>& input, + std::vector<base::FilePath>* output) { + for (size_t i = 0; i < input.size(); ++i) + output->push_back(webkit_base::WebStringToFilePath(input[i])); } } // namespace @@ -516,7 +565,7 @@ std::string HistoryItemToString(const WebHistoryItem& item) { return std::string(); SerializeObject obj; - WriteHistoryItem(item, &obj); + WriteHistoryItem(item, &obj, true); return obj.GetAsString(); } @@ -526,19 +575,30 @@ WebHistoryItem HistoryItemFromString(const std::string& serialized_item) { std::vector<base::FilePath> FilePathsFromHistoryState( const std::string& content_state) { - std::vector<base::FilePath> to_return; // TODO(darin): We should avoid using the WebKit API here, so that we do not // need to have WebKit initialized before calling this method. - const WebHistoryItem& item = - HistoryItemFromString(content_state, ALWAYS_INCLUDE_FORM_DATA, true); - if (item.isNull()) { - // Couldn't parse the string. - return to_return; + + std::vector<base::FilePath> result; + + // In newer versions of the format, the set of referenced files is computed + // at serialization time. + SerializeObject obj(content_state.data(), + static_cast<int>(content_state.length())); + obj.version = ReadInteger(&obj); + + if (obj.version > kVersion || obj.version < 1) + return result; + + if (obj.version >= 14) { + ToFilePathVector(ReadStringVector(&obj), &result); + } else { + // TODO(darin): Delete this code path after we branch for M29. + const WebHistoryItem& item = + HistoryItemFromString(content_state, ALWAYS_INCLUDE_FORM_DATA, true); + if (!item.isNull()) + ToFilePathVector(item.getReferencedFilePaths(), &result); } - const WebVector<WebString> file_paths = item.getReferencedFilePaths(); - for (size_t i = 0; i < file_paths.size(); ++i) - to_return.push_back(webkit_base::WebStringToFilePath(file_paths[i])); - return to_return; + return result; } // For testing purposes only. @@ -554,7 +614,7 @@ void HistoryItemToVersionedString(const WebHistoryItem& item, int version, kVersion = version; SerializeObject obj; - WriteHistoryItem(item, &obj); + WriteHistoryItem(item, &obj, true); *serialized_item = obj.GetAsString(); kVersion = real_version; |