| OLD | NEW |
| 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 | 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/ui/tab_contents/tab_contents_wrapper.h" | 22 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 23 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" | 23 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" |
| 24 #include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h" | 24 #include "chrome/browser/ui/tabs/tab_strip_model_order_controller.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/public/browser/navigation_controller.h" | 28 #include "content/public/browser/navigation_controller.h" |
| 29 #include "content/public/browser/navigation_entry.h" | 29 #include "content/public/browser/navigation_entry.h" |
| 30 #include "content/public/browser/notification_service.h" | 30 #include "content/public/browser/notification_service.h" |
| 31 #include "content/public/browser/render_process_host.h" | 31 #include "content/public/browser/render_process_host.h" |
| 32 #include "content/public/browser/user_metrics.h" | 32 #include "content/public/browser/user_metrics.h" |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 } | 105 } |
| 106 | 106 |
| 107 bool TabStripModel::HasObserver(TabStripModelObserver* observer) { | 107 bool TabStripModel::HasObserver(TabStripModelObserver* observer) { |
| 108 return observers_.HasObserver(observer); | 108 return observers_.HasObserver(observer); |
| 109 } | 109 } |
| 110 | 110 |
| 111 bool TabStripModel::ContainsIndex(int index) const { | 111 bool TabStripModel::ContainsIndex(int index) const { |
| 112 return index >= 0 && index < count(); | 112 return index >= 0 && index < count(); |
| 113 } | 113 } |
| 114 | 114 |
| 115 void TabStripModel::AppendTabContents(TabContentsWrapper* contents, | 115 void TabStripModel::AppendTabContents(TabContents* contents, |
| 116 bool foreground) { | 116 bool foreground) { |
| 117 int index = order_controller_->DetermineInsertionIndexForAppending(); | 117 int index = order_controller_->DetermineInsertionIndexForAppending(); |
| 118 InsertTabContentsAt(index, contents, | 118 InsertTabContentsAt(index, contents, |
| 119 foreground ? (ADD_INHERIT_GROUP | ADD_ACTIVE) : | 119 foreground ? (ADD_INHERIT_GROUP | ADD_ACTIVE) : |
| 120 ADD_NONE); | 120 ADD_NONE); |
| 121 } | 121 } |
| 122 | 122 |
| 123 void TabStripModel::InsertTabContentsAt(int index, | 123 void TabStripModel::InsertTabContentsAt(int index, |
| 124 TabContentsWrapper* contents, | 124 TabContents* contents, |
| 125 int add_types) { | 125 int add_types) { |
| 126 bool active = add_types & ADD_ACTIVE; | 126 bool active = add_types & ADD_ACTIVE; |
| 127 // Force app tabs to be pinned. | 127 // Force app tabs to be pinned. |
| 128 bool pin = | 128 bool pin = |
| 129 contents->extension_tab_helper()->is_app() || add_types & ADD_PINNED; | 129 contents->extension_tab_helper()->is_app() || add_types & ADD_PINNED; |
| 130 index = ConstrainInsertionIndex(index, pin); | 130 index = ConstrainInsertionIndex(index, pin); |
| 131 | 131 |
| 132 // In tab dragging situations, if the last tab in the window was detached | 132 // In tab dragging situations, if the last tab in the window was detached |
| 133 // then the user aborted the drag, we will have the |closing_all_| member | 133 // then the user aborted the drag, we will have the |closing_all_| member |
| 134 // set (see DetachTabContentsAt) which will mess with our mojo here. We need | 134 // set (see DetachTabContentsAt) which will mess with our mojo here. We need |
| 135 // to clear this bit. | 135 // to clear this bit. |
| 136 closing_all_ = false; | 136 closing_all_ = false; |
| 137 | 137 |
| 138 // Have to get the active contents before we monkey with |contents_| | 138 // Have to get the active contents before we monkey with |contents_| |
| 139 // otherwise we run into problems when we try to change the active contents | 139 // otherwise we run into problems when we try to change the active contents |
| 140 // since the old contents and the new contents will be the same... | 140 // since the old contents and the new contents will be the same... |
| 141 TabContentsWrapper* selected_contents = GetActiveTabContents(); | 141 TabContents* selected_contents = GetActiveTabContents(); |
| 142 TabContentsData* data = new TabContentsData(contents); | 142 TabContentsData* data = new TabContentsData(contents); |
| 143 data->pinned = pin; | 143 data->pinned = pin; |
| 144 if ((add_types & ADD_INHERIT_GROUP) && selected_contents) { | 144 if ((add_types & ADD_INHERIT_GROUP) && selected_contents) { |
| 145 if (active) { | 145 if (active) { |
| 146 // Forget any existing relationships, we don't want to make things too | 146 // Forget any existing relationships, we don't want to make things too |
| 147 // confusing by having multiple groups active at the same time. | 147 // confusing by having multiple groups active at the same time. |
| 148 ForgetAllOpeners(); | 148 ForgetAllOpeners(); |
| 149 } | 149 } |
| 150 // Anything opened by a link we deem to have an opener. | 150 // Anything opened by a link we deem to have an opener. |
| 151 data->SetGroup(&selected_contents->web_contents()->GetController()); | 151 data->SetGroup(&selected_contents->web_contents()->GetController()); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 165 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 165 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 166 TabInsertedAt(contents, index, active)); | 166 TabInsertedAt(contents, index, active)); |
| 167 if (active) { | 167 if (active) { |
| 168 TabStripSelectionModel new_model; | 168 TabStripSelectionModel new_model; |
| 169 new_model.Copy(selection_model_); | 169 new_model.Copy(selection_model_); |
| 170 new_model.SetSelectedIndex(index); | 170 new_model.SetSelectedIndex(index); |
| 171 SetSelection(new_model, NOTIFY_DEFAULT); | 171 SetSelection(new_model, NOTIFY_DEFAULT); |
| 172 } | 172 } |
| 173 } | 173 } |
| 174 | 174 |
| 175 TabContentsWrapper* TabStripModel::ReplaceTabContentsAt( | 175 TabContents* TabStripModel::ReplaceTabContentsAt(int index, |
| 176 int index, | 176 TabContents* new_contents) { |
| 177 TabContentsWrapper* new_contents) { | |
| 178 DCHECK(ContainsIndex(index)); | 177 DCHECK(ContainsIndex(index)); |
| 179 TabContentsWrapper* old_contents = GetContentsAt(index); | 178 TabContents* old_contents = GetContentsAt(index); |
| 180 | 179 |
| 181 ForgetOpenersAndGroupsReferencing( | 180 ForgetOpenersAndGroupsReferencing( |
| 182 &(old_contents->web_contents()->GetController())); | 181 &(old_contents->web_contents()->GetController())); |
| 183 | 182 |
| 184 contents_data_[index]->contents = new_contents; | 183 contents_data_[index]->contents = new_contents; |
| 185 | 184 |
| 186 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 185 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 187 TabReplacedAt(this, old_contents, new_contents, index)); | 186 TabReplacedAt(this, old_contents, new_contents, index)); |
| 188 | 187 |
| 189 // When the active tab contents is replaced send out selected notification | 188 // When the active tab contents is replaced send out selected notification |
| 190 // 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 |
| 191 // selected contents as selection changing. | 190 // selected contents as selection changing. |
| 192 if (active_index() == index) { | 191 if (active_index() == index) { |
| 193 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 192 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 194 ActiveTabChanged(old_contents, new_contents, | 193 ActiveTabChanged(old_contents, new_contents, |
| 195 active_index(), false)); | 194 active_index(), false)); |
| 196 } | 195 } |
| 197 return old_contents; | 196 return old_contents; |
| 198 } | 197 } |
| 199 | 198 |
| 200 void TabStripModel::ReplaceNavigationControllerAt( | 199 void TabStripModel::ReplaceNavigationControllerAt( |
| 201 int index, TabContentsWrapper* contents) { | 200 int index, TabContents* contents) { |
| 202 // This appears to be OK with no flicker since no redraw event | 201 // This appears to be OK with no flicker since no redraw event |
| 203 // occurs between the call to add an additional tab and one to close | 202 // occurs between the call to add an additional tab and one to close |
| 204 // the previous tab. | 203 // the previous tab. |
| 205 InsertTabContentsAt(index + 1, contents, ADD_ACTIVE | ADD_INHERIT_GROUP); | 204 InsertTabContentsAt(index + 1, contents, ADD_ACTIVE | ADD_INHERIT_GROUP); |
| 206 std::vector<int> closing_tabs; | 205 std::vector<int> closing_tabs; |
| 207 closing_tabs.push_back(index); | 206 closing_tabs.push_back(index); |
| 208 InternalCloseTabs(closing_tabs, CLOSE_NONE); | 207 InternalCloseTabs(closing_tabs, CLOSE_NONE); |
| 209 } | 208 } |
| 210 | 209 |
| 211 TabContentsWrapper* TabStripModel::DiscardTabContentsAt(int index) { | 210 TabContents* TabStripModel::DiscardTabContentsAt(int index) { |
| 212 DCHECK(ContainsIndex(index)); | 211 DCHECK(ContainsIndex(index)); |
| 213 TabContentsWrapper* null_contents = | 212 TabContents* null_contents = new TabContents( |
| 214 new TabContentsWrapper( | 213 WebContents::Create(profile(), |
| 215 WebContents::Create(profile(), | 214 NULL /* site_instance */, |
| 216 NULL /* site_instance */, | 215 MSG_ROUTING_NONE, |
| 217 MSG_ROUTING_NONE, | 216 NULL /* base_tab_contents */, |
| 218 NULL /* base_tab_contents */, | 217 NULL /* session_storage_namespace */)); |
| 219 NULL /* session_storage_namespace */)); | 218 TabContents* old_contents = GetContentsAt(index); |
| 220 TabContentsWrapper* old_contents = GetContentsAt(index); | |
| 221 // Copy over the state from the navigation controller so we preserve the | 219 // Copy over the state from the navigation controller so we preserve the |
| 222 // back/forward history and continue to display the correct title/favicon. | 220 // back/forward history and continue to display the correct title/favicon. |
| 223 null_contents->web_contents()->GetController().CopyStateFrom( | 221 null_contents->web_contents()->GetController().CopyStateFrom( |
| 224 old_contents->web_contents()->GetController()); | 222 old_contents->web_contents()->GetController()); |
| 225 // Replace the tab we're discarding with the null version. | 223 // Replace the tab we're discarding with the null version. |
| 226 ReplaceTabContentsAt(index, null_contents); | 224 ReplaceTabContentsAt(index, null_contents); |
| 227 // Mark the tab so it will reload when we click. | 225 // Mark the tab so it will reload when we click. |
| 228 contents_data_[index]->discarded = true; | 226 contents_data_[index]->discarded = true; |
| 229 // Discard the old tab's renderer. | 227 // Discard the old tab's renderer. |
| 230 // TODO(jamescook): This breaks script connections with other tabs. | 228 // TODO(jamescook): This breaks script connections with other tabs. |
| 231 // We need to find a different approach that doesn't do that, perhaps based | 229 // We need to find a different approach that doesn't do that, perhaps based |
| 232 // on navigation to swappedout://. | 230 // on navigation to swappedout://. |
| 233 delete old_contents; | 231 delete old_contents; |
| 234 return null_contents; | 232 return null_contents; |
| 235 } | 233 } |
| 236 | 234 |
| 237 TabContentsWrapper* TabStripModel::DetachTabContentsAt(int index) { | 235 TabContents* TabStripModel::DetachTabContentsAt(int index) { |
| 238 if (contents_data_.empty()) | 236 if (contents_data_.empty()) |
| 239 return NULL; | 237 return NULL; |
| 240 | 238 |
| 241 DCHECK(ContainsIndex(index)); | 239 DCHECK(ContainsIndex(index)); |
| 242 | 240 |
| 243 TabContentsWrapper* removed_contents = GetContentsAt(index); | 241 TabContents* removed_contents = GetContentsAt(index); |
| 244 bool was_selected = IsTabSelected(index); | 242 bool was_selected = IsTabSelected(index); |
| 245 int next_selected_index = order_controller_->DetermineNewSelectedIndex(index); | 243 int next_selected_index = order_controller_->DetermineNewSelectedIndex(index); |
| 246 delete contents_data_[index]; | 244 delete contents_data_[index]; |
| 247 contents_data_.erase(contents_data_.begin() + index); | 245 contents_data_.erase(contents_data_.begin() + index); |
| 248 ForgetOpenersAndGroupsReferencing( | 246 ForgetOpenersAndGroupsReferencing( |
| 249 &(removed_contents->web_contents()->GetController())); | 247 &(removed_contents->web_contents()->GetController())); |
| 250 if (empty()) | 248 if (empty()) |
| 251 closing_all_ = true; | 249 closing_all_ = true; |
| 252 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 250 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 253 TabDetachedAt(removed_contents, index)); | 251 TabDetachedAt(removed_contents, index)); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 348 } | 346 } |
| 349 if (selected_mini_count == selected_count) | 347 if (selected_mini_count == selected_count) |
| 350 return; | 348 return; |
| 351 | 349 |
| 352 // Then move the non-pinned tabs. | 350 // Then move the non-pinned tabs. |
| 353 MoveSelectedTabsToImpl(std::max(index, total_mini_count), | 351 MoveSelectedTabsToImpl(std::max(index, total_mini_count), |
| 354 selected_mini_count, | 352 selected_mini_count, |
| 355 selected_count - selected_mini_count); | 353 selected_count - selected_mini_count); |
| 356 } | 354 } |
| 357 | 355 |
| 358 TabContentsWrapper* TabStripModel::GetActiveTabContents() const { | 356 TabContents* TabStripModel::GetActiveTabContents() const { |
| 359 return GetTabContentsAt(active_index()); | 357 return GetTabContentsAt(active_index()); |
| 360 } | 358 } |
| 361 | 359 |
| 362 TabContentsWrapper* TabStripModel::GetTabContentsAt(int index) const { | 360 TabContents* TabStripModel::GetTabContentsAt(int index) const { |
| 363 if (ContainsIndex(index)) | 361 if (ContainsIndex(index)) |
| 364 return GetContentsAt(index); | 362 return GetContentsAt(index); |
| 365 return NULL; | 363 return NULL; |
| 366 } | 364 } |
| 367 | 365 |
| 368 int TabStripModel::GetIndexOfTabContents( | 366 int TabStripModel::GetIndexOfTabContents(const TabContents* contents) const { |
| 369 const TabContentsWrapper* contents) const { | |
| 370 int index = 0; | 367 int index = 0; |
| 371 TabContentsDataVector::const_iterator iter = contents_data_.begin(); | 368 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 372 for (; iter != contents_data_.end(); ++iter, ++index) { | 369 for (; iter != contents_data_.end(); ++iter, ++index) { |
| 373 if ((*iter)->contents == contents) | 370 if ((*iter)->contents == contents) |
| 374 return index; | 371 return index; |
| 375 } | 372 } |
| 376 return kNoTab; | 373 return kNoTab; |
| 377 } | 374 } |
| 378 | 375 |
| 379 int TabStripModel::GetWrapperIndex(const WebContents* contents) const { | 376 int TabStripModel::GetIndexOfWebContents(const WebContents* contents) const { |
| 380 int index = 0; | 377 int index = 0; |
| 381 TabContentsDataVector::const_iterator iter = contents_data_.begin(); | 378 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 382 for (; iter != contents_data_.end(); ++iter, ++index) { | 379 for (; iter != contents_data_.end(); ++iter, ++index) { |
| 383 if ((*iter)->contents->web_contents() == contents) | 380 if ((*iter)->contents->web_contents() == contents) |
| 384 return index; | 381 return index; |
| 385 } | 382 } |
| 386 return kNoTab; | 383 return kNoTab; |
| 387 } | 384 } |
| 388 | 385 |
| 389 int TabStripModel::GetIndexOfController( | 386 int TabStripModel::GetIndexOfController( |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 for (; iter != end; --iter) { | 485 for (; iter != end; --iter) { |
| 489 next = iter - 1; | 486 next = iter - 1; |
| 490 if (next == end) | 487 if (next == end) |
| 491 break; | 488 break; |
| 492 if ((*next)->opener == opener) | 489 if ((*next)->opener == opener) |
| 493 return static_cast<int>(next - contents_data_.begin()); | 490 return static_cast<int>(next - contents_data_.begin()); |
| 494 } | 491 } |
| 495 return kNoTab; | 492 return kNoTab; |
| 496 } | 493 } |
| 497 | 494 |
| 498 void TabStripModel::TabNavigating(TabContentsWrapper* contents, | 495 void TabStripModel::TabNavigating(TabContents* contents, |
| 499 content::PageTransition transition) { | 496 content::PageTransition transition) { |
| 500 if (ShouldForgetOpenersForTransition(transition)) { | 497 if (ShouldForgetOpenersForTransition(transition)) { |
| 501 // Don't forget the openers if this tab is a New Tab page opened at the | 498 // Don't forget the openers if this tab is a New Tab page opened at the |
| 502 // end of the TabStrip (e.g. by pressing Ctrl+T). Give the user one | 499 // end of the TabStrip (e.g. by pressing Ctrl+T). Give the user one |
| 503 // navigation of one of these transition types before resetting the | 500 // navigation of one of these transition types before resetting the |
| 504 // opener relationships (this allows for the use case of opening a new | 501 // opener relationships (this allows for the use case of opening a new |
| 505 // tab to do a quick look-up of something while viewing a tab earlier in | 502 // tab to do a quick look-up of something while viewing a tab earlier in |
| 506 // the strip). We can make this heuristic more permissive if need be. | 503 // the strip). We can make this heuristic more permissive if need be. |
| 507 if (!IsNewTabAtEndOfTabStrip(contents)) { | 504 if (!IsNewTabAtEndOfTabStrip(contents)) { |
| 508 // If the user navigates the current tab to another page in any way | 505 // If the user navigates the current tab to another page in any way |
| 509 // other than by clicking a link, we want to pro-actively forget all | 506 // other than by clicking a link, we want to pro-actively forget all |
| 510 // TabStrip opener relationships since we assume they're beginning a | 507 // TabStrip opener relationships since we assume they're beginning a |
| 511 // different task by reusing the current tab. | 508 // different task by reusing the current tab. |
| 512 ForgetAllOpeners(); | 509 ForgetAllOpeners(); |
| 513 // In this specific case we also want to reset the group relationship, | 510 // In this specific case we also want to reset the group relationship, |
| 514 // since it is now technically invalid. | 511 // since it is now technically invalid. |
| 515 ForgetGroup(contents); | 512 ForgetGroup(contents); |
| 516 } | 513 } |
| 517 } | 514 } |
| 518 } | 515 } |
| 519 | 516 |
| 520 void TabStripModel::ForgetAllOpeners() { | 517 void TabStripModel::ForgetAllOpeners() { |
| 521 // Forget all opener memories so we don't do anything weird with tab | 518 // Forget all opener memories so we don't do anything weird with tab |
| 522 // re-selection ordering. | 519 // re-selection ordering. |
| 523 TabContentsDataVector::const_iterator iter = contents_data_.begin(); | 520 TabContentsDataVector::const_iterator iter = contents_data_.begin(); |
| 524 for (; iter != contents_data_.end(); ++iter) | 521 for (; iter != contents_data_.end(); ++iter) |
| 525 (*iter)->ForgetOpener(); | 522 (*iter)->ForgetOpener(); |
| 526 } | 523 } |
| 527 | 524 |
| 528 void TabStripModel::ForgetGroup(TabContentsWrapper* contents) { | 525 void TabStripModel::ForgetGroup(TabContents* contents) { |
| 529 int index = GetIndexOfTabContents(contents); | 526 int index = GetIndexOfTabContents(contents); |
| 530 DCHECK(ContainsIndex(index)); | 527 DCHECK(ContainsIndex(index)); |
| 531 contents_data_[index]->SetGroup(NULL); | 528 contents_data_[index]->SetGroup(NULL); |
| 532 contents_data_[index]->ForgetOpener(); | 529 contents_data_[index]->ForgetOpener(); |
| 533 } | 530 } |
| 534 | 531 |
| 535 bool TabStripModel::ShouldResetGroupOnSelect( | 532 bool TabStripModel::ShouldResetGroupOnSelect(TabContents* contents) const { |
| 536 TabContentsWrapper* contents) const { | |
| 537 int index = GetIndexOfTabContents(contents); | 533 int index = GetIndexOfTabContents(contents); |
| 538 DCHECK(ContainsIndex(index)); | 534 DCHECK(ContainsIndex(index)); |
| 539 return contents_data_[index]->reset_group_on_select; | 535 return contents_data_[index]->reset_group_on_select; |
| 540 } | 536 } |
| 541 | 537 |
| 542 void TabStripModel::SetTabBlocked(int index, bool blocked) { | 538 void TabStripModel::SetTabBlocked(int index, bool blocked) { |
| 543 DCHECK(ContainsIndex(index)); | 539 DCHECK(ContainsIndex(index)); |
| 544 if (contents_data_[index]->blocked == blocked) | 540 if (contents_data_[index]->blocked == blocked) |
| 545 return; | 541 return; |
| 546 contents_data_[index]->blocked = blocked; | 542 contents_data_[index]->blocked = blocked; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 bool TabStripModel::IsTabPinned(int index) const { | 587 bool TabStripModel::IsTabPinned(int index) const { |
| 592 DCHECK(ContainsIndex(index)); | 588 DCHECK(ContainsIndex(index)); |
| 593 return contents_data_[index]->pinned; | 589 return contents_data_[index]->pinned; |
| 594 } | 590 } |
| 595 | 591 |
| 596 bool TabStripModel::IsMiniTab(int index) const { | 592 bool TabStripModel::IsMiniTab(int index) const { |
| 597 return IsTabPinned(index) || IsAppTab(index); | 593 return IsTabPinned(index) || IsAppTab(index); |
| 598 } | 594 } |
| 599 | 595 |
| 600 bool TabStripModel::IsAppTab(int index) const { | 596 bool TabStripModel::IsAppTab(int index) const { |
| 601 TabContentsWrapper* contents = GetTabContentsAt(index); | 597 TabContents* contents = GetTabContentsAt(index); |
| 602 return contents && contents->extension_tab_helper()->is_app(); | 598 return contents && contents->extension_tab_helper()->is_app(); |
| 603 } | 599 } |
| 604 | 600 |
| 605 bool TabStripModel::IsTabBlocked(int index) const { | 601 bool TabStripModel::IsTabBlocked(int index) const { |
| 606 return contents_data_[index]->blocked; | 602 return contents_data_[index]->blocked; |
| 607 } | 603 } |
| 608 | 604 |
| 609 bool TabStripModel::IsTabDiscarded(int index) const { | 605 bool TabStripModel::IsTabDiscarded(int index) const { |
| 610 return contents_data_[index]->discarded; | 606 return contents_data_[index]->discarded; |
| 611 } | 607 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 666 DCHECK(ContainsIndex(index)); | 662 DCHECK(ContainsIndex(index)); |
| 667 return selection_model_.IsSelected(index); | 663 return selection_model_.IsSelected(index); |
| 668 } | 664 } |
| 669 | 665 |
| 670 void TabStripModel::SetSelectionFromModel( | 666 void TabStripModel::SetSelectionFromModel( |
| 671 const TabStripSelectionModel& source) { | 667 const TabStripSelectionModel& source) { |
| 672 DCHECK_NE(TabStripSelectionModel::kUnselectedIndex, source.active()); | 668 DCHECK_NE(TabStripSelectionModel::kUnselectedIndex, source.active()); |
| 673 SetSelection(source, NOTIFY_DEFAULT); | 669 SetSelection(source, NOTIFY_DEFAULT); |
| 674 } | 670 } |
| 675 | 671 |
| 676 void TabStripModel::AddTabContents(TabContentsWrapper* contents, | 672 void TabStripModel::AddTabContents(TabContents* contents, |
| 677 int index, | 673 int index, |
| 678 content::PageTransition transition, | 674 content::PageTransition transition, |
| 679 int add_types) { | 675 int add_types) { |
| 680 // If the newly-opened tab is part of the same task as the parent tab, we want | 676 // If the newly-opened tab is part of the same task as the parent tab, we want |
| 681 // to inherit the parent's "group" attribute, so that if this tab is then | 677 // to inherit the parent's "group" attribute, so that if this tab is then |
| 682 // closed we'll jump back to the parent tab. | 678 // closed we'll jump back to the parent tab. |
| 683 bool inherit_group = (add_types & ADD_INHERIT_GROUP) == ADD_INHERIT_GROUP; | 679 bool inherit_group = (add_types & ADD_INHERIT_GROUP) == ADD_INHERIT_GROUP; |
| 684 | 680 |
| 685 if (transition == content::PAGE_TRANSITION_LINK && | 681 if (transition == content::PAGE_TRANSITION_LINK && |
| 686 (add_types & ADD_FORCE_INDEX) == 0) { | 682 (add_types & ADD_FORCE_INDEX) == 0) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 // TODO(sky): figure out why this is here and not in InsertTabContentsAt. When | 716 // TODO(sky): figure out why this is here and not in InsertTabContentsAt. When |
| 721 // here we seem to get failures in startup perf tests. | 717 // here we seem to get failures in startup perf tests. |
| 722 // Ensure that the new WebContentsView begins at the same size as the | 718 // Ensure that the new WebContentsView begins at the same size as the |
| 723 // previous WebContentsView if it existed. Otherwise, the initial WebKit | 719 // previous WebContentsView if it existed. Otherwise, the initial WebKit |
| 724 // layout will be performed based on a width of 0 pixels, causing a | 720 // layout will be performed based on a width of 0 pixels, causing a |
| 725 // very long, narrow, inaccurate layout. Because some scripts on pages (as | 721 // very long, narrow, inaccurate layout. Because some scripts on pages (as |
| 726 // well as WebKit's anchor link location calculation) are run on the | 722 // well as WebKit's anchor link location calculation) are run on the |
| 727 // initial layout and not recalculated later, we need to ensure the first | 723 // initial layout and not recalculated later, we need to ensure the first |
| 728 // layout is performed with sane view dimensions even when we're opening a | 724 // layout is performed with sane view dimensions even when we're opening a |
| 729 // new background tab. | 725 // new background tab. |
| 730 if (TabContentsWrapper* old_contents = GetActiveTabContents()) { | 726 if (TabContents* old_contents = GetActiveTabContents()) { |
| 731 if ((add_types & ADD_ACTIVE) == 0) { | 727 if ((add_types & ADD_ACTIVE) == 0) { |
| 732 contents->web_contents()->GetView()-> | 728 contents->web_contents()->GetView()-> |
| 733 SizeContents(old_contents->web_contents()-> | 729 SizeContents(old_contents->web_contents()-> |
| 734 GetView()->GetContainerSize()); | 730 GetView()->GetContainerSize()); |
| 735 // We need to hide the contents or else we get and execute paints for | 731 // We need to hide the contents or else we get and execute paints for |
| 736 // background tabs. With enough background tabs they will steal the | 732 // background tabs. With enough background tabs they will steal the |
| 737 // backing store of the visible tab causing flashing. See bug 20831. | 733 // backing store of the visible tab causing flashing. See bug 20831. |
| 738 contents->web_contents()->HideContents(); | 734 contents->web_contents()->HideContents(); |
| 739 } | 735 } |
| 740 } | 736 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 780 switch (command_id) { | 776 switch (command_id) { |
| 781 case CommandNewTab: | 777 case CommandNewTab: |
| 782 return true; | 778 return true; |
| 783 | 779 |
| 784 case CommandCloseTab: | 780 case CommandCloseTab: |
| 785 return delegate_->CanCloseTab(); | 781 return delegate_->CanCloseTab(); |
| 786 | 782 |
| 787 case CommandReload: { | 783 case CommandReload: { |
| 788 std::vector<int> indices = GetIndicesForCommand(context_index); | 784 std::vector<int> indices = GetIndicesForCommand(context_index); |
| 789 for (size_t i = 0; i < indices.size(); ++i) { | 785 for (size_t i = 0; i < indices.size(); ++i) { |
| 790 TabContentsWrapper* tab = GetTabContentsAt(indices[i]); | 786 TabContents* tab = GetTabContentsAt(indices[i]); |
| 791 if (tab && tab->web_contents()->GetDelegate()->CanReloadContents( | 787 if (tab && tab->web_contents()->GetDelegate()->CanReloadContents( |
| 792 tab->web_contents())) { | 788 tab->web_contents())) { |
| 793 return true; | 789 return true; |
| 794 } | 790 } |
| 795 } | 791 } |
| 796 return false; | 792 return false; |
| 797 } | 793 } |
| 798 | 794 |
| 799 case CommandCloseOtherTabs: | 795 case CommandCloseOtherTabs: |
| 800 case CommandCloseTabsToRight: | 796 case CommandCloseTabsToRight: |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 switch (command_id) { | 837 switch (command_id) { |
| 842 case CommandNewTab: | 838 case CommandNewTab: |
| 843 content::RecordAction(UserMetricsAction("TabContextMenu_NewTab")); | 839 content::RecordAction(UserMetricsAction("TabContextMenu_NewTab")); |
| 844 delegate()->AddBlankTabAt(context_index + 1, true); | 840 delegate()->AddBlankTabAt(context_index + 1, true); |
| 845 break; | 841 break; |
| 846 | 842 |
| 847 case CommandReload: { | 843 case CommandReload: { |
| 848 content::RecordAction(UserMetricsAction("TabContextMenu_Reload")); | 844 content::RecordAction(UserMetricsAction("TabContextMenu_Reload")); |
| 849 std::vector<int> indices = GetIndicesForCommand(context_index); | 845 std::vector<int> indices = GetIndicesForCommand(context_index); |
| 850 for (size_t i = 0; i < indices.size(); ++i) { | 846 for (size_t i = 0; i < indices.size(); ++i) { |
| 851 TabContentsWrapper* tab = GetTabContentsAt(indices[i]); | 847 TabContents* tab = GetTabContentsAt(indices[i]); |
| 852 if (tab && tab->web_contents()->GetDelegate()->CanReloadContents( | 848 if (tab && tab->web_contents()->GetDelegate()->CanReloadContents( |
| 853 tab->web_contents())) { | 849 tab->web_contents())) { |
| 854 tab->web_contents()->GetController().Reload(true); | 850 tab->web_contents()->GetController().Reload(true); |
| 855 } | 851 } |
| 856 } | 852 } |
| 857 break; | 853 break; |
| 858 } | 854 } |
| 859 | 855 |
| 860 case CommandDuplicate: { | 856 case CommandDuplicate: { |
| 861 content::RecordAction(UserMetricsAction("TabContextMenu_Duplicate")); | 857 content::RecordAction(UserMetricsAction("TabContextMenu_Duplicate")); |
| 862 std::vector<int> indices = GetIndicesForCommand(context_index); | 858 std::vector<int> indices = GetIndicesForCommand(context_index); |
| 863 // Copy the TabContentsWrapper off as the indices will change as tabs are | 859 // Copy the TabContents off as the indices will change as tabs are |
| 864 // duplicated. | 860 // duplicated. |
| 865 std::vector<TabContentsWrapper*> tabs; | 861 std::vector<TabContents*> tabs; |
| 866 for (size_t i = 0; i < indices.size(); ++i) | 862 for (size_t i = 0; i < indices.size(); ++i) |
| 867 tabs.push_back(GetTabContentsAt(indices[i])); | 863 tabs.push_back(GetTabContentsAt(indices[i])); |
| 868 for (size_t i = 0; i < tabs.size(); ++i) { | 864 for (size_t i = 0; i < tabs.size(); ++i) { |
| 869 int index = GetIndexOfTabContents(tabs[i]); | 865 int index = GetIndexOfTabContents(tabs[i]); |
| 870 if (index != -1 && delegate_->CanDuplicateContentsAt(index)) | 866 if (index != -1 && delegate_->CanDuplicateContentsAt(index)) |
| 871 delegate_->DuplicateContentsAt(index); | 867 delegate_->DuplicateContentsAt(index); |
| 872 } | 868 } |
| 873 break; | 869 break; |
| 874 } | 870 } |
| 875 | 871 |
| 876 case CommandCloseTab: { | 872 case CommandCloseTab: { |
| 877 content::RecordAction(UserMetricsAction("TabContextMenu_CloseTab")); | 873 content::RecordAction(UserMetricsAction("TabContextMenu_CloseTab")); |
| 878 std::vector<int> indices = GetIndicesForCommand(context_index); | 874 std::vector<int> indices = GetIndicesForCommand(context_index); |
| 879 // Copy the TabContentsWrapper off as the indices will change as we remove | 875 // Copy the TabContents off as the indices will change as we remove |
| 880 // things. | 876 // things. |
| 881 std::vector<TabContentsWrapper*> tabs; | 877 std::vector<TabContents*> tabs; |
| 882 for (size_t i = 0; i < indices.size(); ++i) | 878 for (size_t i = 0; i < indices.size(); ++i) |
| 883 tabs.push_back(GetTabContentsAt(indices[i])); | 879 tabs.push_back(GetTabContentsAt(indices[i])); |
| 884 for (size_t i = 0; i < tabs.size() && delegate_->CanCloseTab(); ++i) { | 880 for (size_t i = 0; i < tabs.size() && delegate_->CanCloseTab(); ++i) { |
| 885 int index = GetIndexOfTabContents(tabs[i]); | 881 int index = GetIndexOfTabContents(tabs[i]); |
| 886 if (index != -1) { | 882 if (index != -1) { |
| 887 CloseTabContentsAt(index, | 883 CloseTabContentsAt(index, |
| 888 CLOSE_CREATE_HISTORICAL_TAB | CLOSE_USER_GESTURE); | 884 CLOSE_CREATE_HISTORICAL_TAB | CLOSE_USER_GESTURE); |
| 889 } | 885 } |
| 890 } | 886 } |
| 891 break; | 887 break; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 | 1000 |
| 1005 void TabStripModel::Observe(int type, | 1001 void TabStripModel::Observe(int type, |
| 1006 const content::NotificationSource& source, | 1002 const content::NotificationSource& source, |
| 1007 const content::NotificationDetails& details) { | 1003 const content::NotificationDetails& details) { |
| 1008 switch (type) { | 1004 switch (type) { |
| 1009 case chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED: { | 1005 case chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED: { |
| 1010 // Sometimes, on qemu, it seems like a WebContents object can be destroyed | 1006 // Sometimes, on qemu, it seems like a WebContents object can be destroyed |
| 1011 // while we still have a reference to it. We need to break this reference | 1007 // while we still have a reference to it. We need to break this reference |
| 1012 // here so we don't crash later. | 1008 // here so we don't crash later. |
| 1013 int index = GetIndexOfTabContents( | 1009 int index = GetIndexOfTabContents( |
| 1014 content::Source<TabContentsWrapper>(source).ptr()); | 1010 content::Source<TabContents>(source).ptr()); |
| 1015 if (index != TabStripModel::kNoTab) { | 1011 if (index != TabStripModel::kNoTab) { |
| 1016 // Note that we only detach the contents here, not close it - it's | 1012 // Note that we only detach the contents here, not close it - it's |
| 1017 // already been closed. We just want to undo our bookkeeping. | 1013 // already been closed. We just want to undo our bookkeeping. |
| 1018 DetachTabContentsAt(index); | 1014 DetachTabContentsAt(index); |
| 1019 } | 1015 } |
| 1020 break; | 1016 break; |
| 1021 } | 1017 } |
| 1022 | 1018 |
| 1023 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | 1019 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
| 1024 const extensions::Extension* extension = | 1020 const extensions::Extension* extension = |
| 1025 content::Details<extensions::UnloadedExtensionInfo>( | 1021 content::Details<extensions::UnloadedExtensionInfo>( |
| 1026 details)->extension; | 1022 details)->extension; |
| 1027 // Iterate backwards as we may remove items while iterating. | 1023 // Iterate backwards as we may remove items while iterating. |
| 1028 for (int i = count() - 1; i >= 0; i--) { | 1024 for (int i = count() - 1; i >= 0; i--) { |
| 1029 TabContentsWrapper* contents = GetTabContentsAt(i); | 1025 TabContents* contents = GetTabContentsAt(i); |
| 1030 if (contents->extension_tab_helper()->extension_app() == extension) { | 1026 if (contents->extension_tab_helper()->extension_app() == extension) { |
| 1031 // The extension an app tab was created from has been nuked. Delete | 1027 // The extension an app tab was created from has been nuked. Delete |
| 1032 // the WebContents. Deleting a WebContents results in a notification | 1028 // the WebContents. Deleting a WebContents results in a notification |
| 1033 // of type NOTIFICATION_WEB_CONTENTS_DESTROYED; we do the necessary | 1029 // of type NOTIFICATION_WEB_CONTENTS_DESTROYED; we do the necessary |
| 1034 // cleanup in handling that notification. | 1030 // cleanup in handling that notification. |
| 1035 | 1031 |
| 1036 InternalCloseTab(contents, i, false); | 1032 InternalCloseTab(contents, i, false); |
| 1037 } | 1033 } |
| 1038 } | 1034 } |
| 1039 break; | 1035 break; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1072 } | 1068 } |
| 1073 | 1069 |
| 1074 return true; | 1070 return true; |
| 1075 } | 1071 } |
| 1076 | 1072 |
| 1077 /////////////////////////////////////////////////////////////////////////////// | 1073 /////////////////////////////////////////////////////////////////////////////// |
| 1078 // TabStripModel, private: | 1074 // TabStripModel, private: |
| 1079 | 1075 |
| 1080 void TabStripModel::GetIndicesWithSameDomain(int index, | 1076 void TabStripModel::GetIndicesWithSameDomain(int index, |
| 1081 std::vector<int>* indices) { | 1077 std::vector<int>* indices) { |
| 1082 TabContentsWrapper* tab = GetTabContentsAt(index); | 1078 TabContents* tab = GetTabContentsAt(index); |
| 1083 std::string domain = tab->web_contents()->GetURL().host(); | 1079 std::string domain = tab->web_contents()->GetURL().host(); |
| 1084 if (domain.empty()) | 1080 if (domain.empty()) |
| 1085 return; | 1081 return; |
| 1086 for (int i = 0; i < count(); ++i) { | 1082 for (int i = 0; i < count(); ++i) { |
| 1087 if (i == index) | 1083 if (i == index) |
| 1088 continue; | 1084 continue; |
| 1089 if (GetTabContentsAt(i)->web_contents()->GetURL().host() == domain) | 1085 if (GetTabContentsAt(i)->web_contents()->GetURL().host() == domain) |
| 1090 indices->push_back(i); | 1086 indices->push_back(i); |
| 1091 } | 1087 } |
| 1092 } | 1088 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1112 | 1108 |
| 1113 std::vector<int> TabStripModel::GetIndicesForCommand(int index) const { | 1109 std::vector<int> TabStripModel::GetIndicesForCommand(int index) const { |
| 1114 if (!IsTabSelected(index)) { | 1110 if (!IsTabSelected(index)) { |
| 1115 std::vector<int> indices; | 1111 std::vector<int> indices; |
| 1116 indices.push_back(index); | 1112 indices.push_back(index); |
| 1117 return indices; | 1113 return indices; |
| 1118 } | 1114 } |
| 1119 return selection_model_.selected_indices(); | 1115 return selection_model_.selected_indices(); |
| 1120 } | 1116 } |
| 1121 | 1117 |
| 1122 bool TabStripModel::IsNewTabAtEndOfTabStrip( | 1118 bool TabStripModel::IsNewTabAtEndOfTabStrip(TabContents* contents) const { |
| 1123 TabContentsWrapper* contents) const { | |
| 1124 const GURL& url = contents->web_contents()->GetURL(); | 1119 const GURL& url = contents->web_contents()->GetURL(); |
| 1125 return url.SchemeIs(chrome::kChromeUIScheme) && | 1120 return url.SchemeIs(chrome::kChromeUIScheme) && |
| 1126 url.host() == chrome::kChromeUINewTabHost && | 1121 url.host() == chrome::kChromeUINewTabHost && |
| 1127 contents == GetContentsAt(count() - 1) && | 1122 contents == GetContentsAt(count() - 1) && |
| 1128 contents->web_contents()->GetController().GetEntryCount() == 1; | 1123 contents->web_contents()->GetController().GetEntryCount() == 1; |
| 1129 } | 1124 } |
| 1130 | 1125 |
| 1131 bool TabStripModel::InternalCloseTabs(const std::vector<int>& in_indices, | 1126 bool TabStripModel::InternalCloseTabs(const std::vector<int>& in_indices, |
| 1132 uint32 close_types) { | 1127 uint32 close_types) { |
| 1133 if (in_indices.empty()) | 1128 if (in_indices.empty()) |
| 1134 return true; | 1129 return true; |
| 1135 | 1130 |
| 1136 std::vector<int> indices(in_indices); | 1131 std::vector<int> indices(in_indices); |
| 1137 bool retval = delegate_->CanCloseContents(&indices); | 1132 bool retval = delegate_->CanCloseContents(&indices); |
| 1138 if (indices.empty()) | 1133 if (indices.empty()) |
| 1139 return retval; | 1134 return retval; |
| 1140 | 1135 |
| 1141 // Map the indices to TabContentsWrapper, that way if deleting a tab deletes | 1136 // Map the indices to TabContents, that way if deleting a tab deletes |
| 1142 // other tabs we're ok. Crashes seem to indicate during tab deletion other | 1137 // other tabs we're ok. Crashes seem to indicate during tab deletion other |
| 1143 // tabs are getting removed. | 1138 // tabs are getting removed. |
| 1144 std::vector<TabContentsWrapper*> tabs; | 1139 std::vector<TabContents*> tabs; |
| 1145 for (size_t i = 0; i < indices.size(); ++i) | 1140 for (size_t i = 0; i < indices.size(); ++i) |
| 1146 tabs.push_back(GetContentsAt(indices[i])); | 1141 tabs.push_back(GetContentsAt(indices[i])); |
| 1147 | 1142 |
| 1148 // We only try the fast shutdown path if the whole browser process is *not* | 1143 // We only try the fast shutdown path if the whole browser process is *not* |
| 1149 // shutting down. Fast shutdown during browser termination is handled in | 1144 // shutting down. Fast shutdown during browser termination is handled in |
| 1150 // BrowserShutdown. | 1145 // BrowserShutdown. |
| 1151 if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) { | 1146 if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) { |
| 1152 // Construct a map of processes to the number of associated tabs that are | 1147 // Construct a map of processes to the number of associated tabs that are |
| 1153 // closing. | 1148 // closing. |
| 1154 std::map<content::RenderProcessHost*, size_t> processes; | 1149 std::map<content::RenderProcessHost*, size_t> processes; |
| 1155 for (size_t i = 0; i < indices.size(); ++i) { | 1150 for (size_t i = 0; i < indices.size(); ++i) { |
| 1156 TabContentsWrapper* detached_contents = GetContentsAt(indices[i]); | 1151 TabContents* detached_contents = GetContentsAt(indices[i]); |
| 1157 content::RenderProcessHost* process = | 1152 content::RenderProcessHost* process = |
| 1158 detached_contents->web_contents()->GetRenderProcessHost(); | 1153 detached_contents->web_contents()->GetRenderProcessHost(); |
| 1159 std::map<content::RenderProcessHost*, size_t>::iterator iter = | 1154 std::map<content::RenderProcessHost*, size_t>::iterator iter = |
| 1160 processes.find(process); | 1155 processes.find(process); |
| 1161 if (iter == processes.end()) { | 1156 if (iter == processes.end()) { |
| 1162 processes[process] = 1; | 1157 processes[process] = 1; |
| 1163 } else { | 1158 } else { |
| 1164 iter->second++; | 1159 iter->second++; |
| 1165 } | 1160 } |
| 1166 } | 1161 } |
| 1167 | 1162 |
| 1168 // Try to fast shutdown the tabs that can close. | 1163 // Try to fast shutdown the tabs that can close. |
| 1169 for (std::map<content::RenderProcessHost*, size_t>::iterator iter = | 1164 for (std::map<content::RenderProcessHost*, size_t>::iterator iter = |
| 1170 processes.begin(); | 1165 processes.begin(); |
| 1171 iter != processes.end(); ++iter) { | 1166 iter != processes.end(); ++iter) { |
| 1172 iter->first->FastShutdownForPageCount(iter->second); | 1167 iter->first->FastShutdownForPageCount(iter->second); |
| 1173 } | 1168 } |
| 1174 } | 1169 } |
| 1175 | 1170 |
| 1176 // We now return to our regularly scheduled shutdown procedure. | 1171 // We now return to our regularly scheduled shutdown procedure. |
| 1177 for (size_t i = 0; i < tabs.size(); ++i) { | 1172 for (size_t i = 0; i < tabs.size(); ++i) { |
| 1178 TabContentsWrapper* detached_contents = tabs[i]; | 1173 TabContents* detached_contents = tabs[i]; |
| 1179 int index = GetIndexOfTabContents(detached_contents); | 1174 int index = GetIndexOfTabContents(detached_contents); |
| 1180 // Make sure we still contain the tab. | 1175 // Make sure we still contain the tab. |
| 1181 if (index == kNoTab) | 1176 if (index == kNoTab) |
| 1182 continue; | 1177 continue; |
| 1183 | 1178 |
| 1184 detached_contents->web_contents()->OnCloseStarted(); | 1179 detached_contents->web_contents()->OnCloseStarted(); |
| 1185 | 1180 |
| 1186 // Update the explicitly closed state. If the unload handlers cancel the | 1181 // Update the explicitly closed state. If the unload handlers cancel the |
| 1187 // close the state is reset in Browser. We don't update the explicitly | 1182 // close the state is reset in Browser. We don't update the explicitly |
| 1188 // closed state if already marked as explicitly closed as unload handlers | 1183 // closed state if already marked as explicitly closed as unload handlers |
| 1189 // call back to this if the close is allowed. | 1184 // call back to this if the close is allowed. |
| 1190 if (!detached_contents->web_contents()->GetClosedByUserGesture()) { | 1185 if (!detached_contents->web_contents()->GetClosedByUserGesture()) { |
| 1191 detached_contents->web_contents()->SetClosedByUserGesture( | 1186 detached_contents->web_contents()->SetClosedByUserGesture( |
| 1192 close_types & CLOSE_USER_GESTURE); | 1187 close_types & CLOSE_USER_GESTURE); |
| 1193 } | 1188 } |
| 1194 | 1189 |
| 1195 if (delegate_->RunUnloadListenerBeforeClosing(detached_contents)) { | 1190 if (delegate_->RunUnloadListenerBeforeClosing(detached_contents)) { |
| 1196 retval = false; | 1191 retval = false; |
| 1197 continue; | 1192 continue; |
| 1198 } | 1193 } |
| 1199 | 1194 |
| 1200 InternalCloseTab(detached_contents, index, | 1195 InternalCloseTab(detached_contents, index, |
| 1201 (close_types & CLOSE_CREATE_HISTORICAL_TAB) != 0); | 1196 (close_types & CLOSE_CREATE_HISTORICAL_TAB) != 0); |
| 1202 } | 1197 } |
| 1203 | 1198 |
| 1204 return retval; | 1199 return retval; |
| 1205 } | 1200 } |
| 1206 | 1201 |
| 1207 void TabStripModel::InternalCloseTab(TabContentsWrapper* contents, | 1202 void TabStripModel::InternalCloseTab(TabContents* contents, |
| 1208 int index, | 1203 int index, |
| 1209 bool create_historical_tabs) { | 1204 bool create_historical_tabs) { |
| 1210 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 1205 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 1211 TabClosingAt(this, contents, index)); | 1206 TabClosingAt(this, contents, index)); |
| 1212 | 1207 |
| 1213 // Ask the delegate to save an entry for this tab in the historical tab | 1208 // Ask the delegate to save an entry for this tab in the historical tab |
| 1214 // database if applicable. | 1209 // database if applicable. |
| 1215 if (create_historical_tabs) | 1210 if (create_historical_tabs) |
| 1216 delegate_->CreateHistoricalTab(contents); | 1211 delegate_->CreateHistoricalTab(contents); |
| 1217 | 1212 |
| 1218 // Deleting the TabContentsWrapper will call back to us via | 1213 // Deleting the TabContents will call back to us via |
| 1219 // NotificationObserver and detach it. | 1214 // NotificationObserver and detach it. |
| 1220 delete contents; | 1215 delete contents; |
| 1221 } | 1216 } |
| 1222 | 1217 |
| 1223 TabContentsWrapper* TabStripModel::GetContentsAt(int index) const { | 1218 TabContents* TabStripModel::GetContentsAt(int index) const { |
| 1224 CHECK(ContainsIndex(index)) << | 1219 CHECK(ContainsIndex(index)) << |
| 1225 "Failed to find: " << index << " in: " << count() << " entries."; | 1220 "Failed to find: " << index << " in: " << count() << " entries."; |
| 1226 return contents_data_[index]->contents; | 1221 return contents_data_[index]->contents; |
| 1227 } | 1222 } |
| 1228 | 1223 |
| 1229 void TabStripModel::NotifyIfTabDeactivated(TabContentsWrapper* contents) { | 1224 void TabStripModel::NotifyIfTabDeactivated(TabContents* contents) { |
| 1230 if (contents) { | 1225 if (contents) { |
| 1231 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 1226 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 1232 TabDeactivated(contents)); | 1227 TabDeactivated(contents)); |
| 1233 } | 1228 } |
| 1234 } | 1229 } |
| 1235 | 1230 |
| 1236 void TabStripModel::NotifyIfActiveTabChanged( | 1231 void TabStripModel::NotifyIfActiveTabChanged(TabContents* old_contents, |
| 1237 TabContentsWrapper* old_contents, | 1232 NotifyTypes notify_types) { |
| 1238 NotifyTypes notify_types) { | 1233 TabContents* new_contents = GetContentsAt(active_index()); |
| 1239 TabContentsWrapper* new_contents = GetContentsAt(active_index()); | |
| 1240 if (old_contents != new_contents) { | 1234 if (old_contents != new_contents) { |
| 1241 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 1235 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 1242 ActiveTabChanged(old_contents, new_contents, | 1236 ActiveTabChanged(old_contents, new_contents, |
| 1243 active_index(), | 1237 active_index(), |
| 1244 notify_types == NOTIFY_USER_GESTURE)); | 1238 notify_types == NOTIFY_USER_GESTURE)); |
| 1245 // Activating a discarded tab reloads it, so it is no longer discarded. | 1239 // Activating a discarded tab reloads it, so it is no longer discarded. |
| 1246 contents_data_[active_index()]->discarded = false; | 1240 contents_data_[active_index()]->discarded = false; |
| 1247 } | 1241 } |
| 1248 } | 1242 } |
| 1249 | 1243 |
| 1250 void TabStripModel::NotifyIfActiveOrSelectionChanged( | 1244 void TabStripModel::NotifyIfActiveOrSelectionChanged( |
| 1251 TabContentsWrapper* old_contents, | 1245 TabContents* old_contents, |
| 1252 NotifyTypes notify_types, | 1246 NotifyTypes notify_types, |
| 1253 const TabStripSelectionModel& old_model) { | 1247 const TabStripSelectionModel& old_model) { |
| 1254 NotifyIfActiveTabChanged(old_contents, notify_types); | 1248 NotifyIfActiveTabChanged(old_contents, notify_types); |
| 1255 | 1249 |
| 1256 if (!selection_model().Equals(old_model)) { | 1250 if (!selection_model().Equals(old_model)) { |
| 1257 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, | 1251 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, |
| 1258 TabSelectionChanged(this, old_model)); | 1252 TabSelectionChanged(this, old_model)); |
| 1259 } | 1253 } |
| 1260 } | 1254 } |
| 1261 | 1255 |
| 1262 void TabStripModel::SetSelection( | 1256 void TabStripModel::SetSelection( |
| 1263 const TabStripSelectionModel& new_model, | 1257 const TabStripSelectionModel& new_model, |
| 1264 NotifyTypes notify_types) { | 1258 NotifyTypes notify_types) { |
| 1265 TabContentsWrapper* old_contents = GetActiveTabContents(); | 1259 TabContents* old_contents = GetActiveTabContents(); |
| 1266 TabStripSelectionModel old_model; | 1260 TabStripSelectionModel old_model; |
| 1267 old_model.Copy(selection_model_); | 1261 old_model.Copy(selection_model_); |
| 1268 if (new_model.active() != selection_model_.active()) | 1262 if (new_model.active() != selection_model_.active()) |
| 1269 NotifyIfTabDeactivated(old_contents); | 1263 NotifyIfTabDeactivated(old_contents); |
| 1270 selection_model_.Copy(new_model); | 1264 selection_model_.Copy(new_model); |
| 1271 NotifyIfActiveOrSelectionChanged(old_contents, notify_types, old_model); | 1265 NotifyIfActiveOrSelectionChanged(old_contents, notify_types, old_model); |
| 1272 } | 1266 } |
| 1273 | 1267 |
| 1274 void TabStripModel::SelectRelativeTab(bool next) { | 1268 void TabStripModel::SelectRelativeTab(bool next) { |
| 1275 // This may happen during automated testing or if a user somehow buffers | 1269 // This may happen during automated testing or if a user somehow buffers |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 void TabStripModel::ForgetOpenersAndGroupsReferencing( | 1340 void TabStripModel::ForgetOpenersAndGroupsReferencing( |
| 1347 const NavigationController* tab) { | 1341 const NavigationController* tab) { |
| 1348 for (TabContentsDataVector::const_iterator i = contents_data_.begin(); | 1342 for (TabContentsDataVector::const_iterator i = contents_data_.begin(); |
| 1349 i != contents_data_.end(); ++i) { | 1343 i != contents_data_.end(); ++i) { |
| 1350 if ((*i)->group == tab) | 1344 if ((*i)->group == tab) |
| 1351 (*i)->group = NULL; | 1345 (*i)->group = NULL; |
| 1352 if ((*i)->opener == tab) | 1346 if ((*i)->opener == tab) |
| 1353 (*i)->opener = NULL; | 1347 (*i)->opener = NULL; |
| 1354 } | 1348 } |
| 1355 } | 1349 } |
| OLD | NEW |