diff options
author | creis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-21 01:27:26 +0000 |
---|---|---|
committer | creis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-12-21 01:27:26 +0000 |
commit | c4572ff9f3a76e2ee5e34c9f3acce9a560043876 (patch) | |
tree | afc28690a5377a794f2c28b00053486eedfec79f | |
parent | b51d88aab10cd6f5825f7adf069154cbb7e2f591 (diff) | |
download | chromium_src-c4572ff9f3a76e2ee5e34c9f3acce9a560043876.zip chromium_src-c4572ff9f3a76e2ee5e34c9f3acce9a560043876.tar.gz chromium_src-c4572ff9f3a76e2ee5e34c9f3acce9a560043876.tar.bz2 |
Merge 114862 - Make page IDs be specific to a RenderView rather than global to its process.
This avoids races that cause the browser to kill the renderer.
BUG=106616
TEST=Restore Chrome with an extension's options page showing.
Review URL: http://codereview.chromium.org/8910020
TBR=creis@chromium.org
Review URL: http://codereview.chromium.org/9007036
git-svn-id: svn://svn.chromium.org/chrome/branches/963/src@115254 0039d316-1c4b-4281-b951-d872f2087c98
27 files changed, 154 insertions, 234 deletions
diff --git a/chrome/browser/tab_contents/web_contents_unittest.cc b/chrome/browser/tab_contents/web_contents_unittest.cc index da5957d..9eda8a35 100644 --- a/chrome/browser/tab_contents/web_contents_unittest.cc +++ b/chrome/browser/tab_contents/web_contents_unittest.cc @@ -235,6 +235,29 @@ TEST_F(TabContentsTest, NTPViewSource) { EXPECT_EQ(ASCIIToUTF16(kUrl), contents()->GetTitle()); } +// Test to ensure UpdateMaxPageID is working properly. +TEST_F(TabContentsTest, UpdateMaxPageID) { + SiteInstance* instance1 = contents()->GetSiteInstance(); + scoped_refptr<SiteInstance> instance2(SiteInstance::CreateSiteInstance(NULL)); + + // Starts at -1. + EXPECT_EQ(-1, contents()->GetMaxPageID()); + EXPECT_EQ(-1, contents()->GetMaxPageIDForSiteInstance(instance1)); + EXPECT_EQ(-1, contents()->GetMaxPageIDForSiteInstance(instance2)); + + // Make sure max_page_id_ is monotonically increasing per SiteInstance. + contents()->UpdateMaxPageID(3); + contents()->UpdateMaxPageID(1); + EXPECT_EQ(3, contents()->GetMaxPageID()); + EXPECT_EQ(3, contents()->GetMaxPageIDForSiteInstance(instance1)); + EXPECT_EQ(-1, contents()->GetMaxPageIDForSiteInstance(instance2)); + + contents()->UpdateMaxPageIDForSiteInstance(instance2, 7); + EXPECT_EQ(3, contents()->GetMaxPageID()); + EXPECT_EQ(3, contents()->GetMaxPageIDForSiteInstance(instance1)); + EXPECT_EQ(7, contents()->GetMaxPageIDForSiteInstance(instance2)); +} + // Test simple same-SiteInstance navigation. TEST_F(TabContentsTest, SimpleNavigation) { TestRenderViewHost* orig_rvh = rvh(); diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc b/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc index 39571e2..4a79f8e 100644 --- a/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc +++ b/chrome/browser/ui/webui/ntp/new_tab_ui_browsertest.cc @@ -45,8 +45,7 @@ IN_PROC_BROWSER_TEST_F(NewTabUIBrowserTest, LoadNTPInExistingProcess) { ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(chrome::kChromeUINewTabURL), NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - EXPECT_EQ(1, - browser()->GetTabContentsAt(1)->GetSiteInstance()->max_page_id()); + EXPECT_EQ(1, browser()->GetTabContentsAt(1)->GetMaxPageID()); // Navigate that tab to another site. This allows the NTP process to exit, // but it keeps the NTP SiteInstance (and its max_page_id) alive in history. @@ -61,34 +60,30 @@ IN_PROC_BROWSER_TEST_F(NewTabUIBrowserTest, LoadNTPInExistingProcess) { process_exited_observer.Wait(); } - // Create and close another two NTPs to inflate the max_page_id. + // Creating a NTP in another tab should not be affected, since page IDs + // are now specific to a tab. ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(chrome::kChromeUINewTabURL), NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - EXPECT_EQ(2, - browser()->GetTabContentsAt(2)->GetSiteInstance()->max_page_id()); - browser()->CloseTab(); - ui_test_utils::NavigateToURLWithDisposition( - browser(), GURL(chrome::kChromeUINewTabURL), NEW_FOREGROUND_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - EXPECT_EQ(3, - browser()->GetTabContentsAt(2)->GetSiteInstance()->max_page_id()); + EXPECT_EQ(1, browser()->GetTabContentsAt(2)->GetMaxPageID()); browser()->CloseTab(); // Open another Web UI page in a new tab. ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(chrome::kChromeUISettingsURL), NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - EXPECT_EQ(1, - browser()->GetTabContentsAt(2)->GetSiteInstance()->max_page_id()); + EXPECT_EQ(1, browser()->GetTabContentsAt(2)->GetMaxPageID()); - // At this point, opening another NTP will use the old SiteInstance (with a - // large max_page_id) in the existing Web UI process (with a small page ID). - // Make sure we don't confuse this as an existing navigation to an unknown - // entry. + // At this point, opening another NTP will use the old SiteInstance in the + // existing Web UI process, but the page IDs shouldn't affect each other. ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(chrome::kChromeUINewTabURL), NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - EXPECT_EQ(4, - browser()->GetTabContentsAt(3)->GetSiteInstance()->max_page_id()); + EXPECT_EQ(1, browser()->GetTabContentsAt(3)->GetMaxPageID()); + + // Only navigating to the NTP in the original tab should have a higher + // page ID. + browser()->ActivateTabAt(1, true); + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + EXPECT_EQ(2, browser()->GetTabContentsAt(1)->GetMaxPageID()); } diff --git a/chrome/browser/visitedlink/visitedlink_unittest.cc b/chrome/browser/visitedlink/visitedlink_unittest.cc index 487c73d..2c5218a 100644 --- a/chrome/browser/visitedlink/visitedlink_unittest.cc +++ b/chrome/browser/visitedlink/visitedlink_unittest.cc @@ -660,7 +660,7 @@ TEST_F(VisitedLinkEventsTest, Coalescense) { TEST_F(VisitedLinkEventsTest, Basics) { VisitedLinkMaster* master = profile()->GetVisitedLinkMaster(); - rvh()->CreateRenderView(string16()); + rvh()->CreateRenderView(string16(), -1); // Add a few URLs. master->AddURL(GURL("http://acidtests.org/")); @@ -684,7 +684,7 @@ TEST_F(VisitedLinkEventsTest, Basics) { TEST_F(VisitedLinkEventsTest, TabVisibility) { VisitedLinkMaster* master = profile()->GetVisitedLinkMaster(); - rvh()->CreateRenderView(string16()); + rvh()->CreateRenderView(string16(), -1); // Simulate tab becoming inactive. rvh()->WasHidden(); diff --git a/chrome/test/base/browser_with_test_window_test.cc b/chrome/test/base/browser_with_test_window_test.cc index f4077a5..1751ac5 100644 --- a/chrome/test/base/browser_with_test_window_test.cc +++ b/chrome/test/base/browser_with_test_window_test.cc @@ -74,8 +74,6 @@ void BrowserWithTestWindowTest::CommitPendingLoad( TestRenderViewHost* old_rvh = TestRenderViewHostForTab(controller->tab_contents()); - MockRenderProcessHost* mock_rph = static_cast<MockRenderProcessHost*>( - old_rvh->process()); TestRenderViewHost* pending_rvh = static_cast<TestRenderViewHost*>( controller->tab_contents()->render_manager_for_testing()-> @@ -100,10 +98,10 @@ void BrowserWithTestWindowTest::CommitPendingLoad( controller->pending_entry()->transition_type()); } else { test_rvh->SendNavigateWithTransition( - mock_rph->max_page_id() + 1, + controller->tab_contents()-> + GetMaxPageIDForSiteInstance(test_rvh->site_instance()) + 1, controller->pending_entry()->url(), controller->pending_entry()->transition_type()); - mock_rph->UpdateMaxPageID(mock_rph->max_page_id() + 1); } // Simulate the SwapOut_ACK that fires if you commit a cross-site navigation diff --git a/content/browser/renderer_host/mock_render_process_host.cc b/content/browser/renderer_host/mock_render_process_host.cc index 9f3bca7..989414e 100644 --- a/content/browser/renderer_host/mock_render_process_host.cc +++ b/content/browser/renderer_host/mock_render_process_host.cc @@ -22,7 +22,6 @@ MockRenderProcessHost::MockRenderProcessHost( factory_(NULL), id_(ChildProcessHostImpl::GenerateChildProcessUniqueId()), browser_context_(browser_context), - max_page_id_(-1), fast_shutdown_started_(false) { // Child process security operations can't be unit tested unless we add // ourselves as an existing child process. @@ -52,10 +51,6 @@ int MockRenderProcessHost::GetNextRoutingID() { return ++prev_routing_id; } -void MockRenderProcessHost::UpdateAndSendMaxPageID(int32 page_id) { - UpdateMaxPageID(page_id); -} - void MockRenderProcessHost::CancelResourceRequests(int render_widget_id) { } @@ -192,11 +187,6 @@ IPC::Channel::Listener* MockRenderProcessHost::GetListenerByID( return listeners_.Lookup(routing_id); } -void MockRenderProcessHost::UpdateMaxPageID(int32 page_id) { - if (page_id > max_page_id_) - max_page_id_ = page_id; -} - content::BrowserContext* MockRenderProcessHost::GetBrowserContext() const { return browser_context_; } diff --git a/content/browser/renderer_host/mock_render_process_host.h b/content/browser/renderer_host/mock_render_process_host.h index 370601f..4a41c43 100644 --- a/content/browser/renderer_host/mock_render_process_host.h +++ b/content/browser/renderer_host/mock_render_process_host.h @@ -26,9 +26,6 @@ class MockRenderProcessHost : public content::RenderProcessHost { // renderer via this RenderProcessHost. IPC::TestSink& sink() { return sink_; } - // Provides tests access to the max page ID currently used for this process. - int max_page_id() const { return max_page_id_; } - // Provides test access to how many times a bad message has been received. int bad_msg_count() const { return bad_msg_count_; } @@ -36,7 +33,6 @@ class MockRenderProcessHost : public content::RenderProcessHost { virtual void EnableSendQueue() OVERRIDE; virtual bool Init(bool is_accessibility_enabled) OVERRIDE; virtual int GetNextRoutingID() OVERRIDE; - virtual void UpdateAndSendMaxPageID(int32 page_id) OVERRIDE; virtual void CancelResourceRequests(int render_widget_id) OVERRIDE; virtual void CrossSiteSwapOutACK( const ViewMsg_SwapOut_Params& params) OVERRIDE; @@ -69,7 +65,6 @@ class MockRenderProcessHost : public content::RenderProcessHost { virtual void RemovePendingView() OVERRIDE; virtual void SetSuddenTerminationAllowed(bool allowed) OVERRIDE; virtual bool SuddenTerminationAllowed() const OVERRIDE; - virtual void UpdateMaxPageID(int32 page_id) OVERRIDE; virtual IPC::Channel::Listener* GetListenerByID(int routing_id) OVERRIDE; virtual content::BrowserContext* GetBrowserContext() const OVERRIDE; virtual IPC::ChannelProxy* GetChannel() OVERRIDE; @@ -98,7 +93,6 @@ class MockRenderProcessHost : public content::RenderProcessHost { const MockRenderProcessHostFactory* factory_; int id_; content::BrowserContext* browser_context_; - int32 max_page_id_; IDMap<IPC::Channel::Listener> listeners_; bool fast_shutdown_started_; diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 009b731..3a659e4 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc @@ -274,8 +274,7 @@ void content::RenderProcessHost::SetMaxRendererProcessCountForTest( RenderProcessHostImpl::RenderProcessHostImpl( content::BrowserContext* browser_context) - : max_page_id_(-1), - fast_shutdown_started_(false), + : fast_shutdown_started_(false), deleting_soon_(false), pending_views_(0), visible_widgets_(0), @@ -548,12 +547,6 @@ int RenderProcessHostImpl::GetNextRoutingID() { return widget_helper_->GetNextRoutingID(); } -void RenderProcessHostImpl::UpdateAndSendMaxPageID(int32 page_id) { - if (page_id > max_page_id_) - Send(new ViewMsg_SetNextPageID(page_id + 1)); - UpdateMaxPageID(page_id); -} - void RenderProcessHostImpl::CancelResourceRequests(int render_widget_id) { widget_helper_->CancelResourceRequests(render_widget_id); } @@ -1083,11 +1076,6 @@ void RenderProcessHostImpl::RemovePendingView() { pending_views_--; } -void RenderProcessHostImpl::UpdateMaxPageID(int32 page_id) { - if (page_id > max_page_id_) - max_page_id_ = page_id; -} - void RenderProcessHostImpl::SetSuddenTerminationAllowed(bool enabled) { sudden_termination_allowed_ = enabled; } @@ -1293,9 +1281,6 @@ void RenderProcessHostImpl::OnProcessLaunched() { child_process_launcher_->SetProcessBackgrounded(backgrounded_); } - if (max_page_id_ != -1) - Send(new ViewMsg_SetNextPageID(max_page_id_ + 1)); - // NOTE: This needs to be before sending queued messages because // ExtensionService uses this notification to initialize the renderer process // with state that must be there before any JavaScript executes. diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index dd9efdd0..269dd97 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h @@ -74,7 +74,6 @@ class CONTENT_EXPORT RenderProcessHostImpl virtual content::BrowserContext* GetBrowserContext() const OVERRIDE; virtual int GetID() const OVERRIDE; virtual bool HasConnection() const OVERRIDE; - virtual void UpdateMaxPageID(int32 page_id) OVERRIDE; virtual IPC::Channel::Listener* GetListenerByID(int routing_id) OVERRIDE; virtual void SetIgnoreInputEvents(bool ignore_input_events) OVERRIDE; virtual bool IgnoreInputEvents() const OVERRIDE; @@ -92,7 +91,6 @@ class CONTENT_EXPORT RenderProcessHostImpl virtual bool FastShutdownForPageCount(size_t count) OVERRIDE; virtual bool FastShutdownStarted() const OVERRIDE; virtual base::TimeDelta GetChildProcessIdleTime() const OVERRIDE; - virtual void UpdateAndSendMaxPageID(int32 page_id) OVERRIDE; // IPC::Channel::Sender via RenderProcessHost. virtual bool Send(IPC::Message* msg) OVERRIDE; @@ -129,9 +127,6 @@ class CONTENT_EXPORT RenderProcessHostImpl // delete ourselves IDMap<IPC::Channel::Listener> listeners_; - // The maximum page ID we've ever seen from the renderer process. - int32 max_page_id_; - // True if fast shutdown has been performed on this RPH. bool fast_shutdown_started_; diff --git a/content/browser/renderer_host/render_view_host.cc b/content/browser/renderer_host/render_view_host.cc index d177462..45b9654 100644 --- a/content/browser/renderer_host/render_view_host.cc +++ b/content/browser/renderer_host/render_view_host.cc @@ -158,7 +158,8 @@ RenderViewHost::~RenderViewHost() { process()->GetID(), routing_id(), false); } -bool RenderViewHost::CreateRenderView(const string16& frame_name) { +bool RenderViewHost::CreateRenderView(const string16& frame_name, + int32 max_page_id) { DCHECK(!IsRenderViewLive()) << "Creating view twice"; // The process may (if we're sharing a process with another host that already @@ -175,6 +176,12 @@ bool RenderViewHost::CreateRenderView(const string16& frame_name) { process()->SetCompositingSurface(routing_id(), GetCompositingSurface()); + // Ensure the RenderView starts with a next_page_id larger than any existing + // page ID it might be asked to render. + int32 next_page_id = 1; + if (max_page_id > -1) + next_page_id = max_page_id + 1; + ViewMsg_New_Params params; params.parent_window = GetNativeViewId(); params.renderer_preferences = @@ -183,6 +190,7 @@ bool RenderViewHost::CreateRenderView(const string16& frame_name) { params.view_id = routing_id(); params.session_storage_namespace_id = session_storage_namespace_->id(); params.frame_name = frame_name; + params.next_page_id = next_page_id; Send(new ViewMsg_New(params)); // If it's enabled, tell the renderer to set up the Javascript bindings for diff --git a/content/browser/renderer_host/render_view_host.h b/content/browser/renderer_host/render_view_host.h index 99cc989..8a1f8b0 100644 --- a/content/browser/renderer_host/render_view_host.h +++ b/content/browser/renderer_host/render_view_host.h @@ -152,8 +152,9 @@ class CONTENT_EXPORT RenderViewHost : public RenderWidgetHost { // Set up the RenderView child process. Virtual because it is overridden by // TestRenderViewHost. If the |frame_name| parameter is non-empty, it is used - // as the name of the new top-level frame. - virtual bool CreateRenderView(const string16& frame_name); + // as the name of the new top-level frame. If |max_page_id| is larger than + // -1, the RenderView is told to start issuing page IDs at |max_page_id| + 1. + virtual bool CreateRenderView(const string16& frame_name, int32 max_page_id); // Returns true if the RenderView is active and has not crashed. Virtual // because it is overridden by TestRenderViewHost. diff --git a/content/browser/renderer_host/test_render_view_host.cc b/content/browser/renderer_host/test_render_view_host.cc index 3eb8ebd..202fa8f 100644 --- a/content/browser/renderer_host/test_render_view_host.cc +++ b/content/browser/renderer_host/test_render_view_host.cc @@ -63,7 +63,8 @@ TestRenderViewHost::~TestRenderViewHost() { delete view(); } -bool TestRenderViewHost::CreateRenderView(const string16& frame_name) { +bool TestRenderViewHost::CreateRenderView(const string16& frame_name, + int32 max_page_id) { DCHECK(!render_view_created_); render_view_created_ = true; return true; diff --git a/content/browser/renderer_host/test_render_view_host.h b/content/browser/renderer_host/test_render_view_host.h index b8af6a3..b3eb12e 100644 --- a/content/browser/renderer_host/test_render_view_host.h +++ b/content/browser/renderer_host/test_render_view_host.h @@ -227,7 +227,8 @@ class TestRenderViewHost : public RenderViewHost { // RenderViewHost overrides -------------------------------------------------- - virtual bool CreateRenderView(const string16& frame_name) OVERRIDE; + virtual bool CreateRenderView(const string16& frame_name, + int32 max_page_id) OVERRIDE; virtual bool IsRenderViewLive() const OVERRIDE; private: diff --git a/content/browser/site_instance.cc b/content/browser/site_instance.cc index b8c55b6..0f0baaf 100644 --- a/content/browser/site_instance.cc +++ b/content/browser/site_instance.cc @@ -37,7 +37,6 @@ SiteInstance::SiteInstance(BrowsingInstance* browsing_instance) browsing_instance_(browsing_instance), render_process_host_factory_(NULL), process_(NULL), - max_page_id_(-1), has_site_(false) { DCHECK(browsing_instance); @@ -87,10 +86,6 @@ content::RenderProcessHost* SiteInstance::GetProcess() { content::GetContentClient()->browser()->SiteInstanceGotProcess(this); - // Make sure the process starts at the right max_page_id, and ensure that - // we send an update to the renderer process. - process_->UpdateAndSendMaxPageID(max_page_id_); - if (has_site_) LockToOrigin(); } diff --git a/content/browser/site_instance.h b/content/browser/site_instance.h index 9feccfc..b85aa9a 100644 --- a/content/browser/site_instance.h +++ b/content/browser/site_instance.h @@ -73,13 +73,6 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance>, render_process_host_factory_ = rph_factory; } - // Update / Get the max page ID for this SiteInstance. - void UpdateMaxPageID(int32 page_id) { - if (page_id > max_page_id_) - max_page_id_ = page_id; - } - int32 max_page_id() const { return max_page_id_; } - // Whether this SiteInstance has a running process associated with it. bool HasProcess() const; @@ -196,11 +189,6 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance>, // scenario the RenderProcessHost remains the same. content::RenderProcessHost* process_; - // The current max_page_id in the SiteInstance's RenderProcessHost. If the - // rendering process dies, its replacement should start issuing page IDs that - // are larger than this value. - int32 max_page_id_; - // The web site that this SiteInstance is rendering pages for. GURL site_; diff --git a/content/browser/site_instance_unittest.cc b/content/browser/site_instance_unittest.cc index 9e439b4..c25d809 100644 --- a/content/browser/site_instance_unittest.cc +++ b/content/browser/site_instance_unittest.cc @@ -265,17 +265,6 @@ TEST_F(SiteInstanceTest, CloneNavigationEntry) { EXPECT_EQ(2, browsingDeleteCounter); } -// Test to ensure UpdateMaxPageID is working properly. -TEST_F(SiteInstanceTest, UpdateMaxPageID) { - scoped_refptr<SiteInstance> instance(SiteInstance::CreateSiteInstance(NULL)); - EXPECT_EQ(-1, instance->max_page_id()); - - // Make sure max_page_id_ is monotonically increasing. - instance->UpdateMaxPageID(3); - instance->UpdateMaxPageID(1); - EXPECT_EQ(3, instance->max_page_id()); -} - // Test to ensure GetProcess returns and creates processes correctly. TEST_F(SiteInstanceTest, GetProcess) { // Ensure that GetProcess returns a process. diff --git a/content/browser/tab_contents/interstitial_page.cc b/content/browser/tab_contents/interstitial_page.cc index e50ba12..5ac99e1 100644 --- a/content/browser/tab_contents/interstitial_page.cc +++ b/content/browser/tab_contents/interstitial_page.cc @@ -407,7 +407,9 @@ TabContentsView* InterstitialPage::CreateTabContentsView() { render_view_host_->SetView(view); render_view_host_->AllowBindings(content::BINDINGS_POLICY_DOM_AUTOMATION); - render_view_host_->CreateRenderView(string16()); + int32 max_page_id = + tab()->GetMaxPageIDForSiteInstance(render_view_host_->site_instance()); + render_view_host_->CreateRenderView(string16(), max_page_id); view->SetSize(tab_contents_view->GetContainerSize()); // Don't show the interstitial until we have navigated to it. view->Hide(); diff --git a/content/browser/tab_contents/render_view_host_manager_unittest.cc b/content/browser/tab_contents/render_view_host_manager_unittest.cc index 6d84a63..38005f4 100644 --- a/content/browser/tab_contents/render_view_host_manager_unittest.cc +++ b/content/browser/tab_contents/render_view_host_manager_unittest.cc @@ -122,11 +122,10 @@ class RenderViewHostManagerTest : public RenderViewHostTestHarness { if (old_rvh != active_rvh()) old_rvh->SendShouldCloseACK(true); - // Commit the navigation. - active_rvh()->SendNavigate( - static_cast<MockRenderProcessHost*>(active_rvh()->process())-> - max_page_id() + 1, - url); + // Commit the navigation with a new page ID. + int32 max_page_id = + contents()->GetMaxPageIDForSiteInstance(active_rvh()->site_instance()); + active_rvh()->SendNavigate(max_page_id + 1, url); // Simulate the SwapOut_ACK that fires if you commit a cross-site navigation // without making any network requests. @@ -232,8 +231,8 @@ TEST_F(RenderViewHostManagerTest, AlwaysSendEnableViewSourceMode) { ViewHostMsg_ShouldClose_ACK(rvh()->routing_id(), true)); ASSERT_TRUE(pending_rvh()); // New pending RenderViewHost will be created. RenderViewHost* last_rvh = pending_rvh(); - int new_id = static_cast<MockRenderProcessHost*>(pending_rvh()->process())-> - max_page_id() + 1; + int32 new_id = contents()->GetMaxPageIDForSiteInstance( + active_rvh()->site_instance()) + 1; pending_rvh()->SendNavigate(new_id, kUrl); EXPECT_EQ(controller().last_committed_entry_index(), 1); ASSERT_TRUE(controller().GetLastCommittedEntry()); diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc index e716148..2bc0ef5 100644 --- a/content/browser/tab_contents/tab_contents.cc +++ b/content/browser/tab_contents/tab_contents.cc @@ -196,7 +196,6 @@ TabContents::TabContents(content::BrowserContext* browser_context, crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING), crashed_error_code_(0), waiting_for_response_(false), - max_page_id_(-1), load_state_(net::LOAD_STATE_IDLE, string16()), upload_size_(0), upload_position_(0), @@ -391,19 +390,24 @@ const string16& TabContents::GetTitle() const { } int32 TabContents::GetMaxPageID() { - if (GetSiteInstance()) - return GetSiteInstance()->max_page_id(); - else - return max_page_id_; + return GetMaxPageIDForSiteInstance(GetSiteInstance()); +} + +int32 TabContents::GetMaxPageIDForSiteInstance(SiteInstance* site_instance) { + if (max_page_ids_.find(site_instance->id()) == max_page_ids_.end()) + max_page_ids_[site_instance->id()] = -1; + + return max_page_ids_[site_instance->id()]; } void TabContents::UpdateMaxPageID(int32 page_id) { - // Ensure both the SiteInstance and RenderProcessHost update their max page - // IDs in sync. Only TabContents will also have site instances, except during - // testing. - if (GetSiteInstance()) - GetSiteInstance()->UpdateMaxPageID(page_id); - GetRenderProcessHost()->UpdateMaxPageID(page_id); + UpdateMaxPageIDForSiteInstance(GetSiteInstance(), page_id); +} + +void TabContents::UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance, + int32 page_id) { + if (GetMaxPageIDForSiteInstance(site_instance) < page_id) + max_page_ids_[site_instance->id()] = page_id; } SiteInstance* TabContents::GetSiteInstance() const { @@ -1329,30 +1333,16 @@ void TabContents::DidNavigateAnyFramePostCommit( DidNavigateAnyFrame(details, params)); } -void TabContents::UpdateMaxPageIDIfNecessary(SiteInstance* site_instance, - RenderViewHost* rvh) { - // If we are creating a RVH for a restored controller, then we might - // have more page IDs than the SiteInstance's current max page ID. We must - // make sure that the max page ID is larger than any restored page ID. - // Note that it is ok for conflicting page IDs to exist in another tab - // (i.e., NavigationController), but if any page ID is larger than the max, - // the back/forward list will get confused. +void TabContents::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) { + // If we are creating a RVH for a restored controller, then we need to make + // sure the RenderView starts with a next_page_id_ larger than the number + // of restored entries. This must be called before the RenderView starts + // navigating (to avoid a race between the browser updating max_page_id and + // the renderer updating next_page_id_). Because of this, we only call this + // from CreateRenderView and allow that to notify the RenderView for us. int max_restored_page_id = controller_.max_restored_page_id(); - if (max_restored_page_id > 0) { - int curr_max_page_id = site_instance->max_page_id(); - if (max_restored_page_id > curr_max_page_id) { - // Need to update the site instance immediately. - site_instance->UpdateMaxPageID(max_restored_page_id); - - // Also tell the renderer to update its internal representation. We - // need to reserve enough IDs to make all restored page IDs less than - // the max. - if (curr_max_page_id < 0) - curr_max_page_id = 0; - rvh->Send(new ViewMsg_ReservePageIDRange( - rvh->routing_id(), max_restored_page_id - curr_max_page_id)); - } - } + if (max_restored_page_id > GetMaxPageIDForSiteInstance(rvh->site_instance())) + UpdateMaxPageIDForSiteInstance(rvh->site_instance(), max_restored_page_id); } bool TabContents::UpdateTitleForEntry(NavigationEntry* entry, @@ -2019,7 +2009,12 @@ bool TabContents::CreateRenderViewForRenderManager( if (rwh_view) rwh_view->SetSize(view_->GetContainerSize()); - if (!render_view_host->CreateRenderView(string16())) + // Make sure we use the correct starting page_id in the new RenderView. + UpdateMaxPageIDIfNecessary(render_view_host); + int32 max_page_id = + GetMaxPageIDForSiteInstance(render_view_host->site_instance()); + + if (!render_view_host->CreateRenderView(string16(), max_page_id)) return false; #if defined(OS_LINUX) || defined(OS_OPENBSD) @@ -2031,8 +2026,6 @@ bool TabContents::CreateRenderViewForRenderManager( } #endif - UpdateMaxPageIDIfNecessary(render_view_host->site_instance(), - render_view_host); return true; } diff --git a/content/browser/tab_contents/tab_contents.h b/content/browser/tab_contents/tab_contents.h index 7fa48b9..b52f162 100644 --- a/content/browser/tab_contents/tab_contents.h +++ b/content/browser/tab_contents/tab_contents.h @@ -147,19 +147,27 @@ class CONTENT_EXPORT TabContents : public PageNavigator, virtual const GURL& GetURL() const OVERRIDE; virtual const string16& GetTitle() const; - // The max PageID of any page that this TabContents has loaded. PageIDs - // increase with each new page that is loaded by a tab. If this is a - // TabContents, then the max PageID is kept separately on each SiteInstance. - // Returns -1 if no PageIDs have yet been seen. + // The max page ID for any page that the current SiteInstance has loaded in + // this TabContents. Page IDs are specific to a given SiteInstance and + // TabContents, corresponding to a specific RenderView in the renderer. + // Page IDs increase with each new page that is loaded by a tab. int32 GetMaxPageID(); - // Updates the max PageID to be at least the given PageID. + // The max page ID for any page that the given SiteInstance has loaded in + // this TabContents. + int32 GetMaxPageIDForSiteInstance(SiteInstance* site_instance); + + // Updates the max page ID for the current SiteInstance in this TabContents + // to be at least |page_id|. void UpdateMaxPageID(int32 page_id); - // Returns the site instance associated with the current page. By default, - // there is no site instance. TabContents overrides this to provide proper - // access to its site instance. - virtual SiteInstance* GetSiteInstance() const; + // Updates the max page ID for the given SiteInstance in this TabContents + // to be at least |page_id|. + void UpdateMaxPageIDForSiteInstance(SiteInstance* site_instance, + int32 page_id); + + // Returns the SiteInstance associated with the current page. + SiteInstance* GetSiteInstance() const; // Returns the SiteInstance for the pending navigation, if any. Otherwise // returns the current SiteInstance. @@ -680,11 +688,11 @@ class CONTENT_EXPORT TabContents : public PageNavigator, const content::LoadCommittedDetails& details, const ViewHostMsg_FrameNavigate_Params& params); - // If our controller was restored and the page id is > than the site - // instance's page id, the site instances page id is updated as well as the - // renderers max page id. - void UpdateMaxPageIDIfNecessary(SiteInstance* site_instance, - RenderViewHost* rvh); + // If our controller was restored, update the max page ID associated with the + // given RenderViewHost to be larger than the number of restored entries. + // This is called in CreateRenderView before any navigations in the RenderView + // have begun, to prevent any races in updating RenderView::next_page_id. + void UpdateMaxPageIDIfNecessary(RenderViewHost* rvh); // Saves the given title to the navigation entry and does associated work. It // will update history and the view for the new title, and also synthesize @@ -790,11 +798,10 @@ class CONTENT_EXPORT TabContents : public PageNavigator, // See waiting_for_response() above. bool waiting_for_response_; - // Indicates the largest PageID we've seen. This field is ignored if we are - // a TabContents, in which case the max page ID is stored separately with - // each SiteInstance. - // TODO(brettw) this seems like it can be removed according to the comment. - int32 max_page_id_; + // Map of SiteInstance ID to max page ID for this tab. A page ID is specific + // to a given tab and SiteInstance, and must be valid for the lifetime of the + // TabContents. + std::map<int32, int32> max_page_ids_; // System time at which the current load was started. base::TimeTicks current_load_start_; diff --git a/content/browser/tab_contents/test_tab_contents.cc b/content/browser/tab_contents/test_tab_contents.cc index 52c0cb0..55289d7 100644 --- a/content/browser/tab_contents/test_tab_contents.cc +++ b/content/browser/tab_contents/test_tab_contents.cc @@ -75,7 +75,7 @@ void TestTabContents::TestDidNavigateWithReferrer( bool TestTabContents::CreateRenderViewForRenderManager( RenderViewHost* render_view_host) { // This will go to a TestRenderViewHost. - render_view_host->CreateRenderView(string16()); + render_view_host->CreateRenderView(string16(), -1); return true; } @@ -114,8 +114,7 @@ void TestTabContents::CommitPendingNavigation() { int page_id = entry->page_id(); if (page_id == -1) { // It's a new navigation, assign a never-seen page id to it. - page_id = - static_cast<MockRenderProcessHost*>(rvh->process())->max_page_id() + 1; + page_id = GetMaxPageIDForSiteInstance(rvh->site_instance()) + 1; } rvh->SendNavigate(page_id, entry->url()); diff --git a/content/common/view_messages.h b/content/common/view_messages.h index ea86707..d29dd3d 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -626,15 +626,15 @@ IPC_STRUCT_BEGIN(ViewMsg_New_Params) // The name of the frame associated with this view (or empty if none). IPC_STRUCT_MEMBER(string16, frame_name) + + // The initial page ID to use for this view, which must be larger than any + // existing navigation that might be loaded in the view. Page IDs are unique + // to a view and are only updated by the renderer after this initial value. + IPC_STRUCT_MEMBER(int32, next_page_id) IPC_STRUCT_END() // Messages sent from the browser to the renderer. -// Used typically when recovering from a crash. The new rendering process -// sets its global "next page id" counter to the given value. -IPC_MESSAGE_CONTROL1(ViewMsg_SetNextPageID, - int32 /* next_page_id */) - // Sent to the RenderView when a new tab is swapped into an existing // tab and the histories need to be merged. The existing tab has a history of // |merged_history_length| which precedes the history of the new tab. All @@ -936,10 +936,6 @@ IPC_MESSAGE_ROUTED1(ViewMsg_SetPageEncoding, // Reset encoding of page in the renderer back to default. IPC_MESSAGE_ROUTED0(ViewMsg_ResetPageEncodingToDefault) -// Requests the renderer to reserve a range of page ids. -IPC_MESSAGE_ROUTED1(ViewMsg_ReservePageIDRange, - int /* size_of_range */) - // Used to tell a render view whether it should expose various bindings // that allow JS content extended privileges. See BindingsPolicy for valid // flag values. diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h index 194675b..68ed032 100644 --- a/content/public/browser/render_process_host.h +++ b/content/public/browser/render_process_host.h @@ -141,12 +141,6 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Message::Sender, // etc. It is generated by ChildProcessInfo. virtual int GetID() const = 0; - // Called to inform the render process host of a new "max page id" for a - // render view host. The render process host computes the largest page id - // across all render view hosts and uses the value when it needs to - // initialize a new renderer in place of the current one. - virtual void UpdateMaxPageID(int32 page_id) = 0; - // Returns the listener for the routing id passed in. virtual IPC::Channel::Listener* GetListenerByID(int routing_id) = 0; @@ -166,9 +160,6 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Message::Sender, // Try to shutdown the associated render process as fast as possible virtual bool FastShutdownForPageCount(size_t count) = 0; - // Update the max page ID and send the update to the renderer process as well - virtual void UpdateAndSendMaxPageID(int32 page_id) = 0; - // TODO(ananta) // Revisit whether the virtual functions declared from here on need to be // part of the interface. diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 219d4f0..c4be328 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -715,7 +715,6 @@ bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) { IPC_BEGIN_MESSAGE_MAP(RenderThreadImpl, msg) IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForCurrentURL, OnSetZoomLevelForCurrentURL) - IPC_MESSAGE_HANDLER(ViewMsg_SetNextPageID, OnSetNextPageID) IPC_MESSAGE_HANDLER(ViewMsg_SetCSSColors, OnSetCSSColors) // TODO(port): removed from render_messages_internal.h; // is there a new non-windows message I should add here? @@ -729,14 +728,6 @@ bool RenderThreadImpl::OnControlMessageReceived(const IPC::Message& msg) { return handled; } -void RenderThreadImpl::OnSetNextPageID(int32 next_page_id) { - // This is called at process initialization time or when this process is - // being re-used for a new RenderView. It is ok if another RenderView - // has identical page_ids or inflates next_page_id_ just before this arrives, - // as long as we ensure next_page_id_ is at least this large. - RenderViewImpl::SetNextPageID(next_page_id); -} - // Called when to register CSS Color name->system color mappings. // We update the colors one by one and then tell WebKit to refresh all render // views. @@ -769,7 +760,8 @@ void RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params& params) { new SharedRenderViewCounter(0), params.view_id, params.session_storage_namespace_id, - params.frame_name); + params.frame_name, + params.next_page_id); } GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync( @@ -846,12 +838,7 @@ void RenderThreadImpl::OnNetworkStateChanged(bool online) { } void RenderThreadImpl::OnTempCrashWithData(const GURL& data) { - // Append next_page_id_ to the data from the browser. - std::string temp = data.spec(); - temp.append("#next"); - temp.append(base::IntToString(RenderViewImpl::next_page_id())); - - content::GetContentClient()->SetActiveURL(GURL(temp)); + content::GetContentClient()->SetActiveURL(data); CHECK(false); } diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 683bc6b..9e5a815 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -179,7 +179,6 @@ class CONTENT_EXPORT RenderThreadImpl : public content::RenderThread, void OnSetZoomLevelForCurrentURL(const GURL& url, double zoom_level); void OnDOMStorageEvent(const DOMStorageMsg_Event_Params& params); - void OnSetNextPageID(int32 next_page_id); void OnSetCSSColors(const std::vector<CSSColors::CSSColorMapping>& colors); void OnCreateNewView(const ViewMsg_New_Params& params); void OnTransferBitmap(const SkBitmap& bitmap, int resource_id); diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index a09574d..1522c2f 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc @@ -314,8 +314,6 @@ static WebReferrerPolicy getReferrerPolicyFromRequest( /////////////////////////////////////////////////////////////////////////////// -int32 RenderViewImpl::next_page_id_ = 1; - struct RenderViewImpl::PendingFileChooser { PendingFileChooser(const content::FileChooserParams& p, WebFileChooserCompletion* c) @@ -334,7 +332,8 @@ RenderViewImpl::RenderViewImpl( SharedRenderViewCounter* counter, int32 routing_id, int64 session_storage_namespace_id, - const string16& frame_name) + const string16& frame_name, + int32 next_page_id) : RenderWidget(WebKit::WebPopupTypeNone), webkit_preferences_(webkit_prefs), send_content_state_immediately_(false), @@ -346,6 +345,7 @@ RenderViewImpl::RenderViewImpl( opener_suppressed_(false), page_id_(-1), last_page_id_sent_to_browser_(-1), + next_page_id_(next_page_id), history_list_offset_(-1), history_list_length_(0), target_url_status_(TARGET_NONE), @@ -371,6 +371,9 @@ RenderViewImpl::RenderViewImpl( if (opener_id != MSG_ROUTING_NONE) opener_id_ = opener_id; + // Ensure we start with a valid next_page_id_ from the browser. + DCHECK_GE(next_page_id_, 0); + #if defined(ENABLE_NOTIFICATIONS) notification_provider_ = new NotificationProvider(this); #else @@ -506,7 +509,8 @@ RenderViewImpl* RenderViewImpl::Create( SharedRenderViewCounter* counter, int32 routing_id, int64 session_storage_namespace_id, - const string16& frame_name) { + const string16& frame_name, + int32 next_page_id) { DCHECK(routing_id != MSG_ROUTING_NONE); return new RenderViewImpl( parent_hwnd, @@ -516,17 +520,8 @@ RenderViewImpl* RenderViewImpl::Create( counter, routing_id, session_storage_namespace_id, - frame_name); // adds reference -} - -// static -void RenderViewImpl::SetNextPageID(int32 next_page_id) { - // This method is called on startup or when the browser knows it needs to - // inflate the page_id when re-using the process. The renderer may have - // incremented this just as the browser was sending the message, but we - // only care that next_page_id_ is at least as large as next_page_id. - if (next_page_id > next_page_id_) - next_page_id_ = next_page_id; + frame_name, + next_page_id); // adds reference } void RenderViewImpl::AddObserver(RenderViewObserver* observer) { @@ -634,7 +629,6 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { OnResetPageEncodingToDefault) IPC_MESSAGE_HANDLER(ViewMsg_ScriptEvalRequest, OnScriptEvalRequest) IPC_MESSAGE_HANDLER(ViewMsg_CSSInsertRequest, OnCSSInsertRequest) - IPC_MESSAGE_HANDLER(ViewMsg_ReservePageIDRange, OnReservePageIDRange) IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter) IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver) IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave) @@ -1353,7 +1347,8 @@ WebView* RenderViewImpl::createView( shared_popup_counter_, routing_id, cloned_session_storage_namespace_id, - frame_name); + frame_name, + 1); view->opened_by_user_gesture_ = params.user_gesture; // Record whether the creator frame is trying to suppress the opener field. @@ -3784,10 +3779,6 @@ void RenderViewImpl::OnSetWebUIProperty(const std::string& name, GetWebUIBindings()->SetProperty(name, value); } -void RenderViewImpl::OnReservePageIDRange(int size_of_range) { - next_page_id_ += size_of_range + 1; -} - void RenderViewImpl::OnDragTargetDragEnter(const WebDropData& drop_data, const gfx::Point& client_point, const gfx::Point& screen_point, diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index cb8ac8f..97e708d 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h @@ -171,20 +171,12 @@ class RenderViewImpl : public RenderWidget, SharedRenderViewCounter* counter, int32 routing_id, int64 session_storage_namespace_id, - const string16& frame_name); + const string16& frame_name, + int32 next_page_id); // Returns the RenderViewImpl containing the given WebView. CONTENT_EXPORT static RenderViewImpl* FromWebView(WebKit::WebView* webview); - // Sets the "next page id" counter. - static void SetNextPageID(int32 next_page_id); - - // TODO(creis): Remove when we no longer need - // RenderThreadImpl::OnTempCrashWithData. - static int32 next_page_id() { - return next_page_id_; - } - // May return NULL when the view is closing. CONTENT_EXPORT WebKit::WebView* webview() const; @@ -687,7 +679,8 @@ class RenderViewImpl : public RenderWidget, SharedRenderViewCounter* counter, int32 routing_id, int64 session_storage_namespace_id, - const string16& frame_name); + const string16& frame_name, + int32 next_page_id); // Do not delete directly. This class is reference counted. virtual ~RenderViewImpl(); @@ -811,7 +804,6 @@ class RenderViewImpl : public RenderWidget, void OnRedo(); void OnReloadFrame(); void OnReplace(const string16& text); - void OnReservePageIDRange(int size_of_range); void OnResetPageEncodingToDefault(); void OnScriptEvalRequest(const string16& frame_xpath, const string16& jscript, @@ -1026,9 +1018,9 @@ class RenderViewImpl : public RenderWidget, // goes back. int32 last_page_id_sent_to_browser_; - // The next available page ID to use. This ensures that the page IDs are - // globally unique in the renderer. - static int32 next_page_id_; + // The next available page ID to use for this RenderView. These IDs are + // specific to a given RenderView and the frames within it. + int32 next_page_id_; // The offset of the current item in the history list. int history_list_offset_; diff --git a/content/test/render_view_test.cc b/content/test/render_view_test.cc index 5d60fc5..7485b79 100644 --- a/content/test/render_view_test.cc +++ b/content/test/render_view_test.cc @@ -117,7 +117,8 @@ void RenderViewTest::SetUp() { new SharedRenderViewCounter(0), kRouteId, kInvalidSessionStorageNamespaceId, - string16()); + string16(), + 1); view->AddRef(); view_ = view; |