<!DOCTYPE html>
<html>
<body>
<script src="../../resources/js-test-pre.js"></script>
<script>

description('This tests calling setData with a malformed URL in a null origin document. The malformed value should not be readable in another document');
jsTestIsAsync = true;

if (window.internals)
    internals.settings.setCustomPasteboardDataEnabled(true);

const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.src = `data:text/html;charset=utf-8,<!DOCTYPE html>
<button onclick="runTest()">1. Copy</button>
<div><br></div>
<div id="source" oncopy="copy(event)" contenteditable>http://webkit.org/b/&%23x1F914;?x=8 + 6<</div>
<div id="destination" onpaste="paste(event)" contenteditable>2. Paste here</div>
<script>

const originalURL = document.getElementById('source').textContent;
function copy(event) {
    event.clipboardData.setData('url', originalURL);
    event.clipboardData.setData('text/html', 'testing');
    event.preventDefault();
}

function paste(event) {
    parent.postMessage({
        originalURL,
        url: event.clipboardData.getData('url'),
        html: event.clipboardData.getData('text/html'),
        types: event.clipboardData.types,
        items: Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type})),
    }, '*');
}

function runTest() {
    document.body.getBoundingClientRect();
    document.getElementById('source').focus();
    document.execCommand('selectAll');
    document.execCommand('copy');
    document.getElementById('destination').focus();
    if (window.testRunner)
        document.execCommand('paste');
}

if (window.testRunner)
    runTest();

</scri` + 'pt>';

onmessage = (event) => {
    originalURL = event.data.originalURL;
    urlReadInSameDocument = event.data.url;
    shouldBeEqualToString('urlReadInSameDocument', originalURL);
    htmlReadInSameDocument = event.data.html;
    shouldBeEqualToString('htmlReadInSameDocument', "testing");
    typesInSameDocument = event.data.types;
    shouldBeEqualToString('JSON.stringify(typesInSameDocument)', '["text/uri-list","text/html"]');
    itemsInSameDocument = event.data.items;
    shouldBeEqualToString('JSON.stringify(itemsInSameDocument)', '[{"kind":"string","type":"text/uri-list"},{"kind":"string","type":"text/html"}]');
    document.getElementById('destination').focus();
    if (window.testRunner)
        document.execCommand('paste');
}

function doPaste(event) {
    shouldBeEqualToString('event.clipboardData.getData("url")', (new URL(originalURL)).href);
    shouldBeEqualToString('JSON.stringify(event.clipboardData.types)', '["text/uri-list","text/html"]');
    shouldBeEqualToString('JSON.stringify(Array.from(event.clipboardData.items).map((item) => ({kind: item.kind, type: item.type})))',
        '[{"kind":"string","type":"text/uri-list"},{"kind":"string","type":"text/html"}]');
    document.getElementById('destination').remove();
    finishJSTest();
}

</script>
<div id="destination" onpaste="doPaste(event)" contenteditable>3. Paste here</div>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
