Index: src/orca/Gecko.py
===================================================================
--- src/orca/Gecko.py	(revision 3001)
+++ src/orca/Gecko.py	(working copy)
@@ -40,8 +40,10 @@
 import braillegenerator
 import debug
 import default
+import gobject
 import input_event
 import keybindings
+import liveregions as live
 import mag
 import orca
 import orca_state
@@ -127,6 +129,9 @@
 # contain to be considered a match in go to next/prev large object
 largeObjectTextLength = 75
 
+# Whether or not Orca should speak live region changes.
+liveRegionsOn = True
+
 # Roles that imply their text starts on a new line.
 #
 NEWLINE_ROLES = [rolenames.ROLE_PARAGRAPH,
@@ -1421,7 +1426,6 @@
         bookmarks.Bookmarks.__init__(self, script)
         self._currentbookmarkindex = {}
         
-        
     def addBookmark(self, inputEvent):
         """ Add an in-page accessible object bookmark for this key and
         webpage URI. """ 
@@ -1775,6 +1779,10 @@
         #
         self._objectForFocusGrab = None
         
+        # Create the live region manager and start the message manager
+        self.liveMngr = live.LiveRegionManager(self)
+        gobject.idle_add(self.liveMngr.pumpMessages, priority=gobject.PRIORITY_LOW)
+        
         # We don't want to prevent the user from arrowing into an
         # autocomplete when it appears in a search form.  We need to
         # keep track if one has appeared or disappeared.
@@ -2153,6 +2161,28 @@
                 #
                 _("Goes to next table."))
 
+        self.inputEventHandlers["goPreviousLiveRegion"] = \
+            input_event.InputEventHandler(
+                Script.goPreviousLiveRegion,
+                # Translators: this is for navigating between live regions
+                #
+                _("Goes to previous live region."))
+
+        self.inputEventHandlers["goNextLiveRegion"] = \
+            input_event.InputEventHandler(
+                Script.goNextLiveRegion,
+                # Translators: this is for navigating between live regions
+                #
+                _("Goes to next live region."))
+                
+        self.inputEventHandlers["advanceLivePriority"] = \
+            input_event.InputEventHandler(
+                Script.advanceLivePriority,
+                # Translators: this is for advancing the live regions 
+                # politeness setting
+                #
+                _("Advance live region politeness setting."))
+
         self.inputEventHandlers["toggleCaretNavigationHandler"] = \
             input_event.InputEventHandler(
                 Script.toggleCaretNavigation,
@@ -2189,8 +2219,6 @@
                 # interrupted.
                 #
                 _("Speaks entire document."))
-                
-        
 
     def getListeners(self):
         """Sets up the AT-SPI event listeners for this script.
@@ -2205,6 +2233,8 @@
             self.onDocumentLoadStopped
         listeners["object:visible-data-changed"]            = \
             self.onVisibleDataChanged
+        listeners["object:children-changed"]                = \
+            self.onChildrenChanged
 
         # [[[TODO: HACK - WDW we need to accomodate Gecko's incorrect
         # use of underscores instead of dashes until they fix their bug.
@@ -2212,7 +2242,7 @@
         #
         listeners["object:property-change:accessible_value"] = \
             self.onValueChanged
-
+        
         return listeners
 
     def __getArrowBindings(self):
@@ -2633,6 +2663,33 @@
 
         keyBindings.add(
             keybindings.KeyBinding(
+                "r",
+                (1 << atspi.Accessibility.MODIFIER_SHIFT \
+                 | 1 << atspi.Accessibility.MODIFIER_ALT \
+                 | 1 << atspi.Accessibility.MODIFIER_CONTROL),
+                1 << atspi.Accessibility.MODIFIER_SHIFT,
+                self.inputEventHandlers["goPreviousLiveRegion"]))
+
+        keyBindings.add(
+            keybindings.KeyBinding(
+                "r",
+                (1 << atspi.Accessibility.MODIFIER_SHIFT \
+                 | 1 << atspi.Accessibility.MODIFIER_ALT \
+                 | 1 << atspi.Accessibility.MODIFIER_CONTROL),
+                0,
+                self.inputEventHandlers["goNextLiveRegion"]))
+
+        keyBindings.add(
+            keybindings.KeyBinding(
+                "y",
+                (1 << atspi.Accessibility.MODIFIER_SHIFT \
+                 | 1 << atspi.Accessibility.MODIFIER_ALT \
+                 | 1 << atspi.Accessibility.MODIFIER_CONTROL),
+                0,
+                self.inputEventHandlers["advanceLivePriority"]))
+
+        keyBindings.add(
+            keybindings.KeyBinding(
                 "F12",
                 1 << settings.MODIFIER_ORCA,
                 1 << settings.MODIFIER_ORCA,
@@ -3459,6 +3516,9 @@
         # If text is deleted from an object, we want to trash our
         # cache of the unicode text.
         #
+        
+    #    print 'onTextDeleted', event.type, event.source.text.getText(0,-1), event.source.attributes
+        
         try:
             del event.source.unicodeText
         except:
@@ -3495,13 +3555,28 @@
         # If text is inserted into an object, we want to trash our
         # cache of the unicode text.
         #
+       # print 'onTextInserted', event.type, event.source.role, event.source.text.getText(0,-1), event.source.attributes
+        if liveRegionsOn and self.isLiveRegion(event.source):
+            self.liveMngr.handleEvent(event)
+            return
+        
         try:
             del event.source.unicodeText
         except:
             pass
 
         default.Script.onTextInserted(self, event)
+        
+    def isLiveRegion(self, obj):
+        attrs = obj.attributes
+        if attrs is None:
+            return False
+        for attr in attrs:
+            if attr.startswith('container-live:'):
+                return True
 
+        return False
+
     def onDocumentReload(self, event):
         """Called when the reload button is hit for a web page."""
         # We care about the main document and we'll ignore document
@@ -3875,6 +3950,12 @@
             self.updateBraille(obj)
             self.speakContents(
                 self.getLineContentsAtOffset(obj, characterOffset))
+                
+    def onChildrenChanged(self, event):
+     #   print 'onChildrenChanged', event.type
+        if event.type.startswith('object:children-changed:add:system'):
+            if liveRegionsOn and self.isLiveRegion(event.source):
+                self.liveMngr.handleEvent(event)
 
     def handleProgressBarUpdate(self, event, obj):
         """Determine whether this progress bar event should be spoken or not.
@@ -4642,7 +4723,7 @@
                 obj = obj.parent
 
         return False
-            
+
     def isAriaWidget(self, obj=None):
         obj = obj or orca_state.locusOfFocus
         
@@ -8451,6 +8532,63 @@
             #
             speech.speak(_("Not in a table."))
 
+    def goNextLiveRegion(self, inputEvent):
+      wrap = True
+      [obj, wrapped] = self.findNextByPredicate(self.__matchLiveRegion, wrap)
+      if wrapped:
+          # Translators: when the user is attempting to locate a
+          # particular object and the bottom of the web page has been
+          # reached without that object being found, we "wrap" to the
+          # top of the page and continuing looking downwards. We need
+          # to inform the user when this is taking place.
+          #
+          speech.speak(_("Wrapping to top."))
+      if obj:
+          [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
+          self.setCaretPosition(obj, characterOffset)
+          self.updateBraille(obj)
+          self.outlineAccessible(obj)
+          self.speakContents(self.getObjectContentsAtOffset(obj,
+                                                            characterOffset))
+      else:
+          # Translators: this is for navigating HTML in a structural
+          # manner, where a 'live region' is a location in a web page
+          # that are updated without having to refresh the entire page.
+          #
+          speech.speak(_("No more live regions."))
+
+    def goPreviousLiveRegion(self, inputEvent):
+      wrap = True
+      [obj, wrapped] = self.findPrevByPredicate(self.__matchLiveRegion, wrap)
+      if wrapped:
+          # Translators: when the user is attempting to locate a
+          # particular object and the bottom of the web page has been
+          # reached without that object being found, we "wrap" to the
+          # top of the page and continuing looking downwards. We need
+          # to inform the user when this is taking place.
+          #
+          speech.speak(_("Wrapping to top."))
+      if obj:
+          [obj, characterOffset] = self.findFirstCaretContext(obj, 0)
+          self.setCaretPosition(obj, characterOffset)
+          self.updateBraille(obj)
+          self.outlineAccessible(obj)
+          self.speakContents(self.getObjectContentsAtOffset(obj,
+                                                            characterOffset))
+      else:
+          # Translators: this is for navigating HTML in a structural
+          # manner, where a 'live region' is a location in a web page
+          # that are updated without having to refresh the entire page.
+          #
+          speech.speak(_("No more live regions."))
+
+    def advanceLivePriority(self, inputEvent):
+        
+        if liveRegionsOn:
+            self.liveMngr.advanceOverride(orca_state.locusOfFocus)
+        else:
+            speech.speak(_("Live region support is off"))
+
     def toggleCaretNavigation(self, inputEvent):
         """Toggles between Firefox native and Orca caret navigation."""
 
@@ -8536,4 +8674,14 @@
                 return False
         else:
             return False
+
+    def __matchLiveRegion(self, obj):
+        attrs = obj.attributes
+        if attrs is None:
+            return False
+        for attr in attrs:
+            if attr.startswith('live:'):
+                return True
+        return False
+
  
Index: src/orca/Makefile.am
===================================================================
--- src/orca/Makefile.am	(revision 3001)
+++ src/orca/Makefile.am	(working copy)
@@ -32,6 +32,7 @@
 	J2SE-access-bridge.py \
 	keybindings.py \
 	keynames.py \
+        liveregions.py \
 	mag.py \
 	orca.py \
 	orca_console_prefs.py \
