Skip to content

Commit 6db8113

Browse files
rorajachromium-wpt-export-bot
authored andcommitted
[Clipboard] - Convert write DOMString to UTF8 for DOMArrayBuffer
This change fixes a crash in ClipboardWriter when handling DOM strings. The issue occurred because we were treating a UTF-16 string as UTF-8 when creating a DOMArrayBuffer. The fix instead uses utf8() method which internally checks for utf-16 string and converts it to utf-8 if required. Please note that DOMString related WPTs introduced in CL 5759427 have been moved to a separate WPT. This was since the previous WPT which contained this test has been marked as expected to fail, which was causing it to not give any test failure signals for this API. Bug: 415304299 Change-Id: I82af30777da6d48db89dd4e96c51d4704aac6105 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6524201 Reviewed-by: Sambamurthy Bandaru <sambamurthy.bandaru@microsoft.com> Reviewed-by: Dan Clark <daniec@microsoft.com> Commit-Queue: Rohan Raja <roraja@microsoft.com> Cr-Commit-Position: refs/heads/main@{#1460379}
1 parent 8b2e229 commit 6db8113

File tree

2 files changed

+112
-50
lines changed

2 files changed

+112
-50
lines changed

clipboard-apis/async-navigator-clipboard-basics.https.html

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -24,56 +24,6 @@
2424
assert_equals(navigator.clipboard, navigator.clipboard);
2525
}, 'navigator.clipboard exists');
2626

27-
promise_test(async t => {
28-
await getPermissions();
29-
const text_plain = "This text was copied using `Clipboard.prototype.write`.";
30-
const html_text = "<p style='color: red; font-style: oblique;'>Test</p>";
31-
await navigator.clipboard.write([
32-
new ClipboardItem({
33-
"text/plain": text_plain,
34-
"text/html" : html_text
35-
}),
36-
]);
37-
}, 'navigator.clipboard.write(DOMString) succeeds');
38-
39-
promise_test(async () => {
40-
await getPermissions();
41-
const promise_text_string = Promise.resolve('hello');
42-
const promise_html_string = Promise.resolve("<p style='color: red; font-style: oblique;'>hello</p>");
43-
const item = new ClipboardItem({
44-
'text/plain': promise_text_string,
45-
'text/html': promise_html_string
46-
});
47-
await navigator.clipboard.write([item]);
48-
}, 'navigator.clipboard.write(Promise<DOMString>) succeeds');
49-
50-
promise_test(async t => {
51-
await getPermissions();
52-
const text_plain = 'hello';
53-
const html_text = "<p style='color: red; font-style: oblique;'>hello</p>";
54-
const image = await fetch("/clipboard-apis/resources/greenbox.png");
55-
const item = new ClipboardItem({
56-
'text/plain': text_plain,
57-
'text/html': new Blob([html_text], {type: 'text/html'}),
58-
'image/png': image.blob(), // Promise<Blob>
59-
'web text/csv': 'hello,world'
60-
});
61-
await navigator.clipboard.write([item]);
62-
}, 'navigator.clipboard.write(web_custom_format) succeeds');
63-
64-
promise_test(async () => {
65-
await getPermissions();
66-
const html_text = "<p style='color: red; font-style: oblique;'>Test</p>";
67-
const item = new ClipboardItem({
68-
'text/plain': 'hello',
69-
'text/html': new Blob([html_text], {type: 'text/html'})
70-
});
71-
const text = await item.getType('text/plain');
72-
const blob = await item.getType('text/html');
73-
assert_true(text instanceof Blob, "item.getType('text/plain') didn't return a Blob");
74-
assert_true(blob instanceof Blob, "item.getType('text/html') didn't return a Blob");
75-
}, 'validate GetType(type) on a contructed ClipboardItem returns Blob');
76-
7727
promise_test(async () => {
7828
await getPermissions();
7929
const blob = new Blob(['hello'], {type: 'text/plain'});
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<!doctype html>
2+
<meta charset="utf-8">
3+
<title>Async Clipboard input type validation tests - DOMString input in write API</title>
4+
<link rel="help" href="https://w3c.github.io/clipboard-apis/#typedefdef-clipboarditemdata">
5+
6+
<body>Body needed for test_driver.click()</body>
7+
<script src="/resources/testharness.js"></script>
8+
<script src="/resources/testharnessreport.js"></script>
9+
<script src="/resources/testdriver.js"></script>
10+
<script src="/resources/testdriver-vendor.js"></script>
11+
<script src="resources/user-activation.js"></script>
12+
<script>
13+
14+
// Permissions are required in order to invoke navigator.clipboard functions in
15+
// an automated test.
16+
async function getPermissions() {
17+
await tryGrantReadPermission();
18+
await tryGrantWritePermission();
19+
await waitForUserActivation();
20+
}
21+
22+
test(() => {
23+
assert_not_equals(navigator.clipboard, undefined);
24+
assert_true(navigator.clipboard instanceof Clipboard);
25+
assert_equals(navigator.clipboard, navigator.clipboard);
26+
}, 'navigator.clipboard exists');
27+
28+
promise_test(async t => {
29+
await getPermissions();
30+
const text_plain = "This text was copied using `Clipboard.prototype.write`.";
31+
const html_text = "<p style='color: red; font-style: oblique;'>Test</p>";
32+
await navigator.clipboard.write([
33+
new ClipboardItem({
34+
"text/plain": text_plain,
35+
"text/html": html_text
36+
}),
37+
]);
38+
}, 'navigator.clipboard.write(DOMString) succeeds');
39+
40+
promise_test(async () => {
41+
await getPermissions();
42+
const promise_text_string = Promise.resolve('hello');
43+
const promise_html_string = Promise.resolve("<p style='color: red; font-style: oblique;'>hello</p>");
44+
const item = new ClipboardItem({
45+
'text/plain': promise_text_string,
46+
'text/html': promise_html_string
47+
});
48+
await navigator.clipboard.write([item]);
49+
}, 'navigator.clipboard.write(Promise<DOMString>) succeeds');
50+
51+
promise_test(async () => {
52+
await getPermissions();
53+
const promise_html_string = `
54+
<table>
55+
<tbody>
56+
<tr>
57+
<td>0,00€</td>
58+
</tr>
59+
<tr>
60+
<td>0,00€</td>
61+
</tr>
62+
</tbody>
63+
</table>
64+
`;
65+
const item = new ClipboardItem({
66+
'text/html': promise_html_string
67+
});
68+
await navigator.clipboard.write([item]);
69+
}, 'navigator.clipboard.write(Promise<DOMString>) with utf-16 string succeeds');
70+
71+
promise_test(async t => {
72+
await getPermissions();
73+
const text_plain = 'hello';
74+
const html_text = "<p style='color: red; font-style: oblique;'>hello</p>";
75+
const image = await fetch("/clipboard-apis/resources/greenbox.png");
76+
const item = new ClipboardItem({
77+
'text/plain': text_plain,
78+
'text/html': new Blob([html_text], {type: 'text/html'}),
79+
'image/png': image.blob(), // Promise<Blob>
80+
'web text/csv': 'hello,world'
81+
});
82+
await navigator.clipboard.write([item]);
83+
}, 'navigator.clipboard.write(web_custom_format) succeeds');
84+
85+
promise_test(async () => {
86+
await getPermissions();
87+
const html_text = "<p style='color: red; font-style: oblique;'>Test</p>";
88+
const item = new ClipboardItem({
89+
'text/plain': 'hello',
90+
'text/html': new Blob([html_text], {type: 'text/html'})
91+
});
92+
const text = await item.getType('text/plain');
93+
const blob = await item.getType('text/html');
94+
assert_true(text instanceof Blob, "item.getType('text/plain') should return a Blob");
95+
assert_true(blob instanceof Blob, "item.getType('text/html') should return a Blob");
96+
}, 'validate GetType(type) on a constructed ClipboardItem returns Blob');
97+
98+
promise_test(async () => {
99+
await getPermissions();
100+
// Test string with various non-Latin characters: Chinese, Arabic, Cyrillic, emoji
101+
const nonLatinText = "你好 مرحبا Привет 👋🌍";
102+
const item = new ClipboardItem({
103+
'text/plain': nonLatinText
104+
});
105+
await navigator.clipboard.write([item]);
106+
107+
// Read back the text and verify it matches
108+
const readText = await navigator.clipboard.readText();
109+
assert_equals(readText, nonLatinText,
110+
"Text read from clipboard should match the non-Latin text that was written");
111+
}, 'write non-Latin characters with DOMString and verify readText returns the same string');
112+
</script>

0 commit comments

Comments
 (0)