From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/mshtml_private.h | 2 ++ dlls/mshtml/nsembed.c | 43 +++++++++++++++++++++++++++++ dlls/mshtml/nsiface.idl | 13 +++++++++ dlls/mshtml/omnavigator.c | 44 +++++++++++++++++++++++++++-- dlls/mshtml/tests/documentmode.js | 3 ++ dlls/mshtml/tests/es5.js | 46 +++++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index 2f06b504b52..507bb4ffcac 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -76,6 +76,7 @@ #define MSHTML_E_INVALID_PROPERTY 0x800a01b6 #define MSHTML_E_INVALID_ACTION 0x800a01bd #define MSHTML_E_NODOC 0x800a025c +#define MSHTML_E_SYNTAX 0x800a03ea #define MSHTML_E_NOT_FUNC 0x800a138a
typedef struct HTMLWindow HTMLWindow; @@ -1294,6 +1295,7 @@ HRESULT nsnode_to_nsstring(nsIDOMNode*,nsAString*); void setup_editor_controller(GeckoBrowser*); nsresult get_nsinterface(nsISupports*,REFIID,void**); nsIWritableVariant *create_nsvariant(void); +nsIDOMParser *create_nsdomparser(HTMLDocumentNode*); nsIXMLHttpRequest *create_nsxhr(nsIDOMWindow *nswindow); nsresult create_nsfile(const PRUnichar*,nsIFile**); char *get_nscategory_entry(const char*,const char*); diff --git a/dlls/mshtml/nsembed.c b/dlls/mshtml/nsembed.c index 5480c4ed044..cbaf05e6345 100644 --- a/dlls/mshtml/nsembed.c +++ b/dlls/mshtml/nsembed.c @@ -42,6 +42,7 @@ WINE_DECLARE_DEBUG_CHANNEL(gecko); #define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1" #define NS_COMMANDPARAMS_CONTRACTID "@mozilla.org/embedcomp/command-params;1" #define NS_HTMLSERIALIZER_CONTRACTID "@mozilla.org/layout/contentserializer;1?mimetype=text/html" +#define NS_DOMPARSER_CONTRACTID "@mozilla.org/xmlextras/domparser;1" #define NS_EDITORCONTROLLER_CONTRACTID "@mozilla.org/editor/editorcontroller;1" #define NS_PREFERENCES_CONTRACTID "@mozilla.org/preferences;1" #define NS_VARIANT_CONTRACTID "@mozilla.org/variant;1" @@ -2415,6 +2416,48 @@ __ASM_GLOBAL_FUNC(call_thiscall_func, #define nsIScriptObjectPrincipal_GetPrincipal(this) ((void* (WINAPI*)(void*,void*))&call_thiscall_func)((this)->lpVtbl->GetPrincipal,this) #endif
+nsIDOMParser *create_nsdomparser(HTMLDocumentNode *doc_node) +{ + nsIScriptObjectPrincipal *sop; + mozIDOMWindow *inner_window; + nsIGlobalObject *nsglo; + nsIDOMParser *nsparser; + nsIPrincipal *nspri; + nsresult nsres; + + nsres = nsIDOMWindow_GetInnerWindow(doc_node->window->dom_window, &inner_window); + if(NS_FAILED(nsres)) { + ERR("Could not get inner window: %08lx\n", nsres); + return NULL; + } + + nsres = mozIDOMWindow_QueryInterface(inner_window, &IID_nsIGlobalObject, (void**)&nsglo); + mozIDOMWindow_Release(inner_window); + assert(nsres == NS_OK); + + nsres = nsIGlobalObject_QueryInterface(nsglo, &IID_nsIScriptObjectPrincipal, (void**)&sop); + assert(nsres == NS_OK); + + /* The returned principal is *not* AddRef'd */ + nspri = nsIScriptObjectPrincipal_GetPrincipal(sop); + nsIScriptObjectPrincipal_Release(sop); + + nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, + NS_DOMPARSER_CONTRACTID, NULL, &IID_nsIDOMParser, (void**)&nsparser); + if(NS_SUCCEEDED(nsres)) { + nsres = nsIDOMParser_Init(nsparser, nspri, NULL, NULL, nsglo); + if(NS_FAILED(nsres)) + nsIDOMParser_Release(nsparser); + } + nsIGlobalObject_Release(nsglo); + if(NS_FAILED(nsres)) { + ERR("nsIDOMParser_Init failed: %08lx\n", nsres); + return NULL; + } + + return nsparser; +} + nsIXMLHttpRequest *create_nsxhr(nsIDOMWindow *nswindow) { nsIScriptObjectPrincipal *sop; diff --git a/dlls/mshtml/nsiface.idl b/dlls/mshtml/nsiface.idl index 43786b490f5..1f2131dfb24 100644 --- a/dlls/mshtml/nsiface.idl +++ b/dlls/mshtml/nsiface.idl @@ -4369,6 +4369,19 @@ interface nsIScriptObjectPrincipal : nsISupports nsIPrincipal* /* thiscall */ GetPrincipal(); }
+[ + object, + uuid(70b9600e-8622-4c93-9ad8-22c28058dc44), + local +] +interface nsIDOMParser : nsISupports +{ + nsresult ParseFromString(const char16_t *str, const char *contentType, nsIDOMDocument **_retval); + nsresult ParseFromBuffer(const uint8_t *buf, uint32_t bufLen, const char *aContentType, nsIDOMDocument **_retval); + nsresult ParseFromStream(nsIInputStream *stream, const char *charset, int32_t contentLength, const char *contentType, nsIDOMDocument **_retval); + nsresult Init(nsIPrincipal *principal, nsIURI *documentURI, nsIURI *baseURI, nsIGlobalObject *scriptObject); +} + [ object, uuid(6f54214c-7175-498d-9d2d-0429e38c2869), diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index ee17332e27a..eb80372d446 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -311,7 +311,13 @@ DISPEX_IDISPATCH_IMPL(dom_parser, IDOMParser, impl_from_IDOMParser(iface)->dispe static HRESULT WINAPI dom_parser_parseFromString(IDOMParser *iface, BSTR string, BSTR mimeType, IHTMLDocument2 **ppNode) { struct dom_parser *This = impl_from_IDOMParser(iface); + nsIDOMDocument *nsdoc = NULL; + HTMLDocumentNode *xml_doc; document_type_t doc_type; + nsAString errns, errtag; + nsIDOMNodeList *nodes; + nsIDOMParser *parser; + nsresult nsres; HRESULT hres;
TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(string), debugstr_w(mimeType), ppNode); @@ -354,8 +360,42 @@ static HRESULT WINAPI dom_parser_parseFromString(IDOMParser *iface, BSTR string, return hres; }
- FIXME("Not implemented for XML Document\n"); - return E_NOTIMPL; + if(!(parser = create_nsdomparser(This->doc))) + return E_FAIL; + nsres = nsIDOMParser_ParseFromString(parser, string ? string : L"", + doc_type == DOCTYPE_SVG ? "image/svg+xml" : + doc_type == DOCTYPE_XHTML ? "application/xhtml+xml" : + "text/xml", &nsdoc); + nsIDOMParser_Release(parser); + if(NS_FAILED(nsres) || !nsdoc) { + ERR("ParseFromString failed: 0x%08lx\n", nsres); + return NS_FAILED(nsres) ? map_nsresult(nsres) : E_FAIL; + } + + nsAString_InitDepend(&errns, L"http://www.mozilla.org/newlayout/xml/parsererror.xml"); + nsAString_InitDepend(&errtag, L"parsererror"); + nsres = nsIDOMDocument_GetElementsByTagNameNS(nsdoc, &errns, &errtag, &nodes); + nsAString_Finish(&errtag); + nsAString_Finish(&errns); + if(NS_SUCCEEDED(nsres)) { + UINT32 length; + nsres = nsIDOMNodeList_GetLength(nodes, &length); + nsIDOMNodeList_Release(nodes); + if(NS_SUCCEEDED(nsres) && length) { + nsIDOMDocument_Release(nsdoc); + return MSHTML_E_SYNTAX; + } + } + + hres = create_document_node(nsdoc, This->doc->browser, NULL, This->doc->script_global, doc_type, This->doc->document_mode, &xml_doc); + nsIDOMDocument_Release(nsdoc); + if(FAILED(hres)) + return hres; + + /* make sure dispex info is initialized */ + dispex_compat_mode(&xml_doc->node.event_target.dispex); + *ppNode = &xml_doc->IHTMLDocument2_iface; + return hres; }
static const IDOMParserVtbl dom_parser_vtbl = { diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 17b4919457d..035d3b2ef31 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -334,6 +334,9 @@ sync_test("builtin_toString", function() { test("computedStyle", window.getComputedStyle(e), "CSSStyleDeclaration"); test("doctype", document.doctype, "DocumentType"); test("domParser", new DOMParser(), "DOMParser"); + test("svgDocument", new DOMParser().parseFromString("<tag>foobar</tag>", "image/svg+xml"), v < 11 ? "Document" : "XMLDocument"); + test("xhtmlDocument", new DOMParser().parseFromString("<tag>foobar</tag>", "application/xhtml+xml"), v < 11 ? "Document" : "XMLDocument"); + test("xmlDocument", new DOMParser().parseFromString("<tag>foobar</tag>", "text/xml"), v < 11 ? "Document" : "XMLDocument");
test("Event", document.createEvent("Event"), "Event"); test("CustomEvent", document.createEvent("CustomEvent"), "CustomEvent"); diff --git a/dlls/mshtml/tests/es5.js b/dlls/mshtml/tests/es5.js index a0b4d758154..02f72586d26 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -2851,6 +2851,44 @@ sync_test("DOMParser", function() { ok(r === html_elem, "body parent of HTML document with mime type " + m + " = " + r); }
+ // XML mime types + mimeType = [ + "text/xmL", + "aPPlication/xml", + "application/xhtml+xml", + "image/svg+xml" + ]; + for(var i = 0; i < mimeType.length; i++) { + var m = mimeType[i], xml = p.parseFromString(teststr, m), e; + e = external.getExpectedMimeType(m === "aPPlication/xml" ? "text/xml" : m.toLowerCase()); + r = xml.mimeType; + ok(r === e, "mimeType of XML document with mime type " + m + " = " + r + ", expected " + e); + r = xml.childNodes; + ok(r.length === 1, "childNodes.length of XML document with mime type " + m + " = " + r.length); + r = r[0]; + ok(r.nodeName === "a", "child nodeName of XML document with mime type " + m + " = " + r.nodeName); + ok(r.nodeValue === null, "child nodeValue of XML document with mime type " + m + " = " + r.nodeValue); + r = r.childNodes; + ok(r.length === 1, "childNodes of child.length of XML document with mime type " + m + " = " + r.length); + r = r[0]; + ok(r.nodeName === "#text", "child of child nodeName of XML document with mime type " + m + " = " + r.nodeName); + ok(r.nodeValue === "wine", "child of child nodeValue of XML document with mime type " + m + " = " + r.nodeValue); + ok(!("test" in xml), "'test' in XML document with mime type " + m); + + // test HTMLDocument specific props, which are available in DocumentPrototype, + // so they are shared in XMLDocument since they both have the same prototype + r = xml.anchors; + if(m === "application/xhtml+xml") { + todo_wine. + ok(r.length === 1, "anchors.length of XML document with mime type " + m + " = " + r.length); + r = r[0]; + todo_wine. + ok(r === xml.childNodes[0], "anchor of XML document with mime type " + m + " = " + r); + }else { + ok(r.length === 0, "anchors.length of XML document with mime type " + m + " = " + r.length); + } + } + // Invalid mime types mimeType = [ "application/html", @@ -2871,6 +2909,14 @@ sync_test("DOMParser", function() { ok(n === E_INVALIDARG, "parseFromString with mime type " + mimeType[i] + " threw " + n); } } + + try { + r = p.parseFromString("<invalid>xml", "text/xml"); + ok(false, "expected exception calling parseFromString with invalid xml"); + }catch(ex) { + ok(ex.name === "SyntaxError", "parseFromString with invalid xml threw " + ex.name); + } + p.parseFromString("<parsererror></parsererror>", "text/xml"); });
sync_test("builtin_func", function() {