• Skip to main content
  • Select language
  • Skip to search
MDN Web Docs
  • Technologies
    • HTML
    • CSS
    • JavaScript
    • Graphics
    • HTTP
    • APIs / DOM
    • WebExtensions
    • MathML
  • References & Guides
    • Learn web development
    • Tutorials
    • References
    • Developer Guides
    • Accessibility
    • Game development
    • ...more docs
Archive of obsolete content
  1. MDN
  2. Archive of obsolete content
  3. Archived Mozilla and build documentation
  4. Space Manager Detailed Design

Space Manager Detailed Design

In This Article
    1. Overview
    2. nsSpaceManager
      1. Public API
      2. Implementation Notes
    3. Cross-Component Algorithms
    4. Tech Notes
  1. Original Document Information

Overview

The Space Manager and related classes and structures are an important of the Gecko Layout system, specifically Block Layout. See the High Level Design document for an overview of the Space Manager, and as an introduction to the classes, structures and algorithms container in this, the Detailed Design Document.

nsSpaceManager

The Space Manager is the central class is a group of classes that manage the occupied and available space that exists in horizontal bands across a canvas. The primary goal of the Space Manager is to provide information about those bands of space to support the CSS notion of floated elements.

There are three important parts to the Space Manager API: the parts that deal with the coordinate space of the Space Manager, the parts that deal with the regions managed by the Space Manager, and the parts that manage float impact intervals.

The class nsSpaceManager is declared in the file nsSpaceManger.h. The class is only used in the layout module and cannot be exported outside of that module (nor does it need to be). It is not a general purpose class, and is not intended to be subclasses .

Here is the class declaration, taken from the source file as of 01.08.02

/**
 * Class for dealing with bands of available space. The space manager
 * defines a coordinate space with an origin at (0, 0) that grows down
 * and to the right.
 */
class nsSpaceManager {
public:
  nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame);
  ~nsSpaceManager();
  void* operator new(size_t aSize);
  void operator delete(void* aPtr, size_t aSize);
  static void Shutdown();
  /*
   * Get the frame that's associated with the space manager. This frame
   * created the space manager, and the world coordinate space is
   * relative to this frame.
   *
   * You can use QueryInterface() on this frame to get any additional
   * interfaces.
   */
  nsIFrame* GetFrame() const { return mFrame; }
  /**
   * Translate the current origin by the specified (dx, dy). This
   * creates a new local coordinate space relative to the current
   * coordinate space.
   */
  void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }
  /**
   * Returns the current translation from local coordinate space to
   * world coordinate space. This represents the accumulated calls to
   * Translate().
   */
  void GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; }
  /**
   * Returns the y-most of the bottommost band or 0 if there are no bands.
   *
   * @return  PR_TRUE if there are bands and PR_FALSE if there are no bands
   */
  PRBool YMost(nscoord& aYMost) const;
  /**
   * Returns a band starting at the specified y-offset. The band data
   * indicates which parts of the band are available, and which parts
   * are unavailable
   *
   * The band data that is returned is in the coordinate space of the
   * local coordinate system.
   *
   * The local coordinate space origin, the y-offset, and the max size
   * describe a rectangle that's used to clip the underlying band of
   * available space, i.e.
   * {0, aYOffset, aMaxSize.width, aMaxSize.height} in the local
   * coordinate space
   *
   * @param   aYOffset the y-offset of where the band begins. The coordinate is
   *            relative to the upper-left corner of the local coordinate space
   * @param   aMaxSize the size to use to constrain the band data
   * @param   aBandData [in,out] used to return the list of trapezoids that
   *            describe the available space and the unavailable space
   * @return  NS_OK if successful and NS_ERROR_FAILURE if the band data is not
   *            not large enough. The 'count' member of the band data struct
   *            indicates how large the array of trapezoids needs to be
   */
  nsresult GetBandData(nscoord       aYOffset,
                       const nsSize& aMaxSize,
                       nsBandData&   aBandData) const;
  /**
   * Add a rectangular region of unavailable space. The space is
   * relative to the local coordinate system.
   *
   * The region is tagged with a frame
   *
   * @param   aFrame the frame used to identify the region. Must not be NULL
   * @param   aUnavailableSpace the bounding rect of the unavailable space
   * @return  NS_OK if successful
   *          NS_ERROR_FAILURE if there is already a region tagged with aFrame
   */
  nsresult AddRectRegion(nsIFrame*     aFrame,
                         const nsRect& aUnavailableSpace);
  /**
   * Resize the rectangular region associated with aFrame by the specified
   * deltas. The height change always applies to the bottom edge or the existing
   * rect. You specify whether the width change applies to the left or right edge
   *
   * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
   * tagged with aFrame
   */
  enum AffectedEdge {LeftEdge, RightEdge};
  nsresult ResizeRectRegion(nsIFrame*    aFrame,
                            nscoord      aDeltaWidth,
                            nscoord      aDeltaHeight,
                            AffectedEdge aEdge = RightEdge);
  /**
   * Offset the region associated with aFrame by the specified amount.
   *
   * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
   * tagged with aFrame
   */
  nsresult OffsetRegion(nsIFrame* aFrame, nscoord dx, nscoord dy);
  /**
   * Remove the region associated with aFrane.
   *
   * Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region
   * tagged with aFrame
   */
  nsresult RemoveRegion(nsIFrame* aFrame);
  /**
   * Clears the list of regions representing the unavailable space.
   */
  void ClearRegions();
  /**
   * Methods for dealing with the propagation of float damage during
   * reflow.
   */
  PRBool HasFloatDamage()
  {
    return !mFloatDamage.IsEmpty();
  }
  void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
  {
    mFloatDamage.IncludeInterval(aIntervalBegin + mY, aIntervalEnd + mY);
  }
  PRBool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
  {
    return mFloatDamage.Intersects(aIntervalBegin + mY, aIntervalEnd + mY);
  }
#ifdef DEBUG
  /**
   * Dump the state of the spacemanager out to a file
   */
  nsresult List(FILE* out);
  void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
#endif
private:
  // Structure that maintains information about the region associated
  // with a particular frame
  struct FrameInfo {
    nsIFrame* const mFrame;
    nsRect          mRect;       // rectangular region
    FrameInfo*      mNext;
    FrameInfo(nsIFrame* aFrame, const nsRect& aRect);
#ifdef NS_BUILD_REFCNT_LOGGING
    ~FrameInfo();
#endif
  };
  // Doubly linked list of band rects
  struct BandRect : PRCListStr {
    nscoord   mLeft, mTop;
    nscoord   mRight, mBottom;
    PRIntn    mNumFrames;    // number of frames occupying this rect
    union {
      nsIFrame*    mFrame;   // single frame occupying the space
      nsVoidArray* mFrames;  // list of frames occupying the space
    };
    BandRect(nscoord aLeft, nscoord aTop,
             nscoord aRight, nscoord aBottom,
             nsIFrame*);
    BandRect(nscoord aLeft, nscoord aTop,
             nscoord aRight, nscoord aBottom,
             nsVoidArray*);
    ~BandRect();
    // List operations
    BandRect* Next() const {return (BandRect*)PR_NEXT_LINK(this);}
    BandRect* Prev() const {return (BandRect*)PR_PREV_LINK(this);}
    void      InsertBefore(BandRect* aBandRect) {PR_INSERT_BEFORE(aBandRect, this);}
    void      InsertAfter(BandRect* aBandRect) {PR_INSERT_AFTER(aBandRect, this);}
    void      Remove() {PR_REMOVE_LINK(this);}
    // Split the band rect into two vertically, with this band rect becoming
    // the top part, and a new band rect being allocated and returned for the
    // bottom part
    //
    // Does not insert the new band rect into the linked list
    BandRect* SplitVertically(nscoord aBottom);
    // Split the band rect into two horizontally, with this band rect becoming
    // the left part, and a new band rect being allocated and returned for the
    // right part
    //
    // Does not insert the new band rect into the linked list
    BandRect* SplitHorizontally(nscoord aRight);
    // Accessor functions
    PRBool  IsOccupiedBy(const nsIFrame*) const;
    void    AddFrame(const nsIFrame*);
    void    RemoveFrame(const nsIFrame*);
    PRBool  HasSameFrameList(const BandRect* aBandRect) const;
    PRInt32 Length() const;
  };
  // Circular linked list of band rects
  struct BandList : BandRect {
    BandList();
    // Accessors
    PRBool    IsEmpty() const {return PR_CLIST_IS_EMPTY((PRCListStr*)this);}
    BandRect* Head() const {return (BandRect*)PR_LIST_HEAD(this);}
    BandRect* Tail() const {return (BandRect*)PR_LIST_TAIL(this);}
    // Operations
    void      Append(BandRect* aBandRect) {PR_APPEND_LINK(aBandRect, this);}
    // Remove and delete all the band rects in the list
    void      Clear();
  };
  FrameInfo* GetFrameInfoFor(nsIFrame* aFrame);
  FrameInfo* CreateFrameInfo(nsIFrame* aFrame, const nsRect& aRect);
  void       DestroyFrameInfo(FrameInfo*);
  void       ClearFrameInfo();
  void       ClearBandRects();
  BandRect*  GetNextBand(const BandRect* aBandRect) const;
  void       DivideBand(BandRect* aBand, nscoord aBottom);
  PRBool     CanJoinBands(BandRect* aBand, BandRect* aPrevBand);
  PRBool     JoinBands(BandRect* aBand, BandRect* aPrevBand);
  void       AddRectToBand(BandRect* aBand, BandRect* aBandRect);
  void       InsertBandRect(BandRect* aBandRect);
  nsresult   GetBandAvailableSpace(const BandRect* aBand,
                                   nscoord         aY,
                                   const nsSize&   aMaxSize,
                                   nsBandData&     aAvailableSpace) const;
  nsIFrame* const mFrame;     // frame associated with the space manager
  nscoord         mX, mY;     // translation from local to global coordinate space
  BandList        mBandList;  // header/sentinel for circular linked list of band rects
  FrameInfo*      mFrameInfoMap;
  nsIntervalSet   mFloatDamage;
  static PRInt32 sCachedSpaceManagerCount;
  static void* sCachedSpaceManagers[NS_SPACE_MANAGER_CACHE_SIZE];
  nsSpaceManager(const nsSpaceManager&);  // no implementation
  void operator=(const nsSpaceManager&);  // no implementation
};

Public API

Life Cycle

The Constructor requires a Presentation Shell, used for arena allocations mostly, and a frame that this Space Manager is rooted on. The coordinate space of this Space Manager is relative to the frame passed in to the constructor.

nsSpaceManager(nsIPresShell* aPresShell, nsIFrame* aFrame);
~nsSpaceManager();

Operators 'new' and 'delete' are overridden to support a recycler. Space Manager instances come and go pretty frequently, and this recycler prevents excessive heap allocations and the performance penalties associated with it. The #define NS_SPACE_MANAGER_CACHE_SIZE is used to control the number of Space Manager instances that can be present in the recycler, currently 4. If more than NS_SPACE_MANAGER_CACHE_SIZE are allocated at a time,then standard allocation is used.

void* operator new(size_t aSize);
void operator delete(void* aPtr, size_t aSize);

A Static method is used to shutdown the Space Manager recycling. This method deletes all of the Space Mangers in the recycler,and prevents further recycling. It is meant to be called only when the layout module is being terminated.

static void Shutdown();
Origin / Coordinate Space Translation
/**
 * Translate the current origin by the specified (dx, dy). This
 * creates a new local coordinate space relative to the current
 * coordinate space.
 */
void Translate(nscoord aDx, nscoord aDy) { mX += aDx; mY += aDy; }
/**
 * Returns the current translation from local coordinate space to
 * world coordinate space. This represents the accumulated calls to
 * Translate().
 */
void GetTranslation(nscoord& aX, nscoord& aY) const { aX = mX; aY = mY; }
/**
 * Returns the y-most of the bottommost band or 0 if there are no bands.
 *
 * @return  PR_TRUE if there are bands and PR_FALSE if there are no bands
 */
PRBool YMost(nscoord& aYMost) const;
Region Management
/**
 * Returns a band starting at the specified y-offset. The band data
 * indicates which parts of the band are available, and which parts
 * are unavailable
 *
 * The band data that is returned is in the coordinate space of the
 * local coordinate system.
 *
 * The local coordinate space origin, the y-offset, and the max size
 * describe a rectangle that's used to clip the underlying band of
 * available space, i.e.
 * {0, aYOffset, aMaxSize.width, aMaxSize.height} in the local
 * coordinate space
 *
 * @param   aYOffset the y-offset of where the band begins. The coordinate is
 *            relative to the upper-left corner of the local coordinate space
 * @param   aMaxSize the size to use to constrain the band data
 * @param   aBandData [in,out] used to return the list of trapezoids that
 *            describe the available space and the unavailable space
 * @return  NS_OK if successful and NS_ERROR_FAILURE if the band data is not
 *            not large enough. The 'count' member of the band data struct
 *            indicates how large the array of trapezoids needs to be
 */
nsresult GetBandData(nscoord       aYOffset,
                     const nsSize& aMaxSize,
                     nsBandData&   aBandData) const;
/**
 * Add a rectangular region of unavailable space. The space is
 * relative to the local coordinate system.
 *
 * The region is tagged with a frame
 *
 * @param   aFrame the frame used to identify the region. Must not be NULL
 * @param   aUnavailableSpace the bounding rect of the unavailable space
 * @return  NS_OK if successful
 *          NS_ERROR_FAILURE if there is already a region tagged with aFrame
 */
nsresult AddRectRegion(nsIFrame*     aFrame,
                       const nsRect& aUnavailableSpace);
/**
 * Resize the rectangular region associated with aFrame by the specified
 * deltas. The height change always applies to the bottom edge or the existing
 * rect. You specify whether the width change applies to the left or right edge
 *
 * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
 * tagged with aFrame
 */
enum AffectedEdge {LeftEdge, RightEdge};
nsresult ResizeRectRegion(nsIFrame*    aFrame,
                          nscoord      aDeltaWidth,
                          nscoord      aDeltaHeight,
                          AffectedEdge aEdge = RightEdge);
/**
 * Offset the region associated with aFrame by the specified amount.
 *
 * Returns NS_OK if successful, NS_ERROR_INVALID_ARG if there is no region
 * tagged with aFrame
 */
nsresult OffsetRegion(nsIFrame* aFrame, nscoord dx, nscoord dy);
/**
 * Remove the region associated with aFrane.
 *
 * Returns NS_OK if successful and NS_ERROR_INVALID_ARG if there is no region
 * tagged with aFrame
 */
nsresult RemoveRegion(nsIFrame* aFrame);
/**
 * Clears the list of regions representing the unavailable space.
 */
void ClearRegions();
Float Impact
/**
 * Methods for dealing with the propagation of float damage during
 * reflow.
 */
PRBool HasFloatDamage()
{
  return !mFloatDamage.IsEmpty();
}
void IncludeInDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
{
  mFloatDamage.IncludeInterval(aIntervalBegin + mY, aIntervalEnd + mY);
}
PRBool IntersectsDamage(nscoord aIntervalBegin, nscoord aIntervalEnd)
{
  return mFloatDamage.Intersects(aIntervalBegin + mY, aIntervalEnd + mY);
}
Debug Only Methods
/**
 * Dump the state of the spacemanager out to a file
 */
nsresult List(FILE* out);
void SizeOf(nsISizeOfHandler* aHandler, PRUint32* aResult) const;
Unused / Obsolete Methods
/*
 * Get the frame that's associated with the space manager. This frame
 * created the space manager, and the world coordinate space is
 * relative to this frame.
 *
 * You can use QueryInterface() on this frame to get any additional
 * interfaces.
 */
nsIFrame* GetFrame() const { return mFrame; }

Implementation Notes

Algorithm 1: GetBandData

GetBandData is used to provide information to clients about what space if available and unavailable in a band of space. The client provides a vertical offset, the yOffset, that corresponds to the band that is of interest. This will be the y offset of the frame that is being reflowed. The caller also provides a collection of BandData objects (an array) and the number of items that the collection can handle. If the collection is too small, then an error is returned and the count is updated to indicate the size required.

The algorithm to provide the band data is as follows:

  • Get a vertical offset in world coordinates (instead of frame-relative coordinates) by adding the y-origin of the SpaceManager to the y offset passed in
  • If the (adjusted) y value passed in is greater than the greatest band being managed, then all space is available so a single trapezoid is returned,marked as available and sized to the maximum size value (passed in).
  • If the (adjusted) y offset intersects a band, then gather the banddata:
    • walk the internal bandData list from head to tail
    • for each band data entry, see if the top of the band is greater than the (adjusted) y offset requested
    • if it is, then band is below the offset requested, so the area between the band and the y offset is available - create a trapezoid with that region and return it.
    • if the (adjusted) y offset is between the band top and bottom, then get the available space for the band by calling GetBandAvailableSpace
    • otherwise, move to the next band
GetBandAvailableSpace:

This method is called from GetBandData only. It walks all of the bands in the space manager and determines which bands intersect with the band passed in, and if within those bands there are regions that are available or occupied.

  • First, walk all of the bands until a band that is to the right of the desired offset is located
  • Starting at that band, walk the remaining bands:
    • if the current band is to the right of the requested band, then there is available space.
      • if there is more room in the bandData collection, then add a trapezoid to the bandData collection such that it is marked as available and has arect that represents the space between the reference band tna dht band being examined
      • if there is no more room in the BandData collection, estimate the number of entries requires as the current count + twice the number of bands below the reference band, plus two. Return an error code so the caller can reallocate the collection and try again.
    • check the size of the collection again, if there is no room left then estimate the number of items requires as the current count + twice the number of bands below the band in question plus one.
    • create a new trapezoid in the band collection that has a region corresponding to the reference band rect, marked as occupied by either a single or multiple frames.
    • move to the next band
  • after walking all of the band data, se if we have reached the rightedge of the band.
    • If not, then check for space in the band collection
      • if there is no room left, then set the count to the current count plus 1 and return an error.
      • otherwise, create another entry in the band collection, marked as available, and with a rect corresponding to the area remain in in the band(e.g. from the right edge of the last band rect to the right edge of the band).
Algorithm 2: AddRectRegion

Clients call into this method to notify the Space Manager that a new frame is occupying some space.

  • First, try to get frame info for the frame. If it is found, return an error since the frame is already associated with a region in the SpaceManager.
  • Next, create a rect from the occupied space passed in by the caller,transforming it first to world-coordinates by adding the Space Manager's offset to the occupied space rect passed in.
  • Create a new Frame Info instance for the frame and rect, returning an error if allocation fails.
  • Check if the occupied space rect (adjusted) is empty, if so, return an error (NOTE: this could be done earlier, or prevented by the caller)
  • Allocate a new BandRect instance with the rect and frame as constructor arguments, and insert it into the collection via InsertBandRect
InsertBandRect:

Internal method to insert a band rect into the BandList in the correct location. There are several cases it has to handle, as specified in the source file comments:

// When comparing a rect to a band there are seven cases to consider.
// 'R' is the rect and 'B' is the band.
//
//      Case 1              Case 2              Case 3              Case 4
//      ------              ------              ------              ------
// +-----+             +-----+                      +-----+             +-----+
// |  R  |             |  R  |  +-----+    +-----+  |     |             |     |
// +-----+             +-----+  |     |    |  R  |  |  B  |             |  B  |
//          +-----+             |  B  |    +-----+  |     |    +-----+  |     |
//          |     |             |     |             +-----+    |  R  |  +-----+
//          |  B  |             +-----+                        +-----+
//          |     |
//          +-----+
//
//
//
//      Case 5              Case 6              Case 7
//      ------              ------              ------
//          +-----+    +-----+  +-----+    +-----+
//          |     |    |  R  |  |  B  |    |     |  +-----+
//          |  B  |    +-----+  +-----+    |  R  |  |  B  |
//          |     |                        |     |  +-----+
//          +-----+                        +-----+
// +-----+
// |  R  |
// +-----+
//
  • First, check for the easiest case, where there are no existing bandrects, or the band rect passed in is below the bottommost rect. In this case,just append the band rect and return.
  • Starting at the head of the list of bandRects, check for intersection with the rect passed in:
    • case #1: the rect is totally above the current band rect, so insert a new band rect before the current bandRect
    • cases #2 and #7: the rect is partially above the band rect, so it is divided into two bandRects, one entirely above the band, and one containing the remainder of the rect. Insert the part that is totally above the bandRect before the current bandRect, as in case #1 above, and adjust the other band rect to exclude the part already added.
    • case #5: the rect is totally below the current bandRect, so just skip to the next band
    • case #3 and #4: rect is at least partially intersection with the bandRect, so divide the current band into two parts, where the top part is above the current rect. Move to the new band just created, which is the next band.
    • case #6: the rect shares the bottom and height with the bandRect,so just add the rect to the band.
    • case #4 and #7: create a new rect for the part that overlaps the bandRect, and add it to the current bandRect (similar to case #6) and then move on to the next band, removing that part from the rect passed in. If no more bands, append the rect passed in to the end of the bandRect list.

This algorithm is pretty confusing - basically what needs to happen is that rects and bands need to be divided up so that complicated cases like#2, #4, and #7, are reduced to simpler cases where the rects is totally above,below, or between a band rect. From the current implementation, it might be worth verifying that the final result of the inserts is a correctly ordered list of bandRects (debug mode only).

Algorithm 3: RemoveRegion

When a float is removed, the Space Manager is notified by a call to RemoveRegion,passing in the frame that is being removed.

  • Get the FrameInfo for the frame passed in. If not found, an error is returned.
  • If the rect for the frame is not empty, then visit each band in the bandList:
    • for each rect in the band:
      • if the bandRect is occupied by the frame, either remove the frame from the bandRect (if there are other frames sharing it) and remember that it was shared
      • otherwise simply remove the bandRect (no other frames share it).
      • if the bandRect was shared, then try to coalesce adjacent bandRects
        • if the previous bandRect is directly next to the current bandRect,and they have the same frame list, then make the current bandRect cover the previous bandRect's full region (adjust the left edge to be that of the previous bandRect) and remove the previous bandRect.
    • if the current band or prior band had a rect occupied by the frame,then try to join the two bands via JoinBands
  • Finally, destroy the frameInfo for the frame.

Cross-Component Algorithms

Tech Notes

Original Document Information

  • Author(s): Marc Attinasi
  • Other Contributors: David Baron, Josh Soref
  • Last Updated Date: November 25, 2005

Document Tags and Contributors

Tags: 
  • Gecko
 Contributors to this page: teoli, DBaron, Kohei
 Last updated by: teoli, May 27, 2014, 12:32:28 AM

  1. .htaccess ( hypertext access )
  2. <input> archive
  3. Add-ons
    1. Add-ons
    2. Firefox addons developer guide
    3. Interaction between privileged and non-privileged pages
    4. Tabbed browser
    5. bookmarks.export()
    6. bookmarks.import()
  4. Adding preferences to an extension
  5. An Interview With Douglas Bowman of Wired News
  6. Apps
    1. Apps
    2. App Development API Reference
    3. Designing Open Web Apps
    4. Graphics and UX
    5. Open web app architecture
    6. Tools and frameworks
    7. Validating web apps with the App Validator
  7. Archived Mozilla and build documentation
    1. Archived Mozilla and build documentation
    2. ActiveX Control for Hosting Netscape Plug-ins in IE
    3. Archived SpiderMonkey docs
    4. Autodial for Windows NT
    5. Automated testing tips and tricks
    6. Automatic Mozilla Configurator
    7. Automatically Handle Failed Asserts in Debug Builds
    8. BlackConnect
    9. Blackwood
    10. Bonsai
    11. Bookmark Keywords
    12. Building TransforMiiX standalone
    13. Chromeless
    14. Creating a Firefox sidebar extension
    15. Creating a Microsummary
    16. Creating a Mozilla Extension
    17. Creating a Release Tag
    18. Creating a Skin for Firefox/Getting Started
    19. Creating a Skin for Mozilla
    20. Creating a Skin for SeaMonkey 2.x
    21. Creating a hybrid CD
    22. Creating regular expressions for a microsummary generator
    23. DTrace
    24. Dehydra
    25. Developing New Mozilla Features
    26. Devmo 1.0 Launch Roadmap
    27. Download Manager improvements in Firefox 3
    28. Download Manager preferences
    29. Drag and Drop
    30. Embedding FAQ
    31. Embedding Mozilla in a Java Application using JavaXPCOM
    32. Error Console
    33. Exception logging in JavaScript
    34. Existing Content
    35. Extension Frequently Asked Questions
    36. Fighting Junk Mail with Netscape 7.1
    37. Firefox Sync
    38. Force RTL
    39. GRE
    40. Gecko Coding Help Wanted
    41. HTTP Class Overview
    42. Hacking wiki
    43. Help Viewer
    44. Helper Apps (and a bit of Save As)
    45. Hidden prefs
    46. How to Write and Land Nanojit Patches
    47. Introducing the Audio API extension
    48. Java in Firefox Extensions
    49. JavaScript crypto
    50. Jetpack
    51. Litmus tests
    52. Makefile.mozextension.2
    53. Microsummary topics
    54. Migrate apps from Internet Explorer to Mozilla
    55. Monitoring downloads
    56. Mozilla Application Framework
    57. Mozilla Crypto FAQ
    58. Mozilla Modules and Module Ownership
    59. Mozprocess
    60. Mozprofile
    61. Mozrunner
    62. Nanojit
    63. New Skin Notes
    64. Persona
    65. Plug-n-Hack
    66. Plugin Architecture
    67. Porting NSPR to Unix Platforms
    68. Priority Content
    69. Prism
    70. Proxy UI
    71. Remote XUL
    72. SXSW 2007 presentations
    73. Space Manager Detailed Design
    74. Space Manager High Level Design
    75. Standalone XPCOM
    76. Stress testing
    77. Structure of an installable bundle
    78. Supporting private browsing mode
    79. Table Cellmap
    80. Table Cellmap - Border Collapse
    81. Table Layout Regression Tests
    82. Table Layout Strategy
    83. Tamarin
    84. The Download Manager schema
    85. The life of an HTML HTTP request
    86. The new nsString class implementation (1999)
    87. TraceVis
    88. Treehydra
    89. URIScheme
    90. URIs and URLs
    91. Using Monotone With Mozilla CVS
    92. Using SVK With Mozilla CVS
    93. Using addresses of stack variables with NSPR threads on win16
    94. Venkman
    95. Video presentations
    96. Why Embed Gecko
    97. XML in Mozilla
    98. XPInstall
    99. XPJS Components Proposal
    100. XRE
    101. XTech 2005 Presentations
    102. XTech 2006 Presentations
    103. XUL Explorer
    104. XULRunner
    105. ant script to assemble an extension
    106. calICalendarView
    107. calICalendarViewController
    108. calIFileType
    109. xbDesignMode.js
  8. Archived open Web documentation
    1. Archived open Web documentation
    2. Browser Detection and Cross Browser Support
    3. Browser Feature Detection
    4. Displaying notifications (deprecated)
    5. E4X
    6. E4X Tutorial
    7. LiveConnect
    8. MSX Emulator (jsMSX)
    9. Old Proxy API
    10. Properly Using CSS and JavaScript in XHTML Documents
    11. Reference
    12. Scope Cheatsheet
    13. Server-Side JavaScript
    14. Sharp variables in JavaScript
    15. Standards-Compliant Authoring Tools
    16. Using JavaScript Generators in Firefox
    17. Window.importDialog()
    18. Writing JavaScript for XHTML
    19. XForms
    20. background-size
    21. forEach
  9. B2G OS
    1. B2G OS
    2. Automated Testing of B2G OS
    3. B2G OS APIs
    4. B2G OS add-ons
    5. B2G OS architecture
    6. B2G OS build prerequisites
    7. B2G OS phone guide
    8. Building B2G OS
    9. Building and installing B2G OS
    10. Building the B2G OS Simulator
    11. Choosing how to run Gaia or B2G
    12. Customization with the .userconfig file
    13. Debugging on Firefox OS
    14. Developer Mode
    15. Developing Firefox OS
    16. Firefox OS Simulator
    17. Firefox OS apps
    18. Firefox OS board guide
    19. Firefox OS developer release notes
    20. Firefox OS security
    21. Firefox OS usage tips
    22. Gaia
    23. Installing B2G OS on a mobile device
    24. Introduction to Firefox OS
    25. Mulet
    26. Open web apps quickstart
    27. Pandaboard
    28. PasscodeHelper Internals
    29. Porting B2G OS
    30. Preparing for your first B2G build
    31. Resources
    32. Running tests on Firefox OS: A guide for developers
    33. The B2G OS platform
    34. Troubleshooting B2G OS
    35. Using the App Manager
    36. Using the B2G emulators
    37. Web Bluetooth API (Firefox OS)
    38. Web Telephony API
    39. Web applications
  10. Beginner tutorials
    1. Beginner tutorials
    2. Creating reusable content with CSS and XBL
    3. Underscores in class and ID Names
    4. XML data
    5. XUL user interfaces
  11. Case Sensitivity in class and id Names
  12. Creating a dynamic status bar extension
  13. Creating a status bar extension
  14. Gecko Compatibility Handbook
  15. Getting the page URL in NPAPI plugin
  16. Index
  17. Inner-browsing extending the browser navigation paradigm
  18. Install.js
  19. JXON
  20. List of Former Mozilla-Based Applications
  21. List of Mozilla-Based Applications
  22. Localizing an extension
  23. MDN
    1. MDN
    2. Content kits
  24. MDN "meta-documentation" archive
    1. MDN "meta-documentation" archive
    2. Article page layout guide
    3. Blog posts to integrate into documentation
    4. Current events
    5. Custom CSS classes for MDN
    6. Design Document
    7. DevEdge
    8. Developer documentation process
    9. Disambiguation
    10. Documentation Wishlist
    11. Documentation planning and tracking
    12. Editing MDN pages
    13. Examples
    14. Existing Content/DOM in Mozilla
    15. External Redirects
    16. Finding the right place to document bugs
    17. Getting started as a new MDN contributor
    18. Landing page layout guide
    19. MDN content on WebPlatform.org
    20. MDN page layout guide
    21. MDN subproject list
    22. Needs Redirect
    23. Page types
    24. RecRoom documentation plan
    25. Remove in-content iframes
    26. Team status board
    27. Trello
    28. Using the Mozilla Developer Center
    29. Welcome to the Mozilla Developer Network
    30. Writing chrome code documentation plan
    31. Writing content
  25. MMgc
  26. Makefile - .mk files
  27. Marketplace
    1. Marketplace
    2. API
    3. Monetization
    4. Options
    5. Publishing
  28. Mozilla release FAQ
  29. Newsgroup summaries
    1. Newsgroup summaries
    2. Format
    3. Mozilla.dev.apps.firefox-2006-09-29
    4. Mozilla.dev.apps.firefox-2006-10-06
    5. mozilla-dev-accessibility
    6. mozilla-dev-apps-calendar
    7. mozilla-dev-apps-firefox
    8. mozilla-dev-apps-thunderbird
    9. mozilla-dev-builds
    10. mozilla-dev-embedding
    11. mozilla-dev-extensions
    12. mozilla-dev-i18n
    13. mozilla-dev-l10n
    14. mozilla-dev-planning
    15. mozilla-dev-platform
    16. mozilla-dev-quality
    17. mozilla-dev-security
    18. mozilla-dev-tech-js-engine
    19. mozilla-dev-tech-layout
    20. mozilla-dev-tech-xpcom
    21. mozilla-dev-tech-xul
    22. mozilla.dev.apps.calendar
    23. mozilla.dev.tech.js-engine
  30. Obsolete: XPCOM-based scripting for NPAPI plugins
  31. Plugins
    1. Plugins
    2. Adobe Flash
    3. External resources for plugin creation
    4. Logging Multi-Process Plugins
    5. Monitoring plugins
    6. Multi-process plugin architecture
    7. NPAPI plugin developer guide
    8. NPAPI plugin reference
    9. Samples and Test Cases
    10. Shipping a plugin as a Toolkit bundle
    11. Supporting private browsing in plugins
    12. The First Install Problem
    13. Writing a plugin for Mac OS X
    14. XEmbed Extension for Mozilla Plugins
  32. SAX
  33. Security
    1. Security
    2. Digital Signatures
    3. Encryption and Decryption
    4. Introduction to Public-Key Cryptography
    5. Introduction to SSL
    6. NSPR Release Engineering Guide
    7. SSL and TLS
  34. Solaris 10 Build Prerequisites
  35. Sunbird Theme Tutorial
  36. Table Reflow Internals
  37. Tamarin Tracing Build Documentation
  38. The Basics of Web Services
  39. Themes
    1. Themes
    2. Building a Theme
    3. Common Firefox theme issues and solutions
    4. Creating a Skin for Firefox
    5. Making sure your theme works with RTL locales
    6. Theme changes in Firefox 2
    7. Theme changes in Firefox 3
    8. Theme changes in Firefox 3.5
    9. Theme changes in Firefox 4
  40. Updating an extension to support multiple Mozilla applications
  41. Using IO Timeout And Interrupt On NT
  42. Using SSH to connect to CVS
  43. Using workers in extensions
  44. WebVR
    1. WebVR
    2. WebVR environment setup
  45. XQuery
  46. XUL Booster
  47. XUL Parser in Python