Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Public Attributes | Static Public Attributes | Protected Member Functions | Private Member Functions
nsXBLService Class Reference

#include <nsXBLService.h>

Inheritance diagram for nsXBLService:
Inheritance graph
[legend]
Collaboration diagram for nsXBLService:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsXBLService ()
virtual ~nsXBLService ()
void observe (in nsISupports aSubject, in string aTopic, in wstring aData)
 Observe will be called when there is a notification for the topic |aTopic|.

Public Attributes

nsFixedSizeAllocator mPool

Static Public Attributes

static PRUint32 gRefCnt = 0
static PRBool gDisableChromeCache = PR_FALSE
static nsHashtable * gClassTable = nsnull
static JSCList gClassLRUList = JS_INIT_STATIC_CLIST(&nsXBLService::gClassLRUList)
static PRUint32 gClassLRUListLength = 0
static PRUint32 gClassLRUListQuota = 64

Protected Member Functions

nsresult FlushStyleBindings (nsIContent *aContent)
nsresult FlushMemory ()
nsresult FetchBindingDocument (nsIContent *aBoundElement, nsIDocument *aBoundDocument, nsIURI *aDocumentURI, nsIURL *aBindingURL, PRBool aForceSyncLoad, nsIDocument **aResult)
nsresult GetXBLDocumentInfo (nsIURI *aURI, nsIContent *aBoundElement, nsIXBLDocumentInfo **aResult)
nsresult GetBinding (nsIContent *aBoundElement, nsIURI *aURI, PRBool aPeekFlag, PRBool *aIsReady, nsXBLBinding **aResult)

Private Member Functions

NS_DECL_ISUPPORTS NS_IMETHOD LoadBindings (nsIContent *aContent, nsIURI *aURL, PRBool aAugmentFlag, nsXBLBinding **aBinding, PRBool *aResolveStyle)
NS_IMETHOD BindingReady (nsIContent *aBoundElement, nsIURI *aURI, PRBool *aIsReady)
NS_IMETHOD ResolveTag (nsIContent *aContent, PRInt32 *aNameSpaceID, nsIAtom **aResult)
NS_IMETHOD LoadBindingDocumentInfo (nsIContent *aBoundElement, nsIDocument *aBoundDocument, nsIURI *aBindingURI, PRBool aForceSyncLoad, nsIXBLDocumentInfo **aResult)
NS_IMETHOD AttachGlobalKeyHandler (nsIDOMEventReceiver *aElement)
NS_IMETHOD AttachGlobalDragHandler (nsIDOMEventReceiver *aElement)

Detailed Description

Definition at line 62 of file nsXBLService.h.


Constructor & Destructor Documentation

Definition at line 469 of file nsXBLService.cpp.

{
  mPool.Init("XBL Binding Requests", kBucketSizes, kNumBuckets, kInitialSize);

  gRefCnt++;
  if (gRefCnt == 1) {
    gClassTable = new nsHashtable();

#ifdef MOZ_XUL
    // Find out if the XUL cache is on or off
    gDisableChromeCache = nsContentUtils::GetBoolPref(kDisableChromeCachePref,
                                                      gDisableChromeCache);

    CallGetService("@mozilla.org/xul/xul-prototype-cache;1", &gXULCache);
#endif
  }
}

Here is the call graph for this function:

Definition at line 487 of file nsXBLService.cpp.

{
  gRefCnt--;
  if (gRefCnt == 0) {
    // Walk the LRU list removing and deleting the nsXBLJSClasses.
    FlushMemory();

    // Any straggling nsXBLJSClass instances held by unfinalized JS objects
    // created for bindings will be deleted when those objects are finalized
    // (and not put on gClassLRUList, because length >= quota).
    gClassLRUListLength = gClassLRUListQuota = 0;

    // At this point, the only hash table entries should be for referenced
    // XBL class structs held by unfinalized JS binding objects.
    delete gClassTable;
    gClassTable = nsnull;

#ifdef MOZ_XUL
    NS_IF_RELEASE(gXULCache);
#endif
  }
}

Here is the call graph for this function:


Member Function Documentation

Implements nsIXBLService.

Definition at line 783 of file nsXBLService.cpp.

{
  // Create the DnD handler
  nsXBLWindowDragHandler* handler;
  NS_NewXBLWindowDragHandler(aReceiver, &handler);
  if (!handler)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDOMEventGroup> systemGroup;
  aReceiver->GetSystemEventGroup(getter_AddRefs(systemGroup));
  nsCOMPtr<nsIDOM3EventTarget> target = do_QueryInterface(aReceiver);

  // listen to these events
  target->AddGroupedEventListener(NS_LITERAL_STRING("draggesture"), handler,
                                  PR_FALSE, systemGroup);
  target->AddGroupedEventListener(NS_LITERAL_STRING("dragenter"), handler,
                                  PR_FALSE, systemGroup);
  target->AddGroupedEventListener(NS_LITERAL_STRING("dragexit"), handler,
                                  PR_FALSE, systemGroup);
  target->AddGroupedEventListener(NS_LITERAL_STRING("dragover"), handler,
                                  PR_FALSE, systemGroup);
  target->AddGroupedEventListener(NS_LITERAL_STRING("dragdrop"), handler,
                                  PR_FALSE, systemGroup);

  // Release.  Do this so that only the event receiver holds onto the handler.
  NS_RELEASE(handler);

  return NS_OK;

} // AttachGlobalDragDropHandler

Here is the call graph for this function:

Implements nsIXBLService.

Definition at line 733 of file nsXBLService.cpp.

{
  // check if the receiver is a content node (not a document), and hook
  // it to the document if that is the case.
  nsCOMPtr<nsIDOMEventReceiver> rec = aReceiver;
  nsCOMPtr<nsIContent> contentNode(do_QueryInterface(aReceiver));
  if (contentNode) {
    // Only attach if we're really in a document
    nsCOMPtr<nsIDocument> doc = contentNode->GetCurrentDoc();
    if (doc)
      rec = do_QueryInterface(doc); // We're a XUL keyset. Attach to our document.
  }
    
  if (!rec)
    return NS_ERROR_FAILURE;
    
  nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(contentNode));

  // Create the key handler
  nsXBLWindowKeyHandler* handler;
  NS_NewXBLWindowKeyHandler(elt, rec, &handler); // This addRef's
  if (!handler)
    return NS_ERROR_FAILURE;

  // listen to these events
  nsCOMPtr<nsIDOMEventGroup> systemGroup;
  rec->GetSystemEventGroup(getter_AddRefs(systemGroup));
  nsCOMPtr<nsIDOM3EventTarget> target = do_QueryInterface(rec);

  target->AddGroupedEventListener(NS_LITERAL_STRING("keydown"), handler,
                                  PR_FALSE, systemGroup);
  target->AddGroupedEventListener(NS_LITERAL_STRING("keyup"), handler, 
                                  PR_FALSE, systemGroup);
  target->AddGroupedEventListener(NS_LITERAL_STRING("keypress"), handler, 
                                  PR_FALSE, systemGroup);

  // Release.  Do this so that only the event receiver holds onto the key handler.
  NS_RELEASE(handler);

  return NS_OK;
}

Here is the call graph for this function:

NS_IMETHODIMP nsXBLService::BindingReady ( nsIContent aBoundElement,
nsIURI aURI,
PRBool aIsReady 
) [private, virtual]

Implements nsIXBLService.

Definition at line 840 of file nsXBLService.cpp.

{
  return GetBinding(aBoundElement, aURI, PR_TRUE, aIsReady, nsnull);
}

Here is the call graph for this function:

nsresult nsXBLService::FetchBindingDocument ( nsIContent aBoundElement,
nsIDocument aBoundDocument,
nsIURI aDocumentURI,
nsIURL aBindingURL,
PRBool  aForceSyncLoad,
nsIDocument **  aResult 
) [protected]

Definition at line 1142 of file nsXBLService.cpp.

{
  nsresult rv = NS_OK;
  // Initialize our out pointer to nsnull
  *aResult = nsnull;

  // Now we have to synchronously load the binding file.
  // Create an XML content sink and a parser. 
  nsCOMPtr<nsILoadGroup> loadGroup;
  if (aBoundDocument)
    loadGroup = aBoundDocument->GetDocumentLoadGroup();

  // 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))
    aForceSyncLoad = PR_TRUE;

  if(!aForceSyncLoad) {
    // Create the XML document
    nsCOMPtr<nsIDocument> doc = do_CreateInstance(kXMLDocumentCID, &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIChannel> channel;
    rv = NS_NewChannel(getter_AddRefs(channel), aDocumentURI, nsnull, loadGroup);
    if (NS_FAILED(rv)) return rv;

    nsCOMPtr<nsIStreamListener> listener;
    nsCOMPtr<nsIXMLContentSink> xblSink;
    NS_NewXBLContentSink(getter_AddRefs(xblSink), doc, aDocumentURI, nsnull);
    if (!xblSink)
      return NS_ERROR_FAILURE;

    if (NS_FAILED(rv = doc->StartDocumentLoad("loadAsInteractiveData", 
                                              channel, 
                                              loadGroup, 
                                              nsnull, 
                                              getter_AddRefs(listener),
                                              PR_TRUE,
                                              xblSink))) {
      NS_ERROR("Failure to init XBL doc prior to load.");
      return rv;
    }

    // We can be asynchronous
    nsXBLStreamListener* xblListener = new nsXBLStreamListener(this, listener, aBoundDocument, doc);
    NS_ENSURE_TRUE(xblListener,NS_ERROR_OUT_OF_MEMORY);

    nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(doc));
    rec->AddEventListener(NS_LITERAL_STRING("load"), (nsIDOMLoadListener*)xblListener, PR_FALSE);

    // Add ourselves to the list of loading docs.
    nsIBindingManager *bindingManager;
    if (aBoundDocument)
      bindingManager = aBoundDocument->BindingManager();
    else
      bindingManager = nsnull;

    if (bindingManager)
      bindingManager->PutLoadingDocListener(aDocumentURI, xblListener);

    // Add our request.
    nsXBLBindingRequest* req = nsXBLBindingRequest::Create(mPool,
                                                           aBindingURL,
                                                           aBoundElement);
    xblListener->AddRequest(req);

    // Now kick off the async read.
    channel->AsyncOpen(xblListener, nsnull);
    return NS_OK;
  }

  // Now do a blocking synchronous parse of the file.

  nsCOMPtr<nsIDOMDocument> domDoc;
  nsCOMPtr<nsISyncLoadDOMService> loader =
    do_GetService("@mozilla.org/content/syncload-dom-service;1", &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // Open channel
  nsCOMPtr<nsIChannel> channel;
  rv = NS_NewChannel(getter_AddRefs(channel), aDocumentURI, nsnull, loadGroup);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = loader->LoadLocalXBLDocument(channel, getter_AddRefs(domDoc));
  if (rv == NS_ERROR_FILE_NOT_FOUND) {
      return NS_OK;
  }
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
  // Clear script handling object on synchronously loaded XBL documents.
  NS_STATIC_CAST(nsDocument*, NS_STATIC_CAST(nsIDocument*, doc.get()))->
    ClearScriptHandlingObject();

  return CallQueryInterface(domDoc, aResult);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 825 of file nsXBLService.cpp.

Here is the caller graph for this function:

Definition at line 655 of file nsXBLService.cpp.

{
  nsCOMPtr<nsIDocument> document = aContent->GetOwnerDoc();

  // XXX doc will be null if we're in the midst of paint suppression.
  if (! document)
    return NS_OK;

  nsIBindingManager *bindingManager = document->BindingManager();
  
  nsXBLBinding *binding = bindingManager->GetBinding(aContent);
  
  if (binding) {
    nsXBLBinding *styleBinding = binding->GetFirstStyleBinding();

    if (styleBinding) {
      // Clear out the script references.
      styleBinding->UnhookEventHandlers();
      styleBinding->ChangeDocument(document, nsnull);
    }

    if (styleBinding == binding) 
      bindingManager->SetBinding(aContent, nsnull); // Flush old style bindings
  }
   
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsXBLService::GetBinding ( nsIContent aBoundElement,
nsIURI aURI,
PRBool  aPeekFlag,
PRBool aIsReady,
nsXBLBinding **  aResult 
) [protected]

Definition at line 848 of file nsXBLService.cpp.

{
  if (aResult)
    *aResult = nsnull;

  if (!aURI)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIURL> url(do_QueryInterface(aURI));
  if (!url) {
#ifdef DEBUG
    NS_ERROR("Binding load from a non-URL URI not allowed.");
    nsCAutoString spec;
    aURI->GetSpec(spec);
    fprintf(stderr, "Spec of non-URL URI is: '%s'\n", spec.get());
#endif
    return NS_ERROR_FAILURE;
  }

  nsCAutoString ref;
  url->GetRef(ref);
  NS_ASSERTION(!ref.IsEmpty(), "Incorrect syntax for an XBL binding");
  if (ref.IsEmpty())
    return NS_ERROR_FAILURE;
  
  nsCOMPtr<nsIDocument> boundDocument = aBoundElement->GetOwnerDoc();

  nsCOMPtr<nsIXBLDocumentInfo> docInfo;
  LoadBindingDocumentInfo(aBoundElement, boundDocument, aURI, PR_FALSE,
                          getter_AddRefs(docInfo));
  if (!docInfo)
    return NS_ERROR_FAILURE;

  // Get our doc info and determine our script access.
  nsCOMPtr<nsIDocument> doc;
  docInfo->GetDocument(getter_AddRefs(doc));
  PRBool allowScripts;
  docInfo->GetScriptAccess(&allowScripts);

  nsXBLPrototypeBinding* protoBinding;
  docInfo->GetPrototypeBinding(ref, &protoBinding);

  NS_ASSERTION(protoBinding, "Unable to locate an XBL binding.");
  if (!protoBinding)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIContent> child = protoBinding->GetBindingElement();

  // Our prototype binding must have all its resources loaded.
  PRBool ready = protoBinding->LoadResources();
  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.
  }

  // If our prototype already has a base, then don't check for an "extends" attribute.
  nsRefPtr<nsXBLBinding> baseBinding;
  PRBool hasBase = protoBinding->HasBasePrototype();
  nsXBLPrototypeBinding* baseProto = protoBinding->GetBasePrototype();
  if (baseProto) {
    if (NS_FAILED(GetBinding(aBoundElement, baseProto->BindingURI(),
                             aPeekOnly, aIsReady, getter_AddRefs(baseBinding))))
      return NS_ERROR_FAILURE; // We aren't ready yet.
  }
  else if (hasBase) {
    // Check for the presence of 'extends' and 'display' attributes
    nsAutoString display, extends;
    child->GetAttr(kNameSpaceID_None, nsXBLAtoms::display, display);
    child->GetAttr(kNameSpaceID_None, nsXBLAtoms::extends, extends);
    PRBool hasDisplay = !display.IsEmpty();
    PRBool hasExtends = !extends.IsEmpty();
    
    nsAutoString value(extends);
         
    if (!hasExtends) 
      protoBinding->SetHasBasePrototype(PR_FALSE);
    else {
      // Now slice 'em up to see what we've got.
      nsAutoString prefix;
      PRInt32 offset;
      if (hasDisplay) {
        offset = display.FindChar(':');
        if (-1 != offset) {
          display.Left(prefix, offset);
          display.Cut(0, offset+1);
        }
      }
      else if (hasExtends) {
        offset = extends.FindChar(':');
        if (-1 != offset) {
          extends.Left(prefix, offset);
          extends.Cut(0, offset+1);
          display = extends;
        }
      }

      nsAutoString nameSpace;

      if (!prefix.IsEmpty()) {
        nsCOMPtr<nsIAtom> prefixAtom = do_GetAtom(prefix);

        nsCOMPtr<nsIDOM3Node> node(do_QueryInterface(child));

        if (node) {
          node->LookupNamespaceURI(prefix, nameSpace);

          if (!nameSpace.IsEmpty()) {
            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;

            nsContentUtils::GetNSManagerWeakRef()->GetNameSpaceID(nameSpace,
                                                                  &nameSpaceID);

            nsCOMPtr<nsIAtom> tagName = do_GetAtom(display);
            protoBinding->SetBaseTag(nameSpaceID, tagName);
          }
        }
      }

      if (hasExtends && (hasDisplay || nameSpace.IsEmpty())) {
        // Look up the prefix.
        // We have a base class binding. Load it right now.
        nsCOMPtr<nsIURI> bindingURI;
        nsresult rv =
          NS_NewURI(getter_AddRefs(bindingURI), value,
                    doc->GetDocumentCharacterSet().get(),
                    doc->GetBaseURI());
        NS_ENSURE_SUCCESS(rv, rv);
        
        if (NS_FAILED(GetBinding(aBoundElement, bindingURI, aPeekOnly,
                                 aIsReady, getter_AddRefs(baseBinding))))
          return NS_ERROR_FAILURE; // Binding not yet ready or an error occurred.
        if (!aPeekOnly) {
          // Make sure to set the base prototype.
          baseProto = baseBinding->PrototypeBinding();
          protoBinding->SetBasePrototype(baseProto);
          child->UnsetAttr(kNameSpaceID_None, nsXBLAtoms::extends, PR_FALSE);
          child->UnsetAttr(kNameSpaceID_None, nsXBLAtoms::display, PR_FALSE);
        }
      }
    }
  }

  *aIsReady = PR_TRUE;
  if (!aPeekOnly) {
    // Make a new binding
    nsXBLBinding *newBinding = new nsXBLBinding(protoBinding);
    NS_ENSURE_TRUE(newBinding, NS_ERROR_OUT_OF_MEMORY);

    if (baseBinding)
      newBinding->SetBaseBinding(baseBinding);

    NS_ADDREF(*aResult = newBinding);
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsXBLService::GetXBLDocumentInfo ( nsIURI aURI,
nsIContent aBoundElement,
nsIXBLDocumentInfo **  aResult 
) [protected]

Definition at line 700 of file nsXBLService.cpp.

{
  *aResult = nsnull;

#ifdef MOZ_XUL
  PRBool useXULCache;
  gXULCache->GetEnabled(&useXULCache);
  if (useXULCache) {
    // The first line of defense is the chrome cache.  
    // This cache crosses the entire product, so any XBL bindings that are
    // part of chrome will be reused across all XUL documents.
    gXULCache->GetXBLDocumentInfo(aURI, aResult);
  }
#endif

  if (!*aResult) {
    // The second line of defense is the binding manager's document table.
    nsIDocument* boundDocument = aBoundElement->GetOwnerDoc();
    if (boundDocument)
      boundDocument->BindingManager()->GetXBLDocumentInfo(aURI, aResult);
  }
  return NS_OK;
}

Here is the call graph for this function:

NS_IMETHODIMP nsXBLService::LoadBindingDocumentInfo ( nsIContent aBoundElement,
nsIDocument aBoundDocument,
nsIURI aBindingURI,
PRBool  aForceSyncLoad,
nsIXBLDocumentInfo **  aResult 
) [private, virtual]

Implements nsIXBLService.

Definition at line 1017 of file nsXBLService.cpp.

{
  NS_PRECONDITION(aBindingURI, "Must have a binding URI");
  
  nsresult rv = NS_OK;

  *aResult = nsnull;
  nsCOMPtr<nsIXBLDocumentInfo> info;

  nsCOMPtr<nsIURI> uriClone;
  rv = aBindingURI->Clone(getter_AddRefs(uriClone));
  NS_ENSURE_SUCCESS(rv, rv);
  
  nsCOMPtr<nsIURL> documentURI(do_QueryInterface(uriClone, &rv));
  NS_ENSURE_TRUE(documentURI, rv);

  documentURI->SetRef(EmptyCString());

#ifdef MOZ_XUL
  // We've got a file.  Check our XBL document cache.
  PRBool useXULCache;
  gXULCache->GetEnabled(&useXULCache);

  if (useXULCache) {
    // The first line of defense is the chrome cache.  
    // This cache crosses the entire product, so that any XBL bindings that are
    // part of chrome will be reused across all XUL documents.
    gXULCache->GetXBLDocumentInfo(documentURI, getter_AddRefs(info));
  }
#endif

  if (!info) {
    // The second line of defense is the binding manager's document table.
    nsIBindingManager *bindingManager = nsnull;

    nsCOMPtr<nsIURL> bindingURL(do_QueryInterface(aBindingURI, &rv));
    NS_ENSURE_SUCCESS(rv, rv);

    if (aBoundDocument) {
      bindingManager = aBoundDocument->BindingManager();
      bindingManager->GetXBLDocumentInfo(documentURI, getter_AddRefs(info));
    }

    nsINodeInfo *ni = nsnull;
    if (aBoundElement)
      ni = aBoundElement->GetNodeInfo();

    if (!info && bindingManager &&
        (!ni || !(ni->Equals(nsXULAtoms::scrollbar, kNameSpaceID_XUL) ||
                  ni->Equals(nsXULAtoms::thumb, kNameSpaceID_XUL) ||
                  ((ni->Equals(nsHTMLAtoms::input) ||
                    ni->Equals(nsHTMLAtoms::select)) &&
                   aBoundElement->IsContentOfType(nsIContent::eHTML)))) &&
        !aForceSyncLoad) {
      // 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.
      nsCOMPtr<nsIStreamListener> listener;
      if (bindingManager)
        bindingManager->GetLoadingDocListener(documentURI, getter_AddRefs(listener));
      if (listener) {
        nsIStreamListener* ilist = listener.get();
        nsXBLStreamListener* xblListener = NS_STATIC_CAST(nsXBLStreamListener*, ilist);
        // Create a new load observer.
        if (!xblListener->HasRequest(aBindingURI, aBoundElement)) {
          nsXBLBindingRequest* req = nsXBLBindingRequest::Create(mPool, bindingURL, aBoundElement);
          xblListener->AddRequest(req);
        }
        return NS_OK;
      }
    }
     
    if (!info) {
      // Finally, if all lines of defense fail, we go and fetch the binding
      // document.
      
      // Always load chrome synchronously
      PRBool chrome;
      if (NS_SUCCEEDED(documentURI->SchemeIs("chrome", &chrome)) && chrome)
        aForceSyncLoad = PR_TRUE;

      nsCOMPtr<nsIDocument> document;
      FetchBindingDocument(aBoundElement, aBoundDocument, documentURI,
                           bindingURL, aForceSyncLoad, getter_AddRefs(document));
   
      if (document) {
        nsIBindingManager *xblDocBindingManager = document->BindingManager();
        xblDocBindingManager->GetXBLDocumentInfo(documentURI, getter_AddRefs(info));
        if (!info) {
          NS_ERROR("An XBL file is malformed.  Did you forget the XBL namespace on the bindings tag?");
          return NS_ERROR_FAILURE;
        }
        xblDocBindingManager->RemoveXBLDocumentInfo(info); // Break the self-imposed cycle.

        // If the doc is a chrome URI, then we put it into the XUL cache.
#ifdef MOZ_XUL
        if (IsChromeOrResourceURI(documentURI)) {
          if (useXULCache)
            gXULCache->PutXBLDocumentInfo(info);
        }
#endif
        
        if (bindingManager) {
          // Also put it in our binding manager's document table.
          bindingManager->PutXBLDocumentInfo(info);
        }
      }
    }
  }

  if (!info)
    return NS_OK;
 
  *aResult = info;
  NS_IF_ADDREF(*aResult);

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsXBLService::LoadBindings ( nsIContent aContent,
nsIURI aURL,
PRBool  aAugmentFlag,
nsXBLBinding **  aBinding,
PRBool aResolveStyle 
) [private, virtual]

Implements nsIXBLService.

Definition at line 513 of file nsXBLService.cpp.

{ 
  *aBinding = nsnull;
  *aResolveStyle = PR_FALSE;

  nsresult rv;

  nsCOMPtr<nsIDocument> document = aContent->GetOwnerDoc();

  // XXX document may be null if we're in the midst of paint suppression
  if (!document)
    return NS_OK;

  nsIBindingManager *bindingManager = document->BindingManager();
  
  nsXBLBinding *binding = bindingManager->GetBinding(aContent);
  if (binding && !aAugmentFlag) {
    nsXBLBinding *styleBinding = binding->GetFirstStyleBinding();
    if (styleBinding) {
      if (binding->MarkedForDeath()) {
        FlushStyleBindings(aContent);
        binding = nsnull;
      }
      else {
        // See if the URIs match.
        nsIURI* uri = styleBinding->PrototypeBinding()->BindingURI();
        PRBool equal;
        if (NS_SUCCEEDED(uri->Equals(aURL, &equal)) && equal)
          return NS_OK;
        FlushStyleBindings(aContent);
        binding = nsnull;
      }
    }
  }

  // Security check - remote pages can't load local bindings, except from chrome
  nsIURI *docURI = document->GetDocumentURI();
  PRBool isChrome = PR_FALSE;
  rv = docURI->SchemeIs("chrome", &isChrome);

  // Not everything with a chrome URI has a system principal.  See bug 160042.
  if (NS_FAILED(rv) || !isChrome) {
    nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();

    rv = secMan->
      CheckLoadURIWithPrincipal(document->GetPrincipal(), aURL,
                                nsIScriptSecurityManager::ALLOW_CHROME);
    if (NS_FAILED(rv))
      return rv;
  }

  // Content policy check.  We have to be careful to not pass aContent as the
  // context here.  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.
  PRInt16 decision = nsIContentPolicy::ACCEPT;
  rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OTHER,
                                 aURL,
                                 docURI,
                                 document,        // context
                                 EmptyCString(),  // mime guess
                                 nsnull,          // extra
                                 &decision);

  if (NS_SUCCEEDED(rv) && !NS_CP_ACCEPTED(decision))
    rv = NS_ERROR_NOT_AVAILABLE;

  if (NS_FAILED(rv))
    return rv;

  PRBool ready;
  nsRefPtr<nsXBLBinding> newBinding;
  if (NS_FAILED(rv = GetBinding(aContent, aURL, PR_FALSE, &ready,
                                getter_AddRefs(newBinding)))) {
    return rv;
  }

  if (!newBinding) {
#ifdef DEBUG
    nsCAutoString spec;
    aURL->GetSpec(spec);
    nsCAutoString 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);
    NS_ERROR(str.get());
#endif
    return NS_OK;
  }

  if (aAugmentFlag) {
    nsXBLBinding *baseBinding;
    nsXBLBinding *nextBinding = newBinding;
    do {
      baseBinding = nextBinding;
      nextBinding = baseBinding->GetBaseBinding();
      baseBinding->SetIsStyleBinding(PR_FALSE);
    } while (nextBinding);

    // XXX Handle adjusting the prototype chain! We need to somehow indicate to
    // InstallImplementation that the whole chain should just be whacked and rebuilt.
    // We are becoming the new binding.
    baseBinding->SetBaseBinding(binding);
    bindingManager->SetBinding(aContent, newBinding);
  }
  else {
    // 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);
    }
    else {
      // Install the binding on the content node.
      bindingManager->SetBinding(aContent, newBinding);
    }
  }

  // Set the binding's bound element.
  newBinding->SetBoundElement(aContent);

  // Tell the binding to build the anonymous content.
  newBinding->GenerateAnonymousContent();

  // Tell the binding to install event handlers
  newBinding->InstallEventHandlers();

  // Set up our properties
  rv = newBinding->InstallImplementation();
  NS_ENSURE_SUCCESS(rv, rv);

  // Figure out if we need to execute a constructor.
  *aBinding = newBinding->GetFirstBindingWithConstructor();
  NS_IF_ADDREF(*aBinding);

  // Figure out if we have any scoped sheets.  If so, we do a second resolve.
  *aResolveStyle = newBinding->HasStyleSheets();
  
  return NS_OK; 
}

Here is the call graph for this function:

void nsIObserver::observe ( in nsISupports  aSubject,
in string  aTopic,
in wstring  aData 
) [inherited]

Observe will be called when there is a notification for the topic |aTopic|.

This assumes that the object implementing this interface has been registered with an observer service such as the nsIObserverService.

If you expect multiple topics/subjects, the impl is responsible for filtering.

You should not modify, add, remove, or enumerate notifications in the implemention of observe.

Parameters:
aSubject: Notification specific interface pointer.
aTopic: The notification topic or subject.
aData: Notification specific wide string. subject event.
NS_IMETHODIMP nsXBLService::ResolveTag ( nsIContent aContent,
PRInt32 aNameSpaceID,
nsIAtom **  aResult 
) [private, virtual]

Implements nsIXBLService.

Definition at line 684 of file nsXBLService.cpp.

{
  nsIDocument* document = aContent->GetOwnerDoc();
  if (document) {
    return document->BindingManager()->ResolveTag(aContent, aNameSpaceID,
                                                  aResult);
  }

  *aNameSpaceID = aContent->GetNameSpaceID();
  NS_ADDREF(*aResult = aContent->Tag());

  return NS_OK;
}

Here is the call graph for this function:


Member Data Documentation

Definition at line 126 of file nsXBLService.h.

Definition at line 127 of file nsXBLService.h.

Definition at line 128 of file nsXBLService.h.

nsHashtable * nsXBLService::gClassTable = nsnull [static]

Definition at line 124 of file nsXBLService.h.

Definition at line 122 of file nsXBLService.h.

Definition at line 120 of file nsXBLService.h.

nsFixedSizeAllocator nsXBLService::mPool

Definition at line 130 of file nsXBLService.h.


The documentation for this class was generated from the following files: