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 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_H_ 6 #define CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_H_ 7 8 #include <vector> 9 10 #include "base/memory/scoped_ptr.h" 11 #include "base/observer_list.h" 12 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" 13 #include "content/public/browser/notification_observer.h" 14 #include "content/public/browser/notification_registrar.h" 15 #include "content/public/common/page_transition_types.h" 16 #include "ui/base/models/list_selection_model.h" 17 18 class Profile; 19 class TabStripModelDelegate; 20 class TabStripModelOrderController; 21 22 namespace content { 23 class WebContents; 24 } 25 26 //////////////////////////////////////////////////////////////////////////////// 27 // 28 // TabStripModel 29 // 30 // A model & low level controller of a Browser Window tabstrip. Holds a vector 31 // of WebContentses, and provides an API for adding, removing and 32 // shuffling them, as well as a higher level API for doing specific Browser- 33 // related tasks like adding new Tabs from just a URL, etc. 34 // 35 // Each tab may be any one of the following states: 36 // . Mini-tab. Mini tabs are locked to the left side of the tab strip and 37 // rendered differently (small tabs with only a favicon). The model makes 38 // sure all mini-tabs are at the beginning of the tab strip. For example, 39 // if a non-mini tab is added it is forced to be with non-mini tabs. Requests 40 // to move tabs outside the range of the tab type are ignored. For example, 41 // a request to move a mini-tab after non-mini-tabs is ignored. 42 // You'll notice there is no explicit api for making a tab a mini-tab, rather 43 // there are two tab types that are implicitly mini-tabs: 44 // . App. Corresponds to an extension that wants an app tab. App tabs are 45 // identified by extensions::TabHelper::is_app(). 46 // App tabs are always pinned (you can't unpin them). 47 // . Pinned. Any tab can be pinned. Non-app tabs whose pinned state is changed 48 // are moved to be with other mini-tabs or non-mini tabs. 49 // 50 // A TabStripModel has one delegate that it relies on to perform certain tasks 51 // like creating new TabStripModels (probably hosted in Browser windows) when 52 // required. See TabStripDelegate above for more information. 53 // 54 // A TabStripModel also has N observers (see TabStripModelObserver above), 55 // which can be registered via Add/RemoveObserver. An Observer is notified of 56 // tab creations, removals, moves, and other interesting events. The 57 // TabStrip implements this interface to know when to create new tabs in 58 // the View, and the Browser object likewise implements to be able to update 59 // its bookkeeping when such events happen. 60 // 61 //////////////////////////////////////////////////////////////////////////////// 62 class TabStripModel : public content::NotificationObserver { 63 public: 64 // Used to specify what should happen when the tab is closed. 65 enum CloseTypes { 66 CLOSE_NONE = 0, 67 68 // Indicates the tab was closed by the user. If true, 69 // WebContents::SetClosedByUserGesture(true) is invoked. 70 CLOSE_USER_GESTURE = 1 << 0, 71 72 // If true the history is recorded so that the tab can be reopened later. 73 // You almost always want to set this. 74 CLOSE_CREATE_HISTORICAL_TAB = 1 << 1, 75 }; 76 77 // Constants used when adding tabs. 78 enum AddTabTypes { 79 // Used to indicate nothing special should happen to the newly inserted 80 // tab. 81 ADD_NONE = 0, 82 83 // The tab should be active. 84 ADD_ACTIVE = 1 << 0, 85 86 // The tab should be pinned. 87 ADD_PINNED = 1 << 1, 88 89 // If not set the insertion index of the WebContents is left up to 90 // the Order Controller associated, so the final insertion index may differ 91 // from the specified index. Otherwise the index supplied is used. 92 ADD_FORCE_INDEX = 1 << 2, 93 94 // If set the newly inserted tab inherits the group of the currently 95 // selected tab. If not set the tab may still inherit the group under 96 // certain situations. 97 ADD_INHERIT_GROUP = 1 << 3, 98 99 // If set the newly inserted tab's opener is set to the active tab. If not 100 // set the tab may still inherit the group/opener under certain situations. 101 // NOTE: this is ignored if ADD_INHERIT_GROUP is set. 102 ADD_INHERIT_OPENER = 1 << 4, 103 }; 104 105 // Enumerates different ways to open a new tab. Does not apply to opening 106 // existing links or searches in a new tab, only to brand new empty tabs. 107 enum NewTab { 108 // New tab was opened using the new tab button on the tab strip. 109 NEW_TAB_BUTTON, 110 111 // New tab was opened using the menu command - either through the keyboard 112 // shortcut, or by opening the menu and selecting the command. Applies to 113 // both Wrench menu and the menu bar's File menu (on platforms that have 114 // one). 115 NEW_TAB_COMMAND, 116 117 // New tab was opened through the context menu on the tab strip. 118 NEW_TAB_CONTEXT_MENU, 119 120 // Number of enum entries, used for UMA histogram reporting macros. 121 NEW_TAB_ENUM_COUNT, 122 }; 123 124 static const int kNoTab = -1; 125 126 // Construct a TabStripModel with a delegate to help it do certain things 127 // (see the TabStripModelDelegate documentation). |delegate| cannot be NULL. 128 TabStripModel(TabStripModelDelegate* delegate, Profile* profile); 129 virtual ~TabStripModel(); 130 131 // Retrieves the TabStripModelDelegate associated with this TabStripModel. 132 TabStripModelDelegate* delegate() const { return delegate_; } 133 134 // Add and remove observers to changes within this TabStripModel. 135 void AddObserver(TabStripModelObserver* observer); 136 void RemoveObserver(TabStripModelObserver* observer); 137 138 // Retrieve the number of WebContentses/emptiness of the TabStripModel. 139 int count() const { return static_cast<int>(contents_data_.size()); } 140 bool empty() const { return contents_data_.empty(); } 141 142 // Retrieve the Profile associated with this TabStripModel. 143 Profile* profile() const { return profile_; } 144 145 // Retrieve the index of the currently active WebContents. 146 int active_index() const { return selection_model_.active(); } 147 148 // Returns true if the tabstrip is currently closing all open tabs (via a 149 // call to CloseAllTabs). As tabs close, the selection in the tabstrip 150 // changes which notifies observers, which can use this as an optimization to 151 // avoid doing meaningless or unhelpful work. 152 bool closing_all() const { return closing_all_; } 153 154 // Access the order controller. Exposed only for unit tests. 155 TabStripModelOrderController* order_controller() const { 156 return order_controller_.get(); 157 } 158 159 // Basic API ///////////////////////////////////////////////////////////////// 160 161 // Determines if the specified index is contained within the TabStripModel. 162 bool ContainsIndex(int index) const; 163 164 // Adds the specified WebContents in the default location. Tabs opened 165 // in the foreground inherit the group of the previously active tab. 166 void AppendWebContents(content::WebContents* contents, bool foreground); 167 168 // Adds the specified WebContents at the specified location. 169 // |add_types| is a bitmask of AddTabTypes; see it for details. 170 // 171 // All append/insert methods end up in this method. 172 // 173 // NOTE: adding a tab using this method does NOT query the order controller, 174 // as such the ADD_FORCE_INDEX AddTabTypes is meaningless here. The only time 175 // the |index| is changed is if using the index would result in breaking the 176 // constraint that all mini-tabs occur before non-mini-tabs. 177 // See also AddWebContents. 178 void InsertWebContentsAt(int index, 179 content::WebContents* contents, 180 int add_types); 181 182 // Closes the WebContents at the specified index. This causes the 183 // WebContents to be destroyed, but it may not happen immediately. 184 // |close_types| is a bitmask of CloseTypes. Returns true if the 185 // WebContents was closed immediately, false if it was not closed (we 186 // may be waiting for a response from an onunload handler, or waiting for the 187 // user to confirm closure). 188 bool CloseWebContentsAt(int index, uint32 close_types); 189 190 // Replaces the WebContents at |index| with |new_contents|. The 191 // WebContents that was at |index| is returned and its ownership returns 192 // to the caller. 193 content::WebContents* ReplaceWebContentsAt( 194 int index, 195 content::WebContents* new_contents); 196 197 // Destroys the WebContents at the specified index, but keeps the tab 198 // visible in the tab strip. Used to free memory in low-memory conditions, 199 // especially on Chrome OS. The tab reloads if the user clicks on it. 200 // Returns the new empty WebContents, used only for testing. 201 content::WebContents* DiscardWebContentsAt(int index); 202 203 // Detaches the WebContents at the specified index from this strip. The 204 // WebContents is not destroyed, just removed from display. The caller 205 // is responsible for doing something with it (e.g. stuffing it into another 206 // strip). Returns the detached WebContents. 207 content::WebContents* DetachWebContentsAt(int index); 208 209 // Makes the tab at the specified index the active tab. |user_gesture| is true 210 // if the user actually clicked on the tab or navigated to it using a keyboard 211 // command, false if the tab was activated as a by-product of some other 212 // action. 213 void ActivateTabAt(int index, bool user_gesture); 214 215 // Adds tab at |index| to the currently selected tabs, without changing the 216 // active tab index. 217 void AddTabAtToSelection(int index); 218 219 // Move the WebContents at the specified index to another index. This 220 // method does NOT send Detached/Attached notifications, rather it moves the 221 // WebContents inline and sends a Moved notification instead. 222 // If |select_after_move| is false, whatever tab was selected before the move 223 // will still be selected, but its index may have incremented or decremented 224 // one slot. 225 // NOTE: This respects basic ordering constraints and thus does nothing if the 226 // move would result in app tabs and non-app tabs mixing. 227 void MoveWebContentsAt(int index, int to_position, bool select_after_move); 228 229 // Moves the selected tabs to |index|. |index| is treated as if the tab strip 230 // did not contain any of the selected tabs. For example, if the tabstrip 231 // contains [A b c D E f] (upper case selected) and this is invoked with 1 the 232 // result is [b A D E c f]. 233 // This method maintains that all mini-tabs occur before non-mini-tabs. When 234 // mini-tabs are selected the move is processed in two chunks: first mini-tabs 235 // are moved, then non-mini-tabs are moved. If the index is after 236 // (mini-tab-count - selected-mini-tab-count), then the index the non-mini 237 // selected tabs are moved to is (index + selected-mini-tab-count). For 238 // example, if the model consists of [A b c D E f] (A b c are mini) and this 239 // is invoked with 2, the result is [b c A D E f]. In this example nothing 240 // special happened because the target index was <= (mini-tab-count - 241 // selected-mini-tab-count). If the target index were 3, then the result would 242 // be [b c A f D F]. A, being mini, can move no further than index 2. The 243 // non-mini-tabs are moved to the target index + selected-mini-tab-count (3 + 244 // 1) 245 void MoveSelectedTabsTo(int index); 246 247 // Returns the currently active WebContents, or NULL if there is none. 248 content::WebContents* GetActiveWebContents() const; 249 250 // Returns the WebContents at the specified index, or NULL if there is 251 // none. 252 content::WebContents* GetWebContentsAt(int index) const; 253 254 // Returns the index of the specified WebContents, or TabStripModel::kNoTab 255 // if the WebContents is not in this TabStripModel. 256 int GetIndexOfWebContents(const content::WebContents* contents) const; 257 258 // Notify any observers that the WebContents at the specified index has 259 // changed in some way. See TabChangeType for details of |change_type|. 260 void UpdateWebContentsStateAt( 261 int index, 262 TabStripModelObserver::TabChangeType change_type); 263 264 // Close all tabs at once. Code can use closing_all() above to defer 265 // operations that might otherwise by invoked by the flurry of detach/select 266 // notifications this method causes. 267 void CloseAllTabs(); 268 269 // Returns true if there are any WebContentses that are currently loading. 270 bool TabsAreLoading() const; 271 272 // Returns the WebContents that opened the WebContents at |index|, or NULL if 273 // there is no opener on record. 274 content::WebContents* GetOpenerOfWebContentsAt(int index); 275 276 // Changes the |opener| of the WebContents at |index|. 277 // Note: |opener| must be in this tab strip. 278 void SetOpenerOfWebContentsAt(int index, content::WebContents* opener); 279 280 // Returns the index of the next WebContents in the sequence of WebContentses 281 // spawned by the specified WebContents after |start_index|. If |use_group| is 282 // true, the group property of the tab is used instead of the opener to find 283 // the next tab. Under some circumstances the group relationship may exist but 284 // the opener may not. 285 int GetIndexOfNextWebContentsOpenedBy(const content::WebContents* opener, 286 int start_index, 287 bool use_group) const; 288 289 // Returns the index of the last WebContents in the model opened by the 290 // specified opener, starting at |start_index|. 291 int GetIndexOfLastWebContentsOpenedBy(const content::WebContents* opener, 292 int start_index) const; 293 294 // To be called when a navigation is about to occur in the specified 295 // WebContents. Depending on the tab, and the transition type of the 296 // navigation, the TabStripModel may adjust its selection and grouping 297 // behavior. 298 void TabNavigating(content::WebContents* contents, 299 content::PageTransition transition); 300 301 // Forget all Opener relationships that are stored (but _not_ group 302 // relationships!) This is to reduce unpredictable tab switching behavior 303 // in complex session states. The exact circumstances under which this method 304 // is called are left up to the implementation of the selected 305 // TabStripModelOrderController. 306 void ForgetAllOpeners(); 307 308 // Forgets the group affiliation of the specified WebContents. This 309 // should be called when a WebContents that is part of a logical group 310 // of tabs is moved to a new logical context by the user (e.g. by typing a new 311 // URL or selecting a bookmark). This also forgets the opener, which is 312 // considered a weaker relationship than group. 313 void ForgetGroup(content::WebContents* contents); 314 315 // Returns true if the group/opener relationships present for |contents| 316 // should be reset when _any_ selection change occurs in the model. 317 bool ShouldResetGroupOnSelect(content::WebContents* contents) const; 318 319 // Changes the blocked state of the tab at |index|. 320 void SetTabBlocked(int index, bool blocked); 321 322 // Changes the pinned state of the tab at |index|. See description above 323 // class for details on this. 324 void SetTabPinned(int index, bool pinned); 325 326 // Returns true if the tab at |index| is pinned. 327 // See description above class for details on pinned tabs. 328 bool IsTabPinned(int index) const; 329 330 // Is the tab a mini-tab? 331 // See description above class for details on this. 332 bool IsMiniTab(int index) const; 333 334 // Is the tab at |index| an app? 335 // See description above class for details on app tabs. 336 bool IsAppTab(int index) const; 337 338 // Returns true if the tab at |index| is blocked by a tab modal dialog. 339 bool IsTabBlocked(int index) const; 340 341 // Returns true if the WebContents at |index| has been discarded to 342 // save memory. See DiscardWebContentsAt() for details. 343 bool IsTabDiscarded(int index) const; 344 345 // Returns the index of the first tab that is not a mini-tab. This returns 346 // |count()| if all of the tabs are mini-tabs, and 0 if none of the tabs are 347 // mini-tabs. 348 int IndexOfFirstNonMiniTab() const; 349 350 // Returns a valid index for inserting a new tab into this model. |index| is 351 // the proposed index and |mini_tab| is true if inserting a tab will become 352 // mini (pinned or app). If |mini_tab| is true, the returned index is between 353 // 0 and IndexOfFirstNonMiniTab. If |mini_tab| is false, the returned index 354 // is between IndexOfFirstNonMiniTab and count(). 355 int ConstrainInsertionIndex(int index, bool mini_tab); 356 357 // Extends the selection from the anchor to |index|. 358 void ExtendSelectionTo(int index); 359 360 // Toggles the selection at |index|. This does nothing if |index| is selected 361 // and there are no other selected tabs. 362 void ToggleSelectionAt(int index); 363 364 // Makes sure the tabs from the anchor to |index| are selected. This only 365 // adds to the selection. 366 void AddSelectionFromAnchorTo(int index); 367 368 // Returns true if the tab at |index| is selected. 369 bool IsTabSelected(int index) const; 370 371 // Sets the selection to match that of |source|. 372 void SetSelectionFromModel(const ui::ListSelectionModel& source); 373 374 const ui::ListSelectionModel& selection_model() const { 375 return selection_model_; 376 } 377 378 // Command level API ///////////////////////////////////////////////////////// 379 380 // Adds a WebContents at the best position in the TabStripModel given 381 // the specified insertion index, transition, etc. |add_types| is a bitmask of 382 // AddTabTypes; see it for details. This method ends up calling into 383 // InsertWebContentsAt to do the actual insertion. Pass kNoTab for |index| to 384 // append the contents to the end of the tab strip. 385 void AddWebContents(content::WebContents* contents, 386 int index, 387 content::PageTransition transition, 388 int add_types); 389 390 // Closes the selected tabs. 391 void CloseSelectedTabs(); 392 393 // Select adjacent tabs 394 void SelectNextTab(); 395 void SelectPreviousTab(); 396 397 // Selects the last tab in the tab strip. 398 void SelectLastTab(); 399 400 // Swap adjacent tabs. 401 void MoveTabNext(); 402 void MoveTabPrevious(); 403 404 // View API ////////////////////////////////////////////////////////////////// 405 406 // Context menu functions. 407 enum ContextMenuCommand { 408 CommandFirst = 0, 409 CommandNewTab, 410 CommandReload, 411 CommandDuplicate, 412 CommandCloseTab, 413 CommandCloseOtherTabs, 414 CommandCloseTabsToRight, 415 CommandRestoreTab, 416 CommandTogglePinned, 417 CommandBookmarkAllTabs, 418 CommandSelectByDomain, 419 CommandSelectByOpener, 420 CommandLast 421 }; 422 423 // Returns true if the specified command is enabled. If |context_index| is 424 // selected the response applies to all selected tabs. 425 bool IsContextMenuCommandEnabled(int context_index, 426 ContextMenuCommand command_id) const; 427 428 // Performs the action associated with the specified command for the given 429 // TabStripModel index |context_index|. If |context_index| is selected the 430 // command applies to all selected tabs. 431 void ExecuteContextMenuCommand(int context_index, 432 ContextMenuCommand command_id); 433 434 // Returns a vector of indices of the tabs that will close when executing the 435 // command |id| for the tab at |index|. The returned indices are sorted in 436 // descending order. 437 std::vector<int> GetIndicesClosedByCommand(int index, 438 ContextMenuCommand id) const; 439 440 // Returns true if 'CommandTogglePinned' will pin. |index| is the index 441 // supplied to |ExecuteContextMenuCommand|. 442 bool WillContextMenuPin(int index); 443 444 // Overridden from content::NotificationObserver: 445 virtual void Observe(int type, 446 const content::NotificationSource& source, 447 const content::NotificationDetails& details) OVERRIDE; 448 449 // Convert a ContextMenuCommand into a browser command. Returns true if a 450 // corresponding browser command exists, false otherwise. 451 static bool ContextMenuCommandToBrowserCommand(int cmd_id, int* browser_cmd); 452 453 private: 454 // Used when making selection notifications. 455 enum NotifyTypes { 456 NOTIFY_DEFAULT, 457 458 // The selection is changing from a user gesture. 459 NOTIFY_USER_GESTURE, 460 }; 461 462 // Convenience for converting a vector of indices into a vector of 463 // WebContents. 464 std::vector<content::WebContents*> GetWebContentsFromIndices( 465 const std::vector<int>& indices) const; 466 467 // Gets the set of tab indices whose domain matches the tab at |index|. 468 void GetIndicesWithSameDomain(int index, std::vector<int>* indices); 469 470 // Gets the set of tab indices that have the same opener as the tab at 471 // |index|. 472 void GetIndicesWithSameOpener(int index, std::vector<int>* indices); 473 474 // If |index| is selected all the selected indices are returned, otherwise a 475 // vector with |index| is returned. This is used when executing commands to 476 // determine which indices the command applies to. 477 std::vector<int> GetIndicesForCommand(int index) const; 478 479 // Returns true if the specified WebContents is a New Tab at the end of 480 // the tabstrip. We check for this because opener relationships are _not_ 481 // forgotten for the New Tab page opened as a result of a New Tab gesture 482 // (e.g. Ctrl+T, etc) since the user may open a tab transiently to look up 483 // something related to their current activity. 484 bool IsNewTabAtEndOfTabStrip(content::WebContents* contents) const; 485 486 // Closes the WebContentses at the specified indices. This causes the 487 // WebContentses to be destroyed, but it may not happen immediately. If 488 // the page in question has an unload event the WebContents will not be 489 // destroyed until after the event has completed, which will then call back 490 // into this method. 491 // 492 // Returns true if the WebContentses were closed immediately, false if we 493 // are waiting for the result of an onunload handler. 494 bool InternalCloseTabs(const std::vector<int>& indices, 495 uint32 close_types); 496 497 // Invoked from InternalCloseTabs and when an extension is removed for an app 498 // tab. Notifies observers of TabClosingAt and deletes |contents|. If 499 // |create_historical_tabs| is true, CreateHistoricalTab is invoked on the 500 // delegate. 501 // 502 // The boolean parameter create_historical_tab controls whether to 503 // record these tabs and their history for reopening recently closed 504 // tabs. 505 void InternalCloseTab(content::WebContents* contents, 506 int index, 507 bool create_historical_tabs); 508 509 // Gets the WebContents at an index. Does no bounds checking. 510 content::WebContents* GetWebContentsAtImpl(int index) const; 511 512 // Notifies the observers if the active tab is being deactivated. 513 void NotifyIfTabDeactivated(content::WebContents* contents); 514 515 // Notifies the observers if the active tab has changed. 516 void NotifyIfActiveTabChanged(content::WebContents* old_contents, 517 NotifyTypes notify_types); 518 519 // Notifies the observers if the active tab or the tab selection has changed. 520 // |old_model| is a snapshot of |selection_model_| before the change. 521 // Note: This function might end up sending 0 to 2 notifications in the 522 // following order: ActiveTabChanged, TabSelectionChanged. 523 void NotifyIfActiveOrSelectionChanged( 524 content::WebContents* old_contents, 525 NotifyTypes notify_types, 526 const ui::ListSelectionModel& old_model); 527 528 // Sets the selection to |new_model| and notifies any observers. 529 // Note: This function might end up sending 0 to 3 notifications in the 530 // following order: TabDeactivated, ActiveTabChanged, TabSelectionChanged. 531 void SetSelection(const ui::ListSelectionModel& new_model, 532 NotifyTypes notify_types); 533 534 // Selects either the next tab (|forward| is true), or the previous tab 535 // (|forward| is false). 536 void SelectRelativeTab(bool forward); 537 538 // Does the work of MoveWebContentsAt. This has no checks to make sure the 539 // position is valid, those are done in MoveWebContentsAt. 540 void MoveWebContentsAtImpl(int index, 541 int to_position, 542 bool select_after_move); 543 544 // Implementation of MoveSelectedTabsTo. Moves |length| of the selected tabs 545 // starting at |start| to |index|. See MoveSelectedTabsTo for more details. 546 void MoveSelectedTabsToImpl(int index, size_t start, size_t length); 547 548 // Returns true if the tab represented by the specified data has an opener 549 // that matches the specified one. If |use_group| is true, then this will 550 // fall back to check the group relationship as well. 551 struct WebContentsData; 552 static bool OpenerMatches(const WebContentsData* data, 553 const content::WebContents* opener, 554 bool use_group); 555 556 // Sets the group/opener of any tabs that reference |tab| to NULL. 557 void ForgetOpenersAndGroupsReferencing(const content::WebContents* tab); 558 559 // Our delegate. 560 TabStripModelDelegate* delegate_; 561 562 // A hunk of data representing a WebContents and (optionally) the 563 // WebContents that spawned it. This memory only sticks around while 564 // the WebContents is in the current TabStripModel, unless otherwise 565 // specified in code. 566 struct WebContentsData { 567 explicit WebContentsData(content::WebContents* a_contents) 568 : contents(a_contents), 569 reset_group_on_select(false), 570 pinned(false), 571 blocked(false), 572 discarded(false) { 573 SetGroup(NULL); 574 } 575 576 // Create a relationship between this WebContentsData and other 577 // WebContentses. Used to identify which WebContents to select next after 578 // one is closed. 579 void SetGroup(content::WebContents* a_group) { 580 group = a_group; 581 opener = a_group; 582 } 583 584 // Forget the opener relationship so that when this WebContents is 585 // closed unpredictable re-selection does not occur. 586 void ForgetOpener() { 587 opener = NULL; 588 } 589 590 content::WebContents* contents; 591 // The group is used to model a set of tabs spawned from a single parent 592 // tab. This value is preserved for a given tab as long as the tab remains 593 // navigated to the link it was initially opened at or some navigation from 594 // that page (i.e. if the user types or visits a bookmark or some other 595 // navigation within that tab, the group relationship is lost). This 596 // property can safely be used to implement features that depend on a 597 // logical group of related tabs. 598 content::WebContents* group; 599 // The owner models the same relationship as group, except it is more 600 // easily discarded, e.g. when the user switches to a tab not part of the 601 // same group. This property is used to determine what tab to select next 602 // when one is closed. 603 content::WebContents* opener; 604 // True if our group should be reset the moment selection moves away from 605 // this tab. This is the case for tabs opened in the foreground at the end 606 // of the TabStrip while viewing another Tab. If these tabs are closed 607 // before selection moves elsewhere, their opener is selected. But if 608 // selection shifts to _any_ tab (including their opener), the group 609 // relationship is reset to avoid confusing close sequencing. 610 bool reset_group_on_select; 611 612 // Is the tab pinned? 613 bool pinned; 614 615 // Is the tab interaction blocked by a modal dialog? 616 bool blocked; 617 618 // Has the tab data been discarded to save memory? 619 bool discarded; 620 }; 621 622 // The WebContents data currently hosted within this TabStripModel. 623 typedef std::vector<WebContentsData*> WebContentsDataVector; 624 WebContentsDataVector contents_data_; 625 626 // A profile associated with this TabStripModel. 627 Profile* profile_; 628 629 // True if all tabs are currently being closed via CloseAllTabs. 630 bool closing_all_; 631 632 // An object that determines where new Tabs should be inserted and where 633 // selection should move when a Tab is closed. 634 scoped_ptr<TabStripModelOrderController> order_controller_; 635 636 // Our observers. 637 typedef ObserverList<TabStripModelObserver> TabStripModelObservers; 638 TabStripModelObservers observers_; 639 640 // A scoped container for notification registries. 641 content::NotificationRegistrar registrar_; 642 643 ui::ListSelectionModel selection_model_; 644 645 DISALLOW_IMPLICIT_CONSTRUCTORS(TabStripModel); 646 }; 647 648 #endif // CHROME_BROWSER_UI_TABS_TAB_STRIP_MODEL_H_ 649