Index: src/orca/scripts/toolkits/Gecko/script.py
===================================================================
--- src/orca/scripts/toolkits/Gecko/script.py	(revision 4094)
+++ src/orca/scripts/toolkits/Gecko/script.py	(working copy)
@@ -3124,23 +3124,12 @@
         """Determines if we should look any further at the object
         for flat review."""
 
-        # [[[TODO: HACK - WDW Gecko has issues about the SHOWING
-        # state of objects, especially those in document frames.
-        # It tells us the content in tabs that are not showing
-        # is actually showing.  See:
-        #
-        # http://bugzilla.gnome.org/show_bug.cgi?id=408071
-        #
-        # To work around this, we do a little extra check.  If
-        # the obj is a document, and it's not the one that
-        # Firefox is currently showing the user, we skip it.
-        #
-        pursue = default.Script.pursueForFlatReview(self, obj)
-        if pursue and (obj.getRole() == pyatspi.ROLE_DOCUMENT_FRAME):
-            documentFrame = self.getDocumentFrame()
-            pursue = obj == documentFrame
+        if not obj:
+            return False
 
-        return pursue
+        state = obj.getState()
+        return state.contains(pyatspi.STATE_SHOWING) \
+               and state.contains(pyatspi.STATE_VISIBLE)
 
     def getHeadingLevel(self, obj):
         """Determines the heading level of the given object.  A value
Index: src/orca/flat_review.py
===================================================================
--- src/orca/flat_review.py	(revision 4094)
+++ src/orca/flat_review.py	(working copy)
@@ -1301,6 +1301,105 @@
 
         return descendants
 
+    def getShowingCells(self, treeTable):
+        """Given a tree table, returns a list of accessible children
+        that are actually showing/visible/pursable for flat review.
+        """
+
+        if not treeTable and treeTable.getRole() == pyatspi.ROLE_TREE_TABLE:
+            return []
+
+        showingCells = []
+
+        # First figure out what columns are visible as there's no point
+        # in examining cells which we know won't be visible.
+        # 
+        visibleColumns = []
+        if treeTable[0].getRole() == pyatspi.ROLE_LIST:
+            for index, header in enumerate(treeTable[0]):
+                if self.script.pursueForFlatReview(header):
+                    visibleColumns.append(index)
+                    showingCells.append(header)
+
+        if not len(visibleColumns):
+            return []
+
+        # Now that we know in which columns we can expect to find visible
+        # cells, try to *quickly* locate the first visible row. While not
+        # necessary in small tree tables, it really pays off in large ones
+        # e.g. message lists with multiple thousands of items.
+        #
+        table = treeTable.queryTable()
+        visibleRow = -1
+
+        # 1. If we have one or more selected items, odds are fairly good
+        #    (although not guaranteed) that one of those items happens to
+        #    be showing.
+        #
+        selectedRows = table.getSelectedRows()
+        for row in selectedRows:
+            acc = table.getAccessibleAt(row, visibleColumns[0])
+            if acc and self.script.pursueForFlatReview(acc):
+                visibleRow = row
+                break
+
+        # 2. If we don't have a selected item, calculate how many rows can
+        #    fit given the current dimensions of this tree table. Then do
+        #    a check every so many rows to find a visible row.
+        #
+        try:
+            tableExtents = treeTable.queryComponent().getExtents(0)
+            acc = table.getAccessibleAt(0, visibleColumns[0])
+            cellExtents = acc.queryComponent().getExtents(0)
+        except:
+            # If we can't figure out how far to scroll, we have no business
+            # guessing.
+            #
+            rowIncrement = table.nRows
+        else:
+            rowIncrement = max(1, tableExtents.height / cellExtents.height)
+            if visibleRow < 0:
+                for row in range(0, table.nRows, rowIncrement):
+                    acc = table.getAccessibleAt(row, visibleColumns[0])
+                    if acc and self.script.pursueForFlatReview(acc):
+                        visibleRow = row
+                        break
+
+        # Hopefully we have a visible row now. Unfortunately, due to our
+        # attempts at being clever, we don't know if this is the first
+        # visible row or not. So scroll back one screen full, and check
+        # just one (known visible) column to locate the first one.
+        #
+        firstRow = max(0, visibleRow - rowIncrement)
+        for row in range(firstRow, table.nRows):
+            acc = table.getAccessibleAt(row, visibleColumns[0])
+            if acc and self.script.pursueForFlatReview(acc):
+                visibleRow = row
+                break
+
+        # Phew! Assuming we have a visible row, start adding the cells
+        # to our list of showing cells. We don't have to go any further
+        # than this screen.
+        #
+        for row in range(visibleRow, rowIncrement + visibleRow + 1):
+            acc = table.getAccessibleAt(row, visibleColumns[0])
+            # Having verified once and for all that the cell in the
+            # first visible column of this row is worth pursuing,
+            # and having already verified the visible columns of
+            # this table, just tack on the rest of the row.
+            #
+            if acc and self.script.pursueForFlatReview(acc):
+                showingCells.append(acc)
+                for col in visibleColumns[1:len(visibleColumns)]:
+                    showingCells.append(table.getAccessibleAt(row, col))
+
+        # And if that wasn't good enough, just return the empty list
+        # taking solace in the knowledge that our efforts were indeed
+        # valiant and let the original child-by-child examination do
+        # its thang.
+        #
+        return showingCells
+
     def getShowingZones(self, root):
         """Returns a list of all interesting, non-intersecting, regions
         that are drawn on the screen.  Each element of the list is the
@@ -1385,11 +1484,16 @@
             pass
         
         stateset = root.getState()
-        if stateset.contains(pyatspi.STATE_MANAGES_DESCENDANTS) \
-           and (root.childCount > 50):
-            for child in self.getShowingDescendants(root):
+        children = []
+        if root.childCount > 50:
+            if stateset.contains(pyatspi.STATE_MANAGES_DESCENDANTS):
+                children = self.getShowingDescendants(root)
+            elif root.getRole() == pyatspi.ROLE_TREE_TABLE:
+                children = self.getShowingCells(root)
+            for child in children:
                 zones.extend(self.getShowingZones(child))
-        else:
+
+        if not len(children):
             for i in range(0, root.childCount):
                 child = root.getChildAtIndex(i)
                 if child == root:
