OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // This script is run multiple times with different configurations. The content |
| 6 // scripts need to determine synchronously which subtest is being run. This |
| 7 // state is communicated via the URL. |
| 8 var TEST_HOST = location.search.slice(1); |
| 9 chrome.test.assertTrue( |
| 10 TEST_HOST !== '', |
| 11 'The subtest type must be specified in the query string.'); |
| 12 |
| 13 var config; |
| 14 var tabId; |
| 15 |
| 16 function getTestUrl(page) { |
| 17 return 'http://' + TEST_HOST + ':' + config.testServer.port + |
| 18 '/extensions/api_test/executescript/destructive/' + page; |
| 19 } |
| 20 |
| 21 chrome.test.getConfig(function(config) { |
| 22 window.config = config; |
| 23 |
| 24 chrome.tabs.create({url: 'about:blank'}, function(tab) { |
| 25 tabId = tab.id; |
| 26 startTest(); |
| 27 }); |
| 28 }); |
| 29 |
| 30 function startTest() { |
| 31 // These tests load a page that contains a frame, where a content script will |
| 32 // be run (and remove the frame). The injection point depends on the URL: |
| 33 // - ?blankstart = Load a script in the blank frame at document_start. |
| 34 // - ?blankend = Load a script in the blank frame at document_end. |
| 35 // - ?start = Load a script in the non-blank frame at document_start. |
| 36 // - ?end = Load a script in the non-blank frame at document_end. |
| 37 |
| 38 var kEmptyHtmlBodyPattern = /<body><\/body>/; |
| 39 |
| 40 var allTests = [ |
| 41 // Empty document. |
| 42 function removeHttpFrameAtDocumentStart() { |
| 43 testRemoveSelf('empty_frame.html?start'); |
| 44 }, |
| 45 |
| 46 function removeHttpFrameAtDocumentEnd() { |
| 47 testRemoveSelf('empty_frame.html?end', kEmptyHtmlBodyPattern); |
| 48 }, |
| 49 |
| 50 // about:blank |
| 51 function removeAboutBlankAtDocumentStart() { |
| 52 testRemoveSelf('about_blank_frame.html?blankstart'); |
| 53 }, |
| 54 |
| 55 function removeAboutBlankAtDocumentEnd() { |
| 56 testRemoveSelf('about_blank_frame.html?blankend', kEmptyHtmlBodyPattern); |
| 57 }, |
| 58 |
| 59 // srcdoc frame with a HTML tag |
| 60 function removeAboutSrcdocHtmlAtDocumentStart() { |
| 61 testRemoveSelf('srcdoc_html_frame.html?blankstart'); |
| 62 }, |
| 63 |
| 64 function removeAboutSrcdocHtmlAtDocumentEnd() { |
| 65 testRemoveSelf('srcdoc_html_frame.html?blankend', /<br>/); |
| 66 }, |
| 67 |
| 68 // srcdoc frame with text |
| 69 function removeAboutSrcdocTextOnlyAtDocumentStart() { |
| 70 testRemoveSelf('srcdoc_text_frame.html?blankstart'); |
| 71 }, |
| 72 |
| 73 function removeAboutSrcdocTextOnlyAtDocumentEnd() { |
| 74 testRemoveSelf('srcdoc_text_frame.html?blankend', /text/); |
| 75 }, |
| 76 |
| 77 // <iframe></iframe> (no URL) |
| 78 function removeFrameWithoutUrlAtDocumentStart() { |
| 79 testRemoveSelf('no_url_frame.html?blankstart'); |
| 80 }, |
| 81 |
| 82 function removeFrameWithoutUrlAtDocumentEnd() { |
| 83 testRemoveSelf('no_url_frame.html?blankend', kEmptyHtmlBodyPattern); |
| 84 }, |
| 85 |
| 86 // An image. |
| 87 function removeImageAtDocumentStart() { |
| 88 testRemoveSelf('image_frame.html?start'); |
| 89 }, |
| 90 |
| 91 function removeImageAtDocumentEnd() { |
| 92 testRemoveSelf('image_frame.html?end', /<img/); |
| 93 }, |
| 94 |
| 95 // Audio (media). |
| 96 function removeAudioAtDocumentStart() { |
| 97 testRemoveSelf('audio_frame.html?start'); |
| 98 }, |
| 99 |
| 100 function removeAudioAtDocumentEnd() { |
| 101 testRemoveSelf('audio_frame.html?end', /<video.+ type="audio\//); |
| 102 }, |
| 103 |
| 104 // Video (media). |
| 105 function removeVideoAtDocumentStart() { |
| 106 testRemoveSelf('video_frame.html?start'); |
| 107 }, |
| 108 |
| 109 function removeVideoAtDocumentEnd() { |
| 110 testRemoveSelf('video_frame.html?end', /<video.+ type="video\//); |
| 111 }, |
| 112 |
| 113 // Plugins |
| 114 function removePluginAtDocumentStart() { |
| 115 if (maybeSkipPluginTest()) |
| 116 return; |
| 117 testRemoveSelf('plugin_frame.html?start'); |
| 118 }, |
| 119 |
| 120 function removePluginAtDocumentEnd() { |
| 121 if (maybeSkipPluginTest()) |
| 122 return; |
| 123 testRemoveSelf('plugin_frame.html?end', /<embed/); |
| 124 }, |
| 125 |
| 126 // Plain text |
| 127 function removePlainTextAtDocumentStart() { |
| 128 testRemoveSelf('txt_frame.html?start'); |
| 129 }, |
| 130 |
| 131 function removePlainTextAtDocumentEnd() { |
| 132 testRemoveSelf('txt_frame.html?end', /<pre/); |
| 133 }, |
| 134 |
| 135 // XHTML |
| 136 function removeXhtmlAtDocumentStart() { |
| 137 testRemoveSelf( |
| 138 'xhtml_frame.html?start', |
| 139 /<html xmlns="http:\/\/www\.w3\.org\/1999\/xhtml"><\/html>/); |
| 140 }, |
| 141 |
| 142 function removeXhtmlAtDocumentEnd() { |
| 143 testRemoveSelf( |
| 144 'xhtml_frame.html?end', |
| 145 /<html xmlns="http:\/\/www\.w3\.org\/1999\/xhtml">/); |
| 146 }, |
| 147 |
| 148 // XML |
| 149 function removeXmlAtDocumentStart() { |
| 150 testRemoveSelf('xml_frame.html?start', /<root\/>/); |
| 151 }, |
| 152 |
| 153 function removeXmlAtDocumentEnd() { |
| 154 testRemoveSelf('xml_frame.html?end', /<root><child\/><\/root>/); |
| 155 }, |
| 156 ]; |
| 157 |
| 158 // Parameters defined in execute_script_apitest.cc. |
| 159 var testParams = new URLSearchParams(location.hash.slice(1)); |
| 160 var kBucketCount = parseInt(testParams.get('bucketcount')); |
| 161 var kBucketIndex = parseInt(testParams.get('bucketindex')); |
| 162 var kTestsPerBucket = Math.ceil(allTests.length / kBucketCount); |
| 163 |
| 164 chrome.test.assertTrue(kBucketCount * kTestsPerBucket >= allTests.length, |
| 165 'To cover all tests, the number of buckets multiplied by the number of ' + |
| 166 'tests per bucket must be at least as big as the number of tests.'); |
| 167 chrome.test.assertTrue(0 <= kBucketIndex >= 0 && kBucketIndex < kBucketCount, |
| 168 'There are only ' + kBucketCount + ' buckets, so the bucket index must ' + |
| 169 'be between 0 and ' + kBucketCount + ', but it was ' + kBucketIndex); |
| 170 |
| 171 // Every run except for the last run contains |kTestsPerBucket| tests. The |
| 172 // last run (i.e. |kBucketIndex| = |kBucketCount| - 1) may contain fewer tests |
| 173 // if there are not enough remaining tests, since the total number of tests is |
| 174 // not necessarily divisible by |kTestsPerBucket|. |
| 175 var filteredTests = |
| 176 allTests.slice(kBucketIndex * kTestsPerBucket).slice(0, kTestsPerBucket); |
| 177 |
| 178 // At the document_end stage, the parser will not modify the DOM any more, so |
| 179 // we can skip those tests that wait for DOM mutations to save time. |
| 180 if (TEST_HOST.startsWith('dom')) { |
| 181 filteredTests = filteredTests.filter(function(testfn) { |
| 182 // Omit the *Documentend tests = keep the *DocumentStart tests. |
| 183 return !testfn.name.endsWith('DocumentEnd'); |
| 184 }); |
| 185 } |
| 186 chrome.test.runTests(filteredTests); |
| 187 } |
| 188 |
| 189 // |page| must be an existing page in this directory, and the URL must be |
| 190 // matched by one content script. Otherwise the test will time out. |
| 191 // |
| 192 // If the regular expression |pattern| is specified, then the serialization of |
| 193 // the frame content must match the pattern. This ensures that the tests are |
| 194 // still testing the expected document in the future. |
| 195 function testRemoveSelf(page, pattern) { |
| 196 // By default, the serialization of the document must be non-empty. |
| 197 var kDefaultPattern = /</; |
| 198 |
| 199 if (page.includes('start')) { |
| 200 pattern = pattern || /^<html><\/html>$/; |
| 201 pattern = TEST_HOST === 'synchronous' ? pattern : kDefaultPattern; |
| 202 } else if (page.includes('end')) { |
| 203 pattern = pattern || kDefaultPattern; |
| 204 } else { |
| 205 chrome.test.fail('URL must contain "start" or "end": ' + page); |
| 206 } |
| 207 |
| 208 chrome.test.listenOnce(chrome.runtime.onMessage, function(msg, sender) { |
| 209 chrome.test.assertEq(tabId, sender.tab && sender.tab.id); |
| 210 chrome.test.assertEq(0, sender.frameId); |
| 211 |
| 212 var frameHTML = msg.frameHTML; |
| 213 delete msg.frameHTML; |
| 214 chrome.test.assertEq({frameCount: 0}, msg); |
| 215 |
| 216 chrome.test.assertTrue( |
| 217 pattern.test(frameHTML), |
| 218 'The pattern ' + pattern + ' should be matched by: ' + frameHTML); |
| 219 }); |
| 220 chrome.tabs.update(tabId, {url: getTestUrl(page)}); |
| 221 } |
| 222 |
| 223 // The plugin test requires a plugin to be installed. Skip the test if plugins |
| 224 // are not supported. |
| 225 function maybeSkipPluginTest() { |
| 226 // This MIME-type should be handled by a browser plugin. |
| 227 var kPluginMimeType = 'application/pdf'; |
| 228 for (var i = 0; i < navigator.plugins.length; ++i) { |
| 229 var plugin = navigator.plugins[i]; |
| 230 for (var j = 0; j < plugin.length; ++j) { |
| 231 var mimeType = plugin[j]; |
| 232 if (mimeType.type === kPluginMimeType) |
| 233 return false; |
| 234 } |
| 235 } |
| 236 var kMessage = 'Plugin not found for ' + kPluginMimeType + ', skipping test.'; |
| 237 console.log(kMessage); |
| 238 chrome.test.log(kMessage); |
| 239 chrome.test.succeed(); |
| 240 return true; |
| 241 } |
OLD | NEW |