| 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)
|
|
|