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