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..bf90db45734fc3329e2e97d8378cd71236fe10cd |
--- /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 (document.readyState === 'complete') |
+ 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(); |
+ } |
+ }); |
+ |
+ } |
+} |