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