| 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" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
| 13 #include "build/build_config.h" | 13 #include "build/build_config.h" |
| 14 #include "chrome/app/chrome_command_ids.h" | 14 #include "chrome/app/chrome_command_ids.h" |
| 15 #include "chrome/browser/bookmarks/bookmark_model.h" | 15 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 16 #include "chrome/browser/browser_shutdown.h" | 16 #include "chrome/browser/browser_shutdown.h" |
| 17 #include "chrome/browser/defaults.h" | 17 #include "chrome/browser/defaults.h" |
| 18 #include "chrome/browser/extensions/extension_service.h" | 18 #include "chrome/browser/extensions/extension_service.h" |
| 19 #include "chrome/browser/extensions/extension_tab_helper.h" | 19 #include "chrome/browser/extensions/extension_tab_helper.h" |
| 20 #include "chrome/browser/profiles/profile.h" | 20 #include "chrome/browser/profiles/profile.h" |
| 21 #include "chrome/browser/sessions/tab_restore_service.h" | 21 #include "chrome/browser/sessions/tab_restore_service.h" |
| 22 #include "chrome/browser/tabs/tab_strip_model_delegate.h" | 22 #include "chrome/browser/tabs/tab_strip_model_delegate.h" |
| 23 #include "chrome/browser/tabs/tab_strip_model_order_controller.h" | 23 #include "chrome/browser/tabs/tab_strip_model_order_controller.h" |
| 24 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 24 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 25 #include "chrome/common/chrome_notification_types.h" | 25 #include "chrome/common/chrome_notification_types.h" |
| 26 #include "chrome/common/extensions/extension.h" | 26 #include "chrome/common/extensions/extension.h" |
| 27 #include "chrome/common/url_constants.h" | 27 #include "chrome/common/url_constants.h" |
| 28 #include "content/browser/tab_contents/navigation_controller.h" | |
| 29 #include "content/browser/tab_contents/tab_contents.h" | 28 #include "content/browser/tab_contents/tab_contents.h" |
| 30 #include "content/browser/tab_contents/tab_contents_view.h" | 29 #include "content/browser/tab_contents/tab_contents_view.h" |
| 30 #include "content/public/browser/navigation_controller.h" |
| 31 #include "content/public/browser/navigation_entry.h" | 31 #include "content/public/browser/navigation_entry.h" |
| 32 #include "content/public/browser/notification_service.h" | 32 #include "content/public/browser/notification_service.h" |
| 33 #include "content/public/browser/render_process_host.h" | 33 #include "content/public/browser/render_process_host.h" |
| 34 #include "content/public/browser/user_metrics.h" | 34 #include "content/public/browser/user_metrics.h" |
| 35 #include "content/public/browser/web_contents_delegate.h" | 35 #include "content/public/browser/web_contents_delegate.h" |
| 36 | 36 |
| 37 using content::NavigationEntry; | 37 using content::NavigationEntry; |
| 38 using content::UserMetricsAction; | 38 using content::UserMetricsAction; |
| 39 using content::WebContents; | 39 using content::WebContents; |
| 40 | 40 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 ForgetAllOpeners(); | 147 ForgetAllOpeners(); |
| 148 } | 148 } |
| 149 // Anything opened by a link we deem to have an opener. | 149 // Anything opened by a link we deem to have an opener. |
| 150 data->SetGroup(&selected_contents->tab_contents()->GetController()); | 150 data->SetGroup(&selected_contents->tab_contents()->GetController()); |
| 151 } else if ((add_types & ADD_INHERIT_OPENER) && selected_contents) { | 151 } else if ((add_types & ADD_INHERIT_OPENER) && selected_contents) { |
| 152 if (active) { | 152 if (active) { |
| 153 // Forget any existing relationships, we don't want to make things too | 153 // Forget any existing relationships, we don't want to make things too |
| 154 // confusing by having multiple groups active at the same time. | 154 // confusing by having multiple groups active at the same time. |
| 155 ForgetAllOpeners(); | 155 ForgetAllOpeners(); |
| 156 } | 156 } |
| 157 data->opener = &selected_contents->tab_contents()->GetController(); | 157 data->opener = &selected_contents->web_contents()->GetController(); |
| 158 } | 158 } |
| 159 | 159 |
| 160 contents_data_.insert(contents_data_.begin() + index, data); | 160 contents_data_.insert(contents_data_.begin() + index, data); |
| 161 | 161 |
| 162 selection_model_.IncrementFrom(index); | 162 selection_model_.IncrementFrom(index); |
| 163 | 163 |
| 164 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 164 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 165 TabInsertedAt(contents, index, active)); | 165 TabInsertedAt(contents, index, active)); |
| 166 TabStripSelectionModel old_model; | 166 TabStripSelectionModel old_model; |
| 167 old_model.Copy(selection_model_); | 167 old_model.Copy(selection_model_); |
| 168 if (active) { | 168 if (active) { |
| 169 selection_model_.SetSelectedIndex(index); | 169 selection_model_.SetSelectedIndex(index); |
| 170 NotifyIfActiveOrSelectionChanged(selected_contents, false, old_model); | 170 NotifyIfActiveOrSelectionChanged(selected_contents, false, old_model); |
| 171 } | 171 } |
| 172 } | 172 } |
| 173 | 173 |
| 174 TabContentsWrapper* TabStripModel::ReplaceTabContentsAt( | 174 TabContentsWrapper* TabStripModel::ReplaceTabContentsAt( |
| 175 int index, | 175 int index, |
| 176 TabContentsWrapper* new_contents) { | 176 TabContentsWrapper* new_contents) { |
| 177 DCHECK(ContainsIndex(index)); | 177 DCHECK(ContainsIndex(index)); |
| 178 TabContentsWrapper* old_contents = GetContentsAt(index); | 178 TabContentsWrapper* old_contents = GetContentsAt(index); |
| 179 | 179 |
| 180 ForgetOpenersAndGroupsReferencing( | 180 ForgetOpenersAndGroupsReferencing( |
| 181 &(old_contents->tab_contents()->GetController())); | 181 &(old_contents->web_contents()->GetController())); |
| 182 | 182 |
| 183 contents_data_[index]->contents = new_contents; | 183 contents_data_[index]->contents = new_contents; |
| 184 | 184 |
| 185 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 185 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 186 TabReplacedAt(this, old_contents, new_contents, index)); | 186 TabReplacedAt(this, old_contents, new_contents, index)); |
| 187 | 187 |
| 188 // When the active tab contents is replaced send out selected notification | 188 // When the active tab contents is replaced send out selected notification |
| 189 // too. We do this as nearly all observers need to treat a replace of the | 189 // too. We do this as nearly all observers need to treat a replace of the |
| 190 // selected contents as selection changing. | 190 // selected contents as selection changing. |
| 191 if (active_index() == index) { | 191 if (active_index() == index) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 return NULL; | 239 return NULL; |
| 240 | 240 |
| 241 DCHECK(ContainsIndex(index)); | 241 DCHECK(ContainsIndex(index)); |
| 242 | 242 |
| 243 TabContentsWrapper* removed_contents = GetContentsAt(index); | 243 TabContentsWrapper* removed_contents = GetContentsAt(index); |
| 244 bool was_selected = IsTabSelected(index); | 244 bool was_selected = IsTabSelected(index); |
| 245 int next_selected_index = order_controller_->DetermineNewSelectedIndex(index); | 245 int next_selected_index = order_controller_->DetermineNewSelectedIndex(index); |
| 246 delete contents_data_.at(index); | 246 delete contents_data_.at(index); |
| 247 contents_data_.erase(contents_data_.begin() + index); | 247 contents_data_.erase(contents_data_.begin() + index); |
| 248 ForgetOpenersAndGroupsReferencing( | 248 ForgetOpenersAndGroupsReferencing( |
| 249 &(removed_contents->tab_contents()->GetController())); | 249 &(removed_contents->web_contents()->GetController())); |
| 250 if (empty()) | 250 if (empty()) |
| 251 closing_all_ = true; | 251 closing_all_ = true; |
| 252 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 252 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 253 TabDetachedAt(removed_contents, index)); | 253 TabDetachedAt(removed_contents, index)); |
| 254 if (empty()) { | 254 if (empty()) { |
| 255 selection_model_.Clear(); | 255 selection_model_.Clear(); |
| 256 // TabDetachedAt() might unregister observers, so send |TabStripEmtpy()| in | 256 // TabDetachedAt() might unregister observers, so send |TabStripEmtpy()| in |
| 257 // a second pass. | 257 // a second pass. |
| 258 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, TabStripEmpty()); | 258 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, TabStripEmpty()); |
| 259 } else { | 259 } else { |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 | 425 |
| 426 bool TabStripModel::TabsAreLoading() const { | 426 bool TabStripModel::TabsAreLoading() const { |
| 427 TabContentsDataVector::const_iterator iter = contents_data_.begin(); | 427 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 428 for (; iter != contents_data_.end(); ++iter) { | 428 for (; iter != contents_data_.end(); ++iter) { |
| 429 if ((*iter)->contents->tab_contents()->IsLoading()) | 429 if ((*iter)->contents->tab_contents()->IsLoading()) |
| 430 return true; | 430 return true; |
| 431 } | 431 } |
| 432 return false; | 432 return false; |
| 433 } | 433 } |
| 434 | 434 |
| 435 NavigationController* TabStripModel::GetOpenerOfTabContentsAt(int index) { | 435 content::NavigationController* TabStripModel::GetOpenerOfTabContentsAt( |
| 436 int index) { |
| 436 DCHECK(ContainsIndex(index)); | 437 DCHECK(ContainsIndex(index)); |
| 437 return contents_data_.at(index)->opener; | 438 return contents_data_.at(index)->opener; |
| 438 } | 439 } |
| 439 | 440 |
| 440 int TabStripModel::GetIndexOfNextTabContentsOpenedBy( | 441 int TabStripModel::GetIndexOfNextTabContentsOpenedBy( |
| 441 const NavigationController* opener, int start_index, bool use_group) const { | 442 const content::NavigationController* opener, |
| 443 int start_index, |
| 444 bool use_group) const { |
| 442 DCHECK(opener); | 445 DCHECK(opener); |
| 443 DCHECK(ContainsIndex(start_index)); | 446 DCHECK(ContainsIndex(start_index)); |
| 444 | 447 |
| 445 // Check tabs after start_index first. | 448 // Check tabs after start_index first. |
| 446 for (int i = start_index + 1; i < count(); ++i) { | 449 for (int i = start_index + 1; i < count(); ++i) { |
| 447 if (OpenerMatches(contents_data_[i], opener, use_group)) | 450 if (OpenerMatches(contents_data_[i], opener, use_group)) |
| 448 return i; | 451 return i; |
| 449 } | 452 } |
| 450 // Then check tabs before start_index, iterating backwards. | 453 // Then check tabs before start_index, iterating backwards. |
| 451 for (int i = start_index - 1; i >= 0; --i) { | 454 for (int i = start_index - 1; i >= 0; --i) { |
| 452 if (OpenerMatches(contents_data_[i], opener, use_group)) | 455 if (OpenerMatches(contents_data_[i], opener, use_group)) |
| 453 return i; | 456 return i; |
| 454 } | 457 } |
| 455 return kNoTab; | 458 return kNoTab; |
| 456 } | 459 } |
| 457 | 460 |
| 458 int TabStripModel::GetIndexOfFirstTabContentsOpenedBy( | 461 int TabStripModel::GetIndexOfFirstTabContentsOpenedBy( |
| 459 const NavigationController* opener, | 462 const content::NavigationController* opener, |
| 460 int start_index) const { | 463 int start_index) const { |
| 461 DCHECK(opener); | 464 DCHECK(opener); |
| 462 DCHECK(ContainsIndex(start_index)); | 465 DCHECK(ContainsIndex(start_index)); |
| 463 | 466 |
| 464 for (int i = 0; i < start_index; ++i) { | 467 for (int i = 0; i < start_index; ++i) { |
| 465 if (contents_data_[i]->opener == opener) | 468 if (contents_data_[i]->opener == opener) |
| 466 return i; | 469 return i; |
| 467 } | 470 } |
| 468 return kNoTab; | 471 return kNoTab; |
| 469 } | 472 } |
| 470 | 473 |
| 471 int TabStripModel::GetIndexOfLastTabContentsOpenedBy( | 474 int TabStripModel::GetIndexOfLastTabContentsOpenedBy( |
| 472 const NavigationController* opener, int start_index) const { | 475 const content::NavigationController* opener, int start_index) const { |
| 473 DCHECK(opener); | 476 DCHECK(opener); |
| 474 DCHECK(ContainsIndex(start_index)); | 477 DCHECK(ContainsIndex(start_index)); |
| 475 | 478 |
| 476 TabContentsDataVector::const_iterator end = | 479 TabContentsDataVector::const_iterator end = |
| 477 contents_data_.begin() + start_index; | 480 contents_data_.begin() + start_index; |
| 478 TabContentsDataVector::const_iterator iter = contents_data_.end(); | 481 TabContentsDataVector::const_iterator iter = contents_data_.end(); |
| 479 TabContentsDataVector::const_iterator next; | 482 TabContentsDataVector::const_iterator next; |
| 480 for (; iter != end; --iter) { | 483 for (; iter != end; --iter) { |
| 481 next = iter - 1; | 484 next = iter - 1; |
| 482 if (next == end) | 485 if (next == end) |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 for (int i = 0; i < count(); ++i) { | 1085 for (int i = 0; i < count(); ++i) { |
| 1083 if (i == index) | 1086 if (i == index) |
| 1084 continue; | 1087 continue; |
| 1085 if (GetTabContentsAt(i)->tab_contents()->GetURL().host() == domain) | 1088 if (GetTabContentsAt(i)->tab_contents()->GetURL().host() == domain) |
| 1086 indices->push_back(i); | 1089 indices->push_back(i); |
| 1087 } | 1090 } |
| 1088 } | 1091 } |
| 1089 | 1092 |
| 1090 void TabStripModel::GetIndicesWithSameOpener(int index, | 1093 void TabStripModel::GetIndicesWithSameOpener(int index, |
| 1091 std::vector<int>* indices) { | 1094 std::vector<int>* indices) { |
| 1092 NavigationController* opener = contents_data_[index]->group; | 1095 content::NavigationController* opener = contents_data_[index]->group; |
| 1093 if (!opener) { | 1096 if (!opener) { |
| 1094 // If there is no group, find all tabs with the selected tab as the opener. | 1097 // If there is no group, find all tabs with the selected tab as the opener. |
| 1095 opener = &(GetTabContentsAt(index)->tab_contents()->GetController()); | 1098 opener = &(GetTabContentsAt(index)->tab_contents()->GetController()); |
| 1096 if (!opener) | 1099 if (!opener) |
| 1097 return; | 1100 return; |
| 1098 } | 1101 } |
| 1099 for (int i = 0; i < count(); ++i) { | 1102 for (int i = 0; i < count(); ++i) { |
| 1100 if (i == index) | 1103 if (i == index) |
| 1101 continue; | 1104 continue; |
| 1102 if (contents_data_[i]->group == opener || | 1105 if (contents_data_[i]->group == opener || |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1311 MoveTabContentsAt(selection_model_.selected_indices()[tab_index], | 1314 MoveTabContentsAt(selection_model_.selected_indices()[tab_index], |
| 1312 target_index, false); | 1315 target_index, false); |
| 1313 } | 1316 } |
| 1314 tab_index++; | 1317 tab_index++; |
| 1315 target_index++; | 1318 target_index++; |
| 1316 } | 1319 } |
| 1317 } | 1320 } |
| 1318 | 1321 |
| 1319 // static | 1322 // static |
| 1320 bool TabStripModel::OpenerMatches(const TabContentsData* data, | 1323 bool TabStripModel::OpenerMatches(const TabContentsData* data, |
| 1321 const NavigationController* opener, | 1324 const content::NavigationController* opener, |
| 1322 bool use_group) { | 1325 bool use_group) { |
| 1323 return data->opener == opener || (use_group && data->group == opener); | 1326 return data->opener == opener || (use_group && data->group == opener); |
| 1324 } | 1327 } |
| 1325 | 1328 |
| 1326 void TabStripModel::ForgetOpenersAndGroupsReferencing( | 1329 void TabStripModel::ForgetOpenersAndGroupsReferencing( |
| 1327 const NavigationController* tab) { | 1330 const content::NavigationController* tab) { |
| 1328 for (TabContentsDataVector::const_iterator i = contents_data_.begin(); | 1331 for (TabContentsDataVector::const_iterator i = contents_data_.begin(); |
| 1329 i != contents_data_.end(); ++i) { | 1332 i != contents_data_.end(); ++i) { |
| 1330 if ((*i)->group == tab) | 1333 if ((*i)->group == tab) |
| 1331 (*i)->group = NULL; | 1334 (*i)->group = NULL; |
| 1332 if ((*i)->opener == tab) | 1335 if ((*i)->opener == tab) |
| 1333 (*i)->opener = NULL; | 1336 (*i)->opener = NULL; |
| 1334 } | 1337 } |
| 1335 } | 1338 } |
| OLD | NEW |