| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/tabs/tab_strip_model.h" | 5 #include "chrome/browser/tabs/tab_strip_model.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 TabContentsWrapper* selected_contents = GetActiveTabContents(); | 135 TabContentsWrapper* selected_contents = GetActiveTabContents(); |
| 136 TabContentsData* data = new TabContentsData(contents); | 136 TabContentsData* data = new TabContentsData(contents); |
| 137 data->pinned = pin; | 137 data->pinned = pin; |
| 138 if ((add_types & ADD_INHERIT_GROUP) && selected_contents) { | 138 if ((add_types & ADD_INHERIT_GROUP) && selected_contents) { |
| 139 if (active) { | 139 if (active) { |
| 140 // Forget any existing relationships, we don't want to make things too | 140 // Forget any existing relationships, we don't want to make things too |
| 141 // confusing by having multiple groups active at the same time. | 141 // confusing by having multiple groups active at the same time. |
| 142 ForgetAllOpeners(); | 142 ForgetAllOpeners(); |
| 143 } | 143 } |
| 144 // Anything opened by a link we deem to have an opener. | 144 // Anything opened by a link we deem to have an opener. |
| 145 data->SetGroup(&selected_contents->controller()); | 145 data->SetGroup(&selected_contents->tab_contents()->controller()); |
| 146 } else if ((add_types & ADD_INHERIT_OPENER) && selected_contents) { | 146 } else if ((add_types & ADD_INHERIT_OPENER) && selected_contents) { |
| 147 if (active) { | 147 if (active) { |
| 148 // Forget any existing relationships, we don't want to make things too | 148 // Forget any existing relationships, we don't want to make things too |
| 149 // confusing by having multiple groups active at the same time. | 149 // confusing by having multiple groups active at the same time. |
| 150 ForgetAllOpeners(); | 150 ForgetAllOpeners(); |
| 151 } | 151 } |
| 152 data->opener = &selected_contents->controller(); | 152 data->opener = &selected_contents->tab_contents()->controller(); |
| 153 } | 153 } |
| 154 | 154 |
| 155 contents_data_.insert(contents_data_.begin() + index, data); | 155 contents_data_.insert(contents_data_.begin() + index, data); |
| 156 | 156 |
| 157 selection_model_.IncrementFrom(index); | 157 selection_model_.IncrementFrom(index); |
| 158 | 158 |
| 159 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 159 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 160 TabInsertedAt(contents, index, active)); | 160 TabInsertedAt(contents, index, active)); |
| 161 TabStripSelectionModel old_model; | 161 TabStripSelectionModel old_model; |
| 162 old_model.Copy(selection_model_); | 162 old_model.Copy(selection_model_); |
| 163 if (active) { | 163 if (active) { |
| 164 selection_model_.SetSelectedIndex(index); | 164 selection_model_.SetSelectedIndex(index); |
| 165 NotifyIfActiveOrSelectionChanged(selected_contents, false, old_model); | 165 NotifyIfActiveOrSelectionChanged(selected_contents, false, old_model); |
| 166 } | 166 } |
| 167 } | 167 } |
| 168 | 168 |
| 169 TabContentsWrapper* TabStripModel::ReplaceTabContentsAt( | 169 TabContentsWrapper* TabStripModel::ReplaceTabContentsAt( |
| 170 int index, | 170 int index, |
| 171 TabContentsWrapper* new_contents) { | 171 TabContentsWrapper* new_contents) { |
| 172 DCHECK(ContainsIndex(index)); | 172 DCHECK(ContainsIndex(index)); |
| 173 TabContentsWrapper* old_contents = GetContentsAt(index); | 173 TabContentsWrapper* old_contents = GetContentsAt(index); |
| 174 | 174 |
| 175 ForgetOpenersAndGroupsReferencing(&(old_contents->controller())); | 175 ForgetOpenersAndGroupsReferencing( |
| 176 &(old_contents->tab_contents()->controller())); |
| 176 | 177 |
| 177 contents_data_[index]->contents = new_contents; | 178 contents_data_[index]->contents = new_contents; |
| 178 | 179 |
| 179 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 180 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 180 TabReplacedAt(this, old_contents, new_contents, index)); | 181 TabReplacedAt(this, old_contents, new_contents, index)); |
| 181 | 182 |
| 182 // When the active tab contents is replaced send out selected notification | 183 // When the active tab contents is replaced send out selected notification |
| 183 // too. We do this as nearly all observers need to treat a replace of the | 184 // too. We do this as nearly all observers need to treat a replace of the |
| 184 // selected contents as selection changing. | 185 // selected contents as selection changing. |
| 185 if (active_index() == index) { | 186 if (active_index() == index) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 204 TabContentsWrapper* TabStripModel::DiscardTabContentsAt(int index) { | 205 TabContentsWrapper* TabStripModel::DiscardTabContentsAt(int index) { |
| 205 DCHECK(ContainsIndex(index)); | 206 DCHECK(ContainsIndex(index)); |
| 206 TabContentsWrapper* null_contents = | 207 TabContentsWrapper* null_contents = |
| 207 new TabContentsWrapper( | 208 new TabContentsWrapper( |
| 208 new TabContents(profile(), | 209 new TabContents(profile(), |
| 209 NULL /* site_instance */, | 210 NULL /* site_instance */, |
| 210 MSG_ROUTING_NONE, | 211 MSG_ROUTING_NONE, |
| 211 NULL /* base_tab_contents */, | 212 NULL /* base_tab_contents */, |
| 212 NULL /* session_storage_namespace */)); | 213 NULL /* session_storage_namespace */)); |
| 213 TabContentsWrapper* old_contents = GetContentsAt(index); | 214 TabContentsWrapper* old_contents = GetContentsAt(index); |
| 214 NavigationEntry* old_nav_entry = old_contents->controller().GetActiveEntry(); | 215 NavigationEntry* old_nav_entry = |
| 216 old_contents->tab_contents()->controller().GetActiveEntry(); |
| 215 if (old_nav_entry) { | 217 if (old_nav_entry) { |
| 216 // Set the new tab contents to reload this URL when clicked. | 218 // Set the new tab contents to reload this URL when clicked. |
| 217 // This also allows the tab to keep drawing the favicon and page title. | 219 // This also allows the tab to keep drawing the favicon and page title. |
| 218 NavigationEntry* new_nav_entry = new NavigationEntry(*old_nav_entry); | 220 NavigationEntry* new_nav_entry = new NavigationEntry(*old_nav_entry); |
| 219 std::vector<NavigationEntry*> entries; | 221 std::vector<NavigationEntry*> entries; |
| 220 entries.push_back(new_nav_entry); | 222 entries.push_back(new_nav_entry); |
| 221 null_contents->controller().Restore(0, false, &entries); | 223 null_contents->tab_contents()->controller().Restore(0, false, &entries); |
| 222 } | 224 } |
| 223 ReplaceTabContentsAt(index, null_contents); | 225 ReplaceTabContentsAt(index, null_contents); |
| 224 // Mark the tab so it will reload when we click. | 226 // Mark the tab so it will reload when we click. |
| 225 contents_data_[index]->discarded = true; | 227 contents_data_[index]->discarded = true; |
| 226 delete old_contents; | 228 delete old_contents; |
| 227 return null_contents; | 229 return null_contents; |
| 228 } | 230 } |
| 229 | 231 |
| 230 TabContentsWrapper* TabStripModel::DetachTabContentsAt(int index) { | 232 TabContentsWrapper* TabStripModel::DetachTabContentsAt(int index) { |
| 231 if (contents_data_.empty()) | 233 if (contents_data_.empty()) |
| 232 return NULL; | 234 return NULL; |
| 233 | 235 |
| 234 DCHECK(ContainsIndex(index)); | 236 DCHECK(ContainsIndex(index)); |
| 235 | 237 |
| 236 TabContentsWrapper* removed_contents = GetContentsAt(index); | 238 TabContentsWrapper* removed_contents = GetContentsAt(index); |
| 237 bool was_selected = IsTabSelected(index); | 239 bool was_selected = IsTabSelected(index); |
| 238 int next_selected_index = order_controller_->DetermineNewSelectedIndex(index); | 240 int next_selected_index = order_controller_->DetermineNewSelectedIndex(index); |
| 239 delete contents_data_.at(index); | 241 delete contents_data_.at(index); |
| 240 contents_data_.erase(contents_data_.begin() + index); | 242 contents_data_.erase(contents_data_.begin() + index); |
| 241 ForgetOpenersAndGroupsReferencing(&(removed_contents->controller())); | 243 ForgetOpenersAndGroupsReferencing( |
| 244 &(removed_contents->tab_contents()->controller())); |
| 242 if (empty()) | 245 if (empty()) |
| 243 closing_all_ = true; | 246 closing_all_ = true; |
| 244 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 247 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 245 TabDetachedAt(removed_contents, index)); | 248 TabDetachedAt(removed_contents, index)); |
| 246 if (empty()) { | 249 if (empty()) { |
| 247 selection_model_.Clear(); | 250 selection_model_.Clear(); |
| 248 // TabDetachedAt() might unregister observers, so send |TabStripEmtpy()| in | 251 // TabDetachedAt() might unregister observers, so send |TabStripEmtpy()| in |
| 249 // a second pass. | 252 // a second pass. |
| 250 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, TabStripEmpty()); | 253 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, TabStripEmpty()); |
| 251 } else { | 254 } else { |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 return index; | 380 return index; |
| 378 } | 381 } |
| 379 return kNoTab; | 382 return kNoTab; |
| 380 } | 383 } |
| 381 | 384 |
| 382 int TabStripModel::GetIndexOfController( | 385 int TabStripModel::GetIndexOfController( |
| 383 const NavigationController* controller) const { | 386 const NavigationController* controller) const { |
| 384 int index = 0; | 387 int index = 0; |
| 385 TabContentsDataVector::const_iterator iter = contents_data_.begin(); | 388 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 386 for (; iter != contents_data_.end(); ++iter, ++index) { | 389 for (; iter != contents_data_.end(); ++iter, ++index) { |
| 387 if (&(*iter)->contents->controller() == controller) | 390 if (&(*iter)->contents->tab_contents()->controller() == controller) |
| 388 return index; | 391 return index; |
| 389 } | 392 } |
| 390 return kNoTab; | 393 return kNoTab; |
| 391 } | 394 } |
| 392 | 395 |
| 393 void TabStripModel::UpdateTabContentsStateAt(int index, | 396 void TabStripModel::UpdateTabContentsStateAt(int index, |
| 394 TabStripModelObserver::TabChangeType change_type) { | 397 TabStripModelObserver::TabChangeType change_type) { |
| 395 DCHECK(ContainsIndex(index)); | 398 DCHECK(ContainsIndex(index)); |
| 396 | 399 |
| 397 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 400 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| (...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 delegate()->AddBlankTabAt(context_index + 1, true); | 837 delegate()->AddBlankTabAt(context_index + 1, true); |
| 835 break; | 838 break; |
| 836 | 839 |
| 837 case CommandReload: { | 840 case CommandReload: { |
| 838 UserMetrics::RecordAction(UserMetricsAction("TabContextMenu_Reload")); | 841 UserMetrics::RecordAction(UserMetricsAction("TabContextMenu_Reload")); |
| 839 std::vector<int> indices = GetIndicesForCommand(context_index); | 842 std::vector<int> indices = GetIndicesForCommand(context_index); |
| 840 for (size_t i = 0; i < indices.size(); ++i) { | 843 for (size_t i = 0; i < indices.size(); ++i) { |
| 841 TabContentsWrapper* tab = GetTabContentsAt(indices[i]); | 844 TabContentsWrapper* tab = GetTabContentsAt(indices[i]); |
| 842 if (tab && tab->tab_contents()->delegate()->CanReloadContents( | 845 if (tab && tab->tab_contents()->delegate()->CanReloadContents( |
| 843 tab->tab_contents())) { | 846 tab->tab_contents())) { |
| 844 tab->controller().Reload(true); | 847 tab->tab_contents()->controller().Reload(true); |
| 845 } | 848 } |
| 846 } | 849 } |
| 847 break; | 850 break; |
| 848 } | 851 } |
| 849 | 852 |
| 850 case CommandDuplicate: { | 853 case CommandDuplicate: { |
| 851 UserMetrics::RecordAction(UserMetricsAction("TabContextMenu_Duplicate")); | 854 UserMetrics::RecordAction(UserMetricsAction("TabContextMenu_Duplicate")); |
| 852 std::vector<int> indices = GetIndicesForCommand(context_index); | 855 std::vector<int> indices = GetIndicesForCommand(context_index); |
| 853 // Copy the TabContents off as the indices will change as tabs are | 856 // Copy the TabContents off as the indices will change as tabs are |
| 854 // duplicated. | 857 // duplicated. |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 if (GetTabContentsAt(i)->tab_contents()->GetURL().host() == domain) | 1080 if (GetTabContentsAt(i)->tab_contents()->GetURL().host() == domain) |
| 1078 indices->push_back(i); | 1081 indices->push_back(i); |
| 1079 } | 1082 } |
| 1080 } | 1083 } |
| 1081 | 1084 |
| 1082 void TabStripModel::GetIndicesWithSameOpener(int index, | 1085 void TabStripModel::GetIndicesWithSameOpener(int index, |
| 1083 std::vector<int>* indices) { | 1086 std::vector<int>* indices) { |
| 1084 NavigationController* opener = contents_data_[index]->group; | 1087 NavigationController* opener = contents_data_[index]->group; |
| 1085 if (!opener) { | 1088 if (!opener) { |
| 1086 // If there is no group, find all tabs with the selected tab as the opener. | 1089 // If there is no group, find all tabs with the selected tab as the opener. |
| 1087 opener = &(GetTabContentsAt(index)->controller()); | 1090 opener = &(GetTabContentsAt(index)->tab_contents()->controller()); |
| 1088 if (!opener) | 1091 if (!opener) |
| 1089 return; | 1092 return; |
| 1090 } | 1093 } |
| 1091 for (int i = 0; i < count(); ++i) { | 1094 for (int i = 0; i < count(); ++i) { |
| 1092 if (i == index) | 1095 if (i == index) |
| 1093 continue; | 1096 continue; |
| 1094 if (contents_data_[i]->group == opener || | 1097 if (contents_data_[i]->group == opener || |
| 1095 &(GetTabContentsAt(i)->controller()) == opener) { | 1098 &(GetTabContentsAt(i)->tab_contents()->controller()) == opener) { |
| 1096 indices->push_back(i); | 1099 indices->push_back(i); |
| 1097 } | 1100 } |
| 1098 } | 1101 } |
| 1099 } | 1102 } |
| 1100 | 1103 |
| 1101 std::vector<int> TabStripModel::GetIndicesForCommand(int index) const { | 1104 std::vector<int> TabStripModel::GetIndicesForCommand(int index) const { |
| 1102 if (!IsTabSelected(index)) { | 1105 if (!IsTabSelected(index)) { |
| 1103 std::vector<int> indices; | 1106 std::vector<int> indices; |
| 1104 indices.push_back(index); | 1107 indices.push_back(index); |
| 1105 return indices; | 1108 return indices; |
| 1106 } | 1109 } |
| 1107 return selection_model_.selected_indices(); | 1110 return selection_model_.selected_indices(); |
| 1108 } | 1111 } |
| 1109 | 1112 |
| 1110 bool TabStripModel::IsNewTabAtEndOfTabStrip( | 1113 bool TabStripModel::IsNewTabAtEndOfTabStrip( |
| 1111 TabContentsWrapper* contents) const { | 1114 TabContentsWrapper* contents) const { |
| 1112 const GURL& url = contents->tab_contents()->GetURL(); | 1115 const GURL& url = contents->tab_contents()->GetURL(); |
| 1113 return url.SchemeIs(chrome::kChromeUIScheme) && | 1116 return url.SchemeIs(chrome::kChromeUIScheme) && |
| 1114 url.host() == chrome::kChromeUINewTabHost && | 1117 url.host() == chrome::kChromeUINewTabHost && |
| 1115 contents == GetContentsAt(count() - 1) && | 1118 contents == GetContentsAt(count() - 1) && |
| 1116 contents->controller().entry_count() == 1; | 1119 contents->tab_contents()->controller().entry_count() == 1; |
| 1117 } | 1120 } |
| 1118 | 1121 |
| 1119 bool TabStripModel::InternalCloseTabs(const std::vector<int>& in_indices, | 1122 bool TabStripModel::InternalCloseTabs(const std::vector<int>& in_indices, |
| 1120 uint32 close_types) { | 1123 uint32 close_types) { |
| 1121 if (in_indices.empty()) | 1124 if (in_indices.empty()) |
| 1122 return true; | 1125 return true; |
| 1123 | 1126 |
| 1124 std::vector<int> indices(in_indices); | 1127 std::vector<int> indices(in_indices); |
| 1125 bool retval = delegate_->CanCloseContents(&indices); | 1128 bool retval = delegate_->CanCloseContents(&indices); |
| 1126 if (indices.empty()) | 1129 if (indices.empty()) |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1318 void TabStripModel::ForgetOpenersAndGroupsReferencing( | 1321 void TabStripModel::ForgetOpenersAndGroupsReferencing( |
| 1319 const NavigationController* tab) { | 1322 const NavigationController* tab) { |
| 1320 for (TabContentsDataVector::const_iterator i = contents_data_.begin(); | 1323 for (TabContentsDataVector::const_iterator i = contents_data_.begin(); |
| 1321 i != contents_data_.end(); ++i) { | 1324 i != contents_data_.end(); ++i) { |
| 1322 if ((*i)->group == tab) | 1325 if ((*i)->group == tab) |
| 1323 (*i)->group = NULL; | 1326 (*i)->group = NULL; |
| 1324 if ((*i)->opener == tab) | 1327 if ((*i)->opener == tab) |
| 1325 (*i)->opener = NULL; | 1328 (*i)->opener = NULL; |
| 1326 } | 1329 } |
| 1327 } | 1330 } |
| OLD | NEW |