Index: chrome/browser/instant/instant_unload_handler.cc |
diff --git a/chrome/browser/instant/instant_unload_handler.cc b/chrome/browser/instant/instant_unload_handler.cc |
index c7b580fd2c80966c323473d6cc1c58c2f4bf53d1..fa64ed1e13894fd15485de712c4eb5a3e1e61397 100644 |
--- a/chrome/browser/instant/instant_unload_handler.cc |
+++ b/chrome/browser/instant/instant_unload_handler.cc |
@@ -12,42 +12,43 @@ |
#include "content/public/browser/web_contents.h" |
#include "content/public/browser/web_contents_delegate.h" |
-// WebContentsDelegate implementation. This owns the WebContents supplied to the |
-// constructor. |
class InstantUnloadHandler::WebContentsDelegateImpl |
: public content::WebContentsDelegate { |
public: |
WebContentsDelegateImpl(InstantUnloadHandler* handler, |
- content::WebContents* contents, |
+ scoped_ptr<content::WebContents> contents, |
int index) |
: handler_(handler), |
- contents_(contents), |
+ contents_(contents.Pass()), |
index_(index) { |
- contents->SetDelegate(this); |
+ contents_->SetDelegate(this); |
+ contents_->GetRenderViewHost()->FirePageBeforeUnload(false); |
} |
- // content::WebContentsDelegate overrides: |
- virtual void WillRunBeforeUnloadConfirm() OVERRIDE { |
- content::WebContents* contents = contents_.release(); |
- contents->SetDelegate(NULL); |
- handler_->Activate(this, contents, index_); |
+ // Overridden from content::WebContentsDelegate: |
+ virtual void CloseContents(content::WebContents* source) OVERRIDE { |
+ DCHECK_EQ(contents_, source); |
+ // Remove ourselves as the delegate, so that CloseContents() won't be |
+ // called twice, leading to double deletion (http://crbug.com/155848). |
+ contents_->SetDelegate(NULL); |
+ handler_->Destroy(this); |
} |
- virtual bool ShouldSuppressDialogs() OVERRIDE { |
- return true; // Return true so dialogs are suppressed. |
+ virtual void WillRunBeforeUnloadConfirm() OVERRIDE { |
+ contents_->SetDelegate(NULL); |
+ handler_->Activate(this, contents_.Pass(), index_); |
} |
- virtual void CloseContents(content::WebContents* source) OVERRIDE { |
- contents_->SetDelegate(NULL); |
- handler_->Destroy(this); |
+ virtual bool ShouldSuppressDialogs() OVERRIDE { |
+ return true; |
} |
private: |
InstantUnloadHandler* const handler_; |
scoped_ptr<content::WebContents> contents_; |
- // The index |contents_| was originally at. If we add the tab back we add it |
- // at this index. |
+ // The tab strip index |contents_| was originally at. If we add the tab back |
+ // to the tabstrip, we add it at this index. |
const int index_; |
DISALLOW_COPY_AND_ASSIGN(WebContentsDelegateImpl); |
@@ -61,7 +62,7 @@ InstantUnloadHandler::~InstantUnloadHandler() { |
} |
void InstantUnloadHandler::RunUnloadListenersOrDestroy( |
- content::WebContents* contents, |
+ scoped_ptr<content::WebContents> contents, |
int index) { |
DCHECK(!contents->GetDelegate()); |
@@ -71,27 +72,25 @@ void InstantUnloadHandler::RunUnloadListenersOrDestroy( |
// get here from BrowserInstantController::TabDeactivated, other tab |
// observers may still expect to interact with the tab before the event has |
// finished propagating. |
- MessageLoop::current()->DeleteSoon(FROM_HERE, contents); |
+ MessageLoop::current()->DeleteSoon(FROM_HERE, contents.release()); |
return; |
} |
- // Tab has before unload listener. Install a delegate and fire the before |
- // unload listener. |
- delegates_.push_back(new WebContentsDelegateImpl(this, contents, index)); |
- contents->GetRenderViewHost()->FirePageBeforeUnload(false); |
+ // Tab has beforeunload listeners. Install a delegate to run them. |
+ delegates_.push_back( |
+ new WebContentsDelegateImpl(this, contents.Pass(), index)); |
} |
void InstantUnloadHandler::Activate(WebContentsDelegateImpl* delegate, |
- content::WebContents* contents, |
+ scoped_ptr<content::WebContents> contents, |
int index) { |
- chrome::NavigateParams params(browser_, contents); |
- params.disposition = NEW_FOREGROUND_TAB; |
- params.tabstrip_index = index; |
- |
// Remove (and delete) the delegate. |
Destroy(delegate); |
// Add the tab back in. |
+ chrome::NavigateParams params(browser_, contents.release()); |
+ params.disposition = NEW_FOREGROUND_TAB; |
+ params.tabstrip_index = index; |
chrome::Navigate(¶ms); |
} |