| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/stl_util-inl.h" | 10 #include "base/stl_util-inl.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| 12 #include "build/build_config.h" | 12 #include "build/build_config.h" |
| 13 #include "chrome/browser/bookmarks/bookmark_model.h" | 13 #include "chrome/browser/bookmarks/bookmark_model.h" |
| 14 #include "chrome/browser/browser_shutdown.h" | 14 #include "chrome/browser/browser_shutdown.h" |
| 15 #include "chrome/browser/defaults.h" | 15 #include "chrome/browser/defaults.h" |
| 16 #include "chrome/browser/extensions/extensions_service.h" | 16 #include "chrome/browser/extensions/extensions_service.h" |
| 17 #include "chrome/browser/metrics/user_metrics.h" | 17 #include "chrome/browser/metrics/user_metrics.h" |
| 18 #include "chrome/browser/profile.h" | 18 #include "chrome/browser/profile.h" |
| 19 #include "chrome/browser/renderer_host/render_process_host.h" | 19 #include "chrome/browser/renderer_host/render_process_host.h" |
| 20 #include "chrome/browser/sessions/tab_restore_service.h" | 20 #include "chrome/browser/sessions/tab_restore_service.h" |
| 21 #include "chrome/browser/tabs/tab_strip_model_delegate.h" | 21 #include "chrome/browser/tabs/tab_strip_model_delegate.h" |
| 22 #include "chrome/browser/tabs/tab_strip_model_order_controller.h" | 22 #include "chrome/browser/tabs/tab_strip_model_order_controller.h" |
| 23 #include "chrome/browser/tab_contents_wrapper.h" |
| 23 #include "chrome/browser/tab_contents/navigation_controller.h" | 24 #include "chrome/browser/tab_contents/navigation_controller.h" |
| 24 #include "chrome/browser/tab_contents/tab_contents.h" | 25 #include "chrome/browser/tab_contents/tab_contents.h" |
| 25 #include "chrome/browser/tab_contents/tab_contents_delegate.h" | 26 #include "chrome/browser/tab_contents/tab_contents_delegate.h" |
| 26 #include "chrome/browser/tab_contents/tab_contents_view.h" | 27 #include "chrome/browser/tab_contents/tab_contents_view.h" |
| 27 #include "chrome/common/chrome_switches.h" | 28 #include "chrome/common/chrome_switches.h" |
| 28 #include "chrome/common/extensions/extension.h" | 29 #include "chrome/common/extensions/extension.h" |
| 29 #include "chrome/common/notification_service.h" | 30 #include "chrome/common/notification_service.h" |
| 30 #include "chrome/common/url_constants.h" | 31 #include "chrome/common/url_constants.h" |
| 31 | 32 |
| 32 namespace { | 33 namespace { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 } | 97 } |
| 97 | 98 |
| 98 bool TabStripModel::HasObserver(TabStripModelObserver* observer) { | 99 bool TabStripModel::HasObserver(TabStripModelObserver* observer) { |
| 99 return observers_.HasObserver(observer); | 100 return observers_.HasObserver(observer); |
| 100 } | 101 } |
| 101 | 102 |
| 102 bool TabStripModel::ContainsIndex(int index) const { | 103 bool TabStripModel::ContainsIndex(int index) const { |
| 103 return index >= 0 && index < count(); | 104 return index >= 0 && index < count(); |
| 104 } | 105 } |
| 105 | 106 |
| 106 void TabStripModel::AppendTabContents(TabContents* contents, bool foreground) { | 107 void TabStripModel::AppendTabContents(TabContentsWrapper* contents, |
| 108 bool foreground) { |
| 107 int index = order_controller_->DetermineInsertionIndexForAppending(); | 109 int index = order_controller_->DetermineInsertionIndexForAppending(); |
| 108 InsertTabContentsAt(index, contents, | 110 InsertTabContentsAt(index, contents, |
| 109 foreground ? (ADD_INHERIT_GROUP | ADD_SELECTED) : | 111 foreground ? (ADD_INHERIT_GROUP | ADD_SELECTED) : |
| 110 ADD_NONE); | 112 ADD_NONE); |
| 111 } | 113 } |
| 112 | 114 |
| 113 void TabStripModel::InsertTabContentsAt(int index, | 115 void TabStripModel::InsertTabContentsAt(int index, |
| 114 TabContents* contents, | 116 TabContentsWrapper* contents, |
| 115 int add_types) { | 117 int add_types) { |
| 116 bool foreground = add_types & ADD_SELECTED; | 118 bool foreground = add_types & ADD_SELECTED; |
| 117 // Force app tabs to be pinned. | 119 // Force app tabs to be pinned. |
| 118 bool pin = contents->is_app() || add_types & ADD_PINNED; | 120 bool pin = contents->is_app() || add_types & ADD_PINNED; |
| 119 index = ConstrainInsertionIndex(index, pin); | 121 index = ConstrainInsertionIndex(index, pin); |
| 120 | 122 |
| 121 // In tab dragging situations, if the last tab in the window was detached | 123 // In tab dragging situations, if the last tab in the window was detached |
| 122 // then the user aborted the drag, we will have the |closing_all_| member | 124 // then the user aborted the drag, we will have the |closing_all_| member |
| 123 // set (see DetachTabContentsAt) which will mess with our mojo here. We need | 125 // set (see DetachTabContentsAt) which will mess with our mojo here. We need |
| 124 // to clear this bit. | 126 // to clear this bit. |
| 125 closing_all_ = false; | 127 closing_all_ = false; |
| 126 | 128 |
| 127 // Have to get the selected contents before we monkey with |contents_| | 129 // Have to get the selected contents before we monkey with |contents_| |
| 128 // otherwise we run into problems when we try to change the selected contents | 130 // otherwise we run into problems when we try to change the selected contents |
| 129 // since the old contents and the new contents will be the same... | 131 // since the old contents and the new contents will be the same... |
| 130 TabContents* selected_contents = GetSelectedTabContents(); | 132 TabContentsWrapper* selected_contents = GetSelectedTabContents(); |
| 131 TabContentsData* data = new TabContentsData(contents); | 133 TabContentsData* data = new TabContentsData(contents); |
| 132 data->pinned = pin; | 134 data->pinned = pin; |
| 133 if ((add_types & ADD_INHERIT_GROUP) && selected_contents) { | 135 if ((add_types & ADD_INHERIT_GROUP) && selected_contents) { |
| 134 if (foreground) { | 136 if (foreground) { |
| 135 // Forget any existing relationships, we don't want to make things too | 137 // Forget any existing relationships, we don't want to make things too |
| 136 // confusing by having multiple groups active at the same time. | 138 // confusing by having multiple groups active at the same time. |
| 137 ForgetAllOpeners(); | 139 ForgetAllOpeners(); |
| 138 } | 140 } |
| 139 // Anything opened by a link we deem to have an opener. | 141 // Anything opened by a link we deem to have an opener. |
| 140 data->SetGroup(&selected_contents->controller()); | 142 data->SetGroup(&selected_contents->controller()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 155 ++selected_index_; | 157 ++selected_index_; |
| 156 } | 158 } |
| 157 | 159 |
| 158 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 160 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 159 TabInsertedAt(contents, index, foreground)); | 161 TabInsertedAt(contents, index, foreground)); |
| 160 | 162 |
| 161 if (foreground) | 163 if (foreground) |
| 162 ChangeSelectedContentsFrom(selected_contents, index, false); | 164 ChangeSelectedContentsFrom(selected_contents, index, false); |
| 163 } | 165 } |
| 164 | 166 |
| 165 void TabStripModel::ReplaceTabContentsAt(int index, TabContents* new_contents) { | 167 void TabStripModel::ReplaceTabContentsAt(int index, |
| 168 TabContentsWrapper* new_contents) { |
| 166 // TODO: this should reset group/opener of any tabs that point at | 169 // TODO: this should reset group/opener of any tabs that point at |
| 167 // old_contents. | 170 // old_contents. |
| 168 DCHECK(ContainsIndex(index)); | 171 DCHECK(ContainsIndex(index)); |
| 169 scoped_ptr<TabContents> old_contents(GetContentsAt(index)); | 172 scoped_ptr<TabContentsWrapper> old_contents(GetContentsAt(index)); |
| 170 | 173 |
| 171 contents_data_[index]->contents = new_contents; | 174 contents_data_[index]->contents = new_contents; |
| 172 | 175 |
| 173 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 176 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 174 TabReplacedAt(old_contents.get(), new_contents, index)); | 177 TabReplacedAt(old_contents.get(), new_contents, index)); |
| 175 | 178 |
| 176 // When the selected tab contents is replaced send out selected notification | 179 // When the selected tab contents is replaced send out selected notification |
| 177 // too. We do this as nearly all observers need to treat a replace of the | 180 // too. We do this as nearly all observers need to treat a replace of the |
| 178 // selected contents as selection changing. | 181 // selected contents as selection changing. |
| 179 if (selected_index_ == index) { | 182 if (selected_index_ == index) { |
| 180 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 183 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 181 TabSelectedAt(old_contents.get(), new_contents, | 184 TabSelectedAt(old_contents.get(), new_contents, |
| 182 selected_index_, false)); | 185 selected_index_, false)); |
| 183 } | 186 } |
| 184 } | 187 } |
| 185 | 188 |
| 186 void TabStripModel::ReplaceNavigationControllerAt( | 189 void TabStripModel::ReplaceNavigationControllerAt( |
| 187 int index, NavigationController* controller) { | 190 int index, TabContentsWrapper* contents) { |
| 188 // This appears to be OK with no flicker since no redraw event | 191 // This appears to be OK with no flicker since no redraw event |
| 189 // occurs between the call to add an aditional tab and one to close | 192 // occurs between the call to add an aditional tab and one to close |
| 190 // the previous tab. | 193 // the previous tab. |
| 191 InsertTabContentsAt( | 194 InsertTabContentsAt( |
| 192 index + 1, controller->tab_contents(), | 195 index + 1, contents, |
| 193 ADD_SELECTED | ADD_INHERIT_GROUP); | 196 ADD_SELECTED | ADD_INHERIT_GROUP); |
| 194 std::vector<int> closing_tabs; | 197 std::vector<int> closing_tabs; |
| 195 closing_tabs.push_back(index); | 198 closing_tabs.push_back(index); |
| 196 InternalCloseTabs(closing_tabs, CLOSE_NONE); | 199 InternalCloseTabs(closing_tabs, CLOSE_NONE); |
| 197 } | 200 } |
| 198 | 201 |
| 199 TabContents* TabStripModel::DetachTabContentsAt(int index) { | 202 TabContentsWrapper* TabStripModel::DetachTabContentsAt(int index) { |
| 200 if (contents_data_.empty()) | 203 if (contents_data_.empty()) |
| 201 return NULL; | 204 return NULL; |
| 202 | 205 |
| 203 DCHECK(ContainsIndex(index)); | 206 DCHECK(ContainsIndex(index)); |
| 204 | 207 |
| 205 TabContents* removed_contents = GetContentsAt(index); | 208 TabContentsWrapper* removed_contents = GetContentsAt(index); |
| 206 int next_selected_index = order_controller_->DetermineNewSelectedIndex(index); | 209 int next_selected_index = order_controller_->DetermineNewSelectedIndex(index); |
| 207 delete contents_data_.at(index); | 210 delete contents_data_.at(index); |
| 208 contents_data_.erase(contents_data_.begin() + index); | 211 contents_data_.erase(contents_data_.begin() + index); |
| 209 if (empty()) | 212 if (empty()) |
| 210 closing_all_ = true; | 213 closing_all_ = true; |
| 211 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 214 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 212 TabDetachedAt(removed_contents, index)); | 215 TabDetachedAt(removed_contents, index)); |
| 213 if (empty()) { | 216 if (empty()) { |
| 214 // TabDetachedAt() might unregister observers, so send |TabStripEmtpy()| in | 217 // TabDetachedAt() might unregister observers, so send |TabStripEmtpy()| in |
| 215 // a second pass. | 218 // a second pass. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 241 if ((index < first_non_mini_tab && to_position >= first_non_mini_tab) || | 244 if ((index < first_non_mini_tab && to_position >= first_non_mini_tab) || |
| 242 (to_position < first_non_mini_tab && index >= first_non_mini_tab)) { | 245 (to_position < first_non_mini_tab && index >= first_non_mini_tab)) { |
| 243 // This would result in mini tabs mixed with non-mini tabs. We don't allow | 246 // This would result in mini tabs mixed with non-mini tabs. We don't allow |
| 244 // that. | 247 // that. |
| 245 return; | 248 return; |
| 246 } | 249 } |
| 247 | 250 |
| 248 MoveTabContentsAtImpl(index, to_position, select_after_move); | 251 MoveTabContentsAtImpl(index, to_position, select_after_move); |
| 249 } | 252 } |
| 250 | 253 |
| 251 TabContents* TabStripModel::GetSelectedTabContents() const { | 254 TabContentsWrapper* TabStripModel::GetSelectedTabContents() const { |
| 252 return GetTabContentsAt(selected_index_); | 255 return GetTabContentsAt(selected_index_); |
| 253 } | 256 } |
| 254 | 257 |
| 255 TabContents* TabStripModel::GetTabContentsAt(int index) const { | 258 TabContentsWrapper* TabStripModel::GetTabContentsAt(int index) const { |
| 256 if (ContainsIndex(index)) | 259 if (ContainsIndex(index)) |
| 257 return GetContentsAt(index); | 260 return GetContentsAt(index); |
| 258 return NULL; | 261 return NULL; |
| 259 } | 262 } |
| 260 | 263 |
| 261 int TabStripModel::GetIndexOfTabContents(const TabContents* contents) const { | 264 int TabStripModel::GetIndexOfTabContents( |
| 265 const TabContentsWrapper* contents) const { |
| 262 int index = 0; | 266 int index = 0; |
| 263 TabContentsDataVector::const_iterator iter = contents_data_.begin(); | 267 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 264 for (; iter != contents_data_.end(); ++iter, ++index) { | 268 for (; iter != contents_data_.end(); ++iter, ++index) { |
| 265 if ((*iter)->contents == contents) | 269 if ((*iter)->contents == contents) |
| 266 return index; | 270 return index; |
| 267 } | 271 } |
| 268 return kNoTab; | 272 return kNoTab; |
| 269 } | 273 } |
| 270 | 274 |
| 275 int TabStripModel::GetWrapperIndex(const TabContents* contents) const { |
| 276 int index = 0; |
| 277 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 278 for (; iter != contents_data_.end(); ++iter, ++index) { |
| 279 if ((*iter)->contents->tab_contents() == contents) |
| 280 return index; |
| 281 } |
| 282 return kNoTab; |
| 283 } |
| 284 |
| 271 int TabStripModel::GetIndexOfController( | 285 int TabStripModel::GetIndexOfController( |
| 272 const NavigationController* controller) const { | 286 const NavigationController* controller) const { |
| 273 int index = 0; | 287 int index = 0; |
| 274 TabContentsDataVector::const_iterator iter = contents_data_.begin(); | 288 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 275 for (; iter != contents_data_.end(); ++iter, ++index) { | 289 for (; iter != contents_data_.end(); ++iter, ++index) { |
| 276 if (&(*iter)->contents->controller() == controller) | 290 if (&(*iter)->contents->controller() == controller) |
| 277 return index; | 291 return index; |
| 278 } | 292 } |
| 279 return kNoTab; | 293 return kNoTab; |
| 280 } | 294 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 300 | 314 |
| 301 bool TabStripModel::CloseTabContentsAt(int index, uint32 close_types) { | 315 bool TabStripModel::CloseTabContentsAt(int index, uint32 close_types) { |
| 302 std::vector<int> closing_tabs; | 316 std::vector<int> closing_tabs; |
| 303 closing_tabs.push_back(index); | 317 closing_tabs.push_back(index); |
| 304 return InternalCloseTabs(closing_tabs, close_types); | 318 return InternalCloseTabs(closing_tabs, close_types); |
| 305 } | 319 } |
| 306 | 320 |
| 307 bool TabStripModel::TabsAreLoading() const { | 321 bool TabStripModel::TabsAreLoading() const { |
| 308 TabContentsDataVector::const_iterator iter = contents_data_.begin(); | 322 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 309 for (; iter != contents_data_.end(); ++iter) { | 323 for (; iter != contents_data_.end(); ++iter) { |
| 310 if ((*iter)->contents->is_loading()) | 324 if ((*iter)->contents->tab_contents()->is_loading()) |
| 311 return true; | 325 return true; |
| 312 } | 326 } |
| 313 return false; | 327 return false; |
| 314 } | 328 } |
| 315 | 329 |
| 316 NavigationController* TabStripModel::GetOpenerOfTabContentsAt(int index) { | 330 NavigationController* TabStripModel::GetOpenerOfTabContentsAt(int index) { |
| 317 DCHECK(ContainsIndex(index)); | 331 DCHECK(ContainsIndex(index)); |
| 318 return contents_data_.at(index)->opener; | 332 return contents_data_.at(index)->opener; |
| 319 } | 333 } |
| 320 | 334 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 for (; iter != end; --iter) { | 375 for (; iter != end; --iter) { |
| 362 next = iter - 1; | 376 next = iter - 1; |
| 363 if (next == end) | 377 if (next == end) |
| 364 break; | 378 break; |
| 365 if ((*next)->opener == opener) | 379 if ((*next)->opener == opener) |
| 366 return static_cast<int>(next - contents_data_.begin()); | 380 return static_cast<int>(next - contents_data_.begin()); |
| 367 } | 381 } |
| 368 return kNoTab; | 382 return kNoTab; |
| 369 } | 383 } |
| 370 | 384 |
| 371 void TabStripModel::TabNavigating(TabContents* contents, | 385 void TabStripModel::TabNavigating(TabContentsWrapper* contents, |
| 372 PageTransition::Type transition) { | 386 PageTransition::Type transition) { |
| 373 if (ShouldForgetOpenersForTransition(transition)) { | 387 if (ShouldForgetOpenersForTransition(transition)) { |
| 374 // Don't forget the openers if this tab is a New Tab page opened at the | 388 // Don't forget the openers if this tab is a New Tab page opened at the |
| 375 // end of the TabStrip (e.g. by pressing Ctrl+T). Give the user one | 389 // end of the TabStrip (e.g. by pressing Ctrl+T). Give the user one |
| 376 // navigation of one of these transition types before resetting the | 390 // navigation of one of these transition types before resetting the |
| 377 // opener relationships (this allows for the use case of opening a new | 391 // opener relationships (this allows for the use case of opening a new |
| 378 // tab to do a quick look-up of something while viewing a tab earlier in | 392 // tab to do a quick look-up of something while viewing a tab earlier in |
| 379 // the strip). We can make this heuristic more permissive if need be. | 393 // the strip). We can make this heuristic more permissive if need be. |
| 380 if (!IsNewTabAtEndOfTabStrip(contents)) { | 394 if (!IsNewTabAtEndOfTabStrip(contents)) { |
| 381 // If the user navigates the current tab to another page in any way | 395 // If the user navigates the current tab to another page in any way |
| 382 // other than by clicking a link, we want to pro-actively forget all | 396 // other than by clicking a link, we want to pro-actively forget all |
| 383 // TabStrip opener relationships since we assume they're beginning a | 397 // TabStrip opener relationships since we assume they're beginning a |
| 384 // different task by reusing the current tab. | 398 // different task by reusing the current tab. |
| 385 ForgetAllOpeners(); | 399 ForgetAllOpeners(); |
| 386 // In this specific case we also want to reset the group relationship, | 400 // In this specific case we also want to reset the group relationship, |
| 387 // since it is now technically invalid. | 401 // since it is now technically invalid. |
| 388 ForgetGroup(contents); | 402 ForgetGroup(contents); |
| 389 } | 403 } |
| 390 } | 404 } |
| 391 } | 405 } |
| 392 | 406 |
| 393 void TabStripModel::ForgetAllOpeners() { | 407 void TabStripModel::ForgetAllOpeners() { |
| 394 // Forget all opener memories so we don't do anything weird with tab | 408 // Forget all opener memories so we don't do anything weird with tab |
| 395 // re-selection ordering. | 409 // re-selection ordering. |
| 396 TabContentsDataVector::const_iterator iter = contents_data_.begin(); | 410 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 397 for (; iter != contents_data_.end(); ++iter) | 411 for (; iter != contents_data_.end(); ++iter) |
| 398 (*iter)->ForgetOpener(); | 412 (*iter)->ForgetOpener(); |
| 399 } | 413 } |
| 400 | 414 |
| 401 void TabStripModel::ForgetGroup(TabContents* contents) { | 415 void TabStripModel::ForgetGroup(TabContentsWrapper* contents) { |
| 402 int index = GetIndexOfTabContents(contents); | 416 int index = GetIndexOfTabContents(contents); |
| 403 DCHECK(ContainsIndex(index)); | 417 DCHECK(ContainsIndex(index)); |
| 404 contents_data_.at(index)->SetGroup(NULL); | 418 contents_data_.at(index)->SetGroup(NULL); |
| 405 contents_data_.at(index)->ForgetOpener(); | 419 contents_data_.at(index)->ForgetOpener(); |
| 406 } | 420 } |
| 407 | 421 |
| 408 bool TabStripModel::ShouldResetGroupOnSelect(TabContents* contents) const { | 422 bool TabStripModel::ShouldResetGroupOnSelect( |
| 423 TabContentsWrapper* contents) const { |
| 409 int index = GetIndexOfTabContents(contents); | 424 int index = GetIndexOfTabContents(contents); |
| 410 DCHECK(ContainsIndex(index)); | 425 DCHECK(ContainsIndex(index)); |
| 411 return contents_data_.at(index)->reset_group_on_select; | 426 return contents_data_.at(index)->reset_group_on_select; |
| 412 } | 427 } |
| 413 | 428 |
| 414 void TabStripModel::SetTabBlocked(int index, bool blocked) { | 429 void TabStripModel::SetTabBlocked(int index, bool blocked) { |
| 415 DCHECK(ContainsIndex(index)); | 430 DCHECK(ContainsIndex(index)); |
| 416 if (contents_data_[index]->blocked == blocked) | 431 if (contents_data_[index]->blocked == blocked) |
| 417 return; | 432 return; |
| 418 contents_data_[index]->blocked = blocked; | 433 contents_data_[index]->blocked = blocked; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 462 | 477 |
| 463 bool TabStripModel::IsTabPinned(int index) const { | 478 bool TabStripModel::IsTabPinned(int index) const { |
| 464 return contents_data_[index]->pinned; | 479 return contents_data_[index]->pinned; |
| 465 } | 480 } |
| 466 | 481 |
| 467 bool TabStripModel::IsMiniTab(int index) const { | 482 bool TabStripModel::IsMiniTab(int index) const { |
| 468 return IsTabPinned(index) || IsAppTab(index); | 483 return IsTabPinned(index) || IsAppTab(index); |
| 469 } | 484 } |
| 470 | 485 |
| 471 bool TabStripModel::IsAppTab(int index) const { | 486 bool TabStripModel::IsAppTab(int index) const { |
| 472 TabContents* contents = GetTabContentsAt(index); | 487 TabContentsWrapper* contents = GetTabContentsAt(index); |
| 473 return contents && contents->is_app(); | 488 return contents && contents->is_app(); |
| 474 } | 489 } |
| 475 | 490 |
| 476 bool TabStripModel::IsTabBlocked(int index) const { | 491 bool TabStripModel::IsTabBlocked(int index) const { |
| 477 return contents_data_[index]->blocked; | 492 return contents_data_[index]->blocked; |
| 478 } | 493 } |
| 479 | 494 |
| 480 int TabStripModel::IndexOfFirstNonMiniTab() const { | 495 int TabStripModel::IndexOfFirstNonMiniTab() const { |
| 481 for (size_t i = 0; i < contents_data_.size(); ++i) { | 496 for (size_t i = 0; i < contents_data_.size(); ++i) { |
| 482 if (!IsMiniTab(static_cast<int>(i))) | 497 if (!IsMiniTab(static_cast<int>(i))) |
| 483 return static_cast<int>(i); | 498 return static_cast<int>(i); |
| 484 } | 499 } |
| 485 // No mini-tabs. | 500 // No mini-tabs. |
| 486 return count(); | 501 return count(); |
| 487 } | 502 } |
| 488 | 503 |
| 489 int TabStripModel::ConstrainInsertionIndex(int index, bool mini_tab) { | 504 int TabStripModel::ConstrainInsertionIndex(int index, bool mini_tab) { |
| 490 return mini_tab ? std::min(std::max(0, index), IndexOfFirstNonMiniTab()) : | 505 return mini_tab ? std::min(std::max(0, index), IndexOfFirstNonMiniTab()) : |
| 491 std::min(count(), std::max(index, IndexOfFirstNonMiniTab())); | 506 std::min(count(), std::max(index, IndexOfFirstNonMiniTab())); |
| 492 } | 507 } |
| 493 | 508 |
| 494 void TabStripModel::AddTabContents(TabContents* contents, | 509 void TabStripModel::AddTabContents(TabContentsWrapper* contents, |
| 495 int index, | 510 int index, |
| 496 PageTransition::Type transition, | 511 PageTransition::Type transition, |
| 497 int add_types) { | 512 int add_types) { |
| 498 // If the newly-opened tab is part of the same task as the parent tab, we want | 513 // If the newly-opened tab is part of the same task as the parent tab, we want |
| 499 // to inherit the parent's "group" attribute, so that if this tab is then | 514 // to inherit the parent's "group" attribute, so that if this tab is then |
| 500 // closed we'll jump back to the parent tab. | 515 // closed we'll jump back to the parent tab. |
| 501 bool inherit_group = (add_types & ADD_INHERIT_GROUP) == ADD_INHERIT_GROUP; | 516 bool inherit_group = (add_types & ADD_INHERIT_GROUP) == ADD_INHERIT_GROUP; |
| 502 | 517 |
| 503 if (transition == PageTransition::LINK && | 518 if (transition == PageTransition::LINK && |
| 504 (add_types & ADD_FORCE_INDEX) == 0) { | 519 (add_types & ADD_FORCE_INDEX) == 0) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 // TODO(sky): figure out why this is here and not in InsertTabContentsAt. When | 553 // TODO(sky): figure out why this is here and not in InsertTabContentsAt. When |
| 539 // here we seem to get failures in startup perf tests. | 554 // here we seem to get failures in startup perf tests. |
| 540 // Ensure that the new TabContentsView begins at the same size as the | 555 // Ensure that the new TabContentsView begins at the same size as the |
| 541 // previous TabContentsView if it existed. Otherwise, the initial WebKit | 556 // previous TabContentsView if it existed. Otherwise, the initial WebKit |
| 542 // layout will be performed based on a width of 0 pixels, causing a | 557 // layout will be performed based on a width of 0 pixels, causing a |
| 543 // very long, narrow, inaccurate layout. Because some scripts on pages (as | 558 // very long, narrow, inaccurate layout. Because some scripts on pages (as |
| 544 // well as WebKit's anchor link location calculation) are run on the | 559 // well as WebKit's anchor link location calculation) are run on the |
| 545 // initial layout and not recalculated later, we need to ensure the first | 560 // initial layout and not recalculated later, we need to ensure the first |
| 546 // layout is performed with sane view dimensions even when we're opening a | 561 // layout is performed with sane view dimensions even when we're opening a |
| 547 // new background tab. | 562 // new background tab. |
| 548 if (TabContents* old_contents = GetSelectedTabContents()) { | 563 if (TabContentsWrapper* old_contents = GetSelectedTabContents()) { |
| 549 if ((add_types & ADD_SELECTED) == 0) { | 564 if ((add_types & ADD_SELECTED) == 0) { |
| 550 contents->view()->SizeContents(old_contents->view()->GetContainerSize()); | 565 contents->tab_contents()->view()-> |
| 566 SizeContents(old_contents->tab_contents()-> |
| 567 view()->GetContainerSize()); |
| 551 // We need to hide the contents or else we get and execute paints for | 568 // We need to hide the contents or else we get and execute paints for |
| 552 // background tabs. With enough background tabs they will steal the | 569 // background tabs. With enough background tabs they will steal the |
| 553 // backing store of the visible tab causing flashing. See bug 20831. | 570 // backing store of the visible tab causing flashing. See bug 20831. |
| 554 contents->HideContents(); | 571 contents->tab_contents()->HideContents(); |
| 555 } | 572 } |
| 556 } | 573 } |
| 557 } | 574 } |
| 558 | 575 |
| 559 void TabStripModel::CloseSelectedTab() { | 576 void TabStripModel::CloseSelectedTab() { |
| 560 CloseTabContentsAt(selected_index_, CLOSE_CREATE_HISTORICAL_TAB); | 577 CloseTabContentsAt(selected_index_, CLOSE_CREATE_HISTORICAL_TAB); |
| 561 } | 578 } |
| 562 | 579 |
| 563 void TabStripModel::SelectNextTab() { | 580 void TabStripModel::SelectNextTab() { |
| 564 SelectRelativeTab(true); | 581 SelectRelativeTab(true); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 584 | 601 |
| 585 // Context menu functions. | 602 // Context menu functions. |
| 586 bool TabStripModel::IsContextMenuCommandEnabled( | 603 bool TabStripModel::IsContextMenuCommandEnabled( |
| 587 int context_index, ContextMenuCommand command_id) const { | 604 int context_index, ContextMenuCommand command_id) const { |
| 588 DCHECK(command_id > CommandFirst && command_id < CommandLast); | 605 DCHECK(command_id > CommandFirst && command_id < CommandLast); |
| 589 switch (command_id) { | 606 switch (command_id) { |
| 590 case CommandNewTab: | 607 case CommandNewTab: |
| 591 case CommandCloseTab: | 608 case CommandCloseTab: |
| 592 return delegate_->CanCloseTab(); | 609 return delegate_->CanCloseTab(); |
| 593 case CommandReload: | 610 case CommandReload: |
| 594 if (TabContents* contents = GetTabContentsAt(context_index)) { | 611 if (TabContentsWrapper* contents = GetTabContentsAt(context_index)) { |
| 595 return contents->delegate()->CanReloadContents(contents); | 612 return contents->tab_contents()-> |
| 613 delegate()->CanReloadContents(contents->tab_contents()); |
| 596 } else { | 614 } else { |
| 597 return false; | 615 return false; |
| 598 } | 616 } |
| 599 case CommandCloseOtherTabs: { | 617 case CommandCloseOtherTabs: { |
| 600 int mini_tab_count = IndexOfFirstNonMiniTab(); | 618 int mini_tab_count = IndexOfFirstNonMiniTab(); |
| 601 int non_mini_tab_count = count() - mini_tab_count; | 619 int non_mini_tab_count = count() - mini_tab_count; |
| 602 // Close other doesn't effect mini-tabs. | 620 // Close other doesn't effect mini-tabs. |
| 603 return non_mini_tab_count > 1 || | 621 return non_mini_tab_count > 1 || |
| 604 (non_mini_tab_count == 1 && context_index != mini_tab_count); | 622 (non_mini_tab_count == 1 && context_index != mini_tab_count); |
| 605 } | 623 } |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 // TabStripModel, NotificationObserver implementation: | 757 // TabStripModel, NotificationObserver implementation: |
| 740 | 758 |
| 741 void TabStripModel::Observe(NotificationType type, | 759 void TabStripModel::Observe(NotificationType type, |
| 742 const NotificationSource& source, | 760 const NotificationSource& source, |
| 743 const NotificationDetails& details) { | 761 const NotificationDetails& details) { |
| 744 switch (type.value) { | 762 switch (type.value) { |
| 745 case NotificationType::TAB_CONTENTS_DESTROYED: { | 763 case NotificationType::TAB_CONTENTS_DESTROYED: { |
| 746 // Sometimes, on qemu, it seems like a TabContents object can be destroyed | 764 // Sometimes, on qemu, it seems like a TabContents object can be destroyed |
| 747 // while we still have a reference to it. We need to break this reference | 765 // while we still have a reference to it. We need to break this reference |
| 748 // here so we don't crash later. | 766 // here so we don't crash later. |
| 749 int index = GetIndexOfTabContents(Source<TabContents>(source).ptr()); | 767 int index = GetWrapperIndex(Source<TabContents>(source).ptr()); |
| 750 if (index != TabStripModel::kNoTab) { | 768 if (index != TabStripModel::kNoTab) { |
| 751 // Note that we only detach the contents here, not close it - it's | 769 // Note that we only detach the contents here, not close it - it's |
| 752 // already been closed. We just want to undo our bookkeeping. | 770 // already been closed. We just want to undo our bookkeeping. |
| 753 DetachTabContentsAt(index); | 771 DetachTabContentsAt(index); |
| 754 } | 772 } |
| 755 break; | 773 break; |
| 756 } | 774 } |
| 757 | 775 |
| 758 case NotificationType::EXTENSION_UNLOADED: { | 776 case NotificationType::EXTENSION_UNLOADED: { |
| 759 const Extension* extension = Details<const Extension>(details).ptr(); | 777 const Extension* extension = Details<const Extension>(details).ptr(); |
| 760 // Iterate backwards as we may remove items while iterating. | 778 // Iterate backwards as we may remove items while iterating. |
| 761 for (int i = count() - 1; i >= 0; i--) { | 779 for (int i = count() - 1; i >= 0; i--) { |
| 762 TabContents* contents = GetTabContentsAt(i); | 780 TabContentsWrapper* contents = GetTabContentsAt(i); |
| 763 if (contents->extension_app() == extension) { | 781 if (contents->extension_app() == extension) { |
| 764 // The extension an app tab was created from has been nuked. Delete | 782 // The extension an app tab was created from has been nuked. Delete |
| 765 // the TabContents. Deleting a TabContents results in a notification | 783 // the TabContents. Deleting a TabContents results in a notification |
| 766 // of type TAB_CONTENTS_DESTROYED; we do the necessary cleanup in | 784 // of type TAB_CONTENTS_DESTROYED; we do the necessary cleanup in |
| 767 // handling that notification. | 785 // handling that notification. |
| 768 | 786 |
| 769 InternalCloseTab(contents, i, false); | 787 InternalCloseTab(contents, i, false); |
| 770 } | 788 } |
| 771 } | 789 } |
| 772 break; | 790 break; |
| 773 } | 791 } |
| 774 | 792 |
| 775 default: | 793 default: |
| 776 NOTREACHED(); | 794 NOTREACHED(); |
| 777 } | 795 } |
| 778 } | 796 } |
| 779 | 797 |
| 780 /////////////////////////////////////////////////////////////////////////////// | 798 /////////////////////////////////////////////////////////////////////////////// |
| 781 // TabStripModel, private: | 799 // TabStripModel, private: |
| 782 | 800 |
| 783 bool TabStripModel::IsNewTabAtEndOfTabStrip(TabContents* contents) const { | 801 bool TabStripModel::IsNewTabAtEndOfTabStrip( |
| 784 return LowerCaseEqualsASCII(contents->GetURL().spec(), | 802 TabContentsWrapper* contents) const { |
| 803 return LowerCaseEqualsASCII(contents->tab_contents()->GetURL().spec(), |
| 785 chrome::kChromeUINewTabURL) && | 804 chrome::kChromeUINewTabURL) && |
| 786 contents == GetContentsAt(count() - 1) && | 805 contents == GetContentsAt(count() - 1) && |
| 787 contents->controller().entry_count() == 1; | 806 contents->controller().entry_count() == 1; |
| 788 } | 807 } |
| 789 | 808 |
| 790 bool TabStripModel::InternalCloseTabs(const std::vector<int>& indices, | 809 bool TabStripModel::InternalCloseTabs(const std::vector<int>& indices, |
| 791 uint32 close_types) { | 810 uint32 close_types) { |
| 792 if (indices.empty()) | 811 if (indices.empty()) |
| 793 return true; | 812 return true; |
| 794 | 813 |
| 795 bool retval = true; | 814 bool retval = true; |
| 796 | 815 |
| 797 // Map the indices to TabContents, that way if deleting a tab deletes other | 816 // Map the indices to TabContents, that way if deleting a tab deletes other |
| 798 // tabs we're ok. Crashes seem to indicate during tab deletion other tabs are | 817 // tabs we're ok. Crashes seem to indicate during tab deletion other tabs are |
| 799 // getting removed. | 818 // getting removed. |
| 800 std::vector<TabContents*> tabs; | 819 std::vector<TabContentsWrapper*> tabs; |
| 801 for (size_t i = 0; i < indices.size(); ++i) | 820 for (size_t i = 0; i < indices.size(); ++i) |
| 802 tabs.push_back(GetContentsAt(indices[i])); | 821 tabs.push_back(GetContentsAt(indices[i])); |
| 803 | 822 |
| 804 // We only try the fast shutdown path if the whole browser process is *not* | 823 // We only try the fast shutdown path if the whole browser process is *not* |
| 805 // shutting down. Fast shutdown during browser termination is handled in | 824 // shutting down. Fast shutdown during browser termination is handled in |
| 806 // BrowserShutdown. | 825 // BrowserShutdown. |
| 807 if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) { | 826 if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) { |
| 808 // Construct a map of processes to the number of associated tabs that are | 827 // Construct a map of processes to the number of associated tabs that are |
| 809 // closing. | 828 // closing. |
| 810 std::map<RenderProcessHost*, size_t> processes; | 829 std::map<RenderProcessHost*, size_t> processes; |
| 811 for (size_t i = 0; i < indices.size(); ++i) { | 830 for (size_t i = 0; i < indices.size(); ++i) { |
| 812 if (!delegate_->CanCloseContentsAt(indices[i])) { | 831 if (!delegate_->CanCloseContentsAt(indices[i])) { |
| 813 retval = false; | 832 retval = false; |
| 814 continue; | 833 continue; |
| 815 } | 834 } |
| 816 | 835 |
| 817 TabContents* detached_contents = GetContentsAt(indices[i]); | 836 TabContentsWrapper* detached_contents = GetContentsAt(indices[i]); |
| 818 RenderProcessHost* process = detached_contents->GetRenderProcessHost(); | 837 RenderProcessHost* process = |
| 838 detached_contents->tab_contents()->GetRenderProcessHost(); |
| 819 std::map<RenderProcessHost*, size_t>::iterator iter = | 839 std::map<RenderProcessHost*, size_t>::iterator iter = |
| 820 processes.find(process); | 840 processes.find(process); |
| 821 if (iter == processes.end()) { | 841 if (iter == processes.end()) { |
| 822 processes[process] = 1; | 842 processes[process] = 1; |
| 823 } else { | 843 } else { |
| 824 iter->second++; | 844 iter->second++; |
| 825 } | 845 } |
| 826 } | 846 } |
| 827 | 847 |
| 828 // Try to fast shutdown the tabs that can close. | 848 // Try to fast shutdown the tabs that can close. |
| 829 for (std::map<RenderProcessHost*, size_t>::iterator iter = | 849 for (std::map<RenderProcessHost*, size_t>::iterator iter = |
| 830 processes.begin(); | 850 processes.begin(); |
| 831 iter != processes.end(); ++iter) { | 851 iter != processes.end(); ++iter) { |
| 832 iter->first->FastShutdownForPageCount(iter->second); | 852 iter->first->FastShutdownForPageCount(iter->second); |
| 833 } | 853 } |
| 834 } | 854 } |
| 835 | 855 |
| 836 // We now return to our regularly scheduled shutdown procedure. | 856 // We now return to our regularly scheduled shutdown procedure. |
| 837 for (size_t i = 0; i < tabs.size(); ++i) { | 857 for (size_t i = 0; i < tabs.size(); ++i) { |
| 838 TabContents* detached_contents = tabs[i]; | 858 TabContentsWrapper* detached_contents = tabs[i]; |
| 839 int index = GetIndexOfTabContents(detached_contents); | 859 int index = GetIndexOfTabContents(detached_contents); |
| 840 // Make sure we still contain the tab. | 860 // Make sure we still contain the tab. |
| 841 if (index == kNoTab) | 861 if (index == kNoTab) |
| 842 continue; | 862 continue; |
| 843 | 863 |
| 844 detached_contents->OnCloseStarted(); | 864 detached_contents->tab_contents()->OnCloseStarted(); |
| 845 | 865 |
| 846 if (!delegate_->CanCloseContentsAt(index)) { | 866 if (!delegate_->CanCloseContentsAt(index)) { |
| 847 retval = false; | 867 retval = false; |
| 848 continue; | 868 continue; |
| 849 } | 869 } |
| 850 | 870 |
| 851 // Update the explicitly closed state. If the unload handlers cancel the | 871 // Update the explicitly closed state. If the unload handlers cancel the |
| 852 // close the state is reset in Browser. We don't update the explicitly | 872 // close the state is reset in Browser. We don't update the explicitly |
| 853 // closed state if already marked as explicitly closed as unload handlers | 873 // closed state if already marked as explicitly closed as unload handlers |
| 854 // call back to this if the close is allowed. | 874 // call back to this if the close is allowed. |
| 855 if (!detached_contents->closed_by_user_gesture()) { | 875 if (!detached_contents->tab_contents()->closed_by_user_gesture()) { |
| 856 detached_contents->set_closed_by_user_gesture( | 876 detached_contents->tab_contents()->set_closed_by_user_gesture( |
| 857 close_types & CLOSE_USER_GESTURE); | 877 close_types & CLOSE_USER_GESTURE); |
| 858 } | 878 } |
| 859 | 879 |
| 860 if (delegate_->RunUnloadListenerBeforeClosing(detached_contents)) { | 880 if (delegate_->RunUnloadListenerBeforeClosing(detached_contents)) { |
| 861 retval = false; | 881 retval = false; |
| 862 continue; | 882 continue; |
| 863 } | 883 } |
| 864 | 884 |
| 865 InternalCloseTab(detached_contents, index, | 885 InternalCloseTab(detached_contents, index, |
| 866 (close_types & CLOSE_CREATE_HISTORICAL_TAB) != 0); | 886 (close_types & CLOSE_CREATE_HISTORICAL_TAB) != 0); |
| 867 } | 887 } |
| 868 | 888 |
| 869 return retval; | 889 return retval; |
| 870 } | 890 } |
| 871 | 891 |
| 872 void TabStripModel::InternalCloseTab(TabContents* contents, | 892 void TabStripModel::InternalCloseTab(TabContentsWrapper* contents, |
| 873 int index, | 893 int index, |
| 874 bool create_historical_tabs) { | 894 bool create_historical_tabs) { |
| 875 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 895 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 876 TabClosingAt(this, contents, index)); | 896 TabClosingAt(this, contents, index)); |
| 877 | 897 |
| 878 // Ask the delegate to save an entry for this tab in the historical tab | 898 // Ask the delegate to save an entry for this tab in the historical tab |
| 879 // database if applicable. | 899 // database if applicable. |
| 880 if (create_historical_tabs) | 900 if (create_historical_tabs) |
| 881 delegate_->CreateHistoricalTab(contents); | 901 delegate_->CreateHistoricalTab(contents); |
| 882 | 902 |
| 883 // Deleting the TabContents will call back to us via NotificationObserver | 903 // Deleting the TabContents will call back to us via NotificationObserver |
| 884 // and detach it. | 904 // and detach it. |
| 885 delete contents; | 905 delete contents; |
| 886 } | 906 } |
| 887 | 907 |
| 888 TabContents* TabStripModel::GetContentsAt(int index) const { | 908 TabContentsWrapper* TabStripModel::GetContentsAt(int index) const { |
| 889 CHECK(ContainsIndex(index)) << | 909 CHECK(ContainsIndex(index)) << |
| 890 "Failed to find: " << index << " in: " << count() << " entries."; | 910 "Failed to find: " << index << " in: " << count() << " entries."; |
| 891 return contents_data_.at(index)->contents; | 911 return contents_data_.at(index)->contents; |
| 892 } | 912 } |
| 893 | 913 |
| 894 void TabStripModel::ChangeSelectedContentsFrom( | 914 void TabStripModel::ChangeSelectedContentsFrom( |
| 895 TabContents* old_contents, int to_index, bool user_gesture) { | 915 TabContentsWrapper* old_contents, int to_index, bool user_gesture) { |
| 896 TabContents* new_contents = GetContentsAt(to_index); | 916 TabContentsWrapper* new_contents = GetContentsAt(to_index); |
| 897 if (old_contents == new_contents) | 917 if (old_contents == new_contents) |
| 898 return; | 918 return; |
| 899 | 919 |
| 900 TabContents* last_selected_contents = old_contents; | 920 TabContentsWrapper* last_selected_contents = old_contents; |
| 901 if (last_selected_contents) { | 921 if (last_selected_contents) { |
| 902 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 922 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 903 TabDeselectedAt(last_selected_contents, selected_index_)); | 923 TabDeselectedAt(last_selected_contents, selected_index_)); |
| 904 } | 924 } |
| 905 | 925 |
| 906 selected_index_ = to_index; | 926 selected_index_ = to_index; |
| 927 ObserverListBase<TabStripModelObserver>::Iterator it(observers_); |
| 928 TabStripModelObserver* obs; |
| 929 while ((obs = it.GetNext()) != NULL) |
| 930 obs->TabSelectedAt(last_selected_contents, new_contents, selected_index_, us
er_gesture); |
| 931 /* |
| 907 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 932 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 908 TabSelectedAt(last_selected_contents, new_contents, selected_index_, | 933 TabSelectedAt(last_selected_contents, new_contents, selected_index_, |
| 909 user_gesture)); | 934 user_gesture)); |
| 935 */ |
| 910 } | 936 } |
| 911 | 937 |
| 912 void TabStripModel::SelectRelativeTab(bool next) { | 938 void TabStripModel::SelectRelativeTab(bool next) { |
| 913 // This may happen during automated testing or if a user somehow buffers | 939 // This may happen during automated testing or if a user somehow buffers |
| 914 // many key accelerators. | 940 // many key accelerators. |
| 915 if (contents_data_.empty()) | 941 if (contents_data_.empty()) |
| 916 return; | 942 return; |
| 917 | 943 |
| 918 int index = selected_index_; | 944 int index = selected_index_; |
| 919 int delta = next ? 1 : -1; | 945 int delta = next ? 1 : -1; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 939 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 965 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 940 TabMoved(moved_data->contents, index, to_position)); | 966 TabMoved(moved_data->contents, index, to_position)); |
| 941 } | 967 } |
| 942 | 968 |
| 943 // static | 969 // static |
| 944 bool TabStripModel::OpenerMatches(const TabContentsData* data, | 970 bool TabStripModel::OpenerMatches(const TabContentsData* data, |
| 945 const NavigationController* opener, | 971 const NavigationController* opener, |
| 946 bool use_group) { | 972 bool use_group) { |
| 947 return data->opener == opener || (use_group && data->group == opener); | 973 return data->opener == opener || (use_group && data->group == opener); |
| 948 } | 974 } |
| OLD | NEW |