From 19490453c95acebf59bc7c693fc7ffe3dbfb5058 Mon Sep 17 00:00:00 2001 From: "hyatt%netscape.com" Date: Fri, 2 Nov 2001 01:53:13 +0000 Subject: [PATCH] Fix for 106153, avoid building a content model for XBL event handlers, r=bryner, sr=waterson --- content/base/public/nsIDocument.h | 4 +- content/base/public/nsINameSpaceManager.h | 1 + content/base/src/nsDocument.cpp | 4 +- content/base/src/nsDocument.h | 3 +- content/base/src/nsNameSpaceManager.cpp | 8 + content/build/nsContentModule.cpp | 3 + content/html/document/src/nsHTMLDocument.cpp | 15 +- content/html/document/src/nsHTMLDocument.h | 3 +- content/html/document/src/nsImageDocument.cpp | 8 +- content/shared/public/MANIFEST | 3 + content/shared/public/Makefile.in | 2 + content/shared/public/makefile.win | 2 + content/shared/public/nsXBLAtomList.h | 101 +++++ content/shared/public/nsXBLAtoms.h | 75 ++++ content/shared/src/Makefile.in | 1 + content/shared/src/makefile.win | 2 + content/shared/src/nsXBLAtoms.cpp | 71 +++ content/xbl/public/nsIBindingManager.h | 1 + content/xbl/public/nsIXBLPrototypeBinding.h | 2 + content/xbl/public/nsIXBLPrototypeHandler.h | 15 +- content/xbl/src/Makefile.in | 51 ++- content/xbl/src/makefile.win | 45 +- content/xbl/src/nsBindingManager.cpp | 408 +----------------- content/xbl/src/nsXBLAtomList.h | 101 +++++ content/xbl/src/nsXBLAtoms.cpp | 71 +++ content/xbl/src/nsXBLAtoms.h | 75 ++++ content/xbl/src/nsXBLBinding.cpp | 114 +---- content/xbl/src/nsXBLBinding.h | 25 -- content/xbl/src/nsXBLContentSink.cpp | 310 +++++++++++++ content/xbl/src/nsXBLContentSink.h | 108 +++++ content/xbl/src/nsXBLDocumentInfo.cpp | 389 +++++++++++++++++ content/xbl/src/nsXBLDocumentInfo.h | 38 ++ content/xbl/src/nsXBLEventHandler.cpp | 55 +-- content/xbl/src/nsXBLEventHandler.h | 11 - content/xbl/src/nsXBLPrototypeBinding.cpp | 172 +++----- content/xbl/src/nsXBLPrototypeBinding.h | 28 +- content/xbl/src/nsXBLPrototypeHandler.cpp | 333 +++++++------- content/xbl/src/nsXBLPrototypeHandler.h | 82 ++-- content/xbl/src/nsXBLService.cpp | 150 ++----- content/xbl/src/nsXBLService.h | 6 +- content/xbl/src/nsXBLWindowHandler.cpp | 31 +- content/xbl/src/nsXBLWindowKeyHandler.cpp | 36 +- content/xbl/src/nsXBLXULHandler.cpp | 3 +- content/xml/document/src/nsXMLContentSink.cpp | 3 + content/xml/document/src/nsXMLContentSink.h | 2 + content/xml/document/src/nsXMLDocument.cpp | 23 +- content/xml/document/src/nsXMLDocument.h | 3 +- content/xul/document/src/nsXULDocument.cpp | 3 +- content/xul/document/src/nsXULDocument.h | 3 +- layout/base/nsCSSFrameConstructor.cpp | 3 + layout/build/nsLayoutModule.cpp | 3 + .../html/style/src/nsCSSFrameConstructor.cpp | 3 + 52 files changed, 1915 insertions(+), 1097 deletions(-) create mode 100644 content/shared/public/nsXBLAtomList.h create mode 100644 content/shared/public/nsXBLAtoms.h create mode 100644 content/shared/src/nsXBLAtoms.cpp create mode 100644 content/xbl/src/nsXBLAtomList.h create mode 100644 content/xbl/src/nsXBLAtoms.cpp create mode 100644 content/xbl/src/nsXBLAtoms.h create mode 100644 content/xbl/src/nsXBLContentSink.cpp create mode 100644 content/xbl/src/nsXBLContentSink.h create mode 100644 content/xbl/src/nsXBLDocumentInfo.cpp create mode 100644 content/xbl/src/nsXBLDocumentInfo.h diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 9c050b8432fe..9312ae7474cf 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -80,6 +80,7 @@ class nsISupportsArray; class nsIScriptLoader; class nsString; class nsIFocusController; +class nsIContentSink; // IID for the nsIDocument interface #define NS_IDOCUMENT_IID \ @@ -109,7 +110,8 @@ public: nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset) = 0; + PRBool aReset, + nsIContentSink* aSink = nsnull) = 0; NS_IMETHOD StopDocumentLoad() = 0; diff --git a/content/base/public/nsINameSpaceManager.h b/content/base/public/nsINameSpaceManager.h index 72ced4078a15..5519e3c8785e 100644 --- a/content/base/public/nsINameSpaceManager.h +++ b/content/base/public/nsINameSpaceManager.h @@ -55,6 +55,7 @@ class nsIElementFactory; #define kNameSpaceID_XLink 4 #define kNameSpaceID_HTML2 5 // This is not a real namespace #define kNameSpaceID_XSLT 6 +#define kNameSpaceID_XBL 7 #define kNameSpaceID_XHTML kNameSpaceID_HTML // 'html' is by definition bound to the namespace name "urn:w3-org-ns:HTML" XXX ??? diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index caf35b2ec0c7..c349fa809bea 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -719,7 +719,8 @@ nsDocument::StartDocumentLoad(const char* aCommand, nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset) + PRBool aReset, + nsIContentSink* aSink) { nsresult rv = NS_OK; if (aReset) @@ -3268,7 +3269,6 @@ PRBool nsDocument::InternalRegisterCompileEventHandler(JSContext* aContext, jsv } #endif - NS_IMETHODIMP nsDocument::SaveFile( nsIURI* aLocation, PRBool aReplaceExisting, // only used for local file locations diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 7383e613fa54..913bb0c6e81c 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -248,7 +248,8 @@ public: nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset = PR_TRUE); + PRBool aReset = PR_TRUE, + nsIContentSink* aContentSink = nsnull); NS_IMETHOD StopDocumentLoad(); diff --git a/content/base/src/nsNameSpaceManager.cpp b/content/base/src/nsNameSpaceManager.cpp index 9151b3eb9c46..a8949712182f 100644 --- a/content/base/src/nsNameSpaceManager.cpp +++ b/content/base/src/nsNameSpaceManager.cpp @@ -58,6 +58,7 @@ static const char kHTMLNameSpaceURI[] = "http://www.w3.org/TR/REC-html40"; // X static const char kXHTMLNameSpaceURI[] = "http://www.w3.org/1999/xhtml"; static const char kXLinkNameSpaceURI[] = "http://www.w3.org/1999/xlink"; static const char kXSLTNameSpaceURI[] = "http://www.w3.org/1999/XSL/Transform"; +static const char kXBLNameSpaceURI[] = "http://www.mozilla.org/xbl"; //----------------------------------------------------------- // Name Space ID table support @@ -89,24 +90,31 @@ static void InitializeNameSpaceManager() nsString* xlink = new nsString( NS_ConvertASCIItoUCS2(kXLinkNameSpaceURI) ); nsString* html = new nsString( NS_ConvertASCIItoUCS2(kHTMLNameSpaceURI) ); nsString* xslt = new nsString( NS_ConvertASCIItoUCS2(kXSLTNameSpaceURI) ); + nsString* xbl = new nsString(NS_ConvertASCIItoUCS2(kXBLNameSpaceURI)); + gURIArray->AppendElement(xmlns); // ordering here needs to match IDs gURIArray->AppendElement(xml); gURIArray->AppendElement(xhtml); gURIArray->AppendElement(xlink); gURIArray->AppendElement(html); gURIArray->AppendElement(xslt); + gURIArray->AppendElement(xbl); + nsStringKey xmlnsKey(*xmlns); nsStringKey xmlKey(*xml); nsStringKey xhtmlKey(*xhtml); nsStringKey xlinkKey(*xlink); nsStringKey htmlKey(*html); nsStringKey xsltKey(*xslt); + nsStringKey xblKey(*xbl); + gURIToIDTable->Put(&xmlnsKey, (void*)kNameSpaceID_XMLNS); gURIToIDTable->Put(&xmlKey, (void*)kNameSpaceID_XML); gURIToIDTable->Put(&xhtmlKey, (void*)kNameSpaceID_HTML); gURIToIDTable->Put(&xlinkKey, (void*)kNameSpaceID_XLink); gURIToIDTable->Put(&htmlKey, (void*)kNameSpaceID_HTML); gURIToIDTable->Put(&xsltKey, (void*)kNameSpaceID_XSLT); + gURIToIDTable->Put(&xblKey, (void*)kNameSpaceID_XBL); NS_NewISupportsArray(&gElementFactoryArray); diff --git a/content/build/nsContentModule.cpp b/content/build/nsContentModule.cpp index 55c8fd7150ce..3d0065842511 100644 --- a/content/build/nsContentModule.cpp +++ b/content/build/nsContentModule.cpp @@ -36,6 +36,7 @@ * the terms of any one of the NPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ +#include "nsXBLAtoms.h" // to addref/release table #include "nsCSSAtoms.h" // to addref/release table #include "nsCSSKeywords.h" // to addref/release table #include "nsCSSProps.h" // to addref/release table @@ -170,6 +171,7 @@ Initialize(nsIModule* aSelf) nsCSSProps::AddRefTable(); nsColorNames::AddRefTable(); nsHTMLAtoms::AddRefAtoms(); + nsXBLAtoms::AddRefAtoms(); nsLayoutAtoms::AddRefAtoms(); #ifdef MOZ_XUL @@ -213,6 +215,7 @@ Shutdown(nsIModule* aSelf) nsCSSKeywords::ReleaseTable(); nsCSSAtoms::ReleaseAtoms(); nsHTMLAtoms::ReleaseAtoms(); + nsXBLAtoms::ReleaseAtoms(); nsLayoutAtoms::ReleaseAtoms(); #ifdef MOZ_XUL diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 9124a591451e..32192dd85b52 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -401,7 +401,8 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand, nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset) + PRBool aReset, + nsIContentSink* aSink) { PRBool needsParser=PR_TRUE; if (aCommand) @@ -821,9 +822,15 @@ nsHTMLDocument::StartDocumentLoad(const char* aCommand, mParser->SetCommand(aCommand); // create the content sink nsCOMPtr webShell(do_QueryInterface(docShell)); - rv = NS_NewHTMLContentSink(getter_AddRefs(sink), this, aURL, webShell,aChannel); - if (NS_FAILED(rv)) { return rv; } - NS_ASSERTION(sink, "null sink with successful result from factory method"); + + if (aSink) + sink = do_QueryInterface(aSink); + else { + rv = NS_NewHTMLContentSink(getter_AddRefs(sink), this, aURL, webShell,aChannel); + if (NS_FAILED(rv)) { return rv; } + NS_ASSERTION(sink, "null sink with successful result from factory method"); + } + mParser->SetContentSink(sink); // parser the content of the URL mParser->Parse(aURL, nsnull, PR_FALSE, (void *)this); diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 18f0455940fc..194d8beaffad 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -91,7 +91,8 @@ public: nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset = PR_TRUE); + PRBool aReset = PR_TRUE, + nsIContentSink* aSink = nsnull); NS_IMETHOD StopDocumentLoad(); diff --git a/content/html/document/src/nsImageDocument.cpp b/content/html/document/src/nsImageDocument.cpp index c69e2b8571f9..411c7ad69532 100644 --- a/content/html/document/src/nsImageDocument.cpp +++ b/content/html/document/src/nsImageDocument.cpp @@ -98,7 +98,8 @@ public: nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset = PR_TRUE); + PRBool aReset = PR_TRUE, + nsIContentSink* aSink = nsnull); nsresult CreateSyntheticDocument(); @@ -249,7 +250,8 @@ nsImageDocument::StartDocumentLoad(const char* aCommand, nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset) + PRBool aReset, + nsIContentSink* aSink) { NS_ASSERTION(aDocListener, "null aDocListener"); NS_ENSURE_ARG_POINTER(aContainer); @@ -262,7 +264,7 @@ nsImageDocument::StartDocumentLoad(const char* aCommand, } rv = nsDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup, - aContainer, aDocListener, aReset); + aContainer, aDocListener, aReset, aSink); if (NS_FAILED(rv)) { return rv; } diff --git a/content/shared/public/MANIFEST b/content/shared/public/MANIFEST index 232882800c52..f94480fff62a 100644 --- a/content/shared/public/MANIFEST +++ b/content/shared/public/MANIFEST @@ -22,3 +22,6 @@ nsStyleStruct.h nsTextFragment.h nsXULAtomList.h nsXULAtoms.h +nsXBLAtomList.h +nsXBLAtoms.h + diff --git a/content/shared/public/Makefile.in b/content/shared/public/Makefile.in index a892d704ac28..781b7feaf4b1 100644 --- a/content/shared/public/Makefile.in +++ b/content/shared/public/Makefile.in @@ -50,6 +50,8 @@ nsStyleStruct.h \ nsTextFragment.h \ nsXULAtomList.h \ nsXULAtoms.h \ +nsXBLAtomList.h \ +nsXBLAtoms.h \ $(NULL) EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS)) diff --git a/content/shared/public/makefile.win b/content/shared/public/makefile.win index 3d263768c5cf..b518d1937768 100644 --- a/content/shared/public/makefile.win +++ b/content/shared/public/makefile.win @@ -43,6 +43,8 @@ EXPORTS = \ nsTextFragment.h \ nsXULAtomList.h \ nsXULAtoms.h \ + nsXBLAtomList.h \ + nsXBLAtoms.h \ $(NULL) include <$(DEPTH)\config\rules.mak> diff --git a/content/shared/public/nsXBLAtomList.h b/content/shared/public/nsXBLAtomList.h new file mode 100644 index 000000000000..148023deae0d --- /dev/null +++ b/content/shared/public/nsXBLAtomList.h @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Original Author: David W. Hyatt (hyatt@netscape.com) + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/****** + + This file contains the list of all XBL nsIAtoms and their values + + It is designed to be used as inline input to nsXBLAtoms.cpp *only* + through the magic of C preprocessing. + + All entires must be enclosed in the macro XBL_ATOM which will have cruel + and unusual things done to it + + It is recommended (but not strictly necessary) to keep all entries + in alphabetical order + + The first argument to XBL_ATOM is the C++ identifier of the atom + The second argument is the string value of the atom + + ******/ + + +XBL_ATOM(binding, "binding") +XBL_ATOM(bindings, "bindings") +XBL_ATOM(handlers, "handlers") +XBL_ATOM(handler, "handler") +XBL_ATOM(resources, "resources") +XBL_ATOM(image, "image") +XBL_ATOM(stylesheet, "stylesheet") +XBL_ATOM(implementation, "implementation") +XBL_ATOM(implements, "implements") +XBL_ATOM(xbltext, "xbl:text") +XBL_ATOM(method, "method") +XBL_ATOM(property, "property") +XBL_ATOM(field, "field") +XBL_ATOM(event, "event") +XBL_ATOM(phase, "phase") +XBL_ATOM(action, "action") +XBL_ATOM(command, "command") +XBL_ATOM(modifiers, "modifiers") +XBL_ATOM(clickcount, "clickcount") +XBL_ATOM(charcode, "charcode") +XBL_ATOM(keycode, "keycode") +XBL_ATOM(key, "key") +XBL_ATOM(onget, "onget") +XBL_ATOM(onset, "onset") +XBL_ATOM(name, "name") +XBL_ATOM(getter, "getter") +XBL_ATOM(setter, "setter") +XBL_ATOM(body, "body") +XBL_ATOM(readonly, "readonly") +XBL_ATOM(parameter, "parameter") +XBL_ATOM(children, "children") +XBL_ATOM(extends, "extends") +XBL_ATOM(display, "display") +XBL_ATOM(inherits, "inherits") +XBL_ATOM(includes, "includes") +XBL_ATOM(excludes, "excludes") +XBL_ATOM(content, "content") +XBL_ATOM(constructor, "constructor") +XBL_ATOM(destructor, "destructor") +XBL_ATOM(inheritstyle, "inheritstyle") + + + diff --git a/content/shared/public/nsXBLAtoms.h b/content/shared/public/nsXBLAtoms.h new file mode 100644 index 000000000000..84a3a5458130 --- /dev/null +++ b/content/shared/public/nsXBLAtoms.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Original Author: David W. Hyatt (hyatt@netscape.com) + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsXBLAtoms_h___ +#define nsXBLAtoms_h___ + +#include "prtypes.h" +#include "nsIAtom.h" + +class nsINameSpaceManager; + +/** + * This class wraps up the creation and destruction of the standard + * set of XBL atoms used during normal XBL handling. This object + * is created when the first XBL content object is created, and + * destroyed when the last such content object is destroyed. + */ +class nsXBLAtoms { +public: + + static void AddRefAtoms(); + static void ReleaseAtoms(); + + // XBL namespace ID, good for the life of the nsXBLAtoms object + static PRInt32 nameSpaceID; + + /* Declare all atoms + + The atom names and values are stored in nsCSSAtomList.h and + are brought to you by the magic of C preprocessing + + Add new atoms to nsCSSAtomList and all support logic will be auto-generated + */ +#define XBL_ATOM(_name, _value) static nsIAtom* _name; +#include "nsXBLAtomList.h" +#undef XBL_ATOM + +}; + +#endif /* nsXBLAtoms_h___ */ diff --git a/content/shared/src/Makefile.in b/content/shared/src/Makefile.in index ffbc10725dbd..794e931b47f1 100644 --- a/content/shared/src/Makefile.in +++ b/content/shared/src/Makefile.in @@ -56,6 +56,7 @@ CPPSRCS = \ nsStyleUtil.cpp \ nsTextFragment.cpp \ nsXULAtoms.cpp \ + nsXBLAtoms.cpp \ nsStyleCoord.cpp \ nsStyleStruct.cpp \ $(NULL) diff --git a/content/shared/src/makefile.win b/content/shared/src/makefile.win index 94d16b025993..4de31d9ac466 100644 --- a/content/shared/src/makefile.win +++ b/content/shared/src/makefile.win @@ -57,6 +57,7 @@ CPPSRCS = \ nsStyleStruct.cpp \ nsTextFragment.cpp \ nsXULAtoms.cpp \ + nsXBLAtoms.cpp \ nsStyleCoord.cpp \ $(NULL) @@ -74,6 +75,7 @@ CPP_OBJS= \ .\$(OBJDIR)\nsStyleStruct.obj \ .\$(OBJDIR)\nsTextFragment.obj \ .\$(OBJDIR)\nsXULAtoms.obj \ + .\$(OBJDIR)\nsXBLAtoms.obj \ .\$(OBJDIR)\nsStyleCoord.obj \ $(NULL) diff --git a/content/shared/src/nsXBLAtoms.cpp b/content/shared/src/nsXBLAtoms.cpp new file mode 100644 index 000000000000..94e468d8d4a8 --- /dev/null +++ b/content/shared/src/nsXBLAtoms.cpp @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Original Author: David W. Hyatt (hyatt@netscape.com) + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsString.h" +#include "nsXBLAtoms.h" +#include "nsContentCID.h" + +// define storage for all atoms +#define XBL_ATOM(_name, _value) nsIAtom* nsXBLAtoms::_name; +#include "nsXBLAtomList.h" +#undef XBL_ATOM + + +static nsrefcnt gRefCnt = 0; + +void nsXBLAtoms::AddRefAtoms() { + + if (gRefCnt == 0) { + // now register the atoms +#define XBL_ATOM(_name, _value) _name = NS_NewPermanentAtom(_value); +#include "nsXBLAtomList.h" +#undef XBL_ATOM + } + ++gRefCnt; +} + +void nsXBLAtoms::ReleaseAtoms() { + + NS_PRECONDITION(gRefCnt != 0, "bad release of XBL atoms"); + if (--gRefCnt == 0) { +#define XBL_ATOM(_name, _value) NS_RELEASE(_name); +#include "nsXBLAtomList.h" +#undef XBL_ATOM + } +} diff --git a/content/xbl/public/nsIBindingManager.h b/content/xbl/public/nsIBindingManager.h index 2f56b10498e7..054089f3432a 100644 --- a/content/xbl/public/nsIBindingManager.h +++ b/content/xbl/public/nsIBindingManager.h @@ -162,6 +162,7 @@ public: NS_IMETHOD ExecuteDetachedHandlers()=0; NS_IMETHOD PutXBLDocumentInfo(nsIXBLDocumentInfo* aDocumentInfo)=0; + NS_IMETHOD RemoveXBLDocumentInfo(nsIXBLDocumentInfo* aDocumentInfo)=0; NS_IMETHOD GetXBLDocumentInfo(const nsCString& aURL, nsIXBLDocumentInfo** aResult)=0; NS_IMETHOD PutLoadingDocListener(const nsCString& aURL, nsIStreamListener* aListener) = 0; diff --git a/content/xbl/public/nsIXBLPrototypeBinding.h b/content/xbl/public/nsIXBLPrototypeBinding.h index be43f0c87f25..a3a705122ce6 100644 --- a/content/xbl/public/nsIXBLPrototypeBinding.h +++ b/content/xbl/public/nsIXBLPrototypeBinding.h @@ -126,6 +126,8 @@ public: NS_IMETHOD AddResourceListener(nsIContent* aBoundElement)=0; NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult)=0; + + NS_IMETHOD Initialize()=0; }; extern nsresult diff --git a/content/xbl/public/nsIXBLPrototypeHandler.h b/content/xbl/public/nsIXBLPrototypeHandler.h index a6287dd29d6a..0937d90834ce 100644 --- a/content/xbl/public/nsIXBLPrototypeHandler.h +++ b/content/xbl/public/nsIXBLPrototypeHandler.h @@ -46,6 +46,8 @@ #ifndef nsIXBLPrototypeHandler_h__ #define nsIXBLPrototypeHandler_h__ +#include "nsAReadableString.h" + class nsIContent; class nsIDOMEvent; class nsIDOMMouseEvent; @@ -67,6 +69,9 @@ public: NS_IMETHOD KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aEvent, PRBool* aResult) = 0; NS_IMETHOD GetHandlerElement(nsIContent** aResult) = 0; + NS_IMETHOD SetHandlerText(const nsAReadableString& aText) = 0; + + NS_IMETHOD GetPhase(PRUint8* aPhase) = 0; NS_IMETHOD BindingAttached(nsIDOMEventReceiver* aRec)=0; NS_IMETHOD BindingDetached(nsIDOMEventReceiver* aRec)=0; @@ -81,6 +86,14 @@ public: }; extern nsresult -NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult); +NS_NewXBLPrototypeHandler(nsAReadableString* aEvent, nsAReadableString* aPhase, + nsAReadableString* aAction, nsAReadableString* aCommand, + nsAReadableString* aKeyCode, nsAReadableString* aCharCode, + nsAReadableString* aModifiers, nsAReadableString* aButton, + nsAReadableString* aClickCount, + nsIXBLPrototypeHandler** aResult); + +extern nsresult +NS_NewXULKeyHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult); #endif // nsIXBLPrototypeHandler_h__ diff --git a/content/xbl/src/Makefile.in b/content/xbl/src/Makefile.in index f4c523c9dcbe..6ed7e0b3252f 100644 --- a/content/xbl/src/Makefile.in +++ b/content/xbl/src/Makefile.in @@ -29,29 +29,33 @@ include $(DEPTH)/config/autoconf.mk MODULE = content LIBRARY_NAME = gkconxbl_s REQUIRES = xpcom \ - string \ - js \ - dom \ - gfx \ - layout \ - widget \ - caps \ - htmlparser \ - necko \ - xpconnect \ - pref \ - docshell \ - chrome \ - lwbrk \ - xul \ - xuldoc \ - gfx2 \ - imglib2 \ - $(NULL) + string \ + js \ + dom \ + gfx \ + layout \ + widget \ + view \ + caps \ + htmlparser \ + necko \ + xpconnect \ + pref \ + docshell \ + chrome \ + lwbrk \ + xul \ + xuldoc \ + gfx2 \ + imglib2 \ + unicharutil \ + $(NULL) CPPSRCS = \ nsXBLBinding.cpp \ nsXBLPrototypeBinding.cpp \ + nsXBLDocumentInfo.cpp \ + nsXBLContentSink.cpp \ nsXBLPrototypeProperty.cpp \ nsXBLEventHandler.cpp \ nsXBLWindowHandler.cpp \ @@ -68,10 +72,10 @@ CPPSRCS = \ nsXBLXULHandler.cpp \ nsXBLFormHandler.cpp \ nsXBLScrollHandler.cpp \ - nsXBLContextMenuHandler.cpp \ - nsXBLService.cpp \ - nsBindingManager.cpp \ - nsXBLInsertionPoint.cpp \ + nsXBLContextMenuHandler.cpp \ + nsXBLService.cpp \ + nsBindingManager.cpp \ + nsXBLInsertionPoint.cpp \ $(NULL) include $(topsrcdir)/config/config.mk @@ -89,5 +93,6 @@ LOCAL_INCLUDES = \ -I$(srcdir)/../../html/base/src \ -I$(srcdir)/../../html/document/src \ -I$(srcdir)/../../xml/document/src \ + -I$(srcdir)/../../xsl/document/src \ $(NULL) diff --git a/content/xbl/src/makefile.win b/content/xbl/src/makefile.win index 18f2decf908a..49342e8b2ff3 100644 --- a/content/xbl/src/makefile.win +++ b/content/xbl/src/makefile.win @@ -24,30 +24,34 @@ DEPTH=..\..\.. LIBRARY_NAME=contentxbl_s MODULE=content REQUIRES = xpcom \ - string \ - js \ - dom \ - widget \ - caps \ - htmlparser \ - necko \ - xpconnect \ - pref \ - docshell \ - chrome \ - lwbrk \ - gfx2 \ - imglib2 \ - layout \ - gfx \ - content_xul \ - $(NULL) + string \ + js \ + dom \ + widget \ + view \ + caps \ + htmlparser \ + necko \ + xpconnect \ + pref \ + docshell \ + chrome \ + lwbrk \ + gfx2 \ + imglib2 \ + layout \ + gfx \ + content_xul \ + unicharutil \ + $(NULL) DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN CPPSRCS= \ nsXBLBinding.cpp \ nsXBLPrototypeBinding.cpp \ + nsXBLDocumentInfo.cpp \ + nsXBLContentSink.cpp \ nsXBLService.cpp \ nsXBLEventHandler.cpp \ nsXBLWindowHandler.cpp \ @@ -73,6 +77,8 @@ CPPSRCS= \ CPP_OBJS= \ .\$(OBJDIR)\nsXBLBinding.obj \ .\$(OBJDIR)\nsXBLPrototypeBinding.obj \ + .\$(OBJDIR)\nsXBLDocumentInfo.obj \ + .\$(OBJDIR)\nsXBLContentSink.obj \ .\$(OBJDIR)\nsXBLEventHandler.obj \ .\$(OBJDIR)\nsXBLWindowHandler.obj \ .\$(OBJDIR)\nsXBLWindowKeyHandler.obj \ @@ -99,8 +105,9 @@ EXPORTS = \ $(NULL) LINCS=-I..\..\html\style\src -I..\..\html\base\src \ - -I..\..\html\document\src \ + -I..\..\html\document\src \ -I..\..\xml\document\src \ + -I..\..\xsl\document\src \ -I..\..\base\src \ $(NULL) diff --git a/content/xbl/src/nsBindingManager.cpp b/content/xbl/src/nsBindingManager.cpp index 8ef786b52b9c..3f4968241bff 100644 --- a/content/xbl/src/nsBindingManager.cpp +++ b/content/xbl/src/nsBindingManager.cpp @@ -97,394 +97,6 @@ static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID); static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); static NS_DEFINE_CID(kParserCID, NS_PARSER_CID); -// an XBLDocumentInfo object has a special context associated with it which we can use to pre-compile properties and methods -// of XBL widgets against..... - - -static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); - - -class nsXBLDocGlobalObject : public nsIScriptGlobalObject, - public nsIScriptObjectPrincipal -{ -public: - nsXBLDocGlobalObject(); - - // nsISupports interface - NS_DECL_ISUPPORTS - - // nsIScriptGlobalObject methods - NS_IMETHOD SetContext(nsIScriptContext *aContext); - NS_IMETHOD GetContext(nsIScriptContext **aContext); - NS_IMETHOD SetNewDocument(nsIDOMDocument *aDocument, - PRBool removeEventListeners); - NS_IMETHOD SetDocShell(nsIDocShell *aDocShell); - NS_IMETHOD GetDocShell(nsIDocShell **aDocShell); - NS_IMETHOD SetOpenerWindow(nsIDOMWindowInternal *aOpener); - NS_IMETHOD SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner); - NS_IMETHOD GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner); - NS_IMETHOD HandleDOMEvent(nsIPresContext* aPresContext, - nsEvent* aEvent, - nsIDOMEvent** aDOMEvent, - PRUint32 aFlags, - nsEventStatus* aEventStatus); - NS_IMETHOD_(JSObject *) GetGlobalJSObject(); - NS_IMETHOD OnFinalize(JSObject *aObject); - - // nsIScriptObjectPrincipal methods - NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal); - -protected: - virtual ~nsXBLDocGlobalObject(); - - nsCOMPtr mScriptContext; - JSObject *mJSObject; // XXX JS language rabies bigotry badness - - nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // weak reference - static JSClass gSharedGlobalClass; -}; - -void PR_CALLBACK nsXBLDocGlobalObject_finalize(JSContext *cx, JSObject *obj) -{ - nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(cx, obj); - - nsCOMPtr sgo(do_QueryInterface(nativeThis)); - - if (sgo) - sgo->OnFinalize(obj); - - // The addref was part of JSObject construction - NS_RELEASE(nativeThis); -} - - -JSBool PR_CALLBACK nsXBLDocGlobalObject_resolve(JSContext *cx, JSObject *obj, jsval id) -{ - JSBool did_resolve = JS_FALSE; - return JS_ResolveStandardClass(cx, obj, id, &did_resolve); -} - - -JSClass nsXBLDocGlobalObject::gSharedGlobalClass = { - "nsXBLPrototypeScript compilation scope", - JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS, - JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, - JS_EnumerateStub, nsXBLDocGlobalObject_resolve, JS_ConvertStub, - nsXBLDocGlobalObject_finalize -}; - -//---------------------------------------------------------------------- -// -// nsXBLDocGlobalObject -// - -nsXBLDocGlobalObject::nsXBLDocGlobalObject() - : mJSObject(nsnull), - mGlobalObjectOwner(nsnull) -{ - NS_INIT_REFCNT(); -} - - -nsXBLDocGlobalObject::~nsXBLDocGlobalObject() -{} - - -NS_IMPL_ISUPPORTS2(nsXBLDocGlobalObject, nsIScriptGlobalObject, nsIScriptObjectPrincipal) - -//---------------------------------------------------------------------- -// -// nsIScriptGlobalObject methods -// - -NS_IMETHODIMP -nsXBLDocGlobalObject::SetContext(nsIScriptContext *aContext) -{ - mScriptContext = aContext; - return NS_OK; -} - - -NS_IMETHODIMP -nsXBLDocGlobalObject::GetContext(nsIScriptContext **aContext) -{ - // This whole fragile mess is predicated on the fact that - // GetContext() will be called before GetScriptObject() is. - if (! mScriptContext) { - nsCOMPtr factory = do_GetService(kDOMScriptObjectFactoryCID); - NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE); - - nsresult rv = factory->NewScriptContext(nsnull, getter_AddRefs(mScriptContext)); - if (NS_FAILED(rv)) - return rv; - - JSContext *cx = (JSContext *)mScriptContext->GetNativeContext(); - - mJSObject = ::JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull); - if (!mJSObject) - return NS_ERROR_OUT_OF_MEMORY; - - ::JS_SetGlobalObject(cx, mJSObject); - - // Add an owning reference from JS back to us. This'll be - // released when the JSObject is finalized. - ::JS_SetPrivate(cx, mJSObject, this); - NS_ADDREF(this); - } - - *aContext = mScriptContext; - NS_IF_ADDREF(*aContext); - return NS_OK; -} - - -NS_IMETHODIMP -nsXBLDocGlobalObject::SetNewDocument(nsIDOMDocument *aDocument, - PRBool removeEventListeners) -{ - NS_NOTREACHED("waaah!"); - return NS_ERROR_UNEXPECTED; -} - - -NS_IMETHODIMP -nsXBLDocGlobalObject::SetDocShell(nsIDocShell *aDocShell) -{ - NS_NOTREACHED("waaah!"); - return NS_ERROR_UNEXPECTED; -} - - -NS_IMETHODIMP -nsXBLDocGlobalObject::GetDocShell(nsIDocShell **aDocShell) -{ - NS_WARNING("waaah!"); - return NS_ERROR_UNEXPECTED; -} - - -NS_IMETHODIMP -nsXBLDocGlobalObject::SetOpenerWindow(nsIDOMWindowInternal *aOpener) -{ - NS_NOTREACHED("waaah!"); - return NS_ERROR_UNEXPECTED; -} - - -NS_IMETHODIMP -nsXBLDocGlobalObject::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner) -{ - mGlobalObjectOwner = aOwner; // weak reference - return NS_OK; -} - - -NS_IMETHODIMP -nsXBLDocGlobalObject::GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner) -{ - *aOwner = mGlobalObjectOwner; - NS_IF_ADDREF(*aOwner); - return NS_OK; -} - - -NS_IMETHODIMP -nsXBLDocGlobalObject::HandleDOMEvent(nsIPresContext* aPresContext, - nsEvent* aEvent, - nsIDOMEvent** aDOMEvent, - PRUint32 aFlags, - nsEventStatus* aEventStatus) -{ - NS_NOTREACHED("waaah!"); - return NS_ERROR_UNEXPECTED; -} - -NS_IMETHODIMP_(JSObject *) -nsXBLDocGlobalObject::GetGlobalJSObject() -{ - // The prototype document has its own special secret script object - // that can be used to compile scripts and event handlers. - - if (!mScriptContext) - return nsnull; - - JSContext* cx = NS_REINTERPRET_CAST(JSContext*, - mScriptContext->GetNativeContext()); - if (!cx) - return nsnull; - - return ::JS_GetGlobalObject(cx); -} - -NS_IMETHODIMP -nsXBLDocGlobalObject::OnFinalize(JSObject *aObject) -{ - NS_ASSERTION(aObject == mJSObject, "Wrong object finalized!"); - - mJSObject = nsnull; - - return NS_OK; -} - -//---------------------------------------------------------------------- -// -// nsIScriptObjectPrincipal methods -// - -NS_IMETHODIMP -nsXBLDocGlobalObject::GetPrincipal(nsIPrincipal** aPrincipal) -{ - nsresult rv = NS_OK; - if (!mGlobalObjectOwner) { - *aPrincipal = nsnull; - return NS_ERROR_FAILURE; - } - - nsCOMPtr docInfo = do_QueryInterface(mGlobalObjectOwner, &rv); - NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); - - nsCOMPtr document; - rv = docInfo->GetDocument(getter_AddRefs(document)); - NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); - - return document->GetPrincipal(aPrincipal); -} - -///////////////////////////////////////////////////////////////////////////////////////////////////// - -class nsXBLDocumentInfo : public nsIXBLDocumentInfo, public nsIScriptGlobalObjectOwner, public nsSupportsWeakReference -{ -public: - NS_DECL_ISUPPORTS - - nsXBLDocumentInfo(const char* aDocURI, nsIDocument* aDocument); - virtual ~nsXBLDocumentInfo(); - - NS_IMETHOD GetDocument(nsIDocument** aResult) { *aResult = mDocument; NS_IF_ADDREF(*aResult); return NS_OK; }; - - NS_IMETHOD GetScriptAccess(PRBool* aResult) { *aResult = mScriptAccess; return NS_OK; }; - NS_IMETHOD SetScriptAccess(PRBool aAccess) { mScriptAccess = aAccess; return NS_OK; }; - - NS_IMETHOD GetDocumentURI(nsCString& aDocURI) { aDocURI = mDocURI; return NS_OK; }; - - NS_IMETHOD GetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding** aResult); - NS_IMETHOD SetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding* aBinding); - - // nsIScriptGlobalObjectOwner methods - NS_DECL_NSISCRIPTGLOBALOBJECTOWNER - -private: - nsCOMPtr mDocument; - nsCString mDocURI; - PRBool mScriptAccess; - nsSupportsHashtable* mBindingTable; - - nsCOMPtr mGlobalObject; -}; - -/* Implementation file */ -NS_IMPL_ISUPPORTS3(nsXBLDocumentInfo, nsIXBLDocumentInfo, nsIScriptGlobalObjectOwner, nsISupportsWeakReference) - -nsXBLDocumentInfo::nsXBLDocumentInfo(const char* aDocURI, nsIDocument* aDocument) -{ - NS_INIT_ISUPPORTS(); - /* member initializers and constructor code */ - mDocURI = aDocURI; - mDocument = aDocument; - mScriptAccess = PR_TRUE; - mBindingTable = nsnull; -} - -nsXBLDocumentInfo::~nsXBLDocumentInfo() -{ - /* destructor code */ - if (mGlobalObject) { - mGlobalObject->SetContext(nsnull); // remove circular reference - mGlobalObject->SetGlobalObjectOwner(nsnull); // just in case - } - delete mBindingTable; -} - -NS_IMETHODIMP -nsXBLDocumentInfo::GetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding** aResult) -{ - *aResult = nsnull; - if (!mBindingTable) - return NS_OK; - - const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); - nsCStringKey key(flat.get()); - *aResult = NS_STATIC_CAST(nsIXBLPrototypeBinding*, mBindingTable->Get(&key)); // Addref happens here. - - return NS_OK; -} - -NS_IMETHODIMP -nsXBLDocumentInfo::SetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding* aBinding) -{ - if (!mBindingTable) - mBindingTable = new nsSupportsHashtable(); - - const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); - nsCStringKey key(flat.get()); - mBindingTable->Put(&key, aBinding); - - return NS_OK; -} - -//---------------------------------------------------------------------- -// -// nsIScriptGlobalObjectOwner methods -// - -NS_IMETHODIMP -nsXBLDocumentInfo::GetScriptGlobalObject(nsIScriptGlobalObject** _result) -{ - if (!mGlobalObject) { - - mGlobalObject = new nsXBLDocGlobalObject(); - - if (!mGlobalObject) { - *_result = nsnull; - return NS_ERROR_OUT_OF_MEMORY; - } - - mGlobalObject->SetGlobalObjectOwner(this); // does not refcount - } - - *_result = mGlobalObject; - NS_ADDREF(*_result); - return NS_OK; -} - -NS_IMETHODIMP -nsXBLDocumentInfo::ReportScriptError(nsIScriptError *errorObject) -{ - if (errorObject == nsnull) - return NS_ERROR_NULL_POINTER; - - // Get the console service, where we're going to register the error. - nsCOMPtr consoleService (do_GetService("@mozilla.org/consoleservice;1")); - - if (!consoleService) - return NS_ERROR_NOT_AVAILABLE; - return consoleService->LogMessage(errorObject); -} - -nsresult NS_NewXBLDocumentInfo(nsIDocument* aDocument, nsIXBLDocumentInfo** aResult) -{ - nsCOMPtr url; - aDocument->GetDocumentURL(getter_AddRefs(url)); - - nsXPIDLCString str; - url->GetSpec(getter_Copies(str)); - - *aResult = new nsXBLDocumentInfo((const char*)str, aDocument); - - NS_IF_ADDREF(*aResult); - return NS_OK; -} - // ================================================================== // = nsAnonymousContentList // ================================================================== @@ -661,6 +273,7 @@ public: NS_IMETHOD PutXBLDocumentInfo(nsIXBLDocumentInfo* aDocumentInfo); NS_IMETHOD GetXBLDocumentInfo(const nsCString& aURL, nsIXBLDocumentInfo** aResult); + NS_IMETHOD RemoveXBLDocumentInfo(nsIXBLDocumentInfo* aDocumentInfo); NS_IMETHOD PutLoadingDocListener(const nsCString& aURL, nsIStreamListener* aListener); NS_IMETHOD GetLoadingDocListener(const nsCString& aURL, nsIStreamListener** aResult); @@ -1351,6 +964,25 @@ nsBindingManager::PutXBLDocumentInfo(nsIXBLDocumentInfo* aDocumentInfo) return NS_OK; } +NS_IMETHODIMP +nsBindingManager::RemoveXBLDocumentInfo(nsIXBLDocumentInfo* aDocumentInfo) +{ + if (!mDocumentTable) + return NS_OK; + + nsCOMPtr doc; + aDocumentInfo->GetDocument(getter_AddRefs(doc)); + + nsCOMPtr uri; + doc->GetDocumentURL(getter_AddRefs(uri)); + nsXPIDLCString str; + uri->GetSpec(getter_Copies(str)); + + nsCStringKey key((const char*)str); + mDocumentTable->Remove(&key); + return NS_OK; +} + NS_IMETHODIMP nsBindingManager::GetXBLDocumentInfo(const nsCString& aURL, nsIXBLDocumentInfo** aResult) { diff --git a/content/xbl/src/nsXBLAtomList.h b/content/xbl/src/nsXBLAtomList.h new file mode 100644 index 000000000000..148023deae0d --- /dev/null +++ b/content/xbl/src/nsXBLAtomList.h @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1999 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Original Author: David W. Hyatt (hyatt@netscape.com) + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/****** + + This file contains the list of all XBL nsIAtoms and their values + + It is designed to be used as inline input to nsXBLAtoms.cpp *only* + through the magic of C preprocessing. + + All entires must be enclosed in the macro XBL_ATOM which will have cruel + and unusual things done to it + + It is recommended (but not strictly necessary) to keep all entries + in alphabetical order + + The first argument to XBL_ATOM is the C++ identifier of the atom + The second argument is the string value of the atom + + ******/ + + +XBL_ATOM(binding, "binding") +XBL_ATOM(bindings, "bindings") +XBL_ATOM(handlers, "handlers") +XBL_ATOM(handler, "handler") +XBL_ATOM(resources, "resources") +XBL_ATOM(image, "image") +XBL_ATOM(stylesheet, "stylesheet") +XBL_ATOM(implementation, "implementation") +XBL_ATOM(implements, "implements") +XBL_ATOM(xbltext, "xbl:text") +XBL_ATOM(method, "method") +XBL_ATOM(property, "property") +XBL_ATOM(field, "field") +XBL_ATOM(event, "event") +XBL_ATOM(phase, "phase") +XBL_ATOM(action, "action") +XBL_ATOM(command, "command") +XBL_ATOM(modifiers, "modifiers") +XBL_ATOM(clickcount, "clickcount") +XBL_ATOM(charcode, "charcode") +XBL_ATOM(keycode, "keycode") +XBL_ATOM(key, "key") +XBL_ATOM(onget, "onget") +XBL_ATOM(onset, "onset") +XBL_ATOM(name, "name") +XBL_ATOM(getter, "getter") +XBL_ATOM(setter, "setter") +XBL_ATOM(body, "body") +XBL_ATOM(readonly, "readonly") +XBL_ATOM(parameter, "parameter") +XBL_ATOM(children, "children") +XBL_ATOM(extends, "extends") +XBL_ATOM(display, "display") +XBL_ATOM(inherits, "inherits") +XBL_ATOM(includes, "includes") +XBL_ATOM(excludes, "excludes") +XBL_ATOM(content, "content") +XBL_ATOM(constructor, "constructor") +XBL_ATOM(destructor, "destructor") +XBL_ATOM(inheritstyle, "inheritstyle") + + + diff --git a/content/xbl/src/nsXBLAtoms.cpp b/content/xbl/src/nsXBLAtoms.cpp new file mode 100644 index 000000000000..94e468d8d4a8 --- /dev/null +++ b/content/xbl/src/nsXBLAtoms.cpp @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Original Author: David W. Hyatt (hyatt@netscape.com) + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsString.h" +#include "nsXBLAtoms.h" +#include "nsContentCID.h" + +// define storage for all atoms +#define XBL_ATOM(_name, _value) nsIAtom* nsXBLAtoms::_name; +#include "nsXBLAtomList.h" +#undef XBL_ATOM + + +static nsrefcnt gRefCnt = 0; + +void nsXBLAtoms::AddRefAtoms() { + + if (gRefCnt == 0) { + // now register the atoms +#define XBL_ATOM(_name, _value) _name = NS_NewPermanentAtom(_value); +#include "nsXBLAtomList.h" +#undef XBL_ATOM + } + ++gRefCnt; +} + +void nsXBLAtoms::ReleaseAtoms() { + + NS_PRECONDITION(gRefCnt != 0, "bad release of XBL atoms"); + if (--gRefCnt == 0) { +#define XBL_ATOM(_name, _value) NS_RELEASE(_name); +#include "nsXBLAtomList.h" +#undef XBL_ATOM + } +} diff --git a/content/xbl/src/nsXBLAtoms.h b/content/xbl/src/nsXBLAtoms.h new file mode 100644 index 000000000000..84a3a5458130 --- /dev/null +++ b/content/xbl/src/nsXBLAtoms.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Original Author: David W. Hyatt (hyatt@netscape.com) + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef nsXBLAtoms_h___ +#define nsXBLAtoms_h___ + +#include "prtypes.h" +#include "nsIAtom.h" + +class nsINameSpaceManager; + +/** + * This class wraps up the creation and destruction of the standard + * set of XBL atoms used during normal XBL handling. This object + * is created when the first XBL content object is created, and + * destroyed when the last such content object is destroyed. + */ +class nsXBLAtoms { +public: + + static void AddRefAtoms(); + static void ReleaseAtoms(); + + // XBL namespace ID, good for the life of the nsXBLAtoms object + static PRInt32 nameSpaceID; + + /* Declare all atoms + + The atom names and values are stored in nsCSSAtomList.h and + are brought to you by the magic of C preprocessing + + Add new atoms to nsCSSAtomList and all support logic will be auto-generated + */ +#define XBL_ATOM(_name, _value) static nsIAtom* _name; +#include "nsXBLAtomList.h" +#undef XBL_ATOM + +}; + +#endif /* nsXBLAtoms_h___ */ diff --git a/content/xbl/src/nsXBLBinding.cpp b/content/xbl/src/nsXBLBinding.cpp index cf05d47a0a90..a274f326e2dd 100644 --- a/content/xbl/src/nsXBLBinding.cpp +++ b/content/xbl/src/nsXBLBinding.cpp @@ -88,11 +88,14 @@ #include "nsIDOMMutationListener.h" #include "nsIDOMContextMenuListener.h" +#include "nsXBLAtoms.h" +#include "nsXULAtoms.h" + #include "nsIDOMAttr.h" #include "nsIDOMNamedNodeMap.h" -#include "nsIXBLPrototypeHandler.h" #include "nsIXBLPrototypeProperty.h" +#include "nsXBLPrototypeHandler.h" #include "nsXBLKeyHandler.h" #include "nsXBLFocusHandler.h" @@ -163,30 +166,6 @@ nsXBLJSClass::Destroy() // Static initialization PRUint32 nsXBLBinding::gRefCnt = 0; -nsIAtom* nsXBLBinding::kXULTemplateAtom = nsnull; -nsIAtom* nsXBLBinding::kXULObservesAtom = nsnull; - -nsIAtom* nsXBLBinding::kContentAtom = nsnull; -nsIAtom* nsXBLBinding::kImplementationAtom = nsnull; -nsIAtom* nsXBLBinding::kHandlersAtom = nsnull; -nsIAtom* nsXBLBinding::kExcludesAtom = nsnull; -nsIAtom* nsXBLBinding::kIncludesAtom = nsnull; -nsIAtom* nsXBLBinding::kInheritsAtom = nsnull; -nsIAtom* nsXBLBinding::kEventAtom = nsnull; -nsIAtom* nsXBLBinding::kPhaseAtom = nsnull; -nsIAtom* nsXBLBinding::kExtendsAtom = nsnull; -nsIAtom* nsXBLBinding::kActionAtom = nsnull; -nsIAtom* nsXBLBinding::kMethodAtom = nsnull; -nsIAtom* nsXBLBinding::kParameterAtom = nsnull; -nsIAtom* nsXBLBinding::kBodyAtom = nsnull; -nsIAtom* nsXBLBinding::kOnSetAtom = nsnull; -nsIAtom* nsXBLBinding::kOnGetAtom = nsnull; -nsIAtom* nsXBLBinding::kGetterAtom = nsnull; -nsIAtom* nsXBLBinding::kSetterAtom = nsnull; -nsIAtom* nsXBLBinding::kNameAtom = nsnull; -nsIAtom* nsXBLBinding::kReadOnlyAtom = nsnull; -nsIAtom* nsXBLBinding::kAttachToAtom = nsnull; - nsXBLBinding::EventHandlerMapEntry nsXBLBinding::kEventHandlerMap[] = { { "click", nsnull, &NS_GET_IID(nsIDOMMouseListener) }, @@ -270,30 +249,6 @@ nsXBLBinding::nsXBLBinding(nsIXBLPrototypeBinding* aBinding) // printf("REF COUNT UP: %d %s\n", gRefCnt, (const char*)mID); if (gRefCnt == 1) { - kXULTemplateAtom = NS_NewAtom("template"); - kXULObservesAtom = NS_NewAtom("observes"); - - kContentAtom = NS_NewAtom("content"); - kImplementationAtom = NS_NewAtom("implementation"); - kHandlersAtom = NS_NewAtom("handlers"); - kExcludesAtom = NS_NewAtom("excludes"); - kIncludesAtom = NS_NewAtom("includes"); - kInheritsAtom = NS_NewAtom("inherits"); - kEventAtom = NS_NewAtom("event"); - kPhaseAtom = NS_NewAtom("phase"); - kExtendsAtom = NS_NewAtom("extends"); - kActionAtom = NS_NewAtom("action"); - kMethodAtom = NS_NewAtom("method"); - kParameterAtom = NS_NewAtom("parameter"); - kBodyAtom = NS_NewAtom("body"); - kOnSetAtom = NS_NewAtom("onset"); - kOnGetAtom = NS_NewAtom("onget"); - kGetterAtom = NS_NewAtom("getter"); - kSetterAtom = NS_NewAtom("setter"); - kNameAtom = NS_NewAtom("name"); - kReadOnlyAtom = NS_NewAtom("readonly"); - kAttachToAtom = NS_NewAtom("attachto"); - EventHandlerMapEntry* entry = kEventHandlerMap; while (entry->mAttributeName) { entry->mAttributeAtom = NS_NewAtom(entry->mAttributeName); @@ -311,30 +266,6 @@ nsXBLBinding::~nsXBLBinding(void) // printf("REF COUNT DOWN: %d %s\n", gRefCnt, (const char*)mID); if (gRefCnt == 0) { - NS_RELEASE(kXULTemplateAtom); - NS_RELEASE(kXULObservesAtom); - - NS_RELEASE(kContentAtom); - NS_RELEASE(kImplementationAtom); - NS_RELEASE(kHandlersAtom); - NS_RELEASE(kExcludesAtom); - NS_RELEASE(kIncludesAtom); - NS_RELEASE(kInheritsAtom); - NS_RELEASE(kEventAtom); - NS_RELEASE(kPhaseAtom); - NS_RELEASE(kExtendsAtom); - NS_RELEASE(kActionAtom); - NS_RELEASE(kMethodAtom); - NS_RELEASE(kParameterAtom); - NS_RELEASE(kBodyAtom); - NS_RELEASE(kOnSetAtom); - NS_RELEASE(kOnGetAtom); - NS_RELEASE(kGetterAtom); - NS_RELEASE(kSetterAtom); - NS_RELEASE(kNameAtom); - NS_RELEASE(kReadOnlyAtom); - NS_RELEASE(kAttachToAtom); - EventHandlerMapEntry* entry = kEventHandlerMap; while (entry->mAttributeName) { NS_IF_RELEASE(entry->mAttributeAtom); @@ -678,7 +609,7 @@ nsXBLBinding::GenerateAnonymousContent() { // Fetch the content element for this binding. nsCOMPtr content; - GetImmediateChild(kContentAtom, getter_AddRefs(content)); + GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(content)); if (!content) { // We have no anonymous content. @@ -700,7 +631,7 @@ nsXBLBinding::GenerateAnonymousContent() #ifdef DEBUG // See if there's an includes attribute. nsAutoString includes; - content->GetAttr(kNameSpaceID_None, kIncludesAtom, includes); + content->GetAttr(kNameSpaceID_None, nsXBLAtoms::includes, includes); if (!includes.IsEmpty()) { nsCAutoString id; mPrototypeBinding->GetID(id); @@ -743,7 +674,7 @@ nsXBLBinding::GenerateAnonymousContent() childContent = do_QueryInterface(node); nsCOMPtr tag; childContent->GetTag(*getter_AddRefs(tag)); - if (tag.get() != kXULObservesAtom && tag.get() != kXULTemplateAtom) { + if (tag != nsXULAtoms::observes && tag != nsXULAtoms::templateAtom) { hasContent = PR_FALSE; break; } @@ -824,7 +755,7 @@ nsXBLBinding::GenerateAnonymousContent() // should be thrown out. Special-case template and observes. nsCOMPtr tag; childContent->GetTag(*getter_AddRefs(tag)); - if (tag.get() != kXULObservesAtom && tag.get() != kXULTemplateAtom) { + if (tag != nsXULAtoms::observes && tag != nsXULAtoms::templateAtom) { // Kill all anonymous content. mContent = nsnull; bindingManager->SetContentListFor(mBoundElement, nsnull); @@ -879,7 +810,7 @@ nsXBLBinding::GenerateAnonymousContent() for (PRInt32 i = 0; i < length; ++i) { content->GetAttrNameAt(i, namespaceID, *getter_AddRefs(name), *getter_AddRefs(prefix)); - if (name.get() != kIncludesAtom) { + if (name != nsXBLAtoms::includes) { nsAutoString value; mBoundElement->GetAttr(namespaceID, name, value); if (value.IsEmpty()) { @@ -915,11 +846,7 @@ nsXBLBinding::InstallEventHandlers() nsXBLEventHandler* currHandler = nsnull; while (curr) { - nsCOMPtr child; - curr->GetHandlerElement(getter_AddRefs(child)); - - // Fetch the type attribute. - // XXX Deal with a comma-separated list of types + // Fetch the event type. nsCOMPtr eventAtom; curr->GetEventName(getter_AddRefs(eventAtom)); @@ -956,12 +883,10 @@ nsXBLBinding::InstallEventHandlers() */ // Figure out if we're using capturing or not. - PRBool useCapture = PR_FALSE; - nsAutoString capturer; - child->GetAttr(kNameSpaceID_None, kPhaseAtom, capturer); - if (capturer == NS_LITERAL_STRING("capturing")) - useCapture = PR_TRUE; - + PRUint8 phase; + curr->GetPhase(&phase); + PRBool useCapture = (phase == NS_PHASE_CAPTURING); + // Create a new nsXBLEventHandler. nsXBLEventHandler* handler = nsnull; @@ -1037,11 +962,8 @@ nsXBLBinding::InstallEventHandlers() } else { NS_WARNING("***** Non-compliant XBL event listener attached! *****"); - nsAutoString value; - child->GetAttr(kNameSpaceID_None, kActionAtom, value); - if (value.IsEmpty()) - GetTextData(child, value); - AddScriptEventListener(mBoundElement, eventAtom, value); + // XXX Need to get the event text from the prototype handler! + //AddScriptEventListener(mBoundElement, eventAtom, value); } // We chain all our event handlers together for easy @@ -1191,7 +1113,7 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen if (mIsStyleBinding) { // Now the binding dies. Unhook our prototypes. nsCOMPtr interfaceElement; - GetImmediateChild(kImplementationAtom, getter_AddRefs(interfaceElement)); + GetImmediateChild(nsXBLAtoms::implementation, getter_AddRefs(interfaceElement)); if (interfaceElement) { nsCOMPtr global; @@ -1480,7 +1402,7 @@ nsXBLBinding::GetImmediateChild(nsIAtom* aTag, nsIContent** aResult) binding->ChildAt(i, *getter_AddRefs(child)); nsCOMPtr tag; child->GetTag(*getter_AddRefs(tag)); - if (aTag == tag.get()) { + if (aTag == tag) { *aResult = child; NS_ADDREF(*aResult); return; diff --git a/content/xbl/src/nsXBLBinding.h b/content/xbl/src/nsXBLBinding.h index 9a8c37ea6211..3b02a637ead0 100644 --- a/content/xbl/src/nsXBLBinding.h +++ b/content/xbl/src/nsXBLBinding.h @@ -135,31 +135,6 @@ public: // Static members static PRUint32 gRefCnt; - static nsIAtom* kXULTemplateAtom; - static nsIAtom* kXULObservesAtom; - - static nsIAtom* kContentAtom; - static nsIAtom* kImplementationAtom; - static nsIAtom* kHandlersAtom; - static nsIAtom* kExcludesAtom; - static nsIAtom* kIncludesAtom; - static nsIAtom* kInheritsAtom; - static nsIAtom* kEventAtom; - static nsIAtom* kPhaseAtom; - static nsIAtom* kExtendsAtom; - static nsIAtom* kChildrenAtom; - static nsIAtom* kMethodAtom; - static nsIAtom* kParameterAtom; - static nsIAtom* kBodyAtom; - static nsIAtom* kOnSetAtom; - static nsIAtom* kOnGetAtom; - static nsIAtom* kGetterAtom; - static nsIAtom* kSetterAtom; - static nsIAtom* kActionAtom; - static nsIAtom* kNameAtom; - static nsIAtom* kReadOnlyAtom; - static nsIAtom* kAttachToAtom; - // Used to easily obtain the correct IID for an event. struct EventHandlerMapEntry { const char* mAttributeName; diff --git a/content/xbl/src/nsXBLContentSink.cpp b/content/xbl/src/nsXBLContentSink.cpp new file mode 100644 index 000000000000..04bba9fbe0b4 --- /dev/null +++ b/content/xbl/src/nsXBLContentSink.cpp @@ -0,0 +1,310 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsXBLContentSink.h" +#include "nsIDocument.h" +#include "nsIBindingManager.h" +#include "nsIDOMNode.h" +#include "nsIParser.h" +#include "nsXBLAtoms.h" +#include "nsINameSpaceManager.h" +#include "nsHTMLAtoms.h" +#include "nsLayoutAtoms.h" +#include "nsHTMLTokens.h" +#include "nsIURI.h" + +nsresult +NS_NewXBLContentSink(nsIXMLContentSink** aResult, + nsIDocument* aDoc, + nsIURI* aURL, + nsIWebShell* aWebShell) +{ + NS_PRECONDITION(nsnull != aResult, "null ptr"); + if (!aResult) + return NS_ERROR_NULL_POINTER; + nsXBLContentSink* it; + NS_NEWXPCOM(it, nsXBLContentSink); + if (!it) + return NS_ERROR_OUT_OF_MEMORY; + nsresult rv = it->Init(aDoc, aURL, aWebShell); + if (NS_FAILED(rv)) + return rv; + return it->QueryInterface(NS_GET_IID(nsIXMLContentSink), (void **)aResult); +} + +nsXBLContentSink::nsXBLContentSink() +{ + mState = eXBL_InDocument; + mSecondaryState = eXBL_None; + mDocInfo = nsnull; + mIsChromeOrResource = PR_FALSE; +} + +nsXBLContentSink::~nsXBLContentSink() +{ +} + +nsresult +nsXBLContentSink::Init(nsIDocument* aDoc, + nsIURI* aURL, + nsIWebShell* aContainer) +{ + nsresult rv; + rv = nsXMLContentSink::Init(aDoc, aURL, aContainer); + return rv; +} + +PRBool +nsXBLContentSink::OnOpenContainer(const nsIParserNode& aNode, PRInt32 aNameSpaceID, nsIAtom* aTagName) +{ + PRBool ret = PR_TRUE; + if (aNameSpaceID == kNameSpaceID_XBL) { + if (aTagName == nsXBLAtoms::bindings) { + NS_NewXBLDocumentInfo(mDocument, &mDocInfo); + if (!mDocInfo) + return NS_ERROR_FAILURE; + + nsCOMPtr bindingManager; + mDocument->GetBindingManager(getter_AddRefs(bindingManager)); + bindingManager->PutXBLDocumentInfo(mDocInfo); + + nsCOMPtr url; + mDocument->GetDocumentURL(getter_AddRefs(url)); + + PRBool isChrome = PR_FALSE; + PRBool isRes = PR_FALSE; + + url->SchemeIs("chrome", &isChrome); + url->SchemeIs("resource", &isRes); + mIsChromeOrResource = isChrome || isRes; + + nsIXBLDocumentInfo* info = mDocInfo; + NS_RELEASE(info); // We keep a weak ref. We've created a cycle between doc/binding manager/doc info. + } + else if (aTagName == nsXBLAtoms::binding) + mState = eXBL_InBinding; + else if (aTagName == nsXBLAtoms::handlers) { + mState = eXBL_InHandlers; + ret = PR_FALSE; // The XML content sink should not do anything with . + } + else if (aTagName == nsXBLAtoms::handler) { + mSecondaryState = eXBL_InHandler; + ConstructHandler(aNode); + ret = PR_FALSE; + } + else if (aTagName == nsXBLAtoms::resources) { + // mState = eXBL_InResources; + // ret = PR_FALSE; // The XML content sink should ignore all . + } + else if (aTagName == nsXBLAtoms::implementation) { + // mState = eXBL_InImplementation; + // ret = PR_FALSE; // The XML content sink should ignore the . + } + } + + return ret; +} + +NS_IMETHODIMP +nsXBLContentSink::OpenContainer(const nsIParserNode& aNode) +{ + nsresult rv = nsXMLContentSink::OpenContainer(aNode); + if (NS_FAILED(rv)) + return rv; + + if (mState == eXBL_InBinding && !mBinding) + ConstructBinding(); + + return rv; +} + +NS_IMETHODIMP +nsXBLContentSink::CloseContainer(const nsIParserNode& aNode) +{ + if (mState != eXBL_InDocument) { + nsCOMPtr nameSpacePrefix, tagAtom; + + SplitXMLName(aNode.GetText(), getter_AddRefs(nameSpacePrefix), + getter_AddRefs(tagAtom)); + + PRInt32 nameSpaceID = GetNameSpaceId(nameSpacePrefix); + if (nameSpaceID == kNameSpaceID_XBL) { + if (mState == eXBL_InHandlers) { + if (tagAtom == nsXBLAtoms::handlers) { + mState = eXBL_InBinding; + mHandler = nsnull; + } + else if (tagAtom == nsXBLAtoms::handler) + mSecondaryState = eXBL_None; + return NS_OK; + } + + nsresult rv = nsXMLContentSink::CloseContainer(aNode); + if (NS_FAILED(rv)) + return rv; + + if (mState == eXBL_InImplementation && tagAtom == nsXBLAtoms::implementation) + mState = eXBL_InBinding; + else if (mState == eXBL_InResources && tagAtom == nsXBLAtoms::resources) + mState = eXBL_InBinding; + else if (mState == eXBL_InBinding && tagAtom == nsXBLAtoms::binding) { + mState = eXBL_InDocument; + mBinding->Initialize(); + mBinding = nsnull; // Clear our current binding ref. + } + + return NS_OK; + } + } + + return nsXMLContentSink::CloseContainer(aNode); +} + +NS_IMETHODIMP +nsXBLContentSink::AddLeaf(const nsIParserNode& aNode) +{ + if (mState == eXBL_InHandlers) { + if (mSecondaryState == eXBL_InHandler) { + // Get the text and add it to the event handler. + switch (aNode.GetTokenType()) { + case eToken_text: + case eToken_cdatasection: + mHandler->SetHandlerText(aNode.GetText()); + case eToken_entity: + { + nsAutoString tmp; + PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp); + if (unicode < 0) + mHandler->SetHandlerText(aNode.GetText()); + else + mHandler->SetHandlerText(aNode.GetText()); + } + } + } + return NS_OK; + } + + return nsXMLContentSink::AddLeaf(aNode); +} + +void +nsXBLContentSink::ConstructBinding() +{ + nsCOMPtr binding = getter_AddRefs(GetCurrentContent()); + nsAutoString id; + binding->GetAttr(kNameSpaceID_None, nsHTMLAtoms::id, id); + nsCAutoString cid; cid.AssignWithConversion(id); + + if (!cid.IsEmpty()) { + NS_NewXBLPrototypeBinding(cid, binding, mDocInfo, getter_AddRefs(mBinding)); + mDocInfo->SetPrototypeBinding(cid, mBinding); + binding->UnsetAttr(kNameSpaceID_None, nsHTMLAtoms::id, PR_FALSE); + } +} + +void +nsXBLContentSink::ConstructHandler(const nsIParserNode& aNode) +{ + nsCOMPtr nameSpacePrefix, nameAtom; + PRInt32 ac = aNode.GetAttributeCount(); + + nsAReadableString* event = nsnull; + nsAReadableString* modifiers = nsnull; + nsAReadableString* button = nsnull; + nsAReadableString* clickcount = nsnull; + nsAReadableString* keycode = nsnull; + nsAReadableString* charcode = nsnull; + nsAReadableString* phase = nsnull; + nsAReadableString* command = nsnull; + nsAReadableString* action = nsnull; + + for (PRInt32 i = 0; i < ac; i++) { + // Get upper-cased key + const nsAReadableString& key = aNode.GetKeyAt(i); + + SplitXMLName(key, getter_AddRefs(nameSpacePrefix), + getter_AddRefs(nameAtom)); + + if (nameSpacePrefix || nameAtom.get() == nsLayoutAtoms::xmlnsNameSpace) + continue; + + // Is this attribute one of the ones we care about? + nsAReadableString* ref = nsnull; + if (key.Equals(NS_LITERAL_STRING("event"))) + event = &(aNode.GetValueAt(i)); + else if (key.Equals(NS_LITERAL_STRING("modifiers"))) + modifiers = &(aNode.GetValueAt(i)); + else if (key.Equals(NS_LITERAL_STRING("button"))) + button = &(aNode.GetValueAt(i)); + else if (key.Equals(NS_LITERAL_STRING("clickcount"))) + clickcount = &(aNode.GetValueAt(i)); + else if (key.Equals(NS_LITERAL_STRING("keycode"))) + keycode = &(aNode.GetValueAt(i)); + else if (key.Equals(NS_LITERAL_STRING("key")) || key.Equals(NS_LITERAL_STRING("charcode"))) + charcode = &(aNode.GetValueAt(i)); + else if (key.Equals(NS_LITERAL_STRING("phase"))) + phase = &(aNode.GetValueAt(i)); + else if (key.Equals(NS_LITERAL_STRING("command"))) + command = &(aNode.GetValueAt(i)); + else if (key.Equals(NS_LITERAL_STRING("action"))) + action = &(aNode.GetValueAt(i)); + else + continue; // Nope, it's some irrelevant attribute. Ignore it and move on. + } + + if (command && !mIsChromeOrResource) + // Make sure the XBL doc is chrome or resource if we have a command + // shorthand syntax. + return; // Don't even make this handler. + + // All of our pointers are now filled in. Construct our handler with all of these + // parameters. + nsCOMPtr newHandler; + NS_NewXBLPrototypeHandler(event, phase, action, command, + keycode, charcode, modifiers, button, clickcount, + getter_AddRefs(newHandler)); + if (newHandler) { + // Add this handler to our chain of handlers. + if (mHandler) + mHandler->SetNextHandler(newHandler); // Already have a chain. Just append to the end. + else + mBinding->SetPrototypeHandlers(newHandler); // We're the first handler in the chain. + + mHandler = newHandler; // Adjust our mHandler pointer to point to the new last handler in the chain. + } +} diff --git a/content/xbl/src/nsXBLContentSink.h b/content/xbl/src/nsXBLContentSink.h new file mode 100644 index 000000000000..105ff620afa7 --- /dev/null +++ b/content/xbl/src/nsXBLContentSink.h @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: NPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Netscape Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * David Hyatt (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the NPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the NPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef nsXBLContentSink_h__ +#define nsXBLContentSink_h__ + +#include "nsXMLContentSink.h" +#include "nsXBLDocumentInfo.h" +#include "nsIXBLPrototypeBinding.h" +#include "nsIXBLPrototypeHandler.h" + +typedef enum { + eXBL_InDocument, + eXBL_InBinding, + eXBL_InResources, + eXBL_InImplementation, + eXBL_InHandlers +} XBLPrimaryState; + +typedef enum { + eXBL_None, + eXBL_InHandler, + eXBL_InMethod, + eXBL_InProperty, + eXBL_InField, + eXBL_InBody, + eXBL_InGetter, + eXBL_InSetter +} XBLSecondaryState; + +// The XBL content sink overrides the XML content sink to +// builds its own lightweight data structures for the , +// , , and + +class nsXBLContentSink : public nsXMLContentSink { +public: + nsXBLContentSink(); + ~nsXBLContentSink(); + + nsresult Init(nsIDocument* aDoc, + nsIURI* aURL, + nsIWebShell* aContainer); + + // nsIContentSink overrides + NS_IMETHOD OpenContainer(const nsIParserNode& aNode); + NS_IMETHOD CloseContainer(const nsIParserNode& aNode); + NS_IMETHOD AddLeaf(const nsIParserNode& aNode); + +protected: + // nsXMLContentSink overrides + PRBool OnOpenContainer(const nsIParserNode& aNode, PRInt32 aNameSpaceID, nsIAtom* aTagName); + + // Our own helpers for constructing XBL prototype objects. + void ConstructBinding(); + void ConstructHandler(const nsIParserNode& aNode); + +protected: + XBLPrimaryState mState; + XBLSecondaryState mSecondaryState; + nsIXBLDocumentInfo* mDocInfo; + PRBool mIsChromeOrResource; // For bug #45989 + + nsCOMPtr mBinding; + nsCOMPtr mHandler; +}; + + +nsresult +NS_NewXBLContentSink(nsIXMLContentSink** aResult, + nsIDocument* aDoc, + nsIURI* aURL, + nsIWebShell* aWebShell); +#endif // nsXBLContentSink_h__ diff --git a/content/xbl/src/nsXBLDocumentInfo.cpp b/content/xbl/src/nsXBLDocumentInfo.cpp new file mode 100644 index 000000000000..7dbfd47965eb --- /dev/null +++ b/content/xbl/src/nsXBLDocumentInfo.cpp @@ -0,0 +1,389 @@ +#include "nsXBLDocumentInfo.h" +#include "nsHashtable.h" +#include "nsIDocument.h" +#include "nsIXBLPrototypeBinding.h" +#include "nsIScriptObjectPrincipal.h" +#include "nsIScriptContext.h" +#include "nsIDOMScriptObjectFactory.h" +#include "jsapi.h" +#include "nsIURI.h" +#include "nsIConsoleService.h" +#include "nsIScriptError.h" +#include "nsIChromeRegistry.h" + +static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); + +// An XBLDocumentInfo object has a special context associated with it which we can use to pre-compile +// properties and methods of XBL bindings against. +class nsXBLDocGlobalObject : public nsIScriptGlobalObject, + public nsIScriptObjectPrincipal +{ +public: + nsXBLDocGlobalObject(); + + // nsISupports interface + NS_DECL_ISUPPORTS + + // nsIScriptGlobalObject methods + NS_IMETHOD SetContext(nsIScriptContext *aContext); + NS_IMETHOD GetContext(nsIScriptContext **aContext); + NS_IMETHOD SetNewDocument(nsIDOMDocument *aDocument, + PRBool removeEventListeners); + NS_IMETHOD SetDocShell(nsIDocShell *aDocShell); + NS_IMETHOD GetDocShell(nsIDocShell **aDocShell); + NS_IMETHOD SetOpenerWindow(nsIDOMWindowInternal *aOpener); + NS_IMETHOD SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner); + NS_IMETHOD GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner); + NS_IMETHOD HandleDOMEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIDOMEvent** aDOMEvent, + PRUint32 aFlags, + nsEventStatus* aEventStatus); + NS_IMETHOD_(JSObject *) GetGlobalJSObject(); + NS_IMETHOD OnFinalize(JSObject *aObject); + + // nsIScriptObjectPrincipal methods + NS_IMETHOD GetPrincipal(nsIPrincipal** aPrincipal); + +protected: + virtual ~nsXBLDocGlobalObject(); + + nsCOMPtr mScriptContext; + JSObject *mJSObject; // XXX JS language rabies bigotry badness + + nsIScriptGlobalObjectOwner* mGlobalObjectOwner; // weak reference + static JSClass gSharedGlobalClass; +}; + +void PR_CALLBACK nsXBLDocGlobalObject_finalize(JSContext *cx, JSObject *obj) +{ + nsISupports *nativeThis = (nsISupports*)JS_GetPrivate(cx, obj); + + nsCOMPtr sgo(do_QueryInterface(nativeThis)); + + if (sgo) + sgo->OnFinalize(obj); + + // The addref was part of JSObject construction + NS_RELEASE(nativeThis); +} + + +JSBool PR_CALLBACK nsXBLDocGlobalObject_resolve(JSContext *cx, JSObject *obj, jsval id) +{ + JSBool did_resolve = JS_FALSE; + return JS_ResolveStandardClass(cx, obj, id, &did_resolve); +} + + +JSClass nsXBLDocGlobalObject::gSharedGlobalClass = { + "nsXBLPrototypeScript compilation scope", + JSCLASS_HAS_PRIVATE | JSCLASS_PRIVATE_IS_NSISUPPORTS, + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, + JS_EnumerateStub, nsXBLDocGlobalObject_resolve, JS_ConvertStub, + nsXBLDocGlobalObject_finalize +}; + +//---------------------------------------------------------------------- +// +// nsXBLDocGlobalObject +// + +nsXBLDocGlobalObject::nsXBLDocGlobalObject() + : mJSObject(nsnull), + mGlobalObjectOwner(nsnull) +{ + NS_INIT_REFCNT(); +} + + +nsXBLDocGlobalObject::~nsXBLDocGlobalObject() +{} + + +NS_IMPL_ISUPPORTS2(nsXBLDocGlobalObject, nsIScriptGlobalObject, nsIScriptObjectPrincipal) + +//---------------------------------------------------------------------- +// +// nsIScriptGlobalObject methods +// + +NS_IMETHODIMP +nsXBLDocGlobalObject::SetContext(nsIScriptContext *aContext) +{ + mScriptContext = aContext; + return NS_OK; +} + + +NS_IMETHODIMP +nsXBLDocGlobalObject::GetContext(nsIScriptContext **aContext) +{ + // This whole fragile mess is predicated on the fact that + // GetContext() will be called before GetScriptObject() is. + if (! mScriptContext) { + nsCOMPtr factory = do_GetService(kDOMScriptObjectFactoryCID); + NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE); + + nsresult rv = factory->NewScriptContext(nsnull, getter_AddRefs(mScriptContext)); + if (NS_FAILED(rv)) + return rv; + + JSContext *cx = (JSContext *)mScriptContext->GetNativeContext(); + + mJSObject = ::JS_NewObject(cx, &gSharedGlobalClass, nsnull, nsnull); + if (!mJSObject) + return NS_ERROR_OUT_OF_MEMORY; + + ::JS_SetGlobalObject(cx, mJSObject); + + // Add an owning reference from JS back to us. This'll be + // released when the JSObject is finalized. + ::JS_SetPrivate(cx, mJSObject, this); + NS_ADDREF(this); + } + + *aContext = mScriptContext; + NS_IF_ADDREF(*aContext); + return NS_OK; +} + + +NS_IMETHODIMP +nsXBLDocGlobalObject::SetNewDocument(nsIDOMDocument *aDocument, + PRBool removeEventListeners) +{ + NS_NOTREACHED("waaah!"); + return NS_ERROR_UNEXPECTED; +} + + +NS_IMETHODIMP +nsXBLDocGlobalObject::SetDocShell(nsIDocShell *aDocShell) +{ + NS_NOTREACHED("waaah!"); + return NS_ERROR_UNEXPECTED; +} + + +NS_IMETHODIMP +nsXBLDocGlobalObject::GetDocShell(nsIDocShell **aDocShell) +{ + NS_WARNING("waaah!"); + return NS_ERROR_UNEXPECTED; +} + + +NS_IMETHODIMP +nsXBLDocGlobalObject::SetOpenerWindow(nsIDOMWindowInternal *aOpener) +{ + NS_NOTREACHED("waaah!"); + return NS_ERROR_UNEXPECTED; +} + + +NS_IMETHODIMP +nsXBLDocGlobalObject::SetGlobalObjectOwner(nsIScriptGlobalObjectOwner* aOwner) +{ + mGlobalObjectOwner = aOwner; // weak reference + return NS_OK; +} + + +NS_IMETHODIMP +nsXBLDocGlobalObject::GetGlobalObjectOwner(nsIScriptGlobalObjectOwner** aOwner) +{ + *aOwner = mGlobalObjectOwner; + NS_IF_ADDREF(*aOwner); + return NS_OK; +} + + +NS_IMETHODIMP +nsXBLDocGlobalObject::HandleDOMEvent(nsIPresContext* aPresContext, + nsEvent* aEvent, + nsIDOMEvent** aDOMEvent, + PRUint32 aFlags, + nsEventStatus* aEventStatus) +{ + NS_NOTREACHED("waaah!"); + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP_(JSObject *) +nsXBLDocGlobalObject::GetGlobalJSObject() +{ + // The prototype document has its own special secret script object + // that can be used to compile scripts and event handlers. + + if (!mScriptContext) + return nsnull; + + JSContext* cx = NS_REINTERPRET_CAST(JSContext*, + mScriptContext->GetNativeContext()); + if (!cx) + return nsnull; + + return ::JS_GetGlobalObject(cx); +} + +NS_IMETHODIMP +nsXBLDocGlobalObject::OnFinalize(JSObject *aObject) +{ + NS_ASSERTION(aObject == mJSObject, "Wrong object finalized!"); + + mJSObject = nsnull; + + return NS_OK; +} + +//---------------------------------------------------------------------- +// +// nsIScriptObjectPrincipal methods +// + +NS_IMETHODIMP +nsXBLDocGlobalObject::GetPrincipal(nsIPrincipal** aPrincipal) +{ + nsresult rv = NS_OK; + if (!mGlobalObjectOwner) { + *aPrincipal = nsnull; + return NS_ERROR_FAILURE; + } + + nsCOMPtr docInfo = do_QueryInterface(mGlobalObjectOwner, &rv); + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); + + nsCOMPtr document; + rv = docInfo->GetDocument(getter_AddRefs(document)); + NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE); + + return document->GetPrincipal(aPrincipal); +} + +static PRBool IsChromeOrResourceURI(nsIURI* aURI) +{ + PRBool isChrome = PR_FALSE; + PRBool isResource = PR_FALSE; + if (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) && + NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource))) + return (isChrome || isResource); + return PR_FALSE; +} + +/* Implementation file */ +NS_IMPL_ISUPPORTS3(nsXBLDocumentInfo, nsIXBLDocumentInfo, nsIScriptGlobalObjectOwner, nsISupportsWeakReference) + +static NS_DEFINE_CID(kChromeRegistryCID, NS_CHROMEREGISTRY_CID); + +nsXBLDocumentInfo::nsXBLDocumentInfo(const char* aDocURI, nsIDocument* aDocument) +{ + NS_INIT_ISUPPORTS(); + /* member initializers and constructor code */ + mDocURI = aDocURI; + mDocument = aDocument; + mScriptAccess = PR_TRUE; + mBindingTable = nsnull; + + nsCOMPtr uri; + mDocument->GetDocumentURL(getter_AddRefs(uri)); + if (IsChromeOrResourceURI(uri)) { + // Cache whether or not this chrome XBL can execute scripts. + nsCOMPtr reg(do_GetService(kChromeRegistryCID)); + if (reg) { + PRBool allow = PR_TRUE; + reg->AllowScriptsForSkin(uri, &allow); + SetScriptAccess(allow); + } + } +} + +nsXBLDocumentInfo::~nsXBLDocumentInfo() +{ + /* destructor code */ + if (mGlobalObject) { + mGlobalObject->SetContext(nsnull); // remove circular reference + mGlobalObject->SetGlobalObjectOwner(nsnull); // just in case + } + delete mBindingTable; +} + +NS_IMETHODIMP +nsXBLDocumentInfo::GetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding** aResult) +{ + *aResult = nsnull; + if (!mBindingTable) + return NS_OK; + + const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); + nsCStringKey key(flat.get()); + *aResult = NS_STATIC_CAST(nsIXBLPrototypeBinding*, mBindingTable->Get(&key)); // Addref happens here. + + return NS_OK; +} + +NS_IMETHODIMP +nsXBLDocumentInfo::SetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding* aBinding) +{ + if (!mBindingTable) + mBindingTable = new nsSupportsHashtable(); + + const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); + nsCStringKey key(flat.get()); + mBindingTable->Put(&key, aBinding); + + return NS_OK; +} + +//---------------------------------------------------------------------- +// +// nsIScriptGlobalObjectOwner methods +// + +NS_IMETHODIMP +nsXBLDocumentInfo::GetScriptGlobalObject(nsIScriptGlobalObject** _result) +{ + if (!mGlobalObject) { + + mGlobalObject = new nsXBLDocGlobalObject(); + + if (!mGlobalObject) { + *_result = nsnull; + return NS_ERROR_OUT_OF_MEMORY; + } + + mGlobalObject->SetGlobalObjectOwner(this); // does not refcount + } + + *_result = mGlobalObject; + NS_ADDREF(*_result); + return NS_OK; +} + +NS_IMETHODIMP +nsXBLDocumentInfo::ReportScriptError(nsIScriptError *errorObject) +{ + if (errorObject == nsnull) + return NS_ERROR_NULL_POINTER; + + // Get the console service, where we're going to register the error. + nsCOMPtr consoleService (do_GetService("@mozilla.org/consoleservice;1")); + + if (!consoleService) + return NS_ERROR_NOT_AVAILABLE; + return consoleService->LogMessage(errorObject); +} + +nsresult NS_NewXBLDocumentInfo(nsIDocument* aDocument, nsIXBLDocumentInfo** aResult) +{ + nsCOMPtr url; + aDocument->GetDocumentURL(getter_AddRefs(url)); + + nsXPIDLCString str; + url->GetSpec(getter_Copies(str)); + + *aResult = new nsXBLDocumentInfo((const char*)str, aDocument); + + NS_IF_ADDREF(*aResult); + return NS_OK; +} diff --git a/content/xbl/src/nsXBLDocumentInfo.h b/content/xbl/src/nsXBLDocumentInfo.h new file mode 100644 index 000000000000..934b0a89faad --- /dev/null +++ b/content/xbl/src/nsXBLDocumentInfo.h @@ -0,0 +1,38 @@ +#include "nsCOMPtr.h" +#include "nsIXBLDocumentInfo.h" +#include "nsIScriptGlobalObjectOwner.h" +#include "nsWeakReference.h" +#include "nsIDocument.h" + +class nsIXBLPrototypeBinding; +class nsSupportsHashtable; + +class nsXBLDocumentInfo : public nsIXBLDocumentInfo, public nsIScriptGlobalObjectOwner, public nsSupportsWeakReference +{ +public: + NS_DECL_ISUPPORTS + + nsXBLDocumentInfo(const char* aDocURI, nsIDocument* aDocument); + virtual ~nsXBLDocumentInfo(); + + NS_IMETHOD GetDocument(nsIDocument** aResult) { *aResult = mDocument; NS_IF_ADDREF(*aResult); return NS_OK; }; + + NS_IMETHOD GetScriptAccess(PRBool* aResult) { *aResult = mScriptAccess; return NS_OK; }; + NS_IMETHOD SetScriptAccess(PRBool aAccess) { mScriptAccess = aAccess; return NS_OK; }; + + NS_IMETHOD GetDocumentURI(nsCString& aDocURI) { aDocURI = mDocURI; return NS_OK; }; + + NS_IMETHOD GetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding** aResult); + NS_IMETHOD SetPrototypeBinding(const nsAReadableCString& aRef, nsIXBLPrototypeBinding* aBinding); + + // nsIScriptGlobalObjectOwner methods + NS_DECL_NSISCRIPTGLOBALOBJECTOWNER + +private: + nsCOMPtr mDocument; + nsCString mDocURI; + PRBool mScriptAccess; + nsSupportsHashtable* mBindingTable; + + nsCOMPtr mGlobalObject; +}; diff --git a/content/xbl/src/nsXBLEventHandler.cpp b/content/xbl/src/nsXBLEventHandler.cpp index cde7fecdbc89..31ecd8686317 100644 --- a/content/xbl/src/nsXBLEventHandler.cpp +++ b/content/xbl/src/nsXBLEventHandler.cpp @@ -39,7 +39,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsCOMPtr.h" -#include "nsIXBLPrototypeHandler.h" +#include "nsXBLPrototypeHandler.h" #include "nsXBLEventHandler.h" #include "nsIContent.h" #include "nsIAtom.h" @@ -75,16 +75,7 @@ #include "nsIDOMDragListener.h" #include "nsIDOMScrollListener.h" #include "nsIDOMFormListener.h" - -PRUint32 nsXBLEventHandler::gRefCnt = 0; -nsIAtom* nsXBLEventHandler::kKeyCodeAtom = nsnull; -nsIAtom* nsXBLEventHandler::kCharCodeAtom = nsnull; -nsIAtom* nsXBLEventHandler::kKeyAtom = nsnull; -nsIAtom* nsXBLEventHandler::kActionAtom = nsnull; -nsIAtom* nsXBLEventHandler::kCommandAtom = nsnull; -nsIAtom* nsXBLEventHandler::kClickCountAtom = nsnull; -nsIAtom* nsXBLEventHandler::kButtonAtom = nsnull; -nsIAtom* nsXBLEventHandler::kModifiersAtom = nsnull; +#include "nsXBLAtoms.h" nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandler) { @@ -92,32 +83,10 @@ nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBL mEventReceiver = aEventReceiver; mProtoHandler = aHandler; mNextHandler = nsnull; - gRefCnt++; - if (gRefCnt == 1) { - kKeyCodeAtom = NS_NewAtom("keycode"); - kKeyAtom = NS_NewAtom("key"); - kCharCodeAtom = NS_NewAtom("charcode"); - kModifiersAtom = NS_NewAtom("modifiers"); - kActionAtom = NS_NewAtom("action"); - kCommandAtom = NS_NewAtom("command"); - kClickCountAtom = NS_NewAtom("clickcount"); - kButtonAtom = NS_NewAtom("button"); - } } nsXBLEventHandler::~nsXBLEventHandler() { - gRefCnt--; - if (gRefCnt == 0) { - NS_RELEASE(kKeyAtom); - NS_RELEASE(kKeyCodeAtom); - NS_RELEASE(kCharCodeAtom); - NS_RELEASE(kModifiersAtom); - NS_RELEASE(kActionAtom); - NS_RELEASE(kCommandAtom); - NS_RELEASE(kButtonAtom); - NS_RELEASE(kClickCountAtom); - } } NS_IMPL_ISUPPORTS1(nsXBLEventHandler, nsISupports) @@ -135,21 +104,13 @@ nsXBLEventHandler::RemoveEventHandlers() nsCOMPtr eventName; mProtoHandler->GetEventName(getter_AddRefs(eventName)); - nsCOMPtr handlerElement; - mProtoHandler->GetHandlerElement(getter_AddRefs(handlerElement)); - mProtoHandler = nsnull; - if (!handlerElement) - return; - - PRBool useCapture = PR_FALSE; - nsAutoString capturer; - handlerElement->GetAttr(kNameSpaceID_None, nsXBLBinding::kPhaseAtom, capturer); - if (capturer == NS_LITERAL_STRING("capturing")) - useCapture = PR_TRUE; - nsAutoString type; - handlerElement->GetAttr(kNameSpaceID_None, nsXBLBinding::kEventAtom, type); - + eventName->ToString(type); + + PRUint8 phase; + mProtoHandler->GetPhase(&phase); + PRBool useCapture = (phase == NS_PHASE_CAPTURING); + PRBool found = PR_FALSE; nsIID iid; nsXBLBinding::GetEventHandlerIID(eventName, &iid, &found); diff --git a/content/xbl/src/nsXBLEventHandler.h b/content/xbl/src/nsXBLEventHandler.h index 5c6849b1013f..70e3cc72af69 100644 --- a/content/xbl/src/nsXBLEventHandler.h +++ b/content/xbl/src/nsXBLEventHandler.h @@ -75,17 +75,6 @@ public: static nsresult GetTextData(nsIContent *aParent, nsAWritableString& aResult); -protected: - static PRUint32 gRefCnt; - static nsIAtom* kKeyAtom; - static nsIAtom* kKeyCodeAtom; - static nsIAtom* kCharCodeAtom; - static nsIAtom* kActionAtom; - static nsIAtom* kCommandAtom; - static nsIAtom* kClickCountAtom; - static nsIAtom* kButtonAtom; - static nsIAtom* kModifiersAtom; - protected: nsCOMPtr mEventReceiver; nsCOMPtr mProtoHandler; diff --git a/content/xbl/src/nsXBLPrototypeBinding.cpp b/content/xbl/src/nsXBLPrototypeBinding.cpp index bc95c36b40b4..e1c93ad54be2 100644 --- a/content/xbl/src/nsXBLPrototypeBinding.cpp +++ b/content/xbl/src/nsXBLPrototypeBinding.cpp @@ -75,6 +75,7 @@ #include "nsIDocumentObserver.h" #include "nsHTMLAtoms.h" #include "nsXULAtoms.h" +#include "nsXBLAtoms.h" #include "nsIScriptContext.h" @@ -231,23 +232,7 @@ NS_IMPL_QUERY_INTERFACE1(nsXBLInsertionPointEntry, nsIXBLInsertionPointEntry) // Static initialization PRUint32 nsXBLPrototypeBinding::gRefCnt = 0; -nsIAtom* nsXBLPrototypeBinding::kInheritStyleAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kHandlersAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kChildrenAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kIncludesAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kContentAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kResourcesAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kResourceAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kStyleSheetAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kSrcAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kInheritsAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kHTMLAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kValueAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kXBLTextAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kConstructorAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kDestructorAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kImplementationAtom = nsnull; -nsIAtom* nsXBLPrototypeBinding::kImplementsAtom = nsnull; + nsFixedSizeAllocator* nsXBLPrototypeBinding::kAttrPool; nsFixedSizeAllocator* nsXBLPrototypeBinding::kInsPool; @@ -273,7 +258,8 @@ static const PRInt32 kInsInitialSize = (NS_SIZE_IN_HEAP(sizeof(nsXBLInsertionPoi NS_IMPL_ISUPPORTS3(nsXBLPrototypeBinding, nsIXBLPrototypeBinding, nsICSSLoaderObserver, nsISupportsWeakReference) // Constructors/Destructors -nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIXBLDocumentInfo* aInfo) +nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIXBLDocumentInfo* aInfo, + nsIContent* aElement) : mID(aID), mInheritStyle(PR_TRUE), mHasBaseProto(PR_TRUE), @@ -298,51 +284,36 @@ nsXBLPrototypeBinding::nsXBLPrototypeBinding(const nsAReadableCString& aID, nsIX kAttrPool->Init("XBL Attribute Entries", kAttrBucketSizes, kAttrNumBuckets, kAttrInitialSize); kInsPool = new nsFixedSizeAllocator(); kInsPool->Init("XBL Insertion Point Entries", kInsBucketSizes, kInsNumBuckets, kInsInitialSize); - - kInheritStyleAtom = NS_NewAtom("inheritstyle"); - kHandlersAtom = NS_NewAtom("handlers"); - kChildrenAtom = NS_NewAtom("children"); - kContentAtom = NS_NewAtom("content"); - kResourcesAtom = NS_NewAtom("resources"); - kResourceAtom = NS_NewAtom("resource"); - kStyleSheetAtom = NS_NewAtom("stylesheet"); - kSrcAtom = NS_NewAtom("src"); - kIncludesAtom = NS_NewAtom("includes"); - kInheritsAtom = NS_NewAtom("inherits"); - kHTMLAtom = NS_NewAtom("html"); - kValueAtom = NS_NewAtom("value"); - kXBLTextAtom = NS_NewAtom("xbl:text"); - kConstructorAtom = NS_NewAtom("constructor"); - kDestructorAtom = NS_NewAtom("destructor"); - kImplementationAtom = NS_NewAtom("implementation"); - kImplementsAtom = NS_NewAtom("implements"); } + + SetBindingElement(aElement); } -void nsXBLPrototypeBinding::Initialize(nsIContent * aElement, nsIXBLDocumentInfo* aInfo) +NS_IMETHODIMP +nsXBLPrototypeBinding::Initialize() { - // These all use atoms, so we have to do these ops last to ensure - // the atoms exist. - SetBindingElement(aElement); - + nsCOMPtr info(do_QueryReferent(mXBLDocInfoWeak)); + PRBool allowScripts; - aInfo->GetScriptAccess(&allowScripts); + info->GetScriptAccess(&allowScripts); if (allowScripts) { - ConstructHandlers(); + BuildConstructorAndDestructor(); ConstructProperties(); } nsCOMPtr content; - GetImmediateChild(kContentAtom, getter_AddRefs(content)); + GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(content)); if (content) { ConstructAttributeTable(content); ConstructInsertionTable(content); } nsCOMPtr impl; - GetImmediateChild(kImplementationAtom, getter_AddRefs(impl)); + GetImmediateChild(nsXBLAtoms::implementation, getter_AddRefs(impl)); if (impl) ConstructInterfaceTable(impl); + + return NS_OK; } nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void) @@ -352,24 +323,6 @@ nsXBLPrototypeBinding::~nsXBLPrototypeBinding(void) delete mInterfaceTable; gRefCnt--; if (gRefCnt == 0) { - NS_RELEASE(kInheritStyleAtom); - NS_RELEASE(kHandlersAtom); - NS_RELEASE(kChildrenAtom); - NS_RELEASE(kContentAtom); - NS_RELEASE(kResourcesAtom); - NS_RELEASE(kResourceAtom); - NS_RELEASE(kStyleSheetAtom); - NS_RELEASE(kSrcAtom); - NS_RELEASE(kIncludesAtom); - NS_RELEASE(kInheritsAtom); - NS_RELEASE(kHTMLAtom); - NS_RELEASE(kValueAtom); - NS_RELEASE(kXBLTextAtom); - NS_RELEASE(kConstructorAtom); - NS_RELEASE(kDestructorAtom); - NS_RELEASE(kImplementationAtom); - NS_RELEASE(kImplementsAtom); - delete kAttrPool; delete kInsPool; } @@ -413,7 +366,7 @@ nsXBLPrototypeBinding::SetBindingElement(nsIContent* aElement) { mBinding = aElement; nsAutoString inheritStyle; - mBinding->GetAttr(kNameSpaceID_None, kInheritStyleAtom, inheritStyle); + mBinding->GetAttr(kNameSpaceID_None, nsXBLAtoms::inheritstyle, inheritStyle); if (inheritStyle == NS_LITERAL_STRING("false")) mInheritStyle = PR_FALSE; @@ -481,7 +434,7 @@ nsXBLPrototypeBinding::LoadResources(PRBool* aResult) nsresult rv = NS_OK; nsCOMPtr content; - GetImmediateChild(kResourcesAtom, getter_AddRefs(content)); + GetImmediateChild(nsXBLAtoms::resources, getter_AddRefs(content)); if (content) { #ifdef USE_IMG2 // Declare our loaders. @@ -513,7 +466,7 @@ nsXBLPrototypeBinding::LoadResources(PRBool* aResult) resource->GetTag(*getter_AddRefs(tag)); nsAutoString src; - resource->GetAttr(kNameSpaceID_None, kSrcAtom, src); + resource->GetAttr(kNameSpaceID_None, nsHTMLAtoms::src, src); if (src.Length() == 0) continue; @@ -523,8 +476,7 @@ nsXBLPrototypeBinding::LoadResources(PRBool* aResult) if (NS_FAILED(rv)) continue; -#ifdef USE_IMG2 - if (tag.get() == nsXULAtoms::image) { + if (tag == nsXBLAtoms::image) { // Obtain our src attribute. // Construct a URI out of our src attribute. // We need to ensure the image loader is constructed. @@ -537,9 +489,7 @@ nsXBLPrototypeBinding::LoadResources(PRBool* aResult) nsCOMPtr req; il->LoadImage(url, nsnull, nsnull, nsnull, nsIRequest::LOAD_BACKGROUND, nsnull, nsnull, getter_AddRefs(req)); } - else -#endif - if (tag.get() == kStyleSheetAtom) { + else if (tag == nsXBLAtoms::stylesheet) { if (!cssLoader) { nsCOMPtr htmlContent(do_QueryInterface(doc)); htmlContent->GetCSSLoader(*getter_AddRefs(cssLoader)); @@ -680,7 +630,7 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI // Iterate over the elements in the array. nsCOMPtr content; - GetImmediateChild(kContentAtom, getter_AddRefs(content)); + GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(content)); while (xblAttr) { nsCOMPtr element; nsCOMPtr dstAttr; @@ -699,7 +649,7 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI nsAutoString value; // Check to see if the src attribute is xbl:text. If so, then we need to obtain the // children of the real element and get the text nodes' values. - if (aAttribute == kXBLTextAtom) { + if (aAttribute == nsXBLAtoms::xbltext) { nsXBLBinding::GetTextData(aChangedElement, value); value.StripChar('\n'); value.StripChar('\r'); @@ -723,7 +673,7 @@ nsXBLPrototypeBinding::AttributeChanged(nsIAtom* aAttribute, PRInt32 aNameSpaceI // xbl:text set on us. nsCOMPtr tag; realElement->GetTag(*getter_AddRefs(tag)); - if (dstAttr.get() == kXBLTextAtom || (tag.get() == kHTMLAtom) && (dstAttr.get() == kValueAtom)) { + if (dstAttr == nsXBLAtoms::xbltext || (tag == nsHTMLAtoms::html) && (dstAttr == nsHTMLAtoms::value)) { // Flush out all our kids. PRInt32 childCount; realElement->ChildCount(childCount); @@ -784,7 +734,7 @@ PRBool PR_CALLBACK InstantiateInsertionPoint(nsHashKey* aKey, void* aData, void* nsCOMPtr instanceRoot; binding->GetAnonymousContent(getter_AddRefs(instanceRoot)); nsCOMPtr templRoot; - proto->GetImmediateChild(nsXBLPrototypeBinding::kContentAtom, getter_AddRefs(templRoot)); + proto->GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(templRoot)); proto->LocateInstance(nsnull, templRoot, instanceRoot, content, getter_AddRefs(realContent)); if (!realContent) binding->GetBoundElement(getter_AddRefs(realContent)); @@ -842,7 +792,7 @@ nsXBLPrototypeBinding::GetInsertionPoint(nsIContent* aBoundElement, nsIContent* nsCOMPtr entry = getter_AddRefs(NS_STATIC_CAST(nsIXBLInsertionPointEntry*, mInsertionPointTable->Get(&key))); if (!entry) { - nsISupportsKey key2(kChildrenAtom); + nsISupportsKey key2(nsXBLAtoms::children); entry = getter_AddRefs(NS_STATIC_CAST(nsIXBLInsertionPointEntry*, mInsertionPointTable->Get(&key2))); } @@ -853,7 +803,7 @@ nsXBLPrototypeBinding::GetInsertionPoint(nsIContent* aBoundElement, nsIContent* entry->GetInsertionIndex(aIndex); entry->GetDefaultContent(aDefaultContent); // Addref happens here. nsCOMPtr templContent; - GetImmediateChild(kContentAtom, getter_AddRefs(templContent)); + GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(templContent)); LocateInstance(nsnull, templContent, aCopyRoot, content, getter_AddRefs(realContent)); } else { @@ -881,7 +831,7 @@ nsXBLPrototypeBinding::GetSingleInsertionPoint(nsIContent* aBoundElement, { if (mInsertionPointTable) { if(mInsertionPointTable->Count() == 1) { - nsISupportsKey key(kChildrenAtom); + nsISupportsKey key(nsXBLAtoms::children); nsCOMPtr entry = getter_AddRefs(NS_STATIC_CAST(nsIXBLInsertionPointEntry*, mInsertionPointTable->Get(&key))); nsCOMPtr realContent; @@ -891,7 +841,7 @@ nsXBLPrototypeBinding::GetSingleInsertionPoint(nsIContent* aBoundElement, entry->GetInsertionIndex(aIndex); entry->GetDefaultContent(aDefaultContent); // Addref happens here. nsCOMPtr templContent; - GetImmediateChild(kContentAtom, getter_AddRefs(templContent)); + GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(templContent)); LocateInstance(nsnull, templContent, aCopyRoot, content, getter_AddRefs(realContent)); } else { @@ -969,7 +919,7 @@ nsXBLPrototypeBinding::GetImmediateChild(nsIAtom* aTag, nsIContent** aResult) mBinding->ChildAt(i, *getter_AddRefs(child)); nsCOMPtr tag; child->GetTag(*getter_AddRefs(tag)); - if (aTag == tag.get()) { + if (aTag == tag) { *aResult = child; NS_ADDREF(*aResult); return; @@ -983,7 +933,7 @@ void nsXBLPrototypeBinding::ConstructProperties() { nsCOMPtr properties; - GetImmediateChild(kImplementationAtom, getter_AddRefs(properties)); + GetImmediateChild(nsXBLAtoms::implementation, getter_AddRefs(properties)); if (properties && mBinding) { nsXBLService::BuildPropertyChain(this, properties, getter_AddRefs(mPrototypeProperty)); } @@ -1094,16 +1044,10 @@ nsXBLPrototypeBinding::InitClass(const nsCString& aClassName, nsIScriptContext * } void -nsXBLPrototypeBinding::ConstructHandlers() +nsXBLPrototypeBinding::BuildConstructorAndDestructor() { - // See if this binding has a handler elt. - nsCOMPtr handlers; - GetImmediateChild(kHandlersAtom, getter_AddRefs(handlers)); - if (handlers) - nsXBLService::BuildHandlerChain(handlers, getter_AddRefs(mPrototypeHandler)); - nsCOMPtr impl; - GetImmediateChild(kImplementationAtom, getter_AddRefs(impl)); + GetImmediateChild(nsXBLAtoms::implementation, getter_AddRefs(impl)); if (impl) { // Look for and . PRInt32 count; @@ -1113,12 +1057,18 @@ nsXBLPrototypeBinding::ConstructHandlers() impl->ChildAt(i, *getter_AddRefs(child)); nsCOMPtr tag; child->GetTag(*getter_AddRefs(tag)); - if (tag.get() == kConstructorAtom) { - NS_NewXBLPrototypeHandler(child, getter_AddRefs(mConstructor)); + if (tag == nsXBLAtoms::constructor) { + nsAutoString value; + nsXBLBinding::GetTextData(child, value); + NS_NewXBLPrototypeHandler(nsnull, nsnull, &value, nsnull, nsnull, nsnull, nsnull, + nsnull, nsnull, getter_AddRefs(mConstructor)); mConstructor->SetEventName(tag); } - else if (tag.get() == kDestructorAtom) { - NS_NewXBLPrototypeHandler(child, getter_AddRefs(mDestructor)); + else if (tag == nsXBLAtoms::destructor) { + nsAutoString value; + nsXBLBinding::GetTextData(child, value); + NS_NewXBLPrototypeHandler(nsnull, nsnull, &value, nsnull, nsnull, nsnull, nsnull, + nsnull, nsnull, getter_AddRefs(mDestructor)); mDestructor->SetEventName(tag); } } @@ -1144,7 +1094,7 @@ nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement, nsIContent* aTe if (aBoundElement) { nsCOMPtr tag; templParent->GetTag(*getter_AddRefs(tag)); - if (tag == kChildrenAtom) { + if (tag == nsXBLAtoms::children) { childPoint = templParent; childPoint->GetParent(*getter_AddRefs(templParent)); } @@ -1153,7 +1103,7 @@ nsXBLPrototypeBinding::LocateInstance(nsIContent* aBoundElement, nsIContent* aTe if (!templParent) return; - if (templParent.get() == aTemplRoot) + if (templParent == aTemplRoot) copyParent = aCopyRoot; else LocateInstance(aBoundElement, aTemplRoot, aCopyRoot, templParent, getter_AddRefs(copyParent)); @@ -1237,7 +1187,7 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure) nsAutoString value; PRBool attrPresent = PR_TRUE; - if (src.get() == nsXBLPrototypeBinding::kXBLTextAtom) { + if (src == nsXBLAtoms::xbltext) { nsXBLBinding::GetTextData(changeData->mBoundElement, value); value.StripChar('\n'); value.StripChar('\r'); @@ -1255,7 +1205,7 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure) if (attrPresent) { nsCOMPtr content; - changeData->mProto->GetImmediateChild(nsXBLPrototypeBinding::kContentAtom, getter_AddRefs(content)); + changeData->mProto->GetImmediateChild(nsXBLAtoms::content, getter_AddRefs(content)); nsCOMPtr curr = entry; while (curr) { @@ -1271,8 +1221,8 @@ PRBool PR_CALLBACK SetAttrs(nsHashKey* aKey, void* aData, void* aClosure) realElement->SetAttr(kNameSpaceID_None, dst, value, PR_FALSE); nsCOMPtr tag; realElement->GetTag(*getter_AddRefs(tag)); - if (dst.get() == nsXBLPrototypeBinding::kXBLTextAtom || - (tag.get() == nsXBLPrototypeBinding::kHTMLAtom) && (dst.get() == nsXBLPrototypeBinding::kValueAtom) && !value.IsEmpty()) { + if (dst == nsXBLAtoms::xbltext || + (tag == nsHTMLAtoms::html) && (dst == nsHTMLAtoms::value) && !value.IsEmpty()) { nsCOMPtr textNode; nsCOMPtr doc; changeData->mBoundElement->GetDocument(*getter_AddRefs(doc)); @@ -1324,7 +1274,7 @@ nsXBLPrototypeBinding::ShouldBuildChildFrames(PRBool* aResult) { *aResult = PR_TRUE; if (mAttributeTable) { - nsISupportsKey key(kXBLTextAtom); + nsISupportsKey key(nsXBLAtoms::xbltext); nsCOMPtr supports = getter_AddRefs(NS_STATIC_CAST(nsISupports*, mAttributeTable->Get(&key))); @@ -1338,7 +1288,7 @@ void nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement) { nsAutoString inherits; - aElement->GetAttr(kNameSpaceID_None, kInheritsAtom, inherits); + aElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::inherits, inherits); if (!inherits.IsEmpty()) { if (!mAttributeTable) { mAttributeTable = new nsSupportsHashtable(4); @@ -1400,7 +1350,7 @@ nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent* aElement) // Now remove the inherits attribute from the element so that it doesn't // show up on clones of the element. It is used // by the template only, and we don't need it anymore. - aElement->UnsetAttr(kNameSpaceID_None, kInheritsAtom, PR_FALSE); + aElement->UnsetAttr(kNameSpaceID_None, nsXBLAtoms::inherits, PR_FALSE); token = nsCRT::strtok( newStr, ", ", &newStr ); } @@ -1422,7 +1372,7 @@ void nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent) { nsCOMPtr childrenElements; - GetNestedChildren(kChildrenAtom, aContent, getter_AddRefs(childrenElements)); + GetNestedChildren(nsXBLAtoms::children, aContent, getter_AddRefs(childrenElements)); if (!childrenElements) return; @@ -1444,9 +1394,9 @@ nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent* aContent) nsXBLInsertionPointEntry* xblIns = nsXBLInsertionPointEntry::Create(parent); nsAutoString includes; - child->GetAttr(kNameSpaceID_None, kIncludesAtom, includes); + child->GetAttr(kNameSpaceID_None, nsXBLAtoms::includes, includes); if (includes.IsEmpty()) { - nsISupportsKey key(kChildrenAtom); + nsISupportsKey key(nsXBLAtoms::children); mInsertionPointTable->Put(&key, xblIns); } else { @@ -1510,7 +1460,7 @@ void nsXBLPrototypeBinding::ConstructInterfaceTable(nsIContent* aElement) { nsAutoString impls; - aElement->GetAttr(kNameSpaceID_None, kImplementsAtom, impls); + aElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::implements, impls); if (!impls.IsEmpty()) { // Obtain the interface info manager that can tell us the IID // for a given interface name. @@ -1557,7 +1507,7 @@ nsXBLPrototypeBinding::GetNestedChildren(nsIAtom* aTag, nsIContent* aContent, ns aContent->ChildAt(i, *getter_AddRefs(child)); nsCOMPtr tag; child->GetTag(*getter_AddRefs(tag)); - if (aTag == tag.get()) { + if (aTag == tag) { if (!*aList) NS_NewISupportsArray(aList); // Addref happens here. (*aList)->AppendElement(child); @@ -1671,13 +1621,11 @@ nsresult NS_NewXBLPrototypeBinding(const nsAReadableCString& aRef, nsIContent* aElement, nsIXBLDocumentInfo* aInfo, nsIXBLPrototypeBinding** aResult) { - nsXBLPrototypeBinding * binding = new nsXBLPrototypeBinding(aRef, aInfo); + nsXBLPrototypeBinding * binding = new nsXBLPrototypeBinding(aRef, aInfo, aElement); if (!binding) return NS_ERROR_OUT_OF_MEMORY; - - binding->QueryInterface(NS_GET_IID(nsIXBLPrototypeBinding), (void **) aResult); - binding->Initialize(aElement, aInfo); - + *aResult = binding; + NS_ADDREF(*aResult); return NS_OK; } diff --git a/content/xbl/src/nsXBLPrototypeBinding.h b/content/xbl/src/nsXBLPrototypeBinding.h index 1ff507238ceb..cde89a2afca2 100644 --- a/content/xbl/src/nsXBLPrototypeBinding.h +++ b/content/xbl/src/nsXBLPrototypeBinding.h @@ -129,32 +129,16 @@ class nsXBLPrototypeBinding: public nsIXBLPrototypeBinding, public nsICSSLoaderO NS_IMETHOD GetConstructor(nsIXBLPrototypeHandler** aResult) { *aResult = mConstructor; NS_IF_ADDREF(*aResult); return NS_OK; }; + NS_IMETHOD Initialize(); + public: - nsXBLPrototypeBinding(const nsAReadableCString& aRef, nsIXBLDocumentInfo* aInfo); + nsXBLPrototypeBinding(const nsAReadableCString& aRef, nsIXBLDocumentInfo* aInfo, nsIContent* aElement); virtual ~nsXBLPrototypeBinding(); - void Initialize(nsIContent * aElement, nsIXBLDocumentInfo* aInfo); - + // Static members static PRUint32 gRefCnt; - static nsIAtom* kInheritStyleAtom; - static nsIAtom* kHandlersAtom; - static nsIAtom* kChildrenAtom; - static nsIAtom* kIncludesAtom; - static nsIAtom* kContentAtom; - static nsIAtom* kResourcesAtom; - static nsIAtom* kResourceAtom; - static nsIAtom* kStyleSheetAtom; - static nsIAtom* kSrcAtom; - static nsIAtom* kInheritsAtom; - static nsIAtom* kHTMLAtom; - static nsIAtom* kValueAtom; - static nsIAtom* kXBLTextAtom; - static nsIAtom* kConstructorAtom; - static nsIAtom* kDestructorAtom; - static nsIAtom* kImplementationAtom; - static nsIAtom* kImplementsAtom; - + static nsFixedSizeAllocator* kAttrPool; static nsFixedSizeAllocator* kInsPool; @@ -165,7 +149,7 @@ public: nsIContent* aTemplChild, nsIContent** aCopyResult); protected: - void ConstructHandlers(); + void BuildConstructorAndDestructor(); void ConstructProperties(); void ConstructAttributeTable(nsIContent* aElement); void ConstructInsertionTable(nsIContent* aElement); diff --git a/content/xbl/src/nsXBLPrototypeHandler.cpp b/content/xbl/src/nsXBLPrototypeHandler.cpp index 37ade01864fc..ec2b7202e4f0 100644 --- a/content/xbl/src/nsXBLPrototypeHandler.cpp +++ b/content/xbl/src/nsXBLPrototypeHandler.cpp @@ -70,10 +70,14 @@ #include "nsXPIDLString.h" #include "nsReadableUtils.h" #include "nsXULAtoms.h" +#include "nsXBLAtoms.h" +#include "nsLayoutAtoms.h" #include "nsGUIEvent.h" #include "nsIXPConnect.h" #include "nsIDOMScriptObjectFactory.h" #include "nsDOMCID.h" +#include "nsUnicharUtils.h" +#include "nsReadableUtils.h" static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, @@ -81,20 +85,6 @@ static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, PRUint32 nsXBLPrototypeHandler::gRefCnt = 0; -nsIAtom* nsXBLPrototypeHandler::kBindingAttachedAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kBindingDetachedAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kKeyCodeAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kCharCodeAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kKeyAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kActionAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kCommandAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kOnCommandAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kFocusCommandAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kClickCountAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kButtonAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kModifiersAtom = nsnull; -nsIAtom* nsXBLPrototypeHandler::kTypeAtom = nsnull; - PRInt32 nsXBLPrototypeHandler::kMenuAccessKey = -1; PRInt32 nsXBLPrototypeHandler::kAccelKey = -1; @@ -103,52 +93,42 @@ const PRInt32 nsXBLPrototypeHandler::cAlt = (1<<2); const PRInt32 nsXBLPrototypeHandler::cControl = (1<<3); const PRInt32 nsXBLPrototypeHandler::cMeta = (1<<4); +nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsAReadableString* aEvent, nsAReadableString* aPhase, + nsAReadableString* aAction, nsAReadableString* aCommand, + nsAReadableString* aKeyCode, nsAReadableString* aCharCode, + nsAReadableString* aModifiers, nsAReadableString* aButton, + nsAReadableString* aClickCount) +{ + NS_INIT_REFCNT(); + gRefCnt++; + if (gRefCnt == 1) + // Get the primary accelerator key. + InitAccessKeys(); + + mHandlerText = nsnull; + + ConstructPrototype(nsnull, aEvent, aPhase, aAction, aCommand, aKeyCode, aCharCode, aModifiers, + aButton, aClickCount); +} + nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement) { NS_INIT_REFCNT(); - mHandlerElement = aHandlerElement; + gRefCnt++; - if (gRefCnt == 1) { - kBindingAttachedAtom = NS_NewAtom("bindingattached"); - kBindingDetachedAtom = NS_NewAtom("bindingdetached"); - kKeyCodeAtom = NS_NewAtom("keycode"); - kKeyAtom = NS_NewAtom("key"); - kCharCodeAtom = NS_NewAtom("charcode"); - kModifiersAtom = NS_NewAtom("modifiers"); - kActionAtom = NS_NewAtom("action"); - kCommandAtom = NS_NewAtom("command"); - kOnCommandAtom = NS_NewAtom("oncommand"); - kFocusCommandAtom = NS_NewAtom("focuscommand"); - kClickCountAtom = NS_NewAtom("clickcount"); - kButtonAtom = NS_NewAtom("button"); - kTypeAtom = NS_NewAtom("event"); - + if (gRefCnt == 1) // Get the primary accelerator key. InitAccessKeys(); - } - // Make sure our mask is initialized. - ConstructMask(); + // Make sure our prototype is initialized. + ConstructPrototype(aHandlerElement); } nsXBLPrototypeHandler::~nsXBLPrototypeHandler() { gRefCnt--; - if (gRefCnt == 0) { - NS_RELEASE(kBindingAttachedAtom); - NS_RELEASE(kBindingDetachedAtom); - NS_RELEASE(kKeyAtom); - NS_RELEASE(kKeyCodeAtom); - NS_RELEASE(kCharCodeAtom); - NS_RELEASE(kModifiersAtom); - NS_RELEASE(kActionAtom); - NS_RELEASE(kOnCommandAtom); - NS_RELEASE(kCommandAtom); - NS_RELEASE(kFocusCommandAtom); - NS_RELEASE(kButtonAtom); - NS_RELEASE(kClickCountAtom); - NS_RELEASE(kTypeAtom); - } + if (mType != NS_HANDLER_TYPE_XUL && mHandlerText) + nsMemory::Free(mHandlerText); } NS_IMPL_ISUPPORTS1(nsXBLPrototypeHandler, nsIXBLPrototypeHandler) @@ -156,8 +136,21 @@ NS_IMPL_ISUPPORTS1(nsXBLPrototypeHandler, nsIXBLPrototypeHandler) NS_IMETHODIMP nsXBLPrototypeHandler::GetHandlerElement(nsIContent** aResult) { - *aResult = mHandlerElement; - NS_IF_ADDREF(*aResult); + if (mType == NS_HANDLER_TYPE_XUL) { + *aResult = mHandlerElement; + NS_IF_ADDREF(*aResult); + } + else + *aResult = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsXBLPrototypeHandler::SetHandlerText(const nsAReadableString& aText) +{ + if (mHandlerText) + nsMemory::Free(mHandlerText); + mHandlerText = ToNewUnicode(aText); return NS_OK; } @@ -209,13 +202,11 @@ NS_IMETHODIMP nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, nsIDOMEvent* aEvent) { - if (!mHandlerElement) + if (!mHandlerElement) // This works for both types of handlers. In both cases, the union's var should be defined. return NS_ERROR_FAILURE; // See if our event receiver is a content node (and not us). - nsCOMPtr tag; - mHandlerElement->GetTag(*getter_AddRefs(tag)); - PRBool isXULKey = (tag.get() == nsXULAtoms::key); + PRBool isXULKey = (mType == NS_HANDLER_TYPE_XUL); PRBool isReceiverCommandElement = PR_FALSE; nsCOMPtr content(do_QueryInterface(aReceiver)); @@ -224,25 +215,7 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, // This is a special-case optimization to make command handling fast. // It isn't really a part of XBL, but it helps speed things up. - nsAutoString command; - mHandlerElement->GetAttr(kNameSpaceID_None, kCommandAtom, command); - - if (!command.IsEmpty() && !isReceiverCommandElement) { - // Make sure the XBL doc is chrome or resource - // Fix for bug #45989 - nsCOMPtr document; - mHandlerElement->GetDocument(*getter_AddRefs(document)); - nsCOMPtr url; - document->GetDocumentURL(getter_AddRefs(url)); - - PRBool isChrome = PR_FALSE; - PRBool isRes = PR_FALSE; - - url->SchemeIs("chrome", &isChrome); - url->SchemeIs("resource", &isRes); - if (!isChrome && !isRes) - return NS_OK; - + if (mType == NS_HANDLER_TYPE_XBL_COMMAND && !isReceiverCommandElement) { // See if preventDefault has been set. If so, don't execute. PRBool preventDefault; nsCOMPtr nsUIEvent(do_QueryInterface(aEvent)); @@ -253,10 +226,10 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, return NS_OK; nsCOMPtr privateEvent = do_QueryInterface(aEvent); - if(privateEvent) { + if (privateEvent) { PRBool dispatchStopped; privateEvent->IsDispatchStopped(&dispatchStopped); - if(dispatchStopped) + if (dispatchStopped) return NS_OK; } @@ -291,16 +264,18 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, privateWindow->GetRootFocusController(getter_AddRefs(focusController)); } + nsDependentString command(mHandlerText); + if (focusController) focusController->GetControllerForCommand(command, getter_AddRefs(controller)); else GetController(aReceiver, getter_AddRefs(controller)); // We're attached to the receiver possibly. nsAutoString type; - GetEventType (type); + mEventName->ToString(type); if (type == NS_LITERAL_STRING("keypress") && mDetail == nsIDOMKeyEvent::DOM_VK_SPACE && - mDetail2 == 1) { + mMisc == 1) { // get the focused element so that we can pageDown only at // certain times. nsCOMPtr focusedElement; @@ -338,24 +313,19 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, void* handler = nsnull; // Compile the event handler. - nsAutoString handlerText; - mHandlerElement->GetAttr(kNameSpaceID_None, kActionAtom, handlerText); - if (handlerText.IsEmpty()) { - // look to see if action content is contained by the handler element - GetTextData(mHandlerElement, handlerText); - if (handlerText.IsEmpty()) { - // Try an oncommand attribute (used by XUL elements, which - // are implemented using this code). - mHandlerElement->GetAttr(kNameSpaceID_None, kOnCommandAtom, handlerText); - if (handlerText.IsEmpty()) { - // Maybe the receiver is a elt. - if (isReceiverCommandElement) - // It is! See if it has an oncommand attribute. - content->GetAttr(kNameSpaceID_None, kOnCommandAtom, handlerText); - - if (handlerText.IsEmpty()) - return NS_ERROR_FAILURE; // For whatever reason, they didn't give us anything to do. - } + nsAutoString xulText; + if (isXULKey) { + // Try an oncommand attribute (used by XUL elements, which + // are implemented using this code). + mHandlerElement->GetAttr(kNameSpaceID_None, nsLayoutAtoms::oncommand, xulText); + if (xulText.IsEmpty()) { + // Maybe the receiver is a elt. + if (isReceiverCommandElement) + // It is! See if it has an oncommand attribute. + content->GetAttr(kNameSpaceID_None, nsLayoutAtoms::oncommand, xulText); + + if (xulText.IsEmpty()) + return NS_ERROR_FAILURE; // For whatever reason, they didn't give us anything to do. } } @@ -425,8 +395,16 @@ nsXBLPrototypeHandler::ExecuteHandler(nsIDOMEventReceiver* aReceiver, NS_ENSURE_SUCCESS(rv, rv); } - boundContext->CompileEventHandler(scriptObject, onEventAtom, handlerText, - PR_TRUE, &handler); + if (isXULKey) + boundContext->CompileEventHandler(scriptObject, onEventAtom, xulText, + PR_TRUE, &handler); + else { + nsDependentString handlerText(mHandlerText); + if (handlerText.IsEmpty()) + return NS_ERROR_FAILURE; + boundContext->CompileEventHandler(scriptObject, onEventAtom, handlerText, + PR_TRUE, &handler); + } // Temporarily bind it to the bound element boundContext->BindCompiledEventHandler(scriptObject, onEventAtom, handler); @@ -583,12 +561,12 @@ nsXBLPrototypeHandler::KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aKey { *aResult = PR_TRUE; - if (!mHandlerElement || (aEventType != mEventName.get())) { + if (aEventType != mEventName.get()) { *aResult = PR_FALSE; return NS_OK; } - if (mDetail == -1 && mDetail2 == 0 && mKeyMask == 0) + if (mDetail == -1 && mMisc == 0 && mKeyMask == 0) return NS_OK; // No filters set up. It's generic. // Get the keycode and charcode of the key event. @@ -596,7 +574,7 @@ nsXBLPrototypeHandler::KeyEventMatched(nsIAtom* aEventType, nsIDOMKeyEvent* aKey aKeyEvent->GetKeyCode(&keyCode); aKeyEvent->GetCharCode(&charCode); - PRBool keyMatched = (mDetail == PRInt32(mDetail2 ? charCode : keyCode)); + PRBool keyMatched = (mDetail == PRInt32(mMisc ? charCode : keyCode)); if (!keyMatched) { *aResult = PR_FALSE; @@ -614,12 +592,12 @@ nsXBLPrototypeHandler::MouseEventMatched(nsIAtom* aEventType, nsIDOMMouseEvent* { *aResult = PR_TRUE; - if (!mHandlerElement || (aEventType != mEventName.get())) { + if (aEventType != mEventName.get()) { *aResult = PR_FALSE; return NS_OK; } - if (mDetail == -1 && mDetail2 == 0 && mKeyMask == 0) + if (mDetail == -1 && mMisc == 0 && mKeyMask == 0) return NS_OK; // No filters set up. It's generic. unsigned short button; @@ -631,7 +609,7 @@ nsXBLPrototypeHandler::MouseEventMatched(nsIAtom* aEventType, nsIDOMMouseEvent* PRInt32 clickcount; aMouseEvent->GetDetail(&clickcount); - if (mDetail2 != 0 && (clickcount != mDetail2)) { + if (mMisc != 0 && (clickcount != mMisc)) { *aResult = PR_FALSE; return NS_OK; } @@ -641,7 +619,7 @@ nsXBLPrototypeHandler::MouseEventMatched(nsIAtom* aEventType, nsIDOMMouseEvent* return NS_OK; } -PRInt32 nsXBLPrototypeHandler::GetMatchingKeyCode(const nsString& aKeyName) +PRInt32 nsXBLPrototypeHandler::GetMatchingKeyCode(const nsAReadableString& aKeyName) { nsCAutoString keyName; keyName.AssignWithConversion(aKeyName); @@ -930,58 +908,78 @@ PRInt32 nsXBLPrototypeHandler::KeyToMask(PRInt32 key) } void -nsXBLPrototypeHandler::GetEventType(nsAWritableString &type) +nsXBLPrototypeHandler::GetEventType(nsAWritableString& aEvent) { - mHandlerElement->GetAttr(kNameSpaceID_None, kTypeAtom, type); + mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::event, aEvent); - if (type.IsEmpty()) { - // If we're a XUL key element, let's assume that we're "keypress". - nsCOMPtr tag; - mHandlerElement->GetTag(*getter_AddRefs(tag)); - if (tag.get() == kKeyAtom) - type = NS_LITERAL_STRING("keypress"); - } + if (aEvent.IsEmpty() && mType == NS_HANDLER_TYPE_XUL) + // If no type is specified for a XUL element, let's assume that we're "keypress". + aEvent = NS_LITERAL_STRING("keypress"); } void -nsXBLPrototypeHandler::ConstructMask() +nsXBLPrototypeHandler::ConstructPrototype(nsIContent* aKeyElement, + nsAReadableString* aEvent, nsAReadableString* aPhase, + nsAReadableString* aAction, nsAReadableString* aCommand, + nsAReadableString* aKeyCode, nsAReadableString* aCharCode, + nsAReadableString* aModifiers, nsAReadableString* aButton, + nsAReadableString* aClickCount) { + if (aKeyElement) { + mType = NS_HANDLER_TYPE_XUL; + mHandlerElement = aKeyElement; + } + else { + mType = aCommand ? NS_HANDLER_TYPE_XBL_COMMAND : NS_HANDLER_TYPE_XBL_JS; + mHandlerText = nsnull; + } + mDetail = -1; - mDetail2 = 0; + mMisc = 0; mKeyMask = 0; - - nsAutoString type; - mHandlerElement->GetAttr(kNameSpaceID_None, kTypeAtom, type); - - if (type.IsEmpty()) { - // If we're a XUL key element, let's assume that we're "keypress". - nsCOMPtr tag; - mHandlerElement->GetTag(*getter_AddRefs(tag)); - if (tag.get() == kKeyAtom) - type = NS_LITERAL_STRING("keypress"); - else return; + mPhase = NS_PHASE_BUBBLING; + + if (aAction) + mHandlerText = ToNewUnicode(*aAction); + else if (aCommand) + mHandlerText = ToNewUnicode(*aCommand); + + nsAutoString event; + if (!aEvent) { + if (mType == NS_HANDLER_TYPE_XUL) + GetEventType(event); + if (event.IsEmpty()) + return; + aEvent = &event; } - mEventName = getter_AddRefs(NS_NewAtom(type)); + if ((*aEvent).IsEmpty()) + return; + mEventName = getter_AddRefs(NS_NewAtom(*aEvent)); - nsAutoString buttonStr, clickCountStr; - mHandlerElement->GetAttr(kNameSpaceID_None, kClickCountAtom, clickCountStr); - mHandlerElement->GetAttr(kNameSpaceID_None, kButtonAtom, buttonStr); - - if (!buttonStr.IsEmpty()) { - PRInt32 error; - mDetail = buttonStr.ToInteger(&error); + if (aPhase) { + if ((*aPhase).Equals(NS_LITERAL_STRING("capturing"))) + mPhase = NS_PHASE_CAPTURING; + else if ((*aPhase).Equals(NS_LITERAL_STRING("target"))) + mPhase = NS_PHASE_TARGET; } - if (!clickCountStr.IsEmpty()) { - PRInt32 error; - mDetail2 = clickCountStr.ToInteger(&error); - } + // Button and clickcount apply only to XBL handlers and don't apply to XUL key + // handlers. + if (aButton && !(*aButton).IsEmpty()) + mDetail = (*aButton).First() - '0'; + if (aClickCount && !(*aClickCount).IsEmpty()) + mMisc = (*aClickCount).First() - '0'; + // Modifiers are supported by both types of handlers (XUL and XBL). nsAutoString modifiers; - mHandlerElement->GetAttr(kNameSpaceID_None, kModifiersAtom, modifiers); - if (!modifiers.IsEmpty()) { - char* str = ToNewCString(modifiers); + if (!aModifiers) + aModifiers = &modifiers; + if (mType == NS_HANDLER_TYPE_XUL) + mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::modifiers, modifiers); + + if (!(*aModifiers).IsEmpty()) { + char* str = ToNewCString(*aModifiers); char* newStr; char* token = nsCRT::strtok( str, ", ", &newStr ); while( token != NULL ) { @@ -1005,24 +1003,34 @@ nsXBLPrototypeHandler::ConstructMask() } nsAutoString key; - mHandlerElement->GetAttr(kNameSpaceID_None, kKeyAtom, key); - if (key.IsEmpty()) - mHandlerElement->GetAttr(kNameSpaceID_None, kCharCodeAtom, key); - - if (!key.IsEmpty()) { + if (!aCharCode) { + aCharCode = &key; + if (mType == NS_HANDLER_TYPE_XUL) { + mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::key, key); + if (key.IsEmpty()) + mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::charcode, key); + } + } + if (!(*aCharCode).IsEmpty()) { + nsAutoString charCode(*aCharCode); if ((mKeyMask & cShift) != 0) - key.ToUpperCase(); - else key.ToLowerCase(); + charCode.ToUpperCase(); + else + charCode.ToLowerCase(); // We have a charcode. - mDetail2 = 1; - mDetail = key[0]; + mMisc = 1; + mDetail = charCode[0]; } else { - mHandlerElement->GetAttr(kNameSpaceID_None, kKeyCodeAtom, key); - if (!key.IsEmpty()) - mDetail = GetMatchingKeyCode(key); + if (!aKeyCode) + aKeyCode = &key; + if (mType == NS_HANDLER_TYPE_XUL) + mHandlerElement->GetAttr(kNameSpaceID_None, nsXBLAtoms::keycode, key); + + if (!(*aKeyCode).IsEmpty()) + mDetail = GetMatchingKeyCode(*aKeyCode); } } @@ -1079,7 +1087,23 @@ nsXBLPrototypeHandler::GetTextData(nsIContent *aParent, nsString& aResult) /////////////////////////////////////////////////////////////////////////////////// nsresult -NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult) +NS_NewXBLPrototypeHandler(nsAReadableString* aEvent, nsAReadableString* aPhase, + nsAReadableString* aAction, nsAReadableString* aCommand, + nsAReadableString* aKeyCode, nsAReadableString* aCharCode, + nsAReadableString* aModifiers, nsAReadableString* aButton, + nsAReadableString* aClickCount, + nsIXBLPrototypeHandler** aResult) +{ + *aResult = new nsXBLPrototypeHandler(aEvent, aPhase, aAction, aCommand, aKeyCode, + aCharCode, aModifiers, aButton, aClickCount); + if (!*aResult) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(*aResult); + return NS_OK; +} + +nsresult +NS_NewXULKeyHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult) { *aResult = new nsXBLPrototypeHandler(aHandlerElement); if (!*aResult) @@ -1087,3 +1111,4 @@ NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** NS_ADDREF(*aResult); return NS_OK; } + diff --git a/content/xbl/src/nsXBLPrototypeHandler.h b/content/xbl/src/nsXBLPrototypeHandler.h index 7b11791b0357..af5ea23e94d6 100644 --- a/content/xbl/src/nsXBLPrototypeHandler.h +++ b/content/xbl/src/nsXBLPrototypeHandler.h @@ -42,6 +42,7 @@ #include "nsIXBLPrototypeHandler.h" #include "nsIAtom.h" +#include "nsString.h" class nsIXBLBinding; class nsIDOMEvent; @@ -49,12 +50,28 @@ class nsIContent; class nsIDOMUIEvent; class nsIDOMKeyEvent; class nsIDOMMouseEvent; -class nsString; + +#define NS_HANDLER_TYPE_XBL_JS 0 +#define NS_HANDLER_TYPE_XBL_COMMAND 1 +#define NS_HANDLER_TYPE_XUL 2 + +#define NS_PHASE_BUBBLING 0 +#define NS_PHASE_TARGET 1 +#define NS_PHASE_CAPTURING 2 class nsXBLPrototypeHandler : public nsIXBLPrototypeHandler { public: - nsXBLPrototypeHandler(nsIContent* aHandlerElement); + // This constructor is used by XBL handlers (both the JS and command shorthand variety) + nsXBLPrototypeHandler(nsAReadableString* aEvent, nsAReadableString* aPhase, + nsAReadableString* aAction, nsAReadableString* aCommand, + nsAReadableString* aKeyCode, nsAReadableString* aCharCode, + nsAReadableString* aModifiers, nsAReadableString* aButton, + nsAReadableString* aClickCount); + + // This constructor is used only by XUL key handlers (e.g., ) + nsXBLPrototypeHandler(nsIContent* aKeyElement); + virtual ~nsXBLPrototypeHandler(); NS_DECL_ISUPPORTS @@ -64,6 +81,10 @@ public: NS_IMETHOD GetHandlerElement(nsIContent** aResult); + NS_IMETHOD SetHandlerText(const nsAReadableString& aText); + + NS_IMETHOD GetPhase(PRUint8* aResult) { *aResult = mPhase; return NS_OK; }; + NS_IMETHOD GetNextHandler(nsIXBLPrototypeHandler** aResult); NS_IMETHOD SetNextHandler(nsIXBLPrototypeHandler* aHandler); @@ -80,25 +101,17 @@ public: static PRUint32 gRefCnt; - static nsIAtom* kBindingAttachedAtom; - static nsIAtom* kBindingDetachedAtom; - static nsIAtom* kKeyAtom; - static nsIAtom* kKeyCodeAtom; - static nsIAtom* kCharCodeAtom; - static nsIAtom* kActionAtom; - static nsIAtom* kCommandAtom; - static nsIAtom* kOnCommandAtom; - static nsIAtom* kFocusCommandAtom; - static nsIAtom* kClickCountAtom; - static nsIAtom* kButtonAtom; - static nsIAtom* kModifiersAtom; - static nsIAtom* kTypeAtom; - protected: NS_IMETHOD GetController(nsIDOMEventReceiver* aReceiver, nsIController** aResult); - inline PRInt32 GetMatchingKeyCode(const nsString& aKeyName); - void ConstructMask(); + inline PRInt32 GetMatchingKeyCode(const nsAReadableString& aKeyName); + void ConstructPrototype(nsIContent* aKeyElement, + nsAReadableString* aEvent=nsnull, nsAReadableString* aPhase=nsnull, + nsAReadableString* aAction=nsnull, nsAReadableString* aCommand=nsnull, + nsAReadableString* aKeyCode=nsnull, nsAReadableString* aCharCode=nsnull, + nsAReadableString* aModifiers=nsnull, nsAReadableString* aButton=nsnull, + nsAReadableString* aClickCount=nsnull); + void GetEventType(nsAWritableString& type); PRBool ModifiersMatchMask(nsIDOMUIEvent* aEvent); @@ -117,23 +130,42 @@ protected: static const PRInt32 cMeta; protected: - nsIContent* mHandlerElement; // This ref is weak. - - PRInt32 mKeyMask; // Which modifier keys this event handler expects to have down + union { + nsIContent* mHandlerElement; // For XUL element handlers. + PRUnichar* mHandlerText; // For XBL handlers (we don't build an element for the , + // and instead we cache the JS text or command name that we should + // use. + }; + + // The following four values make up 32 bits. + PRUint8 mPhase; // The phase (capturing, bubbling) + PRUint8 mKeyMask; // Which modifier keys this event handler expects to have down // in order to be matched. + PRUint8 mType; // The type of the handler. The handler is either a XUL key + // handler, an XBL "command" event, or a normal XBL event with + // accompanying JavaScript. + PRUint8 mMisc; // Miscellaneous extra information. For key events, + // stores whether or not we're a key code or char code. + // For mouse events, stores the clickCount. + // The primary filter information for mouse/key events. PRInt32 mDetail; // For key events, contains a charcode or keycode. For // mouse events, stores the button info. - PRInt32 mDetail2; // Miscellaneous extra information. For key events, - // stores whether or not we're a key code or char code. - // For mouse events, stores the clickCount. + nsCOMPtr mNextHandler; // Prototype handlers are chained. We own the next handler in the chain. nsCOMPtr mEventName; // The type of the event, e.g., "keypress" }; extern nsresult -NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult); +NS_NewXBLPrototypeHandler(nsAReadableString* aEvent, nsAReadableString* aPhase, + nsAReadableString* aAction, nsAReadableString* aCommand, + nsAReadableString* aKeyCode, nsAReadableString* aCharCode, + nsAReadableString* aModifiers, nsAReadableString* aButton, + nsAReadableString* aClickCount, nsIXBLPrototypeHandler** aResult); + +extern nsresult +NS_NewXULKeyHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult); #endif diff --git a/content/xbl/src/nsXBLService.cpp b/content/xbl/src/nsXBLService.cpp index 24cca6b8ea96..c3dde4d2cb85 100644 --- a/content/xbl/src/nsXBLService.cpp +++ b/content/xbl/src/nsXBLService.cpp @@ -70,10 +70,11 @@ #include "nsIMemory.h" #include "nsIObserverService.h" #include "nsIDOMNodeList.h" - +#include "nsXBLContentSink.h" #include "nsIXBLBinding.h" #include "nsIXBLPrototypeBinding.h" #include "nsIXBLDocumentInfo.h" +#include "nsXBLAtoms.h" #include "nsIXBLPrototypeHandler.h" #include "nsIXBLPrototypeProperty.h" @@ -91,7 +92,6 @@ static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID); static NS_DEFINE_CID(kXMLDocumentCID, NS_XMLDOCUMENT_CID); static NS_DEFINE_CID(kParserCID, NS_PARSER_CID); -static NS_DEFINE_CID(kChromeRegistryCID, NS_CHROMEREGISTRY_CID); static PRBool IsChromeOrResourceURI(nsIURI* aURI) { @@ -392,10 +392,13 @@ nsXBLStreamListener::Load(nsIDOMEvent* aEvent) return NS_ERROR_FAILURE; } - // Put our doc in the doc table. + // Put our doc info in the doc table. nsCOMPtr info; - NS_NewXBLDocumentInfo(mBindingDocument, getter_AddRefs(info)); - + nsCOMPtr xblDocBindingManager; + mBindingDocument->GetBindingManager(getter_AddRefs(xblDocBindingManager)); + xblDocBindingManager->GetXBLDocumentInfo(nsCAutoString(NS_STATIC_CAST(const char*, str)), getter_AddRefs(info)); + xblDocBindingManager->RemoveXBLDocumentInfo(info); // Break the self-imposed cycle. + // If the doc is a chrome URI, then we put it into the XUL cache. PRBool cached = PR_FALSE; if (IsChromeOrResourceURI(uri)) { @@ -405,14 +408,6 @@ nsXBLStreamListener::Load(nsIDOMEvent* aEvent) cached = PR_TRUE; gXULCache->PutXBLDocumentInfo(info); } - - // Cache whether or not this chrome XBL can execute scripts. - nsCOMPtr reg(do_GetService(kChromeRegistryCID, &rv)); - if (NS_SUCCEEDED(rv) && reg) { - PRBool allow = PR_TRUE; - reg->AllowScriptsForSkin(uri, &allow); - info->SetScriptAccess(allow); - } } if (!cached) @@ -542,8 +537,6 @@ JSCList nsXBLService::gClassLRUList = JS_INIT_STATIC_CLIST(&nsXBLService::gClas PRUint32 nsXBLService::gClassLRUListLength = 0; PRUint32 nsXBLService::gClassLRUListQuota = 64; -nsIAtom* nsXBLService::kDisplayAtom = nsnull; -nsIAtom* nsXBLService::kExtendsAtom = nsnull; nsIAtom* nsXBLService::kEventAtom = nsnull; nsIAtom* nsXBLService::kScrollbarAtom = nsnull; nsIAtom* nsXBLService::kInputAtom = nsnull; @@ -552,8 +545,6 @@ nsIAtom* nsXBLService::kInputAtom = nsnull; PRBool nsXBLService::gDisableChromeCache = PR_FALSE; static const char kDisableChromeCachePref[] = "nglayout.debug.disable_xul_cache"; -PRInt32 nsXBLService::kNameSpaceID_XBL; - // Implement our nsISupports methods NS_IMPL_ISUPPORTS3(nsXBLService, nsIXBLService, nsIObserver, nsISupportsWeakReference) @@ -565,26 +556,14 @@ nsXBLService::nsXBLService(void) gRefCnt++; if (gRefCnt == 1) { - - // Register the XBL namespace. nsresult rv = nsComponentManager::CreateInstance(kNameSpaceManagerCID, nsnull, NS_GET_IID(nsINameSpaceManager), (void**) &gNameSpaceManager); NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create namespace manager"); if (NS_FAILED(rv)) return; - - // XXX This is sure to change. Copied from mozilla/layout/xul/content/src/nsXULAtoms.cpp - static const char kXBLNameSpaceURI[] - = "http://www.mozilla.org/xbl"; - - rv = gNameSpaceManager->RegisterNameSpace(NS_ConvertASCIItoUCS2(kXBLNameSpaceURI), kNameSpaceID_XBL); - NS_ASSERTION(NS_SUCCEEDED(rv), "unable to register XBL namespace"); - if (NS_FAILED(rv)) return; - + // Create our atoms - kDisplayAtom = NS_NewAtom("display"); - kExtendsAtom = NS_NewAtom("extends"); kEventAtom = NS_NewAtom("event"); kScrollbarAtom = NS_NewAtom("scrollbar"); kInputAtom = NS_NewAtom("input"); @@ -610,8 +589,6 @@ nsXBLService::~nsXBLService(void) NS_IF_RELEASE(gNameSpaceManager); // Release our atoms - NS_RELEASE(kDisplayAtom); - NS_RELEASE(kExtendsAtom); NS_RELEASE(kEventAtom); NS_RELEASE(kScrollbarAtom); NS_RELEASE(kInputAtom); @@ -976,43 +953,14 @@ NS_IMETHODIMP nsXBLService::GetBindingInternal(nsIContent* aBoundElement, nsCOMPtr protoBinding; docInfo->GetPrototypeBinding(ref, getter_AddRefs(protoBinding)); - nsCOMPtr child; - if (!protoBinding) { - // We have a doc. Obtain our specific binding element. - // Walk the children looking for the binding that matches the ref - // specified in the URL. - nsCOMPtr root; - doc->GetRootContent(getter_AddRefs(root)); - if (!root) - return NS_ERROR_FAILURE; - - nsAutoString bindingName; bindingName.AssignWithConversion( ref.get() ); - - PRInt32 count; - root->ChildCount(count); - - for (PRInt32 i = 0; i < count; i++) { - root->ChildAt(i, *getter_AddRefs(child)); - - nsAutoString value; - child->GetAttr(kNameSpaceID_None, nsHTMLAtoms::id, value); - - // If no ref is specified just use this. - if ((bindingName.IsEmpty()) || (bindingName == value)) { - // Construct a prototype binding. - NS_NewXBLPrototypeBinding(ref, child, docInfo, getter_AddRefs(protoBinding)); - docInfo->SetPrototypeBinding(ref, protoBinding); - break; - } - } - } - else - protoBinding->GetBindingElement(getter_AddRefs(child)); NS_ASSERTION(protoBinding, "Unable to locate an XBL binding."); if (!protoBinding) return NS_ERROR_FAILURE; + nsCOMPtr child; + protoBinding->GetBindingElement(getter_AddRefs(child)); + // Our prototype binding must have all its resources loaded. PRBool ready; protoBinding->LoadResources(&ready); @@ -1034,17 +982,12 @@ NS_IMETHODIMP nsXBLService::GetBindingInternal(nsIContent* aBoundElement, baseProto->GetBindingURI(url); if (NS_FAILED(GetBindingInternal(aBoundElement, url, aPeekOnly, aIsReady, getter_AddRefs(baseBinding)))) return NS_ERROR_FAILURE; // We aren't ready yet. - if (!aPeekOnly) { - // Make sure to set the base prototype. - baseBinding->GetPrototypeBinding(getter_AddRefs(baseProto)); - protoBinding->SetBasePrototype(baseProto); - } } else if (hasBase) { // Check for the presence of 'extends' and 'display' attributes nsAutoString display, extends; - child->GetAttr(kNameSpaceID_None, kDisplayAtom, display); - child->GetAttr(kNameSpaceID_None, kExtendsAtom, extends); + child->GetAttr(kNameSpaceID_None, nsXBLAtoms::display, display); + child->GetAttr(kNameSpaceID_None, nsXBLAtoms::extends, extends); PRBool hasDisplay = !display.IsEmpty(); PRBool hasExtends = !extends.IsEmpty(); @@ -1053,6 +996,7 @@ NS_IMETHODIMP nsXBLService::GetBindingInternal(nsIContent* aBoundElement, if (!hasExtends) protoBinding->SetHasBasePrototype(PR_FALSE); else { + // Now slice 'em up to see what we've got. nsAutoString prefix; PRInt32 offset; if (hasDisplay) { @@ -1085,8 +1029,8 @@ NS_IMETHODIMP nsXBLService::GetBindingInternal(nsIContent* aBoundElement, if (!hasDisplay) { // We extend some widget/frame. We don't really have a // base binding. - protoBinding->SetHasBasePrototype(PR_FALSE); + //child->UnsetAttr(kNameSpaceID_None, nsXBLAtoms::extends, PR_FALSE); } PRInt32 nameSpaceID; @@ -1114,6 +1058,8 @@ NS_IMETHODIMP nsXBLService::GetBindingInternal(nsIContent* aBoundElement, // Make sure to set the base prototype. baseBinding->GetPrototypeBinding(getter_AddRefs(baseProto)); protoBinding->SetBasePrototype(baseProto); + child->UnsetAttr(kNameSpaceID_None, nsXBLAtoms::extends, PR_FALSE); + child->UnsetAttr(kNameSpaceID_None, nsXBLAtoms::display, PR_FALSE); } } } @@ -1198,8 +1144,11 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement, nsIDocument* aB FetchBindingDocument(aBoundElement, aBoundDocument, uri, aRef, aForceSyncLoad, getter_AddRefs(document)); if (document) { - NS_NewXBLDocumentInfo(document, getter_AddRefs(info)); - + nsCOMPtr xblDocBindingManager; + document->GetBindingManager(getter_AddRefs(xblDocBindingManager)); + xblDocBindingManager->GetXBLDocumentInfo(aURLStr, getter_AddRefs(info)); + xblDocBindingManager->RemoveXBLDocumentInfo(info); // Break the self-imposed cycle. + // If the doc is a chrome URI, then we put it into the XUL cache. PRBool cached = PR_FALSE; if (IsChromeOrResourceURI(uri)) { @@ -1207,14 +1156,6 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement, nsIDocument* aB cached = PR_TRUE; gXULCache->PutXBLDocumentInfo(info); } - - // Cache whether or not this chrome XBL can execute scripts. - nsCOMPtr reg(do_GetService(kChromeRegistryCID, &rv)); - if (NS_SUCCEEDED(rv) && reg) { - PRBool allow = PR_TRUE; - reg->AllowScriptsForSkin(uri, &allow); - info->SetScriptAccess(allow); - } } if (!cached && bindingManager) { @@ -1272,12 +1213,19 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun aForceSyncLoad = PR_TRUE; nsCOMPtr listener; + nsCOMPtr xblSink; + NS_NewXBLContentSink(getter_AddRefs(xblSink), xmlDoc, aURI, nsnull); + if (!xblSink) + return NS_ERROR_FAILURE; + if(!aForceSyncLoad) { if (NS_FAILED(rv = xmlDoc->StartDocumentLoad("loadAsData", channel, loadGroup, nsnull, - getter_AddRefs(listener)))) { + getter_AddRefs(listener), + PR_TRUE, + xblSink))) { NS_ERROR("Failure to init XBL doc prior to load."); return rv; } @@ -1331,7 +1279,9 @@ nsXBLService::FetchBindingDocument(nsIContent* aBoundElement, nsIDocument* aBoun channel, loadGroup, nsnull, - getter_AddRefs(listener)))) { + getter_AddRefs(listener), + PR_TRUE, + xblSink))) { NS_ERROR("Failure to init XBL doc prior to load."); return rv; } @@ -1457,38 +1407,6 @@ nsXBLService::BuildPropertyChain(nsIXBLPrototypeBinding * aPrototypeBinding, nsI return NS_OK; } -nsresult -nsXBLService::BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult) -{ - nsCOMPtr firstHandler; - nsCOMPtr currHandler; - - PRInt32 handlerCount; - aContent->ChildCount(handlerCount); - for (PRInt32 j = 0; j < handlerCount; j++) { - nsCOMPtr handler; - aContent->ChildAt(j, *getter_AddRefs(handler)); - - nsAutoString event; - handler->GetAttr(kNameSpaceID_None, kEventAtom, event); - - nsCOMPtr newHandler; - NS_NewXBLPrototypeHandler(handler, getter_AddRefs(newHandler)); - - if (newHandler) { - if (currHandler) - currHandler->SetNextHandler(newHandler); - else firstHandler = newHandler; - currHandler = newHandler; - } - } - - *aResult = firstHandler; - NS_IF_ADDREF(*aResult); - - return NS_OK; -} - // Creation Routine /////////////////////////////////////////////////////////////////////// nsresult NS_NewXBLService(nsIXBLService** aResult); diff --git a/content/xbl/src/nsXBLService.h b/content/xbl/src/nsXBLService.h index 9e558d5345e1..0d2d483fff50 100644 --- a/content/xbl/src/nsXBLService.h +++ b/content/xbl/src/nsXBLService.h @@ -118,7 +118,6 @@ public: // This method walks a binding document and removes any text nodes // that contain only whitespace. static nsresult StripWhitespaceNodes(nsIContent* aContent); - static nsresult BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult); static nsresult BuildPropertyChain(nsIXBLPrototypeBinding * aPrototypeBinding, nsIContent * aContent, nsIXBLPrototypeProperty ** aResult); // MEMBER VARIABLES @@ -127,8 +126,7 @@ public: static nsIXULPrototypeCache* gXULCache; static nsINameSpaceManager* gNameSpaceManager; // Used to register the XBL namespace - static PRInt32 kNameSpaceID_XBL; // Convenient cached XBL namespace. - + static PRUint32 gRefCnt; // A count of XBLservice instances. static PRBool gDisableChromeCache; @@ -140,8 +138,6 @@ public: static PRUint32 gClassLRUListQuota; // Quota on class LRU list. // XBL Atoms - static nsIAtom* kDisplayAtom; - static nsIAtom* kExtendsAtom; static nsIAtom* kEventAtom; static nsIAtom* kScrollbarAtom; static nsIAtom* kInputAtom; diff --git a/content/xbl/src/nsXBLWindowHandler.cpp b/content/xbl/src/nsXBLWindowHandler.cpp index 498b557ed415..a6aeb8b87aee 100644 --- a/content/xbl/src/nsXBLWindowHandler.cpp +++ b/content/xbl/src/nsXBLWindowHandler.cpp @@ -148,30 +148,12 @@ nsXBLSpecialDocInfo::GetHandlers(nsIXBLDocumentInfo* aInfo, { nsCOMPtr binding; aInfo->GetPrototypeBinding(aRef, getter_AddRefs(binding)); - if (!binding) { - nsCOMPtr doc; - aInfo->GetDocument(getter_AddRefs(doc)); - nsCOMPtr root; - doc->GetRootContent(getter_AddRefs(root)); - if (root) { // no root, no handlers. don't crash please. - PRInt32 childCount; - root->ChildCount(childCount); - for (PRInt32 i = 0; i < childCount; i++) { - nsCOMPtr child; - root->ChildAt(i, *getter_AddRefs(child)); - nsAutoString id; - child->GetAttr(kNameSpaceID_None, nsHTMLAtoms::id, id); - if (id.EqualsWithConversion(PromiseFlatCString(aRef).get())) { - NS_NewXBLPrototypeBinding(aRef, child, aInfo, getter_AddRefs(binding)); - aInfo->SetPrototypeBinding(aRef, binding); - break; - } - } - } - } + + NS_ASSERTION(binding, "No binding found for the XBL window key handler."); + if (!binding) + return; - if (binding) - binding->GetPrototypeHandlers(aResult); // Addref happens here. + binding->GetPrototypeHandlers(aResult); // Addref happens here. } // GetHandlers void @@ -318,7 +300,8 @@ nsXBLWindowHandler::WalkHandlersInternal(nsIDOMEvent* aEvent, nsIAtom* aEventTyp } } - commandElt->GetAttribute(NS_LITERAL_STRING("disabled"), disabled); + if (commandElt) + commandElt->GetAttribute(NS_LITERAL_STRING("disabled"), disabled); if (!disabled.Equals(NS_LITERAL_STRING("true"))) { nsCOMPtr rec = mReceiver; if (mElement) diff --git a/content/xbl/src/nsXBLWindowKeyHandler.cpp b/content/xbl/src/nsXBLWindowKeyHandler.cpp index 15f88aaed253..0fd8b28cb2ca 100644 --- a/content/xbl/src/nsXBLWindowKeyHandler.cpp +++ b/content/xbl/src/nsXBLWindowKeyHandler.cpp @@ -53,6 +53,7 @@ #include "nsIXBLDocumentInfo.h" #include "nsIScriptGlobalObject.h" #include "nsIDOMElement.h" +#include "nsXBLAtoms.h" PRUint32 nsXBLWindowKeyHandler::gRefCnt = 0; nsIAtom* nsXBLWindowKeyHandler::kKeyDownAtom = nsnull; @@ -85,6 +86,32 @@ nsXBLWindowKeyHandler::~nsXBLWindowKeyHandler() NS_IMPL_ISUPPORTS1(nsXBLWindowKeyHandler, nsIDOMKeyListener) +static void +BuildHandlerChain(nsIContent* aContent, nsIXBLPrototypeHandler** aResult) +{ + nsCOMPtr firstHandler; + nsCOMPtr currHandler; + + PRInt32 handlerCount; + aContent->ChildCount(handlerCount); + for (PRInt32 j = 0; j < handlerCount; j++) { + nsCOMPtr handler; + aContent->ChildAt(j, *getter_AddRefs(handler)); + + nsCOMPtr newHandler; + NS_NewXULKeyHandler(handler, getter_AddRefs(newHandler)); + + if (newHandler) { + if (currHandler) + currHandler->SetNextHandler(newHandler); + else firstHandler = newHandler; + currHandler = newHandler; + } + } + + *aResult = firstHandler; + NS_IF_ADDREF(*aResult); +} // // EnsureHandlers @@ -95,18 +122,17 @@ NS_IMPL_ISUPPORTS1(nsXBLWindowKeyHandler, nsIDOMKeyListener) nsresult nsXBLWindowKeyHandler::EnsureHandlers() { - nsresult rv = NS_ERROR_FAILURE; - if (mElement) { + // We are actually a XUL . if (mHandler) return NS_OK; nsCOMPtr content(do_QueryInterface(mElement)); - rv = nsXBLService::BuildHandlerChain(content, getter_AddRefs(mHandler)); + BuildHandlerChain(content, getter_AddRefs(mHandler)); } - else + else // We are an XBL file of handlers. nsXBLWindowHandler::EnsureHandlers(); - return rv; + return NS_OK; } diff --git a/content/xbl/src/nsXBLXULHandler.cpp b/content/xbl/src/nsXBLXULHandler.cpp index 37c400960be9..6a30565998ba 100644 --- a/content/xbl/src/nsXBLXULHandler.cpp +++ b/content/xbl/src/nsXBLXULHandler.cpp @@ -63,6 +63,7 @@ #include "nsIServiceManager.h" #include "nsIURI.h" #include "nsXPIDLString.h" +#include "nsXBLAtoms.h" PRUint32 nsXBLXULHandler::gRefCnt = 0; nsIAtom* nsXBLXULHandler::kPopupShowingAtom = nsnull; @@ -113,7 +114,7 @@ nsresult nsXBLXULHandler::Command(nsIDOMEvent* aEvent) nsCOMPtr eventName; mProtoHandler->GetEventName(getter_AddRefs(eventName)); - if (eventName.get() != nsXBLPrototypeHandler::kCommandAtom) + if (eventName.get() != nsXBLAtoms::command) return NS_OK; mProtoHandler->ExecuteHandler(mEventReceiver, aEvent); diff --git a/content/xml/document/src/nsXMLContentSink.cpp b/content/xml/document/src/nsXMLContentSink.cpp index 4ff0892aab0d..a269d519d1a2 100644 --- a/content/xml/document/src/nsXMLContentSink.cpp +++ b/content/xml/document/src/nsXMLContentSink.cpp @@ -704,6 +704,9 @@ nsXMLContentSink::OpenContainer(const nsIParserNode& aNode) PRInt32 nameSpaceID = GetNameSpaceId(nameSpacePrefix); + if (!OnOpenContainer(aNode, nameSpaceID, tagAtom)) + return NS_OK; + nsCOMPtr nodeInfo; mNodeInfoManager->GetNodeInfo(tagAtom, nameSpacePrefix, nameSpaceID, diff --git a/content/xml/document/src/nsXMLContentSink.h b/content/xml/document/src/nsXMLContentSink.h index 344f95bb6c8a..450c60367431 100644 --- a/content/xml/document/src/nsXMLContentSink.h +++ b/content/xml/document/src/nsXMLContentSink.h @@ -184,6 +184,8 @@ protected: void ScrollToRef(); + virtual PRBool OnOpenContainer(const nsIParserNode& aNode, PRInt32 aNameSpaceID, nsIAtom* aTagName) { return PR_TRUE; }; + static nsINameSpaceManager* gNameSpaceManager; static PRUint32 gRefCnt; diff --git a/content/xml/document/src/nsXMLDocument.cpp b/content/xml/document/src/nsXMLDocument.cpp index 92b030dca1ee..ce7bd3fee7ef 100644 --- a/content/xml/document/src/nsXMLDocument.cpp +++ b/content/xml/document/src/nsXMLDocument.cpp @@ -370,12 +370,13 @@ nsXMLDocument::StartDocumentLoad(const char* aCommand, nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset) + PRBool aReset, + nsIContentSink* aSink) { nsresult rv = nsDocument::StartDocumentLoad(aCommand, aChannel, aLoadGroup, aContainer, - aDocListener, aReset); + aDocListener, aReset, aSink); if (NS_FAILED(rv)) return rv; nsAutoString charset(NS_LITERAL_STRING("UTF-8")); @@ -424,7 +425,7 @@ nsXMLDocument::StartDocumentLoad(const char* aCommand, (void **)&mParser); if (NS_FAILED(rv)) return rv; - nsIXMLContentSink* sink; + nsCOMPtr sink; nsCOMPtr docShell; if(aContainer) @@ -586,11 +587,18 @@ nsXMLDocument::StartDocumentLoad(const char* aCommand, } //got content view nsCOMPtr webShell(do_QueryInterface(docShell)); - rv = NS_NewXMLContentSink(&sink, this, aUrl, webShell); + if (aSink) + sink = do_QueryInterface(aSink); + else + rv = NS_NewXMLContentSink(getter_AddRefs(sink), this, aUrl, webShell); } - else - rv = NS_NewXMLContentSink(&sink, this, aUrl, nsnull); - + else { + if (aSink) + sink = do_QueryInterface(aSink); + else + rv = NS_NewXMLContentSink(getter_AddRefs(sink), this, aUrl, nsnull); + } + if (NS_OK == rv) { // Set the parser as the stream listener for the document loader... rv = mParser->QueryInterface(NS_GET_IID(nsIStreamListener), (void**)aDocListener); @@ -602,7 +610,6 @@ nsXMLDocument::StartDocumentLoad(const char* aCommand, mParser->SetContentSink(sink); mParser->Parse(aUrl, nsnull, PR_FALSE, (void *)this); } - NS_RELEASE(sink); } return rv; diff --git a/content/xml/document/src/nsXMLDocument.h b/content/xml/document/src/nsXMLDocument.h index 7e4748adeebf..20404fb1c490 100644 --- a/content/xml/document/src/nsXMLDocument.h +++ b/content/xml/document/src/nsXMLDocument.h @@ -74,7 +74,8 @@ public: nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset = PR_TRUE); + PRBool aReset = PR_TRUE, + nsIContentSink* aSink = nsnull); NS_IMETHOD EndLoad(); diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index b2c3db07cda7..c97853ee7976 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -726,7 +726,8 @@ nsXULDocument::StartDocumentLoad(const char* aCommand, nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset) + PRBool aReset, + nsIContentSink* aSink) { nsresult rv; diff --git a/content/xul/document/src/nsXULDocument.h b/content/xul/document/src/nsXULDocument.h index 7ef974c40055..45483c4f97c1 100644 --- a/content/xul/document/src/nsXULDocument.h +++ b/content/xul/document/src/nsXULDocument.h @@ -149,7 +149,8 @@ public: nsILoadGroup* aLoadGroup, nsISupports* aContainer, nsIStreamListener **aDocListener, - PRBool aReset); + PRBool aReset = PR_TRUE, + nsIContentSink* aSink = nsnull); NS_IMETHOD StopDocumentLoad(); diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 5e7393b66c95..6097a19bfb5c 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -13095,6 +13095,9 @@ nsCSSFrameConstructor::WipeContainingBlock(nsIPresContext* aPresContext, // situation: an inline frame that will now contain block // frames. This is a no-no and the frame construction logic knows // how to fix this. + if (!aBlockContent) + return PR_FALSE; + const nsStyleDisplay* parentDisplay; aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&) parentDisplay); if (NS_STYLE_DISPLAY_INLINE == parentDisplay->mDisplay) { diff --git a/layout/build/nsLayoutModule.cpp b/layout/build/nsLayoutModule.cpp index 55662f5c3bfb..a3a3f892f345 100644 --- a/layout/build/nsLayoutModule.cpp +++ b/layout/build/nsLayoutModule.cpp @@ -52,6 +52,7 @@ #include "nsIPrintContext.h" #include "nsTextTransformer.h" +#include "nsXBLAtoms.h" // to addref/release table #include "nsHTMLAtoms.h" // to addref/release table #include "nsLayoutAtoms.h" // to addref/release table #include "nsCSSKeywords.h" // to addref/release table @@ -100,6 +101,7 @@ Initialize(nsIModule* self) nsCSSProps::AddRefTable(); nsColorNames::AddRefTable(); nsHTMLAtoms::AddRefAtoms(); + nsXBLAtoms::AddRefAtoms(); nsLayoutAtoms::AddRefAtoms(); #ifdef INCLUDE_XUL nsXULAtoms::AddRefAtoms(); @@ -142,6 +144,7 @@ Shutdown(nsIModule* self) nsCSSKeywords::ReleaseTable(); nsCSSAtoms::ReleaseAtoms(); nsHTMLAtoms::ReleaseAtoms(); + nsXBLAtoms::ReleaseAtoms(); nsLayoutAtoms::ReleaseAtoms(); #ifdef INCLUDE_XUL diff --git a/layout/html/style/src/nsCSSFrameConstructor.cpp b/layout/html/style/src/nsCSSFrameConstructor.cpp index 5e7393b66c95..6097a19bfb5c 100644 --- a/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -13095,6 +13095,9 @@ nsCSSFrameConstructor::WipeContainingBlock(nsIPresContext* aPresContext, // situation: an inline frame that will now contain block // frames. This is a no-no and the frame construction logic knows // how to fix this. + if (!aBlockContent) + return PR_FALSE; + const nsStyleDisplay* parentDisplay; aFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct *&) parentDisplay); if (NS_STYLE_DISPLAY_INLINE == parentDisplay->mDisplay) {