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