Home | History | Annotate | Download | only in functional
      1 #!/usr/bin/env python
      2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import logging
      7 import os
      8 
      9 import pyauto_functional  # Must be imported before pyauto
     10 import pyauto
     11 import test_utils
     12 
     13 class SpecialTabsTest(pyauto.PyUITest):
     14   """TestCase for Special Tabs like about:version, chrome://history, etc."""
     15 
     16   @staticmethod
     17   def GetSpecialAcceleratorTabs():
     18     """Get a dict of accelerators and corresponding tab titles."""
     19     ret = {
     20         pyauto.IDC_SHOW_HISTORY: 'History',
     21         pyauto.IDC_MANAGE_EXTENSIONS: 'Extensions',
     22         pyauto.IDC_SHOW_DOWNLOADS: 'Downloads',
     23     }
     24     return ret
     25 
     26   special_url_redirects = {
     27    'about:': 'chrome://version',
     28    'about:about': 'chrome://about',
     29    'about:appcache-internals': 'chrome://appcache-internals',
     30    'about:credits': 'chrome://credits',
     31    'about:dns': 'chrome://dns',
     32    'about:histograms': 'chrome://histograms',
     33    'about:plugins': 'chrome://plugins',
     34    'about:sync': 'chrome://sync-internals',
     35    'about:sync-internals': 'chrome://sync-internals',
     36    'about:version': 'chrome://version',
     37   }
     38 
     39   special_url_tabs = {
     40     'chrome://about': { 'title': 'Chrome URLs' },
     41     'chrome://appcache-internals': { 'title': 'AppCache Internals' },
     42     'chrome://blob-internals': { 'title': 'Blob Storage Internals' },
     43     'chrome://feedback': {},
     44     'chrome://chrome-urls': { 'title': 'Chrome URLs' },
     45     'chrome://crashes': { 'title': 'Crashes' },
     46     'chrome://credits': { 'title': 'Credits' },
     47     'chrome://downloads': { 'title': 'Downloads' },
     48     'chrome://dns': { 'title': 'About DNS' },
     49     'chrome://extensions': { 'title': 'Extensions' },
     50     'chrome://flags': {},
     51     'chrome://flash': {},
     52     'chrome://gpu-internals': {},
     53     'chrome://histograms': { 'title': 'About Histograms' },
     54     'chrome://history': { 'title': 'History' },
     55     'chrome://inspect': { 'title': 'Inspect with Chrome Developer Tools' },
     56     'chrome://media-internals': { 'title': 'Media Internals' },
     57     'chrome://memory-redirect': { 'title': 'About Memory' },
     58     'chrome://net-internals': {},
     59     'chrome://net-internals/help.html': {},
     60     'chrome://newtab': { 'title': 'New Tab', 'CSP': False },
     61     'chrome://plugins': { 'title': 'Plug-ins' },
     62     'chrome://settings': { 'title': 'Settings' },
     63     'chrome://settings/autofill': { 'title': 'Settings - Autofill settings' },
     64     'chrome://settings/clearBrowserData':
     65       { 'title': 'Settings - Clear browsing data' },
     66     'chrome://settings/content': { 'title': 'Settings - Content settings' },
     67     'chrome://settings/languages':
     68       { 'title': 'Settings - Languages' },
     69     'chrome://settings/passwords': { 'title': 'Settings - Passwords' },
     70     'chrome://stats': {},
     71     'chrome://sync': { 'title': 'Sync Internals' },
     72     'chrome://sync-internals': { 'title': 'Sync Internals' },
     73     'chrome://terms': {},
     74     'chrome://version': { 'title': 'About Version' },
     75     'chrome://view-http-cache': {},
     76     'chrome://webrtc-internals': { 'title': 'WebRTC Internals' },
     77   }
     78   broken_special_url_tabs = {
     79     # crashed under debug when invoked from location bar (bug 88223).
     80     'chrome://devtools': { 'CSP': False },
     81 
     82     # returns "not available" despite having an URL constant.
     83     'chrome://dialog': { 'CSP': False },
     84 
     85     # separate window on mac, PC untested, not implemented elsewhere.
     86     'chrome://ipc': { 'CSP': False },
     87 
     88     # race against redirects via meta-refresh.
     89     'chrome://memory': { 'CSP': False },
     90   }
     91 
     92   chromeos_special_url_tabs = {
     93     'chrome://choose-mobile-network': { 'title': 'undefined', 'CSP': True },
     94     'chrome://flags': { 'CSP': True },
     95     'chrome://imageburner': { 'title':'Create a Recovery Media', 'CSP': True },
     96     'chrome://keyboardoverlay': { 'title': 'Keyboard Overlay', 'CSP': True },
     97     'chrome://network': { 'title': 'About Network' },
     98     'chrome://os-credits': { 'title': 'Credits', 'CSP': False },
     99     'chrome://proxy-settings': { 'CSP': False },
    100     'chrome://register': { 'CSP': False },
    101     'chrome://settings/languages':
    102       { 'title': 'Settings - Languages and input' },
    103     'chrome://sim-unlock': { 'title': 'Enter SIM card PIN', 'CSP': False },
    104     'chrome://system': { 'title': 'About System', 'CSP': False },
    105 
    106     # OVERRIDE - title and page different on CrOS
    107     'chrome://settings/accounts': { 'title': 'Settings - Users' },
    108   }
    109   broken_chromeos_special_url_tabs = {
    110     # returns "not available" page on chromeos=1 linux but has an URL constant.
    111     'chrome://activationmessage': { 'CSP': False },
    112     'chrome://cloudprintresources': { 'CSP': False },
    113     'chrome://cloudprintsetup': { 'CSP': False },
    114     'chrome://collected-cookies': { 'CSP': False },
    115     'chrome://constrained-test': { 'CSP': False },
    116     'chrome://enterprise-enrollment': { 'CSP': False },
    117     'chrome://http-auth': { 'CSP': False },
    118     'chrome://login-container': { 'CSP': False },
    119     'chrome://media-player': { 'CSP': False },
    120     'chrome://screenshots': { 'CSP': False },
    121     'chrome://slideshow': { 'CSP': False },
    122     'chrome://syncresources': { 'CSP': False },
    123     'chrome://theme': { 'CSP': False },
    124     'chrome://view-http-cache': { 'CSP': False },
    125 
    126     # crashes on chromeos=1 on linux, possibly missing real CrOS features.
    127     'chrome://cryptohome': { 'CSP': False},
    128     'chrome://mobilesetup': { 'CSP': False },
    129     'chrome://print': { 'CSP': False },
    130   }
    131 
    132   linux_special_url_tabs = {
    133     'chrome://linux-proxy-config': { 'title': 'Proxy Configuration Help' },
    134     'chrome://tcmalloc': { 'title': 'tcmalloc stats' },
    135     'chrome://sandbox': { 'title': 'Sandbox Status' },
    136   }
    137   broken_linux_special_url_tabs = {}
    138 
    139   mac_special_url_tabs = {
    140     'chrome://settings/languages': { 'title': 'Settings - Languages' },
    141   }
    142   broken_mac_special_url_tabs = {}
    143 
    144   win_special_url_tabs = {
    145     'chrome://conflicts': {},
    146   }
    147   broken_win_special_url_tabs = {
    148     # Sync on windows badly broken at the moment.
    149     'chrome://sync': {},
    150   }
    151 
    152   google_special_url_tabs = {
    153     # OVERRIDE - different title for Google Chrome vs. Chromium.
    154     'chrome://terms': {
    155       'title': 'Google Chrome Terms of Service',
    156     },
    157   }
    158   broken_google_special_url_tabs = {}
    159 
    160   google_chromeos_special_url_tabs = {
    161     # OVERRIDE - different title for Google Chrome OS vs. Chromium OS.
    162     'chrome://terms': {
    163       'title': 'Google Chrome OS Terms',
    164     },
    165   }
    166   broken_google_chromeos_special_url_tabs = {}
    167 
    168   google_win_special_url_tabs = {}
    169   broken_google_win_special_url_tabs = {}
    170 
    171   google_mac_special_url_tabs = {}
    172   broken_google_mac_special_url_tabs = {}
    173 
    174   google_linux_special_url_tabs = {}
    175   broken_google_linux_special_url_tabs = {}
    176 
    177   def _VerifyAppCacheInternals(self):
    178     """Confirm about:appcache-internals contains expected content for Caches.
    179        Also confirms that the about page populates Application Caches."""
    180     # Navigate to html page to activate DNS prefetching.
    181     self.NavigateToURL('http://futtta.be/html5/offline.php')
    182     # Wait for page to load and display sucess or fail message.
    183     self.WaitUntil(
    184         lambda: self.GetDOMValue('document.getElementById("status").innerHTML'),
    185                                  expect_retval='cached')
    186     self.TabGoBack()
    187     test_utils.StringContentCheck(
    188         self, self.GetTabContents(),
    189         ['Manifest',
    190          'http://futtta.be/html5/manifest.php'],
    191         [])
    192 
    193   def _VerifyAboutDNS(self):
    194     """Confirm about:dns contains expected content related to DNS info.
    195        Also confirms that prefetching DNS records propogate."""
    196     # Navigate to a page to activate DNS prefetching.
    197     self.NavigateToURL('http://www.google.com')
    198     self.TabGoBack()
    199     test_utils.StringContentCheck(self, self.GetTabContents(),
    200                                   ['Host name', 'How long ago', 'Motivation'],
    201                                   [])
    202 
    203   def _GetPlatformSpecialURLTabs(self):
    204     tabs = self.special_url_tabs.copy()
    205     broken_tabs = self.broken_special_url_tabs.copy()
    206     if self.IsChromeOS():
    207       tabs.update(self.chromeos_special_url_tabs)
    208       broken_tabs.update(self.broken_chromeos_special_url_tabs)
    209     elif self.IsLinux():
    210       tabs.update(self.linux_special_url_tabs)
    211       broken_tabs.update(self.broken_linux_special_url_tabs)
    212     elif self.IsMac():
    213       tabs.update(self.mac_special_url_tabs)
    214       broken_tabs.update(self.broken_mac_special_url_tabs)
    215     elif self.IsWin():
    216       tabs.update(self.win_special_url_tabs)
    217       broken_tabs.update(self.broken_win_special_url_tabs)
    218     for key, value in broken_tabs.iteritems():
    219       if key in tabs:
    220        del tabs[key]
    221     broken_tabs = {}
    222     if self.GetBrowserInfo()['properties']['branding'] == 'Google Chrome':
    223       tabs.update(self.google_special_url_tabs)
    224       broken_tabs.update(self.broken_google_special_url_tabs)
    225       if self.IsChromeOS():
    226         tabs.update(self.google_chromeos_special_url_tabs)
    227         broken_tabs.update(self.broken_google_chromeos_special_url_tabs)
    228       elif self.IsLinux():
    229         tabs.update(self.google_linux_special_url_tabs)
    230         broken_tabs.update(self.broken_google_linux_special_url_tabs)
    231       elif self.IsMac():
    232         tabs.update(self.google_mac_special_url_tabs)
    233         broken_tabs.update(self.broken_google_mac_special_url_tabs)
    234       elif self.IsWin():
    235         tabs.update(self.google_win_special_url_tabs)
    236         broken_tabs.update(self.broken_google_win_special_url_tabs)
    237       for key, value in broken_tabs.iteritems():
    238         if key in tabs:
    239          del tabs[key]
    240     return tabs
    241 
    242   def testSpecialURLRedirects(self):
    243     """Test that older about: URLs are implemented by newer chrome:// URLs.
    244        The location bar may not get updated in all cases, so checking the
    245        tab URL is misleading, instead check for the same contents as the
    246        chrome:// page."""
    247     tabs = self._GetPlatformSpecialURLTabs()
    248     for url, redirect in self.special_url_redirects.iteritems():
    249       if redirect in tabs:
    250         logging.debug('Testing redirect from %s to %s.' % (url, redirect))
    251         self.NavigateToURL(url)
    252         self.assertEqual(self.special_url_tabs[redirect]['title'],
    253                          self.GetActiveTabTitle())
    254 
    255   def testSpecialURLTabs(self):
    256     """Test special tabs created by URLs like chrome://downloads,
    257        chrome://settings/extensionSettings, chrome://history etc.
    258        Also ensures they specify content-security-policy and not inline
    259        scripts for those pages that are expected to do so.  Patches which
    260        break this test by including new inline javascript are security
    261        vulnerabilities and should be reverted."""
    262     tabs = self._GetPlatformSpecialURLTabs()
    263     for url, properties in tabs.iteritems():
    264       logging.debug('Testing URL %s.' % url)
    265       self.NavigateToURL(url)
    266       expected_title = 'title' in properties and properties['title'] or url
    267       actual_title = self.GetActiveTabTitle()
    268       self.assertTrue(self.WaitUntil(
    269           lambda: self.GetActiveTabTitle(), expect_retval=expected_title),
    270           msg='Title did not match for %s. Expected: %s. Got %s' % (
    271               url, expected_title, self.GetActiveTabTitle()))
    272       include_list = []
    273       exclude_list = []
    274       no_csp = 'CSP' in properties and not properties['CSP']
    275       if no_csp:
    276         exclude_list.extend(['Content-Security-Policy'])
    277       else:
    278         exclude_list.extend(['<script>', 'onclick=', 'onload=',
    279                              'onchange=', 'onsubmit=', 'javascript:'])
    280       if 'includes' in properties:
    281         include_list.extend(properties['includes'])
    282       if 'excludes' in properties:
    283         exclude_list.extend(properties['exlcudes'])
    284       test_utils.StringContentCheck(self, self.GetTabContents(),
    285                                     include_list, exclude_list)
    286       result = self.ExecuteJavascript("""
    287           var r = 'blocked';
    288           var f = 'executed';
    289           var s = document.createElement('script');
    290           s.textContent = 'r = f';
    291           document.body.appendChild(s);
    292           window.domAutomationController.send(r);
    293         """)
    294       logging.debug('has csp %s, result %s.' % (not no_csp, result))
    295       if no_csp:
    296         self.assertEqual(result, 'executed',
    297                          msg='Got %s for %s' % (result, url))
    298       else:
    299         self.assertEqual(result, 'blocked',
    300                          msg='Got %s for %s' % (result, url))
    301 
    302       # Restart browser so that every URL gets a fresh instance.
    303       self.RestartBrowser(clear_profile=True)
    304 
    305   def testAboutAppCacheTab(self):
    306     """Test App Cache tab to confirm about page populates caches."""
    307     self.NavigateToURL('about:appcache-internals')
    308     self._VerifyAppCacheInternals()
    309     self.assertEqual('AppCache Internals', self.GetActiveTabTitle())
    310 
    311   def testAboutDNSTab(self):
    312     """Test DNS tab to confirm DNS about page propogates records."""
    313     self.NavigateToURL('about:dns')
    314     self._VerifyAboutDNS()
    315     self.assertEqual('About DNS', self.GetActiveTabTitle())
    316 
    317   def testSpecialAcceratorTabs(self):
    318     """Test special tabs created by accelerators."""
    319     for accel, title in self.GetSpecialAcceleratorTabs().iteritems():
    320       self.RunCommand(accel)
    321       self.assertTrue(self.WaitUntil(
    322             self.GetActiveTabTitle, expect_retval=title),
    323           msg='Expected "%s", got "%s"' % (title, self.GetActiveTabTitle()))
    324 
    325 
    326 if __name__ == '__main__':
    327   pyauto_functional.Main()
    328