Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(42)

Side by Side Diff: chrome/browser/ui/tabs/tab_strip_model.cc

Issue 15896023: Makes TabStripModel deal handle the case of the TabStripModel (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Incorporate Avi's feedback Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/tabs/tab_strip_model.h" 5 #include "chrome/browser/ui/tabs/tab_strip_model.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <map> 8 #include <map>
9 #include <string> 9 #include <string>
10 10
(...skipping 27 matching lines...) Expand all
38 // any navigation that can be considered to be the start of a new task distinct 38 // any navigation that can be considered to be the start of a new task distinct
39 // from what had previously occurred in that tab). 39 // from what had previously occurred in that tab).
40 bool ShouldForgetOpenersForTransition(content::PageTransition transition) { 40 bool ShouldForgetOpenersForTransition(content::PageTransition transition) {
41 return transition == content::PAGE_TRANSITION_TYPED || 41 return transition == content::PAGE_TRANSITION_TYPED ||
42 transition == content::PAGE_TRANSITION_AUTO_BOOKMARK || 42 transition == content::PAGE_TRANSITION_AUTO_BOOKMARK ||
43 transition == content::PAGE_TRANSITION_GENERATED || 43 transition == content::PAGE_TRANSITION_GENERATED ||
44 transition == content::PAGE_TRANSITION_KEYWORD || 44 transition == content::PAGE_TRANSITION_KEYWORD ||
45 transition == content::PAGE_TRANSITION_AUTO_TOPLEVEL; 45 transition == content::PAGE_TRANSITION_AUTO_TOPLEVEL;
46 } 46 }
47 47
48 // CloseTracker is used when closing a set of WebContents. It listens for
49 // deletions of the WebContents and removes from the internal set any time one
50 // is deleted.
51 class CloseTracker : public content::NotificationObserver {
52 public:
53 typedef std::vector<WebContents*> Contents;
54
55 explicit CloseTracker(const Contents& contents);
56 virtual ~CloseTracker();
57
58 // Returns true if there is another WebContents in the Tracker.
59 bool HasNext() const;
60
61 // Returns the next WebContents, or NULL if there are no more.
62 WebContents* Next();
63
64 private:
65 // NotificationObserver:
66 virtual void Observe(int type,
67 const content::NotificationSource& source,
68 const content::NotificationDetails& details) OVERRIDE;
69
70 Contents contents_;
71
72 content::NotificationRegistrar registrar_;
73
74 DISALLOW_COPY_AND_ASSIGN(CloseTracker);
75 };
76
77 CloseTracker::CloseTracker(const Contents& contents)
78 : contents_(contents) {
79 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
80 content::NotificationService::AllBrowserContextsAndSources());
81 }
82
83 CloseTracker::~CloseTracker() {
84 }
85
86 bool CloseTracker::HasNext() const {
87 return !contents_.empty();
88 }
89
90 WebContents* CloseTracker::Next() {
91 if (contents_.empty())
92 return NULL;
93
94 WebContents* web_contents = contents_[0];
95 contents_.erase(contents_.begin());
96 return web_contents;
97 }
98
99 void CloseTracker::Observe(int type,
100 const content::NotificationSource& source,
101 const content::NotificationDetails& details) {
102 WebContents* web_contents = content::Source<WebContents>(source).ptr();
103 Contents::iterator i =
104 std::find(contents_.begin(), contents_.end(), web_contents);
105 if (i != contents_.end())
106 contents_.erase(i);
107 }
108
48 } // namespace 109 } // namespace
49 110
50 /////////////////////////////////////////////////////////////////////////////// 111 ///////////////////////////////////////////////////////////////////////////////
51 // TabStripModel, public: 112 // TabStripModel, public:
52 113
53 TabStripModel::TabStripModel(TabStripModelDelegate* delegate, Profile* profile) 114 TabStripModel::TabStripModel(TabStripModelDelegate* delegate, Profile* profile)
54 : delegate_(delegate), 115 : delegate_(delegate),
55 profile_(profile), 116 profile_(profile),
56 closing_all_(false) { 117 closing_all_(false) {
57 DCHECK(delegate_); 118 DCHECK(delegate_);
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 *browser_cmd = 0; 1014 *browser_cmd = 0;
954 return false; 1015 return false;
955 } 1016 }
956 1017
957 return true; 1018 return true;
958 } 1019 }
959 1020
960 /////////////////////////////////////////////////////////////////////////////// 1021 ///////////////////////////////////////////////////////////////////////////////
961 // TabStripModel, private: 1022 // TabStripModel, private:
962 1023
1024 std::vector<WebContents*> TabStripModel::GetWebContentsFromIndices(
1025 const std::vector<int>& indices) const {
1026 std::vector<WebContents*> contents;
1027 for (size_t i = 0; i < indices.size(); ++i)
1028 contents.push_back(GetWebContentsAtImpl(indices[i]));
1029 return contents;
1030 }
1031
963 void TabStripModel::GetIndicesWithSameDomain(int index, 1032 void TabStripModel::GetIndicesWithSameDomain(int index,
964 std::vector<int>* indices) { 1033 std::vector<int>* indices) {
965 std::string domain = GetWebContentsAt(index)->GetURL().host(); 1034 std::string domain = GetWebContentsAt(index)->GetURL().host();
966 if (domain.empty()) 1035 if (domain.empty())
967 return; 1036 return;
968 for (int i = 0; i < count(); ++i) { 1037 for (int i = 0; i < count(); ++i) {
969 if (i == index) 1038 if (i == index)
970 continue; 1039 continue;
971 if (GetWebContentsAt(i)->GetURL().host() == domain) 1040 if (GetWebContentsAt(i)->GetURL().host() == domain)
972 indices->push_back(i); 1041 indices->push_back(i);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 url.host() == chrome::kChromeUINewTabHost && 1076 url.host() == chrome::kChromeUINewTabHost &&
1008 contents == GetWebContentsAtImpl(count() - 1) && 1077 contents == GetWebContentsAtImpl(count() - 1) &&
1009 contents->GetController().GetEntryCount() == 1; 1078 contents->GetController().GetEntryCount() == 1;
1010 } 1079 }
1011 1080
1012 bool TabStripModel::InternalCloseTabs(const std::vector<int>& indices, 1081 bool TabStripModel::InternalCloseTabs(const std::vector<int>& indices,
1013 uint32 close_types) { 1082 uint32 close_types) {
1014 if (indices.empty()) 1083 if (indices.empty())
1015 return true; 1084 return true;
1016 1085
1017 // Map the indices to WebContentses, that way if deleting a tab deletes 1086 CloseTracker close_tracker(GetWebContentsFromIndices(indices));
1018 // other tabs we're ok. Crashes seem to indicate during tab deletion other
1019 // tabs are getting removed.
1020 std::vector<WebContents*> closing_contentses;
1021 for (size_t i = 0; i < indices.size(); ++i)
1022 closing_contentses.push_back(GetWebContentsAtImpl(indices[i]));
1023 1087
1024 // We only try the fast shutdown path if the whole browser process is *not* 1088 // We only try the fast shutdown path if the whole browser process is *not*
1025 // shutting down. Fast shutdown during browser termination is handled in 1089 // shutting down. Fast shutdown during browser termination is handled in
1026 // BrowserShutdown. 1090 // BrowserShutdown.
1027 if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) { 1091 if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) {
1028 // Construct a map of processes to the number of associated tabs that are 1092 // Construct a map of processes to the number of associated tabs that are
1029 // closing. 1093 // closing.
1030 std::map<content::RenderProcessHost*, size_t> processes; 1094 std::map<content::RenderProcessHost*, size_t> processes;
1031 for (size_t i = 0; i < indices.size(); ++i) { 1095 for (size_t i = 0; i < indices.size(); ++i) {
1032 WebContents* closing_contents = GetWebContentsAtImpl(indices[i]); 1096 WebContents* closing_contents = GetWebContentsAtImpl(indices[i]);
1033 content::RenderProcessHost* process = 1097 content::RenderProcessHost* process =
1034 closing_contents->GetRenderProcessHost(); 1098 closing_contents->GetRenderProcessHost();
1035 ++processes[process]; 1099 ++processes[process];
1036 } 1100 }
1037 1101
1038 // Try to fast shutdown the tabs that can close. 1102 // Try to fast shutdown the tabs that can close.
1039 for (std::map<content::RenderProcessHost*, size_t>::iterator iter = 1103 for (std::map<content::RenderProcessHost*, size_t>::iterator iter =
1040 processes.begin(); iter != processes.end(); ++iter) { 1104 processes.begin(); iter != processes.end(); ++iter) {
1041 iter->first->FastShutdownForPageCount(iter->second); 1105 iter->first->FastShutdownForPageCount(iter->second);
1042 } 1106 }
1043 } 1107 }
1044 1108
1045 // We now return to our regularly scheduled shutdown procedure. 1109 // We now return to our regularly scheduled shutdown procedure.
1046 bool retval = true; 1110 bool retval = true;
1047 for (size_t i = 0; i < closing_contentses.size(); ++i) { 1111 while (close_tracker.HasNext()) {
1048 WebContents* closing_contents = closing_contentses[i]; 1112 WebContents* closing_contents = close_tracker.Next();
1049 int index = GetIndexOfWebContents(closing_contents); 1113 int index = GetIndexOfWebContents(closing_contents);
1050 // Make sure we still contain the tab. 1114 // Make sure we still contain the tab.
1051 if (index == kNoTab) 1115 if (index == kNoTab)
1052 continue; 1116 continue;
1053 1117
1054 closing_contents->OnCloseStarted(); 1118 closing_contents->OnCloseStarted();
1055 1119
1056 // Update the explicitly closed state. If the unload handlers cancel the 1120 // Update the explicitly closed state. If the unload handlers cancel the
1057 // close the state is reset in Browser. We don't update the explicitly 1121 // close the state is reset in Browser. We don't update the explicitly
1058 // closed state if already marked as explicitly closed as unload handlers 1122 // closed state if already marked as explicitly closed as unload handlers
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 void TabStripModel::ForgetOpenersAndGroupsReferencing( 1283 void TabStripModel::ForgetOpenersAndGroupsReferencing(
1220 const WebContents* tab) { 1284 const WebContents* tab) {
1221 for (WebContentsDataVector::const_iterator i = contents_data_.begin(); 1285 for (WebContentsDataVector::const_iterator i = contents_data_.begin();
1222 i != contents_data_.end(); ++i) { 1286 i != contents_data_.end(); ++i) {
1223 if ((*i)->group == tab) 1287 if ((*i)->group == tab)
1224 (*i)->group = NULL; 1288 (*i)->group = NULL;
1225 if ((*i)->opener == tab) 1289 if ((*i)->opener == tab)
1226 (*i)->opener = NULL; 1290 (*i)->opener = NULL;
1227 } 1291 }
1228 } 1292 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/tabs/tab_strip_model.h ('k') | chrome/browser/ui/tabs/tab_strip_model_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698