Index: chrome/test/data/extensions/api_test/executescript/removed_frames/test.js |
diff --git a/chrome/test/data/extensions/api_test/executescript/removed_frames/test.js b/chrome/test/data/extensions/api_test/executescript/removed_frames/test.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..9787465ae20eb75b1a2f35cfa2b314e542ff9e42 |
--- /dev/null |
+++ b/chrome/test/data/extensions/api_test/executescript/removed_frames/test.js |
@@ -0,0 +1,97 @@ |
+// Copyright 2015 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. |
+ |
+// A simple helper to keep track of how many responses are received, and fail |
+// if it receives a "fail" message. It's unfortunate that these are never |
+// cleaned up, but, realistically, doesn't matter. |
+function ResponseCounter() { |
+ this.responsesReceived = 0; |
+ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { |
+ if (request == 'fail') { |
+ chrome.test.fail(); |
+ } else { |
+ chrome.test.assertEq('complete', request); |
+ ++this.responsesReceived; |
+ } |
+ }.bind(this)); |
+} |
+ |
+var waitForCommittedAndRun = function(functionToRun, numCommits, url) { |
+ var committedCount = 0; |
+ var counter = new ResponseCounter(); // Every test gets a counter. |
+ var onCommitted = function(details) { |
+ if (++committedCount == numCommits) { |
+ functionToRun(counter, details.tabId); |
+ chrome.webNavigation.onCommitted.removeListener(onCommitted); |
+ } |
+ }; |
+ chrome.webNavigation.onCommitted.addListener(onCommitted); |
+ chrome.tabs.create({url: url}); |
+}; |
+ |
+chrome.test.getConfig(function(config) { |
+ var url = 'http://a.com:' + config.testServer.port + |
+ '/extensions/api_test/executescript/removed_frames/outer.html'; |
+ // Regression tests for crbug.com/500574. |
+ chrome.test.runTests([ |
+ function() { |
+ waitForCommittedAndRun(injectAndDeleteIframeFromMainFrame, 2, url); |
+ } |
+ // This is another great test to have, but currently it crashes in blink. |
+ // TODO(devlin): Fix the crash in blink and enable this! |
+ // function() { |
+ // waitForCommittedAndRun(injectAndDeleteIframeFromIframe, 2, url); |
+ // } |
+ ]); |
+}); |
+ |
+function injectAndDeleteIframeFromMainFrame(counter, tabId) { |
+ // Inject code into each frame. If it's the parent frame, it removes the child |
+ // frame from the DOM (invalidating it). The child frame's code shouldn't |
+ // finish executing, since it's been removed. |
+ var injectFrameCode = [ |
+ 'if (window === window.top) {', |
+ ' iframe = document.getElementsByTagName("iframe")[0];', |
+ ' iframe.parentElement.removeChild(iframe);', |
+ ' chrome.runtime.sendMessage("complete");', |
+ '}' |
+ ].join('\n'); |
+ chrome.tabs.executeScript( |
+ tabId, |
+ {code: injectFrameCode, allFrames: true, runAt: 'document_idle'}, |
+ function() { |
+ chrome.test.assertEq(1, counter.responsesReceived); |
+ chrome.test.succeed(); |
+ }); |
+}; |
+ |
+function injectAndDeleteIframeFromIframe(counter, tabId) { |
+ // Inject code into each frame. Have the child frame remove itself, deleting |
+ // the frame while it's still executing. |
+ var injectFrameCode = [ |
+ 'if (window.self !== window.top) {', |
+ ' var iframe = window.top.document.getElementsByTagName("iframe")[0];', |
+ ' if (!iframe || iframe.contentWindow !== window)', |
+ ' chrome.runtime.sendMessage("fail");', |
+ ' else', |
+ ' window.top.document.body.removeChild(iframe);', |
+ '} else {', |
+ ' chrome.runtime.sendMessage("complete");', |
+ '}' |
+ ].join('\n'); |
+ // We also use two "executeScript" calls here so that we have a pending script |
+ // execution on a frame that gets deleted. |
+ chrome.tabs.executeScript( |
+ tabId, |
+ {code: injectFrameCode, allFrames: true, runAt: 'document_idle'}); |
+ chrome.tabs.executeScript( |
+ tabId, |
+ {code: injectFrameCode, allFrames: true, runAt: 'document_idle'}, |
+ function() { |
+ // Script execution, all other things equal, should happen in the order it |
+ // was received, so we only need a check in the second callback. |
+ chrome.test.assertEq(2, counter.responsesReceived); |
+ chrome.test.succeed(); |
+ }); |
+} |