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)import uuid
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TabTracker(object):
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Uniquely track tabs within a window.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  This allows the creation of tabs whose indices can be
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  determined even after lower indexed tabs have been closed, therefore changing
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  that tab's index.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  This is accomplished via a containing window which is created and tracked via
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  the window's index. As a result of this, all calls to open and close tabs in
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this TabTracker's window must go through the appropriate instance of the
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabTracker. Also note that if a lower indexed window is closed after this
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TabTracker is instantiated, this TabTracker will lose track of its window
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, browser, visible=False):
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser: an instance of PyUITest
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visible: whether or not this TabTracker's window will be visible
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # A binary search tree would be faster, but this is easier to write.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # If this needs to become faster, understand that the important operations
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # here are append, arbitrary deletion and searching.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._uuids = [None]
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._window_idx = browser.GetBrowserWindowCount()
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._browser = browser
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    browser.OpenNewBrowserWindow(visible)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # We leave the 0'th tab empty to have something to close on __del__
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __del__(self):
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._browser.CloseBrowserWindow(self._window_idx)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def CreateTab(self, url='about:blank'):
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Create a tracked tab and return its uuid.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url: a URL to navigate to
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      a uuid uniquely identifying that tab within this TabTracker
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._browser.AppendTab(url, self._window_idx)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # We use uuids here rather than a monotonic integer to prevent confusion
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # with the tab index.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tab_uuid = uuid.uuid4()
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._uuids.append(tab_uuid)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return tab_uuid
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ReleaseTab(self, tab_uuid):
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Release and close a tab tracked by this TabTracker.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_uuid: the uuid of the tab to close
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    idx = self.GetTabIndex(tab_uuid)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._browser.CloseTab(tab_index=idx, windex=self._window_idx)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    del self._uuids[idx]
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetTabIndex(self, tab_uuid):
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Get the index of a tracked tab within this TabTracker's window.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tab_uuid: the uuid of the tab to close
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      the index of the tab within this TabTracker's window
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._uuids.index(tab_uuid)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def GetWindowIndex(self):
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Get the index of this TabTracker's window.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      the index of this TabTracker's window
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._window_idx
84