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

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

Issue 2844017: Fix pinned tab link navigations. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: back to dchecks Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/common/renderer_preferences.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/renderer_host/render_view_host.h"
20 #include "chrome/browser/sessions/tab_restore_service.h" 21 #include "chrome/browser/sessions/tab_restore_service.h"
21 #include "chrome/browser/tabs/tab_strip_model_order_controller.h" 22 #include "chrome/browser/tabs/tab_strip_model_order_controller.h"
22 #include "chrome/browser/tab_contents/navigation_controller.h" 23 #include "chrome/browser/tab_contents/navigation_controller.h"
23 #include "chrome/browser/tab_contents/tab_contents.h" 24 #include "chrome/browser/tab_contents/tab_contents.h"
24 #include "chrome/browser/tab_contents/tab_contents_delegate.h" 25 #include "chrome/browser/tab_contents/tab_contents_delegate.h"
25 #include "chrome/browser/tab_contents/tab_contents_view.h" 26 #include "chrome/browser/tab_contents/tab_contents_view.h"
26 #include "chrome/common/chrome_switches.h" 27 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/extensions/extension.h" 28 #include "chrome/common/extensions/extension.h"
28 #include "chrome/common/notification_service.h" 29 #include "chrome/common/notification_service.h"
29 #include "chrome/common/url_constants.h" 30 #include "chrome/common/url_constants.h"
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 } 168 }
168 169
169 TabContents* TabStripModel::DetachTabContentsAt(int index) { 170 TabContents* TabStripModel::DetachTabContentsAt(int index) {
170 if (contents_data_.empty()) 171 if (contents_data_.empty())
171 return NULL; 172 return NULL;
172 173
173 DCHECK(ContainsIndex(index)); 174 DCHECK(ContainsIndex(index));
174 TabContents* removed_contents = GetContentsAt(index); 175 TabContents* removed_contents = GetContentsAt(index);
175 int next_selected_index = 176 int next_selected_index =
176 order_controller_->DetermineNewSelectedIndex(index, true); 177 order_controller_->DetermineNewSelectedIndex(index, true);
177 delete contents_data_.at(index); 178 delete contents_data_[index];
178 contents_data_.erase(contents_data_.begin() + index); 179 contents_data_.erase(contents_data_.begin() + index);
179 next_selected_index = IndexOfNextNonPhantomTab(next_selected_index, -1); 180 next_selected_index = IndexOfNextNonPhantomTab(next_selected_index, -1);
180 if (!HasNonPhantomTabs()) 181 if (!HasNonPhantomTabs())
181 closing_all_ = true; 182 closing_all_ = true;
182 TabStripModelObservers::Iterator iter(observers_); 183 TabStripModelObservers::Iterator iter(observers_);
183 while (TabStripModelObserver* obs = iter.GetNext()) { 184 while (TabStripModelObserver* obs = iter.GetNext()) {
184 obs->TabDetachedAt(removed_contents, index); 185 obs->TabDetachedAt(removed_contents, index);
185 if (!HasNonPhantomTabs()) 186 if (!HasNonPhantomTabs())
186 obs->TabStripEmpty(); 187 obs->TabStripEmpty();
187 } 188 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 TabContentsDataVector::const_iterator iter = contents_data_.begin(); 280 TabContentsDataVector::const_iterator iter = contents_data_.begin();
280 for (; iter != contents_data_.end(); ++iter) { 281 for (; iter != contents_data_.end(); ++iter) {
281 if ((*iter)->contents->is_loading()) 282 if ((*iter)->contents->is_loading())
282 return true; 283 return true;
283 } 284 }
284 return false; 285 return false;
285 } 286 }
286 287
287 NavigationController* TabStripModel::GetOpenerOfTabContentsAt(int index) { 288 NavigationController* TabStripModel::GetOpenerOfTabContentsAt(int index) {
288 DCHECK(ContainsIndex(index)); 289 DCHECK(ContainsIndex(index));
289 return contents_data_.at(index)->opener; 290 return contents_data_[index]->opener;
290 } 291 }
291 292
292 int TabStripModel::GetIndexOfNextTabContentsOpenedBy( 293 int TabStripModel::GetIndexOfNextTabContentsOpenedBy(
293 const NavigationController* opener, int start_index, bool use_group) const { 294 const NavigationController* opener, int start_index, bool use_group) const {
294 DCHECK(opener); 295 DCHECK(opener);
295 DCHECK(ContainsIndex(start_index)); 296 DCHECK(ContainsIndex(start_index));
296 297
297 // Check tabs after start_index first. 298 // Check tabs after start_index first.
298 for (int i = start_index + 1; i < count(); ++i) { 299 for (int i = start_index + 1; i < count(); ++i) {
299 if (OpenerMatches(contents_data_[i], opener, use_group) && 300 if (OpenerMatches(contents_data_[i], opener, use_group) &&
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 // Forget all opener memories so we don't do anything weird with tab 372 // Forget all opener memories so we don't do anything weird with tab
372 // re-selection ordering. 373 // re-selection ordering.
373 TabContentsDataVector::const_iterator iter = contents_data_.begin(); 374 TabContentsDataVector::const_iterator iter = contents_data_.begin();
374 for (; iter != contents_data_.end(); ++iter) 375 for (; iter != contents_data_.end(); ++iter)
375 (*iter)->ForgetOpener(); 376 (*iter)->ForgetOpener();
376 } 377 }
377 378
378 void TabStripModel::ForgetGroup(TabContents* contents) { 379 void TabStripModel::ForgetGroup(TabContents* contents) {
379 int index = GetIndexOfTabContents(contents); 380 int index = GetIndexOfTabContents(contents);
380 DCHECK(ContainsIndex(index)); 381 DCHECK(ContainsIndex(index));
381 contents_data_.at(index)->SetGroup(NULL); 382 contents_data_[index]->SetGroup(NULL);
382 contents_data_.at(index)->ForgetOpener(); 383 contents_data_[index]->ForgetOpener();
383 } 384 }
384 385
385 bool TabStripModel::ShouldResetGroupOnSelect(TabContents* contents) const { 386 bool TabStripModel::ShouldResetGroupOnSelect(TabContents* contents) const {
386 int index = GetIndexOfTabContents(contents); 387 int index = GetIndexOfTabContents(contents);
387 DCHECK(ContainsIndex(index)); 388 DCHECK(ContainsIndex(index));
388 return contents_data_.at(index)->reset_group_on_select; 389 return contents_data_[index]->reset_group_on_select;
389 } 390 }
390 391
391 void TabStripModel::SetTabBlocked(int index, bool blocked) { 392 void TabStripModel::SetTabBlocked(int index, bool blocked) {
392 DCHECK(ContainsIndex(index)); 393 DCHECK(ContainsIndex(index));
393 if (contents_data_[index]->blocked == blocked) 394 if (contents_data_[index]->blocked == blocked)
394 return; 395 return;
395 contents_data_[index]->blocked = blocked; 396 contents_data_[index]->blocked = blocked;
396 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 397 FOR_EACH_OBSERVER(TabStripModelObserver, observers_,
397 TabBlockedStateChanged(contents_data_[index]->contents, 398 TabBlockedStateChanged(contents_data_[index]->contents,
398 index)); 399 index));
399 } 400 }
400 401
401 void TabStripModel::SetTabPinned(int index, bool pinned) { 402 void TabStripModel::SetTabPinned(int index, bool pinned) {
402 DCHECK(ContainsIndex(index)); 403 DCHECK(ContainsIndex(index));
403 if (contents_data_[index]->pinned == pinned) 404 if (contents_data_[index]->pinned == pinned)
404 return; 405 return;
405 406
407 // Reroute toplevel requests to the browser if the tab is pinned. This allows
408 // us to rewrite the WindowOpenDisposition in certain cases.
409 TabContents* contents = contents_data_[index]->contents;
410 contents->GetMutableRendererPrefs()->browser_handles_top_level_requests =
411 pinned;
412 if (contents->render_view_host())
413 contents->render_view_host()->SyncRendererPrefs();
414
406 if (IsAppTab(index)) { 415 if (IsAppTab(index)) {
407 // Changing the pinned state of an app tab doesn't effect it's mini-tab 416 // Changing the pinned state of an app tab doesn't effect it's mini-tab
408 // status. 417 // status.
409 contents_data_[index]->pinned = pinned; 418 contents_data_[index]->pinned = pinned;
410 } else { 419 } else {
411 // The tab is not an app tab, it's position may have to change as the 420 // The tab is not an app tab, it's position may have to change as the
412 // mini-tab state is changing. 421 // mini-tab state is changing.
413 int non_mini_tab_index = IndexOfFirstNonMiniTab(); 422 int non_mini_tab_index = IndexOfFirstNonMiniTab();
414 contents_data_[index]->pinned = pinned; 423 contents_data_[index]->pinned = pinned;
415 if (pinned && index != non_mini_tab_index) { 424 if (pinned && index != non_mini_tab_index) {
416 MoveTabContentsAtImpl(index, non_mini_tab_index, false); 425 MoveTabContentsAtImpl(index, non_mini_tab_index, false);
417 return; // Don't send TabPinnedStateChanged notification. 426 return; // Don't send TabPinnedStateChanged notification.
418 } else if (!pinned && index + 1 != non_mini_tab_index) { 427 } else if (!pinned && index + 1 != non_mini_tab_index) {
419 MoveTabContentsAtImpl(index, non_mini_tab_index - 1, false); 428 MoveTabContentsAtImpl(index, non_mini_tab_index - 1, false);
420 return; // Don't send TabPinnedStateChanged notification. 429 return; // Don't send TabPinnedStateChanged notification.
421 } 430 }
422 431
423 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 432 FOR_EACH_OBSERVER(TabStripModelObserver, observers_,
424 TabMiniStateChanged(contents_data_[index]->contents, 433 TabMiniStateChanged(contents, index));
425 index));
426 } 434 }
427 435
428 // else: the tab was at the boundary and it's position doesn't need to 436 // else: the tab was at the boundary and it's position doesn't need to
429 // change. 437 // change.
430 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 438 FOR_EACH_OBSERVER(TabStripModelObserver, observers_,
431 TabPinnedStateChanged(contents_data_[index]->contents, 439 TabPinnedStateChanged(contents, index));
432 index));
433 } 440 }
434 441
435 bool TabStripModel::IsTabPinned(int index) const { 442 bool TabStripModel::IsTabPinned(int index) const {
436 return contents_data_[index]->pinned; 443 return contents_data_[index]->pinned;
437 } 444 }
438 445
439 bool TabStripModel::IsMiniTab(int index) const { 446 bool TabStripModel::IsMiniTab(int index) const {
440 return IsTabPinned(index) || IsAppTab(index); 447 return IsTabPinned(index) || IsAppTab(index);
441 } 448 }
442 449
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 // creates a New Tab (e.g. Ctrl+T, or clicks the New Tab button), or types 518 // creates a New Tab (e.g. Ctrl+T, or clicks the New Tab button), or types
512 // in the address bar and presses Alt+Enter. This allows for opening a new 519 // in the address bar and presses Alt+Enter. This allows for opening a new
513 // Tab to quickly look up something. When this Tab is closed, the old one 520 // Tab to quickly look up something. When this Tab is closed, the old one
514 // is re-selected, not the next-adjacent. 521 // is re-selected, not the next-adjacent.
515 inherit_group = true; 522 inherit_group = true;
516 } 523 }
517 InsertTabContentsAt(index, contents, foreground, inherit_group); 524 InsertTabContentsAt(index, contents, foreground, inherit_group);
518 // Reset the index, just in case insert ended up moving it on us. 525 // Reset the index, just in case insert ended up moving it on us.
519 index = GetIndexOfTabContents(contents); 526 index = GetIndexOfTabContents(contents);
520 if (inherit_group && transition == PageTransition::TYPED) 527 if (inherit_group && transition == PageTransition::TYPED)
521 contents_data_.at(index)->reset_group_on_select = true; 528 contents_data_[index]->reset_group_on_select = true;
522 529
523 // Ensure that the new TabContentsView begins at the same size as the 530 // Ensure that the new TabContentsView begins at the same size as the
524 // previous TabContentsView if it existed. Otherwise, the initial WebKit 531 // previous TabContentsView if it existed. Otherwise, the initial WebKit
525 // layout will be performed based on a width of 0 pixels, causing a 532 // layout will be performed based on a width of 0 pixels, causing a
526 // very long, narrow, inaccurate layout. Because some scripts on pages (as 533 // very long, narrow, inaccurate layout. Because some scripts on pages (as
527 // well as WebKit's anchor link location calculation) are run on the 534 // well as WebKit's anchor link location calculation) are run on the
528 // initial layout and not recalculated later, we need to ensure the first 535 // initial layout and not recalculated later, we need to ensure the first
529 // layout is performed with sane view dimensions even when we're opening a 536 // layout is performed with sane view dimensions even when we're opening a
530 // new background tab. 537 // new background tab.
531 if (TabContents* old_contents = GetSelectedTabContents()) { 538 if (TabContents* old_contents = GetSelectedTabContents()) {
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after
930 delegate_->CreateHistoricalTab(contents); 937 delegate_->CreateHistoricalTab(contents);
931 938
932 // Deleting the TabContents will call back to us via NotificationObserver 939 // Deleting the TabContents will call back to us via NotificationObserver
933 // and detach it. 940 // and detach it.
934 delete contents; 941 delete contents;
935 } 942 }
936 943
937 TabContents* TabStripModel::GetContentsAt(int index) const { 944 TabContents* TabStripModel::GetContentsAt(int index) const {
938 CHECK(ContainsIndex(index)) << 945 CHECK(ContainsIndex(index)) <<
939 "Failed to find: " << index << " in: " << count() << " entries."; 946 "Failed to find: " << index << " in: " << count() << " entries.";
940 return contents_data_.at(index)->contents; 947 return contents_data_[index]->contents;
941 } 948 }
942 949
943 void TabStripModel::ChangeSelectedContentsFrom( 950 void TabStripModel::ChangeSelectedContentsFrom(
944 TabContents* old_contents, int to_index, bool user_gesture) { 951 TabContents* old_contents, int to_index, bool user_gesture) {
945 DCHECK(ContainsIndex(to_index)); 952 DCHECK(ContainsIndex(to_index));
946 TabContents* new_contents = GetContentsAt(to_index); 953 TabContents* new_contents = GetContentsAt(to_index);
947 if (old_contents == new_contents) 954 if (old_contents == new_contents)
948 return; 955 return;
949 956
950 TabContents* last_selected_contents = old_contents; 957 TabContents* last_selected_contents = old_contents;
951 if (last_selected_contents) { 958 if (last_selected_contents) {
952 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 959 FOR_EACH_OBSERVER(TabStripModelObserver, observers_,
953 TabDeselectedAt(last_selected_contents, selected_index_)); 960 TabDeselectedAt(last_selected_contents, selected_index_));
954 } 961 }
955 962
956 selected_index_ = to_index; 963 selected_index_ = to_index;
957 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 964 FOR_EACH_OBSERVER(TabStripModelObserver, observers_,
958 TabSelectedAt(last_selected_contents, new_contents, selected_index_, 965 TabSelectedAt(last_selected_contents, new_contents, selected_index_,
959 user_gesture)); 966 user_gesture));
960 } 967 }
961 968
962 void TabStripModel::SetOpenerForContents(TabContents* contents, 969 void TabStripModel::SetOpenerForContents(TabContents* contents,
963 TabContents* opener) { 970 TabContents* opener) {
964 int index = GetIndexOfTabContents(contents); 971 int index = GetIndexOfTabContents(contents);
965 contents_data_.at(index)->opener = &opener->controller(); 972 contents_data_[index]->opener = &opener->controller();
966 } 973 }
967 974
968 void TabStripModel::SelectRelativeTab(bool next) { 975 void TabStripModel::SelectRelativeTab(bool next) {
969 // This may happen during automated testing or if a user somehow buffers 976 // This may happen during automated testing or if a user somehow buffers
970 // many key accelerators. 977 // many key accelerators.
971 if (contents_data_.empty()) 978 if (contents_data_.empty())
972 return; 979 return;
973 980
974 // Skip pinned-app-phantom tabs when iterating. 981 // Skip pinned-app-phantom tabs when iterating.
975 int index = selected_index_; 982 int index = selected_index_;
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 SelectTabContentsAt(new_selected_index, true); 1050 SelectTabContentsAt(new_selected_index, true);
1044 } 1051 }
1045 1052
1046 if (!HasNonPhantomTabs()) 1053 if (!HasNonPhantomTabs())
1047 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, TabStripEmpty()); 1054 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, TabStripEmpty());
1048 } 1055 }
1049 1056
1050 1057
1051 void TabStripModel::MoveTabContentsAtImpl(int index, int to_position, 1058 void TabStripModel::MoveTabContentsAtImpl(int index, int to_position,
1052 bool select_after_move) { 1059 bool select_after_move) {
1053 TabContentsData* moved_data = contents_data_.at(index); 1060 TabContentsData* moved_data = contents_data_[index];
1054 contents_data_.erase(contents_data_.begin() + index); 1061 contents_data_.erase(contents_data_.begin() + index);
1055 contents_data_.insert(contents_data_.begin() + to_position, moved_data); 1062 contents_data_.insert(contents_data_.begin() + to_position, moved_data);
1056 1063
1057 // if !select_after_move, keep the same tab selected as was selected before. 1064 // if !select_after_move, keep the same tab selected as was selected before.
1058 if (select_after_move || index == selected_index_) { 1065 if (select_after_move || index == selected_index_) {
1059 selected_index_ = to_position; 1066 selected_index_ = to_position;
1060 } else if (index < selected_index_ && to_position >= selected_index_) { 1067 } else if (index < selected_index_ && to_position >= selected_index_) {
1061 selected_index_--; 1068 selected_index_--;
1062 } else if (index > selected_index_ && to_position <= selected_index_) { 1069 } else if (index > selected_index_ && to_position <= selected_index_) {
1063 selected_index_++; 1070 selected_index_++;
1064 } 1071 }
1065 1072
1066 FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 1073 FOR_EACH_OBSERVER(TabStripModelObserver, observers_,
1067 TabMoved(moved_data->contents, index, to_position)); 1074 TabMoved(moved_data->contents, index, to_position));
1068 } 1075 }
1069 1076
1070 // static 1077 // static
1071 bool TabStripModel::OpenerMatches(const TabContentsData* data, 1078 bool TabStripModel::OpenerMatches(const TabContentsData* data,
1072 const NavigationController* opener, 1079 const NavigationController* opener,
1073 bool use_group) { 1080 bool use_group) {
1074 return data->opener == opener || (use_group && data->group == opener); 1081 return data->opener == opener || (use_group && data->group == opener);
1075 } 1082 }
OLDNEW
« no previous file with comments | « no previous file | chrome/common/renderer_preferences.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698