| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/tab_contents/navigation_controller_impl.h" | 5 #include "content/browser/tab_contents/navigation_controller_impl.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.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 15 matching lines...) Expand all Loading... |
| 26 #include "content/public/browser/user_metrics.h" | 26 #include "content/public/browser/user_metrics.h" |
| 27 #include "content/public/browser/web_contents_delegate.h" | 27 #include "content/public/browser/web_contents_delegate.h" |
| 28 #include "content/public/common/content_constants.h" | 28 #include "content/public/common/content_constants.h" |
| 29 #include "net/base/escape.h" | 29 #include "net/base/escape.h" |
| 30 #include "net/base/mime_util.h" | 30 #include "net/base/mime_util.h" |
| 31 #include "net/base/net_util.h" | 31 #include "net/base/net_util.h" |
| 32 #include "webkit/glue/webkit_glue.h" | 32 #include "webkit/glue/webkit_glue.h" |
| 33 | 33 |
| 34 using content::BrowserContext; | 34 using content::BrowserContext; |
| 35 using content::GlobalRequestID; | 35 using content::GlobalRequestID; |
| 36 using content::NavigationController; |
| 36 using content::NavigationEntry; | 37 using content::NavigationEntry; |
| 37 using content::NavigationEntryImpl; | 38 using content::NavigationEntryImpl; |
| 38 using content::UserMetricsAction; | 39 using content::UserMetricsAction; |
| 39 using content::WebContents; | 40 using content::WebContents; |
| 40 | 41 |
| 41 namespace { | 42 namespace { |
| 42 | 43 |
| 43 const int kInvalidateAll = 0xFFFFFFFF; | 44 const int kInvalidateAll = 0xFFFFFFFF; |
| 44 | 45 |
| 45 // Invoked when entries have been pruned, or removed. For example, if the | 46 // Invoked when entries have been pruned, or removed. For example, if the |
| 46 // current entries are [google, digg, yahoo], with the current entry google, | 47 // current entries are [google, digg, yahoo], with the current entry google, |
| 47 // and the user types in cnet, then digg and yahoo are pruned. | 48 // and the user types in cnet, then digg and yahoo are pruned. |
| 48 void NotifyPrunedEntries(NavigationControllerImpl* nav_controller, | 49 void NotifyPrunedEntries(NavigationControllerImpl* nav_controller, |
| 49 bool from_front, | 50 bool from_front, |
| 50 int count) { | 51 int count) { |
| 51 content::PrunedDetails details; | 52 content::PrunedDetails details; |
| 52 details.from_front = from_front; | 53 details.from_front = from_front; |
| 53 details.count = count; | 54 details.count = count; |
| 54 content::NotificationService::current()->Notify( | 55 content::NotificationService::current()->Notify( |
| 55 content::NOTIFICATION_NAV_LIST_PRUNED, | 56 content::NOTIFICATION_NAV_LIST_PRUNED, |
| 56 content::Source<content::NavigationController>(nav_controller), | 57 content::Source<NavigationController>(nav_controller), |
| 57 content::Details<content::PrunedDetails>(&details)); | 58 content::Details<content::PrunedDetails>(&details)); |
| 58 } | 59 } |
| 59 | 60 |
| 60 // Ensure the given NavigationEntry has a valid state, so that WebKit does not | 61 // Ensure the given NavigationEntry has a valid state, so that WebKit does not |
| 61 // get confused if we navigate back to it. | 62 // get confused if we navigate back to it. |
| 62 // | 63 // |
| 63 // An empty state is treated as a new navigation by WebKit, which would mean | 64 // An empty state is treated as a new navigation by WebKit, which would mean |
| 64 // losing the navigation entries and generating a new navigation entry after | 65 // losing the navigation entries and generating a new navigation entry after |
| 65 // this one. We don't want that. To avoid this we create a valid state which | 66 // this one. We don't want that. To avoid this we create a valid state which |
| 66 // WebKit will not treat as a new navigation. | 67 // WebKit will not treat as a new navigation. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 session_storage_namespace_ = new SessionStorageNamespace( | 182 session_storage_namespace_ = new SessionStorageNamespace( |
| 182 browser_context_->GetWebKitContext()); | 183 browser_context_->GetWebKitContext()); |
| 183 } | 184 } |
| 184 } | 185 } |
| 185 | 186 |
| 186 NavigationControllerImpl::~NavigationControllerImpl() { | 187 NavigationControllerImpl::~NavigationControllerImpl() { |
| 187 DiscardNonCommittedEntriesInternal(); | 188 DiscardNonCommittedEntriesInternal(); |
| 188 | 189 |
| 189 content::NotificationService::current()->Notify( | 190 content::NotificationService::current()->Notify( |
| 190 content::NOTIFICATION_TAB_CLOSED, | 191 content::NOTIFICATION_TAB_CLOSED, |
| 191 content::Source<content::NavigationController>(this), | 192 content::Source<NavigationController>(this), |
| 192 content::NotificationService::NoDetails()); | 193 content::NotificationService::NoDetails()); |
| 193 } | 194 } |
| 194 | 195 |
| 195 WebContents* NavigationControllerImpl::GetWebContents() const { | 196 WebContents* NavigationControllerImpl::GetWebContents() const { |
| 196 return tab_contents_; | 197 return tab_contents_; |
| 197 } | 198 } |
| 198 | 199 |
| 199 BrowserContext* NavigationControllerImpl::GetBrowserContext() const { | 200 BrowserContext* NavigationControllerImpl::GetBrowserContext() const { |
| 200 return browser_context_; | 201 return browser_context_; |
| 201 } | 202 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 return; | 248 return; |
| 248 } | 249 } |
| 249 | 250 |
| 250 if (g_check_for_repost && check_for_repost && | 251 if (g_check_for_repost && check_for_repost && |
| 251 GetEntryAtIndex(current_index)->GetHasPostData()) { | 252 GetEntryAtIndex(current_index)->GetHasPostData()) { |
| 252 // The user is asking to reload a page with POST data. Prompt to make sure | 253 // The user is asking to reload a page with POST data. Prompt to make sure |
| 253 // they really want to do this. If they do, the dialog will call us back | 254 // they really want to do this. If they do, the dialog will call us back |
| 254 // with check_for_repost = false. | 255 // with check_for_repost = false. |
| 255 content::NotificationService::current()->Notify( | 256 content::NotificationService::current()->Notify( |
| 256 content::NOTIFICATION_REPOST_WARNING_SHOWN, | 257 content::NOTIFICATION_REPOST_WARNING_SHOWN, |
| 257 content::Source<content::NavigationController>(this), | 258 content::Source<NavigationController>(this), |
| 258 content::NotificationService::NoDetails()); | 259 content::NotificationService::NoDetails()); |
| 259 | 260 |
| 260 pending_reload_ = reload_type; | 261 pending_reload_ = reload_type; |
| 261 tab_contents_->Activate(); | 262 tab_contents_->Activate(); |
| 262 tab_contents_->GetDelegate()->ShowRepostFormWarningDialog(tab_contents_); | 263 tab_contents_->GetDelegate()->ShowRepostFormWarningDialog(tab_contents_); |
| 263 } else { | 264 } else { |
| 264 DiscardNonCommittedEntriesInternal(); | 265 DiscardNonCommittedEntriesInternal(); |
| 265 | 266 |
| 266 pending_entry_index_ = current_index; | 267 pending_entry_index_ = current_index; |
| 267 entries_[pending_entry_index_]->SetTransitionType( | 268 entries_[pending_entry_index_]->SetTransitionType( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 return; | 309 return; |
| 309 } | 310 } |
| 310 | 311 |
| 311 // When navigating to a new page, we don't know for sure if we will actually | 312 // When navigating to a new page, we don't know for sure if we will actually |
| 312 // end up leaving the current page. The new page load could for example | 313 // end up leaving the current page. The new page load could for example |
| 313 // result in a download or a 'no content' response (e.g., a mailto: URL). | 314 // result in a download or a 'no content' response (e.g., a mailto: URL). |
| 314 DiscardNonCommittedEntriesInternal(); | 315 DiscardNonCommittedEntriesInternal(); |
| 315 pending_entry_ = entry; | 316 pending_entry_ = entry; |
| 316 content::NotificationService::current()->Notify( | 317 content::NotificationService::current()->Notify( |
| 317 content::NOTIFICATION_NAV_ENTRY_PENDING, | 318 content::NOTIFICATION_NAV_ENTRY_PENDING, |
| 318 content::Source<content::NavigationController>(this), | 319 content::Source<NavigationController>(this), |
| 319 content::Details<NavigationEntry>(entry)); | 320 content::Details<NavigationEntry>(entry)); |
| 320 NavigateToPendingEntry(NO_RELOAD); | 321 NavigateToPendingEntry(NO_RELOAD); |
| 321 } | 322 } |
| 322 | 323 |
| 323 NavigationEntry* NavigationControllerImpl::GetActiveEntry() const { | 324 NavigationEntry* NavigationControllerImpl::GetActiveEntry() const { |
| 324 if (transient_entry_index_ != -1) | 325 if (transient_entry_index_ != -1) |
| 325 return entries_[transient_entry_index_].get(); | 326 return entries_[transient_entry_index_].get(); |
| 326 if (pending_entry_) | 327 if (pending_entry_) |
| 327 return pending_entry_; | 328 return pending_entry_; |
| 328 return GetLastCommittedEntry(); | 329 return GetLastCommittedEntry(); |
| (...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 } | 967 } |
| 967 | 968 |
| 968 bool NavigationControllerImpl::IsURLInPageNavigation(const GURL& url) const { | 969 bool NavigationControllerImpl::IsURLInPageNavigation(const GURL& url) const { |
| 969 NavigationEntry* last_committed = GetLastCommittedEntry(); | 970 NavigationEntry* last_committed = GetLastCommittedEntry(); |
| 970 if (!last_committed) | 971 if (!last_committed) |
| 971 return false; | 972 return false; |
| 972 return AreURLsInPageNavigation(last_committed->GetURL(), url); | 973 return AreURLsInPageNavigation(last_committed->GetURL(), url); |
| 973 } | 974 } |
| 974 | 975 |
| 975 void NavigationControllerImpl::CopyStateFrom( | 976 void NavigationControllerImpl::CopyStateFrom( |
| 976 const content::NavigationController& temp) { | 977 const NavigationController& temp) { |
| 977 const NavigationControllerImpl& source = | 978 const NavigationControllerImpl& source = |
| 978 static_cast<const NavigationControllerImpl&>(temp); | 979 static_cast<const NavigationControllerImpl&>(temp); |
| 979 // Verify that we look new. | 980 // Verify that we look new. |
| 980 DCHECK(GetEntryCount() == 0 && !GetPendingEntry()); | 981 DCHECK(GetEntryCount() == 0 && !GetPendingEntry()); |
| 981 | 982 |
| 982 if (source.GetEntryCount() == 0) | 983 if (source.GetEntryCount() == 0) |
| 983 return; // Nothing new to do. | 984 return; // Nothing new to do. |
| 984 | 985 |
| 985 needs_reload_ = true; | 986 needs_reload_ = true; |
| 986 InsertEntriesFrom(source, source.GetEntryCount()); | 987 InsertEntriesFrom(source, source.GetEntryCount()); |
| 987 | 988 |
| 988 session_storage_namespace_ = source.session_storage_namespace_->Clone(); | 989 session_storage_namespace_ = source.session_storage_namespace_->Clone(); |
| 989 | 990 |
| 990 FinishRestore(source.last_committed_entry_index_, false); | 991 FinishRestore(source.last_committed_entry_index_, false); |
| 991 } | 992 } |
| 992 | 993 |
| 993 void NavigationControllerImpl::CopyStateFromAndPrune( | 994 void NavigationControllerImpl::CopyStateFromAndPrune( |
| 994 content::NavigationController* temp) { | 995 NavigationController* temp) { |
| 995 NavigationControllerImpl* source = | 996 NavigationControllerImpl* source = |
| 996 static_cast<NavigationControllerImpl*>(temp); | 997 static_cast<NavigationControllerImpl*>(temp); |
| 997 // The SiteInstance and page_id of the last committed entry needs to be | 998 // The SiteInstance and page_id of the last committed entry needs to be |
| 998 // remembered at this point, in case there is only one committed entry | 999 // remembered at this point, in case there is only one committed entry |
| 999 // and it is pruned. | 1000 // and it is pruned. |
| 1000 NavigationEntryImpl* last_committed = | 1001 NavigationEntryImpl* last_committed = |
| 1001 NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry()); | 1002 NavigationEntryImpl::FromNavigationEntry(GetLastCommittedEntry()); |
| 1002 SiteInstance* site_instance = | 1003 SiteInstance* site_instance = |
| 1003 last_committed ? last_committed->site_instance() : NULL; | 1004 last_committed ? last_committed->site_instance() : NULL; |
| 1004 int32 minimum_page_id = last_committed ? last_committed->GetPageID() : -1; | 1005 int32 minimum_page_id = last_committed ? last_committed->GetPageID() : -1; |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1242 // when it wants to draw. See http://crbug.com/11157 | 1243 // when it wants to draw. See http://crbug.com/11157 |
| 1243 ssl_manager_.DidCommitProvisionalLoad(notification_details); | 1244 ssl_manager_.DidCommitProvisionalLoad(notification_details); |
| 1244 | 1245 |
| 1245 // TODO(pkasting): http://b/1113079 Probably these explicit notification paths | 1246 // TODO(pkasting): http://b/1113079 Probably these explicit notification paths |
| 1246 // should be removed, and interested parties should just listen for the | 1247 // should be removed, and interested parties should just listen for the |
| 1247 // notification below instead. | 1248 // notification below instead. |
| 1248 tab_contents_->NotifyNavigationStateChanged(kInvalidateAll); | 1249 tab_contents_->NotifyNavigationStateChanged(kInvalidateAll); |
| 1249 | 1250 |
| 1250 content::NotificationService::current()->Notify( | 1251 content::NotificationService::current()->Notify( |
| 1251 content::NOTIFICATION_NAV_ENTRY_COMMITTED, | 1252 content::NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 1252 content::Source<content::NavigationController>(this), | 1253 content::Source<NavigationController>(this), |
| 1253 notification_details); | 1254 notification_details); |
| 1254 } | 1255 } |
| 1255 | 1256 |
| 1256 // static | 1257 // static |
| 1257 size_t NavigationControllerImpl::max_entry_count() { | 1258 size_t NavigationControllerImpl::max_entry_count() { |
| 1258 if (max_entry_count_for_testing_ != kMaxEntryCountForTestingNotSet) | 1259 if (max_entry_count_for_testing_ != kMaxEntryCountForTestingNotSet) |
| 1259 return max_entry_count_for_testing_; | 1260 return max_entry_count_for_testing_; |
| 1260 return content::kMaxSessionHistoryEntries; | 1261 return content::kMaxSessionHistoryEntries; |
| 1261 } | 1262 } |
| 1262 | 1263 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1276 NavigateToPendingEntry(NO_RELOAD); | 1277 NavigateToPendingEntry(NO_RELOAD); |
| 1277 } | 1278 } |
| 1278 | 1279 |
| 1279 void NavigationControllerImpl::NotifyEntryChanged(const NavigationEntry* entry, | 1280 void NavigationControllerImpl::NotifyEntryChanged(const NavigationEntry* entry, |
| 1280 int index) { | 1281 int index) { |
| 1281 content::EntryChangedDetails det; | 1282 content::EntryChangedDetails det; |
| 1282 det.changed_entry = entry; | 1283 det.changed_entry = entry; |
| 1283 det.index = index; | 1284 det.index = index; |
| 1284 content::NotificationService::current()->Notify( | 1285 content::NotificationService::current()->Notify( |
| 1285 content::NOTIFICATION_NAV_ENTRY_CHANGED, | 1286 content::NOTIFICATION_NAV_ENTRY_CHANGED, |
| 1286 content::Source<content::NavigationController>(this), | 1287 content::Source<NavigationController>(this), |
| 1287 content::Details<content::EntryChangedDetails>(&det)); | 1288 content::Details<content::EntryChangedDetails>(&det)); |
| 1288 } | 1289 } |
| 1289 | 1290 |
| 1290 void NavigationControllerImpl::FinishRestore(int selected_index, | 1291 void NavigationControllerImpl::FinishRestore(int selected_index, |
| 1291 bool from_last_session) { | 1292 bool from_last_session) { |
| 1292 DCHECK(selected_index >= 0 && selected_index < GetEntryCount()); | 1293 DCHECK(selected_index >= 0 && selected_index < GetEntryCount()); |
| 1293 ConfigureEntriesForRestore(&entries_, from_last_session); | 1294 ConfigureEntriesForRestore(&entries_, from_last_session); |
| 1294 | 1295 |
| 1295 SetMaxRestoredPageID(static_cast<int32>(GetEntryCount())); | 1296 SetMaxRestoredPageID(static_cast<int32>(GetEntryCount())); |
| 1296 | 1297 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1339 for (int i = 0; i < max_index; i++) { | 1340 for (int i = 0; i < max_index; i++) { |
| 1340 // When cloning a tab, copy all entries except interstitial pages | 1341 // When cloning a tab, copy all entries except interstitial pages |
| 1341 if (source.entries_[i].get()->GetPageType() != | 1342 if (source.entries_[i].get()->GetPageType() != |
| 1342 content::PAGE_TYPE_INTERSTITIAL) { | 1343 content::PAGE_TYPE_INTERSTITIAL) { |
| 1343 entries_.insert(entries_.begin() + insert_index++, | 1344 entries_.insert(entries_.begin() + insert_index++, |
| 1344 linked_ptr<NavigationEntryImpl>( | 1345 linked_ptr<NavigationEntryImpl>( |
| 1345 new NavigationEntryImpl(*source.entries_[i]))); | 1346 new NavigationEntryImpl(*source.entries_[i]))); |
| 1346 } | 1347 } |
| 1347 } | 1348 } |
| 1348 } | 1349 } |
| OLD | NEW |