LCOV - code coverage report
Current view: directory - layout/inspector/src - inDeepTreeWalker.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 168 0 0.0 %
Date: 2012-06-02 Functions: 25 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=79: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Joe Hewitt <hewitt@netscape.com> (original author)
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "inDeepTreeWalker.h"
      41                 : #include "inLayoutUtils.h"
      42                 : 
      43                 : #include "nsString.h"
      44                 : #include "nsIDOMDocument.h"
      45                 : #include "nsIDOMNodeFilter.h"
      46                 : #include "nsIDOMNodeList.h"
      47                 : #include "nsServiceManagerUtils.h"
      48                 : #include "inIDOMUtils.h"
      49                 : #include "nsIContent.h"
      50                 : #include "nsBindingManager.h"
      51                 : 
      52                 : /*****************************************************************************
      53                 :  * This implementation does not currently operaate according to the W3C spec.
      54                 :  * In particular it does NOT handle DOM mutations during the walk.  It also
      55                 :  * ignores whatToShow and the filter.
      56                 :  *****************************************************************************/
      57                 : 
      58                 : ////////////////////////////////////////////////////
      59                 : 
      60               0 : inDeepTreeWalker::inDeepTreeWalker() 
      61                 :   : mShowAnonymousContent(false),
      62                 :     mShowSubDocuments(false),
      63               0 :     mWhatToShow(nsIDOMNodeFilter::SHOW_ALL)
      64                 : {
      65               0 : }
      66                 : 
      67               0 : inDeepTreeWalker::~inDeepTreeWalker() 
      68                 : { 
      69               0 : }
      70                 : 
      71               0 : NS_IMPL_ISUPPORTS2(inDeepTreeWalker,
      72                 :                    inIDeepTreeWalker,
      73                 :                    nsIDOMTreeWalker)
      74                 : 
      75                 : ////////////////////////////////////////////////////
      76                 : // inIDeepTreeWalker
      77                 : 
      78                 : NS_IMETHODIMP
      79               0 : inDeepTreeWalker::GetShowAnonymousContent(bool *aShowAnonymousContent)
      80                 : {
      81               0 :   *aShowAnonymousContent = mShowAnonymousContent;
      82               0 :   return NS_OK;
      83                 : }
      84                 : 
      85                 : NS_IMETHODIMP
      86               0 : inDeepTreeWalker::SetShowAnonymousContent(bool aShowAnonymousContent)
      87                 : {
      88               0 :   mShowAnonymousContent = aShowAnonymousContent;
      89               0 :   return NS_OK;
      90                 : }
      91                 : 
      92                 : NS_IMETHODIMP
      93               0 : inDeepTreeWalker::GetShowSubDocuments(bool *aShowSubDocuments)
      94                 : {
      95               0 :   *aShowSubDocuments = mShowSubDocuments;
      96               0 :   return NS_OK;
      97                 : }
      98                 : 
      99                 : NS_IMETHODIMP
     100               0 : inDeepTreeWalker::SetShowSubDocuments(bool aShowSubDocuments)
     101                 : {
     102               0 :   mShowSubDocuments = aShowSubDocuments;
     103               0 :   return NS_OK;
     104                 : }
     105                 : 
     106                 : NS_IMETHODIMP
     107               0 : inDeepTreeWalker::Init(nsIDOMNode* aRoot, PRUint32 aWhatToShow)
     108                 : {
     109               0 :   mRoot = aRoot;
     110               0 :   mWhatToShow = aWhatToShow;
     111                 :   
     112               0 :   PushNode(aRoot);
     113                 : 
     114               0 :   return NS_OK;
     115                 : }
     116                 : 
     117                 : ////////////////////////////////////////////////////
     118                 : // nsIDOMTreeWalker
     119                 : 
     120                 : NS_IMETHODIMP
     121               0 : inDeepTreeWalker::GetRoot(nsIDOMNode** aRoot)
     122                 : {
     123               0 :   *aRoot = mRoot;
     124               0 :   NS_IF_ADDREF(*aRoot);
     125                 :   
     126               0 :   return NS_OK;
     127                 : }
     128                 : 
     129                 : NS_IMETHODIMP 
     130               0 : inDeepTreeWalker::GetWhatToShow(PRUint32* aWhatToShow)
     131                 : {
     132               0 :   *aWhatToShow = mWhatToShow;
     133               0 :   return NS_OK;
     134                 : }
     135                 : 
     136                 : NS_IMETHODIMP
     137               0 : inDeepTreeWalker::GetFilter(nsIDOMNodeFilter** aFilter)
     138                 : {
     139               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     140                 : }
     141                 : 
     142                 : NS_IMETHODIMP
     143               0 : inDeepTreeWalker::GetExpandEntityReferences(bool* aExpandEntityReferences)
     144                 : {
     145               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     146                 : }
     147                 : 
     148                 : NS_IMETHODIMP
     149               0 : inDeepTreeWalker::GetCurrentNode(nsIDOMNode** aCurrentNode)
     150                 : {
     151               0 :   *aCurrentNode = mCurrentNode;
     152               0 :   NS_IF_ADDREF(*aCurrentNode);
     153                 :   
     154               0 :   return NS_OK;
     155                 : }
     156                 : 
     157                 : NS_IMETHODIMP
     158               0 : inDeepTreeWalker::SetCurrentNode(nsIDOMNode* aCurrentNode)
     159                 : {
     160               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     161                 : }
     162                 : 
     163                 : NS_IMETHODIMP
     164               0 : inDeepTreeWalker::ParentNode(nsIDOMNode** _retval)
     165                 : {
     166               0 :   *_retval = nsnull;
     167               0 :   if (!mCurrentNode) return NS_OK;
     168                 : 
     169               0 :   if (mStack.Length() == 1) {
     170                 :     // No parent
     171               0 :     return NS_OK;
     172                 :   }
     173                 : 
     174                 :   // Pop off the current node, and push the new one
     175               0 :   mStack.RemoveElementAt(mStack.Length()-1);
     176               0 :   DeepTreeStackItem& top = mStack.ElementAt(mStack.Length() - 1);
     177               0 :   mCurrentNode = top.node;
     178               0 :   top.lastIndex = 0;
     179               0 :   NS_ADDREF(*_retval = mCurrentNode);
     180               0 :   return NS_OK;
     181                 : }
     182                 : 
     183                 : NS_IMETHODIMP
     184               0 : inDeepTreeWalker::FirstChild(nsIDOMNode **_retval)
     185                 : {
     186               0 :   *_retval = nsnull;
     187               0 :   if (!mCurrentNode) {
     188               0 :     return NS_OK;
     189                 :   }
     190                 : 
     191               0 :   DeepTreeStackItem& top = mStack.ElementAt(mStack.Length() - 1);
     192               0 :   nsCOMPtr<nsIDOMNode> kid;
     193               0 :   top.kids->Item(0, getter_AddRefs(kid));
     194               0 :   if (!kid) {
     195               0 :     return NS_OK;
     196                 :   }
     197               0 :   top.lastIndex = 1;
     198               0 :   PushNode(kid);
     199               0 :   kid.forget(_retval);
     200               0 :   return NS_OK;
     201                 : }
     202                 : 
     203                 : NS_IMETHODIMP
     204               0 : inDeepTreeWalker::LastChild(nsIDOMNode **_retval)
     205                 : {
     206               0 :   *_retval = nsnull;
     207               0 :   if (!mCurrentNode) {
     208               0 :     return NS_OK;
     209                 :   }
     210                 : 
     211               0 :   DeepTreeStackItem& top = mStack.ElementAt(mStack.Length() - 1);
     212               0 :   nsCOMPtr<nsIDOMNode> kid;
     213                 :   PRUint32 length;
     214               0 :   top.kids->GetLength(&length);
     215               0 :   top.kids->Item(length - 1, getter_AddRefs(kid));
     216               0 :   if (!kid) {
     217               0 :     return NS_OK;
     218                 :   }
     219               0 :   top.lastIndex = length;
     220               0 :   PushNode(kid);
     221               0 :   kid.forget(_retval);
     222               0 :   return NS_OK;
     223                 : }
     224                 : 
     225                 : NS_IMETHODIMP
     226               0 : inDeepTreeWalker::PreviousSibling(nsIDOMNode **_retval)
     227                 : {
     228               0 :   *_retval = nsnull;
     229               0 :   if (!mCurrentNode) {
     230               0 :     return NS_OK;
     231                 :   }
     232                 : 
     233               0 :   NS_ASSERTION(mStack.Length() > 0, "Should have things in mStack");
     234                 : 
     235               0 :   if (mStack.Length() == 1) {
     236                 :     // No previous sibling
     237               0 :     return NS_OK;
     238                 :   }
     239                 : 
     240               0 :   DeepTreeStackItem& parent = mStack.ElementAt(mStack.Length()-2);
     241               0 :   nsCOMPtr<nsIDOMNode> previousSibling;
     242               0 :   parent.kids->Item(parent.lastIndex-2, getter_AddRefs(previousSibling));
     243               0 :   if (!previousSibling) {
     244               0 :     return NS_OK;
     245                 :   }
     246                 : 
     247                 :   // Our mStack's topmost element is our current node. Since we're trying to
     248                 :   // change that to the previous sibling, pop off the current node, and push
     249                 :   // the new one.
     250               0 :   mStack.RemoveElementAt(mStack.Length() - 1);
     251               0 :   parent.lastIndex--;
     252               0 :   PushNode(previousSibling);
     253               0 :   previousSibling.forget(_retval);
     254               0 :   return NS_OK;
     255                 : }
     256                 : 
     257                 : NS_IMETHODIMP
     258               0 : inDeepTreeWalker::NextSibling(nsIDOMNode **_retval)
     259                 : {
     260               0 :   *_retval = nsnull;
     261               0 :   if (!mCurrentNode) {
     262               0 :     return NS_OK;
     263                 :   }
     264                 : 
     265               0 :   NS_ASSERTION(mStack.Length() > 0, "Should have things in mStack");
     266                 : 
     267               0 :   if (mStack.Length() == 1) {
     268                 :     // No next sibling
     269               0 :     return NS_OK;
     270                 :   }
     271                 : 
     272               0 :   DeepTreeStackItem& parent = mStack.ElementAt(mStack.Length()-2);
     273               0 :   nsCOMPtr<nsIDOMNode> nextSibling;
     274               0 :   parent.kids->Item(parent.lastIndex, getter_AddRefs(nextSibling));
     275               0 :   if (!nextSibling) {
     276               0 :     return NS_OK;
     277                 :   }
     278                 : 
     279                 :   // Our mStack's topmost element is our current node. Since we're trying to
     280                 :   // change that to the next sibling, pop off the current node, and push
     281                 :   // the new one.
     282               0 :   mStack.RemoveElementAt(mStack.Length() - 1);
     283               0 :   parent.lastIndex++;
     284               0 :   PushNode(nextSibling);
     285               0 :   nextSibling.forget(_retval);
     286               0 :   return NS_OK;
     287                 : }
     288                 : 
     289                 : NS_IMETHODIMP
     290               0 : inDeepTreeWalker::PreviousNode(nsIDOMNode **_retval)
     291                 : {
     292               0 :   if (!mCurrentNode || mStack.Length() == 1) {
     293                 :     // Nowhere to go from here
     294               0 :     *_retval = nsnull;
     295               0 :     return NS_OK;
     296                 :   }
     297                 : 
     298               0 :   nsCOMPtr<nsIDOMNode> node;
     299               0 :   PreviousSibling(getter_AddRefs(node));
     300                 : 
     301               0 :   if (!node) {
     302               0 :     return ParentNode(_retval);
     303                 :   }
     304                 : 
     305                 :   // Now we're positioned at our previous sibling.  But since the DOM tree
     306                 :   // traversal is depth-first, the previous node is its most deeply nested last
     307                 :   // child.  Just loop until LastChild() returns null; since the LastChild()
     308                 :   // call that returns null won't affect our position, we will then be
     309                 :   // positioned at the correct node.
     310               0 :   while (node) {
     311               0 :     LastChild(getter_AddRefs(node));
     312                 :   }
     313                 : 
     314               0 :   NS_ADDREF(*_retval = mCurrentNode);
     315               0 :   return NS_OK;
     316                 : }
     317                 : 
     318                 : NS_IMETHODIMP
     319               0 : inDeepTreeWalker::NextNode(nsIDOMNode **_retval)
     320                 : {
     321                 :   // First try our kids
     322               0 :   FirstChild(_retval);
     323                 : 
     324               0 :   if (*_retval) {
     325               0 :     return NS_OK;
     326                 :   }
     327                 : 
     328                 :   // Now keep trying next siblings up the parent chain, but if we
     329                 :   // discover there's nothing else restore our state.
     330                 : #ifdef DEBUG
     331               0 :   nsIDOMNode* origCurrentNode = mCurrentNode;
     332                 : #endif
     333               0 :   PRUint32 lastChildCallsToMake = 0;
     334               0 :   while (1) {
     335               0 :     NextSibling(_retval);
     336                 : 
     337               0 :     if (*_retval) {
     338               0 :       return NS_OK;
     339                 :     }
     340                 : 
     341               0 :     nsCOMPtr<nsIDOMNode> parent;
     342               0 :     ParentNode(getter_AddRefs(parent));
     343               0 :     if (!parent) {
     344                 :       // Nowhere else to go; we're done.  Restore our state.
     345               0 :       while (lastChildCallsToMake--) {
     346               0 :         nsCOMPtr<nsIDOMNode> dummy;
     347               0 :         LastChild(getter_AddRefs(dummy));
     348                 :       }
     349               0 :       NS_ASSERTION(mCurrentNode == origCurrentNode,
     350                 :                    "Didn't go back to the right node?");
     351               0 :       *_retval = nsnull;
     352               0 :       return NS_OK;
     353                 :     }
     354               0 :     ++lastChildCallsToMake;
     355                 :   }
     356                 : 
     357                 :   NS_NOTREACHED("how did we get here?");
     358                 :   return NS_OK;
     359                 : }
     360                 : 
     361                 : void
     362               0 : inDeepTreeWalker::PushNode(nsIDOMNode* aNode)
     363                 : {
     364               0 :   mCurrentNode = aNode;
     365               0 :   if (!aNode) return;
     366                 : 
     367               0 :   DeepTreeStackItem item;
     368               0 :   item.node = aNode;
     369                 : 
     370               0 :   nsCOMPtr<nsIDOMNodeList> kids;
     371               0 :   if (mShowSubDocuments) {
     372               0 :     nsCOMPtr<nsIDOMDocument> domdoc = inLayoutUtils::GetSubDocumentFor(aNode);
     373               0 :     if (domdoc) {
     374               0 :       domdoc->GetChildNodes(getter_AddRefs(kids));
     375                 :     }
     376                 :   }
     377                 :   
     378               0 :   if (!kids) {
     379               0 :     if (mShowAnonymousContent) {
     380               0 :       nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
     381               0 :       nsRefPtr<nsBindingManager> bindingManager;
     382               0 :       if (content &&
     383               0 :           (bindingManager = inLayoutUtils::GetBindingManagerFor(aNode))) {
     384               0 :         bindingManager->GetAnonymousNodesFor(content, getter_AddRefs(kids));
     385               0 :         if (!kids)
     386               0 :           bindingManager->GetContentListFor(content, getter_AddRefs(kids));
     387                 :       } else {
     388               0 :         aNode->GetChildNodes(getter_AddRefs(kids));
     389                 :       }
     390                 :     } else
     391               0 :       aNode->GetChildNodes(getter_AddRefs(kids));
     392                 :   }
     393                 :   
     394               0 :   item.kids = kids;
     395               0 :   item.lastIndex = 0;
     396               0 :   mStack.AppendElement(item);
     397                 : }
     398                 : 
     399                 : /*
     400                 : // This NextNode implementation does not require the use of stacks, 
     401                 : // as does the one above. However, it does not handle anonymous 
     402                 : // content and sub-documents.
     403                 : NS_IMETHODIMP
     404                 : inDeepTreeWalker::NextNode(nsIDOMNode **_retval)
     405                 : {
     406                 :   if (!mCurrentNode) return NS_OK;
     407                 :   
     408                 :   // walk down the tree first
     409                 :   nsCOMPtr<nsIDOMNode> next;
     410                 :   mCurrentNode->GetFirstChild(getter_AddRefs(next));
     411                 :   if (!next) {
     412                 :     mCurrentNode->GetNextSibling(getter_AddRefs(next));
     413                 :     if (!next) { 
     414                 :       // we've hit the end, so walk back up the tree until another
     415                 :       // downward opening is found, or the top of the tree
     416                 :       nsCOMPtr<nsIDOMNode> subject = mCurrentNode;
     417                 :       nsCOMPtr<nsIDOMNode> parent;
     418                 :       while (1) {
     419                 :         subject->GetParentNode(getter_AddRefs(parent));
     420                 :         if (!parent) // hit the top of the tree
     421                 :           break;
     422                 :         parent->GetNextSibling(getter_AddRefs(subject));
     423                 :         if (subject) { // found a downward opening
     424                 :           next = subject;
     425                 :           break;
     426                 :         } else // walk up another level
     427                 :           subject = parent;
     428                 :       } 
     429                 :     }
     430                 :   }
     431                 :   
     432                 :   mCurrentNode = next;
     433                 :   
     434                 :   *_retval = next;
     435                 :   NS_IF_ADDREF(*_retval);
     436                 :   
     437                 :   return NS_OK;
     438                 : }
     439                 : 
     440                 : 
     441                 : char* getURL(nsIDOMDocument* aDoc)
     442                 : {
     443                 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
     444                 :   nsIURI *uri = doc->GetDocumentURI();
     445                 :   char* s;
     446                 :   uri->GetSpec(&s);
     447                 :   return s;
     448                 : }
     449                 : */

Generated by: LCOV version 1.7