1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/ui/browser_tab_strip_tracker.h"
6 
7 #include "base/auto_reset.h"
8 #include "chrome/browser/ui/browser.h"
9 #include "chrome/browser/ui/browser_list.h"
10 #include "chrome/browser/ui/browser_tab_strip_tracker_delegate.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 
BrowserTabStripTracker(TabStripModelObserver * tab_strip_model_observer,BrowserTabStripTrackerDelegate * delegate)13 BrowserTabStripTracker::BrowserTabStripTracker(
14     TabStripModelObserver* tab_strip_model_observer,
15     BrowserTabStripTrackerDelegate* delegate)
16     : tab_strip_model_observer_(tab_strip_model_observer),
17       delegate_(delegate),
18       is_processing_initial_browsers_(false) {
19   DCHECK(tab_strip_model_observer_);
20 }
21 
~BrowserTabStripTracker()22 BrowserTabStripTracker::~BrowserTabStripTracker() {
23   // Per ObserverList::RemoveObserver() documentation, this does nothing if the
24   // observer is not in the ObserverList (i.e. if |browser| is not tracked).
25   for (auto* browser : *BrowserList::GetInstance())
26     browser->tab_strip_model()->RemoveObserver(tab_strip_model_observer_);
27 
28   BrowserList::RemoveObserver(this);
29 }
30 
Init()31 void BrowserTabStripTracker::Init() {
32   BrowserList::AddObserver(this);
33 
34   base::AutoReset<bool> resetter(&is_processing_initial_browsers_, true);
35   for (auto* browser : *BrowserList::GetInstance())
36     MaybeTrackBrowser(browser);
37 }
38 
ShouldTrackBrowser(Browser * browser)39 bool BrowserTabStripTracker::ShouldTrackBrowser(Browser* browser) {
40   return !delegate_ || delegate_->ShouldTrackBrowser(browser);
41 }
42 
MaybeTrackBrowser(Browser * browser)43 void BrowserTabStripTracker::MaybeTrackBrowser(Browser* browser) {
44   if (!ShouldTrackBrowser(browser))
45     return;
46 
47   TabStripModel* tab_strip_model = browser->tab_strip_model();
48   tab_strip_model->AddObserver(tab_strip_model_observer_);
49 
50   TabStripModelChange::Insert insert;
51   for (int i = 0; i < tab_strip_model->count(); ++i) {
52     insert.contents.push_back({tab_strip_model->GetWebContentsAt(i), i});
53   }
54 
55   TabStripModelChange change(std::move(insert));
56   TabStripSelectionChange selection(tab_strip_model->GetActiveWebContents(),
57                                     tab_strip_model->selection_model());
58   tab_strip_model_observer_->OnTabStripModelChanged(tab_strip_model, change,
59                                                     selection);
60 }
61 
OnBrowserAdded(Browser * browser)62 void BrowserTabStripTracker::OnBrowserAdded(Browser* browser) {
63   // No Browser should be added when iterating on Browsers in Init(), as that
64   // may invalidate the iterator.
65   DCHECK(!is_processing_initial_browsers_);
66 
67   MaybeTrackBrowser(browser);
68 }
69 
OnBrowserRemoved(Browser * browser)70 void BrowserTabStripTracker::OnBrowserRemoved(Browser* browser) {
71   // No Browser should be removed when iterating on Browsers in Init(), as that
72   // invalidates any iterator that is past the removed Browser.
73   DCHECK(!is_processing_initial_browsers_);
74 
75   // Per ObserverList::RemoveObserver() documentation, this does nothing if the
76   // observer is not in the ObserverList (i.e. if |browser| is not tracked).
77   browser->tab_strip_model()->RemoveObserver(tab_strip_model_observer_);
78 }
79