2001-09-25 05:32:19 +04:00
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2012-05-21 15:12:37 +04:00
/* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2.0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/. */
2000-03-21 16:14:34 +03:00
2013-12-09 06:52:54 +04:00
# include "mozilla/ArrayUtils.h"
2011-10-11 09:50:08 +04:00
2000-01-12 12:25:28 +03:00
# include "nsCOMPtr.h"
2001-06-22 02:02:47 +04:00
# include "nsNetUtil.h"
2000-05-28 08:10:50 +04:00
# include "nsXBLService.h"
2000-09-22 09:02:20 +04:00
# include "nsXBLWindowKeyHandler.h"
2000-01-12 12:44:18 +03:00
# include "nsIInputStream.h"
2014-02-28 03:04:46 +04:00
# include "nsNameSpaceManager.h"
2000-01-12 12:44:18 +03:00
# include "nsIURI.h"
2000-09-22 09:02:20 +04:00
# include "nsIDOMElement.h"
2000-01-12 12:44:18 +03:00
# include "nsIURL.h"
# include "nsIChannel.h"
# include "nsXPIDLString.h"
# include "plstr.h"
2000-01-12 12:57:45 +03:00
# include "nsIContent.h"
# include "nsIDocument.h"
2000-01-12 13:20:11 +03:00
# include "nsIXMLContentSink.h"
2001-02-19 15:55:42 +03:00
# include "nsContentCID.h"
2013-03-20 20:22:26 +04:00
# include "mozilla/dom/XMLDocument.h"
2006-12-26 20:47:52 +03:00
# include "nsGkAtoms.h"
2000-09-20 09:44:19 +04:00
# include "nsIMemory.h"
# include "nsIObserverService.h"
2000-12-10 12:23:43 +03:00
# include "nsIDOMNodeList.h"
2001-11-02 04:53:13 +03:00
# include "nsXBLContentSink.h"
2005-02-26 01:07:01 +03:00
# include "nsXBLBinding.h"
2003-03-07 02:59:18 +03:00
# include "nsXBLPrototypeBinding.h"
2010-07-15 05:53:11 +04:00
# include "nsXBLDocumentInfo.h"
2002-05-15 22:55:21 +04:00
# include "nsCRT.h"
2002-10-09 11:03:15 +04:00
# include "nsContentUtils.h"
2006-06-16 00:30:44 +04:00
# include "nsSyncLoadService.h"
2005-05-11 01:07:00 +04:00
# include "nsContentPolicyUtils.h"
2009-03-20 11:15:35 +03:00
# include "nsTArray.h"
2012-07-27 18:03:27 +04:00
# include "nsError.h"
2000-08-12 10:28:02 +04:00
2000-08-14 08:04:18 +04:00
# include "nsIPresShell.h"
# include "nsIDocumentObserver.h"
2004-02-24 00:29:06 +03:00
# include "nsFrameManager.h"
2003-02-22 03:32:13 +03:00
# include "nsStyleContext.h"
2003-05-01 06:41:45 +04:00
# include "nsIScriptSecurityManager.h"
2006-10-08 14:18:41 +04:00
# include "nsIScriptError.h"
2011-11-04 00:39:08 +04:00
# include "nsXBLSerialize.h"
2000-08-14 08:04:18 +04:00
2003-04-11 04:56:27 +04:00
# ifdef MOZ_XUL
2007-03-12 08:53:33 +03:00
# include "nsXULPrototypeCache.h"
2003-04-11 04:56:27 +04:00
# endif
2011-06-25 03:12:34 +04:00
# include "nsIDOMEventListener.h"
2014-03-05 04:37:43 +04:00
# include "mozilla/Attributes.h"
2014-03-17 10:56:53 +04:00
# include "mozilla/EventListenerManager.h"
2011-05-29 03:42:57 +04:00
# include "mozilla/Preferences.h"
2014-03-05 04:37:43 +04:00
# include "mozilla/dom/Event.h"
2011-07-20 23:18:54 +04:00
# include "mozilla/dom/Element.h"
2011-05-29 03:42:57 +04:00
using namespace mozilla ;
2013-04-06 04:44:15 +04:00
using namespace mozilla : : dom ;
2000-08-06 02:33:29 +04:00
2007-04-01 16:19:44 +04:00
# define NS_MAX_XBL_BINDING_RECURSION 20
2012-07-30 18:20:58 +04:00
nsXBLService * nsXBLService : : gInstance = nullptr ;
2012-05-23 22:46:04 +04:00
2011-09-29 10:19:26 +04:00
static bool
2006-10-08 14:18:41 +04:00
IsAncestorBinding ( nsIDocument * aDocument ,
nsIURI * aChildBindingURI ,
nsIContent * aChild )
{
NS_ASSERTION ( aDocument , " expected a document " ) ;
NS_ASSERTION ( aChildBindingURI , " expected a binding URI " ) ;
NS_ASSERTION ( aChild , " expected a child content " ) ;
2012-08-22 19:56:38 +04:00
uint32_t bindingRecursion = 0 ;
2008-07-23 08:50:20 +04:00
for ( nsIContent * bindingParent = aChild - > GetBindingParent ( ) ;
bindingParent ;
bindingParent = bindingParent - > GetBindingParent ( ) ) {
2013-07-17 20:05:03 +04:00
nsXBLBinding * binding = bindingParent - > GetXBLBinding ( ) ;
2006-10-08 14:18:41 +04:00
if ( ! binding ) {
continue ;
}
2008-09-22 03:40:02 +04:00
2009-11-04 00:45:10 +03:00
if ( binding - > PrototypeBinding ( ) - > CompareBindingURI ( aChildBindingURI ) ) {
2007-04-01 16:19:44 +04:00
+ + bindingRecursion ;
if ( bindingRecursion < NS_MAX_XBL_BINDING_RECURSION ) {
continue ;
}
2012-09-02 06:35:17 +04:00
nsAutoCString spec ;
2006-10-08 14:18:41 +04:00
aChildBindingURI - > GetSpec ( spec ) ;
NS_ConvertUTF8toUTF16 bindingURI ( spec ) ;
2014-01-04 19:02:17 +04:00
const char16_t * params [ ] = { bindingURI . get ( ) } ;
2011-12-15 18:47:03 +04:00
nsContentUtils : : ReportToConsole ( nsIScriptError : : warningFlag ,
2013-08-21 23:28:26 +04:00
NS_LITERAL_CSTRING ( " XBL " ) , aDocument ,
2011-12-15 18:47:03 +04:00
nsContentUtils : : eXBL_PROPERTIES ,
2007-04-01 16:19:44 +04:00
" TooDeepBindingRecursion " ,
2011-12-15 18:47:03 +04:00
params , ArrayLength ( params ) ) ;
2011-10-17 18:59:28 +04:00
return true ;
2006-10-08 14:18:41 +04:00
}
}
2011-10-17 18:59:28 +04:00
return false ;
2006-10-08 14:18:41 +04:00
}
2000-08-06 02:33:29 +04:00
// Individual binding requests.
2001-04-04 09:00:08 +04:00
class nsXBLBindingRequest
2000-08-06 02:33:29 +04:00
{
2001-04-04 09:00:08 +04:00
public :
2007-02-24 19:27:51 +03:00
nsCOMPtr < nsIURI > mBindingURI ;
2000-08-06 08:57:55 +04:00
nsCOMPtr < nsIContent > mBoundElement ;
void DocumentLoaded ( nsIDocument * aBindingDoc )
{
2004-12-02 05:24:28 +03:00
// We only need the document here to cause frame construction, so
// we need the current doc, not the owner doc.
nsIDocument * doc = mBoundElement - > GetCurrentDoc ( ) ;
2000-08-06 08:57:55 +04:00
if ( ! doc )
return ;
2000-08-14 08:04:18 +04:00
// Get the binding.
2011-09-29 10:19:26 +04:00
bool ready = false ;
2012-05-23 22:46:04 +04:00
nsXBLService : : GetInstance ( ) - > BindingReady ( mBoundElement , mBindingURI , & ready ) ;
2000-08-14 08:04:18 +04:00
if ( ! ready )
return ;
2000-08-06 08:57:55 +04:00
2002-05-01 04:36:50 +04:00
// If |mBoundElement| is (in addition to having binding |mBinding|)
// also a descendant of another element with binding |mBinding|,
// then we might have just constructed it due to the
// notification of its parent. (We can know about both if the
// binding loads were triggered from the DOM rather than frame
// construction.) So we have to check both whether the element
// has a primary frame and whether it's in the undisplayed map
// before sending a ContentInserted notification, or bad things
// will happen.
2010-06-25 17:59:57 +04:00
nsIPresShell * shell = doc - > GetShell ( ) ;
2000-08-14 08:04:18 +04:00
if ( shell ) {
2009-12-25 00:20:05 +03:00
nsIFrame * childFrame = mBoundElement - > GetPrimaryFrame ( ) ;
2002-05-01 04:36:50 +04:00
if ( ! childFrame ) {
// Check to see if it's in the undisplayed content map.
2004-02-24 00:29:06 +03:00
nsStyleContext * sc =
shell - > FrameManager ( ) - > GetUndisplayedContent ( mBoundElement ) ;
2002-05-01 04:36:50 +04:00
if ( ! sc ) {
2007-01-13 06:32:31 +03:00
shell - > RecreateFramesFor ( mBoundElement ) ;
2002-05-01 04:36:50 +04:00
}
}
2000-08-14 08:04:18 +04:00
}
2000-08-06 08:57:55 +04:00
}
2007-02-24 19:27:51 +03:00
nsXBLBindingRequest ( nsIURI * aURI , nsIContent * aBoundElement )
: mBindingURI ( aURI ) ,
2003-11-18 00:03:32 +03:00
mBoundElement ( aBoundElement )
2001-04-04 09:00:08 +04:00
{
}
2000-08-14 08:04:18 +04:00
} ;
2014-03-19 01:25:39 +04:00
// nsXBLStreamListener, a helper class used for
2000-08-04 12:45:29 +04:00
// asynchronous parsing of URLs
/* Header file */
2012-06-19 06:30:09 +04:00
class nsXBLStreamListener MOZ_FINAL : public nsIStreamListener ,
public nsIDOMEventListener
2000-08-04 12:45:29 +04:00
{
public :
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLISTENER
2001-04-10 10:01:08 +04:00
NS_DECL_NSIREQUESTOBSERVER
2011-06-25 03:12:34 +04:00
NS_DECL_NSIDOMEVENTLISTENER
2000-08-12 10:28:02 +04:00
2012-05-23 22:46:04 +04:00
nsXBLStreamListener ( nsIDocument * aBoundDocument ,
2009-01-14 14:24:26 +03:00
nsIXMLContentSink * aSink ,
nsIDocument * aBindingDocument ) ;
2007-11-08 03:05:03 +03:00
2007-04-23 18:21:53 +04:00
void AddRequest ( nsXBLBindingRequest * aRequest ) { mBindingRequests . AppendElement ( aRequest ) ; }
2011-09-29 10:19:26 +04:00
bool HasRequest ( nsIURI * aURI , nsIContent * aBoundElement ) ;
2000-08-06 02:33:29 +04:00
2000-08-06 08:57:55 +04:00
private :
2014-06-23 23:56:07 +04:00
~ nsXBLStreamListener ( ) ;
2000-08-06 08:57:55 +04:00
nsCOMPtr < nsIStreamListener > mInner ;
2009-03-20 11:15:35 +03:00
nsAutoTArray < nsXBLBindingRequest * , 8 > mBindingRequests ;
2014-03-19 01:25:39 +04:00
2009-01-14 14:24:26 +03:00
nsCOMPtr < nsIWeakReference > mBoundDocument ;
nsCOMPtr < nsIXMLContentSink > mSink ; // Only set until OnStartRequest
nsCOMPtr < nsIDocument > mBindingDocument ; // Only set until OnStartRequest
2000-08-04 12:45:29 +04:00
} ;
/* Implementation file */
2014-04-27 11:06:00 +04:00
NS_IMPL_ISUPPORTS ( nsXBLStreamListener ,
nsIStreamListener ,
nsIRequestObserver ,
nsIDOMEventListener )
2000-08-04 12:45:29 +04:00
2012-05-23 22:46:04 +04:00
nsXBLStreamListener : : nsXBLStreamListener ( nsIDocument * aBoundDocument ,
2009-01-14 14:24:26 +03:00
nsIXMLContentSink * aSink ,
nsIDocument * aBindingDocument )
: mSink ( aSink ) , mBindingDocument ( aBindingDocument )
2000-08-04 12:45:29 +04:00
{
/* member initializers and constructor code */
2009-01-14 14:24:26 +03:00
mBoundDocument = do_GetWeakReference ( aBoundDocument ) ;
2007-11-08 03:05:03 +03:00
}
nsXBLStreamListener : : ~ nsXBLStreamListener ( )
{
2012-08-22 19:56:38 +04:00
for ( uint32_t i = 0 ; i < mBindingRequests . Length ( ) ; i + + ) {
2009-03-20 11:15:35 +03:00
nsXBLBindingRequest * req = mBindingRequests . ElementAt ( i ) ;
2013-03-05 16:37:47 +04:00
delete req ;
2007-11-08 03:05:03 +03:00
}
2000-08-04 12:45:29 +04:00
}
NS_IMETHODIMP
2012-09-06 06:41:02 +04:00
nsXBLStreamListener : : OnDataAvailable ( nsIRequest * request , nsISupports * aCtxt ,
2013-03-05 16:37:47 +04:00
nsIInputStream * aInStr ,
2012-09-06 06:41:02 +04:00
uint64_t aSourceOffset , uint32_t aCount )
2000-08-04 12:45:29 +04:00
{
if ( mInner )
2001-02-21 23:38:08 +03:00
return mInner - > OnDataAvailable ( request , aCtxt , aInStr , aSourceOffset , aCount ) ;
2000-08-04 12:45:29 +04:00
return NS_ERROR_FAILURE ;
}
NS_IMETHODIMP
2001-02-21 23:38:08 +03:00
nsXBLStreamListener : : OnStartRequest ( nsIRequest * request , nsISupports * aCtxt )
2000-08-04 12:45:29 +04:00
{
2009-01-14 14:24:26 +03:00
// Make sure we don't hold on to the sink and binding document past this point
nsCOMPtr < nsIXMLContentSink > sink ;
mSink . swap ( sink ) ;
nsCOMPtr < nsIDocument > doc ;
mBindingDocument . swap ( doc ) ;
nsCOMPtr < nsIChannel > channel = do_QueryInterface ( request ) ;
NS_ENSURE_TRUE ( channel , NS_ERROR_UNEXPECTED ) ;
nsCOMPtr < nsILoadGroup > group ;
request - > GetLoadGroup ( getter_AddRefs ( group ) ) ;
nsresult rv = doc - > StartDocumentLoad ( " loadAsInteractiveData " ,
channel ,
group ,
2012-07-30 18:20:58 +04:00
nullptr ,
2009-01-14 14:24:26 +03:00
getter_AddRefs ( mInner ) ,
2011-10-17 18:59:28 +04:00
true ,
2009-01-14 14:24:26 +03:00
sink ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
// Make sure to add ourselves as a listener after StartDocumentLoad,
// since that resets the event listners on the document.
2013-04-06 04:44:15 +04:00
doc - > AddEventListener ( NS_LITERAL_STRING ( " load " ) , this , false ) ;
2009-01-14 14:24:26 +03:00
return mInner - > OnStartRequest ( request , aCtxt ) ;
2000-08-04 12:45:29 +04:00
}
2014-03-19 01:25:39 +04:00
NS_IMETHODIMP
2001-04-10 10:01:08 +04:00
nsXBLStreamListener : : OnStopRequest ( nsIRequest * request , nsISupports * aCtxt , nsresult aStatus )
2000-08-04 12:45:29 +04:00
{
2000-08-12 10:28:02 +04:00
nsresult rv = NS_OK ;
2000-08-06 08:57:55 +04:00
if ( mInner ) {
2001-04-10 10:01:08 +04:00
rv = mInner - > OnStopRequest ( request , aCtxt , aStatus ) ;
2000-08-12 10:28:02 +04:00
}
2000-08-06 08:57:55 +04:00
2007-11-08 03:05:03 +03:00
// Don't hold onto the inner listener; holding onto it can create a cycle
// with the document
2012-07-30 18:20:58 +04:00
mInner = nullptr ;
2000-08-06 08:57:55 +04:00
2000-08-12 10:28:02 +04:00
return rv ;
}
2011-09-29 10:19:26 +04:00
bool
2003-11-18 00:03:32 +03:00
nsXBLStreamListener : : HasRequest ( nsIURI * aURI , nsIContent * aElt )
2000-08-14 08:04:18 +04:00
{
// XXX Could be more efficient.
2012-08-22 19:56:38 +04:00
uint32_t count = mBindingRequests . Length ( ) ;
for ( uint32_t i = 0 ; i < count ; i + + ) {
2009-03-20 11:15:35 +03:00
nsXBLBindingRequest * req = mBindingRequests . ElementAt ( i ) ;
2011-09-29 10:19:26 +04:00
bool eq ;
2003-11-18 00:03:32 +03:00
if ( req - > mBoundElement = = aElt & &
2007-02-24 19:27:51 +03:00
NS_SUCCEEDED ( req - > mBindingURI - > Equals ( aURI , & eq ) ) & & eq )
2011-10-17 18:59:28 +04:00
return true ;
2000-08-14 08:04:18 +04:00
}
2011-10-17 18:59:28 +04:00
return false ;
2000-08-14 08:04:18 +04:00
}
2000-08-12 10:28:02 +04:00
nsresult
2011-06-25 03:12:34 +04:00
nsXBLStreamListener : : HandleEvent ( nsIDOMEvent * aEvent )
2000-08-12 10:28:02 +04:00
{
nsresult rv = NS_OK ;
2012-08-22 19:56:38 +04:00
uint32_t i ;
uint32_t count = mBindingRequests . Length ( ) ;
2007-11-08 03:05:03 +03:00
// Get the binding document; note that we don't hold onto it in this object
// to avoid creating a cycle
2014-03-05 04:37:43 +04:00
Event * event = aEvent - > InternalDOMEvent ( ) ;
2013-04-06 04:44:26 +04:00
EventTarget * target = event - > GetCurrentTarget ( ) ;
2007-11-08 03:05:03 +03:00
nsCOMPtr < nsIDocument > bindingDocument = do_QueryInterface ( target ) ;
NS_ASSERTION ( bindingDocument , " Event not targeted at document?! " ) ;
2000-08-16 01:00:52 +04:00
// See if we're still alive.
2009-01-14 14:24:26 +03:00
nsCOMPtr < nsIDocument > doc ( do_QueryReferent ( mBoundDocument ) ) ;
2000-08-16 01:00:52 +04:00
if ( ! doc ) {
2000-10-29 02:17:53 +04:00
NS_WARNING ( " XBL load did not complete until after document went away! Modal dialog bug? \n " ) ;
2000-08-16 01:00:52 +04:00
}
else {
2001-03-04 01:01:01 +03:00
// We have to do a flush prior to notification of the document load.
// This has to happen since the HTML content sink can be holding on
// to notifications related to our children (e.g., if you bind to the
2014-03-19 01:25:39 +04:00
// <body> tag) that result in duplication of content.
2001-03-04 01:01:01 +03:00
// We need to get the sink's notifications flushed and then make the binding
// ready.
if ( count > 0 ) {
2009-03-20 11:15:35 +03:00
nsXBLBindingRequest * req = mBindingRequests . ElementAt ( 0 ) ;
2004-12-02 05:24:28 +03:00
nsIDocument * document = req - > mBoundElement - > GetCurrentDoc ( ) ;
2001-03-04 01:01:01 +03:00
if ( document )
2004-05-28 02:08:42 +04:00
document - > FlushPendingNotifications ( Flush_ContentAndNotify ) ;
2001-03-04 01:01:01 +03:00
}
2000-08-16 01:00:52 +04:00
// Remove ourselves from the set of pending docs.
2007-02-17 02:02:08 +03:00
nsBindingManager * bindingManager = doc - > BindingManager ( ) ;
2007-11-08 03:05:03 +03:00
nsIURI * documentURI = bindingDocument - > GetDocumentURI ( ) ;
2003-11-18 00:03:32 +03:00
bindingManager - > RemoveLoadingDocListener ( documentURI ) ;
2000-08-16 01:00:52 +04:00
2010-04-30 17:12:05 +04:00
if ( ! bindingDocument - > GetRootElement ( ) ) {
2010-05-05 08:28:19 +04:00
// FIXME: How about an error console warning?
2012-04-09 05:37:41 +04:00
NS_WARNING ( " XBL doc with no root element - this usually shouldn't happen " ) ;
2000-09-02 05:09:47 +04:00
return NS_ERROR_FAILURE ;
}
2000-08-16 01:00:52 +04:00
2001-11-02 04:53:13 +03:00
// Put our doc info in the doc table.
2007-11-08 03:05:03 +03:00
nsBindingManager * xblDocBindingManager = bindingDocument - > BindingManager ( ) ;
2010-07-15 05:53:11 +04:00
nsRefPtr < nsXBLDocumentInfo > info =
2007-02-27 03:14:01 +03:00
xblDocBindingManager - > GetXBLDocumentInfo ( documentURI ) ;
2001-11-02 04:53:13 +03:00
xblDocBindingManager - > RemoveXBLDocumentInfo ( info ) ; // Break the self-imposed cycle.
2001-11-11 04:15:22 +03:00
if ( ! info ) {
2011-11-04 00:39:07 +04:00
if ( nsXBLService : : IsChromeOrResourceURI ( documentURI ) ) {
2010-05-05 08:28:19 +04:00
NS_WARNING ( " An XBL file is malformed. Did you forget the XBL namespace on the bindings tag? " ) ;
}
2011-12-15 18:47:03 +04:00
nsContentUtils : : ReportToConsole ( nsIScriptError : : warningFlag ,
2013-08-21 23:28:26 +04:00
NS_LITERAL_CSTRING ( " XBL " ) , nullptr ,
2011-12-15 18:47:03 +04:00
nsContentUtils : : eXBL_PROPERTIES ,
2010-05-05 08:28:19 +04:00
" MalformedXBL " ,
2012-07-30 18:20:58 +04:00
nullptr , 0 , documentURI ) ;
2001-11-11 04:15:22 +03:00
return NS_ERROR_FAILURE ;
}
2001-11-02 04:53:13 +03:00
2000-08-16 01:00:52 +04:00
// If the doc is a chrome URI, then we put it into the XUL cache.
2003-04-11 04:56:27 +04:00
# ifdef MOZ_XUL
2011-11-04 00:39:07 +04:00
if ( nsXBLService : : IsChromeOrResourceURI ( documentURI ) ) {
2007-03-12 08:53:33 +03:00
nsXULPrototypeCache * cache = nsXULPrototypeCache : : GetInstance ( ) ;
if ( cache & & cache - > IsEnabled ( ) )
cache - > PutXBLDocumentInfo ( info ) ;
2000-08-12 10:28:02 +04:00
}
2003-04-11 04:56:27 +04:00
# endif
2014-03-19 01:25:39 +04:00
2003-06-21 03:33:43 +04:00
bindingManager - > PutXBLDocumentInfo ( info ) ;
2000-08-12 10:28:02 +04:00
2000-08-16 01:00:52 +04:00
// Notify all pending requests that their bindings are
// ready and can be installed.
for ( i = 0 ; i < count ; i + + ) {
2009-03-20 11:15:35 +03:00
nsXBLBindingRequest * req = mBindingRequests . ElementAt ( i ) ;
2007-11-08 03:05:03 +03:00
req - > DocumentLoaded ( bindingDocument ) ;
2000-08-16 01:00:52 +04:00
}
2000-08-12 10:28:02 +04:00
}
2011-10-17 18:59:28 +04:00
target - > RemoveEventListener ( NS_LITERAL_STRING ( " load " ) , this , false ) ;
2000-08-12 10:28:02 +04:00
return rv ;
2000-08-04 12:45:29 +04:00
}
2000-01-12 12:44:18 +03:00
// Implementation /////////////////////////////////////////////////////////////////
// Static member variable initialization
2011-09-29 10:19:26 +04:00
bool nsXBLService : : gAllowDataURIs = false ;
2008-04-29 03:56:07 +04:00
2000-01-12 12:44:18 +03:00
// Implement our nsISupports methods
2014-04-27 11:06:00 +04:00
NS_IMPL_ISUPPORTS ( nsXBLService , nsISupportsWeakReference )
2012-05-23 22:46:04 +04:00
void
nsXBLService : : Init ( )
{
gInstance = new nsXBLService ( ) ;
NS_ADDREF ( gInstance ) ;
}
2000-01-12 12:25:28 +03:00
2000-01-12 12:44:18 +03:00
// Constructors/Destructors
nsXBLService : : nsXBLService ( void )
{
2011-05-29 03:42:57 +04:00
Preferences : : AddBoolVarCache ( & gAllowDataURIs , " layout.debug.enable_data_xbl " ) ;
2000-01-12 12:44:18 +03:00
}
nsXBLService : : ~ nsXBLService ( void )
{
}
2000-01-12 12:32:29 +03:00
2011-11-04 00:39:07 +04:00
// static
bool
nsXBLService : : IsChromeOrResourceURI ( nsIURI * aURI )
{
bool isChrome = false ;
bool isResource = false ;
2014-03-19 01:25:39 +04:00
if ( NS_SUCCEEDED ( aURI - > SchemeIs ( " chrome " , & isChrome ) ) & &
2011-11-04 00:39:07 +04:00
NS_SUCCEEDED ( aURI - > SchemeIs ( " resource " , & isResource ) ) )
return ( isChrome | | isResource ) ;
return false ;
}
2000-01-12 12:32:29 +03:00
// This function loads a particular XBL file and installs all of the bindings
// onto the element.
2012-05-23 22:46:04 +04:00
nsresult
2007-07-19 01:56:57 +04:00
nsXBLService : : LoadBindings ( nsIContent * aContent , nsIURI * aURL ,
2013-01-24 21:45:50 +04:00
nsIPrincipal * aOriginPrincipal ,
2014-03-19 01:25:39 +04:00
nsXBLBinding * * aBinding , bool * aResolveStyle )
2007-07-19 01:56:57 +04:00
{
NS_PRECONDITION ( aOriginPrincipal , " Must have an origin principal " ) ;
2014-03-19 01:25:39 +04:00
2012-07-30 18:20:58 +04:00
* aBinding = nullptr ;
2011-10-17 18:59:28 +04:00
* aResolveStyle = false ;
2000-07-28 04:35:02 +04:00
2000-01-12 12:57:45 +03:00
nsresult rv ;
2000-01-13 05:23:54 +03:00
2011-10-18 14:53:36 +04:00
nsCOMPtr < nsIDocument > document = aContent - > OwnerDoc ( ) ;
2001-07-04 09:54:09 +04:00
2012-09-02 06:35:17 +04:00
nsAutoCString urlspec ;
2008-11-14 03:00:11 +03:00
if ( nsContentUtils : : GetWrapperSafeScriptFilename ( document , aURL , urlspec ) ) {
// Block an attempt to load a binding that has special wrapper
// automation needs.
return NS_OK ;
}
2013-07-17 20:05:03 +04:00
nsXBLBinding * binding = aContent - > GetXBLBinding ( ) ;
2013-01-24 21:45:50 +04:00
if ( binding ) {
2013-07-11 19:58:28 +04:00
if ( binding - > MarkedForDeath ( ) ) {
FlushStyleBindings ( aContent ) ;
binding = nullptr ;
}
else {
// See if the URIs match.
if ( binding - > PrototypeBinding ( ) - > CompareBindingURI ( aURL ) )
return NS_OK ;
FlushStyleBindings ( aContent ) ;
binding = nullptr ;
2000-06-02 12:13:29 +04:00
}
2000-04-27 06:08:35 +04:00
}
2000-01-13 11:54:16 +03:00
2011-09-29 10:19:26 +04:00
bool ready ;
2005-02-26 01:07:01 +03:00
nsRefPtr < nsXBLBinding > newBinding ;
2011-10-17 18:59:28 +04:00
if ( NS_FAILED ( rv = GetBinding ( aContent , aURL , false , aOriginPrincipal ,
2007-07-19 01:56:57 +04:00
& ready , getter_AddRefs ( newBinding ) ) ) ) {
2000-01-12 12:57:45 +03:00
return rv ;
}
2000-01-12 12:44:18 +03:00
2000-06-02 12:13:29 +04:00
if ( ! newBinding ) {
2003-10-02 02:53:56 +04:00
# ifdef DEBUG
2012-09-02 06:35:17 +04:00
nsAutoCString spec ;
2003-10-02 02:53:56 +04:00
aURL - > GetSpec ( spec ) ;
2012-09-02 06:35:17 +04:00
nsAutoCString str ( NS_LITERAL_CSTRING ( " Failed to locate XBL binding. XBL is now using id instead of name to reference bindings. Make sure you have switched over. The invalid binding name is: " ) + spec ) ;
2001-10-27 10:44:19 +04:00
NS_ERROR ( str . get ( ) ) ;
2003-10-02 02:53:56 +04:00
# endif
2000-08-04 12:45:29 +04:00
return NS_OK ;
2000-03-30 07:18:44 +04:00
}
2006-10-08 14:18:41 +04:00
if ( : : IsAncestorBinding ( document , aURL , aContent ) ) {
return NS_ERROR_ILLEGAL_VALUE ;
}
2013-01-24 21:45:50 +04:00
// We loaded a style binding. It goes on the end.
if ( binding ) {
// Get the last binding that is in the append layer.
binding - > RootBinding ( ) - > SetBaseBinding ( newBinding ) ;
2000-06-02 12:13:29 +04:00
}
else {
2013-01-24 21:45:50 +04:00
// Install the binding on the content node.
2013-07-17 20:05:03 +04:00
aContent - > SetXBLBinding ( newBinding ) ;
2000-06-02 12:13:29 +04:00
}
2009-11-18 18:14:14 +03:00
{
nsAutoScriptBlocker scriptBlocker ;
2000-01-13 05:23:54 +03:00
2009-11-18 18:14:14 +03:00
// Set the binding's bound element.
newBinding - > SetBoundElement ( aContent ) ;
2000-01-13 11:54:16 +03:00
2009-11-18 18:14:14 +03:00
// Tell the binding to build the anonymous content.
newBinding - > GenerateAnonymousContent ( ) ;
2008-03-15 02:08:57 +03:00
2009-11-18 18:14:14 +03:00
// Tell the binding to install event handlers
newBinding - > InstallEventHandlers ( ) ;
2008-03-15 02:08:57 +03:00
2009-11-18 18:14:14 +03:00
// Set up our properties
rv = newBinding - > InstallImplementation ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
// Figure out if we have any scoped sheets. If so, we do a second resolve.
* aResolveStyle = newBinding - > HasStyleSheets ( ) ;
2014-03-19 01:25:39 +04:00
2009-11-18 18:14:14 +03:00
newBinding . swap ( * aBinding ) ;
}
2007-10-27 04:14:43 +04:00
2014-03-19 01:25:39 +04:00
return NS_OK ;
2000-01-12 12:32:29 +03:00
}
2003-03-04 04:04:27 +03:00
nsresult
2000-06-02 12:13:29 +04:00
nsXBLService : : FlushStyleBindings ( nsIContent * aContent )
2000-03-28 04:41:33 +04:00
{
2011-10-18 14:53:36 +04:00
nsCOMPtr < nsIDocument > document = aContent - > OwnerDoc ( ) ;
2001-07-04 09:54:09 +04:00
2013-07-17 20:05:03 +04:00
nsXBLBinding * binding = aContent - > GetXBLBinding ( ) ;
2000-04-03 11:13:07 +04:00
if ( binding ) {
2013-07-11 19:58:28 +04:00
// Clear out the script references.
binding - > ChangeDocument ( document , nullptr ) ;
2000-06-02 12:13:29 +04:00
2013-07-17 20:05:03 +04:00
aContent - > SetXBLBinding ( nullptr ) ; // Flush old style bindings
2000-04-03 11:13:07 +04:00
}
2014-03-19 01:25:39 +04:00
2000-03-28 04:41:33 +04:00
return NS_OK ;
}
2000-11-29 09:01:33 +03:00
//
// AttachGlobalKeyHandler
//
// Creates a new key handler and prepares to listen to key events on the given
// event receiver (either a document or an content node). If the receiver is content,
// then extra work needs to be done to hook it up to the document (XXX WHY??)
//
2012-05-23 22:46:04 +04:00
nsresult
2013-04-06 04:44:26 +04:00
nsXBLService : : AttachGlobalKeyHandler ( EventTarget * aTarget )
2000-09-22 09:02:20 +04:00
{
2000-11-29 09:01:33 +03:00
// check if the receiver is a content node (not a document), and hook
// it to the document if that is the case.
2013-04-06 04:44:26 +04:00
nsCOMPtr < EventTarget > piTarget = aTarget ;
2007-05-14 13:11:38 +04:00
nsCOMPtr < nsIContent > contentNode ( do_QueryInterface ( aTarget ) ) ;
2000-11-29 09:01:33 +03:00
if ( contentNode ) {
2004-12-02 05:24:28 +03:00
// Only attach if we're really in a document
nsCOMPtr < nsIDocument > doc = contentNode - > GetCurrentDoc ( ) ;
2000-09-22 09:02:20 +04:00
if ( doc )
2011-06-24 06:18:02 +04:00
piTarget = doc ; // We're a XUL keyset. Attach to our document.
2000-09-22 09:02:20 +04:00
}
2011-06-24 06:18:02 +04:00
2014-03-17 10:56:53 +04:00
EventListenerManager * manager = piTarget - > GetOrCreateListenerManager ( ) ;
2013-04-06 04:44:26 +04:00
2011-06-24 06:18:02 +04:00
if ( ! piTarget | | ! manager )
2000-09-22 09:02:20 +04:00
return NS_ERROR_FAILURE ;
2008-08-06 18:32:09 +04:00
// the listener already exists, so skip this
if ( contentNode & & contentNode - > GetProperty ( nsGkAtoms : : listener ) )
return NS_OK ;
2013-04-14 22:27:33 +04:00
2000-11-29 09:01:33 +03:00
nsCOMPtr < nsIDOMElement > elt ( do_QueryInterface ( contentNode ) ) ;
2000-09-22 09:02:20 +04:00
2000-11-29 09:01:33 +03:00
// Create the key handler
2013-04-14 22:27:33 +04:00
nsRefPtr < nsXBLWindowKeyHandler > handler =
NS_NewXBLWindowKeyHandler ( elt , piTarget ) ;
2000-09-22 09:02:20 +04:00
2000-11-29 09:01:33 +03:00
// listen to these events
2011-06-24 06:18:02 +04:00
manager - > AddEventListenerByType ( handler , NS_LITERAL_STRING ( " keydown " ) ,
2014-03-17 10:56:52 +04:00
TrustedEventsAtSystemGroupBubble ( ) ) ;
2011-06-24 06:18:02 +04:00
manager - > AddEventListenerByType ( handler , NS_LITERAL_STRING ( " keyup " ) ,
2014-03-17 10:56:52 +04:00
TrustedEventsAtSystemGroupBubble ( ) ) ;
2011-06-24 06:18:02 +04:00
manager - > AddEventListenerByType ( handler , NS_LITERAL_STRING ( " keypress " ) ,
2014-03-17 10:56:52 +04:00
TrustedEventsAtSystemGroupBubble ( ) ) ;
2000-09-22 09:02:20 +04:00
2014-03-18 19:16:47 +04:00
// The capturing listener is only used for XUL keysets to properly handle
// shortcut keys in a multi-process environment.
manager - > AddEventListenerByType ( handler , NS_LITERAL_STRING ( " keydown " ) ,
TrustedEventsAtSystemGroupCapture ( ) ) ;
manager - > AddEventListenerByType ( handler , NS_LITERAL_STRING ( " keyup " ) ,
TrustedEventsAtSystemGroupCapture ( ) ) ;
manager - > AddEventListenerByType ( handler , NS_LITERAL_STRING ( " keypress " ) ,
TrustedEventsAtSystemGroupCapture ( ) ) ;
2008-08-06 18:32:09 +04:00
if ( contentNode )
2014-03-15 23:00:15 +04:00
return contentNode - > SetProperty ( nsGkAtoms : : listener ,
handler . forget ( ) . take ( ) ,
2011-10-17 18:59:28 +04:00
nsPropertyTable : : SupportsDtorFunc , true ) ;
2008-08-06 18:32:09 +04:00
2013-04-14 22:27:33 +04:00
// The reference to the handler will be maintained by the event target,
2008-08-06 18:32:09 +04:00
// and, if there is a content node, the property.
return NS_OK ;
}
//
// DetachGlobalKeyHandler
//
// Removes a key handler added by DeatchGlobalKeyHandler.
//
2012-05-23 22:46:04 +04:00
nsresult
2013-04-06 04:44:26 +04:00
nsXBLService : : DetachGlobalKeyHandler ( EventTarget * aTarget )
2008-08-06 18:32:09 +04:00
{
2013-04-06 04:44:26 +04:00
nsCOMPtr < EventTarget > piTarget = aTarget ;
2008-08-06 18:32:09 +04:00
nsCOMPtr < nsIContent > contentNode ( do_QueryInterface ( aTarget ) ) ;
if ( ! contentNode ) // detaching is only supported for content nodes
return NS_ERROR_FAILURE ;
// Only attach if we're really in a document
nsCOMPtr < nsIDocument > doc = contentNode - > GetCurrentDoc ( ) ;
if ( doc )
piTarget = do_QueryInterface ( doc ) ;
2011-06-24 06:18:02 +04:00
2014-03-17 10:56:53 +04:00
EventListenerManager * manager = piTarget - > GetOrCreateListenerManager ( ) ;
2013-04-06 04:44:26 +04:00
2011-06-24 06:18:02 +04:00
if ( ! piTarget | | ! manager )
2008-08-06 18:32:09 +04:00
return NS_ERROR_FAILURE ;
nsIDOMEventListener * handler =
static_cast < nsIDOMEventListener * > ( contentNode - > GetProperty ( nsGkAtoms : : listener ) ) ;
if ( ! handler )
return NS_ERROR_FAILURE ;
2011-06-24 06:18:02 +04:00
manager - > RemoveEventListenerByType ( handler , NS_LITERAL_STRING ( " keydown " ) ,
2014-03-17 10:56:52 +04:00
TrustedEventsAtSystemGroupBubble ( ) ) ;
2011-06-24 06:18:02 +04:00
manager - > RemoveEventListenerByType ( handler , NS_LITERAL_STRING ( " keyup " ) ,
2014-03-17 10:56:52 +04:00
TrustedEventsAtSystemGroupBubble ( ) ) ;
2011-06-24 06:18:02 +04:00
manager - > RemoveEventListenerByType ( handler , NS_LITERAL_STRING ( " keypress " ) ,
2014-03-17 10:56:52 +04:00
TrustedEventsAtSystemGroupBubble ( ) ) ;
2008-08-06 18:32:09 +04:00
2014-03-18 19:16:47 +04:00
manager - > RemoveEventListenerByType ( handler , NS_LITERAL_STRING ( " keydown " ) ,
TrustedEventsAtSystemGroupCapture ( ) ) ;
manager - > RemoveEventListenerByType ( handler , NS_LITERAL_STRING ( " keyup " ) ,
TrustedEventsAtSystemGroupCapture ( ) ) ;
manager - > RemoveEventListenerByType ( handler , NS_LITERAL_STRING ( " keypress " ) ,
TrustedEventsAtSystemGroupCapture ( ) ) ;
2008-08-06 18:32:09 +04:00
contentNode - > DeleteProperty ( nsGkAtoms : : listener ) ;
2000-09-22 09:02:20 +04:00
return NS_OK ;
}
2000-01-12 12:57:45 +03:00
// Internal helper methods ////////////////////////////////////////////////////////////////
2012-05-23 22:46:04 +04:00
nsresult
nsXBLService : : BindingReady ( nsIContent * aBoundElement ,
2014-03-19 01:25:39 +04:00
nsIURI * aURI ,
2012-05-23 22:46:04 +04:00
bool * aIsReady )
2000-08-14 08:04:18 +04:00
{
2007-07-19 01:56:57 +04:00
// Don't do a security check here; we know this binding is set to go.
2012-07-30 18:20:58 +04:00
return GetBinding ( aBoundElement , aURI , true , nullptr , aIsReady , nullptr ) ;
2000-08-14 08:04:18 +04:00
}
2005-02-26 01:07:01 +03:00
nsresult
2014-03-19 01:25:39 +04:00
nsXBLService : : GetBinding ( nsIContent * aBoundElement , nsIURI * aURI ,
2011-09-29 10:19:26 +04:00
bool aPeekOnly , nsIPrincipal * aOriginPrincipal ,
bool * aIsReady , nsXBLBinding * * aResult )
2006-11-09 04:58:12 +03:00
{
// More than 6 binding URIs are rare, see bug 55070 comment 18.
2007-12-13 07:17:14 +03:00
nsAutoTArray < nsIURI * , 6 > uris ;
2007-07-19 01:56:57 +04:00
return GetBinding ( aBoundElement , aURI , aPeekOnly , aOriginPrincipal , aIsReady ,
aResult , uris ) ;
2006-11-09 04:58:12 +03:00
}
2014-08-12 07:06:55 +04:00
static bool
MayBindToContent ( nsXBLPrototypeBinding * aProtoBinding , nsIContent * aBoundElement ,
nsIURI * aURI )
{
// If this binding explicitly allows untrusted content, we're done.
if ( aProtoBinding - > BindToUntrustedContent ( ) ) {
return true ;
}
// We let XUL content and content in XUL documents through, since XUL is
// restricted anyway and we want to minimize remote XUL breakage.
if ( aBoundElement - > IsXUL ( ) | | aBoundElement - > OwnerDoc ( ) - > IsXUL ( ) ) {
return true ;
}
// Similarly, we make an exception for anonymous content (which
// lives in the XBL scope), because it's already protected from content,
// and tends to use a lot of bindings that we wouldn't otherwise need to
// whitelist.
if ( aBoundElement - > IsInAnonymousSubtree ( ) ) {
return true ;
}
// Allow if the bound content subsumes the binding.
nsCOMPtr < nsIDocument > bindingDoc = aProtoBinding - > XBLDocumentInfo ( ) - > GetDocument ( ) ;
NS_ENSURE_TRUE ( bindingDoc , false ) ;
if ( aBoundElement - > NodePrincipal ( ) - > Subsumes ( bindingDoc - > NodePrincipal ( ) ) ) {
return true ;
}
// One last special case: we need to watch out for in-document data: URI
// bindings from remote-XUL-whitelisted domains (especially tests), because
// they end up with a null principal (rather than inheriting the document's
// principal), which causes them to fail the check above.
if ( nsContentUtils : : AllowXULXBLForPrincipal ( aBoundElement - > NodePrincipal ( ) ) ) {
bool isDataURI = false ;
nsresult rv = aURI - > SchemeIs ( " data " , & isDataURI ) ;
NS_ENSURE_SUCCESS ( rv , false ) ;
if ( isDataURI ) {
return true ;
}
}
// Disallow.
return false ;
}
2006-11-09 04:58:12 +03:00
nsresult
2014-03-19 01:25:39 +04:00
nsXBLService : : GetBinding ( nsIContent * aBoundElement , nsIURI * aURI ,
2011-09-29 10:19:26 +04:00
bool aPeekOnly , nsIPrincipal * aOriginPrincipal ,
bool * aIsReady , nsXBLBinding * * aResult ,
2006-11-09 04:58:12 +03:00
nsTArray < nsIURI * > & aDontExtendURIs )
2000-08-14 08:04:18 +04:00
{
2006-04-15 05:52:32 +04:00
NS_ASSERTION ( aPeekOnly | | aResult ,
" Must have non-null out param if not just peeking to see "
" whether the binding is ready " ) ;
2014-03-19 01:25:39 +04:00
2000-08-14 08:04:18 +04:00
if ( aResult )
2012-07-30 18:20:58 +04:00
* aResult = nullptr ;
2000-01-13 05:23:54 +03:00
2003-11-18 00:03:32 +03:00
if ( ! aURI )
2000-01-13 05:23:54 +03:00
return NS_ERROR_FAILURE ;
2012-09-02 06:35:17 +04:00
nsAutoCString ref ;
2011-05-22 05:12:46 +04:00
aURI - > GetRef ( ref ) ;
2001-12-14 08:04:05 +03:00
2011-10-18 14:53:36 +04:00
nsCOMPtr < nsIDocument > boundDocument = aBoundElement - > OwnerDoc ( ) ;
2003-04-18 12:44:25 +04:00
2010-07-15 05:53:11 +04:00
nsRefPtr < nsXBLDocumentInfo > docInfo ;
2007-07-19 01:56:57 +04:00
nsresult rv = LoadBindingDocumentInfo ( aBoundElement , boundDocument , aURI ,
aOriginPrincipal ,
2011-10-17 18:59:28 +04:00
false , getter_AddRefs ( docInfo ) ) ;
2007-07-19 01:56:57 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2014-03-19 01:25:39 +04:00
2000-08-12 10:28:02 +04:00
if ( ! docInfo )
2000-01-13 05:23:54 +03:00
return NS_ERROR_FAILURE ;
2010-07-15 05:55:54 +04:00
nsXBLPrototypeBinding * protoBinding = docInfo - > GetPrototypeBinding ( ref ) ;
2000-09-28 00:23:49 +04:00
2012-05-10 02:57:44 +04:00
if ( ! protoBinding ) {
# ifdef DEBUG
2012-09-02 06:35:17 +04:00
nsAutoCString uriSpec ;
2012-05-10 02:57:44 +04:00
aURI - > GetSpec ( uriSpec ) ;
2012-09-02 06:35:17 +04:00
nsAutoCString doc ;
2012-05-10 02:57:44 +04:00
boundDocument - > GetDocumentURI ( ) - > GetSpec ( doc ) ;
2012-09-02 06:35:17 +04:00
nsAutoCString message ( " Unable to locate an XBL binding for URI " ) ;
2012-05-10 02:57:44 +04:00
message + = uriSpec ;
message + = " in document " ;
message + = doc ;
NS_WARNING ( message . get ( ) ) ;
# endif
2000-11-04 14:03:14 +03:00
return NS_ERROR_FAILURE ;
2012-05-10 02:57:44 +04:00
}
2000-10-17 01:46:59 +04:00
2014-08-12 07:06:55 +04:00
// If the binding isn't whitelisted, refuse to apply it to content that
// doesn't subsume it (modulo a few exceptions).
if ( ! MayBindToContent ( protoBinding , aBoundElement , aURI ) ) {
# ifdef DEBUG
nsAutoCString uriSpec ;
aURI - > GetSpec ( uriSpec ) ;
nsAutoCString message ( " Permission denied to apply binding " ) ;
message + = uriSpec ;
message + = " to unprivileged content. Set bindToUntrustedContent=true on "
" the binding to override this restriction. " ;
NS_WARNING ( message . get ( ) ) ;
# endif
return NS_ERROR_FAILURE ;
}
2009-11-04 00:45:10 +03:00
NS_ENSURE_TRUE ( aDontExtendURIs . AppendElement ( protoBinding - > BindingURI ( ) ) ,
NS_ERROR_OUT_OF_MEMORY ) ;
nsCOMPtr < nsIURI > altBindingURI = protoBinding - > AlternateBindingURI ( ) ;
if ( altBindingURI ) {
NS_ENSURE_TRUE ( aDontExtendURIs . AppendElement ( altBindingURI ) ,
NS_ERROR_OUT_OF_MEMORY ) ;
}
2001-03-10 04:43:09 +03:00
// Our prototype binding must have all its resources loaded.
2011-09-29 10:19:26 +04:00
bool ready = protoBinding - > LoadResources ( ) ;
2001-03-10 04:43:09 +03:00
if ( ! ready ) {
// Add our bound element to the protos list of elts that should
// be notified when the stylesheets and scripts finish loading.
protoBinding - > AddResourceListener ( aBoundElement ) ;
return NS_ERROR_FAILURE ; // The binding isn't ready yet.
}
2011-11-04 00:39:07 +04:00
rv = protoBinding - > ResolveBaseBinding ( ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
nsIURI * baseBindingURI ;
2003-03-07 02:59:18 +03:00
nsXBLPrototypeBinding * baseProto = protoBinding - > GetBasePrototype ( ) ;
2000-09-28 00:23:49 +04:00
if ( baseProto ) {
2011-11-04 00:39:07 +04:00
baseBindingURI = baseProto - > BindingURI ( ) ;
2000-09-28 00:23:49 +04:00
}
2011-11-04 00:39:07 +04:00
else {
baseBindingURI = protoBinding - > GetBaseBindingURI ( ) ;
if ( baseBindingURI ) {
2012-08-22 19:56:38 +04:00
uint32_t count = aDontExtendURIs . Length ( ) ;
for ( uint32_t index = 0 ; index < count ; + + index ) {
2011-11-04 00:39:07 +04:00
bool equal ;
rv = aDontExtendURIs [ index ] - > Equals ( baseBindingURI , & equal ) ;
2003-11-18 00:03:32 +03:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2011-11-04 00:39:07 +04:00
if ( equal ) {
2012-09-02 06:35:17 +04:00
nsAutoCString spec , basespec ;
2011-11-04 00:39:07 +04:00
protoBinding - > BindingURI ( ) - > GetSpec ( spec ) ;
NS_ConvertUTF8toUTF16 protoSpec ( spec ) ;
baseBindingURI - > GetSpec ( basespec ) ;
NS_ConvertUTF8toUTF16 baseSpecUTF16 ( basespec ) ;
2014-01-04 19:02:17 +04:00
const char16_t * params [ ] = { protoSpec . get ( ) , baseSpecUTF16 . get ( ) } ;
2011-12-15 18:47:03 +04:00
nsContentUtils : : ReportToConsole ( nsIScriptError : : warningFlag ,
2013-08-21 23:28:26 +04:00
NS_LITERAL_CSTRING ( " XBL " ) , nullptr ,
2011-12-15 18:47:03 +04:00
nsContentUtils : : eXBL_PROPERTIES ,
2011-11-04 00:39:07 +04:00
" CircularExtendsBinding " ,
2011-12-15 18:47:03 +04:00
params , ArrayLength ( params ) ,
boundDocument - > GetDocumentURI ( ) ) ;
2011-11-04 00:39:07 +04:00
return NS_ERROR_ILLEGAL_VALUE ;
2000-12-07 13:11:21 +03:00
}
}
2000-01-13 05:23:54 +03:00
}
}
2011-11-04 00:39:07 +04:00
nsRefPtr < nsXBLBinding > baseBinding ;
if ( baseBindingURI ) {
2013-07-19 08:13:35 +04:00
nsIContent * child = protoBinding - > GetBindingElement ( ) ;
2011-11-04 00:39:07 +04:00
rv = GetBinding ( aBoundElement , baseBindingURI , aPeekOnly ,
child - > NodePrincipal ( ) , aIsReady ,
getter_AddRefs ( baseBinding ) , aDontExtendURIs ) ;
if ( NS_FAILED ( rv ) )
return rv ; // We aren't ready yet.
}
2011-10-17 18:59:28 +04:00
* aIsReady = true ;
2011-11-04 00:39:07 +04:00
2000-09-28 00:23:49 +04:00
if ( ! aPeekOnly ) {
// Make a new binding
2005-02-26 01:07:01 +03:00
nsXBLBinding * newBinding = new nsXBLBinding ( protoBinding ) ;
NS_ENSURE_TRUE ( newBinding , NS_ERROR_OUT_OF_MEMORY ) ;
2011-11-04 00:39:07 +04:00
if ( baseBinding ) {
if ( ! baseProto ) {
protoBinding - > SetBasePrototype ( baseBinding - > PrototypeBinding ( ) ) ;
}
newBinding - > SetBaseBinding ( baseBinding ) ;
}
2005-02-26 01:07:01 +03:00
NS_ADDREF ( * aResult = newBinding ) ;
2000-09-28 00:23:49 +04:00
}
2000-01-13 05:23:54 +03:00
return NS_OK ;
}
2011-09-29 10:19:26 +04:00
static bool SchemeIs ( nsIURI * aURI , const char * aScheme )
2009-03-10 11:35:00 +03:00
{
nsCOMPtr < nsIURI > baseURI = NS_GetInnermostURI ( aURI ) ;
2011-10-17 18:59:28 +04:00
NS_ENSURE_TRUE ( baseURI , false ) ;
2009-03-10 11:35:00 +03:00
2011-09-29 10:19:26 +04:00
bool isScheme = false ;
2009-03-10 11:35:00 +03:00
return NS_SUCCEEDED ( baseURI - > SchemeIs ( aScheme , & isScheme ) ) & & isScheme ;
}
2011-09-29 10:19:26 +04:00
static bool
2010-08-20 03:12:46 +04:00
IsSystemOrChromeURLPrincipal ( nsIPrincipal * aPrincipal )
{
if ( nsContentUtils : : IsSystemPrincipal ( aPrincipal ) ) {
2011-10-17 18:59:28 +04:00
return true ;
2010-08-20 03:12:46 +04:00
}
2014-03-19 01:25:39 +04:00
2010-08-20 03:12:46 +04:00
nsCOMPtr < nsIURI > uri ;
aPrincipal - > GetURI ( getter_AddRefs ( uri ) ) ;
2011-10-17 18:59:28 +04:00
NS_ENSURE_TRUE ( uri , false ) ;
2014-03-19 01:25:39 +04:00
2011-09-29 10:19:26 +04:00
bool isChrome = false ;
2010-08-20 03:12:46 +04:00
return NS_SUCCEEDED ( uri - > SchemeIs ( " chrome " , & isChrome ) ) & & isChrome ;
}
2012-05-23 22:46:04 +04:00
nsresult
2003-11-18 00:03:32 +03:00
nsXBLService : : LoadBindingDocumentInfo ( nsIContent * aBoundElement ,
nsIDocument * aBoundDocument ,
nsIURI * aBindingURI ,
2007-07-19 01:56:57 +04:00
nsIPrincipal * aOriginPrincipal ,
2011-09-29 10:19:26 +04:00
bool aForceSyncLoad ,
2010-07-15 05:53:11 +04:00
nsXBLDocumentInfo * * aResult )
2000-01-13 05:23:54 +03:00
{
2003-11-18 00:03:32 +03:00
NS_PRECONDITION ( aBindingURI , " Must have a binding URI " ) ;
2007-07-19 01:56:57 +04:00
NS_PRECONDITION ( ! aOriginPrincipal | | aBoundDocument ,
" If we're doing a security check, we better have a document! " ) ;
2014-03-19 01:25:39 +04:00
2007-06-13 01:56:06 +04:00
nsresult rv ;
2007-07-19 01:56:57 +04:00
if ( aOriginPrincipal ) {
// Security check - Enforce same-origin policy, except to chrome.
2014-03-19 01:25:39 +04:00
// We have to be careful to not pass aContent as the context here.
2007-07-19 01:56:57 +04:00
// Otherwise, if there is a JS-implemented content policy, we will attempt
// to wrap the content node, which will try to load XBL bindings for it, if
// any. Since we're not done loading this binding yet, that will reenter
// this method and we'll end up creating a binding and then immediately
// clobbering it in our table. That makes things very confused, leading to
// misbehavior and crashes.
2007-06-13 01:56:06 +04:00
rv = nsContentUtils : :
2007-07-19 01:56:57 +04:00
CheckSecurityBeforeLoad ( aBindingURI , aOriginPrincipal ,
2007-06-13 01:56:06 +04:00
nsIScriptSecurityManager : : ALLOW_CHROME ,
2008-04-29 03:56:07 +04:00
gAllowDataURIs ,
2007-06-17 17:50:50 +04:00
nsIContentPolicy : : TYPE_XBL ,
2007-06-13 01:56:06 +04:00
aBoundDocument ) ;
2010-09-16 02:53:01 +04:00
NS_ENSURE_SUCCESS ( rv , NS_ERROR_XBL_BLOCKED ) ;
2009-03-10 09:15:06 +03:00
2010-08-20 03:12:46 +04:00
if ( ! IsSystemOrChromeURLPrincipal ( aOriginPrincipal ) ) {
// Also make sure that we're same-origin with the bound document
// except if the stylesheet has the system principal.
if ( ! ( gAllowDataURIs & & SchemeIs ( aBindingURI , " data " ) ) & &
! SchemeIs ( aBindingURI , " chrome " ) ) {
rv = aBoundDocument - > NodePrincipal ( ) - > CheckMayLoad ( aBindingURI ,
2012-08-20 22:34:33 +04:00
true , false ) ;
2010-09-16 02:53:01 +04:00
NS_ENSURE_SUCCESS ( rv , NS_ERROR_XBL_BLOCKED ) ;
2010-08-20 03:12:46 +04:00
}
2009-03-10 09:15:06 +03:00
2010-08-20 03:12:46 +04:00
// Finally check if this document is allowed to use XBL at all.
NS_ENSURE_TRUE ( aBoundDocument - > AllowXULXBL ( ) ,
2010-09-16 02:53:01 +04:00
NS_ERROR_XBL_BLOCKED ) ;
2009-03-10 09:15:06 +03:00
}
2007-06-13 01:56:06 +04:00
}
2000-05-19 08:48:43 +04:00
2012-07-30 18:20:58 +04:00
* aResult = nullptr ;
2010-07-15 05:53:11 +04:00
nsRefPtr < nsXBLDocumentInfo > info ;
2000-12-02 13:34:52 +03:00
2007-02-24 19:27:51 +03:00
nsCOMPtr < nsIURI > documentURI ;
2011-05-22 05:12:46 +04:00
rv = aBindingURI - > CloneIgnoringRef ( getter_AddRefs ( documentURI ) ) ;
2003-11-18 00:03:32 +03:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2003-04-11 04:56:27 +04:00
# ifdef MOZ_XUL
2000-08-06 02:33:29 +04:00
// We've got a file. Check our XBL document cache.
2007-03-12 08:53:33 +03:00
nsXULPrototypeCache * cache = nsXULPrototypeCache : : GetInstance ( ) ;
2014-03-19 01:25:39 +04:00
bool useXULCache = cache & & cache - > IsEnabled ( ) ;
2001-02-22 06:01:34 +03:00
if ( useXULCache ) {
2014-03-19 01:25:39 +04:00
// The first line of defense is the chrome cache.
2000-08-06 02:33:29 +04:00
// This cache crosses the entire product, so that any XBL bindings that are
// part of chrome will be reused across all XUL documents.
2014-03-19 01:25:39 +04:00
info = cache - > GetXBLDocumentInfo ( documentURI ) ;
2000-08-06 02:33:29 +04:00
}
2003-04-11 04:56:27 +04:00
# endif
2000-08-06 02:33:29 +04:00
2000-08-12 10:28:02 +04:00
if ( ! info ) {
2000-08-06 02:33:29 +04:00
// The second line of defense is the binding manager's document table.
2012-07-30 18:20:58 +04:00
nsBindingManager * bindingManager = nullptr ;
2000-09-22 09:02:20 +04:00
if ( aBoundDocument ) {
2005-02-19 13:31:27 +03:00
bindingManager = aBoundDocument - > BindingManager ( ) ;
2007-02-27 03:14:01 +03:00
info = bindingManager - > GetXBLDocumentInfo ( documentURI ) ;
2013-08-02 13:26:21 +04:00
if ( aBoundDocument - > IsStaticDocument ( ) & &
IsChromeOrResourceURI ( aBindingURI ) ) {
aForceSyncLoad = true ;
}
2000-09-22 09:02:20 +04:00
}
2000-08-22 02:30:36 +04:00
2014-06-20 06:01:40 +04:00
NodeInfo * ni = nullptr ;
2000-08-17 12:11:11 +04:00
if ( aBoundElement )
2005-09-24 22:43:15 +04:00
ni = aBoundElement - > NodeInfo ( ) ;
2003-11-19 04:20:56 +03:00
2002-03-04 02:31:26 +03:00
if ( ! info & & bindingManager & &
2006-12-26 20:47:52 +03:00
( ! ni | | ! ( ni - > Equals ( nsGkAtoms : : scrollbar , kNameSpaceID_XUL ) | |
ni - > Equals ( nsGkAtoms : : thumb , kNameSpaceID_XUL ) | |
( ( ni - > Equals ( nsGkAtoms : : input ) | |
ni - > Equals ( nsGkAtoms : : select ) ) & &
2009-08-25 00:02:07 +04:00
aBoundElement - > IsHTML ( ) ) ) ) & & ! aForceSyncLoad ) {
2000-08-06 08:57:55 +04:00
// The third line of defense is to investigate whether or not the
// document is currently being loaded asynchronously. If so, there's no
// document yet, but we need to glom on our request so that it will be
// processed whenever the doc does finish loading.
2000-08-06 09:03:36 +04:00
nsCOMPtr < nsIStreamListener > listener ;
2000-09-22 09:02:20 +04:00
if ( bindingManager )
2007-02-27 03:14:01 +03:00
listener = bindingManager - > GetLoadingDocListener ( documentURI ) ;
2000-08-06 08:57:55 +04:00
if ( listener ) {
2007-02-27 03:14:01 +03:00
nsXBLStreamListener * xblListener =
2007-07-08 11:08:04 +04:00
static_cast < nsXBLStreamListener * > ( listener . get ( ) ) ;
2000-08-06 08:57:55 +04:00
// Create a new load observer.
2003-11-18 00:03:32 +03:00
if ( ! xblListener - > HasRequest ( aBindingURI , aBoundElement ) ) {
2013-03-05 16:37:47 +04:00
nsXBLBindingRequest * req = new nsXBLBindingRequest ( aBindingURI , aBoundElement ) ;
2000-08-14 08:04:18 +04:00
xblListener - > AddRequest ( req ) ;
}
2000-08-12 10:28:02 +04:00
return NS_OK ;
2000-08-06 02:33:29 +04:00
}
2000-08-06 08:57:55 +04:00
}
2011-11-04 00:39:08 +04:00
# ifdef MOZ_XUL
// Next, look in the startup cache
bool useStartupCache = useXULCache & & IsChromeOrResourceURI ( documentURI ) ;
if ( ! info & & useStartupCache ) {
rv = nsXBLDocumentInfo : : ReadPrototypeBindings ( documentURI , getter_AddRefs ( info ) ) ;
if ( NS_SUCCEEDED ( rv ) ) {
cache - > PutXBLDocumentInfo ( info ) ;
if ( bindingManager ) {
// Cache it in our binding manager's document table.
bindingManager - > PutXBLDocumentInfo ( info ) ;
}
}
}
# endif
2000-08-12 10:28:02 +04:00
if ( ! info ) {
2000-08-06 08:57:55 +04:00
// Finally, if all lines of defense fail, we go and fetch the binding
// document.
2014-03-19 01:25:39 +04:00
2003-04-18 12:44:25 +04:00
// Always load chrome synchronously
2011-09-29 10:19:26 +04:00
bool chrome ;
2003-11-18 00:03:32 +03:00
if ( NS_SUCCEEDED ( documentURI - > SchemeIs ( " chrome " , & chrome ) ) & & chrome )
2011-10-17 18:59:28 +04:00
aForceSyncLoad = true ;
2003-04-18 12:44:25 +04:00
2000-08-12 10:28:02 +04:00
nsCOMPtr < nsIDocument > document ;
2003-11-18 00:03:32 +03:00
FetchBindingDocument ( aBoundElement , aBoundDocument , documentURI ,
2014-09-21 20:38:38 +04:00
aBindingURI , aOriginPrincipal , aForceSyncLoad ,
getter_AddRefs ( document ) ) ;
2011-11-04 00:39:08 +04:00
2000-08-06 08:57:55 +04:00
if ( document ) {
2007-02-17 02:02:08 +03:00
nsBindingManager * xblDocBindingManager = document - > BindingManager ( ) ;
2007-02-27 03:14:01 +03:00
info = xblDocBindingManager - > GetXBLDocumentInfo ( documentURI ) ;
2001-11-11 04:15:22 +03:00
if ( ! info ) {
NS_ERROR ( " An XBL file is malformed. Did you forget the XBL namespace on the bindings tag? " ) ;
return NS_ERROR_FAILURE ;
}
2001-12-14 08:04:05 +03:00
xblDocBindingManager - > RemoveXBLDocumentInfo ( info ) ; // Break the self-imposed cycle.
2001-11-11 04:15:22 +03:00
2000-08-06 08:57:55 +04:00
// If the doc is a chrome URI, then we put it into the XUL cache.
2003-04-11 04:56:27 +04:00
# ifdef MOZ_XUL
2011-11-04 00:39:08 +04:00
if ( useStartupCache ) {
2007-03-12 08:53:33 +03:00
cache - > PutXBLDocumentInfo ( info ) ;
2011-11-04 00:39:08 +04:00
// now write the bindings into the startup cache
info - > WritePrototypeBindings ( ) ;
2000-08-06 08:57:55 +04:00
}
2003-04-11 04:56:27 +04:00
# endif
2014-03-19 01:25:39 +04:00
2003-06-21 03:33:43 +04:00
if ( bindingManager ) {
// Also put it in our binding manager's document table.
2000-08-12 10:28:02 +04:00
bindingManager - > PutXBLDocumentInfo ( info ) ;
2000-08-06 08:57:55 +04:00
}
2000-05-19 08:48:43 +04:00
}
2000-01-12 12:57:45 +03:00
}
}
2012-03-23 00:46:03 +04:00
info . forget ( aResult ) ;
2000-01-12 12:57:45 +03:00
return NS_OK ;
}
2003-03-04 04:04:27 +03:00
nsresult
2000-08-22 02:30:36 +04:00
nsXBLService : : FetchBindingDocument ( nsIContent * aBoundElement , nsIDocument * aBoundDocument ,
2014-03-19 01:25:39 +04:00
nsIURI * aDocumentURI , nsIURI * aBindingURI ,
2014-09-21 20:38:38 +04:00
nsIPrincipal * aOriginPrincipal , bool aForceSyncLoad ,
nsIDocument * * aResult )
2000-01-12 12:57:45 +03:00
{
2002-10-09 11:03:15 +04:00
nsresult rv = NS_OK ;
2012-07-30 18:20:58 +04:00
// Initialize our out pointer to nullptr
* aResult = nullptr ;
2000-01-12 13:20:11 +03:00
2009-01-14 01:53:04 +03:00
// Now we have to synchronously load the binding file.
2014-03-19 01:25:39 +04:00
// Create an XML content sink and a parser.
2000-08-12 10:28:02 +04:00
nsCOMPtr < nsILoadGroup > loadGroup ;
2000-09-22 09:02:20 +04:00
if ( aBoundDocument )
2003-10-22 10:09:48 +04:00
loadGroup = aBoundDocument - > GetDocumentLoadGroup ( ) ;
2000-01-12 13:20:11 +03:00
2006-04-04 06:41:04 +04:00
// We really shouldn't have to force a sync load for anything here... could
// we get away with not doing that? Not sure.
if ( IsChromeOrResourceURI ( aDocumentURI ) )
2011-10-17 18:59:28 +04:00
aForceSyncLoad = true ;
2000-12-02 13:34:52 +03:00
2006-06-16 00:30:44 +04:00
// Create document and contentsink and set them up.
nsCOMPtr < nsIDocument > doc ;
rv = NS_NewXMLDocument ( getter_AddRefs ( doc ) ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2002-10-09 11:03:15 +04:00
2006-06-16 00:30:44 +04:00
nsCOMPtr < nsIXMLContentSink > xblSink ;
2012-07-30 18:20:58 +04:00
rv = NS_NewXBLContentSink ( getter_AddRefs ( xblSink ) , doc , aDocumentURI , nullptr ) ;
2006-06-16 00:30:44 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2002-10-09 11:03:15 +04:00
2006-06-16 00:30:44 +04:00
// Open channel
2014-09-21 20:38:38 +04:00
// Note: There are some cases where aOriginPrincipal and aBoundDocument are purposely
// set to null (to bypass security checks) when calling LoadBindingDocumentInfo() which calls
// FetchBindingDocument(). LoadInfo will end up with no principal or node in those cases,
// so we use systemPrincipal. This achieves the same result of bypassing security checks,
// but it gives the wrong information to potential future consumers of loadInfo.
nsCOMPtr < nsIPrincipal > requestingPrincipal = aOriginPrincipal ? aOriginPrincipal
: nsContentUtils : : GetSystemPrincipal ( ) ;
2006-06-16 00:30:44 +04:00
nsCOMPtr < nsIChannel > channel ;
2014-09-21 20:38:38 +04:00
// Note that we are calling NS_NewChannelInternal here with both a node and a principal.
// This is because the principal and node could be different.
rv = NS_NewChannelInternal ( getter_AddRefs ( channel ) ,
aDocumentURI ,
aBoundDocument ,
requestingPrincipal ,
nsILoadInfo : : SEC_NORMAL ,
nsIContentPolicy : : TYPE_OTHER ,
loadGroup ) ;
2006-06-16 00:30:44 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2001-11-28 08:00:29 +03:00
2008-09-08 05:13:02 +04:00
nsCOMPtr < nsIInterfaceRequestor > sameOriginChecker = nsContentUtils : : GetSameOriginChecker ( ) ;
2007-06-13 01:56:06 +04:00
NS_ENSURE_TRUE ( sameOriginChecker , NS_ERROR_OUT_OF_MEMORY ) ;
channel - > SetNotificationCallbacks ( sameOriginChecker ) ;
2006-06-16 00:30:44 +04:00
if ( ! aForceSyncLoad ) {
2000-08-12 10:28:02 +04:00
// We can be asynchronous
2009-01-14 14:24:26 +03:00
nsXBLStreamListener * xblListener =
2012-05-23 22:46:04 +04:00
new nsXBLStreamListener ( aBoundDocument , xblSink , doc ) ;
2001-06-20 05:11:56 +04:00
NS_ENSURE_TRUE ( xblListener , NS_ERROR_OUT_OF_MEMORY ) ;
2000-08-06 08:57:55 +04:00
// Add ourselves to the list of loading docs.
2007-02-17 02:02:08 +03:00
nsBindingManager * bindingManager ;
2001-08-01 11:50:47 +04:00
if ( aBoundDocument )
2005-02-19 13:31:27 +03:00
bindingManager = aBoundDocument - > BindingManager ( ) ;
2003-10-22 10:09:48 +04:00
else
2012-07-30 18:20:58 +04:00
bindingManager = nullptr ;
2003-10-22 10:09:48 +04:00
2001-08-01 11:50:47 +04:00
if ( bindingManager )
2003-11-18 00:03:32 +03:00
bindingManager - > PutLoadingDocListener ( aDocumentURI , xblListener ) ;
2000-08-06 08:57:55 +04:00
// Add our request.
2013-03-05 16:37:47 +04:00
nsXBLBindingRequest * req = new nsXBLBindingRequest ( aBindingURI ,
aBoundElement ) ;
2000-08-06 08:57:55 +04:00
xblListener - > AddRequest ( req ) ;
// Now kick off the async read.
2012-07-30 18:20:58 +04:00
rv = channel - > AsyncOpen ( xblListener , nullptr ) ;
2008-12-12 22:46:59 +03:00
if ( NS_FAILED ( rv ) ) {
// Well, we won't be getting a load. Make sure to clean up our stuff!
if ( bindingManager ) {
bindingManager - > RemoveLoadingDocListener ( aDocumentURI ) ;
}
}
2000-08-04 12:45:29 +04:00
return NS_OK ;
}
2009-01-14 14:24:26 +03:00
nsCOMPtr < nsIStreamListener > listener ;
rv = doc - > StartDocumentLoad ( " loadAsInteractiveData " ,
channel ,
loadGroup ,
2012-07-30 18:20:58 +04:00
nullptr ,
2009-01-14 14:24:26 +03:00
getter_AddRefs ( listener ) ,
2011-10-17 18:59:28 +04:00
true ,
2009-01-14 14:24:26 +03:00
xblSink ) ;
NS_ENSURE_SUCCESS ( rv , rv ) ;
2000-01-12 13:20:11 +03:00
// Now do a blocking synchronous parse of the file.
2006-06-16 00:30:44 +04:00
nsCOMPtr < nsIInputStream > in ;
rv = channel - > Open ( getter_AddRefs ( in ) ) ;
2002-10-09 11:03:15 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2000-01-12 13:20:11 +03:00
2006-06-16 00:30:44 +04:00
rv = nsSyncLoadService : : PushSyncStreamToListener ( in , listener , channel ) ;
2002-10-09 11:03:15 +04:00
NS_ENSURE_SUCCESS ( rv , rv ) ;
2000-01-12 13:20:11 +03:00
2006-06-16 00:30:44 +04:00
doc . swap ( * aResult ) ;
2000-01-12 13:20:11 +03:00
2006-06-16 00:30:44 +04:00
return NS_OK ;
2000-01-12 12:32:29 +03:00
}