content/xul/templates/src/nsXULTemplateBuilder.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef nsXULTemplateBuilder_h__
     7 #define nsXULTemplateBuilder_h__
     9 #include "nsStubDocumentObserver.h"
    10 #include "nsIScriptSecurityManager.h"
    11 #include "nsIObserver.h"
    12 #include "nsIRDFCompositeDataSource.h"
    13 #include "nsIRDFContainer.h"
    14 #include "nsIRDFContainerUtils.h"
    15 #include "nsIRDFDataSource.h"
    16 #include "nsIRDFObserver.h"
    17 #include "nsIRDFService.h"
    18 #include "nsIXULTemplateBuilder.h"
    20 #include "nsCOMArray.h"
    21 #include "nsTArray.h"
    22 #include "nsDataHashtable.h"
    23 #include "nsTemplateRule.h"
    24 #include "nsTemplateMatch.h"
    25 #include "nsIXULTemplateQueryProcessor.h"
    26 #include "nsCycleCollectionParticipant.h"
    28 #include "prlog.h"
    29 #ifdef PR_LOGGING
    30 extern PRLogModuleInfo* gXULTemplateLog;
    31 #endif
    33 class nsIContent;
    34 class nsIObserverService;
    35 class nsIRDFCompositeDataSource;
    36 class nsIXULDocument;
    38 /**
    39  * An object that translates an RDF graph into a presentation using a
    40  * set of rules.
    41  */
    42 class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
    43                              public nsIObserver,
    44                              public nsStubDocumentObserver
    45 {
    46     void CleanUp(bool aIsFinal);
    48 public:
    49     nsXULTemplateBuilder();
    50     virtual ~nsXULTemplateBuilder();
    52     nsresult InitGlobals();
    54     /**
    55      * Clear the template builder structures. The aIsFinal flag is set to true
    56      * when the template is going away.
    57      */
    58     virtual void Uninit(bool aIsFinal);
    60     // nsISupports interface
    61     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    62     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateBuilder,
    63                                              nsIXULTemplateBuilder)
    65     // nsIXULTemplateBuilder interface
    66     NS_DECL_NSIXULTEMPLATEBUILDER
    68     // nsIObserver Interface
    69     NS_DECL_NSIOBSERVER
    71     // nsIMutationObserver
    72     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
    73     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
    74     NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
    76     /**
    77      * Remove an old result and/or add a new result. This method will retrieve
    78      * the set of containers where the result could be inserted and either add
    79      * the new result to those containers, or remove the result from those
    80      * containers. UpdateResultInContainer is called for each container.
    81      *
    82      * @param aOldResult result to remove
    83      * @param aNewResult result to add
    84      * @param aQueryNode query node for new result
    85      */
    86     nsresult
    87     UpdateResult(nsIXULTemplateResult* aOldResult,
    88                  nsIXULTemplateResult* aNewResult,
    89                  nsIDOMNode* aQueryNode);
    91     /**
    92      * Remove an old result and/or add a new result from a specific container.
    93      *
    94      * @param aOldResult result to remove
    95      * @param aNewResult result to add
    96      * @param aQueryNode queryset for the new result
    97      * @param aOldId id of old result
    98      * @param aNewId id of new result
    99      * @param aInsertionPoint container to remove or add result inside
   100      */
   101     nsresult
   102     UpdateResultInContainer(nsIXULTemplateResult* aOldResult,
   103                             nsIXULTemplateResult* aNewResult,
   104                             nsTemplateQuerySet* aQuerySet,
   105                             nsIRDFResource* aOldId,
   106                             nsIRDFResource* aNewId,
   107                             nsIContent* aInsertionPoint);
   109     nsresult
   110     ComputeContainmentProperties();
   112     static bool
   113     IsTemplateElement(nsIContent* aContent);
   115     virtual nsresult
   116     RebuildAll() = 0; // must be implemented by subclasses
   118     void RunnableRebuild() { Rebuild(); }
   119     void RunnableLoadAndRebuild() {
   120       Uninit(false);  // Reset results
   122       nsCOMPtr<nsIDocument> doc = mRoot ? mRoot->GetDocument() : nullptr;
   123       if (doc) {
   124         bool shouldDelay;
   125         LoadDataSources(doc, &shouldDelay);
   126         if (!shouldDelay) {
   127           Rebuild();
   128         }
   129       }
   130     }
   132     // mRoot should not be cleared until after Uninit is finished so that
   133     // generated content can be removed during uninitialization.
   134     void UninitFalse() { Uninit(false); mRoot = nullptr; }
   135     void UninitTrue() { Uninit(true); mRoot = nullptr; }
   137     /**
   138      * Find the <template> tag that applies for this builder
   139      */
   140     nsresult
   141     GetTemplateRoot(nsIContent** aResult);
   143     /**
   144      * Compile the template's queries
   145      */
   146     nsresult
   147     CompileQueries();
   149     /**
   150      * Compile the template given a <template> in aTemplate. This function
   151      * is called recursively to handle queries inside a queryset. For the
   152      * outer pass, aIsQuerySet will be false, while the inner pass this will
   153      * be true.
   154      *
   155      * aCanUseTemplate will be set to true if the template's queries could be
   156      * compiled, and false otherwise. If false, the entire template is
   157      * invalid.
   158      *
   159      * @param aTemplate <template> to compile
   160      * @param aQuerySet first queryset
   161      * @param aIsQuerySet true if 
   162      * @param aPriority the queryset index, incremented when a new one is added
   163      * @param aCanUseTemplate true if template is valid
   164      */
   165     nsresult
   166     CompileTemplate(nsIContent* aTemplate,
   167                     nsTemplateQuerySet* aQuerySet,
   168                     bool aIsQuerySet,
   169                     int32_t* aPriority,
   170                     bool* aCanUseTemplate);
   172     /**
   173      * Compile a query using the extended syntax. For backwards compatible RDF
   174      * syntax where there is no <query>, the <conditions> becomes the query.
   175      *
   176      * @param aRuleElement <rule> element
   177      * @param aActionElement <action> element
   178      * @param aMemberVariable member variable for the query
   179      * @param aQuerySet the queryset
   180      */
   181     nsresult 
   182     CompileExtendedQuery(nsIContent* aRuleElement,
   183                          nsIContent* aActionElement,
   184                          nsIAtom* aMemberVariable,
   185                          nsTemplateQuerySet* aQuerySet);
   187     /**
   188      * Determine the ref variable and tag from inside a RDF query.
   189      */
   190     void DetermineRDFQueryRef(nsIContent* aQueryElement, nsIAtom** tag);
   192     /**
   193      * Determine the member variable from inside an action body. It will be
   194      * the value of the uri attribute on a node.
   195      */
   196     already_AddRefed<nsIAtom> DetermineMemberVariable(nsIContent* aElement);
   198     /**
   199      * Compile a simple query. A simple query is one that doesn't have a
   200      * <query> and should use a default query which would normally just return
   201      * a list of children of the reference point.
   202      *
   203      * @param aRuleElement the <rule>
   204      * @param aQuerySet the query set
   205      * @param aCanUseTemplate true if the query is valid
   206      */
   207     nsresult 
   208     CompileSimpleQuery(nsIContent* aRuleElement,
   209                        nsTemplateQuerySet* aQuerySet,
   210                        bool* aCanUseTemplate);
   212     /**
   213      * Compile the <conditions> tag in a rule
   214      *
   215      * @param aRule template rule
   216      * @param aConditions <conditions> element
   217      */
   218     nsresult
   219     CompileConditions(nsTemplateRule* aRule, nsIContent* aConditions);
   221     /**
   222      * Compile a <where> tag in a condition. The caller should set
   223      * *aCurrentCondition to null for the first condition. This value will be
   224      * updated to point to the new condition before returning. The conditions
   225      * will be added to the rule aRule by this method.
   226      *
   227      * @param aRule template rule
   228      * @param aCondition <where> element
   229      * @param aCurrentCondition compiled condition
   230      */
   231     nsresult
   232     CompileWhereCondition(nsTemplateRule* aRule,
   233                           nsIContent* aCondition,
   234                           nsTemplateCondition** aCurrentCondition);
   236     /**
   237      * Compile the <bindings> for an extended template syntax rule.
   238      */
   239     nsresult
   240     CompileBindings(nsTemplateRule* aRule, nsIContent* aBindings);
   242     /**
   243      * Compile a single binding for an extended template syntax rule.
   244      */
   245     nsresult
   246     CompileBinding(nsTemplateRule* aRule, nsIContent* aBinding);
   248     /**
   249      * Add automatic bindings for simple rules
   250      */
   251     nsresult
   252     AddSimpleRuleBindings(nsTemplateRule* aRule, nsIContent* aElement);
   254     static void
   255     AddBindingsFor(nsXULTemplateBuilder* aSelf,
   256                    const nsAString& aVariable,
   257                    void* aClosure);
   259     /**
   260      * Load the datasources for the template. shouldDelayBuilding is an out
   261      * parameter which will be set to true to indicate that content building
   262      * should not be performed yet as the datasource has not yet loaded. If
   263      * false, the datasource has already loaded so building can proceed
   264      * immediately. In the former case, the datasource or query processor
   265      * should either rebuild the template or update results when the
   266      * datasource is loaded as needed.
   267      */
   268     nsresult
   269     LoadDataSources(nsIDocument* aDoc, bool* shouldDelayBuilding);
   271     /**
   272      * Called by LoadDataSources to load a datasource given a uri list
   273      * in aDataSource. The list is a set of uris separated by spaces.
   274      * If aIsRDFQuery is true, then this is for an RDF datasource which
   275      * causes the method to check for additional flags specific to the
   276      * RDF processor.
   277      */
   278     nsresult
   279     LoadDataSourceUrls(nsIDocument* aDocument,
   280                        const nsAString& aDataSources,
   281                        bool aIsRDFQuery,
   282                        bool* aShouldDelayBuilding);
   284     nsresult
   285     InitHTMLTemplateRoot();
   287     /**
   288      * Determine which rule matches a given result. aContainer is used for
   289      * tag matching and is optional for non-content generating builders.
   290      * The returned matched rule is always one of the rules owned by the
   291      * query set aQuerySet.
   292      *
   293      * @param aContainer parent where generated content will be inserted
   294      * @param aResult result to match
   295      * @param aQuerySet query set to examine the rules of
   296      * @param aMatchedRule [out] rule that has matched, or null if any.
   297      * @param aRuleIndex [out] index of the rule
   298      */
   299     nsresult
   300     DetermineMatchedRule(nsIContent* aContainer,
   301                          nsIXULTemplateResult* aResult,
   302                          nsTemplateQuerySet* aQuerySet,
   303                          nsTemplateRule** aMatchedRule,
   304                          int16_t *aRuleIndex);
   306     // XXX sigh, the string template foo doesn't mix with
   307     // operator->*() on egcs-1.1.2, so we'll need to explicitly pass
   308     // "this" and use good ol' fashioned static callbacks.
   309     void
   310     ParseAttribute(const nsAString& aAttributeValue,
   311                    void (*aVariableCallback)(nsXULTemplateBuilder* aThis, const nsAString&, void*),
   312                    void (*aTextCallback)(nsXULTemplateBuilder* aThis, const nsAString&, void*),
   313                    void* aClosure);
   315     nsresult
   316     SubstituteText(nsIXULTemplateResult* aMatch,
   317                    const nsAString& aAttributeValue,
   318                    nsAString& aResult);
   320     static void
   321     SubstituteTextAppendText(nsXULTemplateBuilder* aThis, const nsAString& aText, void* aClosure);
   323     static void
   324     SubstituteTextReplaceVariable(nsXULTemplateBuilder* aThis, const nsAString& aVariable, void* aClosure);    
   326     nsresult 
   327     IsSystemPrincipal(nsIPrincipal *principal, bool *result);
   329     /**
   330      * Convenience method which gets a resource for a result. If a result
   331      * doesn't have a resource set, it will create one from the result's id.
   332      */
   333     nsresult GetResultResource(nsIXULTemplateResult* aResult,
   334                                nsIRDFResource** aResource);
   336 protected:
   337     nsCOMPtr<nsISupports> mDataSource;
   338     nsCOMPtr<nsIRDFDataSource> mDB;
   339     nsCOMPtr<nsIRDFCompositeDataSource> mCompDB;
   341     /**
   342      * Circular reference, broken when the document is destroyed.
   343      */
   344     nsCOMPtr<nsIContent> mRoot;
   346     /**
   347      * The root result, translated from the root element's ref
   348      */
   349     nsCOMPtr<nsIXULTemplateResult> mRootResult;
   351     nsCOMArray<nsIXULBuilderListener> mListeners;
   353     /**
   354      * The query processor which generates results
   355      */
   356     nsCOMPtr<nsIXULTemplateQueryProcessor> mQueryProcessor;
   358     /**
   359      * The list of querysets
   360      */
   361     nsTArray<nsTemplateQuerySet *> mQuerySets;
   363     /**
   364      * Set to true if the rules have already been compiled
   365      */
   366     bool          mQueriesCompiled;
   368     /**
   369      * The default reference and member variables.
   370      */
   371     nsCOMPtr<nsIAtom> mRefVariable;
   372     nsCOMPtr<nsIAtom> mMemberVariable;
   374     /**
   375      * The match map contains nsTemplateMatch objects, one for each unique
   376      * match found, keyed by the resource for that match. A particular match
   377      * will contain a linked list of all of the matches for that unique result
   378      * id. Only one is active at a time. When a match is retracted, look in
   379      * the match map, remove it, and apply the next valid match in sequence to
   380      * make active.
   381      */
   382     nsDataHashtable<nsISupportsHashKey, nsTemplateMatch*> mMatchMap;
   384     // pseudo-constants
   385     static nsrefcnt gRefCnt;
   386     static nsIRDFService*            gRDFService;
   387     static nsIRDFContainerUtils*     gRDFContainerUtils;
   388     static nsIScriptSecurityManager* gScriptSecurityManager;
   389     static nsIPrincipal*             gSystemPrincipal;
   390     static nsIObserverService*       gObserverService;
   392     enum {
   393         eDontTestEmpty = (1 << 0),
   394         eDontRecurse = (1 << 1),
   395         eLoggingEnabled = (1 << 2)
   396     };
   398     int32_t mFlags;
   400     /**
   401      * Stack-based helper class to maintain a list of ``activated''
   402      * resources; i.e., resources for which we are currently building
   403      * content.
   404      */
   405     class ActivationEntry {
   406     public:
   407         nsIRDFResource   *mResource;
   408         ActivationEntry  *mPrevious;
   409         ActivationEntry **mLink;
   411         ActivationEntry(nsIRDFResource *aResource, ActivationEntry **aLink)
   412             : mResource(aResource),
   413               mPrevious(*aLink),
   414               mLink(aLink) { *mLink = this; }
   416         ~ActivationEntry() { *mLink = mPrevious; }
   417     };
   419     /**
   420      * The top of the stack of resources that we're currently building
   421      * content for.
   422      */
   423     ActivationEntry *mTop;
   425     /**
   426      * Determine if a resource is currently on the activation stack.
   427      */
   428     bool
   429     IsActivated(nsIRDFResource *aResource);
   431     /**
   432      * Returns true if content may be generated for a result, or false if it
   433      * cannot, for example, if it would be created inside a closed container.
   434      * Those results will be generated when the container is opened.
   435      * If false is returned, no content should be generated. Possible 
   436      * insertion locations may optionally be set for new content, depending on
   437      * the builder being used. Note that *aLocations or some items within
   438      * aLocations may be null.
   439      */
   440     virtual bool
   441     GetInsertionLocations(nsIXULTemplateResult* aResult,
   442                           nsCOMArray<nsIContent>** aLocations) = 0;
   444     /**
   445      * Must be implemented by subclasses. Handle removing the generated
   446      * output for aOldMatch and adding new output for aNewMatch. Either
   447      * aOldMatch or aNewMatch may be null. aContext is the location returned
   448      * from the call to MayGenerateResult.
   449      */
   450     virtual nsresult
   451     ReplaceMatch(nsIXULTemplateResult* aOldResult,
   452                  nsTemplateMatch* aNewMatch,
   453                  nsTemplateRule* aNewMatchRule,
   454                  void *aContext) = 0;
   456     /**
   457      * Must be implemented by subclasses. Handle change in bound
   458      * variable values for aResult. aModifiedVars contains the set
   459      * of variables that have changed.
   460      * @param aResult the ersult for which variable bindings has changed.
   461      * @param aModifiedVars the set of variables for which the bindings
   462      * have changed.
   463      */
   464     virtual nsresult
   465     SynchronizeResult(nsIXULTemplateResult* aResult) = 0;
   467     /**
   468      * Output a new match or removed match to the console.
   469      *
   470      * @param aId id of the result
   471      * @param aMatch new or removed match
   472      * @param aIsNew true for new matched, false for removed matches
   473      */
   474     void
   475     OutputMatchToLog(nsIRDFResource* aId,
   476                      nsTemplateMatch* aMatch,
   477                      bool aIsNew);
   479     virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const
   480     {
   481     }
   483     /**
   484      * Start observing events from the observer service and the given
   485      * document.
   486      *
   487      * @param aDocument the document to observe
   488      */
   489     void StartObserving(nsIDocument* aDocument);
   491     /**
   492      * Stop observing events from the observer service and any associated
   493      * document.
   494      */
   495     void StopObserving();
   497     /**
   498      * Document that we're observing. Weak ref!
   499      */
   500     nsIDocument* mObservedDocument;
   501 };
   503 #endif // nsXULTemplateBuilder_h__

mercurial