-- v6: mshtml: Remove outdated FIXME comment. mshtml: Try to guess the script encoding when there's no BOM. mshtml/tests: Test mixed charset encodings for document and text resources.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/tests/dom.c | 147 ++++++++++++++++++++++++++++++++ dlls/mshtml/tests/rsrc.rc | 24 ++++++ dlls/mshtml/tests/utf16_bom_css | Bin 0 -> 84 bytes dlls/mshtml/tests/utf16_bom_js | Bin 0 -> 56 bytes dlls/mshtml/tests/utf16_css | Bin 0 -> 82 bytes dlls/mshtml/tests/utf16_js | Bin 0 -> 54 bytes dlls/mshtml/tests/utf8_bom_css | 1 + dlls/mshtml/tests/utf8_bom_js | 1 + dlls/mshtml/tests/utf8_css | 1 + dlls/mshtml/tests/utf8_js | 1 + 10 files changed, 175 insertions(+) create mode 100644 dlls/mshtml/tests/utf16_bom_css create mode 100644 dlls/mshtml/tests/utf16_bom_js create mode 100644 dlls/mshtml/tests/utf16_css create mode 100644 dlls/mshtml/tests/utf16_js create mode 100644 dlls/mshtml/tests/utf8_bom_css create mode 100644 dlls/mshtml/tests/utf8_bom_js create mode 100644 dlls/mshtml/tests/utf8_css create mode 100644 dlls/mshtml/tests/utf8_js
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index b1625b619ca..b09c5ef971f 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -12037,6 +12037,152 @@ static void test_quirks_mode(void) } }
+static void test_default_content_charset(void) +{ +#define CHARSETS X(utf8) X(utf16) X(utf8_bom) X(utf16_bom) + enum { +#define X(c) c, + CHARSETS +#undef X + } doc_charset, rsrc_charset; + static const char *charsets[] = { +#define X(c) #c, + CHARSETS +#undef X + }; + static const WCHAR *charsetsW[] = { +#define X(c) L"" #c, + CHARSETS +#undef X + }; +#undef CHARSETS + unsigned module_len, module_lenW; + IHTMLCSSStyleDeclaration *style; + char module_path[MAX_PATH * 3]; + WCHAR module_pathW[MAX_PATH]; + IPersistStreamInit *init; + IHTMLWindow7 *window7; + IHTMLWindow2 *window; + IHTMLDocument2 *doc; + IHTMLElement *body; + IHTMLDOMNode *node; + IStream *stream; + DISPID dispid; + HRESULT hres; + VARIANT var; + HGLOBAL mem; + SIZE_T size; + void *buf; + BSTR bstr; + MSG msg; + + module_lenW = GetModuleFileNameW(NULL, module_pathW, ARRAY_SIZE(module_pathW)); + module_len = WideCharToMultiByte(CP_UTF8, 0, module_pathW, -1, module_path, ARRAY_SIZE(module_path), NULL, NULL); + + for(doc_charset = utf8; doc_charset <= utf16; doc_charset++) { + for(rsrc_charset = utf8; rsrc_charset < ARRAY_SIZE(charsets); rsrc_charset++) { + notif_doc = doc = create_document(); + if(!doc) + return; + doc_complete = FALSE; + + buf = malloc((128 + (doc_charset == utf16 ? module_lenW : module_len)) * (doc_charset == utf16 ? sizeof(WCHAR) : 1)); + if(doc_charset == utf16) + size = wsprintfW(buf, L"<!DOCTYPE html>\n<html><head><link href="res://%s/%s_css" rel="stylesheet"></head><body></body></html>", module_pathW, charsetsW[rsrc_charset]) * sizeof(WCHAR); + else + size = sprintf(buf, "<!DOCTYPE html>\n<html><head><link href="res://%s/%s_css" rel="stylesheet"></head><body></body></html>", module_path, charsets[rsrc_charset]); + mem = GlobalAlloc(0, size); + memcpy(mem, buf, size); + free(buf); + + hres = CreateStreamOnHGlobal(mem, TRUE, &stream); + ok(hres == S_OK, "Failed to create stream: %08lx.\n", hres); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); + ok(hres == S_OK, "Failed to get IPersistStreamInit: %08lx.\n", hres); + IPersistStreamInit_Load(init, stream); + IPersistStreamInit_Release(init); + IStream_Release(stream); + + set_client_site(doc, TRUE); + do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); + + while(!doc_complete && GetMessageW(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + hres = IHTMLDocument2_get_parentWindow(doc, &window); + ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres); + + hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow7, (void**)&window7); + ok(hres == S_OK, "Could not get IHTMLWindow7: %08lx\n", hres); + IHTMLWindow2_Release(window); + + hres = IHTMLDocument2_get_body(doc, &body); + ok(hres == S_OK, "Could not get body: %08lx\n", hres); + + hres = IHTMLElement_QueryInterface(body, &IID_IHTMLDOMNode, (void**)&node); + ok(hres == S_OK, "Could not get IHTMLDOMNode: %08lx\n", hres); + IHTMLElement_Release(body); + + hres = IHTMLWindow7_getComputedStyle(window7, node, NULL, &style); + ok(hres == S_OK, "getComputedStyle failed: %08lx\n", hres); + IHTMLWindow7_Release(window7); + IHTMLDOMNode_Release(node); + + hres = IHTMLCSSStyleDeclaration_get_backgroundColor(style, &var); + ok(hres == S_OK, "get_backgroundColor failed: %08lx\n", hres); + ok(V_VT(&var) == VT_BSTR, "backgroundColor VT = %d\n", V_VT(&var)); + todo_wine_if((doc_charset == utf8 && rsrc_charset == utf16) || (doc_charset == utf16 && rsrc_charset == utf8)) + ok(!wcscmp(V_BSTR(&var), L"rgb(222, 173, 184)"), "[%s:%s] backgroundColor = %s\n", charsets[doc_charset], charsets[rsrc_charset], wine_dbgstr_w(V_BSTR(&var))); + IHTMLCSSStyleDeclaration_Release(style); + VariantClear(&var); + + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); + + notif_doc = doc = create_document(); + if(!doc) + return; + doc_complete = FALSE; + + buf = malloc((128 + (doc_charset == utf16 ? module_lenW : module_len)) * (doc_charset == utf16 ? sizeof(WCHAR) : 1)); + if(doc_charset == utf16) + size = wsprintfW(buf, L"<!DOCTYPE html>\n<html><head><script type="text/javascript" src="res://%s/%s_js"></script></head><body></body></html>", module_pathW, charsetsW[rsrc_charset]) * sizeof(WCHAR); + else + size = sprintf(buf, "<!DOCTYPE html>\n<html><head><script type="text/javascript" src="res://%s/%s_js"></script></head><body></body></html>", module_path, charsets[rsrc_charset]); + mem = GlobalAlloc(0, size); + memcpy(mem, buf, size); + free(buf); + + hres = CreateStreamOnHGlobal(mem, TRUE, &stream); + ok(hres == S_OK, "Failed to create stream: %08lx.\n", hres); + hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init); + ok(hres == S_OK, "Failed to get IPersistStreamInit: %08lx.\n", hres); + IPersistStreamInit_Load(init, stream); + IPersistStreamInit_Release(init); + IStream_Release(stream); + + set_client_site(doc, TRUE); + do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink); + + while(!doc_complete && GetMessageW(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + bstr = SysAllocString(L"wineTestProp"); + hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &dispid); + todo_wine_if((doc_charset == utf8 || doc_charset == utf16) && rsrc_charset == utf16) + ok(hres == S_OK, "[%s:%s] GetIDsOfNames(wineTestProp) returned: %08lx\n", charsets[doc_charset], charsets[rsrc_charset], hres); + SysFreeString(bstr); + + set_client_site(doc, FALSE); + IHTMLDocument2_Release(doc); + } + } +} + static void test_document_mode_lock(void) { IHTMLOptionElementFactory *option, *option2; @@ -12414,6 +12560,7 @@ START_TEST(dom) }
test_quirks_mode(); + test_default_content_charset(); test_document_mode_lock(); test_document_mode_after_initnew(); test_threads(); diff --git a/dlls/mshtml/tests/rsrc.rc b/dlls/mshtml/tests/rsrc.rc index 61b53520781..dc586f42c68 100644 --- a/dlls/mshtml/tests/rsrc.rc +++ b/dlls/mshtml/tests/rsrc.rc @@ -91,6 +91,30 @@ iframe.html HTML "iframe.html" /* @makedep: xhr_iframe.html */ xhr_iframe.html HTML "xhr_iframe.html"
+/* @makedep: utf8_css */ +utf8_css HTML "utf8_css" + +/* @makedep: utf16_css */ +utf16_css HTML "utf16_css" + +/* @makedep: utf8_bom_css */ +utf8_bom_css HTML "utf8_bom_css" + +/* @makedep: utf16_bom_css */ +utf16_bom_css HTML "utf16_bom_css" + +/* @makedep: utf8_js */ +utf8_js HTML "utf8_js" + +/* @makedep: utf16_js */ +utf16_js HTML "utf16_js" + +/* @makedep: utf8_bom_js */ +utf8_bom_js HTML "utf8_bom_js" + +/* @makedep: utf16_bom_js */ +utf16_bom_js HTML "utf16_bom_js" + /* For res: protocol test: */
/* @makedep: jstest.html */ diff --git a/dlls/mshtml/tests/utf16_bom_css b/dlls/mshtml/tests/utf16_bom_css new file mode 100644 index 0000000000000000000000000000000000000000..873d27b6544a5d3d373d8e03f090b067f4910636 GIT binary patch literal 84 zcmezWPmiIPA&()2p_-wVL4hHOA)g_Ip^`y?p_(CyA(0`OA)6tcp@<=$p%ko2mm!%U kpCN}KpP`7sia~)vnIVNCl_8NKg&~Q-g29@hmVt`_04ggGr2qf`
literal 0 HcmV?d00001
diff --git a/dlls/mshtml/tests/utf16_bom_js b/dlls/mshtml/tests/utf16_bom_js new file mode 100644 index 0000000000000000000000000000000000000000..4acc12a612bc2ce431bace8c4a23a223b83a50c0 GIT binary patch literal 56 zcmezWFNGnWA(^3+A(tVQA&;SiL64!FA(J7GA(bJ7A(f$+p@boTp@<=$p@2bw!InXR L!H~h4fr|kEmQM?E
literal 0 HcmV?d00001
diff --git a/dlls/mshtml/tests/utf16_css b/dlls/mshtml/tests/utf16_css new file mode 100644 index 0000000000000000000000000000000000000000..fb315b0139f946b4010182b833ee8e229764a8bf GIT binary patch literal 82 zcmdO6C}zlGNMWdEsAW)KNMgumNMWdCP++KLNMcB2NM^`pNM|Tw$Y&@8tI}miX2@sA iVaR7FVz6RRU{GdAVMt|2WJqC1Vz6MaW~gQ0VgLYy6b`5W
literal 0 HcmV?d00001
diff --git a/dlls/mshtml/tests/utf16_js b/dlls/mshtml/tests/utf16_js new file mode 100644 index 0000000000000000000000000000000000000000..649619ba960f339dbab22df3bb64773839e99d25 GIT binary patch literal 54 zcmYdc$Y)4qC}qfHNM*=lC}GfJC}+rI$YV%l2w_NNC}t>O2w*5;$Y&^EP++iSP+%}* Jux8+5001ZR33UJf
literal 0 HcmV?d00001
diff --git a/dlls/mshtml/tests/utf8_bom_css b/dlls/mshtml/tests/utf8_bom_css new file mode 100644 index 00000000000..b44b804ba27 --- /dev/null +++ b/dlls/mshtml/tests/utf8_bom_css @@ -0,0 +1 @@ +.snd{} body {background-color: #deadb8;} diff --git a/dlls/mshtml/tests/utf8_bom_js b/dlls/mshtml/tests/utf8_bom_js new file mode 100644 index 00000000000..4e1d2b52a49 --- /dev/null +++ b/dlls/mshtml/tests/utf8_bom_js @@ -0,0 +1 @@ +document.wineTestProp = 1; diff --git a/dlls/mshtml/tests/utf8_css b/dlls/mshtml/tests/utf8_css new file mode 100644 index 00000000000..8dcd51fc75e --- /dev/null +++ b/dlls/mshtml/tests/utf8_css @@ -0,0 +1 @@ +.snd{} body {background-color: #deadb8;} diff --git a/dlls/mshtml/tests/utf8_js b/dlls/mshtml/tests/utf8_js new file mode 100644 index 00000000000..49a369ce60f --- /dev/null +++ b/dlls/mshtml/tests/utf8_js @@ -0,0 +1 @@ +document.wineTestProp = 1;
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/script.c | 25 +++++++++++++++---------- dlls/mshtml/tests/dom.c | 1 - 2 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/dlls/mshtml/script.c b/dlls/mshtml/script.c index 9d663ee1cf7..065c3568410 100644 --- a/dlls/mshtml/script.c +++ b/dlls/mshtml/script.c @@ -963,6 +963,7 @@ typedef struct {
static HRESULT get_binding_text(ScriptBSC *bsc, WCHAR **ret) { + binding_bom_t bom; UINT cp = CP_UTF8; WCHAR *text;
@@ -975,8 +976,19 @@ static HRESULT get_binding_text(ScriptBSC *bsc, WCHAR **ret) return S_OK; }
- switch(bsc->bsc.bom) { - case BOM_UTF16: + bom = bsc->bsc.bom; + if(bom == BOM_NONE) { + /* FIXME: Try to use charset from HTTP headers first */ + + /* IE guesses the encoding here using heuristics. Since valid script must start with an + * ASCII char (keyword, comment slash, string literal char, etc) that should be enough. */ + if(bsc->bsc.read > sizeof(WCHAR) && *(WCHAR*)bsc->buf < 128) + bom = BOM_UTF16; + else + cp = get_document_charset(bsc->script_elem->element.node.doc); + } + + if(bom == BOM_UTF16) { if(bsc->bsc.read % sizeof(WCHAR)) { FIXME("The buffer is not a valid utf16 string\n"); return E_FAIL; @@ -988,13 +1000,7 @@ static HRESULT get_binding_text(ScriptBSC *bsc, WCHAR **ret)
memcpy(text, bsc->buf, bsc->bsc.read); text[bsc->bsc.read/sizeof(WCHAR)] = 0; - break; - - default: - /* FIXME: Try to use charset from HTTP headers first */ - cp = get_document_charset(bsc->script_elem->element.node.doc); - /* fall through */ - case BOM_UTF8: { + }else { DWORD len;
len = MultiByteToWideChar(cp, 0, bsc->buf, bsc->bsc.read, NULL, 0); @@ -1005,7 +1011,6 @@ static HRESULT get_binding_text(ScriptBSC *bsc, WCHAR **ret) MultiByteToWideChar(cp, 0, bsc->buf, bsc->bsc.read, text, len); text[len] = 0; } - }
*ret = text; return S_OK; diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c index b09c5ef971f..cd03db02df8 100644 --- a/dlls/mshtml/tests/dom.c +++ b/dlls/mshtml/tests/dom.c @@ -12173,7 +12173,6 @@ static void test_default_content_charset(void)
bstr = SysAllocString(L"wineTestProp"); hres = IHTMLDocument2_GetIDsOfNames(doc, &IID_NULL, &bstr, 1, 0, &dispid); - todo_wine_if((doc_charset == utf8 || doc_charset == utf16) && rsrc_charset == utf16) ok(hres == S_OK, "[%s:%s] GetIDsOfNames(wineTestProp) returned: %08lx\n", charsets[doc_charset], charsets[rsrc_charset], hres); SysFreeString(bstr);
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/navigate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index f05bf0be9c6..6b5eff15105 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -1144,8 +1144,9 @@ static HRESULT read_stream_data(nsChannelBSC *This, IStream *stream) break; case BOM_UTF16: This->nschannel->charset = strdup("utf-16"); + break; case BOM_NONE: - /* FIXME: Get charset from HTTP headers */; + break; }
if(!This->nschannel->content_type) {
Jacek Caban (@jacek) commented about dlls/mshtml/tests/rsrc.rc:
/* @makedep: xhr_iframe.html */ xhr_iframe.html HTML "xhr_iframe.html"
+/* @makedep: utf8_css */ +utf8_css HTML "utf8_css"
Please use proper file extensions for the added files. Note that the name shown in resources doesn't have to match the filename used to create them.
While omitting the extension may have been useful for experimentation earlier, we now know that the extensions don’t affect behavior, so there's no real benefit in leaving them out. In fact, doing so prevents us from testing with the correct MIME type, which is a much more common and relevant scenario.
Jacek Caban (@jacek) commented about dlls/mshtml/script.c:
return S_OK; }
- switch(bsc->bsc.bom) {
- case BOM_UTF16:
- bom = bsc->bsc.bom;
- if(bom == BOM_NONE) {
/* FIXME: Try to use charset from HTTP headers first */
/* IE guesses the encoding here using heuristics. Since valid script must start with an
* ASCII char (keyword, comment slash, string literal char, etc) that should be enough. */
if(bsc->bsc.read > sizeof(WCHAR) && *(WCHAR*)bsc->buf < 128)
bom = BOM_UTF16;
else
cp = get_document_charset(bsc->script_elem->element.node.doc);
You could leave the switch statement as it was and just handle the `BOM_NONE` to `BOM_UTF16` fixup here.