| 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 "content/browser/web_contents/navigation_controller_impl.h" | 5 #include "content/browser/web_contents/navigation_controller_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/string_number_conversions.h" // Temporary | 9 #include "base/string_number_conversions.h" // Temporary |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 1186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1197 FinishRestore(source.last_committed_entry_index_, RESTORE_CURRENT_SESSION); | 1197 FinishRestore(source.last_committed_entry_index_, RESTORE_CURRENT_SESSION); |
| 1198 | 1198 |
| 1199 // Copy the max page id map from the old tab to the new tab. This ensures | 1199 // Copy the max page id map from the old tab to the new tab. This ensures |
| 1200 // that new and existing navigations in the tab's current SiteInstances | 1200 // that new and existing navigations in the tab's current SiteInstances |
| 1201 // are identified properly. | 1201 // are identified properly. |
| 1202 web_contents_->CopyMaxPageIDsFrom(source.web_contents()); | 1202 web_contents_->CopyMaxPageIDsFrom(source.web_contents()); |
| 1203 } | 1203 } |
| 1204 | 1204 |
| 1205 void NavigationControllerImpl::CopyStateFromAndPrune( | 1205 void NavigationControllerImpl::CopyStateFromAndPrune( |
| 1206 NavigationController* temp) { | 1206 NavigationController* temp) { |
| 1207 // It is up to callers to check the invariants before calling this. |
| 1208 CHECK(CanPruneAllButVisible()); |
| 1209 |
| 1207 NavigationControllerImpl* source = | 1210 NavigationControllerImpl* source = |
| 1208 static_cast<NavigationControllerImpl*>(temp); | 1211 static_cast<NavigationControllerImpl*>(temp); |
| 1209 // The SiteInstance and page_id of the last committed entry needs to be | 1212 // The SiteInstance and page_id of the last committed entry needs to be |
| 1210 // remembered at this point, in case there is only one committed entry | 1213 // remembered at this point, in case there is only one committed entry |
| 1211 // and it is pruned. We use a scoped_refptr to ensure the SiteInstance | 1214 // and it is pruned. We use a scoped_refptr to ensure the SiteInstance |
| 1212 // can't be freed during this time period. | 1215 // can't be freed during this time period. |
| 1213 NavigationEntryImpl* last_committed = | 1216 NavigationEntryImpl* last_committed = |
| 1214 NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry()); | 1217 NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry()); |
| 1215 scoped_refptr<SiteInstance> site_instance( | 1218 scoped_refptr<SiteInstance> site_instance( |
| 1216 last_committed ? last_committed->site_instance() : NULL); | 1219 last_committed->site_instance()); |
| 1217 int32 minimum_page_id = last_committed ? last_committed->GetPageID() : -1; | 1220 int32 minimum_page_id = last_committed->GetPageID(); |
| 1218 int32 max_page_id = last_committed ? | 1221 int32 max_page_id = |
| 1219 web_contents_->GetMaxPageIDForSiteInstance(site_instance.get()) : -1; | 1222 web_contents_->GetMaxPageIDForSiteInstance(site_instance.get()); |
| 1220 | |
| 1221 // This code is intended for use when the last entry is the active entry. | |
| 1222 DCHECK( | |
| 1223 (transient_entry_index_ != -1 && | |
| 1224 transient_entry_index_ == GetEntryCount() - 1) || | |
| 1225 (pending_entry_ && (pending_entry_index_ == -1 || | |
| 1226 pending_entry_index_ == GetEntryCount() - 1)) || | |
| 1227 (!pending_entry_ && last_committed_entry_index_ == GetEntryCount() - 1)); | |
| 1228 | 1223 |
| 1229 // Remove all the entries leaving the active entry. | 1224 // Remove all the entries leaving the active entry. |
| 1230 PruneAllButActiveInternal(); | 1225 PruneAllButVisibleInternal(); |
| 1231 | 1226 |
| 1232 // We now have zero or one entries. Ensure that adding the entries from | 1227 // We now have one entry, possibly with a new pending entry. Ensure that |
| 1233 // source won't put us over the limit. | 1228 // adding the entries from source won't put us over the limit. |
| 1234 DCHECK(GetEntryCount() == 0 || GetEntryCount() == 1); | 1229 DCHECK_EQ(1, GetEntryCount()); |
| 1235 if (GetEntryCount() > 0) | 1230 source->PruneOldestEntryIfFull(); |
| 1236 source->PruneOldestEntryIfFull(); | |
| 1237 | 1231 |
| 1238 // Insert the entries from source. Don't use source->GetCurrentEntryIndex as | 1232 // Insert the entries from source. Don't use source->GetCurrentEntryIndex as |
| 1239 // we don't want to copy over the transient entry. | 1233 // we don't want to copy over the transient entry. Ignore any pending entry, |
| 1240 int max_source_index = source->pending_entry_index_ != -1 ? | 1234 // since it has not committed in source. |
| 1241 source->pending_entry_index_ : source->last_committed_entry_index_; | 1235 int max_source_index = source->last_committed_entry_index_; |
| 1242 if (max_source_index == -1) | 1236 if (max_source_index == -1) |
| 1243 max_source_index = source->GetEntryCount(); | 1237 max_source_index = source->GetEntryCount(); |
| 1244 else | 1238 else |
| 1245 max_source_index++; | 1239 max_source_index++; |
| 1246 InsertEntriesFrom(*source, max_source_index); | 1240 InsertEntriesFrom(*source, max_source_index); |
| 1247 | 1241 |
| 1248 // Adjust indices such that the last entry and pending are at the end now. | 1242 // Adjust indices such that the last entry and pending are at the end now. |
| 1249 last_committed_entry_index_ = GetEntryCount() - 1; | 1243 last_committed_entry_index_ = GetEntryCount() - 1; |
| 1250 if (pending_entry_index_ != -1) | |
| 1251 pending_entry_index_ = GetEntryCount() - 1; | |
| 1252 if (transient_entry_index_ != -1) { | |
| 1253 // There's a transient entry. In this case we want the last committed to | |
| 1254 // point to the previous entry. | |
| 1255 transient_entry_index_ = GetEntryCount() - 1; | |
| 1256 if (last_committed_entry_index_ != -1) | |
| 1257 last_committed_entry_index_--; | |
| 1258 } | |
| 1259 | 1244 |
| 1260 web_contents_->SetHistoryLengthAndPrune(site_instance.get(), | 1245 web_contents_->SetHistoryLengthAndPrune(site_instance.get(), |
| 1261 max_source_index, | 1246 max_source_index, |
| 1262 minimum_page_id); | 1247 minimum_page_id); |
| 1263 | 1248 |
| 1264 // Copy the max page id map from the old tab to the new tab. This ensures | 1249 // Copy the max page id map from the old tab to the new tab. This ensures |
| 1265 // that new and existing navigations in the tab's current SiteInstances | 1250 // that new and existing navigations in the tab's current SiteInstances |
| 1266 // are identified properly. | 1251 // are identified properly. |
| 1267 web_contents_->CopyMaxPageIDsFrom(source->web_contents()); | 1252 web_contents_->CopyMaxPageIDsFrom(source->web_contents()); |
| 1268 | 1253 |
| 1269 // If there is a last committed entry, be sure to include it in the new | 1254 // If there is a last committed entry, be sure to include it in the new |
| 1270 // max page ID map. | 1255 // max page ID map. |
| 1271 if (max_page_id > -1) { | 1256 if (max_page_id > -1) { |
| 1272 web_contents_->UpdateMaxPageIDForSiteInstance(site_instance.get(), | 1257 web_contents_->UpdateMaxPageIDForSiteInstance(site_instance.get(), |
| 1273 max_page_id); | 1258 max_page_id); |
| 1274 } | 1259 } |
| 1275 } | 1260 } |
| 1276 | 1261 |
| 1277 void NavigationControllerImpl::PruneAllButActive() { | 1262 bool NavigationControllerImpl::CanPruneAllButVisible() { |
| 1278 PruneAllButActiveInternal(); | 1263 // If there is no last committed entry, we cannot prune. Even if there is a |
| 1264 // pending entry, it may not commit, leaving this WebContents blank, despite |
| 1265 // possibly giving it new entries via CopyStateFromAndPrune. |
| 1266 if (last_committed_entry_index_ == -1) |
| 1267 return false; |
| 1279 | 1268 |
| 1280 // If there is an entry left, we need to update the session history length of | 1269 // We cannot prune if there is a pending entry at an existing entry index. |
| 1281 // the RenderView. | 1270 // It may not commit, so we have to keep the last committed entry, and thus |
| 1282 if (!GetActiveEntry()) | 1271 // there is no sensible place to keep the pending entry. It is ok to have |
| 1283 return; | 1272 // a new pending entry, which can optionally commit as a new navigation. |
| 1273 if (pending_entry_index_ != -1) |
| 1274 return false; |
| 1275 |
| 1276 // We should not prune if we are currently showing a transient entry. |
| 1277 if (transient_entry_index_ != -1) |
| 1278 return false; |
| 1279 |
| 1280 return true; |
| 1281 } |
| 1282 |
| 1283 void NavigationControllerImpl::PruneAllButVisible() { |
| 1284 PruneAllButVisibleInternal(); |
| 1285 |
| 1286 // We should still have a last committed entry. |
| 1287 DCHECK_NE(-1, last_committed_entry_index_); |
| 1284 | 1288 |
| 1285 NavigationEntryImpl* entry = | 1289 NavigationEntryImpl* entry = |
| 1286 NavigationEntryImpl::FromNavigationEntry(GetActiveEntry()); | 1290 NavigationEntryImpl::FromNavigationEntry(GetActiveEntry()); |
| 1287 // We pass 0 instead of GetEntryCount() for the history_length parameter of | 1291 // We pass 0 instead of GetEntryCount() for the history_length parameter of |
| 1288 // SetHistoryLengthAndPrune, because it will create history_length additional | 1292 // SetHistoryLengthAndPrune, because it will create history_length additional |
| 1289 // history entries. | 1293 // history entries. |
| 1290 // TODO(jochen): This API is confusing and we should clean it up. | 1294 // TODO(jochen): This API is confusing and we should clean it up. |
| 1291 // http://crbug.com/178491 | 1295 // http://crbug.com/178491 |
| 1292 web_contents_->SetHistoryLengthAndPrune( | 1296 web_contents_->SetHistoryLengthAndPrune( |
| 1293 entry->site_instance(), 0, entry->GetPageID()); | 1297 entry->site_instance(), 0, entry->GetPageID()); |
| 1294 } | 1298 } |
| 1295 | 1299 |
| 1296 void NavigationControllerImpl::PruneAllButActiveInternal() { | 1300 void NavigationControllerImpl::PruneAllButVisibleInternal() { |
| 1297 if (transient_entry_index_ != -1) { | 1301 // It is up to callers to check the invariants before calling this. |
| 1298 // There is a transient entry. Prune up to it. | 1302 CHECK(CanPruneAllButVisible()); |
| 1299 DCHECK_EQ(GetEntryCount() - 1, transient_entry_index_); | |
| 1300 entries_.erase(entries_.begin(), entries_.begin() + transient_entry_index_); | |
| 1301 transient_entry_index_ = 0; | |
| 1302 last_committed_entry_index_ = -1; | |
| 1303 pending_entry_index_ = -1; | |
| 1304 } else if (!pending_entry_) { | |
| 1305 // There's no pending entry. Leave the last entry (if there is one). | |
| 1306 if (!GetEntryCount()) | |
| 1307 return; | |
| 1308 | 1303 |
| 1309 DCHECK_GE(last_committed_entry_index_, 0); | 1304 // Erase all entries but the last committed entry. There may still be a |
| 1310 entries_.erase(entries_.begin(), | 1305 // new pending entry after this. |
| 1311 entries_.begin() + last_committed_entry_index_); | 1306 entries_.erase(entries_.begin(), |
| 1312 entries_.erase(entries_.begin() + 1, entries_.end()); | 1307 entries_.begin() + last_committed_entry_index_); |
| 1313 last_committed_entry_index_ = 0; | 1308 entries_.erase(entries_.begin() + 1, entries_.end()); |
| 1314 } else if (pending_entry_index_ != -1) { | 1309 last_committed_entry_index_ = 0; |
| 1315 entries_.erase(entries_.begin(), entries_.begin() + pending_entry_index_); | |
| 1316 entries_.erase(entries_.begin() + 1, entries_.end()); | |
| 1317 pending_entry_index_ = 0; | |
| 1318 last_committed_entry_index_ = 0; | |
| 1319 } else { | |
| 1320 // There is a pending_entry, but it's not in entries_. | |
| 1321 pending_entry_index_ = -1; | |
| 1322 last_committed_entry_index_ = -1; | |
| 1323 entries_.clear(); | |
| 1324 } | |
| 1325 | |
| 1326 if (web_contents_->GetInterstitialPage()) { | |
| 1327 // Normally the interstitial page hides itself if the user doesn't proceeed. | |
| 1328 // This would result in showing a NavigationEntry we just removed. Set this | |
| 1329 // so the interstitial triggers a reload if the user doesn't proceed. | |
| 1330 static_cast<InterstitialPageImpl*>(web_contents_->GetInterstitialPage())-> | |
| 1331 set_reload_on_dont_proceed(true); | |
| 1332 } | |
| 1333 } | 1310 } |
| 1334 | 1311 |
| 1335 void NavigationControllerImpl::ClearAllScreenshots() { | 1312 void NavigationControllerImpl::ClearAllScreenshots() { |
| 1336 screenshot_manager_->ClearAllScreenshots(); | 1313 screenshot_manager_->ClearAllScreenshots(); |
| 1337 } | 1314 } |
| 1338 | 1315 |
| 1339 void NavigationControllerImpl::SetSessionStorageNamespace( | 1316 void NavigationControllerImpl::SetSessionStorageNamespace( |
| 1340 const std::string& partition_id, | 1317 const std::string& partition_id, |
| 1341 SessionStorageNamespace* session_storage_namespace) { | 1318 SessionStorageNamespace* session_storage_namespace) { |
| 1342 if (!session_storage_namespace) | 1319 if (!session_storage_namespace) |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1674 } | 1651 } |
| 1675 } | 1652 } |
| 1676 } | 1653 } |
| 1677 | 1654 |
| 1678 void NavigationControllerImpl::SetGetTimestampCallbackForTest( | 1655 void NavigationControllerImpl::SetGetTimestampCallbackForTest( |
| 1679 const base::Callback<base::Time()>& get_timestamp_callback) { | 1656 const base::Callback<base::Time()>& get_timestamp_callback) { |
| 1680 get_timestamp_callback_ = get_timestamp_callback; | 1657 get_timestamp_callback_ = get_timestamp_callback; |
| 1681 } | 1658 } |
| 1682 | 1659 |
| 1683 } // namespace content | 1660 } // namespace content |
| OLD | NEW |