| 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 |