15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/app/chrome_command_ids.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_shutdown.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/defaults.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tab_contents/core_tab_helper.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tab_contents/core_tab_helper_delegate.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model_order_controller.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_types.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/user_metrics.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::UserMetricsAction; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the specified transition is one of the types that cause the 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// opener relationships for the tab in which the transition occurred to be 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// forgotten. This is generally any navigation that isn't a link click (i.e. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// any navigation that can be considered to be the start of a new task distinct 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from what had previously occurred in that tab). 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldForgetOpenersForTransition(content::PageTransition transition) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transition == content::PAGE_TRANSITION_TYPED || 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition == content::PAGE_TRANSITION_AUTO_BOOKMARK || 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition == content::PAGE_TRANSITION_GENERATED || 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition == content::PAGE_TRANSITION_KEYWORD || 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transition == content::PAGE_TRANSITION_AUTO_TOPLEVEL; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// CloseTracker is used when closing a set of WebContents. It listens for 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// deletions of the WebContents and removes from the internal set any time one 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// is deleted. 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class CloseTracker : public content::NotificationObserver { 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public: 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) typedef std::vector<WebContents*> Contents; 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) explicit CloseTracker(const Contents& contents); 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual ~CloseTracker(); 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Returns true if there is another WebContents in the Tracker. 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool HasNext() const; 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Returns the next WebContents, or NULL if there are no more. 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) WebContents* Next(); 63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private: 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // NotificationObserver: 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) virtual void Observe(int type, 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const content::NotificationSource& source, 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const content::NotificationDetails& details) OVERRIDE; 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Contents contents_; 71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::NotificationRegistrar registrar_; 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CloseTracker); 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}; 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)CloseTracker::CloseTracker(const Contents& contents) 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : contents_(contents) { 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::NotificationService::AllBrowserContextsAndSources()); 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)CloseTracker::~CloseTracker() { 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 86868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool CloseTracker::HasNext() const { 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return !contents_.empty(); 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)WebContents* CloseTracker::Next() { 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (contents_.empty()) 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return NULL; 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) WebContents* web_contents = contents_[0]; 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) contents_.erase(contents_.begin()); 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return web_contents; 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CloseTracker::Observe(int type, 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const content::NotificationSource& source, 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const content::NotificationDetails& details) { 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) WebContents* web_contents = content::Source<WebContents>(source).ptr(); 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) Contents::iterator i = 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::find(contents_.begin(), contents_.end(), web_contents); 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (i != contents_.end()) 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) contents_.erase(i); 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabStripModel, public: 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabStripModel::TabStripModel(TabStripModelDelegate* delegate, Profile* profile) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : delegate_(delegate), 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(profile), 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closing_all_(false) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate_); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationService::AllBrowserContextsAndSources()); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) order_controller_.reset(new TabStripModelOrderController(this)); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TabStripModel::~TabStripModel() { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModelDeleted()); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&contents_data_); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) order_controller_.reset(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::AddObserver(TabStripModelObserver* observer) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.AddObserver(observer); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::RemoveObserver(TabStripModelObserver* observer) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.RemoveObserver(observer); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::ContainsIndex(int index) const { 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index >= 0 && index < count(); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::AppendWebContents(WebContents* contents, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool foreground) { 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InsertWebContentsAt(count(), contents, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) foreground ? (ADD_INHERIT_GROUP | ADD_ACTIVE) : 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ADD_NONE); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::InsertWebContentsAt(int index, 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* contents, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int add_types) { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->WillAddWebContents(contents); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool active = add_types & ADD_ACTIVE; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Force app tabs to be pinned. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::TabHelper* extensions_tab_helper = 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::TabHelper::FromWebContents(contents); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool pin = extensions_tab_helper->is_app() || add_types & ADD_PINNED; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = ConstrainInsertionIndex(index, pin); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In tab dragging situations, if the last tab in the window was detached 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // then the user aborted the drag, we will have the |closing_all_| member 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // set (see DetachWebContentsAt) which will mess with our mojo here. We need 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to clear this bit. 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closing_all_ = false; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have to get the active contents before we monkey with |contents_| 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise we run into problems when we try to change the active contents 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since the old contents and the new contents will be the same... 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* active_contents = GetActiveWebContents(); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContentsData* data = new WebContentsData(contents); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->pinned = pin; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((add_types & ADD_INHERIT_GROUP) && active_contents) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (active) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Forget any existing relationships, we don't want to make things too 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // confusing by having multiple groups active at the same time. 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ForgetAllOpeners(); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Anything opened by a link we deem to have an opener. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->SetGroup(active_contents); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if ((add_types & ADD_INHERIT_OPENER) && active_contents) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (active) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Forget any existing relationships, we don't want to make things too 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // confusing by having multiple groups active at the same time. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ForgetAllOpeners(); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data->opener = active_contents; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_.insert(contents_data_.begin() + index, data); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.IncrementFrom(index); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabInsertedAt(contents, index, active)); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (active) { 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel new_model; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.Copy(selection_model_); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.SetSelectedIndex(index); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelection(new_model, NOTIFY_DEFAULT); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebContents* TabStripModel::ReplaceWebContentsAt(int index, 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* new_contents) { 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->WillAddWebContents(new_contents); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* old_contents = GetWebContentsAtImpl(index); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ForgetOpenersAndGroupsReferencing(old_contents); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_data_[index]->contents = new_contents; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabReplacedAt(this, old_contents, new_contents, index)); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When the active WebContents is replaced send out a selection notification 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // too. We do this as nearly all observers need to treat a replacement of the 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // selected contents as the selection changing. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (active_index() == index) { 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FOR_EACH_OBSERVER( 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TabStripModelObserver, 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) observers_, 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ActiveTabChanged(old_contents, 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new_contents, 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) active_index(), 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) TabStripModelObserver::CHANGE_REASON_REPLACED)); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return old_contents; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebContents* TabStripModel::DiscardWebContentsAt(int index) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do not discard active tab. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (active_index() == index) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* null_contents = 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents::Create(WebContents::CreateParams(profile())); 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* old_contents = GetWebContentsAtImpl(index); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy over the state from the navigation controller so we preserve the 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // back/forward history and continue to display the correct title/favicon. 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) null_contents->GetController().CopyStateFrom(old_contents->GetController()); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Replace the tab we're discarding with the null version. 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ReplaceWebContentsAt(index, null_contents); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark the tab so it will reload when we click. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_[index]->discarded = true; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Discard the old tab's renderer. 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jamescook): This breaks script connections with other tabs. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to find a different approach that doesn't do that, perhaps based 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on navigation to swappedout://. 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete old_contents; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return null_contents; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebContents* TabStripModel::DetachWebContentsAt(int index) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents_data_.empty()) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* removed_contents = GetWebContentsAtImpl(index); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_selected = IsTabSelected(index); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int next_selected_index = order_controller_->DetermineNewSelectedIndex(index); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete contents_data_[index]; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_.erase(contents_data_.begin() + index); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ForgetOpenersAndGroupsReferencing(removed_contents); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (empty()) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closing_all_ = true; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabDetachedAt(removed_contents, index)); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (empty()) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.Clear(); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TabDetachedAt() might unregister observers, so send |TabStripEmpty()| in 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a second pass. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, TabStripEmpty()); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_active = active_index(); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.DecrementFrom(index); 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel old_model; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_model.Copy(selection_model_); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == old_active) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyIfTabDeactivated(removed_contents); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!selection_model_.empty()) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The active tab was removed, but there is still something selected. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move the active and anchor to the first selected index. 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.set_active(selection_model_.selected_indices()[0]); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.set_anchor(selection_model_.active()); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The active tab was removed and nothing is selected. Reset the 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // selection and send out notification. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.SetSelectedIndex(next_selected_index); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyIfActiveTabChanged(removed_contents, NOTIFY_DEFAULT); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sending notification in case the detached tab was selected. Using 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NotifyIfActiveOrSelectionChanged() here would not guarantee that a 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notification is sent even though the tab selection has changed because 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |old_model| is stored after calling DecrementFrom(). 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (was_selected) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabSelectionChanged(this, old_model)); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return removed_contents; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::ActivateTabAt(int index, bool user_gesture) { 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel new_model; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.Copy(selection_model_); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.SetSelectedIndex(index); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelection(new_model, user_gesture ? NOTIFY_USER_GESTURE : NOTIFY_DEFAULT); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::AddTabAtToSelection(int index) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel new_model; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.Copy(selection_model_); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.AddIndexToSelection(index); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelection(new_model, NOTIFY_DEFAULT); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::MoveWebContentsAt(int index, 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int to_position, 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool select_after_move) { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == to_position) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int first_non_mini_tab = IndexOfFirstNonMiniTab(); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((index < first_non_mini_tab && to_position >= first_non_mini_tab) || 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (to_position < first_non_mini_tab && index >= first_non_mini_tab)) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This would result in mini tabs mixed with non-mini tabs. We don't allow 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that. 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MoveWebContentsAtImpl(index, to_position, select_after_move); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::MoveSelectedTabsTo(int index) { 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int total_mini_count = IndexOfFirstNonMiniTab(); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_mini_count = 0; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int selected_count = 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<int>(selection_model_.selected_indices().size()); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < selected_count && 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsMiniTab(selection_model_.selected_indices()[i]); ++i) { 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_mini_count++; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To maintain that all mini-tabs occur before non-mini-tabs we move them 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // first. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selected_mini_count > 0) { 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MoveSelectedTabsToImpl( 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(total_mini_count - selected_mini_count, index), 0u, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_mini_count); 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index > total_mini_count - selected_mini_count) { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We're being told to drag mini-tabs to an invalid location. Adjust the 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // index such that non-mini-tabs end up at a location as though we could 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // move the mini-tabs to index. See description in header for more 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // details. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index += selected_mini_count; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selected_mini_count == selected_count) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then move the non-pinned tabs. 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MoveSelectedTabsToImpl(std::max(index, total_mini_count), 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_mini_count, 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selected_count - selected_mini_count); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebContents* TabStripModel::GetActiveWebContents() const { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetWebContentsAt(active_index()); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebContents* TabStripModel::GetWebContentsAt(int index) const { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ContainsIndex(index)) 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetWebContentsAtImpl(index); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabStripModel::GetIndexOfWebContents(const WebContents* contents) const { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < contents_data_.size(); ++i) { 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents_data_[i]->contents == contents) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kNoTab; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::UpdateWebContentsStateAt(int index, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModelObserver::TabChangeType change_type) { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabChangedAt(GetWebContentsAtImpl(index), index, change_type)); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::CloseAllTabs() { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set state so that observers can adjust their behavior to suit this 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // specific condition when CloseWebContentsAt causes a flurry of 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close/Detach/Select notifications to be sent. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closing_all_ = true; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> closing_tabs; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = count() - 1; i >= 0; --i) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closing_tabs.push_back(i); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InternalCloseTabs(closing_tabs, CLOSE_CREATE_HISTORICAL_TAB); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TabStripModel::CloseWebContentsAt(int index, uint32 close_types) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> closing_tabs; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closing_tabs.push_back(index); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InternalCloseTabs(closing_tabs, close_types); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::TabsAreLoading() const { 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (WebContentsDataVector::const_iterator iter = contents_data_.begin(); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != contents_data_.end(); ++iter) { 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*iter)->contents->IsLoading()) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebContents* TabStripModel::GetOpenerOfWebContentsAt(int index) { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return contents_data_[index]->opener; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::SetOpenerOfWebContentsAt(int index, 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* opener) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(opener); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_[index]->opener = opener; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabStripModel::GetIndexOfNextWebContentsOpenedBy(const WebContents* opener, 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int start_index, 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_group) const { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(opener); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(start_index)); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check tabs after start_index first. 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = start_index + 1; i < count(); ++i) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (OpenerMatches(contents_data_[i], opener, use_group)) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then check tabs before start_index, iterating backwards. 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = start_index - 1; i >= 0; --i) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (OpenerMatches(contents_data_[i], opener, use_group)) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kNoTab; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabStripModel::GetIndexOfLastWebContentsOpenedBy(const WebContents* opener, 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int start_index) const { 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(opener); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(start_index)); 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = contents_data_.size() - 1; i > start_index; --i) { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents_data_[i]->opener == opener) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return i; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kNoTab; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::TabNavigating(WebContents* contents, 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition) { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldForgetOpenersForTransition(transition)) { 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't forget the openers if this tab is a New Tab page opened at the 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // end of the TabStrip (e.g. by pressing Ctrl+T). Give the user one 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // navigation of one of these transition types before resetting the 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // opener relationships (this allows for the use case of opening a new 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // tab to do a quick look-up of something while viewing a tab earlier in 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the strip). We can make this heuristic more permissive if need be. 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsNewTabAtEndOfTabStrip(contents)) { 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the user navigates the current tab to another page in any way 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other than by clicking a link, we want to pro-actively forget all 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TabStrip opener relationships since we assume they're beginning a 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // different task by reusing the current tab. 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ForgetAllOpeners(); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this specific case we also want to reset the group relationship, 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since it is now technically invalid. 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ForgetGroup(contents); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::ForgetAllOpeners() { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Forget all opener memories so we don't do anything weird with tab 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // re-selection ordering. 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (WebContentsDataVector::const_iterator iter = contents_data_.begin(); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != contents_data_.end(); ++iter) 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*iter)->ForgetOpener(); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::ForgetGroup(WebContents* contents) { 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index = GetIndexOfWebContents(contents); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_[index]->SetGroup(NULL); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_[index]->ForgetOpener(); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TabStripModel::ShouldResetGroupOnSelect(WebContents* contents) const { 5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index = GetIndexOfWebContents(contents); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return contents_data_[index]->reset_group_on_select; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::SetTabBlocked(int index, bool blocked) { 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents_data_[index]->blocked == blocked) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_[index]->blocked = blocked; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabBlockedStateChanged(contents_data_[index]->contents, 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index)); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::SetTabPinned(int index, bool pinned) { 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents_data_[index]->pinned == pinned) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsAppTab(index)) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!pinned) { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // App tabs should always be pinned. 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Changing the pinned state of an app tab doesn't affect its mini-tab 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // status. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_[index]->pinned = pinned; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The tab is not an app tab, its position may have to change as the 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mini-tab state is changing. 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int non_mini_tab_index = IndexOfFirstNonMiniTab(); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_[index]->pinned = pinned; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pinned && index != non_mini_tab_index) { 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MoveWebContentsAtImpl(index, non_mini_tab_index, false); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = non_mini_tab_index; 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (!pinned && index + 1 != non_mini_tab_index) { 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MoveWebContentsAtImpl(index, non_mini_tab_index - 1, false); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = non_mini_tab_index - 1; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabMiniStateChanged(contents_data_[index]->contents, 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index)); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // else: the tab was at the boundary and its position doesn't need to change. 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabPinnedStateChanged(contents_data_[index]->contents, 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index)); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::IsTabPinned(int index) const { 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return contents_data_[index]->pinned; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::IsMiniTab(int index) const { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsTabPinned(index) || IsAppTab(index); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::IsAppTab(int index) const { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* contents = GetWebContentsAt(index); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return contents && extensions::TabHelper::FromWebContents(contents)->is_app(); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::IsTabBlocked(int index) const { 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return contents_data_[index]->blocked; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::IsTabDiscarded(int index) const { 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return contents_data_[index]->discarded; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabStripModel::IndexOfFirstNonMiniTab() const { 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < contents_data_.size(); ++i) { 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsMiniTab(static_cast<int>(i))) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(i); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No mini-tabs. 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return count(); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int TabStripModel::ConstrainInsertionIndex(int index, bool mini_tab) { 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mini_tab ? std::min(std::max(0, index), IndexOfFirstNonMiniTab()) : 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(count(), std::max(index, IndexOfFirstNonMiniTab())); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::ExtendSelectionTo(int index) { 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel new_model; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.Copy(selection_model_); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.SetSelectionFromAnchorTo(index); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelection(new_model, NOTIFY_DEFAULT); 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::ToggleSelectionAt(int index) { 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel new_model; 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.Copy(selection_model()); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selection_model_.IsSelected(index)) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selection_model_.size() == 1) { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // One tab must be selected and this tab is currently selected so we can't 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unselect it. 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.RemoveIndexFromSelection(index); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.set_anchor(index); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_model.active() == index || 6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_model.active() == ui::ListSelectionModel::kUnselectedIndex) 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.set_active(new_model.selected_indices()[0]); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.AddIndexToSelection(index); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.set_anchor(index); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.set_active(index); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelection(new_model, NOTIFY_DEFAULT); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::AddSelectionFromAnchorTo(int index) { 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel new_model; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.Copy(selection_model_); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_model.AddSelectionFromAnchorTo(index); 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelection(new_model, NOTIFY_DEFAULT); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::IsTabSelected(int index) const { 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return selection_model_.IsSelected(index); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::SetSelectionFromModel( 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ui::ListSelectionModel& source) { 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_NE(ui::ListSelectionModel::kUnselectedIndex, source.active()); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelection(source, NOTIFY_DEFAULT); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::AddWebContents(WebContents* contents, 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::PageTransition transition, 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int add_types) { 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the newly-opened tab is part of the same task as the parent tab, we want 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to inherit the parent's "group" attribute, so that if this tab is then 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // closed we'll jump back to the parent tab. 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool inherit_group = (add_types & ADD_INHERIT_GROUP) == ADD_INHERIT_GROUP; 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transition == content::PAGE_TRANSITION_LINK && 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (add_types & ADD_FORCE_INDEX) == 0) { 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We assume tabs opened via link clicks are part of the same task as their 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // parent. Note that when |force_index| is true (e.g. when the user 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // drag-and-drops a link to the tab strip), callers aren't really handling 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // link clicks, they just want to score the navigation like a link click in 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the history backend, so we don't inherit the group in this case. 6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) index = order_controller_->DetermineInsertionIndex(transition, 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) add_types & ADD_ACTIVE); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inherit_group = true; 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For all other types, respect what was passed to us, normalizing -1s and 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // values that are too large. 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < 0 || index > count()) 6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) index = count(); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transition == content::PAGE_TRANSITION_TYPED && index == count()) { 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Also, any tab opened at the end of the TabStrip with a "TYPED" 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // transition inherit group as well. This covers the cases where the user 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // creates a New Tab (e.g. Ctrl+T, or clicks the New Tab button), or types 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the address bar and presses Alt+Enter. This allows for opening a new 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tab to quickly look up something. When this Tab is closed, the old one 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is re-selected, not the next-adjacent. 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inherit_group = true; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InsertWebContentsAt(index, contents, 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) add_types | (inherit_group ? ADD_INHERIT_GROUP : 0)); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset the index, just in case insert ended up moving it on us. 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) index = GetIndexOfWebContents(contents); 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inherit_group && transition == content::PAGE_TRANSITION_TYPED) 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_[index]->reset_group_on_select = true; 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(sky): figure out why this is here and not in InsertWebContentsAt. When 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // here we seem to get failures in startup perf tests. 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that the new WebContentsView begins at the same size as the 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // previous WebContentsView if it existed. Otherwise, the initial WebKit 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // layout will be performed based on a width of 0 pixels, causing a 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // very long, narrow, inaccurate layout. Because some scripts on pages (as 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // well as WebKit's anchor link location calculation) are run on the 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // initial layout and not recalculated later, we need to ensure the first 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // layout is performed with sane view dimensions even when we're opening a 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new background tab. 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (WebContents* old_contents = GetActiveWebContents()) { 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((add_types & ADD_ACTIVE) == 0) { 7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents->GetView()->SizeContents( 7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) old_contents->GetView()->GetContainerSize()); 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to hide the contents or else we get and execute paints for 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // background tabs. With enough background tabs they will steal the 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // backing store of the visible tab causing flashing. See bug 20831. 7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents->WasHidden(); 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::CloseSelectedTabs() { 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InternalCloseTabs(selection_model_.selected_indices(), 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLOSE_CREATE_HISTORICAL_TAB | CLOSE_USER_GESTURE); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::SelectNextTab() { 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectRelativeTab(true); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::SelectPreviousTab() { 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SelectRelativeTab(false); 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::SelectLastTab() { 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ActivateTabAt(count() - 1, true); 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::MoveTabNext() { 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO: this likely needs to be updated for multi-selection. 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_index = std::min(active_index() + 1, count() - 1); 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MoveWebContentsAt(active_index(), new_index, true); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::MoveTabPrevious() { 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO: this likely needs to be updated for multi-selection. 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_index = std::max(active_index() - 1, 0); 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MoveWebContentsAt(active_index(), new_index, true); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Context menu functions. 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::IsContextMenuCommandEnabled( 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int context_index, ContextMenuCommand command_id) const { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(command_id > CommandFirst && command_id < CommandLast); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (command_id) { 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandNewTab: 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandCloseTab: 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandReload: { 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices = GetIndicesForCommand(context_index); 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < indices.size(); ++i) { 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* tab = GetWebContentsAt(indices[i]); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab) { 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CoreTabHelperDelegate* core_delegate = 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CoreTabHelper::FromWebContents(tab)->delegate(); 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!core_delegate || core_delegate->CanReloadContents(tab)) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandCloseOtherTabs: 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandCloseTabsToRight: 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !GetIndicesClosedByCommand(context_index, command_id).empty(); 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandDuplicate: { 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices = GetIndicesForCommand(context_index); 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < indices.size(); ++i) { 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delegate_->CanDuplicateContentsAt(indices[i])) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandRestoreTab: 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return delegate_->GetRestoreTabType() != 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabStripModelDelegate::RESTORE_NONE; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandTogglePinned: { 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices = GetIndicesForCommand(context_index); 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < indices.size(); ++i) { 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsAppTab(indices[i])) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandBookmarkAllTabs: 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser_defaults::bookmarks_enabled && 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->CanBookmarkAllTabs(); 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandSelectByDomain: 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandSelectByOpener: 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::ExecuteContextMenuCommand( 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int context_index, ContextMenuCommand command_id) { 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(command_id > CommandFirst && command_id < CommandLast); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (command_id) { 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandNewTab: 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction(UserMetricsAction("TabContextMenu_NewTab")); 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel::NEW_TAB_CONTEXT_MENU, 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabStripModel::NEW_TAB_ENUM_COUNT); 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate()->AddBlankTabAt(context_index + 1, true); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandReload: { 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction(UserMetricsAction("TabContextMenu_Reload")); 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices = GetIndicesForCommand(context_index); 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < indices.size(); ++i) { 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* tab = GetWebContentsAt(indices[i]); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab) { 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CoreTabHelperDelegate* core_delegate = 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CoreTabHelper::FromWebContents(tab)->delegate(); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!core_delegate || core_delegate->CanReloadContents(tab)) 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab->GetController().Reload(true); 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandDuplicate: { 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction(UserMetricsAction("TabContextMenu_Duplicate")); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices = GetIndicesForCommand(context_index); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the WebContents off as the indices will change as tabs are 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // duplicated. 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<WebContents*> tabs; 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < indices.size(); ++i) 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tabs.push_back(GetWebContentsAt(indices[i])); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < tabs.size(); ++i) { 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = GetIndexOfWebContents(tabs[i]); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != -1 && delegate_->CanDuplicateContentsAt(index)) 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->DuplicateContentsAt(index); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandCloseTab: { 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction(UserMetricsAction("TabContextMenu_CloseTab")); 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InternalCloseTabs(GetIndicesForCommand(context_index), 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLOSE_CREATE_HISTORICAL_TAB | CLOSE_USER_GESTURE); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandCloseOtherTabs: { 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction( 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserMetricsAction("TabContextMenu_CloseOtherTabs")); 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InternalCloseTabs(GetIndicesClosedByCommand(context_index, command_id), 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLOSE_CREATE_HISTORICAL_TAB); 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandCloseTabsToRight: { 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction( 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserMetricsAction("TabContextMenu_CloseTabsToRight")); 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InternalCloseTabs(GetIndicesClosedByCommand(context_index, command_id), 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CLOSE_CREATE_HISTORICAL_TAB); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandRestoreTab: { 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction(UserMetricsAction("TabContextMenu_RestoreTab")); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->RestoreTab(); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandTogglePinned: { 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction( 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserMetricsAction("TabContextMenu_TogglePinned")); 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices = GetIndicesForCommand(context_index); 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool pin = WillContextMenuPin(context_index); 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pin) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < indices.size(); ++i) { 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsAppTab(indices[i])) 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetTabPinned(indices[i], true); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unpin from the back so that the order is maintained (unpinning can 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // trigger moving a tab). 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = indices.size(); i > 0; --i) { 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsAppTab(indices[i - 1])) 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetTabPinned(indices[i - 1], false); 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandBookmarkAllTabs: { 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RecordAction( 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UserMetricsAction("TabContextMenu_BookmarkAllTabs")); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->BookmarkAllTabs(); 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandSelectByDomain: 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandSelectByOpener: { 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_id == CommandSelectByDomain) 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetIndicesWithSameDomain(context_index, &indices); 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetIndicesWithSameOpener(context_index, &indices); 9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel selection_model; 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model.SetSelectedIndex(context_index); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < indices.size(); ++i) 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model.AddIndexToSelection(indices[i]); 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetSelectionFromModel(selection_model); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<int> TabStripModel::GetIndicesClosedByCommand( 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContextMenuCommand id) const { 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ContainsIndex(index)); 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(id == CommandCloseTabsToRight || id == CommandCloseOtherTabs); 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_selected = IsTabSelected(index); 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int start; 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id == CommandCloseTabsToRight) { 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_selected) { 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start = selection_model_.selected_indices()[ 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.selected_indices().size() - 1] + 1; 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start = index + 1; 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start = 0; 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: callers expect the vector to be sorted in descending order. 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = count() - 1; i >= start; --i) { 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i != index && !IsMiniTab(i) && (!is_selected || !IsTabSelected(i))) 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) indices.push_back(i); 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return indices; 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::WillContextMenuPin(int index) { 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices = GetIndicesForCommand(index); 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If all tabs are pinned, then we unpin, otherwise we pin. 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool all_pinned = true; 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < indices.size() && all_pinned; ++i) { 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsAppTab(index)) // We never change app tabs. 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_pinned = IsTabPinned(indices[i]); 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !all_pinned; 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabStripModel, content::NotificationObserver implementation: 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::Observe(int type, 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case content::NOTIFICATION_WEB_CONTENTS_DESTROYED: { 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sometimes, on qemu, it seems like a WebContents object can be destroyed 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // while we still have a reference to it. We need to break this reference 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // here so we don't crash later. 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = GetIndexOfWebContents( 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<WebContents>(source).ptr()); 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != TabStripModel::kNoTab) { 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that we only detach the contents here, not close it - it's 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already been closed. We just want to undo our bookkeeping. 9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DetachWebContentsAt(index); 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::ContextMenuCommandToBrowserCommand(int cmd_id, 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* browser_cmd) { 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (cmd_id) { 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandNewTab: 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser_cmd = IDC_NEW_TAB; 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandReload: 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser_cmd = IDC_RELOAD; 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandDuplicate: 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser_cmd = IDC_DUPLICATE_TAB; 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandCloseTab: 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser_cmd = IDC_CLOSE_TAB; 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandRestoreTab: 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser_cmd = IDC_RESTORE_TAB; 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CommandBookmarkAllTabs: 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser_cmd = IDC_BOOKMARK_ALL_TABS; 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *browser_cmd = 0; 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TabStripModel, private: 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1024868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::vector<WebContents*> TabStripModel::GetWebContentsFromIndices( 1025868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const std::vector<int>& indices) const { 1026868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::vector<WebContents*> contents; 1027868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for (size_t i = 0; i < indices.size(); ++i) 1028868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) contents.push_back(GetWebContentsAtImpl(indices[i])); 1029868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return contents; 1030868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 1031868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::GetIndicesWithSameDomain(int index, 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int>* indices) { 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string domain = GetWebContentsAt(index)->GetURL().host(); 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (domain.empty()) 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < count(); ++i) { 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == index) 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetWebContentsAt(i)->GetURL().host() == domain) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) indices->push_back(i); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::GetIndicesWithSameOpener(int index, 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int>* indices) { 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* opener = contents_data_[index]->group; 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opener) { 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no group, find all tabs with the selected tab as the opener. 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) opener = GetWebContentsAt(index); 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!opener) 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < count(); ++i) { 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == index) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents_data_[i]->group == opener || 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetWebContentsAtImpl(i) == opener) { 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) indices->push_back(i); 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<int> TabStripModel::GetIndicesForCommand(int index) const { 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!IsTabSelected(index)) { 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int> indices; 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) indices.push_back(index); 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return indices; 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return selection_model_.selected_indices(); 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TabStripModel::IsNewTabAtEndOfTabStrip(WebContents* contents) const { 10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url = contents->GetURL(); 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return url.SchemeIs(chrome::kChromeUIScheme) && 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url.host() == chrome::kChromeUINewTabHost && 10772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents == GetWebContentsAtImpl(count() - 1) && 10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents->GetController().GetEntryCount() == 1; 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::InternalCloseTabs(const std::vector<int>& indices, 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 close_types) { 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (indices.empty()) 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1086868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CloseTracker close_tracker(GetWebContentsFromIndices(indices)); 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only try the fast shutdown path if the whole browser process is *not* 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutting down. Fast shutdown during browser termination is handled in 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // BrowserShutdown. 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_shutdown::GetShutdownType() == browser_shutdown::NOT_VALID) { 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Construct a map of processes to the number of associated tabs that are 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // closing. 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<content::RenderProcessHost*, size_t> processes; 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < indices.size(); ++i) { 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* closing_contents = GetWebContentsAtImpl(indices[i]); 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderProcessHost* process = 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closing_contents->GetRenderProcessHost(); 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++processes[process]; 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try to fast shutdown the tabs that can close. 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::map<content::RenderProcessHost*, size_t>::iterator iter = 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processes.begin(); iter != processes.end(); ++iter) { 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->first->FastShutdownForPageCount(iter->second); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We now return to our regularly scheduled shutdown procedure. 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool retval = true; 1111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) while (close_tracker.HasNext()) { 1112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) WebContents* closing_contents = close_tracker.Next(); 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = GetIndexOfWebContents(closing_contents); 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we still contain the tab. 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == kNoTab) 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CoreTabHelper* core_tab_helper = 11197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CoreTabHelper::FromWebContents(closing_contents); 11207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) core_tab_helper->OnCloseStarted(); 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the explicitly closed state. If the unload handlers cancel the 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // close the state is reset in Browser. We don't update the explicitly 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // closed state if already marked as explicitly closed as unload handlers 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // call back to this if the close is allowed. 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!closing_contents->GetClosedByUserGesture()) { 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) closing_contents->SetClosedByUserGesture( 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_types & CLOSE_USER_GESTURE); 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (delegate_->RunUnloadListenerBeforeClosing(closing_contents)) { 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retval = false; 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InternalCloseTab(closing_contents, index, 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (close_types & CLOSE_CREATE_HISTORICAL_TAB) != 0); 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return retval; 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::InternalCloseTab(WebContents* contents, 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index, 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool create_historical_tabs) { 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabClosingAt(this, contents, index)); 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ask the delegate to save an entry for this tab in the historical tab 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // database if applicable. 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (create_historical_tabs) 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_->CreateHistoricalTab(contents); 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deleting the WebContents will call back to us via 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NotificationObserver and detach it. 11562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete contents; 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WebContents* TabStripModel::GetWebContentsAtImpl(int index) const { 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(ContainsIndex(index)) << 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Failed to find: " << index << " in: " << count() << " entries."; 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return contents_data_[index]->contents; 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::NotifyIfTabDeactivated(WebContents* contents) { 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents) { 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabDeactivated(contents)); 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::NotifyIfActiveTabChanged(WebContents* old_contents, 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyTypes notify_types) { 11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* new_contents = GetWebContentsAtImpl(active_index()); 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_contents != new_contents) { 1176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int reason = notify_types == NOTIFY_USER_GESTURE 1177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ? TabStripModelObserver::CHANGE_REASON_USER_GESTURE 1178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : TabStripModelObserver::CHANGE_REASON_NONE; 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 1180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ActiveTabChanged(old_contents, 1181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new_contents, 1182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) active_index(), 1183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) reason)); 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Activating a discarded tab reloads it, so it is no longer discarded. 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_[active_index()]->discarded = false; 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::NotifyIfActiveOrSelectionChanged( 11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* old_contents, 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyTypes notify_types, 11922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ui::ListSelectionModel& old_model) { 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyIfActiveTabChanged(old_contents, notify_types); 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!selection_model().Equals(old_model)) { 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TabSelectionChanged(this, old_model)); 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::SetSelection( 12022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ui::ListSelectionModel& new_model, 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyTypes notify_types) { 12042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* old_contents = GetActiveWebContents(); 12052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ListSelectionModel old_model; 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_model.Copy(selection_model_); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_model.active() != selection_model_.active()) 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyIfTabDeactivated(old_contents); 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.Copy(new_model); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyIfActiveOrSelectionChanged(old_contents, notify_types, old_model); 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::SelectRelativeTab(bool next) { 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This may happen during automated testing or if a user somehow buffers 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // many key accelerators. 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents_data_.empty()) 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = active_index(); 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int delta = next ? 1 : -1; 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = (index + count() + delta) % count(); 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ActivateTabAt(index, true); 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabStripModel::MoveWebContentsAtImpl(int index, 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int to_position, 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool select_after_move) { 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContentsData* moved_data = contents_data_[index]; 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_.erase(contents_data_.begin() + index); 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_data_.insert(contents_data_.begin() + to_position, moved_data); 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.Move(index, to_position); 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!selection_model_.IsSelected(select_after_move) && select_after_move) { 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky): why doesn't this code notify observers? 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.SetSelectedIndex(to_position); 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FOR_EACH_OBSERVER(TabStripModelObserver, observers_, 12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabMoved(moved_data->contents, index, to_position)); 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::MoveSelectedTabsToImpl(int index, 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t start, 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t length) { 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(start < selection_model_.selected_indices().size() && 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start + length <= selection_model_.selected_indices().size()); 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t end = start + length; 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int count_before_index = 0; 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = start; i < end && 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.selected_indices()[i] < index + count_before_index; 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++i) { 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count_before_index++; 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First move those before index. Any tabs before index end up moving in the 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // selection model so we use start each time through. 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_index = index + count_before_index; 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t tab_index = start; 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (tab_index < end && 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selection_model_.selected_indices()[start] < index) { 12612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MoveWebContentsAt(selection_model_.selected_indices()[start], 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_index - 1, false); 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_index++; 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then move those after the index. These don't result in reordering the 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // selection. 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (tab_index < end) { 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (selection_model_.selected_indices()[tab_index] != target_index) { 12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MoveWebContentsAt(selection_model_.selected_indices()[tab_index], 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_index, false); 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_index++; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_index++; 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TabStripModel::OpenerMatches(const WebContentsData* data, 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* opener, 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_group) { 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return data->opener == opener || (use_group && data->group == opener); 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TabStripModel::ForgetOpenersAndGroupsReferencing( 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebContents* tab) { 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (WebContentsDataVector::const_iterator i = contents_data_.begin(); 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != contents_data_.end(); ++i) { 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*i)->group == tab) 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->group = NULL; 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*i)->opener == tab) 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->opener = NULL; 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1295