summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/dom_ui/dom_ui_unittest.cc116
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.cc34
-rw-r--r--chrome/browser/tab_contents/render_view_host_manager.cc66
-rw-r--r--chrome/browser/tab_contents/render_view_host_manager.h50
-rw-r--r--chrome/browser/tab_contents/web_contents.cc89
-rw-r--r--chrome/browser/tab_contents/web_contents.h11
6 files changed, 286 insertions, 80 deletions
diff --git a/chrome/browser/dom_ui/dom_ui_unittest.cc b/chrome/browser/dom_ui/dom_ui_unittest.cc
new file mode 100644
index 0000000..40a5617
--- /dev/null
+++ b/chrome/browser/dom_ui/dom_ui_unittest.cc
@@ -0,0 +1,116 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/dom_ui/new_tab_ui.h"
+#include "chrome/browser/renderer_host/test_render_view_host.h"
+#include "chrome/common/url_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class DOMUITest : public RenderViewHostTestHarness {
+ public:
+ DOMUITest() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DOMUITest);
+};
+
+// Tests that the New Tab Page flags are correctly set and propogated by
+// WebContents when we first navigate to a DOM UI page, then to a standard
+// non-DOM-UI page.
+TEST_F(DOMUITest, DOMUIToStandard) {
+ // Start a pending load.
+ GURL new_tab_url(chrome::kChromeUINewTabURL);
+ controller()->LoadURL(new_tab_url, GURL(), PageTransition::LINK);
+
+ // The navigation entry should be pending with no committed entry.
+ ASSERT_TRUE(controller()->GetPendingEntry());
+ ASSERT_FALSE(controller()->GetLastCommittedEntry());
+
+ // Check the things the pending DOM UI should have set.
+ EXPECT_FALSE(contents()->ShouldDisplayURL());
+ EXPECT_FALSE(contents()->ShouldDisplayFavIcon());
+ EXPECT_TRUE(contents()->IsBookmarkBarAlwaysVisible());
+ EXPECT_TRUE(contents()->FocusLocationBarByDefault());
+
+ // Now commit the load.
+ rvh()->SendNavigate(1, new_tab_url);
+
+ // The same flags should be set as before now that the load has committed.
+ // Note that the location bar isn't focused now. Once the load commits, we
+ // don't care about this flag, so this value is OK.
+ EXPECT_FALSE(contents()->ShouldDisplayURL());
+ EXPECT_FALSE(contents()->ShouldDisplayFavIcon());
+ EXPECT_TRUE(contents()->IsBookmarkBarAlwaysVisible());
+ EXPECT_FALSE(contents()->FocusLocationBarByDefault());
+
+ // Start a pending navigation to a regular page.
+ GURL next_url("http://google.com/");
+ controller()->LoadURL(next_url, GURL(), PageTransition::LINK);
+
+ // Check the flags. Some should reflect the new page (URL, title), some should
+ // reflect the old one (bookmark bar) until it has committed.
+ EXPECT_TRUE(contents()->ShouldDisplayURL());
+ EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
+ EXPECT_TRUE(contents()->IsBookmarkBarAlwaysVisible());
+ EXPECT_FALSE(contents()->FocusLocationBarByDefault());
+
+ // Commit the regular page load. Note that we must send it to the "pending"
+ // RenderViewHost, since this transition will also cause a process transition,
+ // and our RVH pointer will be the "committed" one.
+ static_cast<TestRenderViewHost*>(
+ contents()->render_manager()->pending_render_view_host())->SendNavigate(
+ 2, next_url);
+
+ // The state should now reflect a regular page.
+ EXPECT_TRUE(contents()->ShouldDisplayURL());
+ EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
+ EXPECT_FALSE(contents()->IsBookmarkBarAlwaysVisible());
+ EXPECT_FALSE(contents()->FocusLocationBarByDefault());
+}
+
+TEST_F(DOMUITest, DOMUIToDOMUI) {
+ // Do a load (this state is tested above).
+ GURL new_tab_url(chrome::kChromeUINewTabURL);
+ controller()->LoadURL(new_tab_url, GURL(), PageTransition::LINK);
+ rvh()->SendNavigate(1, new_tab_url);
+
+ // Start another pending load of the new tab page.
+ controller()->LoadURL(new_tab_url, GURL(), PageTransition::LINK);
+ rvh()->SendNavigate(2, new_tab_url);
+
+ // The flags should be the same as the non-pending state.
+ EXPECT_FALSE(contents()->ShouldDisplayURL());
+ EXPECT_FALSE(contents()->ShouldDisplayFavIcon());
+ EXPECT_TRUE(contents()->IsBookmarkBarAlwaysVisible());
+ EXPECT_FALSE(contents()->FocusLocationBarByDefault());
+}
+
+TEST_F(DOMUITest, StandardToDOMUI) {
+ // Start a pending navigation to a regular page.
+ GURL std_url("http://google.com/");
+ controller()->LoadURL(std_url, GURL(), PageTransition::LINK);
+
+ // The state should now reflect the default.
+ EXPECT_TRUE(contents()->ShouldDisplayURL());
+ EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
+ EXPECT_FALSE(contents()->IsBookmarkBarAlwaysVisible());
+ EXPECT_FALSE(contents()->FocusLocationBarByDefault());
+
+ // Commit the load, the state should be the same.
+ rvh()->SendNavigate(1, std_url);
+ EXPECT_TRUE(contents()->ShouldDisplayURL());
+ EXPECT_TRUE(contents()->ShouldDisplayFavIcon());
+ EXPECT_FALSE(contents()->IsBookmarkBarAlwaysVisible());
+ EXPECT_FALSE(contents()->FocusLocationBarByDefault());
+
+ // Start a pending load for a DOMUI.
+ GURL new_tab_url(chrome::kChromeUINewTabURL);
+ controller()->LoadURL(new_tab_url, GURL(), PageTransition::LINK);
+ EXPECT_FALSE(contents()->ShouldDisplayURL());
+ EXPECT_FALSE(contents()->ShouldDisplayFavIcon());
+ EXPECT_FALSE(contents()->IsBookmarkBarAlwaysVisible());
+ EXPECT_TRUE(contents()->FocusLocationBarByDefault());
+
+ // Committing DOM UI is tested above.
+}
diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc
index 199e5db..8318f15 100644
--- a/chrome/browser/dom_ui/new_tab_ui.cc
+++ b/chrome/browser/dom_ui/new_tab_ui.cc
@@ -382,16 +382,19 @@ MostVisitedHandler::MostVisitedHandler(DOMUI* dom_ui)
dom_ui_->RegisterMessageCallback("getMostVisited",
NewCallback(this, &MostVisitedHandler::HandleGetMostVisited));
- // Set up our sources for thumbnail and favicon data.
- // Ownership is passed to the ChromeURLDataManager.
- g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(&chrome_url_data_manager,
- &ChromeURLDataManager::AddDataSource,
- new DOMUIThumbnailSource(dom_ui->GetProfile())));
- g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(&chrome_url_data_manager,
- &ChromeURLDataManager::AddDataSource,
- new DOMUIFavIconSource(dom_ui->GetProfile())));
+ // Set up our sources for thumbnail and favicon data. Since we may be in
+ // testing mode with no I/O thread, only add our handler when an I/O thread
+ // exists. Ownership is passed to the ChromeURLDataManager.
+ if (g_browser_process->io_thread()) {
+ g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(&chrome_url_data_manager,
+ &ChromeURLDataManager::AddDataSource,
+ new DOMUIThumbnailSource(dom_ui->GetProfile())));
+ g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(&chrome_url_data_manager,
+ &ChromeURLDataManager::AddDataSource,
+ new DOMUIFavIconSource(dom_ui->GetProfile())));
+ }
// Get notifications when history is cleared.
NotificationService* service = NotificationService::current();
@@ -1052,9 +1055,12 @@ NewTabUI::NewTabUI(WebContents* contents)
NewTabHTMLSource* html_source = new NewTabHTMLSource();
- g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(&chrome_url_data_manager,
- &ChromeURLDataManager::AddDataSource,
- html_source));
+ // In testing mode there may not be an I/O thread.
+ if (g_browser_process->io_thread()) {
+ g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
+ NewRunnableMethod(&chrome_url_data_manager,
+ &ChromeURLDataManager::AddDataSource,
+ html_source));
+ }
}
}
diff --git a/chrome/browser/tab_contents/render_view_host_manager.cc b/chrome/browser/tab_contents/render_view_host_manager.cc
index d1f8259..d22b052 100644
--- a/chrome/browser/tab_contents/render_view_host_manager.cc
+++ b/chrome/browser/tab_contents/render_view_host_manager.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/logging.h"
+#include "chrome/browser/dom_ui/dom_ui.h"
#include "chrome/browser/dom_ui/dom_ui_factory.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
@@ -57,7 +58,7 @@ void RenderViewHostManager::Init(Profile* profile,
void RenderViewHostManager::Shutdown() {
if (pending_render_view_host_)
- CancelPendingRenderView();
+ CancelPending();
// We should always have a main RenderViewHost.
RenderViewHost* render_view_host = render_view_host_;
@@ -66,10 +67,15 @@ void RenderViewHostManager::Shutdown() {
}
RenderViewHost* RenderViewHostManager::Navigate(const NavigationEntry& entry) {
- RenderViewHost* dest_render_view_host = UpdateRendererStateNavigate(entry);
+ // Create a pending RenderViewHost. It will give us the one we should use
+ RenderViewHost* dest_render_view_host = UpdateRendererStateForNavigate(entry);
if (!dest_render_view_host)
return NULL; // We weren't able to create a pending render view host.
+ // This will possibly create (set to NULL) a DOM UI object for the pending
+ // page. We'll use this later to give the page special access.
+ pending_dom_ui_.reset(delegate_->CreateDOMUIForRenderManager(entry.url()));
+
// If the current render_view_host_ isn't live, we should create it so
// that we don't show a sad tab while the dest_render_view_host fetches
// its first page. (Bug 1145340)
@@ -92,7 +98,7 @@ RenderViewHost* RenderViewHostManager::Navigate(const NavigationEntry& entry) {
dest_render_view_host->view()->Hide();
} else {
// This is our primary renderer, notify here as we won't be calling
- // SwapToRenderView (which does the notify).
+ // CommitPending (which does the notify).
RenderViewHostSwitchedDetails details;
details.new_host = render_view_host_;
details.old_host = NULL;
@@ -112,10 +118,8 @@ void RenderViewHostManager::Stop() {
// If we are cross-navigating, we should stop the pending renderers. This
// will lead to a DidFailProvisionalLoad, which will properly destroy them.
- if (cross_navigation_pending_) {
+ if (cross_navigation_pending_)
pending_render_view_host_->Stop();
-
- }
}
void RenderViewHostManager::SetIsLoading(bool is_loading) {
@@ -157,19 +161,25 @@ bool RenderViewHostManager::ShouldCloseTabOnUnresponsiveRenderer() {
void RenderViewHostManager::DidNavigateMainFrame(
RenderViewHost* render_view_host) {
if (!cross_navigation_pending_) {
+ DCHECK(!pending_render_view_host_);
+
// We should only hear this from our current renderer.
DCHECK(render_view_host == render_view_host_);
+
+ // Even when there is no pending RVH, there may be a pending DOM UI.
+ if (pending_dom_ui_.get())
+ CommitPending();
return;
}
if (render_view_host == pending_render_view_host_) {
// The pending cross-site navigation completed, so show the renderer.
- SwapToRenderView(&pending_render_view_host_, true);
+ CommitPending();
cross_navigation_pending_ = false;
} else if (render_view_host == render_view_host_) {
// A navigation in the original page has taken place. Cancel the pending
// one.
- CancelPendingRenderView();
+ CancelPending();
cross_navigation_pending_ = false;
} else {
// No one else should be sending us DidNavigate in this state.
@@ -237,7 +247,7 @@ void RenderViewHostManager::ShouldClosePage(bool proceed) {
pending_render_view_host_->SetNavigationsSuspended(false);
} else {
// Current page says to cancel.
- CancelPendingRenderView();
+ CancelPending();
cross_navigation_pending_ = false;
}
}
@@ -397,7 +407,7 @@ bool RenderViewHostManager::CreatePendingRenderView(SiteInstance* instance) {
// Don't show the view until we get a DidNavigate from it.
pending_render_view_host_->view()->Hide();
} else {
- CancelPendingRenderView();
+ CancelPending();
}
return success;
}
@@ -415,9 +425,17 @@ RenderViewHost* RenderViewHostManager::CreateRenderViewHost(
}
}
-void RenderViewHostManager::SwapToRenderView(
- RenderViewHost** new_render_view_host,
- bool destroy_after) {
+void RenderViewHostManager::CommitPending() {
+ // First commit the DOM UI, if any.
+ dom_ui_.swap(pending_dom_ui_);
+ pending_dom_ui_.reset();
+
+ // It's possible for the pending_render_view_host_ to be NULL when we aren't
+ // crossing process boundaries. If so, we just needed to handle the DOM UI
+ // committing above and we're done.
+ if (!pending_render_view_host_)
+ return;
+
// Remember if the page was focused so we can focus the new renderer in
// that case.
bool focus_render_view = render_view_host_->view() &&
@@ -431,8 +449,8 @@ void RenderViewHostManager::SwapToRenderView(
RenderViewHost* old_render_view_host = render_view_host_;
// Swap in the pending view and make it active.
- render_view_host_ = (*new_render_view_host);
- (*new_render_view_host) = NULL;
+ render_view_host_ = pending_render_view_host_;
+ pending_render_view_host_ = NULL;
// If the view is gone, then this RenderViewHost died while it was hidden.
// We ignored the RenderViewGone call at the time, so we should send it now
@@ -456,21 +474,20 @@ void RenderViewHostManager::SwapToRenderView(
Source<NavigationController>(delegate_->GetControllerForRenderManager()),
Details<RenderViewHostSwitchedDetails>(&details));
- if (destroy_after)
- old_render_view_host->Shutdown();
+ old_render_view_host->Shutdown();
// Let the task manager know that we've swapped RenderViewHosts, since it
// might need to update its process groupings.
delegate_->NotifySwappedFromRenderManager();
}
-RenderViewHost* RenderViewHostManager::UpdateRendererStateNavigate(
+RenderViewHost* RenderViewHostManager::UpdateRendererStateForNavigate(
const NavigationEntry& entry) {
// If we are cross-navigating, then we want to get back to normal and navigate
// as usual.
if (cross_navigation_pending_) {
if (pending_render_view_host_)
- CancelPendingRenderView();
+ CancelPending();
cross_navigation_pending_ = false;
}
@@ -485,7 +502,8 @@ RenderViewHost* RenderViewHostManager::UpdateRendererStateNavigate(
if (ShouldTransitionCrossSite())
new_instance = GetSiteInstanceForEntry(entry, curr_instance);
- if (new_instance != curr_instance || ShouldSwapRenderViewsForNavigation(
+ if (new_instance != curr_instance ||
+ ShouldSwapRenderViewsForNavigation(
delegate_->GetLastCommittedNavigationEntryForRenderManager(),
&entry)) {
// New SiteInstance.
@@ -504,7 +522,7 @@ RenderViewHost* RenderViewHostManager::UpdateRendererStateNavigate(
// navigate. Just switch to the pending RVH now and go back to non
// cross-navigating (Note that we don't care about on{before}unload
// handlers if the current RVH isn't live.)
- SwapToRenderView(&pending_render_view_host_, true);
+ CommitPending();
return render_view_host_;
} else {
NOTREACHED();
@@ -546,15 +564,17 @@ RenderViewHost* RenderViewHostManager::UpdateRendererStateNavigate(
return render_view_host_;
}
-void RenderViewHostManager::CancelPendingRenderView() {
+void RenderViewHostManager::CancelPending() {
RenderViewHost* pending_render_view_host = pending_render_view_host_;
pending_render_view_host_ = NULL;
pending_render_view_host->Shutdown();
+
+ pending_dom_ui_.reset();
}
void RenderViewHostManager::CrossSiteNavigationCanceled() {
DCHECK(cross_navigation_pending_);
cross_navigation_pending_ = false;
if (pending_render_view_host_)
- CancelPendingRenderView();
+ CancelPending();
}
diff --git a/chrome/browser/tab_contents/render_view_host_manager.h b/chrome/browser/tab_contents/render_view_host_manager.h
index 160ecff..9d9bb67 100644
--- a/chrome/browser/tab_contents/render_view_host_manager.h
+++ b/chrome/browser/tab_contents/render_view_host_manager.h
@@ -6,10 +6,12 @@
#define CHROME_BROWSER_TAB_CONTENTS_RENDER_VIEW_HOST_MANAGER_H_
#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_observer.h"
+class DOMUI;
class InterstitialPage;
class NavigationController;
class NavigationEntry;
@@ -48,6 +50,11 @@ class RenderViewHostManager : public NotificationObserver {
virtual void NotifySwappedFromRenderManager() = 0;
virtual NavigationController* GetControllerForRenderManager() = 0;
+ // Creates a DOMUI object for the given URL if one applies. Ownership of the
+ // returned pointer will be passed to the caller. If no DOMUI applies,
+ // returns NULL.
+ virtual DOMUI* CreateDOMUIForRenderManager(const GURL& url) = 0;
+
// Returns the navigation entry of the current navigation, or NULL if there
// is none.
virtual NavigationEntry*
@@ -94,6 +101,17 @@ class RenderViewHostManager : public NotificationObserver {
return render_view_host_->view();
}
+ // Returns the pending render view host, or NULL if there is no pending one.
+ RenderViewHost* pending_render_view_host() const {
+ return pending_render_view_host_;
+ }
+
+ // Returns the current committed DOM UI or NULL if none applies.
+ DOMUI* dom_ui() const { return dom_ui_.get(); }
+
+ // Returns the DOM UI for the pending navigation, or NULL of none applies.
+ DOMUI* pending_dom_ui() const { return pending_dom_ui_.get(); }
+
// Called when we want to instruct the renderer to navigate to the given
// navigation entry. It may create a new RenderViewHost or re-use an existing
// one. The RenderViewHost to navigate will be returned. Returns NULL if one
@@ -195,19 +213,15 @@ class RenderViewHostManager : public NotificationObserver {
int routing_id,
base::WaitableEvent* modal_dialog_event);
- // Replaces the currently shown render_view_host_ with the RenderViewHost in
- // the field pointed to by |new_render_view_host|, and then NULLs the field.
- // Callers should only pass pointers to the pending_render_view_host_,
- // interstitial_render_view_host_, or original_render_view_host_ fields of
- // this object. If |destroy_after|, this method will call
- // ScheduleDeferredDestroy on the previous render_view_host_.
- void SwapToRenderView(RenderViewHost** new_render_view_host,
- bool destroy_after);
+ // Sets the pending RenderViewHost/DOMUI to be the active one. Note that this
+ // doesn't require the pending render_view_host_ pointer to be non-NULL, since
+ // there could be DOM UI switching as well. Call this for every commit.
+ void CommitPending();
// Helper method to terminate the pending RenderViewHost.
- void CancelPendingRenderView();
+ void CancelPending();
- RenderViewHost* UpdateRendererStateNavigate(const NavigationEntry& entry);
+ RenderViewHost* UpdateRendererStateForNavigate(const NavigationEntry& entry);
// Our delegate, not owned by us. Guaranteed non-NULL.
Delegate* delegate_;
@@ -224,13 +238,23 @@ class RenderViewHostManager : public NotificationObserver {
// the RenderViewHosts that we create.
RenderViewHostDelegate* render_view_delegate_;
- // Our RenderView host. This object is responsible for all communication with
+ // Our RenderView host and its associated DOM UI (if any, will be NULL for
+ // non-DOM-UI pages). This object is responsible for all communication with
// a child RenderView instance.
RenderViewHost* render_view_host_;
+ scoped_ptr<DOMUI> dom_ui_;
- // A RenderViewHost used to load a cross-site page. This remains hidden
- // while a cross-site request is pending until it calls DidNavigate.
+ // A RenderViewHost used to load a cross-site page. This remains hidden
+ // while a cross-site request is pending until it calls DidNavigate. It may
+ // have an associated DOM UI, in which case the DOM UI pointer will be non-
+ // NULL.
+ //
+ // The pending_dom_ui may be non-NULL even when the pending_render_view_host_
+ // is. This will happen when we're transitioning between two DOM UI pages:
+ // the RVH won't be swapped, so the pending pointer will be unused, but there
+ // will be a pending DOM UI associated with the navigation.
RenderViewHost* pending_render_view_host_;
+ scoped_ptr<DOMUI> pending_dom_ui_;
// The intersitial page currently shown if any, not own by this class
// (the InterstitialPage is self-owned, it deletes itself when hidden).
diff --git a/chrome/browser/tab_contents/web_contents.cc b/chrome/browser/tab_contents/web_contents.cc
index fa7e904..6a8b721 100644
--- a/chrome/browser/tab_contents/web_contents.cc
+++ b/chrome/browser/tab_contents/web_contents.cc
@@ -347,9 +347,11 @@ void WebContents::Destroy() {
}
const string16& WebContents::GetTitle() const {
- if (dom_ui_.get()) {
+ DOMUI* our_dom_ui = render_manager_.pending_dom_ui() ?
+ render_manager_.pending_dom_ui() : render_manager_.dom_ui();
+ if (our_dom_ui) {
// Give the DOM UI the chance to override our title.
- const string16& title = dom_ui_->overridden_title();
+ const string16& title = our_dom_ui->overridden_title();
if (!title.empty())
return title;
}
@@ -361,14 +363,30 @@ SiteInstance* WebContents::GetSiteInstance() const {
}
bool WebContents::ShouldDisplayURL() {
- if (dom_ui_.get())
- return !dom_ui_->should_hide_url();
+ if (controller()->GetPendingEntry()) {
+ // When there is a pending entry, that should determine whether the URL is
+ // displayed (including getting the default behavior if the DOMUI doesn't
+ // specify).
+ if (render_manager_.pending_dom_ui())
+ return !render_manager_.pending_dom_ui()->should_hide_url();
+ return true;
+ }
+
+ if (render_manager_.dom_ui())
+ return !render_manager_.dom_ui()->should_hide_url();
return true;
}
bool WebContents::ShouldDisplayFavIcon() {
- if (dom_ui_.get())
- return !dom_ui_->hide_favicon();
+ if (controller()->GetPendingEntry()) {
+ // See ShouldDisplayURL.
+ if (render_manager_.pending_dom_ui())
+ return !render_manager_.pending_dom_ui()->hide_favicon();
+ return true;
+ }
+
+ if (render_manager_.dom_ui())
+ return !render_manager_.dom_ui()->hide_favicon();
return true;
}
@@ -402,10 +420,6 @@ std::wstring WebContents::GetStatusText() const {
bool WebContents::NavigateToPendingEntry(bool reload) {
const NavigationEntry& entry = *controller()->GetPendingEntry();
- // This will possibly create (or NULL out) a DOM UI object for the page. We'll
- // use this later when the page starts doing stuff to allow it to do so.
- dom_ui_.reset(DOMUIFactory::CreateDOMUIForURL(this, entry.url()));
-
RenderViewHost* dest_render_view_host = render_manager_.Navigate(entry);
if (!dest_render_view_host)
return false; // Unable to create the desired render view host.
@@ -518,8 +532,20 @@ void WebContents::HideContents() {
}
bool WebContents::IsBookmarkBarAlwaysVisible() {
- if (dom_ui_.get())
- return dom_ui_->force_bookmark_bar_visible();
+ // We want the bookmarks bar to go with the committed entry. This way, when
+ // you're on the new tab page and navigate, the bookmarks bar doesn't
+ // disappear until the next load commits (the same time the page changes).
+ if (!controller()->GetLastCommittedEntry()) {
+ // However, when there is no committed entry (the first load of the tab),
+ // then we fall back on the pending entry. This means that the bookmarks bar
+ // will be visible before the new tab page load commits.
+ if (render_manager_.pending_dom_ui())
+ return render_manager_.pending_dom_ui()->force_bookmark_bar_visible();
+ return false;
+ }
+
+ if (render_manager_.dom_ui())
+ return render_manager_.dom_ui()->force_bookmark_bar_visible();
return false;
}
@@ -537,9 +563,12 @@ void WebContents::PopupNotificationVisibilityChanged(bool visible) {
}
bool WebContents::FocusLocationBarByDefault() {
- // Allow the DOM Ui to override the default.
- if (dom_ui_.get())
- return dom_ui_->focus_location_bar_by_default();
+ // Allow the DOM UI to override the default. We use the pending DOM UI since
+ // that's what the user "just did" so should control what happens after they
+ // did it. Using the committed one would mean when they navigate from a DOMUI
+ // to a regular page, the location bar would be focused.
+ if (render_manager_.pending_dom_ui())
+ return render_manager_.pending_dom_ui()->focus_location_bar_by_default();
return false;
}
@@ -726,8 +755,10 @@ void WebContents::RenderViewCreated(RenderViewHost* render_view_host) {
if (!entry)
return;
- if (dom_ui_.get()) {
- dom_ui_->RenderViewCreated(render_view_host);
+ // When we're creating views, we're still doing initial setup, so we always
+ // use the pending DOM UI rather than any possibly existing committed one.
+ if (render_manager_.pending_dom_ui()) {
+ render_manager_.pending_dom_ui()->RenderViewCreated(render_view_host);
} else if (entry->IsViewSourceMode()) {
// Put the renderer in view source mode.
render_view_host->Send(
@@ -1070,7 +1101,7 @@ void WebContents::DidDownloadImage(
void WebContents::RequestOpenURL(const GURL& url, const GURL& referrer,
WindowOpenDisposition disposition) {
- if (dom_ui_.get()) {
+ if (render_manager_.dom_ui()) {
// When we're a DOM UI, it will provide a page transition type for us (this
// is so the new tab page can specify AUTO_BOOKMARK for automatically
// generated suggestions).
@@ -1079,7 +1110,8 @@ void WebContents::RequestOpenURL(const GURL& url, const GURL& referrer,
// want web sites to see a referrer of "chrome-ui://blah" (and some
// chrome-ui URLs might have search terms or other stuff we don't want to
// send to the site), so we send no referrer.
- OpenURL(url, GURL(), disposition, dom_ui_->link_transition_type());
+ OpenURL(url, GURL(), disposition,
+ render_manager_.dom_ui()->link_transition_type());
} else {
OpenURL(url, referrer, disposition, PageTransition::LINK);
}
@@ -1095,14 +1127,14 @@ void WebContents::DomOperationResponse(const std::string& json_string,
void WebContents::ProcessDOMUIMessage(const std::string& message,
const std::string& content) {
- if (!dom_ui_.get()) {
+ if (!render_manager_.dom_ui()) {
// We shouldn't get a DOM UI message when we haven't enabled the DOM UI.
// Because the renderer might be owned and sending random messages, we need
// to ignore these inproper ones.
NOTREACHED();
return;
}
- dom_ui_->ProcessDOMUIMessage(message, content);
+ render_manager_.dom_ui()->ProcessDOMUIMessage(message, content);
}
void WebContents::ProcessExternalHostMessage(const std::string& message,
@@ -1404,8 +1436,9 @@ WebPreferences WebContents::GetWebkitPrefs() {
}
DCHECK(!web_prefs.default_encoding.empty());
- // Override some prefs when we're a DOM UI, or the pages won't work.
- if (dom_ui_.get()) {
+ // Override some prefs when we're a DOM UI, or the pages won't work. This is
+ // called during setup, so we will always use the pending one.
+ if (render_manager_.pending_dom_ui()) {
web_prefs.loads_images_automatically = true;
web_prefs.javascript_enabled = true;
}
@@ -1581,6 +1614,10 @@ void WebContents::UpdateRenderViewSizeForRenderManager() {
view_->SizeContents(view_->GetContainerSize());
}
+DOMUI* WebContents::CreateDOMUIForRenderManager(const GURL& url) {
+ return DOMUIFactory::CreateDOMUIForURL(this, url);
+}
+
NavigationEntry*
WebContents::GetLastCommittedNavigationEntryForRenderManager() {
if (!controller())
@@ -1591,8 +1628,10 @@ WebContents::GetLastCommittedNavigationEntryForRenderManager() {
bool WebContents::CreateRenderViewForRenderManager(
RenderViewHost* render_view_host) {
// When we're running a DOM UI, the RenderViewHost needs to be put in DOM UI
- // mode before CreateRenderView is called.
- if (dom_ui_.get())
+ // mode before CreateRenderView is called. When we're asked to create a
+ // RenderView, that means it's for the pending entry, so we have to use the
+ // pending DOM UI.
+ if (render_manager_.pending_dom_ui())
render_view_host->AllowDOMUIBindings();
RenderWidgetHostView* rwh_view = view_->CreateViewForWidget(render_view_host);
diff --git a/chrome/browser/tab_contents/web_contents.h b/chrome/browser/tab_contents/web_contents.h
index 21ca7eb..b3bdf15 100644
--- a/chrome/browser/tab_contents/web_contents.h
+++ b/chrome/browser/tab_contents/web_contents.h
@@ -109,6 +109,11 @@ class WebContents : public TabContents,
return view_.get();
}
+#ifdef UNIT_TEST
+ // Expose the render manager for testing.
+ RenderViewHostManager* render_manager() { return &render_manager_; }
+#endif
+
// Page state getters & setters ----------------------------------------------
bool is_starred() const { return is_starred_; }
@@ -449,6 +454,7 @@ class WebContents : public TabContents,
virtual NavigationController* GetControllerForRenderManager() {
return controller();
}
+ virtual DOMUI* CreateDOMUIForRenderManager(const GURL& url);
virtual NavigationEntry* GetLastCommittedNavigationEntryForRenderManager();
// Initializes the given renderer if necessary and creates the view ID
@@ -635,11 +641,6 @@ class WebContents : public TabContents,
// PluginInstaller, lazily created.
scoped_ptr<PluginInstaller> plugin_installer_;
- // When the current page is a DOM UI page, this will point to the specific
- // DOMUI object handling it. When we don't have a DOM UI page, this will be
- // null.
- scoped_ptr<DOMUI> dom_ui_;
-
// Handles downloading favicons.
FavIconHelper fav_icon_helper_;