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 | 38 |
39 } // namespace | 39 } // namespace |
40 | 40 |
41 bool WriteToPickle(const content::WebContents& web_contents, | 41 bool WriteToPickle(const content::WebContents& web_contents, |
42 base::Pickle* pickle) { | 42 base::Pickle* pickle) { |
43 DCHECK(pickle); | 43 DCHECK(pickle); |
44 | 44 |
45 if (!internal::WriteHeaderToPickle(pickle)) | 45 if (!internal::WriteHeaderToPickle(pickle)) |
46 return false; | 46 return false; |
47 | 47 |
(...skipping 10 matching lines...) Expand all Loading... |
58 | 58 |
59 if (!pickle->WriteInt(selected_entry)) | 59 if (!pickle->WriteInt(selected_entry)) |
60 return false; | 60 return false; |
61 | 61 |
62 for (int i = 0; i < entry_count; ++i) { | 62 for (int i = 0; i < entry_count; ++i) { |
63 if (!internal::WriteNavigationEntryToPickle(*controller.GetEntryAtIndex(i), | 63 if (!internal::WriteNavigationEntryToPickle(*controller.GetEntryAtIndex(i), |
64 pickle)) | 64 pickle)) |
65 return false; | 65 return false; |
66 } | 66 } |
67 | 67 |
68 // Please update AW_STATE_VERSION if serialization format is changed. | 68 // Please update AW_STATE_VERSION and IsSupportedVersion() if serialization |
| 69 // format is changed. |
| 70 // Make sure the serialization format is updated in a backwards compatible |
| 71 // way. |
69 | 72 |
70 return true; | 73 return true; |
71 } | 74 } |
72 | 75 |
73 bool RestoreFromPickle(base::PickleIterator* iterator, | 76 bool RestoreFromPickle(base::PickleIterator* iterator, |
74 content::WebContents* web_contents) { | 77 content::WebContents* web_contents) { |
75 DCHECK(iterator); | 78 DCHECK(iterator); |
76 DCHECK(web_contents); | 79 DCHECK(web_contents); |
77 | 80 |
78 if (!internal::RestoreHeaderFromPickle(iterator)) | 81 uint32_t state_version = internal::RestoreHeaderFromPickle(iterator); |
| 82 if (!state_version) |
79 return false; | 83 return false; |
80 | 84 |
81 int entry_count = -1; | 85 int entry_count = -1; |
82 int selected_entry = -2; // -1 is a valid value | 86 int selected_entry = -2; // -1 is a valid value |
83 | 87 |
84 if (!iterator->ReadInt(&entry_count)) | 88 if (!iterator->ReadInt(&entry_count)) |
85 return false; | 89 return false; |
86 | 90 |
87 if (!iterator->ReadInt(&selected_entry)) | 91 if (!iterator->ReadInt(&selected_entry)) |
88 return false; | 92 return false; |
89 | 93 |
90 if (entry_count < 0) | 94 if (entry_count < 0) |
91 return false; | 95 return false; |
92 if (selected_entry < -1) | 96 if (selected_entry < -1) |
93 return false; | 97 return false; |
94 if (selected_entry >= entry_count) | 98 if (selected_entry >= entry_count) |
95 return false; | 99 return false; |
96 | 100 |
97 std::vector<scoped_ptr<content::NavigationEntry>> entries; | 101 std::vector<scoped_ptr<content::NavigationEntry>> entries; |
98 entries.reserve(entry_count); | 102 entries.reserve(entry_count); |
99 for (int i = 0; i < entry_count; ++i) { | 103 for (int i = 0; i < entry_count; ++i) { |
100 entries.push_back(content::NavigationEntry::Create()); | 104 entries.push_back(content::NavigationEntry::Create()); |
101 if (!internal::RestoreNavigationEntryFromPickle(iterator, entries[i].get())) | 105 if (!internal::RestoreNavigationEntryFromPickle(state_version, iterator, |
| 106 entries[i].get())) |
102 return false; | 107 return false; |
103 | 108 |
104 entries[i]->SetPageID(i); | 109 entries[i]->SetPageID(i); |
105 } | 110 } |
106 | 111 |
107 // |web_contents| takes ownership of these entries after this call. | 112 // |web_contents| takes ownership of these entries after this call. |
108 content::NavigationController& controller = web_contents->GetController(); | 113 content::NavigationController& controller = web_contents->GetController(); |
109 controller.Restore( | 114 controller.Restore( |
110 selected_entry, | 115 selected_entry, |
111 content::NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY, | 116 content::NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY, |
(...skipping 20 matching lines...) Expand all Loading... |
132 | 137 |
133 return true; | 138 return true; |
134 } | 139 } |
135 | 140 |
136 namespace internal { | 141 namespace internal { |
137 | 142 |
138 bool WriteHeaderToPickle(base::Pickle* pickle) { | 143 bool WriteHeaderToPickle(base::Pickle* pickle) { |
139 return pickle->WriteUInt32(AW_STATE_VERSION); | 144 return pickle->WriteUInt32(AW_STATE_VERSION); |
140 } | 145 } |
141 | 146 |
142 bool RestoreHeaderFromPickle(base::PickleIterator* iterator) { | 147 uint32_t RestoreHeaderFromPickle(base::PickleIterator* iterator) { |
143 uint32_t state_version = -1; | 148 uint32_t state_version = -1; |
144 if (!iterator->ReadUInt32(&state_version)) | 149 if (!iterator->ReadUInt32(&state_version)) |
145 return false; | 150 return 0; |
146 | 151 |
147 if (AW_STATE_VERSION != state_version) | 152 if (IsSupportedVersion(state_version)) { |
148 return false; | 153 return state_version; |
| 154 } |
149 | 155 |
150 return true; | 156 return 0; |
| 157 } |
| 158 |
| 159 bool IsSupportedVersion(uint32_t state_version) { |
| 160 return state_version == AW_STATE_VERSION_INITIAL || |
| 161 state_version == AW_STATE_VERSION_DATA_URL; |
151 } | 162 } |
152 | 163 |
153 bool WriteNavigationEntryToPickle(const content::NavigationEntry& entry, | 164 bool WriteNavigationEntryToPickle(const content::NavigationEntry& entry, |
154 base::Pickle* pickle) { | 165 base::Pickle* pickle) { |
| 166 return WriteNavigationEntryToPickle(AW_STATE_VERSION, entry, pickle); |
| 167 } |
| 168 |
| 169 bool WriteNavigationEntryToPickle(uint32_t state_version, |
| 170 const content::NavigationEntry& entry, |
| 171 base::Pickle* pickle) { |
| 172 DCHECK(IsSupportedVersion(state_version)); |
155 if (!pickle->WriteString(entry.GetURL().spec())) | 173 if (!pickle->WriteString(entry.GetURL().spec())) |
156 return false; | 174 return false; |
157 | 175 |
158 if (!pickle->WriteString(entry.GetVirtualURL().spec())) | 176 if (!pickle->WriteString(entry.GetVirtualURL().spec())) |
159 return false; | 177 return false; |
160 | 178 |
161 const content::Referrer& referrer = entry.GetReferrer(); | 179 const content::Referrer& referrer = entry.GetReferrer(); |
162 if (!pickle->WriteString(referrer.url.spec())) | 180 if (!pickle->WriteString(referrer.url.spec())) |
163 return false; | 181 return false; |
164 if (!pickle->WriteInt(static_cast<int>(referrer.policy))) | 182 if (!pickle->WriteInt(static_cast<int>(referrer.policy))) |
165 return false; | 183 return false; |
166 | 184 |
167 if (!pickle->WriteString16(entry.GetTitle())) | 185 if (!pickle->WriteString16(entry.GetTitle())) |
168 return false; | 186 return false; |
169 | 187 |
170 if (!pickle->WriteString(entry.GetPageState().ToEncodedData())) | 188 if (!pickle->WriteString(entry.GetPageState().ToEncodedData())) |
171 return false; | 189 return false; |
172 | 190 |
173 if (!pickle->WriteBool(static_cast<int>(entry.GetHasPostData()))) | 191 if (!pickle->WriteBool(static_cast<int>(entry.GetHasPostData()))) |
174 return false; | 192 return false; |
175 | 193 |
176 if (!pickle->WriteString(entry.GetOriginalRequestURL().spec())) | 194 if (!pickle->WriteString(entry.GetOriginalRequestURL().spec())) |
177 return false; | 195 return false; |
178 | 196 |
179 if (!pickle->WriteString(entry.GetBaseURLForDataURL().spec())) | 197 if (!pickle->WriteString(entry.GetBaseURLForDataURL().spec())) |
180 return false; | 198 return false; |
181 | 199 |
182 { | 200 if (state_version >= AW_STATE_VERSION_DATA_URL) { |
183 const char* data = nullptr; | 201 const char* data = nullptr; |
184 size_t size = 0; | 202 size_t size = 0; |
185 scoped_refptr<const base::RefCountedString> s = entry.GetDataURLAsString(); | 203 scoped_refptr<const base::RefCountedString> s = entry.GetDataURLAsString(); |
186 if (s) { | 204 if (s) { |
187 data = s->front_as<char>(); | 205 data = s->front_as<char>(); |
188 size = s->size(); | 206 size = s->size(); |
189 } | 207 } |
190 // Even when |entry.GetDataForDataURL()| is null we still need to write a | 208 // 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. | 209 // zero-length entry to ensure the fields all line up when read back in. |
192 if (!pickle->WriteData(data, size)) | 210 if (!pickle->WriteData(data, size)) |
193 return false; | 211 return false; |
194 } | 212 } |
195 | 213 |
196 if (!pickle->WriteBool(static_cast<int>(entry.GetIsOverridingUserAgent()))) | 214 if (!pickle->WriteBool(static_cast<int>(entry.GetIsOverridingUserAgent()))) |
197 return false; | 215 return false; |
198 | 216 |
199 if (!pickle->WriteInt64(entry.GetTimestamp().ToInternalValue())) | 217 if (!pickle->WriteInt64(entry.GetTimestamp().ToInternalValue())) |
200 return false; | 218 return false; |
201 | 219 |
202 if (!pickle->WriteInt(entry.GetHttpStatusCode())) | 220 if (!pickle->WriteInt(entry.GetHttpStatusCode())) |
203 return false; | 221 return false; |
204 | 222 |
205 // Please update AW_STATE_VERSION if serialization format is changed. | 223 // Please update AW_STATE_VERSION if serialization format is changed. |
206 | 224 |
207 return true; | 225 return true; |
208 } | 226 } |
209 | 227 |
210 bool RestoreNavigationEntryFromPickle(base::PickleIterator* iterator, | 228 bool RestoreNavigationEntryFromPickle(base::PickleIterator* iterator, |
211 content::NavigationEntry* entry) { | 229 content::NavigationEntry* entry) { |
| 230 return RestoreNavigationEntryFromPickle(AW_STATE_VERSION, iterator, entry); |
| 231 } |
| 232 |
| 233 bool RestoreNavigationEntryFromPickle(uint32_t state_version, |
| 234 base::PickleIterator* iterator, |
| 235 content::NavigationEntry* entry) { |
| 236 DCHECK(IsSupportedVersion(state_version)); |
212 { | 237 { |
213 string url; | 238 string url; |
214 if (!iterator->ReadString(&url)) | 239 if (!iterator->ReadString(&url)) |
215 return false; | 240 return false; |
216 entry->SetURL(GURL(url)); | 241 entry->SetURL(GURL(url)); |
217 } | 242 } |
218 | 243 |
219 { | 244 { |
220 string virtual_url; | 245 string virtual_url; |
221 if (!iterator->ReadString(&virtual_url)) | 246 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)); | 292 entry->SetOriginalRequestURL(GURL(original_request_url)); |
268 } | 293 } |
269 | 294 |
270 { | 295 { |
271 string base_url_for_data_url; | 296 string base_url_for_data_url; |
272 if (!iterator->ReadString(&base_url_for_data_url)) | 297 if (!iterator->ReadString(&base_url_for_data_url)) |
273 return false; | 298 return false; |
274 entry->SetBaseURLForDataURL(GURL(base_url_for_data_url)); | 299 entry->SetBaseURLForDataURL(GURL(base_url_for_data_url)); |
275 } | 300 } |
276 | 301 |
277 { | 302 if (state_version >= AW_STATE_VERSION_DATA_URL) { |
278 const char* data; | 303 const char* data; |
279 int size; | 304 int size; |
280 if (!iterator->ReadData(&data, &size)) | 305 if (!iterator->ReadData(&data, &size)) |
281 return false; | 306 return false; |
282 if (size > 0) { | 307 if (size > 0) { |
283 scoped_refptr<base::RefCountedString> ref = new base::RefCountedString(); | 308 scoped_refptr<base::RefCountedString> ref = new base::RefCountedString(); |
284 ref->data().assign(data, size); | 309 ref->data().assign(data, size); |
285 entry->SetDataURLAsString(ref); | 310 entry->SetDataURLAsString(ref); |
286 } | 311 } |
287 } | 312 } |
(...skipping 18 matching lines...) Expand all Loading... |
306 return false; | 331 return false; |
307 entry->SetHttpStatusCode(http_status_code); | 332 entry->SetHttpStatusCode(http_status_code); |
308 } | 333 } |
309 | 334 |
310 return true; | 335 return true; |
311 } | 336 } |
312 | 337 |
313 } // namespace internal | 338 } // namespace internal |
314 | 339 |
315 } // namespace android_webview | 340 } // namespace android_webview |
OLD | NEW |