From be3e221b3fd4eb0521604ddddd6d8ccbe2703fb0 Mon Sep 17 00:00:00 2001 From: David Hewitt Date: Thu, 13 Feb 2025 23:23:47 +0900 Subject: [PATCH] LibWeb/XHR: Ensure type set on blob responses --- Libraries/LibWeb/XHR/XMLHttpRequest.cpp | 3 +- Tests/LibWeb/Text/data/mime-types.json | 471 ++++++++++++++++++ .../XMLHttpRequest-override-mimetype-blob.txt | 1 + ...XMLHttpRequest-override-mimetype-blob.html | 60 +++ 4 files changed, 533 insertions(+), 2 deletions(-) create mode 100644 Tests/LibWeb/Text/data/mime-types.json create mode 100644 Tests/LibWeb/Text/expected/XHR/XMLHttpRequest-override-mimetype-blob.txt create mode 100644 Tests/LibWeb/Text/input/XHR/XMLHttpRequest-override-mimetype-blob.html diff --git a/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index 9219b0cf3e3..cdf536d06d3 100644 --- a/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -217,8 +217,7 @@ WebIDL::ExceptionOr XMLHttpRequest::response() // 6. Otherwise, if this’s response type is "blob", set this’s response object to a new Blob object representing this’s received bytes with type set to the result of get a final MIME type for this. else if (m_response_type == Bindings::XMLHttpRequestResponseType::Blob) { auto mime_type_as_string = get_final_mime_type().serialized(); - auto blob_part = FileAPI::Blob::create(realm(), m_received_bytes, move(mime_type_as_string)); - auto blob = FileAPI::Blob::create(realm(), Vector { GC::make_root(*blob_part) }); + auto blob = FileAPI::Blob::create(realm(), m_received_bytes, move(mime_type_as_string)); m_response_object = GC::Ref { blob }; } // 7. Otherwise, if this’s response type is "document", set a document response for this. diff --git a/Tests/LibWeb/Text/data/mime-types.json b/Tests/LibWeb/Text/data/mime-types.json new file mode 100644 index 00000000000..544e6d83a69 --- /dev/null +++ b/Tests/LibWeb/Text/data/mime-types.json @@ -0,0 +1,471 @@ +[ + "Basics", + { + "input": "text/html;charset=gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "TEXT/HTML;CHARSET=GBK", + "output": "text/html;charset=GBK", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + "Legacy comment syntax", + { + "input": "text/html;charset=gbk(", + "output": "text/html;charset=\"gbk(\"", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;x=(;charset=gbk", + "output": "text/html;x=\"(\";charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + "Duplicate parameter", + { + "input": "text/html;charset=gbk;charset=windows-1255", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=();charset=GBK", + "output": "text/html;charset=\"()\"", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + "Spaces", + { + "input": "text/html;charset =gbk", + "output": "text/html", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html ;charset=gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html; charset=gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset= gbk", + "output": "text/html;charset=\" gbk\"", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset= \"gbk\"", + "output": "text/html;charset=\" \\\"gbk\\\"\"", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + "0x0B and 0x0C", + { + "input": "text/html;charset=\u000Bgbk", + "output": "text/html", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\u000Cgbk", + "output": "text/html", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;\u000Bcharset=gbk", + "output": "text/html", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;\u000Ccharset=gbk", + "output": "text/html", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + "Single quotes are a token, not a delimiter", + { + "input": "text/html;charset='gbk'", + "output": "text/html;charset='gbk'", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset='gbk", + "output": "text/html;charset='gbk", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=gbk'", + "output": "text/html;charset=gbk'", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=';charset=GBK", + "output": "text/html;charset='", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + "Invalid parameters", + { + "input": "text/html;test;charset=gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;test=;charset=gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;';charset=gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;\";charset=gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html ; ; charset=gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;;;;charset=gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset= \"\u007F;charset=GBK", + "output": "text/html;charset=GBK", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\"\u007F;charset=foo\";charset=GBK", + "output": "text/html;charset=GBK", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + "Double quotes", + { + "input": "text/html;charset=\"gbk\"", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\"gbk", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=gbk\"", + "output": "text/html;charset=\"gbk\\\"\"", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\" gbk\"", + "output": "text/html;charset=\" gbk\"", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\"gbk \"", + "output": "text/html;charset=\"gbk \"", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\"\\ gbk\"", + "output": "text/html;charset=\" gbk\"", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\"\\g\\b\\k\"", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\"gbk\"x", + "output": "text/html;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\"\";charset=GBK", + "output": "text/html;charset=\"\"", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;charset=\";charset=GBK", + "output": "text/html;charset=\";charset=GBK\"", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + "Unexpected code points", + { + "input": "text/html;charset={gbk}", + "output": "text/html;charset=\"{gbk}\"", + "navigable": true, + "encoding": null, + "minimizedMIMEType": "text/html" + }, + "Parameter name longer than 127", + { + "input": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk", + "output": "text/html;0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789=x;charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + "type/subtype longer than 127", + { + "input": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", + "output": "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789/0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", + "minimizedMIMEType": "" + }, + "Invalid names", + { + "input": "text/html;a]=bar;b[=bar;c=bar", + "output": "text/html;c=bar", + "minimizedMIMEType": "text/html" + }, + "Semicolons in value", + { + "input": "text/html;valid=\";\";foo=bar", + "output": "text/html;valid=\";\";foo=bar", + "minimizedMIMEType": "text/html" + }, + { + "input": "text/html;in]valid=\";asd=foo\";foo=bar", + "output": "text/html;foo=bar", + "minimizedMIMEType": "text/html" + }, + "Valid", + { + "input": "!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + "output": "!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz/!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz;!#$%&'*+-.^_`|~0123456789abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz=!#$%&'*+-.^_`|~0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + "minimizedMIMEType": "" + }, + { + "input": "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008A\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E\u009F\u00A0\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AD\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF\"", + "output": "x/x;x=\"\t !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0080\u0081\u0082\u0083\u0084\u0085\u0086\u0087\u0088\u0089\u008A\u008B\u008C\u008D\u008E\u008F\u0090\u0091\u0092\u0093\u0094\u0095\u0096\u0097\u0098\u0099\u009A\u009B\u009C\u009D\u009E\u009F\u00A0\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9\u00AA\u00AB\u00AC\u00AD\u00AE\u00AF\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF\"", + "minimizedMIMEType": "" + }, + "End-of-file handling", + { + "input": "x/x;test", + "output": "x/x", + "minimizedMIMEType": "" + }, + { + "input": "x/x;test=\"\\", + "output": "x/x;test=\"\\\\\"", + "minimizedMIMEType": "" + }, + "Whitespace (not handled by generated-mime-types.json or above)", + { + "input": "x/x;x= ", + "output": "x/x", + "minimizedMIMEType": "" + }, + { + "input": "x/x;x=\t", + "output": "x/x", + "minimizedMIMEType": "" + }, + { + "input": "x/x\n\r\t ;x=x", + "output": "x/x;x=x", + "minimizedMIMEType": "" + }, + { + "input": "\n\r\t x/x;x=x\n\r\t ", + "output": "x/x;x=x", + "minimizedMIMEType": "" + }, + { + "input": "x/x;\n\r\t x=x\n\r\t ;x=y", + "output": "x/x;x=x", + "minimizedMIMEType": "" + }, + "Latin1", + { + "input": "text/html;test=\u00FF;charset=gbk", + "output": "text/html;test=\"\u00FF\";charset=gbk", + "navigable": true, + "encoding": "GBK", + "minimizedMIMEType": "text/html" + }, + ">Latin1", + { + "input": "x/x;test=\uFFFD;x=x", + "output": "x/x;x=x", + "minimizedMIMEType": "" + }, + "Failure", + { + "input": "\u000Bx/x", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "\u000Cx/x", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "x/x\u000B", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "x/x\u000C", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "\t", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "/", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "bogus", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "bogus/", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "bogus/ ", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "bogus/bogus/;", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "(/)", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "ÿ/ÿ", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "text/html(;doesnot=matter", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "{/}", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "\u0100/\u0100", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "text /html", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "text/ html", + "output": null, + "minimizedMIMEType": "" + }, + { + "input": "\"text/html\"", + "output": null, + "minimizedMIMEType": "" + } +] \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/XHR/XMLHttpRequest-override-mimetype-blob.txt b/Tests/LibWeb/Text/expected/XHR/XMLHttpRequest-override-mimetype-blob.txt new file mode 100644 index 00000000000..465701e3460 --- /dev/null +++ b/Tests/LibWeb/Text/expected/XHR/XMLHttpRequest-override-mimetype-blob.txt @@ -0,0 +1 @@ +PASS \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/XHR/XMLHttpRequest-override-mimetype-blob.html b/Tests/LibWeb/Text/input/XHR/XMLHttpRequest-override-mimetype-blob.html new file mode 100644 index 00000000000..70f619150fc --- /dev/null +++ b/Tests/LibWeb/Text/input/XHR/XMLHttpRequest-override-mimetype-blob.html @@ -0,0 +1,60 @@ + + +