Chromium Code Reviews| 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(); |
| + }); |
| +} |