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..364ff6c5921698f89cae6bea4ac7dc953a258bb2 |
--- /dev/null |
+++ b/chrome/test/data/extensions/api_test/executescript/removed_frames/test.js |
@@ -0,0 +1,100 @@ |
+// 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. |
+ |
+var responsesReceived = 0; |
not at google - send to devlin
2015/06/29 18:28:11
Can we avoid global variables? Worst case it'll be
Devlin
2015/06/29 19:41:44
Not sure I follow. This count is used in both tes
not at google - send to devlin
2015/06/29 20:09:07
It seems like it's reset to 0 in each test. Why do
Devlin
2015/06/29 20:43:13
chrome.runtime.onMessage listener is global to avo
not at google - send to devlin
2015/06/29 21:24:35
I don't think it's excessive. You can listen to th
Devlin
2015/06/29 21:51:20
Done.
|
+chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { |
+ if (request == 'fail') { |
+ chrome.test.fail(); |
+ } else { |
+ chrome.test.assertEq('complete', request); |
+ ++responsesReceived; |
+ } |
+}); |
+ |
+var waitForCommittedAndRun = function(functionToRun, numCommits, url) { |
+ responsesReceived = 0; |
+ var committedCount = 0; |
+ var onCommitted = function(details) { |
+ if (++committedCount == numCommits) { |
+ functionToRun(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:PORT/extensions/api_test/executescript/' + |
+ 'removed_frames/outer.html').replace(/PORT/, |
+ config.testServer.port); |
not at google - send to devlin
2015/06/29 18:28:11
I find this pattern pretty weird, and I've seen it
Devlin
2015/06/29 19:41:44
I don't know either (copied). Changed.
|
+ // Regression tests for crbug.com/500574. |
+ chrome.test.runTests([ |
+ function() { |
+ waitForCommittedAndRun(injectAndDeleteIframeFromMainFrame, 2, url); |
not at google - send to devlin
2015/06/29 21:24:35
Err, why is the tab ID 2? Can you make it not depe
Devlin
2015/06/29 21:51:20
Tab id is not 2. The number of commits to wait fo
|
+ } |
+ // This is another great test to have, but currently it crashes in blink. |
+ // TODO(devlin): Fix the crash in blink and enable this! |
Devlin
2015/06/25 21:12:27
This will be done soon.
|
+ // function() { |
+ // waitForCommittedAndRun(injectAndDeleteIframeFromIframe, 2, url); |
+ // } |
+ ]); |
+}); |
+ |
+function injectAndDeleteIframeFromMainFrame(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) {' + |
not at google - send to devlin
2015/06/29 18:28:11
nit (sorta): the problem with this is that the lin
Devlin
2015/06/29 19:41:44
Done.
|
+ // There's a (good) chance the child frame reaches "idle" first, since it |
+ // is a subresource of the main frame. But it shouldn't stick around for |
+ // more than 200ms or so, since that's the max delay for idle. If the |
+ // script still tries to execute, it's probably bad. |
+ ' window.setTimeout(function() {' + |
+ ' chrome.runtime.sendMessage("fail");' + |
not at google - send to devlin
2015/06/29 18:28:11
Why does it matter? The way I read this (?) withou
Devlin
2015/06/29 19:41:44
Well, even if that were the case, failing is a lot
not at google - send to devlin
2015/06/29 20:09:07
That is beside the point, but I disagree, and will
Devlin
2015/06/29 20:43:13
But the point is that this code will *not* run. I
|
+ ' }, 250);' + |
+ '} else {' + |
+ ' iframe = document.getElementsByTagName("iframe")[0];' + |
+ ' iframe.parentElement.removeChild(iframe);' + |
+ ' chrome.runtime.sendMessage("complete");' + |
+ '}'; |
+ chrome.tabs.executeScript( |
+ tabId, |
+ {code: injectFrameCode, allFrames: true, runAt: 'document_idle'}, |
+ function() { |
+ chrome.test.assertEq(1, responsesReceived); |
+ chrome.test.succeed(); |
+ }); |
+}; |
+ |
+function injectAndDeleteIframeFromIframe(tabId) { |
+ responsesReceived = 0; |
+ // 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");' + |
+ '}'; |
+ // 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, responsesReceived); |
+ chrome.test.succeed(); |
+ }); |
+} |