Index: chrome/browser/ui/tabs/tab_strip_model.cc |
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc |
index da4302a9707f818b363d7e0fc77c6ad60449d138..78c8f0e1fa9620c82c4bac5195361223f1d84cdb 100644 |
--- a/chrome/browser/ui/tabs/tab_strip_model.cc |
+++ b/chrome/browser/ui/tabs/tab_strip_model.cc |
@@ -45,6 +45,67 @@ bool ShouldForgetOpenersForTransition(content::PageTransition transition) { |
transition == content::PAGE_TRANSITION_AUTO_TOPLEVEL; |
} |
+// CloseTracker is used when closing a set of WebContents. It listens for |
+// deletions of the WebContents and removes from the internal set any time one |
+// is deleted. |
+class CloseTracker : public content::NotificationObserver { |
+ public: |
+ typedef std::vector<WebContents*> Contents; |
+ |
+ explicit CloseTracker(const Contents& contents); |
+ virtual ~CloseTracker(); |
+ |
+ // Returns true if there is another WebContents in the Tracker. |
+ bool HasNext() const; |
+ |
+ // Returns the next WebContents, or NULL if there are no more. |
+ WebContents* Next(); |
+ |
+ private: |
+ // NotificationObserver: |
+ virtual void Observe(int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) OVERRIDE; |
+ |
+ Contents contents_; |
+ |
+ content::NotificationRegistrar registrar_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(CloseTracker); |
+}; |
+ |
+CloseTracker::CloseTracker(const Contents& contents) |
+ : contents_(contents) { |
+ registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
+ content::NotificationService::AllBrowserContextsAndSources()); |
+} |
+ |
+CloseTracker::~CloseTracker() { |
+} |
+ |
+bool CloseTracker::HasNext() const { |
+ return !contents_.empty(); |
+} |
+ |
+WebContents* CloseTracker::Next() { |
+ if (contents_.empty()) |
+ return NULL; |
+ |
+ WebContents* web_contents = contents_[0]; |
+ contents_.erase(contents_.begin()); |
+ return web_contents; |
+} |
+ |
+void CloseTracker::Observe(int type, |
+ const content::NotificationSource& source, |
+ const content::NotificationDetails& details) { |
+ WebContents* web_contents = content::Source<WebContents>(source).ptr(); |
+ Contents::iterator i = |
+ std::find(contents_.begin(), contents_.end(), web_contents); |
+ if (i != contents_.end()) |
+ contents_.erase(i); |
+} |
+ |
} // namespace |
/////////////////////////////////////////////////////////////////////////////// |
@@ -960,6 +1021,14 @@ bool TabStripModel::ContextMenuCommandToBrowserCommand(int cmd_id, |
/////////////////////////////////////////////////////////////////////////////// |
// TabStripModel, private: |
+std::vector<WebContents*> TabStripModel::GetWebContentsFromIndices( |
+ const std::vector<int>& indices) const { |
+ std::vector<WebContents*> contents; |
+ for (size_t i = 0; i < indices.size(); ++i) |
+ contents.push_back(GetWebContentsAtImpl(indices[i])); |
+ return contents; |
+} |
+ |
void TabStripModel::GetIndicesWithSameDomain(int index, |
std::vector<int>* indices) { |
std::string domain = GetWebContentsAt(index)->GetURL().host(); |
@@ -1014,12 +1083,7 @@ bool TabStripModel::InternalCloseTabs(const std::vector<int>& indices, |
if (indices.empty()) |
return true; |
- // Map the indices to WebContentses, that way if deleting a tab deletes |
- // other tabs we're ok. Crashes seem to indicate during tab deletion other |
- // tabs are getting removed. |
- std::vector<WebContents*> closing_contentses; |
- for (size_t i = 0; i < indices.size(); ++i) |
- closing_contentses.push_back(GetWebContentsAtImpl(indices[i])); |
+ CloseTracker close_tracker(GetWebContentsFromIndices(indices)); |
// We only try the fast shutdown path if the whole browser process is *not* |
// shutting down. Fast shutdown during browser termination is handled in |
@@ -1044,8 +1108,8 @@ bool TabStripModel::InternalCloseTabs(const std::vector<int>& indices, |
// We now return to our regularly scheduled shutdown procedure. |
bool retval = true; |
- for (size_t i = 0; i < closing_contentses.size(); ++i) { |
- WebContents* closing_contents = closing_contentses[i]; |
+ while (close_tracker.HasNext()) { |
+ WebContents* closing_contents = close_tracker.Next(); |
int index = GetIndexOfWebContents(closing_contents); |
// Make sure we still contain the tab. |
if (index == kNoTab) |