| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "android_webview/native/state_serializer.h" |
| 6 |
| 7 #include <string> |
| 8 #include <vector> |
| 9 |
| 10 #include "base/pickle.h" |
| 11 #include "base/time.h" |
| 12 #include "content/public/browser/navigation_controller.h" |
| 13 #include "content/public/browser/navigation_entry.h" |
| 14 #include "content/public/browser/web_contents.h" |
| 15 |
| 16 using std::string; |
| 17 using std::vector; |
| 18 |
| 19 namespace android_webview { |
| 20 |
| 21 namespace { |
| 22 const uint32 AW_STATE_VERSION = 20121116; |
| 23 } // namespace |
| 24 |
| 25 bool WriteToPickle(const content::WebContents& web_contents, |
| 26 Pickle* pickle) { |
| 27 DCHECK(pickle); |
| 28 |
| 29 if (!WriteHeaderToPickle(pickle)) |
| 30 return false; |
| 31 |
| 32 const content::NavigationController& controller = |
| 33 web_contents.GetController(); |
| 34 const int entry_count = controller.GetEntryCount(); |
| 35 const int selected_entry = controller.GetCurrentEntryIndex(); |
| 36 DCHECK(entry_count >= 0); |
| 37 DCHECK(selected_entry >= -1); // -1 is valid |
| 38 // TODO(boliu): _thispatch_ check correct even if entry_count == 0 |
| 39 DCHECK(selected_entry < entry_count); |
| 40 |
| 41 if (!pickle->WriteInt(entry_count)) |
| 42 return false; |
| 43 |
| 44 if (!pickle->WriteInt(selected_entry)) |
| 45 return false; |
| 46 |
| 47 for (int i = 0; i < entry_count; ++i) { |
| 48 if (!WriteNavigationEntryToPickle(*controller.GetEntryAtIndex(i), pickle)) |
| 49 return false; |
| 50 } |
| 51 |
| 52 return true; |
| 53 } |
| 54 |
| 55 bool RestoreFromPickle(PickleIterator* iterator, |
| 56 content::WebContents* web_contents) { |
| 57 if (!RestoreHeaderFromPickle(iterator)) |
| 58 return false; |
| 59 |
| 60 int entry_count = -1; |
| 61 int selected_entry = -2; // -1 is a valid value |
| 62 if (!iterator->ReadInt(&entry_count)) |
| 63 return false; |
| 64 if (!iterator->ReadInt(&selected_entry)) |
| 65 return false; |
| 66 if (entry_count < 0) |
| 67 return false; |
| 68 if (selected_entry < -1) |
| 69 return false; |
| 70 if (selected_entry >= entry_count) |
| 71 return false; |
| 72 |
| 73 scoped_ptr<content::NavigationEntry> restored_entries[entry_count]; |
| 74 vector<content::NavigationEntry*> restored_entries_vector(entry_count); |
| 75 for (int i = 0; i < entry_count; ++i) { |
| 76 restored_entries[i].reset(content::NavigationEntry::Create()); |
| 77 restored_entries_vector[i] = restored_entries[i].get(); |
| 78 if (!RestoreNavigationEntryFromPickle(iterator, restored_entries[i].get())) |
| 79 return false; |
| 80 } |
| 81 |
| 82 web_contents->GetController().Restore( |
| 83 selected_entry, |
| 84 content::NavigationController::RESTORE_LAST_SESSION_EXITED_CLEANLY, |
| 85 &restored_entries_vector); |
| 86 |
| 87 content::NavigationEntry* unused_warning ALLOW_UNUSED; |
| 88 if (0 == restored_entries_vector.size()) { |
| 89 for (int i = 0; i < entry_count; ++i) { |
| 90 unused_warning = restored_entries[i].release(); |
| 91 } |
| 92 } else { |
| 93 return false; |
| 94 } |
| 95 |
| 96 return true; |
| 97 } |
| 98 |
| 99 bool WriteHeaderToPickle(Pickle* pickle) { |
| 100 return pickle->WriteUInt32(AW_STATE_VERSION); |
| 101 } |
| 102 |
| 103 bool RestoreHeaderFromPickle(PickleIterator* iterator) { |
| 104 uint32 state_version = -1; |
| 105 if (!iterator->ReadUInt32(&state_version)) |
| 106 return false; |
| 107 |
| 108 if (AW_STATE_VERSION != state_version) |
| 109 return false; |
| 110 |
| 111 return true; |
| 112 } |
| 113 |
| 114 bool WriteNavigationEntryToPickle(const content::NavigationEntry& entry, |
| 115 Pickle* pickle) { |
| 116 if (!pickle->WriteString(entry.GetURL().spec())) |
| 117 return false; |
| 118 |
| 119 if (!pickle->WriteString(entry.GetVirtualURL().spec())) |
| 120 return false; |
| 121 |
| 122 // TODO(boliu): _thispatch_ why is base url for data url not persisted? |
| 123 |
| 124 const content::Referrer& referrer = entry.GetReferrer(); |
| 125 if (!pickle->WriteString(referrer.url.spec())) |
| 126 return false; |
| 127 if (!pickle->WriteInt(static_cast<int>(referrer.policy))) |
| 128 return false; |
| 129 |
| 130 if (!pickle->WriteString16(entry.GetTitle())) |
| 131 return false; |
| 132 |
| 133 if (!pickle->WriteString(entry.GetContentState())) |
| 134 return false; |
| 135 |
| 136 /* |
| 137 TODO(boliu): _thispatch_ transition type gets restored to reload? Check. |
| 138 if (!pickle->WriteInt(static_cast<int>(entry.GetTransitionType()))) |
| 139 return false; |
| 140 */ |
| 141 |
| 142 if (!pickle->WriteBool(static_cast<int>(entry.GetHasPostData()))) |
| 143 return false; |
| 144 |
| 145 if (!pickle->WriteString(entry.GetOriginalRequestURL().spec())) |
| 146 return false; |
| 147 |
| 148 if (!pickle->WriteBool(static_cast<int>(entry.GetIsOverridingUserAgent()))) |
| 149 return false; |
| 150 |
| 151 if (!pickle->WriteInt64(entry.GetTimestamp().ToInternalValue())) |
| 152 return false; |
| 153 |
| 154 return true; |
| 155 } |
| 156 |
| 157 bool RestoreNavigationEntryFromPickle(PickleIterator* iterator, |
| 158 content::NavigationEntry* entry) { |
| 159 { |
| 160 string url; |
| 161 if (!iterator->ReadString(&url)) |
| 162 return false; |
| 163 entry->SetURL(GURL(url)); |
| 164 } |
| 165 |
| 166 { |
| 167 string virtual_url; |
| 168 if (!iterator->ReadString(&virtual_url)) |
| 169 return false; |
| 170 entry->SetVirtualURL(GURL(virtual_url)); |
| 171 } |
| 172 |
| 173 { |
| 174 content::Referrer referrer; |
| 175 string referrer_url; |
| 176 int policy; |
| 177 |
| 178 if (!iterator->ReadString(&referrer_url)) |
| 179 return false; |
| 180 if (!iterator->ReadInt(&policy)) |
| 181 return false; |
| 182 |
| 183 referrer.url = GURL(referrer_url); |
| 184 referrer.policy = static_cast<WebKit::WebReferrerPolicy>(policy); |
| 185 entry->SetReferrer(referrer); |
| 186 } |
| 187 |
| 188 { |
| 189 string16 title; |
| 190 if (!iterator->ReadString16(&title)) |
| 191 return false; |
| 192 entry->SetTitle(title); |
| 193 } |
| 194 |
| 195 { |
| 196 string content_state; |
| 197 if (!iterator->ReadString(&content_state)) |
| 198 return false; |
| 199 entry->SetContentState(content_state); |
| 200 } |
| 201 |
| 202 { |
| 203 bool has_post_data; |
| 204 if (!iterator->ReadBool(&has_post_data)) |
| 205 return false; |
| 206 entry->SetHasPostData(has_post_data); |
| 207 } |
| 208 |
| 209 { |
| 210 string original_request_url; |
| 211 if (!iterator->ReadString(&original_request_url)) |
| 212 return false; |
| 213 entry->SetOriginalRequestURL(GURL(original_request_url)); |
| 214 } |
| 215 |
| 216 { |
| 217 bool is_overriding_user_agent; |
| 218 if (!iterator->ReadBool(&is_overriding_user_agent)) |
| 219 return false; |
| 220 entry->SetIsOverridingUserAgent(is_overriding_user_agent); |
| 221 } |
| 222 |
| 223 { |
| 224 int64 timestamp; |
| 225 if (!iterator->ReadInt64(×tamp)) |
| 226 return false; |
| 227 entry->SetTimestamp(base::Time::FromInternalValue(timestamp)); |
| 228 } |
| 229 |
| 230 return true; |
| 231 } |
| 232 |
| 233 } // namespace android_webview |
| OLD | NEW |