Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "android_webview/native/state_serializer.h" | 5 #include "android_webview/native/state_serializer.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/pickle.h" | 9 #include "base/pickle.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 // * TabNavigation is tightly integrated with the rest of chrome session | 24 // * TabNavigation is tightly integrated with the rest of chrome session |
| 25 // restore and sync code, and has other purpose in addition to serializing | 25 // restore and sync code, and has other purpose in addition to serializing |
| 26 // NavigationEntry. | 26 // NavigationEntry. |
| 27 | 27 |
| 28 using std::string; | 28 using std::string; |
| 29 | 29 |
| 30 namespace android_webview { | 30 namespace android_webview { |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 |
| 34 // Sanity check value that we are restoring from a valid pickle. | 34 const uint32_t AW_STATE_VERSION_INITIAL = 20130814; |
| 35 // This can potentially used as an actual serialization version number in the | 35 const uint32_t AW_STATE_VERSION_DATA_URL = 20151204; |
| 36 // future if we ever decide to support restoring from older versions. | 36 |
| 37 const uint32_t AW_STATE_VERSION = 20151204; | 37 const uint32_t AW_STATE_VERSION = AW_STATE_VERSION_DATA_URL; |
| 38 | |
| 39 const uint32_t SUPPORTED_VERSIONS[] = { | |
|
mnaganov (inactive)
2016/02/10 16:37:45
Do we really need an array? Since there just 2 pos
sbergner
2016/02/11 07:23:28
Sure, makes sense.
| |
| 40 AW_STATE_VERSION_INITIAL, | |
| 41 AW_STATE_VERSION_DATA_URL | |
| 42 }; | |
| 43 const uint32_t NUM_SUPPORTED_VERSIONS = | |
|
mnaganov (inactive)
2016/02/10 16:37:45
nit: there is `arraysize` in base/macros.h
| |
| 44 sizeof(SUPPORTED_VERSIONS) / sizeof(SUPPORTED_VERSIONS[0]); | |
| 38 | 45 |
| 39 } // namespace | 46 } // namespace |
| 40 | 47 |
| 41 bool WriteToPickle(const content::WebContents& web_contents, | 48 bool WriteToPickle(const content::WebContents& web_contents, |
| 42 base::Pickle* pickle) { | 49 base::Pickle* pickle) { |
| 43 DCHECK(pickle); | 50 DCHECK(pickle); |
| 44 | 51 |
| 45 if (!internal::WriteHeaderToPickle(pickle)) | 52 if (!internal::WriteHeaderToPickle(pickle)) |
| 46 return false; | 53 return false; |
| 47 | 54 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 58 | 65 |
| 59 if (!pickle->WriteInt(selected_entry)) | 66 if (!pickle->WriteInt(selected_entry)) |
| 60 return false; | 67 return false; |
| 61 | 68 |
| 62 for (int i = 0; i < entry_count; ++i) { | 69 for (int i = 0; i < entry_count; ++i) { |
| 63 if (!internal::WriteNavigationEntryToPickle(*controller.GetEntryAtIndex(i), | 70 if (!internal::WriteNavigationEntryToPickle(*controller.GetEntryAtIndex(i), |
| 64 pickle)) | 71 pickle)) |
| 65 return false; | 72 return false; |
| 66 } | 73 } |
| 67 | 74 |
| 68 // Please update AW_STATE_VERSION if serialization format is changed. | 75 // Please update AW_STATE_VERSION and SUPPORTED_VERSIONS if serialization |
| 76 // format is changed. | |
| 77 // Make sure the serialization format is updated in a backwards compatible | |
| 78 // way. | |
| 69 | 79 |
| 70 return true; | 80 return true; |
| 71 } | 81 } |
| 72 | 82 |
| 73 bool RestoreFromPickle(base::PickleIterator* iterator, | 83 bool RestoreFromPickle(base::PickleIterator* iterator, |
| 74 content::WebContents* web_contents) { | 84 content::WebContents* web_contents) { |
| 75 DCHECK(iterator); | 85 DCHECK(iterator); |
| 76 DCHECK(web_contents); | 86 DCHECK(web_contents); |
| 77 | 87 |
| 78 if (!internal::RestoreHeaderFromPickle(iterator)) | 88 uint32_t state_version = internal::RestoreHeaderFromPickle(iterator); |
| 89 if (!state_version) | |
| 79 return false; | 90 return false; |
| 80 | 91 |
| 81 int entry_count = -1; | 92 int entry_count = -1; |
| 82 int selected_entry = -2; // -1 is a valid value | 93 int selected_entry = -2; // -1 is a valid value |
| 83 | 94 |
| 84 if (!iterator->ReadInt(&entry_count)) | 95 if (!iterator->ReadInt(&entry_count)) |
| 85 return false; | 96 return false; |
| 86 | 97 |
| 87 if (!iterator->ReadInt(&selected_entry)) | 98 if (!iterator->ReadInt(&selected_entry)) |
| 88 return false; | 99 return false; |
| 89 | 100 |
| 90 if (entry_count < 0) | 101 if (entry_count < 0) |
| 91 return false; | 102 return false; |
| 92 if (selected_entry < -1) | 103 if (selected_entry < -1) |
| 93 return false; | 104 return false; |
| 94 if (selected_entry >= entry_count) | 105 if (selected_entry >= entry_count) |
| 95 return false; | 106 return false; |
| 96 | 107 |
| 97 std::vector<scoped_ptr<content::NavigationEntry>> entries; | 108 std::vector<scoped_ptr<content::NavigationEntry>> entries; |
| 98 entries.reserve(entry_count); | 109 entries.reserve(entry_count); |
| 99 for (int i = 0; i < entry_count; ++i) { | 110 for (int i = 0; i < entry_count; ++i) { |
| 100 entries.push_back(content::NavigationEntry::Create()); | 111 entries.push_back(content::NavigationEntry::Create()); |
| 101 if (!internal::RestoreNavigationEntryFromPickle(iterator, entries[i].get())) | 112 if (!internal::RestoreNavigationEntryFromPickle(state_version, iterator, |
| 113 entries[i].get())) | |
| 102 return false; | 114 return false; |
| 103 | 115 |
| 104 entries[i]->SetPageID(i); | 116 entries[i]->SetPageID(i); |
| 105 } | 117 } |
| 106 | 118 |
| 107 // |web_contents| takes ownership of these entries after this call. | 119 // |web_contents| takes ownership of these entries after this call. |
| 108 content::NavigationController& controller = web_contents->GetController(); | 120 content::NavigationController& controller = web_contents->GetController(); |
| 109 controller.Restore( | 121 controller.Restore( |
| 110 selected_entry, | 122 selected_entry, |
| 111 content::NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY, | 123 content::NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY, |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 132 | 144 |
| 133 return true; | 145 return true; |
| 134 } | 146 } |
| 135 | 147 |
| 136 namespace internal { | 148 namespace internal { |
| 137 | 149 |
| 138 bool WriteHeaderToPickle(base::Pickle* pickle) { | 150 bool WriteHeaderToPickle(base::Pickle* pickle) { |
| 139 return pickle->WriteUInt32(AW_STATE_VERSION); | 151 return pickle->WriteUInt32(AW_STATE_VERSION); |
| 140 } | 152 } |
| 141 | 153 |
| 142 bool RestoreHeaderFromPickle(base::PickleIterator* iterator) { | 154 uint32_t RestoreHeaderFromPickle(base::PickleIterator* iterator) { |
| 143 uint32_t state_version = -1; | 155 uint32_t state_version = -1; |
| 144 if (!iterator->ReadUInt32(&state_version)) | 156 if (!iterator->ReadUInt32(&state_version)) |
| 145 return false; | 157 return 0; |
| 146 | 158 |
| 147 if (AW_STATE_VERSION != state_version) | 159 if (IsSupportedVersion(state_version)) { |
| 148 return false; | 160 return state_version; |
| 161 } | |
| 149 | 162 |
| 150 return true; | 163 return 0; |
| 164 } | |
| 165 | |
| 166 bool IsSupportedVersion(uint32_t state_version) { | |
| 167 for (uint32_t version_index = 0; version_index < NUM_SUPPORTED_VERSIONS; | |
| 168 version_index++) { | |
| 169 if (state_version == SUPPORTED_VERSIONS[version_index]) | |
| 170 return true; | |
| 171 } | |
| 172 return false; | |
| 151 } | 173 } |
| 152 | 174 |
| 153 bool WriteNavigationEntryToPickle(const content::NavigationEntry& entry, | 175 bool WriteNavigationEntryToPickle(const content::NavigationEntry& entry, |
| 154 base::Pickle* pickle) { | 176 base::Pickle* pickle) { |
| 177 return WriteNavigationEntryToPickle(AW_STATE_VERSION, entry, pickle); | |
| 178 } | |
| 179 | |
| 180 bool WriteNavigationEntryToPickle(uint32_t state_version, | |
| 181 const content::NavigationEntry& entry, | |
| 182 base::Pickle* pickle) { | |
| 183 DCHECK(IsSupportedVersion(state_version)); | |
| 155 if (!pickle->WriteString(entry.GetURL().spec())) | 184 if (!pickle->WriteString(entry.GetURL().spec())) |
| 156 return false; | 185 return false; |
| 157 | 186 |
| 158 if (!pickle->WriteString(entry.GetVirtualURL().spec())) | 187 if (!pickle->WriteString(entry.GetVirtualURL().spec())) |
| 159 return false; | 188 return false; |
| 160 | 189 |
| 161 const content::Referrer& referrer = entry.GetReferrer(); | 190 const content::Referrer& referrer = entry.GetReferrer(); |
| 162 if (!pickle->WriteString(referrer.url.spec())) | 191 if (!pickle->WriteString(referrer.url.spec())) |
| 163 return false; | 192 return false; |
| 164 if (!pickle->WriteInt(static_cast<int>(referrer.policy))) | 193 if (!pickle->WriteInt(static_cast<int>(referrer.policy))) |
| 165 return false; | 194 return false; |
| 166 | 195 |
| 167 if (!pickle->WriteString16(entry.GetTitle())) | 196 if (!pickle->WriteString16(entry.GetTitle())) |
| 168 return false; | 197 return false; |
| 169 | 198 |
| 170 if (!pickle->WriteString(entry.GetPageState().ToEncodedData())) | 199 if (!pickle->WriteString(entry.GetPageState().ToEncodedData())) |
| 171 return false; | 200 return false; |
| 172 | 201 |
| 173 if (!pickle->WriteBool(static_cast<int>(entry.GetHasPostData()))) | 202 if (!pickle->WriteBool(static_cast<int>(entry.GetHasPostData()))) |
| 174 return false; | 203 return false; |
| 175 | 204 |
| 176 if (!pickle->WriteString(entry.GetOriginalRequestURL().spec())) | 205 if (!pickle->WriteString(entry.GetOriginalRequestURL().spec())) |
| 177 return false; | 206 return false; |
| 178 | 207 |
| 179 if (!pickle->WriteString(entry.GetBaseURLForDataURL().spec())) | 208 if (!pickle->WriteString(entry.GetBaseURLForDataURL().spec())) |
| 180 return false; | 209 return false; |
| 181 | 210 |
| 182 { | 211 if (state_version >= AW_STATE_VERSION_DATA_URL) { |
| 183 const char* data = nullptr; | 212 const char* data = nullptr; |
| 184 size_t size = 0; | 213 size_t size = 0; |
| 185 scoped_refptr<const base::RefCountedString> s = entry.GetDataURLAsString(); | 214 scoped_refptr<const base::RefCountedString> s = entry.GetDataURLAsString(); |
| 186 if (s) { | 215 if (s) { |
| 187 data = s->front_as<char>(); | 216 data = s->front_as<char>(); |
| 188 size = s->size(); | 217 size = s->size(); |
| 189 } | 218 } |
| 190 // Even when |entry.GetDataForDataURL()| is null we still need to write a | 219 // Even when |entry.GetDataForDataURL()| is null we still need to write a |
| 191 // zero-length entry to ensure the fields all line up when read back in. | 220 // zero-length entry to ensure the fields all line up when read back in. |
| 192 if (!pickle->WriteData(data, size)) | 221 if (!pickle->WriteData(data, size)) |
| 193 return false; | 222 return false; |
| 194 } | 223 } |
| 195 | 224 |
| 196 if (!pickle->WriteBool(static_cast<int>(entry.GetIsOverridingUserAgent()))) | 225 if (!pickle->WriteBool(static_cast<int>(entry.GetIsOverridingUserAgent()))) |
| 197 return false; | 226 return false; |
| 198 | 227 |
| 199 if (!pickle->WriteInt64(entry.GetTimestamp().ToInternalValue())) | 228 if (!pickle->WriteInt64(entry.GetTimestamp().ToInternalValue())) |
| 200 return false; | 229 return false; |
| 201 | 230 |
| 202 if (!pickle->WriteInt(entry.GetHttpStatusCode())) | 231 if (!pickle->WriteInt(entry.GetHttpStatusCode())) |
| 203 return false; | 232 return false; |
| 204 | 233 |
| 205 // Please update AW_STATE_VERSION if serialization format is changed. | 234 // Please update AW_STATE_VERSION if serialization format is changed. |
| 206 | 235 |
| 207 return true; | 236 return true; |
| 208 } | 237 } |
| 209 | 238 |
| 210 bool RestoreNavigationEntryFromPickle(base::PickleIterator* iterator, | 239 bool RestoreNavigationEntryFromPickle(base::PickleIterator* iterator, |
| 211 content::NavigationEntry* entry) { | 240 content::NavigationEntry* entry) { |
| 241 return RestoreNavigationEntryFromPickle(AW_STATE_VERSION, iterator, entry); | |
| 242 } | |
| 243 | |
| 244 bool RestoreNavigationEntryFromPickle(uint32_t state_version, | |
| 245 base::PickleIterator* iterator, | |
| 246 content::NavigationEntry* entry) { | |
| 247 DCHECK(IsSupportedVersion(state_version)); | |
| 212 { | 248 { |
| 213 string url; | 249 string url; |
| 214 if (!iterator->ReadString(&url)) | 250 if (!iterator->ReadString(&url)) |
| 215 return false; | 251 return false; |
| 216 entry->SetURL(GURL(url)); | 252 entry->SetURL(GURL(url)); |
| 217 } | 253 } |
| 218 | 254 |
| 219 { | 255 { |
| 220 string virtual_url; | 256 string virtual_url; |
| 221 if (!iterator->ReadString(&virtual_url)) | 257 if (!iterator->ReadString(&virtual_url)) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 entry->SetOriginalRequestURL(GURL(original_request_url)); | 303 entry->SetOriginalRequestURL(GURL(original_request_url)); |
| 268 } | 304 } |
| 269 | 305 |
| 270 { | 306 { |
| 271 string base_url_for_data_url; | 307 string base_url_for_data_url; |
| 272 if (!iterator->ReadString(&base_url_for_data_url)) | 308 if (!iterator->ReadString(&base_url_for_data_url)) |
| 273 return false; | 309 return false; |
| 274 entry->SetBaseURLForDataURL(GURL(base_url_for_data_url)); | 310 entry->SetBaseURLForDataURL(GURL(base_url_for_data_url)); |
| 275 } | 311 } |
| 276 | 312 |
| 277 { | 313 if (state_version >= AW_STATE_VERSION_DATA_URL) { |
| 278 const char* data; | 314 const char* data; |
| 279 int size; | 315 int size; |
| 280 if (!iterator->ReadData(&data, &size)) | 316 if (!iterator->ReadData(&data, &size)) |
| 281 return false; | 317 return false; |
| 282 if (size > 0) { | 318 if (size > 0) { |
| 283 scoped_refptr<base::RefCountedString> ref = new base::RefCountedString(); | 319 scoped_refptr<base::RefCountedString> ref = new base::RefCountedString(); |
| 284 ref->data().assign(data, size); | 320 ref->data().assign(data, size); |
| 285 entry->SetDataURLAsString(ref); | 321 entry->SetDataURLAsString(ref); |
| 286 } | 322 } |
| 287 } | 323 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 306 return false; | 342 return false; |
| 307 entry->SetHttpStatusCode(http_status_code); | 343 entry->SetHttpStatusCode(http_status_code); |
| 308 } | 344 } |
| 309 | 345 |
| 310 return true; | 346 return true; |
| 311 } | 347 } |
| 312 | 348 |
| 313 } // namespace internal | 349 } // namespace internal |
| 314 | 350 |
| 315 } // namespace android_webview | 351 } // namespace android_webview |
| OLD | NEW |