summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsreeram@chromium.org <sreeram@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-31 05:19:12 +0000
committersreeram@chromium.org <sreeram@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-31 05:19:12 +0000
commitf3bf87bf5740e1d014159581e2f1f01d5957c254 (patch)
tree9eaf5e3b84bef01897bad06808f0aa876f985612
parent7c622dc75ef2ca1cf033b2e55e263c3b2d4a5c60 (diff)
downloadchromium_src-f3bf87bf5740e1d014159581e2f1f01d5957c254.zip
chromium_src-f3bf87bf5740e1d014159581e2f1f01d5957c254.tar.gz
chromium_src-f3bf87bf5740e1d014159581e2f1f01d5957c254.tar.bz2
Keep around old tab contents until their unload handlers are done.
Delete the old tab contents only after its CloseContents() has been called. BUG=none TEST=View a page with an unload handler. Cause a prerendered page to be swapped into it. Observe that the unload handler runs fully (e.g.: via a network trace). Review URL: http://codereview.chromium.org/7063025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@87271 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/prerender/prerender_manager.cc68
-rw-r--r--chrome/browser/prerender/prerender_manager.h10
2 files changed, 74 insertions, 4 deletions
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 58c8f76..0979589 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -22,11 +22,12 @@
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper_delegate.h"
#include "chrome/common/render_messages.h"
#include "content/browser/browser_thread.h"
-#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/render_process_host.h"
+#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/renderer_host/resource_dispatcher_host.h"
#include "content/browser/tab_contents/render_view_host_manager.h"
#include "content/browser/tab_contents/tab_contents.h"
+#include "content/browser/tab_contents/tab_contents_delegate.h"
#include "content/common/notification_service.h"
#include "googleurl/src/url_canon.h"
#include "googleurl/src/url_parse.h"
@@ -69,6 +70,43 @@ const char* const kValidHttpMethods[] = {
} // namespace
+class PrerenderManager::OnCloseTabContentsDeleter : public TabContentsDelegate {
+ public:
+ OnCloseTabContentsDeleter(PrerenderManager* manager,
+ TabContentsWrapper* tab)
+ : manager_(manager),
+ tab_(tab) {
+ tab_->tab_contents()->set_delegate(this);
+ }
+
+ virtual void CloseContents(TabContents* source) OVERRIDE {
+ manager_->ScheduleDeleteOldTabContents(tab_.release(), this);
+ }
+
+ virtual bool ShouldSuppressDialogs() OVERRIDE {
+ return true;
+ }
+
+ // TabContentsDelegate implementation (pure virtual methods). Since we are
+ // waiting for the tab to close, none of this matters.
+ virtual void OpenURLFromTab(TabContents*, const GURL&, const GURL&,
+ WindowOpenDisposition, PageTransition::Type) OVERRIDE {}
+ virtual void NavigationStateChanged(const TabContents*, unsigned) OVERRIDE {}
+ virtual void AddNewContents(TabContents*, TabContents*, WindowOpenDisposition,
+ const gfx::Rect&, bool) OVERRIDE {}
+ virtual void ActivateContents(TabContents*) OVERRIDE {}
+ virtual void DeactivateContents(TabContents*) OVERRIDE {}
+ virtual void LoadingStateChanged(TabContents*) OVERRIDE {}
+ virtual void MoveContents(TabContents*, const gfx::Rect&) OVERRIDE {}
+ virtual void UpdateTargetURL(TabContents*, const GURL&) OVERRIDE {}
+
+ private:
+ PrerenderManager* manager_;
+ scoped_ptr<TabContentsWrapper> tab_;
+
+ DISALLOW_COPY_AND_ASSIGN(OnCloseTabContentsDeleter);
+};
+
// static
int PrerenderManager::prerenders_per_session_count_ = 0;
@@ -526,9 +564,15 @@ bool PrerenderManager::MaybeUsePreloadedPage(TabContents* tab_contents,
pending_prerender_list_.erase(pending_it);
}
- old_tab_contents_list_.push_back(old_tab_contents);
- // Destroy the old TabContents relatively promptly to reduce resource usage.
- PostCleanupTask();
+ if (old_tab_contents->tab_contents()->NeedToFireBeforeUnload()) {
+ // Schedule the delete to occur after the tab has run its unload handlers.
+ on_close_tab_contents_deleters_.push_back(
+ new OnCloseTabContentsDeleter(this, old_tab_contents));
+ old_tab_contents->render_view_host()->FirePageBeforeUnload(false);
+ } else {
+ // No unload handler to run, so delete asap.
+ ScheduleDeleteOldTabContents(old_tab_contents, NULL);
+ }
return true;
}
@@ -922,4 +966,20 @@ void PrerenderManager::CleanUpOldNavigations() {
}
}
+void PrerenderManager::ScheduleDeleteOldTabContents(
+ TabContentsWrapper* tab,
+ OnCloseTabContentsDeleter* deleter) {
+ old_tab_contents_list_.push_back(tab);
+ PostCleanupTask();
+
+ if (deleter) {
+ ScopedVector<OnCloseTabContentsDeleter>::iterator i = std::find(
+ on_close_tab_contents_deleters_.begin(),
+ on_close_tab_contents_deleters_.end(),
+ deleter);
+ DCHECK(i != on_close_tab_contents_deleters_.end());
+ on_close_tab_contents_deleters_.erase(i);
+ }
+}
+
} // namespace prerender
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index f35aa18..616cb35 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -12,6 +12,7 @@
#include "base/hash_tables.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "base/task.h"
#include "base/threading/non_thread_safe.h"
@@ -206,6 +207,8 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
struct PrerenderContentsData;
struct NavigationRecord;
+ class OnCloseTabContentsDeleter;
+
// Adds a pending preload issued by the prerendering RenderView identified by
// |child_route_id_pair|. If and when that prerendering RenderView is used,
// the specified prerender will start.
@@ -271,6 +274,11 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
// Cleans up old NavigationRecord's.
void CleanUpOldNavigations();
+ // Arrange for the given tab contents to be deleted asap. If deleter is not
+ // NULL, deletes that as well.
+ void ScheduleDeleteOldTabContents(TabContentsWrapper* tab,
+ OnCloseTabContentsDeleter* deleter);
+
// Specifies whether prerendering is currently enabled for this
// manager. The value can change dynamically during the lifetime
// of the PrerenderManager.
@@ -333,6 +341,8 @@ class PrerenderManager : public base::SupportsWeakPtr<PrerenderManager>,
// Cancels pending tasks on deletion.
ScopedRunnableMethodFactory<PrerenderManager> runnable_method_factory_;
+ ScopedVector<OnCloseTabContentsDeleter> on_close_tab_contents_deleters_;
+
DISALLOW_COPY_AND_ASSIGN(PrerenderManager);
};