Index: content/browser/tab_contents/navigation_controller.cc |
diff --git a/content/browser/tab_contents/navigation_controller.cc b/content/browser/tab_contents/navigation_controller.cc |
index ddaf3004c52e03b69f043d79a8716a6840e39415..11c90d3cc0a7469f6e92bad6553d052a06389b70 100644 |
--- a/content/browser/tab_contents/navigation_controller.cc |
+++ b/content/browser/tab_contents/navigation_controller.cc |
@@ -222,7 +222,7 @@ bool NavigationController::IsInitialNavigation() { |
// static |
NavigationEntry* NavigationController::CreateNavigationEntry( |
const GURL& url, const GURL& referrer, content::PageTransition transition, |
- const std::string& extra_headers, |
+ bool is_renderer_initiated, const std::string& extra_headers, |
content::BrowserContext* browser_context) { |
// Allow the browser URL handler to rewrite the URL. This will, for example, |
// remove "view-source:" from the beginning of the URL to get the URL that |
@@ -240,7 +240,8 @@ NavigationEntry* NavigationController::CreateNavigationEntry( |
loaded_url, |
referrer, |
string16(), |
- transition); |
+ transition, |
+ is_renderer_initiated); |
entry->set_virtual_url(url); |
entry->set_user_typed_url(url); |
entry->set_update_virtual_url_with_url(reverse_on_redirect); |
@@ -291,8 +292,15 @@ NavigationEntry* NavigationController::GetActiveEntry() const { |
NavigationEntry* NavigationController::GetVisibleEntry() const { |
if (transient_entry_index_ != -1) |
return entries_[transient_entry_index_].get(); |
- // Only return pending_entry for new navigations. |
- if (pending_entry_ && pending_entry_->page_id() == -1) |
+ // Only return the pending_entry for new (non-history), browser-initiated |
+ // navigations, in order to prevent URL spoof attacks. |
+ // Ideally we would also show the pending entry's URL for new renderer- |
+ // initiated navigations with no last committed entry (e.g., a link opening |
+ // in a new tab), but an attacker can insert content into the about:blank |
+ // page while the pending URL loads in that case. |
+ if (pending_entry_ && |
+ pending_entry_->page_id() == -1 && |
+ !pending_entry_->is_renderer_initiated()) |
return pending_entry_; |
return GetLastCommittedEntry(); |
} |
@@ -496,6 +504,23 @@ void NavigationController::LoadURL( |
needs_reload_ = false; |
NavigationEntry* entry = CreateNavigationEntry(url, referrer, transition, |
+ false, |
+ extra_headers, |
+ browser_context_); |
+ |
+ LoadEntry(entry); |
+} |
+ |
+void NavigationController::LoadURLFromRenderer( |
+ const GURL& url, |
+ const GURL& referrer, |
+ content::PageTransition transition, |
+ const std::string& extra_headers) { |
+ // The user initiated a load, we don't need to reload anymore. |
+ needs_reload_ = false; |
+ |
+ NavigationEntry* entry = CreateNavigationEntry(url, referrer, transition, |
+ true, |
extra_headers, |
browser_context_); |
@@ -571,6 +596,10 @@ bool NavigationController::RendererDidNavigate( |
NavigationEntry* active_entry = GetActiveEntry(); |
active_entry->set_content_state(params.content_state); |
+ // Once committed, we do not need to track if the entry was initiated by |
+ // the renderer. |
+ active_entry->set_is_renderer_initiated(false); |
+ |
// The active entry's SiteInstance should match our SiteInstance. |
DCHECK(active_entry->site_instance() == tab_contents_->GetSiteInstance()); |