Chromium Code Reviews| Index: chrome/test/data/extensions/api_test/executescript/destructive/remove_self.js |
| diff --git a/chrome/test/data/extensions/api_test/executescript/destructive/remove_self.js b/chrome/test/data/extensions/api_test/executescript/destructive/remove_self.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e40f2922af79f727b97157da7db6704079bdadaa |
| --- /dev/null |
| +++ b/chrome/test/data/extensions/api_test/executescript/destructive/remove_self.js |
| @@ -0,0 +1,93 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +if (top === window) { |
| + testTop(); |
| +} else if (!parent.location.search.includes('end') || |
| + window.didRunAtDocumentEnd) { |
| + testChild(); |
| +} |
| + |
| +function testTop() { |
| + var testMessage = {}; |
| + function reportFrames() { |
| + testMessage.frameCount = frames.length; |
| + testMessage.frameHTML = window.frameHTML; |
| + chrome.runtime.sendMessage(testMessage); |
| + } |
| + |
| + if (window.frameHTML) { // Set by child frame... |
| + // about:blank frames are synchronously parsed, so their document_end script |
| + // injection happens before the main frame's injection. |
| + var expectChildBeforeMain = location.search.includes('?blankend'); |
| + if (!expectChildBeforeMain) { |
| + // Add a message to the test notification to cause the test to fail, |
| + // with some useful information for diagnostics. |
| + testMessage.warning = 'Content script in child frame was executed ' + |
| + 'before the main frame\'s content script!'; |
| + } |
| + reportFrames(); |
| + } else { |
| + window.frameHTML = '(not set)'; |
| + window.onmessage = function(event) { |
| + chrome.test.assertEq('toBeRemoved', event.data); |
| + reportFrames(); |
| + }; |
| + } |
| +} |
| + |
| +function testChild() { |
| + var TEST_HOST = parent.location.hostname; |
| + |
| + if (TEST_HOST === 'synchronous') { |
| + doRemove(); |
| + } else if (TEST_HOST === 'microtask') { |
| + Promise.resolve().then(doRemove); |
| + } else if (TEST_HOST === 'macrotask') { |
| + setTimeout(doRemove, 0); |
| + } else if (TEST_HOST.startsWith('domnodeinserted')) { |
| + removeOnEvent('DOMNodeInserted'); |
| + } else if (TEST_HOST.startsWith('domsubtreemodified')) { |
| + removeOnEvent('DOMSubtreeModified'); |
| + } else { |
| + console.error('Unexpected test: ' + TEST_HOST); |
| + chrome.test.fail(); |
| + } |
| + |
| + function doRemove() { |
| + parent.frameHTML = document.documentElement.outerHTML || '(no outerHTML)'; |
| + parent.postMessage('toBeRemoved', '*'); |
| + // frameElement = <iframe> element in parent document. |
| + frameElement.remove(); |
| + } |
| + |
| + function removeOnEvent(eventName) { |
| + var expected = parseInt(TEST_HOST.match(/\d+/)[0]); |
| + document.addEventListener(eventName, function() { |
| + // Synchronously remove the frame in the mutation event. |
| + if (--expected === 0) |
| + doRemove(); |
| + }); |
| + |
| + // Fallback in case the mutation events are not triggered. |
| + new Promise(function(resolve) { |
| + // The window.onload event signals that the document and its resources |
| + // have finished loading, so we don't expect any other parser-initiated |
| + // DOM mutations after that point. |
| + if (performance.timing.loadEventEnd > 0) |
|
Devlin
2016/03/18 16:46:10
nit: while this works, I think it'd be clearer to
robwu
2016/03/18 19:25:38
Done.
|
| + resolve(); |
| + else |
| + window.addEventListener('load', resolve); |
| + }).then(function() { |
| + if (expected > 0) { |
| + expected = 0; |
| + // Print this message to make it clear that the expected condition |
| + // (mutation event |eventName| triggered XXX times) did not happen. |
| + console.log('Mutation condition not triggered: ' + TEST_HOST); |
| + doRemove(); |
| + } |
| + }); |
| + |
| + } |
| +} |