diff options
author | sreeram@chromium.org <sreeram@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-31 05:19:12 +0000 |
---|---|---|
committer | sreeram@chromium.org <sreeram@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-31 05:19:12 +0000 |
commit | f3bf87bf5740e1d014159581e2f1f01d5957c254 (patch) | |
tree | 9eaf5e3b84bef01897bad06808f0aa876f985612 | |
parent | 7c622dc75ef2ca1cf033b2e55e263c3b2d4a5c60 (diff) | |
download | chromium_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.cc | 68 | ||||
-rw-r--r-- | chrome/browser/prerender/prerender_manager.h | 10 |
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); }; |