15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2011 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)This module is a simple qa tool that installs extensions and tests whether the
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)browser crashes while visiting a list of urls.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Usage: python extensions.py -v
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Note: This assumes that there is a directory of extensions called
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)'extensions-tool' and that there is a file of newline-separated urls to visit
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)called 'urls.txt' in the data directory.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import glob
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import pyauto_functional # must be imported before pyauto
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import pyauto
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionsPage(object):
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Access options in extensions page (chrome://extensions-frame)."""
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  _URL = 'chrome://extensions-frame'
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def __init__(self, driver):
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._driver = driver
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._driver.get(ExtensionsPage._URL)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def CheckExtensionVisible(self, ext_id):
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Returns True if |ext_id| exists on page."""
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return len(self._driver.find_elements_by_id(ext_id)) == 1
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SetEnabled(self, ext_id, enabled):
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Clicks on 'Enabled' checkbox for specified extension.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ext_id: Extension ID to be enabled or disabled.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      enabled: Boolean indicating whether |ext_id| is to be enabled or disabled.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    checkbox = self._driver.find_element_by_xpath(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '//*[@id="%s"]//*[@class="enable-controls"]//*[@type="checkbox"]' %
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ext_id)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if checkbox != enabled:
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      checkbox.click()
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Reload page to ensure that the UI is recreated.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._driver.get(ExtensionsPage._URL)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SetAllowInIncognito(self, ext_id, allowed):
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Clicks on 'Allow in incognito' checkbox for specified extension.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ext_id: Extension ID to be enabled or disabled.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allowed: Boolean indicating whether |ext_id| is to be allowed or
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          disallowed in incognito.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    checkbox = self._driver.find_element_by_xpath(
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '//*[@id="%s"]//*[@class="incognito-control"]//*[@type="checkbox"]' %
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ext_id)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if checkbox.is_selected() != allowed:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      checkbox.click()
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Reload page to ensure that the UI is recreated.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self._driver.get(ExtensionsPage._URL)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def SetAllowAccessFileURLs(self, ext_id, allowed):
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Clicks on 'Allow access to file URLs' checkbox for specified extension.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ext_id: Extension ID to be enabled or disabled.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      allowed: Boolean indicating whether |ext_id| is to be allowed access to
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          file URLs.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    checkbox = self._driver.find_element_by_xpath(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '//*[@id="%s"]//*[@class="file-access-control"]//*[@type="checkbox"]' %
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ext_id)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if checkbox.is_selected() != allowed:
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      checkbox.click()
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionsTest(pyauto.PyUITest):
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  """Test of extensions."""
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def Debug(self):
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Test method for experimentation.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This method is not run automatically.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while True:
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      raw_input('Interact with the browser and hit <enter> to dump history.')
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      print '*' * 20
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      self.pprint(self.GetExtensionsInfo())
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GetInstalledExtensionIds(self):
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return [extension['id'] for extension in self.GetExtensionsInfo()]
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _ReturnCrashingExtensions(self, extensions, group_size, top_urls):
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Returns the group of extensions that crashes (if any).
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Install the given extensions in groups of group_size and return the
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group of extensions that crashes (if any).
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extensions: A list of extensions to install.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      group_size: The number of extensions to install at one time.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      top_urls: The list of top urls to visit.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      The extensions in the crashing group or None if there is no crash.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    curr_extension = 0
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_extensions = len(extensions)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.RestartBrowser()
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    orig_extension_ids = self._GetInstalledExtensionIds()
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while curr_extension < num_extensions:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      logging.debug('New group of %d extensions.', group_size)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      group_end = curr_extension + group_size
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for extension in extensions[curr_extension:group_end]:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        logging.debug('Installing extension: %s', extension)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.InstallExtension(extension)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for url in top_urls:
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.NavigateToURL(url)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      def _LogAndReturnCrashing():
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        crashing_extensions = extensions[curr_extension:group_end]
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        logging.debug('Crashing extensions: %s', crashing_extensions)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return crashing_extensions
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      # If the browser has crashed, return the extensions in the failing group.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      try:
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_browser_windows = self.GetBrowserWindowCount()
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      except:
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return _LogAndReturnCrashing()
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else:
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not num_browser_windows:
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return _LogAndReturnCrashing()
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          # Uninstall all extensions that aren't installed by default.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new_extension_ids = [id for id in self._GetInstalledExtensionIds()
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               if id not in orig_extension_ids]
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          for extension_id in new_extension_ids:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.UninstallExtensionById(extension_id)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      curr_extension = group_end
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # None of the extensions crashed.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _GetExtensionInfoById(self, extensions, id):
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for x in extensions:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if x['id'] == id:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return x
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def ExtensionCrashes(self):
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Add top extensions; confirm browser stays up when visiting top urls."""
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # TODO: provide a way in pyauto to pass args to a test - take these as args
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions_dir = os.path.join(self.DataDir(), 'extensions-tool')
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    urls_file = os.path.join(self.DataDir(), 'urls.txt')
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_msg = 'The dir "%s" must exist' % os.path.abspath(extensions_dir)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert os.path.exists(extensions_dir), error_msg
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_msg = 'The file "%s" must exist' % os.path.abspath(urls_file)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert os.path.exists(urls_file), error_msg
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_urls_to_visit = 100
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions_group_size = 20
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    top_urls = [l.rstrip() for l in
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                open(urls_file).readlines()[:num_urls_to_visit]]
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    failed_extensions = glob.glob(os.path.join(extensions_dir, '*.crx'))
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    group_size = extensions_group_size
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (group_size and failed_extensions):
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      failed_extensions = self._ReturnCrashingExtensions(
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          failed_extensions, group_size, top_urls)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      group_size = group_size // 2
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertFalse(failed_extensions,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     'Extension(s) in failing group: %s' % failed_extensions)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _InstallExtensionCheckDefaults(self, crx_file):
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Installs extension at extensions/|crx_file| and checks default status.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Checks that the installed extension is enabled and not allowed in incognito.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      crx_file: Relative path from self.DataDir()/extensions to .crx extension
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                to be installed.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      The extension ID.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crx_file_path = os.path.abspath(
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        os.path.join(self.DataDir(), 'extensions', crx_file))
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_id = self.InstallExtension(crx_file_path)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension = self._GetExtensionInfoById(self.GetExtensionsInfo(), ext_id)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(extension['is_enabled'],
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    msg='Extension was not enabled on installation')
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertFalse(extension['allowed_in_incognito'],
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     msg='Extension was allowed in incognito on installation.')
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ext_id
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _ExtensionValue(self, ext_id, key):
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Returns the value of |key| for |ext_id|.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ext_id: The extension ID.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key: The key for which the extensions info value is required.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      The value of extensions info |key| for |ext_id|.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return self._GetExtensionInfoById(self.GetExtensionsInfo(), ext_id)[key]
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def _FileAccess(self, ext_id):
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Returns the value of newAllowFileAccess for |ext_id|.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Args:
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ext_id: The extension ID.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Returns:
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      The value of extensions settings newAllowFileAccess for |ext_id|.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_settings = self.GetPrefsInfo().Prefs()['extensions']['settings']
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return extension_settings[ext_id]['newAllowFileAccess']
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testGetExtensionPermissions(self):
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Ensures we can retrieve the host/api permissions for an extension.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    This test assumes that the 'Bookmark Manager' extension exists in a fresh
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    profile.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions_info = self.GetExtensionsInfo()
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bm_exts = [x for x in extensions_info if x['name'] == 'Bookmark Manager']
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(bm_exts,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    msg='Could not find info for the Bookmark Manager '
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'extension.')
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext = bm_exts[0]
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    permissions_host = ext['host_permissions']
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(len(permissions_host) == 2 and
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'chrome://favicon/*' in permissions_host and
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'chrome://resources/*' in permissions_host,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    msg='Unexpected host permissions information.')
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    permissions_api = ext['api_permissions']
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print permissions_api
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    self.assertTrue(len(permissions_api) == 5 and
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'bookmarks' in permissions_api and
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'bookmarkManagerPrivate' in permissions_api and
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    'metricsPrivate' in permissions_api and
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'systemPrivate' in permissions_api and
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'tabs' in permissions_api,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    msg='Unexpected API permissions information.')
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testDisableEnableExtension(self):
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Tests that an extension can be disabled and enabled with the UI."""
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_id = self._InstallExtensionCheckDefaults('good.crx')
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Disable extension.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    driver = self.NewWebDriver()
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_page = ExtensionsPage(driver)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(ext_page.CheckExtensionVisible, args=[ext_id])
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_page.SetEnabled(ext_id, False)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(self._ExtensionValue, args=[ext_id, 'is_enabled'],
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   expect_retval=False)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertFalse(self._ExtensionValue(ext_id, 'is_enabled'),
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     msg='Extension did not get disabled.')
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Enable extension.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(ext_page.CheckExtensionVisible, args=[ext_id])
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_page.SetEnabled(ext_id, True)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(self._ExtensionValue, args=[ext_id, 'is_enabled'],
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   expect_retval=True)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(self._ExtensionValue(ext_id, 'is_enabled'),
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    msg='Extension did not get enabled.')
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testAllowIncognitoExtension(self):
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Tests allowing and disallowing an extension in incognito mode."""
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_id = self._InstallExtensionCheckDefaults('good.crx')
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Allow in incognito.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    driver = self.NewWebDriver()
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_page = ExtensionsPage(driver)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(ext_page.CheckExtensionVisible, args=[ext_id])
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_page.SetAllowInIncognito(ext_id, True)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Check extension now allowed in incognito.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(self._ExtensionValue, args=[ext_id, 'allowed_in_incognito'],
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   expect_retval=True)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(self._ExtensionValue(ext_id, 'allowed_in_incognito'),
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    msg='Extension did not get allowed in incognito.')
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Disallow in incognito.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(ext_page.CheckExtensionVisible, args=[ext_id])
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_page.SetAllowInIncognito(ext_id, False)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Check extension now disallowed in incognito.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(self._ExtensionValue, args=[ext_id, 'allowed_in_incognito'],
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   expect_retval=False)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertFalse(self._ExtensionValue(ext_id, 'allowed_in_incognito'),
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     msg='Extension did not get disallowed in incognito.')
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  def testAllowAccessFileURLs(self):
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Tests disallowing and allowing and extension access to file URLs."""
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_id = self._InstallExtensionCheckDefaults(os.path.join('permissions',
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                              'files'))
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Check extension allowed access to file URLs by default.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_settings = self.GetPrefsInfo().Prefs()['extensions']['settings']
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(extension_settings[ext_id]['newAllowFileAccess'],
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    msg='Extension was not allowed access to file URLs on '
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    'installation')
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Disallow access to file URLs.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    driver = self.NewWebDriver()
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_page = ExtensionsPage(driver)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(ext_page.CheckExtensionVisible, args=[ext_id])
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_page.SetAllowAccessFileURLs(ext_id, False)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Check that extension does not have access to file URLs.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(self._FileAccess, args=[ext_id], expect_retval=False)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertFalse(self._FileAccess(ext_id),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     msg='Extension did not have access to file URLs denied.')
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Allow access to file URLs.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(ext_page.CheckExtensionVisible, args=[ext_id])
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ext_page.SetAllowAccessFileURLs(ext_id, True)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Check that extension now has access to file URLs.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.WaitUntil(self._FileAccess, args=[ext_id], expect_retval=True)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    self.assertTrue(self._FileAccess(ext_id),
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    msg='Extension did not have access to file URLs granted.')
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pyauto_functional.Main()
347