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
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@114862 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/content/browser/tab_contents/tab_contents.cc b/content/browser/tab_contents/tab_contents.cc
index a3ffb433..390acb4 100644
--- a/content/browser/tab_contents/tab_contents.cc
+++ b/content/browser/tab_contents/tab_contents.cc
@@ -196,7 +196,6 @@
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 @@
}
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 {
@@ -1328,30 +1332,16 @@
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,
@@ -2018,7 +2008,12 @@
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)
@@ -2030,8 +2025,6 @@
}
#endif
- UpdateMaxPageIDIfNecessary(render_view_host->site_instance(),
- render_view_host);
return true;
}