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 |