Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Fri, 24 Feb 2012 13:26:30 -0800
changeset 105886 1a9e91a88a5488d15b39a0530c326fdb1e1ce77b
parent 105885 d85d370124470821649071bcc537fdb96eeed133 (current diff)
parent 87627 58dd942011a81f3149d9bc34e808806bda099056 (diff)
child 105887 ebd61b600176d9fe2cfef187ae028515ee4f722a
push id23447
push userdanderson@mozilla.com
push dateTue, 11 Sep 2012 17:34:27 +0000
treeherderautoland@fdfaef738a00 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge from mozilla-central.
accessible/src/base/nsAccessible.cpp
b2g/chrome/jar.mn
browser/app/profile/firefox.js
browser/base/content/browser.js
build/mobile/devicemanagerADB.py
build/mobile/devicemanagerSUT.py
caps/src/nsNullPrincipal.cpp
caps/src/nsPrincipal.cpp
caps/src/nsSystemPrincipal.cpp
config/autoconf.mk.in
configure.in
content/base/public/nsContentUtils.h
content/base/src/nsContentAreaDragDrop.cpp
content/base/src/nsContentUtils.cpp
content/base/src/nsDOMAttribute.cpp
content/base/src/nsDocument.cpp
content/base/src/nsGenericDOMDataNode.h
content/base/src/nsGenericElement.h
content/base/src/nsRange.cpp
content/base/test/Makefile.in
content/canvas/src/Makefile.in
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/html/content/src/nsHTMLSelectElement.cpp
content/html/content/src/nsTextEditorState.cpp
content/smil/nsSMILAnimationFunction.cpp
content/smil/nsSMILAnimationFunction.h
content/smil/nsSMILCompositor.cpp
content/smil/nsSMILCompositor.h
content/smil/nsSMILParserUtils.cpp
content/smil/nsSMILTimedElement.cpp
content/svg/content/src/SVGMotionSMILAnimationFunction.cpp
content/xslt/src/xpath/nsXPathNamespace.cpp
content/xul/templates/src/nsXULContentBuilder.cpp
docshell/base/nsDocShell.cpp
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/base/nsFocusManager.cpp
dom/base/nsFocusManager.h
dom/base/nsJSEnvironment.cpp
dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsPluginsDirWin.cpp
dom/plugins/ipc/PluginProcessChild.cpp
dom/src/storage/nsDOMStorage.cpp
editor/libeditor/base/SplitElementTxn.cpp
editor/libeditor/base/nsEditor.cpp
editor/libeditor/text/nsPlaintextDataTransfer.cpp
embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
extensions/auth/nsAuthSSPI.cpp
extensions/spellcheck/src/mozEnglishWordUtils.cpp
extensions/spellcheck/src/mozEnglishWordUtils.h
extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
extensions/spellcheck/src/mozInlineSpellWordUtil.h
gfx/angle/README.mozilla
gfx/gl/GLContext.cpp
gfx/gl/GLContext.h
gfx/gl/GLContextProviderEGL.cpp
gfx/thebes/genUnicodeScriptData.pl
gfx/thebes/gfxDWriteFonts.cpp
gfx/thebes/gfxFT2Fonts.cpp
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxGDIFont.cpp
gfx/thebes/gfxGDIFontList.cpp
gfx/thebes/gfxHarfBuzzShaper.cpp
gfx/thebes/gfxMacFont.cpp
gfx/thebes/gfxPangoFonts.cpp
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatformFontList.cpp
gfx/thebes/gfxScriptItemizer.cpp
gfx/thebes/gfxScriptItemizer.h
gfx/thebes/gfxUnicodeProperties.cpp
gfx/thebes/gfxUnicodeProperties.h
gfx/thebes/gfxUnicodePropertyData.cpp
gfx/thebes/gfxUnicodeScriptCodes.h
gfx/thebes/gfxWindowsPlatform.h
intl/hyphenation/public/nsHyphenator.h
intl/hyphenation/src/nsHyphenator.cpp
intl/unicharutil/public/nsIUGenDetailCategory.h
intl/unicharutil/src/cattable.h
intl/unicharutil/tools/gencattable.pl
js/src/configure.in
js/src/jsanalyze.cpp
js/src/jsanalyze.h
js/src/jsapi-tests/Makefile.in
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsbool.cpp
js/src/jsfriendapi.cpp
js/src/jsgc.cpp
js/src/jsproxy.cpp
js/src/jsproxy.h
js/src/jsprvtd.h
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsstr.cpp
js/src/jswrapper.cpp
js/src/jswrapper.h
js/src/jsxdrapi.h
js/src/methodjit/Compiler.cpp
js/src/shell/js.cpp
js/src/vm/RegExpObject-inl.h
js/src/vm/RegExpObject.cpp
js/src/vm/RegExpObject.h
js/src/vm/Stack.cpp
js/src/vm/Stack.h
js/src/vm/String.cpp
js/src/vm/String.h
js/xpconnect/loader/mozJSComponentLoader.cpp
js/xpconnect/src/Makefile.in
js/xpconnect/src/dom_quickstubs.qsconf
layout/base/nsBidiPresUtils.cpp
layout/base/nsPresShell.cpp
layout/build/nsLayoutModule.cpp
layout/generic/nsFrame.cpp
layout/generic/nsSelection.cpp
layout/generic/nsTextFrameThebes.cpp
layout/reftests/bugs/reftest.list
layout/reftests/svg/reftest.list
layout/reftests/svg/smil/reftest.list
layout/style/Declaration.cpp
layout/style/StyleRule.cpp
layout/style/nsAnimationManager.cpp
layout/style/nsCSSDataBlock.h
layout/style/nsCSSParser.cpp
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSScanner.cpp
layout/style/nsCSSValue.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleAnimation.cpp
layout/style/nsStyleContext.cpp
layout/style/nsStyleCoord.cpp
layout/style/nsStyleStruct.cpp
layout/svg/base/src/nsSVGTextFrame.cpp
mobile/android/base/GeckoAppShell.java
mobile/android/base/Makefile.in
mobile/xul/app/mobile.js
modules/libpref/src/init/all.js
netwerk/base/src/nsAutodialWin.cpp
netwerk/base/src/nsAutodialWin.h
netwerk/base/src/nsSocketTransportService2.cpp
netwerk/protocol/http/SpdySession.cpp
netwerk/protocol/http/SpdySession.h
netwerk/protocol/http/nsHttpConnection.cpp
netwerk/protocol/http/nsHttpConnection.h
netwerk/protocol/http/nsHttpConnectionMgr.cpp
netwerk/protocol/http/nsHttpConnectionMgr.h
netwerk/protocol/http/nsHttpHandler.cpp
netwerk/protocol/http/nsHttpHandler.h
netwerk/system/win32/nsNotifyAddrListener.cpp
netwerk/system/win32/nsNotifyAddrListener.h
toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp
uriloader/exthandler/win/nsMIMEInfoWin.cpp
widget/windows/GfxInfo.cpp
widget/windows/nsNativeThemeWin.cpp
widget/windows/nsUXThemeData.cpp
widget/windows/nsUXThemeData.h
widget/windows/nsWindow.cpp
widget/windows/nsWindowGfx.cpp
widget/windows/nsWindowGfx.h
widget/xpwidgets/GfxInfoX11.cpp
widget/xpwidgets/GfxInfoX11.h
xpcom/base/nsCycleCollector.cpp
xpcom/base/nsStackWalk.cpp
xpcom/glue/nsTArray-inl.h
xpcom/io/SpecialSystemDirectory.cpp
xpcom/io/nsLocalFileWin.cpp
xpcom/io/nsLocalFileWin.h
xpcom/threads/nsProcess.h
xpcom/threads/nsProcessCommon.cpp
xpfe/appshell/src/nsContentTreeOwner.cpp
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -848,16 +848,21 @@ nsAccessible::ChildAtPoint(PRInt32 aX, P
   nsIContent* content = nsnull;
   if (!foundFrame || !(content = foundFrame->GetContent()))
     return fallbackAnswer;
 
   // Get accessible for the node with the point or the first accessible in
   // the DOM parent chain.
   nsDocAccessible* contentDocAcc = GetAccService()->
     GetDocAccessible(content->OwnerDoc());
+
+  // contentDocAcc in some circumstances can be NULL
+  // See https://bugzilla.mozilla.org/show_bug.cgi?id=729861
+  NS_ENSURE_TRUE(contentDocAcc, fallbackAnswer);
+
   nsAccessible* accessible = contentDocAcc->GetAccessibleOrContainer(content);
   if (!accessible)
     return fallbackAnswer;
 
   if (accessible == this) {
     // Manually walk through accessible children and see if the are within this
     // point. Skip offscreen or invisible accessibles. This takes care of cases
     // where layout won't walk into things for us, such as image map areas and
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -101,16 +101,17 @@ pref("browser.sessionstore.resume_from_c
 pref("browser.sessionstore.interval", 10000); // milliseconds
 pref("browser.sessionstore.max_tabs_undo", 1);
 
 /* these should help performance */
 pref("mozilla.widget.force-24bpp", true);
 pref("mozilla.widget.use-buffer-pixmap", true);
 pref("mozilla.widget.disable-native-theme", true);
 pref("layout.reflow.synthMouseMove", false);
+pref("dom.send_after_paint_to_content", true);
 
 /* download manager (don't show the window or alert) */
 pref("browser.download.useDownloadDir", true);
 pref("browser.download.folderList", 1); // Default to ~/Downloads
 pref("browser.download.manager.showAlertOnComplete", false);
 pref("browser.download.manager.showAlertInterval", 2000);
 pref("browser.download.manager.retention", 2);
 pref("browser.download.manager.showWhenStarting", false);
@@ -348,19 +349,16 @@ pref("urlclassifier.gethashnoise", 4);
 // The list of tables that use the gethash request to confirm partial results.
 pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
 
 // If an urlclassifier table has not been updated in this number of seconds,
 // a gethash request will be forced to check that the result is still in
 // the database.
 pref("urlclassifier.confirm-age", 2700);
 
-// Maximum size of the sqlite3 cache during an update, in bytes
-pref("urlclassifier.updatecachemax", 4194304);
-
 // URL for checking the reason for a malware warning.
 pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
 #endif
 
 // True if this is the first time we are showing about:firstrun
 pref("browser.firstrun.show.uidiscovery", true);
 pref("browser.firstrun.show.localepicker", true);
 
@@ -387,16 +385,17 @@ pref("security.fileuri.strict_origin_pol
 // Temporarily force-enable GL compositing.  This is default-disabled
 // deep within the bowels of the widgetry system.  Remove me when GL
 // compositing isn't default disabled in widget/android.
 pref("layers.acceleration.force-enabled", true);
 
 // screen.enabled and screen.brightness properties.
 pref("dom.screenEnabledProperty.enabled", true);
 pref("dom.screenBrightnessProperty.enabled", true);
+pref("dom.mozScreenWhitelist", "http://localhost:7777");
 
 // handle links targeting new windows
 // 1=current window/tab, 2=new window, 3=new tab in most recent window
 pref("browser.link.open_newwindow", 3);
 
 // 0: no restrictions - divert everything
 // 1: don't divert window.open at all
 // 2: don't divert window.open with features
@@ -425,14 +424,18 @@ pref("media.realtime_decoder.enabled", t
 // secondary bug isn't really worth investigating since it's obseleted
 // by bug 710563.
 pref("layout.frame_rate.precise", true);
 
 // Temporary remote js console hack
 pref("b2g.remote-js.enabled", true);
 pref("b2g.remote-js.port", 9999);
 
+// Handle hardware buttons in the b2g chrome package
+pref("b2g.keys.menu.enabled", true);
+pref("b2g.keys.search.enabled", false);
+
 // Screen timeout in minutes
 pref("power.screen.timeout", 60);
 
 pref("full-screen-api.enabled", true);
 
 pref("media.volume.steps", 10);
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -32,16 +32,33 @@ XPCOMUtils.defineLazyGetter(Services, 'i
            .getService(Ci.nsIIdleService);
 });
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'fm', function(){
   return Cc['@mozilla.org/focus-managr;1']
            .getService(Ci.nsFocusManager);
 });
 
+
+#ifndef MOZ_WIDGET_GONK
+// In order to use http:// scheme instead of file:// scheme
+// (that is much more restricted) the following code kick-off
+// a local http server listening on http://127.0.0.1:7777 and
+// http://localhost:7777.
+function startupHttpd(baseDir, port) {
+  const httpdURL = 'chrome://browser/content/httpd.js';
+  let httpd = {};
+  Services.scriptloader.loadSubScript(httpdURL, httpd);
+  let server = new httpd.nsHttpServer();
+  server.registerDirectory('/', new LocalFile(baseDir));
+  server.registerContentType('appcache', 'text/cache-manifest');
+  server.start(port);
+}
+#endif
+
 // FIXME Bug 707625
 // until we have a proper security model, add some rights to
 // the pre-installed web applications
 // XXX never grant 'content-camera' to non-gaia apps
 function addPermissions(urls) {
   let permissions = [
     'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app', 'content-camera'
   ];
@@ -100,17 +117,31 @@ var shell = {
     window.addEventListener('mozfullscreenchange', this);
     this.contentBrowser.addEventListener('load', this, true);
 
     try {
       Services.io.offline = false;
 
       let fileScheme = 'file://';
       if (homeURL.substring(0, fileScheme.length) == fileScheme) {
+#ifndef MOZ_WIDGET_GONK
+        homeURL = homeURL.replace(fileScheme, '');
+
+        let baseDir = homeURL.split('/');
+        baseDir.pop();
+        baseDir = baseDir.join('/');
+
+        const SERVER_PORT = 7777;
+        startupHttpd(baseDir, SERVER_PORT);
+
+        let baseHost = 'http://localhost';
+        homeURL = homeURL.replace(baseDir, baseHost + ':' + SERVER_PORT);
+#else
         homeURL = 'http://localhost:7777' + homeURL.replace(fileScheme, '');
+#endif
       }
       addPermissions([homeURL]);
     } catch (e) {
       let msg = 'Fatal error during startup: [' + e + '[' + homeURL + ']';
       return alert(msg);
     }
 
     // Load webapi.js as a frame script
@@ -208,20 +239,22 @@ var shell = {
               return;
             this.doCommand('cmd_close');
             break;
         }
         break;
       case 'AppCommand':
         switch (evt.command) {
           case 'Menu':
-            this.sendEvent(content, 'menu');
+            if (Services.prefs.getBoolPref('b2g.keys.menu.enabled'))
+              this.sendEvent(content, 'menu');
             break;
           case 'Search':
-            this.toggleDebug();
+            if (Services.prefs.getBoolPref('b2g.keys.search.enabled'))
+              this.toggleDebug();
             break;
           case 'VolumeUp':
             this.changeVolume(1);
             break;
           case 'VolumeDown':
             this.changeVolume(-1);
             break;
         }
--- a/b2g/chrome/content/shell.xul
+++ b/b2g/chrome/content/shell.xul
@@ -15,16 +15,23 @@
         onload="shell.start();"
         onunload="shell.stop();">
 
   <script type="application/javascript" src="chrome://browser/content/commandUtil.js"/>
   <script type="application/javascript" src="chrome://browser/content/shell.js"/>
 #ifndef MOZ_TOUCH
   <script type="application/javascript" src="chrome://browser/content/touch.js"/>
 #endif
+#ifndef MOZ_WIDGET_GONK
+  <script type="application/javascript" src="chrome://browser/content/httpd.js"/>
+#endif
 
   <commandset id="mainCommandSet">
     <command id="cmd_close" oncommand="CommandUpdater.doCommand(this.id);"/>
   </commandset>
 
-  <browser id="homescreen" type="content-primary" flex="1" style="overflow: hidden;"/>
+  <browser id="homescreen"
+           type="content-primary"
+           flex="1"
+           style="overflow: hidden;"
+           src="data:text/html;base64,PCFET0NUWVBFIGh0bWw+PGh0bWw+PGJvZHkgc3R5bGU9ImJhY2tncm91bmQ6YmxhY2s7Ij48L2JvZHk+PC9odG1sPgo="/>
 </window>
 
--- a/b2g/chrome/content/webapi.js
+++ b/b2g/chrome/content/webapi.js
@@ -79,16 +79,28 @@ XPCOMUtils.defineLazyGetter(Services, 'f
   let isKeyboardOpened = false;
   
   function fireEvent(type, details) {
     let event = content.document.createEvent('CustomEvent');
     event.initCustomEvent(type, true, true, details ? details : {});
     content.dispatchEvent(event);
   }
 
+  function maybeShowIme(targetElement) {
+    // FIXME/bug 729623: work around apparent bug in the IME manager
+    // in gecko.
+    let readonly = targetElement.getAttribute('readonly');
+    if (readonly)
+      return false;
+
+    let type = targetElement.type;
+    fireEvent('showime', { type: type });
+    return true;
+  }
+
   let constructor = {
     handleEvent: function vkm_handleEvent(evt) {
       switch (evt.type) {
         case 'keypress':
           if (evt.keyCode != evt.DOM_VK_ESCAPE || !isKeyboardOpened)
             return;
 
           fireEvent('hideime');
@@ -97,31 +109,28 @@ XPCOMUtils.defineLazyGetter(Services, 'f
           evt.preventDefault();
           evt.stopPropagation();
           break;
 
         case 'mousedown':
           if (evt.target != activeElement || isKeyboardOpened)
             return;
 
-          let type = activeElement.type;
-          fireEvent('showime', { type: type });
-          isKeyboardOpened = true;
+          isKeyboardOpened = maybeShowIme(activeElement);
           break;
       }
     },
     observe: function vkm_observe(subject, topic, data) {
       let shouldOpen = parseInt(data);
       if (shouldOpen && !isKeyboardOpened) {
         activeElement = Services.fm.focusedElement;
-        if (!activeElement)
+        if (!activeElement || !maybeShowIme(activeElement)) {
+          activeElement = null;
           return;
-
-        let type = activeElement.type;
-        fireEvent('showime', { type: type });
+        }
       } else if (!shouldOpen && isKeyboardOpened) {
         fireEvent('hideime');
       }
       isKeyboardOpened = shouldOpen;
     }
   };
 
   Services.obs.addObserver(constructor, 'ime-enabled-state-changed', false);
@@ -308,17 +317,17 @@ const KineticPanning = {
   _position: new Point(0, 0),
   _velocity: new Point(0, 0),
   _acceleration: new Point(0, 0),
 
   get active() {
     return this.target !== null;
   },
 
-  _target: null,
+  target: null,
   start: function kp_start(target) {
     this.target = target;
 
     // Calculate the initial velocity of the movement based on user input
     let momentums = this.momentums.slice(-kSamples);
 
     let distance = new Point(0, 0);
     momentums.forEach(function(momentum) {
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -1,21 +1,23 @@
 #filter substitution
 
 chrome.jar:
 % content branding %content/branding/
 % content browser %content/
 
 * content/shell.xul                     (content/shell.xul)
-  content/shell.js                      (content/shell.js)
+* content/shell.js                      (content/shell.js)
 #ifndef MOZ_TOUCH
   content/touch.js                      (content/touch.js)
 #endif
   content/commandUtil.js                (content/commandUtil.js)
+#ifndef MOZ_WIDGET_GONK
   content/httpd.js                      (content/httpd.js)
+#endif
   content/webapi.js                     (content/webapi.js)
   content/content.css                   (content/content.css)
 
 % override chrome://global/content/netError.xhtml chrome://browser/content/netError.xhtml
 % override chrome://global/skin/netError.css chrome://browser/content/netError.css
   content/netError.xhtml                (content/netError.xhtml)
   content/netError.css                  (content/netError.css)
   content/images/errorpage-larry-black.png (content/images/errorpage-larry-black.png)
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -754,22 +754,16 @@ pref("urlclassifier.gethashnoise", 4);
 // The list of tables that use the gethash request to confirm partial results.
 pref("urlclassifier.gethashtables", "goog-phish-shavar,goog-malware-shavar");
 
 // If an urlclassifier table has not been updated in this number of seconds,
 // a gethash request will be forced to check that the result is still in
 // the database.
 pref("urlclassifier.confirm-age", 2700);
 
-// Maximum size of the sqlite3 cache during an update, in bytes
-pref("urlclassifier.updatecachemax", 41943040);
-
-// Maximum size of the sqlite3 cache for lookups, in bytes
-pref("urlclassifier.lookupcachemax", 1048576);
-
 // URL for checking the reason for a malware warning.
 pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
 
 #endif
 
 pref("browser.EULA.version", 3);
 pref("browser.rights.version", 3);
 pref("browser.rights.3.shown", false);
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -160,50 +160,44 @@ var StarUI = {
     if (this._overlayLoading)
       return;
 
     if (this._overlayLoaded) {
       this._doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition);
       return;
     }
 
-    var loadObserver = {
-      _self: this,
-      _itemId: aItemId,
-      _anchorElement: aAnchorElement,
-      _position: aPosition,
-      observe: function (aSubject, aTopic, aData) {
+    this._overlayLoading = true;
+    document.loadOverlay(
+      "chrome://browser/content/places/editBookmarkOverlay.xul",
+      (function (aSubject, aTopic, aData) {
         //XXX We just caused localstore.rdf to be re-applied (bug 640158)
         retrieveToolbarIconsizesFromTheme();
 
-        this._self._overlayLoading = false;
-        this._self._overlayLoaded = true;
-        this._self._doShowEditBookmarkPanel(this._itemId, this._anchorElement,
-                                            this._position);
-      }
-    };
-    this._overlayLoading = true;
-    document.loadOverlay("chrome://browser/content/places/editBookmarkOverlay.xul",
-                         loadObserver);
+        // Move the header (star, title, button) into the grid,
+        // so that it aligns nicely with the other items (bug 484022).
+        let header = this._element("editBookmarkPanelHeader");
+        let rows = this._element("editBookmarkPanelGrid").lastChild;
+        rows.insertBefore(header, rows.firstChild);
+        header.hidden = false;
+
+        this._overlayLoading = false;
+        this._overlayLoaded = true;
+        this._doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition);
+      }).bind(this)
+    );
   },
 
   _doShowEditBookmarkPanel:
   function SU__doShowEditBookmarkPanel(aItemId, aAnchorElement, aPosition) {
     if (this.panel.state != "closed")
       return;
 
     this._blockCommands(); // un-done in the popuphiding handler
 
-    // Move the header (star, title, possibly a button) into the grid,
-    // so that it aligns nicely with the other items (bug 484022).
-    var rows = this._element("editBookmarkPanelGrid").lastChild;
-    var header = this._element("editBookmarkPanelHeader");
-    rows.insertBefore(header, rows.firstChild);
-    header.hidden = false;
-
     // Set panel title:
     // if we are batching, i.e. the bookmark has been added now,
     // then show Page Bookmarked, else if the bookmark did already exist,
     // we are about editing it, then use Edit This Bookmark.
     this._element("editBookmarkPanelTitle").value =
       this._batching ?
         gNavigatorBundle.getString("editBookmarkPanel.pageBookmarkedTitle") :
         gNavigatorBundle.getString("editBookmarkPanel.editBookmarkTitle");
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3568,17 +3568,16 @@ const BrowserSearch = {
    */
   get searchBar() {
     return document.getElementById("searchbar");
   },
 
   loadAddEngines: function BrowserSearch_loadAddEngines() {
     var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
     var where = newWindowPref == 3 ? "tab" : "window";
-    var regionBundle = document.getElementById("bundle_browser_region");
     var searchEnginesURL = formatURL("browser.search.searchEnginesURL", true);
     openUILinkIn(searchEnginesURL, where);
   }
 }
 
 function FillHistoryMenu(aParent) {
   // Lazily add the hover listeners on first showing and never remove them
   if (!aParent.hasStatusListener) {
--- a/browser/components/migration/src/FirefoxProfileMigrator.js
+++ b/browser/components/migration/src/FirefoxProfileMigrator.js
@@ -219,17 +219,16 @@ FirefoxProfileMigrator.prototype = {
    * @param   aStartup
    *          non-null if called during startup.
    * @param   aProfile
    *          profile directory path to migrate from
    */
   migrate : function Firefox_migrate(aItems, aStartup, aProfile)
   {
     if (aStartup) {
-      aStartup.doStartup();
       this._replaceBookmarks = true;
     }
 
     Services.obs.notifyObservers(null, "Migration:Started", null);
 
     // Reset pending count.  If this count becomes 0, "Migration:Ended"
     // notification is sent
     this._pendingCount = 1;
@@ -241,16 +240,21 @@ FirefoxProfileMigrator.prototype = {
       this._migrateCookies();
 
     if (aItems & MIGRATOR.BOOKMARKS)
       this._migrateBookmarks();
 
     if (aItems & MIGRATOR.PASSWORDS)
       this._migratePasswords();
 
+    // The password manager encryption key must be copied before startup.
+    if (aStartup) {
+      aStartup.doStartup();
+    }
+
     if (aItems & MIGRATOR.FORMDATA)
       this._migrateFormData();
 
     if (--this._pendingCount == 0) {
       // When async imports are immediately completed unfortunately,
       // this will be called.
       // Usually, this notification is sent by _notifyCompleted()
       Services.obs.notifyObservers(null, "Migration:Ended", null);
--- a/browser/components/search/content/engineManager.js
+++ b/browser/components/search/content/engineManager.js
@@ -148,42 +148,43 @@ var gEngineManagerDialog = {
     var alias = { value: selectedEngine.alias };
     var strings = document.getElementById("engineManagerBundle");
     var title = strings.getString("editTitle");
     var msg = strings.getFormattedString("editMsg", [selectedEngine.name]);
 
     while (Services.prompt.prompt(window, title, msg, alias, null, {})) {
       var bduplicate = false;
       var eduplicate = false;
+      var dupName = "";
 
       if (alias.value != "") {
         try {
           let bmserv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
                        getService(Ci.nsINavBookmarksService);
           if (bmserv.getURIForKeyword(alias.value))
             bduplicate = true;
         } catch(ex) {}
 
         // Check for duplicates in changes we haven't committed yet
         let engines = gEngineView._engineStore.engines;
         for each (let engine in engines) {
           if (engine.alias == alias.value &&
               engine.name != selectedEngine.name) {
             eduplicate = true;
+            dupName = engine.name;
             break;
           }
         }
       }
 
       // Notify the user if they have chosen an existing engine/bookmark keyword
       if (eduplicate || bduplicate) {
         var dtitle = strings.getString("duplicateTitle");
         var bmsg = strings.getString("duplicateBookmarkMsg");
-        var emsg = strings.getFormattedString("duplicateEngineMsg",
-                                              [engine.name]);
+        var emsg = strings.getFormattedString("duplicateEngineMsg", [dupName]);
 
         Services.prompt.alert(window, dtitle, eduplicate ? emsg : bmsg);
       } else {
         gEngineView._engineStore.changeEngine(selectedEngine, "alias",
                                               alias.value);
         gEngineView.invalidate();
         break;
       }
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -45,19 +45,19 @@
 <!DOCTYPE bindings [
 <!ENTITY % searchBarDTD SYSTEM "chrome://browser/locale/searchbar.dtd" >
 %searchBarDTD;
 <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
 %browserDTD;
 ]>
 
 <bindings id="SearchBindings"
-      xmlns="http://www.mozilla.org/xbl"
-      xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-      xmlns:xbl="http://www.mozilla.org/xbl">
+          xmlns="http://www.mozilla.org/xbl"
+          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+          xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="searchbar">
     <resources>
       <stylesheet src="chrome://browser/content/search/searchbarBindings.css"/>
       <stylesheet src="chrome://browser/skin/searchbar.css"/>
     </resources>
     <content>
       <xul:stringbundle src="chrome://browser/locale/search.properties"
@@ -91,23 +91,22 @@
                             oncommand="openManager(event);"/>
             </xul:menupopup>
           </xul:button>
         </xul:box>
         <xul:hbox class="search-go-container">
           <xul:image class="search-go-button"
                      anonid="search-go-button"
                      onclick="handleSearchCommand(event);"
-                     tooltiptext="&searchEndCap.label;" />
+                     tooltiptext="&searchEndCap.label;"/>
         </xul:hbox>
       </xul:textbox>
     </content>
 
     <implementation implements="nsIObserver">
-
       <constructor><![CDATA[
         if (this.parentNode.parentNode.localName == "toolbarpaletteitem")
           return;
         setTimeout(function (a) { a.init(); }, 0, this);
       ]]></constructor>
 
       <method name="init">
         <body><![CDATA[
@@ -159,17 +158,17 @@
       <field name="searchButton">document.getAnonymousElementByAttribute(this,
           "anonid", "searchbar-engine-button");</field>
 
       <property name="currentEngine"
                 onset="this.searchService.currentEngine = val; return val;">
         <getter><![CDATA[
           var currentEngine = this.searchService.currentEngine;
           // Return a dummy engine if there is no currentEngine
-          return currentEngine || {name:"", uri:null};
+          return currentEngine || {name: "", uri: null};
         ]]></getter>
       </property>
 
       <!-- textbox is used by sanitize.js to clear the undo history when
            clearing form information. -->
       <property name="textbox" readonly="true"
                 onget="return this._textbox;"/>
 
@@ -330,17 +329,18 @@
             this.rebuildPopup();
 
           var popup = this._popup;
           // Clear any addengine menuitems, including addengine-item entries and
           // the addengine-separator.  Work backward to avoid invalidating the
           // indexes as items are removed.
           var items = popup.childNodes;
           for (var i = items.length - 1; i >= 0; i--) {
-            if (items[i].getAttribute("class").indexOf("addengine") != -1)
+            if (items[i].classList.contains("addengine-item") ||
+                items[i].classList.contains("addengine-separator"))
               popup.removeChild(items[i]);
           }
 
           var addengines = getBrowser().mCurrentBrowser.engines;
           if (addengines && addengines.length > 0) {
             const kXULNS =
                "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
@@ -439,17 +439,17 @@
       </method>
 
       <method name="selectEngine">
         <parameter name="aEvent"/>
         <parameter name="isNextEngine"/>
         <body><![CDATA[
           // Find the new index
           var newIndex = this.engines.indexOf(this.currentEngine);
-          newIndex += (isNextEngine) ? 1 : -1;
+          newIndex += isNextEngine ? 1 : -1;
 
           if (newIndex >= 0 && newIndex < this.engines.length)
             this.currentEngine = this.engines[newIndex];
 
           aEvent.preventDefault();
           aEvent.stopPropagation();
         ]]></body>
       </method>
@@ -490,23 +490,22 @@
         <parameter name="aData"/>
         <parameter name="aWhere"/>
         <body><![CDATA[
           // null parameter below specifies HTML response for search
           var submission = this.currentEngine.getSubmission(aData);
           openUILinkIn(submission.uri.spec, aWhere, null, submission.postData);
         ]]></body>
       </method>
-
     </implementation>
 
     <handlers>
       <handler event="command"><![CDATA[
         const target = event.originalTarget;
-        if (target.getAttribute("class").indexOf("addengine-item") != -1) {
+        if (target.classList.contains("addengine-item")) {
           var searchService =
             Components.classes["@mozilla.org/browser/search-service;1"]
                       .getService(Components.interfaces.nsIBrowserSearchService);
           // We only detect OpenSearch files
           var type = Components.interfaces.nsISearchEngine.DATA_XML;
           searchService.addEngine(target.getAttribute("uri"), type,
                                   target.getAttribute("src"), false);
         }
@@ -714,17 +713,17 @@
               document.getBindingParent(this).searchButton.open = true;
               return false;
             }
             return true;
           ]]>
         </body>
       </method>
 
-      <!-- overload |onTextEntered| in autocomplete.xml -->
+      <!-- override |onTextEntered| in autocomplete.xml -->
       <method name="onTextEntered">
         <parameter name="aEvent"/>
         <body><![CDATA[
           var evt = aEvent || this.mEnterEvent;
           document.getBindingParent(this).handleSearchCommand(evt);
           this.mEnterEvent = null;
         ]]></body>
       </method>
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -159,16 +159,17 @@
 @BINPATH@/components/dom_events.xpt
 @BINPATH@/components/dom_geolocation.xpt
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
+@BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_sms.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_traversal.xpt
 @BINPATH@/components/dom_xbl.xpt
 @BINPATH@/components/dom_xpath.xpt
--- a/browser/locales/Makefile.in
+++ b/browser/locales/Makefile.in
@@ -164,21 +164,21 @@ libs:: $(addsuffix .xml,$(SEARCH_PLUGINS
 	$(NSINSTALL) -D $(FINAL_TARGET)/searchplugins
 	for SEARCH_PLUGIN in $^; do\
 	  SEARCH_PLUGIN_BASE=`basename $$SEARCH_PLUGIN`;\
 	  $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \
 	    $$SEARCH_PLUGIN > $(FINAL_TARGET)/searchplugins/$$SEARCH_PLUGIN_BASE; \
 	done
 
 install:: $(addsuffix .xml,$(SEARCH_PLUGINS))
-	$(NSINSTALL) -D $(DESTDIR)$mozappdir/searchplugins
+	$(NSINSTALL) -D $(DESTDIR)$(mozappdir)/searchplugins
 	for i in $^; do \
 	  SEARCH_PLUGIN_BASE=`basename $$SEARCH_PLUGIN`;\
 	  $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) \
-	    $$SEARCH_PLUGIN > $(DESTDIR)$mozappdir/searchplugins/$$SEARCH_PLUGIN_BASE; \
+	    $$SEARCH_PLUGIN > $(DESTDIR)$(mozappdir)/searchplugins/$$SEARCH_PLUGIN_BASE; \
 	done
 
 
 libs-%:
 	$(NSINSTALL) -D $(DIST)/install
 	@$(MAKE) -C ../../toolkit/locales libs-$* BOTH_MANIFESTS=1
 	@$(MAKE) -C ../../services/sync/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
 	@$(MAKE) -C ../../extensions/spellcheck/locales AB_CD=$* XPI_NAME=locale-$* BOTH_MANIFESTS=1
--- a/browser/locales/en-US/chrome/browser/places/places.properties
+++ b/browser/locales/en-US/chrome/browser/places/places.properties
@@ -70,23 +70,23 @@ recentlyBookmarkedTitle=Recently Bookmar
 recentTagsTitle=Recent Tags
 
 OrganizerQueryHistory=History
 OrganizerQueryDownloads=Downloads
 OrganizerQueryAllBookmarks=All Bookmarks
 OrganizerQueryTags=Tags
 
 # LOCALIZATION NOTE (tagResultLabel) :
-# This is what we use to form the label (for screen readers)
-# for url bar autocomplete results of type "tag"
+# Noun used to describe the location bar autocomplete result type
+# to users with screen readers
 # See createResultLabel() in urlbarBindings.xml 
 tagResultLabel=Tag
 # LOCALIZATION NOTE (bookmarkResultLabel) :
-# This is what we use to form the label (for screen readers)
-# for url bar autocomplete results of type "bookmark"
+# Noun used to describe the location bar autocomplete result type
+# to users with screen readers
 # See createResultLabel() in urlbarBindings.xml 
 bookmarkResultLabel=Bookmark
 
 # LOCALIZATION NOTE (lockPrompt.text)
 # %S will be replaced with the application name.
 lockPrompt.title=Browser Startup Error
 lockPrompt.text=The bookmarks and history system will not be functional because one of %S's files is in use by another application. Some security software can cause this problem.
 lockPromptInfoButton.label=Learn More
--- a/build/mobile/devicemanager.py
+++ b/build/mobile/devicemanager.py
@@ -56,28 +56,36 @@ class DMError(Exception):
   "generic devicemanager exception."
 
   def __init__(self, msg= ''):
     self.msg = msg
 
   def __str__(self):
     return self.msg
 
-
 def abstractmethod(method):
   line = method.func_code.co_firstlineno
   filename = method.func_code.co_filename
   def not_implemented(*args, **kwargs):
     raise NotImplementedError('Abstract method %s at File "%s", line %s '
                               'should be implemented by a concrete class' %
                               (repr(method), filename,line))
   return not_implemented
-  
+
 class DeviceManager:
-  
+
+  @abstractmethod
+  def shell(self, cmd, outputfile, env=None, cwd=None):
+    """
+    executes shell command on device
+    returns:
+    success: Return code from command
+    failure: None
+    """
+
   @abstractmethod
   def pushFile(self, localname, destname):
     """
     external function
     returns:
     success: True
     failure: False
     """
@@ -163,35 +171,37 @@ class DeviceManager:
   @abstractmethod
   def getProcessList(self):
     """
     external function
     returns:
     success: array of process tuples
     failure: None
     """
-    
+
   @abstractmethod
   def fireProcess(self, appname, failIfRunning=False):
     """
     external function
+    DEPRECATED: Use shell() or launchApplication() for new code
     returns:
     success: pid
     failure: None
     """
-    
+
   @abstractmethod
   def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
     """
     external function
+    DEPRECATED: Use shell() or launchApplication() for new code
     returns:
     success: output filename
     failure: None
     """
-    
+
   def communicate(self, process, timeout = 600, interval = 5):
     """
     loops until 'process' has exited or 'timeout' seconds is reached
     loop sleeps for 'interval' seconds between iterations
     external function
     returns:
     success: [file contents, None]
     failure: [None, None]
@@ -576,8 +586,40 @@ class NetworkTools:
           if seed > maxportnum:
             print "Could not find open port after checking 5000 ports"
           raise
         seed += 1
     except:
       print "Socket error trying to find open port"
         
     return seed
+
+def _pop_last_line(file):
+  '''
+  Utility function to get the last line from a file (shared between ADB and
+  SUT device managers). Function also removes it from the file. Intended to
+  strip off the return code from a shell command.
+  '''
+  bytes_from_end = 1
+  file.seek(0, 2)
+  length = file.tell() + 1
+  while bytes_from_end <= length:
+    file.seek((-1)*bytes_from_end, 2)
+    data = file.read()
+
+    if bytes_from_end == length and len(data) == 0: # no data, return None
+      return None
+
+    if data[0] == '\n' or bytes_from_end == length:
+      # found the last line, which should have the return value
+      if data[0] == '\n':
+        data = data[1:]
+
+      # truncate off the return code line
+      file.truncate(length - bytes_from_end)
+      file.seek(0,2)
+      file.write('\0')
+
+      return data
+
+    bytes_from_end += 1
+
+  return None
--- a/build/mobile/devicemanagerADB.py
+++ b/build/mobile/devicemanagerADB.py
@@ -1,10 +1,10 @@
 import subprocess
-from devicemanager import DeviceManager, DMError
+from devicemanager import DeviceManager, DMError, _pop_last_line
 import re
 import os
 import sys
 import tempfile
 
 class DeviceManagerADB(DeviceManager):
 
   def __init__(self, host = None, port = 20701, retrylimit = 5, packageName = None):
@@ -58,16 +58,57 @@ class DeviceManagerADB(DeviceManager):
         # to check again ourselves that we have root now.
         verifyRoot()
       except:
         if (self.useRunAs):
           print "restarting as root failed, but run-as available"
         else:
           print "restarting as root failed"
 
+  # external function: executes shell command on device
+  # returns:
+  # success: <return code>
+  # failure: None
+  def shell(self, cmd, outputfile, env=None, cwd=None):
+    # need to quote special characters here
+    for (index, arg) in enumerate(cmd):
+      if arg.find(" ") or arg.find("(") or arg.find(")") or arg.find("\""):
+        cmd[index] = '\'%s\'' % arg
+
+    # This is more complex than you'd think because adb doesn't actually
+    # return the return code from a process, so we have to capture the output
+    # to get it
+    # FIXME: this function buffers all output of the command into memory,
+    # always. :(
+    cmdline = subprocess.list2cmdline(cmd) + "; echo $?"
+
+    # prepend cwd and env to command if necessary
+    if cwd:
+      cmdline = "cd %s; %s" % (cwd, cmdline)
+    if env:
+      envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems()))
+      cmdline = envstr + "; " + cmdline
+
+    # all output should be in stdout
+    proc = subprocess.Popen(["adb", "shell", cmdline],
+                            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    (stdout, stderr) = proc.communicate()
+    outputfile.write(stdout.rstrip('\n'))
+
+    lastline = _pop_last_line(outputfile)
+    if lastline:
+      m = re.search('([0-9]+)', lastline)
+      if m:
+        return_code = m.group(1)
+        outputfile.seek(-2, 2)
+        outputfile.truncate() # truncate off the return code
+        return return_code
+
+    return None
+
   # external function
   # returns:
   #  success: True
   #  failure: False
   def pushFile(self, localname, destname):
     try:
       if (os.name == "nt"):
         destname = destname.replace('\\', '/')
@@ -259,27 +300,29 @@ class DeviceManagerADB(DeviceManager):
     ret = []
     while (proc):
       els = proc.split()
       ret.append(list([els[1], els[len(els) - 1], els[0]]))
       proc =  p.stdout.readline()
     return ret
 
   # external function
+  # DEPRECATED: Use shell() or launchApplication() for new code
   # returns:
   #  success: pid
   #  failure: None
   def fireProcess(self, appname, failIfRunning=False):
     #strip out env vars
     parts = appname.split('"');
     if (len(parts) > 2):
       parts = parts[2:]
     return self.launchProcess(parts, failIfRunning)
 
   # external function
+  # DEPRECATED: Use shell() or launchApplication() for new code
   # returns:
   #  success: output filename
   #  failure: None
   def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
     if cmd[0] == "am":
       self.checkCmd(["shell"] + cmd)
       return outputFile
 
@@ -322,16 +365,17 @@ class DeviceManagerADB(DeviceManager):
   #  success: output from testagent
   #  failure: None
   def killProcess(self, appname):
     procs = self.getProcessList()
     for (pid, name, user) in procs:
       if name == appname:
         p = self.runCmdAs(["shell", "kill", pid])
         return p.stdout.read()
+
     return None
 
   # external function
   # returns:
   #  success: filecontents
   #  failure: None
   def catFile(self, remoteFile):
     #p = self.runCmd(["shell", "cat", remoteFile])
@@ -606,17 +650,17 @@ class DeviceManagerADB(DeviceManager):
 
   def runCmd(self, args):
     # If we are not root but have run-as, and we're trying to execute 
     # a shell command then using run-as is the best we can do
     if (not self.haveRoot and self.useRunAs and args[0] == "shell" and args[1] != "run-as"):
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
     args.insert(0, "adb")
-    return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
   def runCmdAs(self, args):
     if self.useRunAs:
       args.insert(1, "run-as")
       args.insert(2, self.packageName)
     return self.runCmd(args)
 
   def checkCmd(self, args):
--- a/build/mobile/devicemanagerSUT.py
+++ b/build/mobile/devicemanagerSUT.py
@@ -42,17 +42,28 @@ import SocketServer
 import time, datetime
 import os
 import re
 import hashlib
 import subprocess
 from threading import Thread
 import traceback
 import sys
-from devicemanager import DeviceManager, DMError, FileError, NetworkTools
+import StringIO
+from devicemanager import DeviceManager, DMError, FileError, NetworkTools, _pop_last_line
+
+class AgentError(Exception):
+  "SUTAgent-specific exception."
+
+  def __init__(self, msg= '', fatal = False):
+    self.msg = msg
+    self.fatal = fatal
+
+  def __str__(self):
+    return self.msg
 
 class DeviceManagerSUT(DeviceManager):
   host = ''
   port = 0
   debug = 2 
   retries = 0
   tempRoot = os.getcwd()
   base_prompt = '$>'
@@ -71,196 +82,237 @@ class DeviceManagerSUT(DeviceManager):
   def __init__(self, host, port = 20701, retrylimit = 5):
     self.host = host
     self.port = port
     self.retrylimit = retrylimit
     self.retries = 0
     self._sock = None
     self.getDeviceRoot()
 
-  def cmdNeedsResponse(self, cmd):
+  def _cmdNeedsResponse(self, cmd):
     """ Not all commands need a response from the agent:
         * if the cmd matches the pushRE then it is the first half of push
           and therefore we want to wait until the second half before looking
           for a response
         * rebt obviously doesn't get a response
         * uninstall performs a reboot to ensure starting in a clean state and
           so also doesn't look for a response
     """
     noResponseCmds = [re.compile('^push .*$'),
                       re.compile('^rebt'),
                       re.compile('^uninst .*$'),
                       re.compile('^pull .*$')]
 
     for c in noResponseCmds:
       if (c.match(cmd)):
         return False
-    
+
     # If the command is not in our list, then it gets a response
     return True
 
-  def shouldCmdCloseSocket(self, cmd):
+  def _stripPrompt(self, data):
+    '''
+    internal function
+    take a data blob and strip instances of the prompt '$>\x00'
+    '''
+    promptre = re.compile(self.prompt_regex + '.*')
+    retVal = []
+    lines = data.split('\n')
+    for line in lines:
+      foundPrompt = False
+      try:
+        while (promptre.match(line)):
+          foundPrompt = True
+          pieces = line.split(self.prompt_sep)
+          index = pieces.index('$>')
+          pieces.pop(index)
+          line = self.prompt_sep.join(pieces)
+      except(ValueError):
+        pass
+
+      # we don't want to append lines that are blank after stripping the
+      # prompt (those are basically "prompts")
+      if not foundPrompt or line:
+        retVal.append(line)
+
+    return '\n'.join(retVal)
+
+  def _shouldCmdCloseSocket(self, cmd):
     """ Some commands need to close the socket after they are sent:
     * push
     * rebt
     * uninst
     * quit
     """
-    
     socketClosingCmds = [re.compile('^push .*$'),
                          re.compile('^quit.*'),
                          re.compile('^rebt.*'),
                          re.compile('^uninst .*$')]
 
     for c in socketClosingCmds:
       if (c.match(cmd)):
         return True
 
     return False
 
-  # convenience function to enable checks for agent errors
-  def verifySendCMD(self, cmdline, newline = True):
-    return self.sendCMD(cmdline, newline, False)
-
-
-  #
-  # create a wrapper for sendCMD that loops up to self.retrylimit iterations.
-  # this allows us to move the retry logic outside of the _doCMD() to make it 
-  # easier for debugging in the future.
-  # note that since cmdline is a list of commands, they will all be retried if
-  # one fails.  this is necessary in particular for pushFile(), where we don't want
-  # to accidentally send extra data if a failure occurs during data transmission.
-  #
-  def sendCMD(self, cmdline, newline = True, ignoreAgentErrors = True):
+  def sendCmds(self, cmdlist, outputfile, timeout = None, newline = True):
+    '''
+    a wrapper for _doCmds that loops up to self.retrylimit iterations.
+    this allows us to move the retry logic outside of the _doCmds() to make it
+    easier for debugging in the future.
+    note that since cmdlist is a list of commands, they will all be retried if
+    one fails.  this is necessary in particular for pushFile(), where we don't want
+    to accidentally send extra data if a failure occurs during data transmission.
+    '''
     done = False
-    while (not done):
-      retVal = self._doCMD(cmdline, newline)
-      if (retVal is None):
+    while self.retries < self.retrylimit:
+      try:
+        self._doCmds(cmdlist, outputfile, timeout, newline)
+        return
+      except AgentError, err:
+        # re-raise error if it's fatal (i.e. the device got the command but
+        # couldn't execute it). retry otherwise
+        if err.fatal:
+          raise err
+        if self.debug >= 2:
+          print err
         self.retries += 1
-      else:
-        self.retries = 0
-        if ignoreAgentErrors == False:
-          if (self.agentErrorRE.match(retVal)):
-            raise DMError("error on the agent executing '%s'" % cmdline)
-        return retVal
+
+    raise AgentError("unable to connect to %s after %s attempts" % (self.host, self.retrylimit))
 
-      if (self.retries >= self.retrylimit):
-        done = True
+  def runCmds(self, cmdlist, timeout = None, newline = True):
+    '''
+    similar to sendCmds, but just returns any output as a string instead of
+    writing to a file. this is normally what you want to call to send a set
+    of commands to the agent
+    '''
+    outputfile = StringIO.StringIO()
+    self.sendCmds(cmdlist, outputfile, timeout, newline)
+    outputfile.seek(0)
+    return outputfile.read()
 
-    raise DMError("unable to connect to %s after %s attempts" % (self.host, self.retrylimit))        
-
-  def _doCMD(self, cmdline, newline = True):
+  def _doCmds(self, cmdlist, outputfile, timeout, newline):
     promptre = re.compile(self.prompt_regex + '$')
-    data = ""
     shouldCloseSocket = False
     recvGuard = 1000
 
-    if (self._sock == None):
+    if not self._sock:
       try:
-        if (self.debug >= 1):
+        if self.debug >= 1:
           print "reconnecting socket"
         self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
       except:
         self._sock = None
-        if (self.debug >= 2):
-          print "unable to create socket"
-        return None
-      
+        raise AgentError("unable to create socket")
+
       try:
         self._sock.connect((self.host, int(self.port)))
         self._sock.recv(1024)
       except:
         self._sock.close()
         self._sock = None
-        if (self.debug >= 2):
-          print "unable to connect socket"
-        return None
-    
-    for cmd in cmdline:
+        raise AgentError("unable to connect socket")
+
+    for cmd in cmdlist:
       if newline: cmd += '\r\n'
-      
+
       try:
         numbytes = self._sock.send(cmd)
         if (numbytes != len(cmd)):
-          print "ERROR: our cmd was " + str(len(cmd)) + " bytes and we only sent " + str(numbytes)
-          return None
+          raise AgentError("ERROR: our cmd was %s bytes and we only sent %s" % (len(cmd),
+                                                                                numbytes))
         if (self.debug >= 4): print "send cmd: " + str(cmd)
       except:
         self._sock.close()
         self._sock = None
-        return None
-      
+        return False
+
       # Check if the command should close the socket
-      shouldCloseSocket = self.shouldCmdCloseSocket(cmd)
+      shouldCloseSocket = self._shouldCmdCloseSocket(cmd)
 
       # Handle responses from commands
-      if (self.cmdNeedsResponse(cmd)):
+      if (self._cmdNeedsResponse(cmd)):
         found = False
         loopguard = 0
+        data = ""
 
         while (found == False and (loopguard < recvGuard)):
           temp = ''
           if (self.debug >= 4): print "recv'ing..."
 
           # Get our response
           try:
             temp = self._sock.recv(1024)
             if (self.debug >= 4): print "response: " + str(temp)
           except:
             self._sock.close()
             self._sock = None
-            return None
+            raise AgentError("Error receiving data from socket")
 
           data += temp
 
           # If something goes wrong in the agent it will send back a string that
           # starts with '##AGENT-ERROR##'
           if self.agentErrorRE.match(data):
-            break
+            raise AgentError("Agent Error processing command: %s" % cmd, fatal=True)
 
           for line in data.splitlines():
             if promptre.match(line):
               found = True
               data = self._stripPrompt(data)
               break
 
+          # periodically flush data to output file to make sure it doesn't get
+          # too big/unwieldly
+          if len(data) > 1024:
+              outputfile.write(data[0:1024])
+              data = data[1024:]
+
           # If we violently lose the connection to the device, this loop tends to spin,
           # this guard prevents that
           if (temp == ''):
             loopguard += 1
 
-    if (shouldCloseSocket == True):
+        # Write any remaining data to outputfile
+        outputfile.write(data)
+
+    if shouldCloseSocket:
       try:
         self._sock.close()
         self._sock = None
       except:
         self._sock = None
-        return None
+        raise AgentError("Error closing socket")
+
+  # external function: executes shell command on device
+  # returns:
+  # success: <return code>
+  # failure: None
+  def shell(self, cmd, outputfile, env=None, cwd=None):
+    cmdline = subprocess.list2cmdline(cmd)
+    if env:
+      cmdline = '%s %s' % (self.formatEnvString(env), cmdline)
 
-    return data
-  
-  # internal function
-  # take a data blob and strip instances of the prompt '$>\x00'
-  def _stripPrompt(self, data):
-    promptre = re.compile(self.prompt_regex + '.*')
-    retVal = []
-    lines = data.split('\n')
-    for line in lines:
-      try:
-        while (promptre.match(line)):
-          pieces = line.split(self.prompt_sep)
-          index = pieces.index('$>')
-          pieces.pop(index)
-          line = self.prompt_sep.join(pieces)
-      except(ValueError):
-        pass
-      retVal.append(line)
+    try:
+      if cwd:
+        self.sendCmds(['execcwd %s %s' % (cwd, cmdline)], outputfile)
+      else:
+        self.sendCmds(['exec %s' % cmdline], outputfile)
+    except AgentError:
+      return None
 
-    return '\n'.join(retVal)
-  
+    # dig through the output to get the return code
+    lastline = _pop_last_line(outputfile)
+    if lastline:
+      m = re.search('return code \[([0-9]+)\]', lastline)
+      if m:
+        return m.group(1)
+
+    # woops, we couldn't find an end of line/return value
+    return None
 
   # external function
   # returns:
   #  success: True
   #  failure: False
   def pushFile(self, localname, destname):
     if (os.name == "nt"):
       destname = destname.replace('\\', '/')
@@ -281,18 +333,18 @@ class DeviceManagerSUT(DeviceManager):
     if (self.debug >= 3): print "sending: push " + destname
     
     filesize = os.path.getsize(localname)
     f = open(localname, 'rb')
     data = f.read()
     f.close()
 
     try:
-      retVal = self.verifySendCMD(['push ' + destname + ' ' + str(filesize) + '\r\n', data], newline = False)
-    except(DMError):
+      retVal = self.runCmds(['push ' + destname + ' ' + str(filesize) + '\r\n', data], newline = False)
+    except AgentError:
       retVal = False
   
     if (self.debug >= 3): print "push returned: " + str(retVal)
 
     validated = False
     if (retVal):
       retline = retVal.strip()
       if (retline == None):
@@ -318,18 +370,18 @@ class DeviceManagerSUT(DeviceManager):
   # returns:
   #  success: directory name
   #  failure: None
   def mkDir(self, name):
     if (self.dirExists(name)):
       return name
     else:
       try:
-        retVal = self.verifySendCMD(['mkdr ' + name])
-      except(DMError):
+        retVal = self.runCmds(['mkdr ' + name])
+      except AgentError:
         retVal = None
       return retVal
 
   # make directory structure on the device
   # external function
   # returns:
   #  success: directory structure that we created
   #  failure: None
@@ -371,18 +423,18 @@ class DeviceManagerSUT(DeviceManager):
   # external function
   # returns:
   #  success: True
   #  failure: False
   def dirExists(self, dirname):
     match = ".*" + dirname + "$"
     dirre = re.compile(match)
     try:
-      data = self.verifySendCMD(['cd ' + dirname, 'cwd'])
-    except(DMError):
+      data = self.runCmds(['cd ' + dirname, 'cwd'])
+    except AgentError:
       return False
 
     found = False
     for d in data.splitlines():
       if (dirre.match(d)):
         found = True
 
     return found
@@ -407,107 +459,109 @@ class DeviceManagerSUT(DeviceManager):
   # returns:
   #  success: array of filenames, ['file1', 'file2', ...]
   #  failure: []
   def listFiles(self, rootdir):
     rootdir = rootdir.rstrip('/')
     if (self.dirExists(rootdir) == False):
       return []
     try:
-      data = self.verifySendCMD(['cd ' + rootdir, 'ls'])
-    except(DMError):
+      data = self.runCmds(['cd ' + rootdir, 'ls'])
+    except AgentError:
       return []
 
     files = filter(lambda x: x, data.splitlines())
     if len(files) == 1 and files[0] == '<empty>':
       # special case on the agent: empty directories return just the string "<empty>"
       return []
     return files
 
   # external function
   # returns:
   #  success: output of telnet, i.e. "removing file: /mnt/sdcard/tests/test.txt"
   #  failure: None
   def removeFile(self, filename):
     if (self.debug>= 2): print "removing file: " + filename
     try:
-      retVal = self.verifySendCMD(['rm ' + filename])
-    except(DMError):
+      retVal = self.runCmds(['rm ' + filename])
+    except AgentError:
       return None
 
     return retVal
   
   # does a recursive delete of directory on the device: rm -Rf remoteDir
   # external function
   # returns:
   #  success: output of telnet, i.e. "removing file: /mnt/sdcard/tests/test.txt"
   #  failure: None
   def removeDir(self, remoteDir):
     try:
-      retVal = self.verifySendCMD(['rmdr ' + remoteDir])
-    except(DMError):
+      retVal = self.runCmds(['rmdr ' + remoteDir])
+    except AgentError:
       return None
 
     return retVal
 
   # external function
   # returns:
   #  success: array of process tuples
   #  failure: []
   def getProcessList(self):
     try:
-      data = self.verifySendCMD(['ps'])
-    except DMError:
+      data = self.runCmds(['ps'])
+    except AgentError:
       return []
 
     files = []
     for line in data.splitlines():
       if line:
         pidproc = line.strip().split()
         if (len(pidproc) == 2):
           files += [[pidproc[0], pidproc[1]]]
         elif (len(pidproc) == 3):
           #android returns <userID> <procID> <procName>
           files += [[pidproc[1], pidproc[2], pidproc[0]]]     
     return files
 
   # external function
+  # DEPRECATED: Use shell() or launchApplication() for new code
   # returns:
   #  success: pid
   #  failure: None
   def fireProcess(self, appname, failIfRunning=False):
     if (not appname):
       if (self.debug >= 1): print "WARNING: fireProcess called with no command to run"
       return None
 
     if (self.debug >= 2): print "FIRE PROC: '" + appname + "'"
 
     if (self.processExist(appname) != None):
       print "WARNING: process %s appears to be running already\n" % appname
       if (failIfRunning):
         return None
     
     try:
-      data = self.verifySendCMD(['exec ' + appname])
-    except(DMError):
+      data = self.runCmds(['exec ' + appname])
+    except AgentError:
       return None
 
     # wait up to 30 seconds for process to start up
     timeslept = 0
     while (timeslept <= 30):
       process = self.processExist(appname)
       if (process is not None):
         break
       time.sleep(3)
       timeslept += 3
 
     if (self.debug >= 4): print "got pid: %s for process: %s" % (process, appname)
     return process
 
   # external function
+  # DEPRECATED: Use shell() or launchApplication() for new code
   # returns:
   #  success: output filename
   #  failure: None
   def launchProcess(self, cmd, outputFile = "process.txt", cwd = '', env = '', failIfRunning=False):
     if not cmd:
       if (self.debug >= 1): print "WARNING: launchProcess called without command to run"
       return None
 
@@ -527,46 +581,46 @@ class DeviceManagerSUT(DeviceManager):
     return outputFile
 
   # external function
   # returns:
   #  success: output from testagent
   #  failure: None
   def killProcess(self, appname):
     try:
-      data = self.verifySendCMD(['kill ' + appname])
-    except(DMError):
+      data = self.runCmds(['kill ' + appname])
+    except AgentError:
       return None
 
     return data
 
   # external function
   # returns:
   #  success: tmpdir, string
   #  failure: None
   def getTempDir(self):
     try:
-      data = self.verifySendCMD(['tmpd'])
-    except(DMError):
+      data = self.runCmds(['tmpd'])
+    except AgentError:
       return None
 
     return data.strip()
 
   # external function
   # returns:
   #  success: filecontents
   #  failure: None
   def catFile(self, remoteFile):
     try:
-      data = self.verifySendCMD(['cat ' + remoteFile])
-    except(DMError):
+      data = self.runCmds(['cat ' + remoteFile])
+    except AgentError:
       return None
 
     return data
-  
+
   # external function
   # returns:
   #  success: output of pullfile, string
   #  failure: None
   def pullFile(self, remoteFile):
     """Returns contents of remoteFile using the "pull" command.
     The "pull" command is different from other commands in that DeviceManager
     has to read a certain number of bytes instead of just reading to the
@@ -620,18 +674,18 @@ class DeviceManagerSUT(DeviceManager):
     prompt = self.base_prompt + self.prompt_sep
     buffer = ''
     
     # expected return value:
     # <filename>,<filesize>\n<filedata>
     # or, if error,
     # <filename>,-1\n<error message>
     try:
-      data = self.verifySendCMD(['pull ' + remoteFile])
-    except(DMError):
+      data = self.runCmds(['pull ' + remoteFile])
+    except AgentError:
       return None
 
     # read metadata; buffer the rest
     metadata, sep, buffer = read_until_char('\n', buffer, 'could not find metadata')
     if not metadata:
       return None
     if self.debug >= 3:
       print 'metadata: %s' % metadata
@@ -739,18 +793,18 @@ class DeviceManagerSUT(DeviceManager):
 
   # external function
   # returns:
   #  success: True
   #  failure: False
   #  Throws a FileError exception when null (invalid dir/filename)
   def isDir(self, remotePath):
     try:
-      data = self.verifySendCMD(['isdir ' + remotePath])
-    except(DMError):
+      data = self.runCmds(['isdir ' + remotePath])
+    except AgentError:
       # normally there should be no error here; a nonexistent file/directory will
       # return the string "<filename>: No such file or directory".
       # However, I've seen AGENT-WARNING returned before. 
       return False
 
     retVal = data.strip()
     if not retVal:
       raise FileError('isdir returned null')
@@ -775,18 +829,18 @@ class DeviceManagerSUT(DeviceManager):
   
   # return the md5 sum of a remote file
   # internal function
   # returns:
   #  success: MD5 hash for given filename
   #  failure: None
   def getRemoteHash(self, filename):
     try:
-      data = self.verifySendCMD(['hash ' + filename])
-    except(DMError):
+      data = self.runCmds(['hash ' + filename])
+    except AgentError:
       return None
 
     retVal = None
     if data:
       retVal = data.strip()
     if (self.debug >= 3): print "remote hash returned: '" + retVal + "'"
     return retVal
     
@@ -804,31 +858,31 @@ class DeviceManagerSUT(DeviceManager):
   #       /mochitest
   #
   # external function
   # returns:
   #  success: path for device root
   #  failure: None
   def getDeviceRoot(self):
     try:
-      data = self.verifySendCMD(['testroot'])
+      data = self.runCmds(['testroot'])
     except:
       return None
 
     deviceRoot = data.strip() + '/tests'
 
     if (not self.dirExists(deviceRoot)):
       if (self.mkDir(deviceRoot) == None):
         return None
 
     return deviceRoot
 
   def getAppRoot(self, packageName):
     try:
-      data = self.verifySendCMD(['getapproot '+packageName])
+      data = self.runCmds(['getapproot '+packageName])
     except:
       return None
 
     return data.strip()
 
   # external function
   # returns:
   #  success: output of unzip command
@@ -846,18 +900,18 @@ class DeviceManagerSUT(DeviceManager):
     elif self.fileExists('/' + filename):
       dir = '/' + filename
     elif self.fileExists(devroot + '/' + filename):
       dir = devroot + '/' + filename
     else:
       return None
 
     try:
-      data = self.verifySendCMD(['cd ' + dir, 'unzp ' + filename])
-    except(DMError):
+      data = self.runCmds(['cd ' + dir, 'unzp ' + filename])
+    except AgentError:
       return None
 
     return data
 
   # external function
   # returns:
   #  success: status from test agent
   #  failure: None
@@ -867,28 +921,28 @@ class DeviceManagerSUT(DeviceManager):
     if (self.debug > 3): print "INFO: sending rebt command"
     callbacksvrstatus = None    
 
     if (ipAddr is not None):
     #create update.info file:
       try:
         destname = '/data/data/com.mozilla.SUTAgentAndroid/files/update.info'
         data = "%s,%s\rrebooting\r" % (ipAddr, port)
-        self.verifySendCMD(['push ' + destname + ' ' + str(len(data)) + '\r\n', data], newline = False)
-      except(DMError):
+        self.runCmds(['push ' + destname + ' ' + str(len(data)) + '\r\n', data], newline = False)
+      except AgentError:
         return None
 
       ip, port = self.getCallbackIpAndPort(ipAddr, port)
       cmd += " %s %s" % (ip, port)
       # Set up our callback server
       callbacksvr = callbackServer(ip, port, self.debug)
 
     try:
-      status = self.verifySendCMD([cmd])
-    except(DMError):
+      status = self.runCmds([cmd])
+    except AgentError:
       return None
 
     if (ipAddr is not None):
       status = callbacksvr.disconnect()
 
     if (self.debug > 3): print "INFO: rebt- got status back: " + str(status)
     return status
 
@@ -913,17 +967,17 @@ class DeviceManagerSUT(DeviceManager):
     collapseSpaces = re.compile('  +')
 
     directives = ['os', 'id','uptime','systime','screen','memory','process',
                   'disk','power']
     if (directive in directives):
       directives = [directive]
 
     for d in directives:
-      data = self.verifySendCMD(['info ' + d])
+      data = self.runCmds(['info ' + d])
       if (data is None):
         continue
       data = collapseSpaces.sub(' ', data)
       result[d] = data.split('\n')
 
     # Get rid of any 0 length members of the arrays
     for k, v in result.iteritems():
       result[k] = filter(lambda x: x != '', result[k])
@@ -950,18 +1004,18 @@ class DeviceManagerSUT(DeviceManager):
   # returns:
   #  success: output from agent for inst command
   #  failure: None
   def installApp(self, appBundlePath, destPath=None):
     cmd = 'inst ' + appBundlePath
     if destPath:
       cmd += ' ' + destPath
     try:
-      data = self.verifySendCMD([cmd])
-    except(DMError):
+      data = self.runCmds([cmd])
+    except AgentError:
       return None
 
     f = re.compile('Failure')
     for line in data.split():
       if (f.match(line)):
         return data
     return None
 
@@ -976,18 +1030,18 @@ class DeviceManagerSUT(DeviceManager):
   # returns:
   #  success: True
   #  failure: None
   def uninstallAppAndReboot(self, appName, installPath=None):
     cmd = 'uninst ' + appName
     if installPath:
       cmd += ' ' + installPath
     try:
-      data = self.verifySendCMD([cmd])
-    except(DMError):
+      data = self.runCmds([cmd])
+    except AgentError:
       return None
 
     if (self.debug > 3): print "uninstallAppAndReboot: " + str(data)
     return True
 
   """
   Updates the application on the device.
   Application bundle - path to the application bundle on the device
@@ -1021,18 +1075,18 @@ class DeviceManagerSUT(DeviceManager):
       ip, port = self.getCallbackIpAndPort(ipAddr, port)
       cmd += " %s %s" % (ip, port)
       # Set up our callback server
       callbacksvr = callbackServer(ip, port, self.debug)
 
     if (self.debug >= 3): print "INFO: updateApp using command: " + str(cmd)
 
     try:
-      status = self.verifySendCMD([cmd])
-    except(DMError):
+      status = self.runCmds([cmd])
+    except AgentError:
       return None
 
     if ipAddr is not None:
       status = callbacksvr.disconnect()
 
     if (self.debug >= 3): print "INFO: updateApp: got status back: " + str(status)
 
     return status
@@ -1041,18 +1095,18 @@ class DeviceManagerSUT(DeviceManager):
     return the current time on the device
   """
   # external function
   # returns:
   #  success: time in ms
   #  failure: None
   def getCurrentTime(self):
     try:
-      data = self.verifySendCMD(['clok'])
-    except(DMError):
+      data = self.runCmds(['clok'])
+    except AgentError:
       return None
 
     return data.strip()
 
   """
     Connect the ipaddress and port for a callback ping.  Defaults to current IP address
     And ports starting at 30000.
     NOTE: the detection for current IP address only works on Linux!
@@ -1074,18 +1128,18 @@ class DeviceManagerSUT(DeviceManager):
     elif self.fileExists('/' + filename):
       dir = '/' + filename
     elif self.fileExists(devroot + '/' + filename):
       dir = devroot + '/' + filename
     else:
       return None
 
     try:
-      data = self.verifySendCMD(['cd ' + dir, 'unzp ' + filename])
-    except(DMError):
+      data = self.runCmds(['cd ' + dir, 'unzp ' + filename])
+    except AgentError:
       return None
 
     return data
 
   def getCallbackIpAndPort(self, aIp, aPort):
     ip = aIp
     nettools = NetworkTools()
     if (ip == None):
@@ -1145,19 +1199,19 @@ class DeviceManagerSUT(DeviceManager):
     if (width < 100 or width > 9999):
       return False
 
     if (height < 100 or height > 9999):
       return False
 
     if (self.debug >= 3): print "INFO: adjusting screen resolution to %s, %s and rebooting" % (width, height)
     try:
-      self.verifySendCMD(["exec setprop persist.tegra.dpy%s.mode.width %s" % (screentype, width)])
-      self.verifySendCMD(["exec setprop persist.tegra.dpy%s.mode.height %s" % (screentype, height)])
-    except(DMError):
+      self.runCmds(["exec setprop persist.tegra.dpy%s.mode.width %s" % (screentype, width)])
+      self.runCmds(["exec setprop persist.tegra.dpy%s.mode.height %s" % (screentype, height)])
+    except AgentError:
       return False
 
     return True
 
 gCallbackData = ''
 
 class myServer(SocketServer.TCPServer):
   allow_reuse_address = True
new file mode 100644
--- /dev/null
+++ b/build/mobile/droid.py
@@ -0,0 +1,87 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Test Automation Framework.
+#
+# The Initial Developer of the Original Code is
+# Mozilla foundation
+#
+# Portions created by the Initial Developer are Copyright (C) 2009
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Joel Maher <joel.maher@gmail.com> (Original Developer)
+#   William Lachance <wlachance@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+from devicemanagerADB import DeviceManagerADB
+from devicemanagerSUT import DeviceManagerSUT
+
+class DroidMixin(object):
+  """Mixin to extend DeviceManager with Android-specific functionality"""
+
+  def launchApplication(self, app, activity="App",
+                        intent="android.intent.action.VIEW", env=None,
+                        url=None, extra_args=None):
+    """
+    Launches an Android application
+    returns:
+    success: True
+    failure: False
+    """
+    # only one instance of an application may be running at once
+    if self.processExist(app):
+      return False
+
+    acmd = [ "am", "start", "-a", intent, "-W", "-n", "%s/.%s" % (app, activity)]
+
+    if extra_args:
+      acmd.extend(["--es", "args", " ".join(args)])
+
+    if env:
+      envCnt = 0
+      # env is expected to be a dict of environment variables
+      for envkey, envval in env.iteritems():
+        acmd.extend(["--es", "env" + str(envCnt), envkey + "=" + envval])
+        envCnt += 1
+
+    if url:
+      acmd.extend(["-d", ''.join(['"', url, '"'])])
+
+    # shell output not that interesting and debugging logs should already
+    # show what's going on here... so just create an empty memory buffer
+    # and ignore
+    shellOutput = StringIO.StringIO()
+    if self.shell(acmd, shellOutput) == 0:
+      return True
+
+    return False
+
+class DroidADB(DeviceManagerADB, DroidMixin):
+  pass
+
+class DroidSUT(DeviceManagerSUT, DroidMixin):
+  pass
--- a/build/mobile/sutagent/android/DoCommand.java
+++ b/build/mobile/sutagent/android/DoCommand.java
@@ -131,22 +131,23 @@ public class DoCommand {
 
     String    currentDir = "/";
     String    sErrorPrefix = "##AGENT-WARNING## ";
     boolean bTraceOn = false;
 
     String ffxProvider = "org.mozilla.ffxcp";
     String fenProvider = "org.mozilla.fencp";
 
-    private final String prgVersion = "SUTAgentAndroid Version 1.05";
+    private final String prgVersion = "SUTAgentAndroid Version 1.06";
 
     public enum Command
         {
         RUN ("run"),
         EXEC ("exec"),
+        EXECCWD ("execcwd"),
         ENVRUN ("envrun"),
         KILL ("kill"),
         PS ("ps"),
         DEVINFO ("info"),
         OS ("os"),
         ID ("id"),
         UPTIME ("uptime"),
         SETTIME ("settime"),
@@ -687,17 +688,35 @@ public class DoCommand {
                     {
                     String [] theArgs = new String [Argc - 1];
 
                     for (int lcv = 1; lcv < Argc; lcv++)
                         {
                         theArgs[lcv - 1] = Argv[lcv];
                         }
 
-                    strReturn = StartPrg2(theArgs, cmdOut);
+                    strReturn = StartPrg2(theArgs, cmdOut, null);
+                    }
+                else
+                    {
+                    strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
+                    }
+                break;
+
+            case EXECCWD:
+                if (Argc >= 3)
+                    {
+                    String [] theArgs = new String [Argc - 2];
+
+                    for (int lcv = 2; lcv < Argc; lcv++)
+                        {
+                        theArgs[lcv - 2] = Argv[lcv];
+                        }
+
+                    strReturn = StartPrg2(theArgs, cmdOut, Argv[1]);
                     }
                 else
                     {
                     strReturn = sErrorPrefix + "Wrong number of arguments for " + Argv[0] + " command!";
                     }
                 break;
 
             case RUN:
@@ -1257,16 +1276,21 @@ private void CancelNotification()
 
         return(sRet);
         }
 
     public String GetTestRoot()
         {
         String    sRet = null;
 
+        File tmpFile = new java.io.File("/data/local/tests");
+        if (tmpFile.exists() && tmpFile.isDirectory()) 
+            {
+            return("/data/local");
+            }
         if (Environment.getExternalStorageState().equalsIgnoreCase(Environment.MEDIA_MOUNTED))
             {
             sRet = Environment.getExternalStorageDirectory().getAbsolutePath();
             }
         else
             {
             sRet = GetTmpDir();
             }
@@ -3458,17 +3482,17 @@ private void CancelNotification()
             {
             e.printStackTrace();
             sRet = "Timed out!";
             }
 
         return (sRet);
         }
 
-    public String StartPrg2(String [] progArray, OutputStream out)
+    public String StartPrg2(String [] progArray, OutputStream out, String cwd)
         {
         String sRet = "";
 
         int    nArraySize = 0;
         int    nArgs = progArray.length - 1; // 1st arg is the environment string
         int    lcv    = 0;
         int    temp = 0;
 
@@ -3548,17 +3572,25 @@ private void CancelNotification()
 
             for (Map.Entry<String, String> entry : newEnv.entrySet())
                 {
                 envArray[i++] = entry.getKey() + "=" + entry.getValue();
                 }
 
             if (theArgs[0].contains("/") || theArgs[0].contains("\\") || !theArgs[0].contains("."))
                 {
-                pProc = Runtime.getRuntime().exec(theArgs, envArray);
+                if (cwd != null)
+                    {
+                    File f = new File(cwd);
+                    pProc = Runtime.getRuntime().exec(theArgs, envArray, f);
+                    }
+                else
+                    {
+                    pProc = Runtime.getRuntime().exec(theArgs, envArray);
+                    }
 
                 RedirOutputThread outThrd = new RedirOutputThread(pProc, out);
                 outThrd.start();
 
                 lcv = 0;
 
                 while (lcv < 30) {
                     try {
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -47,17 +47,17 @@ struct JSPrincipals;
 %}
 
 interface nsIURI;
 interface nsIContentSecurityPolicy;
 
 [ptr] native JSContext(JSContext);
 [ptr] native JSPrincipals(JSPrincipals);
 
-[scriptable, uuid(B406A2DB-E547-4C95-B8E2-AD09ECB54CE0)]
+[scriptable, uuid(1f83b0e0-6b63-4bdc-a50a-b9afe256bd25)]
 interface nsIPrincipal : nsISerializable
 {
     /**
      * Values of capabilities for each principal. Order is
      * significant: if an operation is performed on a set
      * of capabilities, the minimum is computed.
      */
     const short ENABLE_DENIED                = 1;
@@ -202,16 +202,22 @@ interface nsIPrincipal : nsISerializable
      * Note for the future: Perhaps we should consider a certificate principal
      * for a given URI subsuming a codebase principal for the same URI?  Not
      * sure what the immediate benefit would be, but I think the setup could
      * make some code (e.g. MaybeDowngradeToCodebase) clearer.
      */
     boolean subsumes(in nsIPrincipal other);
 
     /**
+     * Same as the previous method, subsumes(), but for codebase principals
+     * ignores changes to document.domain.
+     */
+    boolean subsumesIgnoringDomain(in nsIPrincipal other);
+
+    /**
      * Checks whether this principal is allowed to load the network resource
      * located at the given URI under the same-origin policy. This means that
      * codebase principals are only allowed to load resources from the same
      * domain, the system principal is allowed to load anything, and null
      * principals are not allowed to load anything.
      *
      * If the load is allowed this function does nothing. If the load is not
      * allowed the function throws NS_ERROR_DOM_BAD_URI.
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -332,16 +332,22 @@ nsNullPrincipal::Subsumes(nsIPrincipal *
   // We don't subsume anything except ourselves.  Note that nsPrincipal::Equals
   // will return false for us, since we're not about:blank and not Equals to
   // reasonable nsPrincipals.
   *aResult = (aOther == this);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsNullPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
+{
+  return Subsumes(aOther, aResult);
+}
+
+NS_IMETHODIMP
 nsNullPrincipal::CheckMayLoad(nsIURI* aURI, bool aReport)
 {
   if (aReport) {
     nsScriptSecurityManager::ReportError(
       nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mURI, aURI);
   }
 
   return NS_ERROR_DOM_BAD_URI;
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -372,16 +372,22 @@ nsPrincipal::EqualsIgnoringDomain(nsIPri
 }
 
 NS_IMETHODIMP
 nsPrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
 {
   return Equals(aOther, aResult);
 }
 
+NS_IMETHODIMP
+nsPrincipal::SubsumesIgnoringDomain(nsIPrincipal *aOther, bool *aResult)
+{
+  return EqualsIgnoringDomain(aOther, aResult);
+}
+
 static bool
 URIIsLocalFile(nsIURI *aURI)
 {
   bool isFile;
   nsCOMPtr<nsINetUtil> util = do_GetNetUtil();
 
   return util && NS_SUCCEEDED(util->ProtocolHasFlags(aURI,
                                 nsIProtocolHandler::URI_IS_LOCAL_FILE,
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -121,16 +121,23 @@ nsSystemPrincipal::EqualsIgnoringDomain(
 NS_IMETHODIMP
 nsSystemPrincipal::Subsumes(nsIPrincipal *other, bool *result)
 {
     *result = true;
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsSystemPrincipal::SubsumesIgnoringDomain(nsIPrincipal *other, bool *result)
+{
+    *result = true;
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsSystemPrincipal::CheckMayLoad(nsIURI* uri, bool aReport)
 {
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSystemPrincipal::GetHashValue(PRUint32 *result)
 {
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -692,16 +692,18 @@ ANDROID_PLATFORM_TOOLS = @ANDROID_PLATFO
 ANDROID_VERSION   = @ANDROID_VERSION@
 
 ANDROID_PACKAGE_NAME = @ANDROID_PACKAGE_NAME@
 
 JS_SHARED_LIBRARY = @JS_SHARED_LIBRARY@
 
 MOZ_INSTRUMENT_EVENT_LOOP = @MOZ_INSTRUMENT_EVENT_LOOP@
 
+MOZ_SYSTEM_PLY = @MOZ_SYSTEM_PLY@
+
 # We only want to do the pymake sanity on Windows, other os's can cope
 ifeq ($(HOST_OS_ARCH),WINNT)
 # Ensure invariants between GNU Make and pymake
 # Checked here since we want the sane error in a file that
 # actually can be found regardless of path-style.
 ifeq (_:,$(.PYMAKE)_$(findstring :,$(srcdir)))
 $(error Windows-style srcdir being used with GNU make. Did you mean to run $(topsrcdir)/build/pymake/make.py instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake])
 endif
--- a/config/config.mk
+++ b/config/config.mk
@@ -787,18 +787,20 @@ EXPAND_LIBS_EXEC = $(PYTHON) $(topsrcdir
 EXPAND_LIBS_GEN = $(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(DEPTH)/config $(topsrcdir)/config/expandlibs_gen.py
 EXPAND_AR = $(EXPAND_LIBS_EXEC) --extract -- $(AR)
 EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselist -- $(CC)
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
 EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist $(if $(REORDER),--reorder $(REORDER))-- $(LD)
 EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) --uselist $(if $(REORDER),--reorder $(REORDER))-- $(MKSHLIB)
 
 ifdef STDCXX_COMPAT
+ifneq ($(OS_ARCH),Darwin)
 CHECK_STDCXX = objdump -p $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' > /dev/null && echo "TEST-UNEXPECTED-FAIL | | We don't want these libstdc++ symbols to be used:" && objdump -T $(1) | grep -e 'GLIBCXX_3\.4\.\(9\|[1-9][0-9]\)' && exit 1 || exit 0
 endif
+endif
 
 # autoconf.mk sets OBJ_SUFFIX to an error to avoid use before including
 # this file
 OBJ_SUFFIX := $(_OBJ_SUFFIX)
 
 # PGO builds with GCC build objects with instrumentation in a first pass,
 # then objects optimized, without instrumentation, in a second pass. If
 # we overwrite the ojects from the first pass with those from the second,
--- a/configure.in
+++ b/configure.in
@@ -1044,16 +1044,26 @@ else
     AC_MSG_RESULT([yes])
 fi
 
 MOZ_PATH_PROGS(PYTHON, $PYTHON python2.7 python2.6 python2.5 python)
 if test -z "$PYTHON"; then
     AC_MSG_ERROR([python was not found in \$PATH])
 fi
 
+MOZ_ARG_WITH_BOOL(system-ply,
+[  --with-system-ply       Use system installed python ply library],
+    [if $PYTHON -c 'import ply' 2>&5; then
+         MOZ_SYSTEM_PLY=1
+     else
+         AC_MSG_ERROR([python ply library is not found but --with-system-ply was requested])
+     fi])
+
+AC_SUBST(MOZ_SYSTEM_PLY)
+
 if test -z "$COMPILE_ENVIRONMENT"; then
     NSINSTALL_BIN='$(PYTHON) $(topsrcdir)/config/nsinstall.py'
 fi
 AC_SUBST(NSINSTALL_BIN)
 
 MOZ_PATH_PROG(DOXYGEN, doxygen, :)
 MOZ_PATH_PROG(AUTOCONF, autoconf, :)
 MOZ_PATH_PROGS(UNZIP, unzip)
@@ -3713,30 +3723,33 @@ fi
 dnl Checks for library functions.
 dnl ========================================================
 AC_PROG_GCC_TRADITIONAL
 AC_FUNC_MEMCMP
 AC_CHECK_FUNCS(random strerror lchown fchmod snprintf statvfs memmove rint stat64 lstat64 truncate64 statvfs64 setbuf isatty)
 AC_CHECK_FUNCS(flockfile getpagesize)
 AC_CHECK_FUNCS(localtime_r strtok_r)
 
-dnl check for clock_gettime(), the CLOCK_MONOTONIC clock, and -lrt
-_SAVE_LDFLAGS=$LDFLAGS
-LDFLAGS="$LDFLAGS -lrt"
-AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC) and -lrt,
-               ac_cv_have_clock_monotonic,
-               [AC_TRY_LINK([#include <time.h>],
-                            [ struct timespec ts;
-                              clock_gettime(CLOCK_MONOTONIC, &ts); ],
-                            ac_cv_have_clock_monotonic=yes,
-                            ac_cv_have_clock_monotonic=no)])
-LDFLAGS=$_SAVE_LDFLAGS
-if test "$ac_cv_have_clock_monotonic" = "yes"; then
+dnl check for clock_gettime(), the CLOCK_MONOTONIC clock
+AC_CACHE_CHECK(for clock_gettime(CLOCK_MONOTONIC),
+               ac_cv_clock_monotonic,
+               [for libs in "" -lrt; do
+                    _SAVE_LDFLAGS="$LDFLAGS"
+                    LDFLAGS="$LDFLAGS $libs"
+                    AC_TRY_LINK([#include <time.h>],
+                                 [ struct timespec ts;
+                                   clock_gettime(CLOCK_MONOTONIC, &ts); ],
+                                 ac_cv_clock_monotonic=$libs
+                                 break,
+                                 ac_cv_clock_monotonic=no)
+                    LDFLAGS="$_SAVE_LDFLAGS"
+                done])
+if test "$ac_cv_clock_monotonic" != "no"; then
     HAVE_CLOCK_MONOTONIC=1
-    REALTIME_LIBS=-lrt
+    REALTIME_LIBS=$ac_cv_clock_monotonic
     AC_DEFINE(HAVE_CLOCK_MONOTONIC)
     AC_SUBST(HAVE_CLOCK_MONOTONIC)
     AC_SUBST(REALTIME_LIBS)
 fi
 
 dnl check for wcrtomb/mbrtowc
 dnl =======================================================================
 if test -z "$MACOS_DEPLOYMENT_TARGET" || test "$MACOS_DEPLOYMENT_TARGET" -ge "100300"; then
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -126,17 +126,16 @@ class nsIWordBreaker;
 class nsIJSRuntimeService;
 class nsEventListenerManager;
 class nsIScriptContext;
 class nsIRunnable;
 class nsIInterfaceRequestor;
 template<class E> class nsCOMArray;
 template<class K, class V> class nsRefPtrHashtable;
 struct JSRuntime;
-class nsIUGenCategory;
 class nsIWidget;
 class nsIDragSession;
 class nsIPresShell;
 class nsIXPConnectJSObjectHolder;
 #ifdef MOZ_XTF
 class nsIXTFService;
 #endif
 #ifdef IBMBIDI
@@ -620,21 +619,16 @@ public:
     return sLineBreaker;
   }
 
   static nsIWordBreaker* WordBreaker()
   {
     return sWordBreaker;
   }
 
-  static nsIUGenCategory* GetGenCat()
-  {
-    return sGenCat;
-  }
-
   /**
    * Regster aObserver as a shutdown observer. A strong reference is held
    * to aObserver until UnregisterShutdownObserver is called.
    */
   static void RegisterShutdownObserver(nsIObserver* aObserver);
   static void UnregisterShutdownObserver(nsIObserver* aObserver);
 
   /**
@@ -2012,17 +2006,16 @@ private:
   static nsIStringBundleService* sStringBundleService;
   static nsIStringBundle* sStringBundles[PropertiesFile_COUNT];
 
   static nsIContentPolicy* sContentPolicyService;
   static bool sTriedToGetContentPolicy;
 
   static nsILineBreaker* sLineBreaker;
   static nsIWordBreaker* sWordBreaker;
-  static nsIUGenCategory* sGenCat;
 
   static nsIScriptRuntime* sScriptRuntimes[NS_STID_ARRAY_UBOUND];
   static PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND];
   static PRUint32 sJSGCThingRootCount;
 
 #ifdef IBMBIDI
   static nsIBidiKeyboard* sBidiKeyboard;
 #endif
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -686,16 +686,17 @@ DragDataProducer::Produce(nsDOMDataTrans
     if (*aSelection) {
       rv = nsCopySupport::GetTransferableForSelection(*aSelection, doc,
                                                       getter_AddRefs(transferable));
     }
     else {
       rv = nsCopySupport::GetTransferableForNode(nodeToSerialize, doc,
                                                  getter_AddRefs(transferable));
     }
+    NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsISupportsString> data;
     PRUint32 dataSize;
     rv = transferable->GetTransferData(kHTMLMime, getter_AddRefs(data), &dataSize);
     if (NS_SUCCEEDED(rv)) {
       data->GetData(mHtmlString);
     }
     rv = transferable->GetTransferData(kHTMLContext, getter_AddRefs(data), &dataSize);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -117,16 +117,17 @@
 #ifdef MOZ_XTF
 #include "nsIXTFService.h"
 static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
 #endif
 #include "nsIMIMEService.h"
 #include "nsLWBrkCIID.h"
 #include "nsILineBreaker.h"
 #include "nsIWordBreaker.h"
+#include "nsUnicodeProperties.h"
 #include "jsdbgapi.h"
 #include "nsIJSRuntimeService.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsBindingManager.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsXBLBinding.h"
 #include "nsXBLPrototypeBinding.h"
@@ -149,17 +150,16 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsIPermissionManager.h"
 #include "nsIContentPrefService.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIRunnable.h"
 #include "nsDOMJSUtils.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValue.h"
 #include "nsReferencedElement.h"
-#include "nsIUGenCategory.h"
 #include "nsIDragService.h"
 #include "nsIChannelEventSink.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsCPrefetchService.h"
 #include "nsIChromeRegistry.h"
 #include "nsEventDispatcher.h"
@@ -255,17 +255,16 @@ nsDataHashtable<nsISupportsHashKey, Even
 nsDataHashtable<nsStringHashKey, EventNameMapping>* nsContentUtils::sStringEventTable = nsnull;
 nsCOMArray<nsIAtom>* nsContentUtils::sUserDefinedEvents = nsnull;
 nsIStringBundleService *nsContentUtils::sStringBundleService;
 nsIStringBundle *nsContentUtils::sStringBundles[PropertiesFile_COUNT];
 nsIContentPolicy *nsContentUtils::sContentPolicyService;
 bool nsContentUtils::sTriedToGetContentPolicy = false;
 nsILineBreaker *nsContentUtils::sLineBreaker;
 nsIWordBreaker *nsContentUtils::sWordBreaker;
-nsIUGenCategory *nsContentUtils::sGenCat;
 nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
 PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
 PRUint32 nsContentUtils::sJSGCThingRootCount;
 #ifdef IBMBIDI
 nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
 #endif
 PRUint32 nsContentUtils::sScriptBlockerCount = 0;
 #ifdef DEBUG
@@ -384,19 +383,16 @@ nsContentUtils::Init()
   }
 
   rv = CallGetService(NS_LBRK_CONTRACTID, &sLineBreaker);
   NS_ENSURE_SUCCESS(rv, rv);
   
   rv = CallGetService(NS_WBRK_CONTRACTID, &sWordBreaker);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  rv = CallGetService(NS_UNICHARCATEGORY_CONTRACTID, &sGenCat);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   if (!InitializeEventTable())
     return NS_ERROR_FAILURE;
 
   if (!sEventListenerManagersHash.ops) {
     static PLDHashTableOps hash_table_ops =
     {
       PL_DHashAllocTable,
       PL_DHashFreeTable,
@@ -972,17 +968,17 @@ nsContentUtils::IsPunctuationMarkAt(cons
     }
   }
   return false;
 }
 
 // static
 bool nsContentUtils::IsAlphanumeric(PRUint32 aChar)
 {
-  nsIUGenCategory::nsUGenCategory cat = sGenCat->Get(aChar);
+  nsIUGenCategory::nsUGenCategory cat = mozilla::unicode::GetGenCategory(aChar);
 
   return (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kNumber);
 }
  
 // static
 bool nsContentUtils::IsAlphanumericAt(const nsTextFragment* aFrag, PRUint32 aOffset)
 {
   PRUnichar h = aFrag->CharAt(aOffset);
@@ -1133,17 +1129,16 @@ nsContentUtils::Shutdown()
   sXPConnect = nsnull;
   sThreadJSContextStack = nsnull;
   NS_IF_RELEASE(sSecurityManager);
   NS_IF_RELEASE(sNameSpaceManager);
   NS_IF_RELEASE(sParserService);
   NS_IF_RELEASE(sIOService);
   NS_IF_RELEASE(sLineBreaker);
   NS_IF_RELEASE(sWordBreaker);
-  NS_IF_RELEASE(sGenCat);
 #ifdef MOZ_XTF
   NS_IF_RELEASE(sXTFService);
 #endif
   NS_IF_RELEASE(sImgLoader);
   NS_IF_RELEASE(sImgCache);
 #ifdef IBMBIDI
   NS_IF_RELEASE(sBidiKeyboard);
 #endif
--- a/content/base/src/nsDOMAttribute.cpp
+++ b/content/base/src/nsDOMAttribute.cpp
@@ -475,20 +475,24 @@ nsDOMAttribute::Clone(nsINodeInfo *aNode
   }
 
   NS_ADDREF(*aResult);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMAttribute::CloneNode(bool aDeep, nsIDOMNode** aResult)
+nsDOMAttribute::CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aResult)
 {
   OwnerDoc()->WarnOnceAbout(nsIDocument::eCloneNode);
 
+  if (!aOptionalArgc) {
+    aDeep = true;
+  }
+
   return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aResult);
 }
 
 NS_IMETHODIMP
 nsDOMAttribute::GetOwnerDocument(nsIDOMDocument** aOwnerDocument)
 {
   OwnerDoc()->WarnOnceAbout(nsIDocument::eOwnerDocument);
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5825,18 +5825,22 @@ nsDocument::RemoveChild(nsIDOMNode* aOld
 
 NS_IMETHODIMP
 nsDocument::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
 {
   return nsDocument::InsertBefore(aNewChild, nsnull, aReturn);
 }
 
 NS_IMETHODIMP
-nsDocument::CloneNode(bool aDeep, nsIDOMNode** aReturn)
-{
+nsDocument::CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aReturn)
+{
+  if (!aOptionalArgc) {
+    aDeep = true;
+  }
+  
   return nsNodeUtils::CloneNodeImpl(this, aDeep, !mCreatingStaticClone, aReturn);
 }
 
 NS_IMETHODIMP
 nsDocument::Normalize()
 {
   return nsIDocument::Normalize();
 }
@@ -8057,17 +8061,17 @@ nsIDocument::CreateStaticClone(nsISuppor
   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(this);
   NS_ENSURE_TRUE(domDoc, nsnull);
   mCreatingStaticClone = true;
 
   // Make document use different container during cloning.
   nsCOMPtr<nsISupports> originalContainer = GetContainer();
   SetContainer(aCloneContainer);
   nsCOMPtr<nsIDOMNode> clonedNode;
-  nsresult rv = domDoc->CloneNode(true, getter_AddRefs(clonedNode));
+  nsresult rv = domDoc->CloneNode(true, 1, getter_AddRefs(clonedNode));
   SetContainer(originalContainer);
 
   nsCOMPtr<nsIDocument> clonedDoc;
   if (NS_SUCCEEDED(rv)) {
     clonedDoc = do_QueryInterface(clonedNode);
     nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
     if (clonedDOMDoc) {
       clonedDoc->mOriginalDocument = this;
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -138,18 +138,22 @@ public:
   {
     aLocalName = LocalName();
     return NS_OK;
   }
   nsresult GetPrefix(nsAString& aPrefix);
   nsresult IsSupported(const nsAString& aFeature,
                        const nsAString& aVersion,
                        bool* aReturn);
-  nsresult CloneNode(bool aDeep, nsIDOMNode** aReturn)
+  nsresult CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode** aReturn)
   {
+    if (!aOptionalArgc) {
+      aDeep = true;
+    }
+    
     return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aReturn);
   }
 
   // Implementation for nsIDOMCharacterData
   nsresult GetData(nsAString& aData) const;
   nsresult SetData(const nsAString& aData);
   nsresult GetLength(PRUint32* aLength);
   nsresult SubstringData(PRUint32 aOffset, PRUint32 aCount,
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -432,18 +432,22 @@ public:
   nsresult AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn)
   {
     return InsertBefore(aNewChild, nsnull, aReturn);
   }
 
   // nsIDOMElement method implementation
   NS_DECL_NSIDOMELEMENT
 
-  nsresult CloneNode(bool aDeep, nsIDOMNode **aResult)
+  nsresult CloneNode(bool aDeep, PRUint8 aOptionalArgc, nsIDOMNode **aResult)
   {
+    if (!aOptionalArgc) {
+      aDeep = true;
+    }
+    
     return nsNodeUtils::CloneNodeImpl(this, aDeep, true, aResult);
   }
 
   //----------------------------------------
 
   /**
    * Add a script event listener with the given event handler name
    * (like onclick) and with the value as JS
--- a/content/base/src/nsRange.cpp
+++ b/content/base/src/nsRange.cpp
@@ -1591,17 +1591,17 @@ nsresult nsRange::CutContents(nsIDOMDocu
           if (endOffset > startOffset)
           {
             if (retval) {
               nsAutoString cutValue;
               rv = charData->SubstringData(startOffset, endOffset - startOffset,
                                            cutValue);
               NS_ENSURE_SUCCESS(rv, rv);
               nsCOMPtr<nsIDOMNode> clone;
-              rv = charData->CloneNode(false, getter_AddRefs(clone));
+              rv = charData->CloneNode(false, 1, getter_AddRefs(clone));
               NS_ENSURE_SUCCESS(rv, rv);
               clone->SetNodeValue(cutValue);
               nodeToResult = clone;
             }
 
             rv = charData->DeleteData(startOffset, endOffset - startOffset);
             NS_ENSURE_SUCCESS(rv, rv);
           }
@@ -1651,17 +1651,17 @@ nsresult nsRange::CutContents(nsIDOMDocu
       nsCOMPtr<nsINode> iNode = do_QueryInterface(node);
       if (iNode && iNode->IsElement() &&
           ((node == endContainer && endOffset == 0) ||
            (node == startContainer &&
             PRInt32(iNode->AsElement()->GetChildCount()) == startOffset)))
       {
         if (retval) {
           nsCOMPtr<nsIDOMNode> clone;
-          rv = node->CloneNode(false, getter_AddRefs(clone));
+          rv = node->CloneNode(false, 1, getter_AddRefs(clone));
           NS_ENSURE_SUCCESS(rv, rv);
           nodeToResult = clone;
         }
         handled = true;
       }
     }
 
     if (!handled)
@@ -1822,17 +1822,17 @@ nsRange::CloneParentsBetween(nsIDOMNode 
   nsCOMPtr<nsIDOMNode> parent, firstParent, lastParent;
 
   nsresult res = aNode->GetParentNode(getter_AddRefs(parent));
 
   while(parent && parent != aAncestor)
   {
     nsCOMPtr<nsIDOMNode> clone, tmpNode;
 
-    res = parent->CloneNode(false, getter_AddRefs(clone));
+    res = parent->CloneNode(false, 1, getter_AddRefs(clone));
 
     if (NS_FAILED(res)) return res;
     if (!clone)         return NS_ERROR_FAILURE;
 
     if (! firstParent)
       firstParent = lastParent = clone;
     else
     {
@@ -1923,17 +1923,17 @@ nsRange::CloneContents(nsIDOMDocumentFra
                        (!(iNode == mEndParent && mEndOffset == 0) &&
                         !(iNode == mStartParent &&
                           mStartOffset ==
                             PRInt32(iNode->AsElement()->GetChildCount())));
 
     // Clone the current subtree!
 
     nsCOMPtr<nsIDOMNode> clone;
-    res = node->CloneNode(deepClone, getter_AddRefs(clone));
+    res = node->CloneNode(deepClone, 1, getter_AddRefs(clone));
     if (NS_FAILED(res)) return res;
 
     // If it's CharacterData, make sure we only clone what
     // is in the range.
     //
     // XXX_kin: We need to also handle ProcessingInstruction
     // XXX_kin: according to the spec.
 
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -550,16 +550,17 @@ include $(topsrcdir)/config/rules.mk
 		test_XHR_timeout.js \
 		file_XHR_timeout.sjs \
 		test_bug717511.html \
 		file_bug717511.html \
 		file_bug717511.html^headers^ \
 		file_bug717511_2.html \
 		file_bug717511_2.html^headers^ \
 		test_bug726364.html \
+		test_bug698381.html \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug698381.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+  <!--
+    https://bugzilla.mozilla.org/show_bug.cgi?id=698381
+  -->
+  <head>
+    <title>Test for Bug 698381</title>
+    <script type="text/javascript"
+      src="/tests/SimpleTest/SimpleTest.js"></script>
+    <script src="/tests/SimpleTest/EventUtils.js"
+      type="text/javascript"></script>
+    <link rel="stylesheet" type="text/css"
+      href="/tests/SimpleTest/test.css" />
+  </head>
+  <body onload="runTests();">
+    <a target="_blank"
+      href="https://bugzilla.mozilla.org/show_bug.cgi?id=698381">
+      Mozilla Bug 698381</a>
+    <p id="display"></p>
+    <div id="content" style="display: none"></div>
+    <div id="noChildren" style="display: none"></div>
+    <div id="hasChildren" style="display: none">
+      <div id="childOne" style="display: none"></div>
+    </div>
+    <pre id="test">
+      <script type="text/javascript">
+        /*
+          Checks to see if default parameter handling is correct when 0
+          parameters are passed.
+
+          If none are passed, then Node.cloneNode should default aDeep
+          to true.
+        */
+        SimpleTest.waitForExplicitFinish();
+
+        var hasChildren = document.getElementById("hasChildren"),
+            noChildren = document.getElementById("noChildren"),
+            clonedNode;
+
+        function runTests() {
+
+          // Test Node.cloneNode when no arguments are given
+          clonedNode = hasChildren.cloneNode();
+          is(clonedNode.hasChildNodes(), true, "Node.cloneNode with true " +
+            "default on a node with children clones the child nodes.");
+
+          clonedNode = noChildren.cloneNode();
+          is(clonedNode.hasChildNodes(), false, "Node.cloneNode with true " +
+            "default on a node without children doesn't clone child nodes." );
+
+          SimpleTest.finish();
+        }
+      </script>
+    </pre>
+  </body>
+</html>
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -66,16 +66,17 @@ ifdef MOZ_WEBGL
 
 CPPSRCS += \
 	WebGLContext.cpp \
 	WebGLContextGL.cpp \
 	WebGLContextUtils.cpp \
 	WebGLContextReporter.cpp \
 	WebGLContextValidate.cpp \
 	WebGLExtensionStandardDerivatives.cpp \
+	WebGLExtensionTextureFilterAnisotropic.cpp \
 	WebGLExtensionLoseContext.cpp \
 	$(NULL)
 
 DEFINES += -DUSE_ANGLE
 USE_ANGLE=1
 
 else
 
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -815,24 +815,26 @@ WebGLContext::MozGetUnderlyingParamStrin
 }
 
 bool WebGLContext::IsExtensionSupported(WebGLExtensionID ei)
 {
     bool isSupported;
 
     switch (ei) {
         case WebGL_OES_texture_float:
-            MakeContextCurrent();
             isSupported = gl->IsExtensionSupported(gl->IsGLES2() ? GLContext::OES_texture_float 
                                                                  : GLContext::ARB_texture_float);
 	    break;
         case WebGL_OES_standard_derivatives:
             // We always support this extension.
             isSupported = true;
             break;
+        case WebGL_EXT_texture_filter_anisotropic:
+            isSupported = gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
+            break;
         case WebGL_MOZ_WEBGL_lose_context:
             // We always support this extension.
             isSupported = true;
             break;
         default:
             isSupported = false;
     }
 
@@ -855,27 +857,34 @@ WebGLContext::GetExtension(const nsAStri
     if (aName.EqualsLiteral("OES_texture_float")) {
         if (IsExtensionSupported(WebGL_OES_texture_float))
             ei = WebGL_OES_texture_float;
     }
     else if (aName.EqualsLiteral("OES_standard_derivatives")) {
         if (IsExtensionSupported(WebGL_OES_standard_derivatives))
             ei = WebGL_OES_standard_derivatives;
     }
+    else if (aName.EqualsLiteral("MOZ_EXT_texture_filter_anisotropic")) {
+        if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
+            ei = WebGL_EXT_texture_filter_anisotropic;
+    }
     else if (aName.EqualsLiteral("MOZ_WEBGL_lose_context")) {
         if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
             ei = WebGL_MOZ_WEBGL_lose_context;
     }
 
     if (ei != WebGLExtensionID_Max) {
         if (!IsExtensionEnabled(ei)) {
             switch (ei) {
                 case WebGL_OES_standard_derivatives:
                     mEnabledExtensions[ei] = new WebGLExtensionStandardDerivatives(this);
                     break;
+                case WebGL_EXT_texture_filter_anisotropic:
+                    mEnabledExtensions[ei] = new WebGLExtensionTextureFilterAnisotropic(this);
+                    break;
                 case WebGL_MOZ_WEBGL_lose_context:
                     mEnabledExtensions[ei] = new WebGLExtensionLoseContext(this);
                     break;
                 // create an extension for any types that don't
                 // have any additional tokens or methods
                 default:
                     mEnabledExtensions[ei] = new WebGLExtension(this);
                     break;
@@ -1290,16 +1299,21 @@ NS_IMPL_RELEASE(WebGLExtensionStandardDe
 DOMCI_DATA(WebGLExtensionStandardDerivatives, WebGLExtensionStandardDerivatives)
 
 NS_INTERFACE_MAP_BEGIN(WebGLExtensionStandardDerivatives)
   NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionStandardDerivatives)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionStandardDerivatives)
 NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
 
+NS_IMPL_ADDREF(WebGLExtensionTextureFilterAnisotropic)
+NS_IMPL_RELEASE(WebGLExtensionTextureFilterAnisotropic)
+
+DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, WebGLExtensionTextureFilterAnisotropic)
+
 NS_IMPL_ADDREF(WebGLExtensionLoseContext)
 NS_IMPL_RELEASE(WebGLExtensionLoseContext)
 
 DOMCI_DATA(WebGLExtensionLoseContext, WebGLExtensionLoseContext)
 
 NS_INTERFACE_MAP_BEGIN(WebGLExtensionLoseContext)
   NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionLoseContext)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
@@ -1404,16 +1418,18 @@ WebGLContext::GetSupportedExtensions(nsI
     NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
 
     nsTArray<const char *> extList;
 
     if (IsExtensionSupported(WebGL_OES_texture_float))
         extList.InsertElementAt(extList.Length(), "OES_texture_float");
     if (IsExtensionSupported(WebGL_OES_standard_derivatives))
         extList.InsertElementAt(extList.Length(), "OES_standard_derivatives");
+    if (IsExtensionSupported(WebGL_EXT_texture_filter_anisotropic))
+        extList.InsertElementAt(extList.Length(), "MOZ_EXT_texture_filter_anisotropic");
     if (IsExtensionSupported(WebGL_MOZ_WEBGL_lose_context))
         extList.InsertElementAt(extList.Length(), "MOZ_WEBGL_lose_context");
 
     nsresult rv;
     if (extList.Length() > 0) {
         rv = wrval->SetAsArray(nsIDataType::VTYPE_CHAR_STR, nsnull,
                                extList.Length(), &extList[0]);
     } else {
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -740,16 +740,17 @@ protected:
         // be restored.
         ContextLostAwaitingRestore
     };
 
     // extensions
     enum WebGLExtensionID {
         WebGL_OES_texture_float,
         WebGL_OES_standard_derivatives,
+        WebGL_EXT_texture_filter_anisotropic,
         WebGL_MOZ_WEBGL_lose_context,
         WebGLExtensionID_Max
     };
     nsCOMPtr<WebGLExtension> mEnabledExtensions[WebGLExtensionID_Max];
     bool IsExtensionEnabled(WebGLExtensionID ext) const {
         NS_ABORT_IF_FALSE(ext >= 0 && ext < WebGLExtensionID_Max, "bogus index!");
         return mEnabledExtensions[ext] != nsnull;
     }
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -2205,16 +2205,25 @@ WebGLContext::GetParameter(PRUint32 pnam
             gl->fGetIntegerv(pname, &i);
             GLuint i_unsigned(i); // this is where -1 becomes 2^32-1
             double i_double(i_unsigned); // pass as FP value to allow large values such as 2^32-1.
             wrval->SetAsDouble(i_double);
         }
             break;
 
 // float
+        case LOCAL_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+            if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
+                GLfloat f = 0.f;
+                gl->fGetFloatv(pname, &f);
+                wrval->SetAsFloat(f);
+            } else {
+                return ErrorInvalidEnum("getParameter: parameter", pname);
+            }
+            break;
         case LOCAL_GL_DEPTH_CLEAR_VALUE:
         case LOCAL_GL_LINE_WIDTH:
         case LOCAL_GL_POLYGON_OFFSET_FACTOR:
         case LOCAL_GL_POLYGON_OFFSET_UNITS:
         case LOCAL_GL_SAMPLE_COVERAGE_VALUE:
         {
             GLfloat f = 0.f;
             gl->fGetFloatv(pname, &f);
@@ -2674,16 +2683,17 @@ nsresult WebGLContext::TexParameter_base
     if (!ValidateTextureTargetEnum(target, "texParameter: target"))
         return NS_OK;
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
     if (!tex)
         return ErrorInvalidOperation("texParameter: no texture is bound to this target");
 
     bool pnameAndParamAreIncompatible = false;
+    bool paramValueInvalid = false;
 
     switch (pname) {
         case LOCAL_GL_TEXTURE_MIN_FILTER:
             switch (intParam) {
                 case LOCAL_GL_NEAREST:
                 case LOCAL_GL_LINEAR:
                 case LOCAL_GL_NEAREST_MIPMAP_NEAREST:
                 case LOCAL_GL_LINEAR_MIPMAP_NEAREST:
@@ -2722,28 +2732,43 @@ nsresult WebGLContext::TexParameter_base
                 case LOCAL_GL_MIRRORED_REPEAT:
                 case LOCAL_GL_REPEAT:
                     tex->SetWrapT(intParam);
                     break;
                 default:
                     pnameAndParamAreIncompatible = true;
             }
             break;
+        case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
+            if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
+                if (floatParamPtr && floatParam < 1.f)
+                    paramValueInvalid = true;
+                else if (intParamPtr && intParam < 1)
+                    paramValueInvalid = true;
+            }
+            else
+                pnameAndParamAreIncompatible = true;
+            break;
         default:
             return ErrorInvalidEnumInfo("texParameter: pname", pname);
     }
 
     if (pnameAndParamAreIncompatible) {
-        // note that currently all params are enums, and the tex-input-validation test wants INVALID_ENUM errors
-        // even for texParameterf. why not.
         if (intParamPtr)
             return ErrorInvalidEnum("texParameteri: pname %x and param %x (decimal %d) are mutually incompatible",
                                     pname, intParam, intParam);
         else
-            return ErrorInvalidEnum("texParameterf: pname %x and floating-point param %e are mutually incompatible",
+            return ErrorInvalidEnum("texParameterf: pname %x and param %g are mutually incompatible",
+                                    pname, floatParam);
+    } else if (paramValueInvalid) {
+        if (intParamPtr)
+            return ErrorInvalidValue("texParameteri: pname %x and param %x (decimal %d) is invalid",
+                                    pname, intParam, intParam);
+        else
+            return ErrorInvalidValue("texParameterf: pname %x and param %g is invalid",
                                     pname, floatParam);
     }
 
     MakeContextCurrent();
     if (intParamPtr)
         gl->fTexParameteri(target, pname, intParam);
     else
         gl->fTexParameterf(target, pname, floatParam);
@@ -2794,16 +2819,25 @@ WebGLContext::GetTexParameter(WebGLenum 
         case LOCAL_GL_TEXTURE_WRAP_S:
         case LOCAL_GL_TEXTURE_WRAP_T:
         {
             GLint i = 0;
             gl->fGetTexParameteriv(target, pname, &i);
             wrval->SetAsInt32(i);
         }
             break;
+        case LOCAL_GL_TEXTURE_MAX_ANISOTROPY_EXT:
+            if (mEnabledExtensions[WebGL_EXT_texture_filter_anisotropic]) {
+                GLfloat f = 0.f;
+                gl->fGetTexParameterfv(target, pname, &f);
+                wrval->SetAsFloat(f);
+            }
+            else
+                return ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
+            break;
 
         default:
             return ErrorInvalidEnumInfo("getTexParameter: parameter", pname);
     }
 
     *retval = wrval.forget().get();
 
     return NS_OK;
--- a/content/canvas/src/WebGLContextNotSupported.cpp
+++ b/content/canvas/src/WebGLContextNotSupported.cpp
@@ -50,9 +50,10 @@ DOMCI_DATA(WebGLProgram, void)
 DOMCI_DATA(WebGLShader, void)
 DOMCI_DATA(WebGLFramebuffer, void)
 DOMCI_DATA(WebGLRenderbuffer, void)
 DOMCI_DATA(WebGLUniformLocation, void)
 DOMCI_DATA(WebGLShaderPrecisionFormat, void)
 DOMCI_DATA(WebGLActiveInfo, void)
 DOMCI_DATA(WebGLExtension, void)
 DOMCI_DATA(WebGLExtensionStandardDerivatives, void)
+DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, void)
 DOMCI_DATA(WebGLExtensionLoseContext, void)
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/WebGLExtensionTextureFilterAnisotropic.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Florian Boesch <pyalot@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdarg.h>
+
+#include "WebGLContext.h"
+#include "WebGLExtensions.h"
+
+#include "nsContentUtils.h"
+#include "mozilla/Preferences.h"
+
+using namespace mozilla;
+
+NS_INTERFACE_MAP_BEGIN(WebGLExtensionTextureFilterAnisotropic)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionTextureFilterAnisotropic)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionTextureFilterAnisotropic)
+NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
+
+WebGLExtensionTextureFilterAnisotropic::WebGLExtensionTextureFilterAnisotropic(WebGLContext* context) :
+    WebGLExtension(context)
+{
+
+}
+
+WebGLExtensionTextureFilterAnisotropic::~WebGLExtensionTextureFilterAnisotropic()
+{
+
+}
--- a/content/canvas/src/WebGLExtensions.h
+++ b/content/canvas/src/WebGLExtensions.h
@@ -36,19 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef WEBGLEXTENSIONS_H_
 #define WEBGLEXTENSIONS_H_
 
 namespace mozilla {
 
-class WebGLExtensionLoseContext;
-class WebGLExtensionStandardDerivatives;
-
 class WebGLExtensionLoseContext :
     public nsIWebGLExtensionLoseContext,
     public WebGLExtension
 {
 public:
     WebGLExtensionLoseContext(WebGLContext*);
     virtual ~WebGLExtensionLoseContext();
 
@@ -63,11 +60,23 @@ class WebGLExtensionStandardDerivatives 
 public:
     WebGLExtensionStandardDerivatives(WebGLContext* context);
     virtual ~WebGLExtensionStandardDerivatives();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLEXTENSION
 };
 
+class WebGLExtensionTextureFilterAnisotropic :
+    public nsIWebGLExtensionTextureFilterAnisotropic,
+    public WebGLExtension
+{
+public:
+    WebGLExtensionTextureFilterAnisotropic(WebGLContext* context);
+    virtual ~WebGLExtensionTextureFilterAnisotropic();
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSIWEBGLEXTENSION
+};
+
 }
 
 #endif // WEBGLEXTENSIONS_H_
--- a/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
+++ b/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
@@ -1,7 +1,8 @@
 oes-standard-derivatives.html
+ext-texture-filter-anisotropic.html
 oes-texture-float.html
 oes-vertex-array-object.html
 webgl-debug-renderer-info.html
 webgl-debug-shaders.html
 --min-version 1.0.2 webgl-experimental-compressed-textures.html
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
@@ -0,0 +1,157 @@
+<!--
+Copyright (c) 2012 Florian Boesch <pyalot@gmail.com>. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebGL EXT_texture_filter_anisotropic Conformance Tests</title>
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../resources/webgl-test.js"></script>
+<script src="../resources/webgl-test-utils.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<div id="console"></div>
+
+<script>
+description("This test verifies the functionality of the EXT_texture_filter_anisotropic extension, if it is available.");
+
+debug("");
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = create3DContext(canvas);
+var ext = null;
+
+if (!gl) {
+    testFailed("WebGL context does not exist");
+} else {
+    testPassed("WebGL context exists");
+
+    // Run tests with extension disabled
+    runHintTestDisabled();
+
+    // Query the extension and store globally so shouldBe can access it
+    ext = gl.getExtension("MOZ_EXT_texture_filter_anisotropic");
+    if (!ext) {
+        testPassed("No EXT_texture_filter_anisotropic support -- this is legal");
+
+        runSupportedTest(false);
+    } else {
+        testPassed("Successfully enabled EXT_texture_filter_anisotropic extension");
+
+        runSupportedTest(true);
+        runHintTestEnabled();
+    }
+}
+
+function runSupportedTest(extensionEnabled) {
+    var supported = gl.getSupportedExtensions();
+    if (supported.indexOf("MOZ_EXT_texture_filter_anisotropic") >= 0) {
+        if (extensionEnabled) {
+            testPassed("EXT_texture_filter_anisotropic listed as supported and getExtension succeeded");
+        } else {
+            testFailed("EXT_texture_filter_anisotropic listed as supported but getExtension failed");
+        }
+    } else {
+        if (extensionEnabled) {
+            testFailed("EXT_texture_filter_anisotropic not listed as supported but getExtension succeeded");
+        } else {
+            testPassed("EXt_texture_filter_anisotropic not listed as supported and getExtension failed -- this is legal");
+        }
+    }
+}
+
+function runHintTestDisabled() {
+    debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension disabled");
+    
+    var MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF;
+    gl.getParameter(MAX_TEXTURE_MAX_ANISOTROPY);
+    glErrorShouldBe(gl, gl.INVALID_ENUM, "MAX_TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
+    
+    debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
+    var TEXTURE_MAX_ANISOTROPY = 0x84FE;
+    var texture = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+   
+    gl.getTexParameter(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY);
+    glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
+
+    gl.texParameterf(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
+    glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
+    
+    gl.texParameteri(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
+    glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
+
+    gl.deleteTexture(texture);
+}
+
+function runHintTestEnabled() {
+    debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension enabled");
+
+    shouldBe("ext.MAX_TEXTURE_MAX_ANISOTROPY", "0x84FF");
+
+    var max_anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY);
+    glErrorShouldBe(gl, gl.NO_ERROR, "MAX_TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
+
+    if(max_anisotropy >= 2){
+        testPassed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0");
+    }
+    else{
+        testFailed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0, returned values was: " + max_anisotropy);
+    }
+    
+    // TODO make a texture and verify initial value == 1 and setting to less than 1 is invalid value
+
+    debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
+    shouldBe("ext.TEXTURE_MAX_ANISOTROPY", "0x84FE");
+
+    var texture = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+   
+    var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
+    glErrorShouldBe(gl, gl.NO_ERROR, "TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
+
+    if(queried_value == 1){
+        testPassed("Initial value of TEXTURE_MAX_ANISOTROPY is 1.0");
+    }
+    else{
+        testFailed("Initial value of TEXTURE_MAX_ANISOTROPY should be 1.0, returned value was: " + queried_value);
+    }
+
+    gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameterf TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
+    
+    gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameteri TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
+    
+    gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
+    glErrorShouldBe(gl, gl.NO_ERROR, "texParameterf TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
+    
+    gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
+    glErrorShouldBe(gl, gl.NO_ERROR, "texParameteri TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
+
+    var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
+    if(queried_value == max_anisotropy){
+        testPassed("Set value of TEXTURE_MAX_ANISOTROPY matches expecation");
+    }
+    else{
+        testFailed("Set value of TEXTURE_MAX_ANISOTROPY should be: " + max_anisotropy + " , returned value was: " + queried_value);
+    }
+
+    gl.deleteTexture(texture);
+}
+
+debug("");
+successfullyParsed = true;
+</script>
+<script src="../../resources/js-test-post.js"></script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/ext-texture-filter-anisotropic.patch
@@ -0,0 +1,174 @@
+diff --git a/content/canvas/test/webgl/conformance/extensions/00_test_list.txt b/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
+--- a/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
++++ b/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
+@@ -1,7 +1,8 @@
+ oes-standard-derivatives.html
++ext-texture-filter-anisotropic.html
+ oes-texture-float.html
+ oes-vertex-array-object.html
+ webgl-debug-renderer-info.html
+ webgl-debug-shaders.html
+ --min-version 1.0.2 webgl-experimental-compressed-textures.html
+ 
+diff --git a/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html b/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
+new file mode 100644
+--- /dev/null
++++ b/content/canvas/test/webgl/conformance/extensions/ext-texture-filter-anisotropic.html
+@@ -0,0 +1,157 @@
++<!--
++Copyright (c) 2012 Florian Boesch <pyalot@gmail.com>. All rights reserved.
++Use of this source code is governed by a BSD-style license that can be
++found in the LICENSE file.
++ -->
++<!DOCTYPE html>
++<html>
++<head>
++<meta charset="utf-8">
++<title>WebGL EXT_texture_filter_anisotropic Conformance Tests</title>
++<link rel="stylesheet" href="../../resources/js-test-style.css"/>
++<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script>
++<script src="../../resources/js-test-pre.js"></script>
++<script src="../resources/webgl-test.js"></script>
++<script src="../resources/webgl-test-utils.js"></script>
++</head>
++<body>
++<div id="description"></div>
++<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
++<div id="console"></div>
++
++<script>
++description("This test verifies the functionality of the EXT_texture_filter_anisotropic extension, if it is available.");
++
++debug("");
++
++var wtu = WebGLTestUtils;
++var canvas = document.getElementById("canvas");
++var gl = create3DContext(canvas);
++var ext = null;
++
++if (!gl) {
++    testFailed("WebGL context does not exist");
++} else {
++    testPassed("WebGL context exists");
++
++    // Run tests with extension disabled
++    runHintTestDisabled();
++
++    // Query the extension and store globally so shouldBe can access it
++    ext = gl.getExtension("MOZ_EXT_texture_filter_anisotropic");
++    if (!ext) {
++        testPassed("No EXT_texture_filter_anisotropic support -- this is legal");
++
++        runSupportedTest(false);
++    } else {
++        testPassed("Successfully enabled EXT_texture_filter_anisotropic extension");
++
++        runSupportedTest(true);
++        runHintTestEnabled();
++    }
++}
++
++function runSupportedTest(extensionEnabled) {
++    var supported = gl.getSupportedExtensions();
++    if (supported.indexOf("MOZ_EXT_texture_filter_anisotropic") >= 0) {
++        if (extensionEnabled) {
++            testPassed("EXT_texture_filter_anisotropic listed as supported and getExtension succeeded");
++        } else {
++            testFailed("EXT_texture_filter_anisotropic listed as supported but getExtension failed");
++        }
++    } else {
++        if (extensionEnabled) {
++            testFailed("EXT_texture_filter_anisotropic not listed as supported but getExtension succeeded");
++        } else {
++            testPassed("EXt_texture_filter_anisotropic not listed as supported and getExtension failed -- this is legal");
++        }
++    }
++}
++
++function runHintTestDisabled() {
++    debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension disabled");
++    
++    var MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF;
++    gl.getParameter(MAX_TEXTURE_MAX_ANISOTROPY);
++    glErrorShouldBe(gl, gl.INVALID_ENUM, "MAX_TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
++    
++    debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
++    var TEXTURE_MAX_ANISOTROPY = 0x84FE;
++    var texture = gl.createTexture();
++    gl.bindTexture(gl.TEXTURE_2D, texture);
++   
++    gl.getTexParameter(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY);
++    glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be queryable if extension is disabled");
++
++    gl.texParameterf(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
++    glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
++    
++    gl.texParameteri(gl.TEXTURE_2D, TEXTURE_MAX_ANISOTROPY, 1);
++    glErrorShouldBe(gl, gl.INVALID_ENUM, "TEXTURE_MAX_ANISOTROPY should not be settable if extension is disabled");
++
++    gl.deleteTexture(texture);
++}
++
++function runHintTestEnabled() {
++    debug("Testing MAX_TEXTURE_MAX_ANISOTROPY with extension enabled");
++
++    shouldBe("ext.MAX_TEXTURE_MAX_ANISOTROPY", "0x84FF");
++
++    var max_anisotropy = gl.getParameter(ext.MAX_TEXTURE_MAX_ANISOTROPY);
++    glErrorShouldBe(gl, gl.NO_ERROR, "MAX_TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
++
++    if(max_anisotropy >= 2){
++        testPassed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0");
++    }
++    else{
++        testFailed("Minimum value of MAX_TEXTURE_MAX_ANISOTROPY is 2.0, returned values was: " + max_anisotropy);
++    }
++    
++    // TODO make a texture and verify initial value == 1 and setting to less than 1 is invalid value
++
++    debug("Testing TEXTURE_MAX_ANISOTROPY with extension disabled");
++    shouldBe("ext.TEXTURE_MAX_ANISOTROPY", "0x84FE");
++
++    var texture = gl.createTexture();
++    gl.bindTexture(gl.TEXTURE_2D, texture);
++   
++    var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
++    glErrorShouldBe(gl, gl.NO_ERROR, "TEXTURE_MAX_ANISOTROPY query should succeed if extension is enabled");
++
++    if(queried_value == 1){
++        testPassed("Initial value of TEXTURE_MAX_ANISOTROPY is 1.0");
++    }
++    else{
++        testFailed("Initial value of TEXTURE_MAX_ANISOTROPY should be 1.0, returned value was: " + queried_value);
++    }
++
++    gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
++    glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameterf TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
++    
++    gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, 0);
++    glErrorShouldBe(gl, gl.INVALID_VALUE, "texParameteri TEXTURE_MAX_ANISOTROPY set to < 1 should be an invalid value");
++    
++    gl.texParameterf(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
++    glErrorShouldBe(gl, gl.NO_ERROR, "texParameterf TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
++    
++    gl.texParameteri(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY, max_anisotropy);
++    glErrorShouldBe(gl, gl.NO_ERROR, "texParameteri TEXTURE_MAX_ANISOTROPY set to >= 2 should should succeed");
++
++    var queried_value = gl.getTexParameter(gl.TEXTURE_2D, ext.TEXTURE_MAX_ANISOTROPY);
++    if(queried_value == max_anisotropy){
++        testPassed("Set value of TEXTURE_MAX_ANISOTROPY matches expecation");
++    }
++    else{
++        testFailed("Set value of TEXTURE_MAX_ANISOTROPY should be: " + max_anisotropy + " , returned value was: " + queried_value);
++    }
++
++    gl.deleteTexture(texture);
++}
++
++debug("");
++successfullyParsed = true;
++</script>
++<script src="../../resources/js-test-post.js"></script>
++
++</body>
++</html>
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -803,17 +803,17 @@ nsHTMLSelectElement::SetLength(PRUint32 
       nsCOMPtr<nsIDOMNode> tmpNode;
 
       rv = AppendChild(node, getter_AddRefs(tmpNode));
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (i + 1 < aLength) {
         nsCOMPtr<nsIDOMNode> newNode;
 
-        rv = node->CloneNode(true, getter_AddRefs(newNode));
+        rv = node->CloneNode(true, 1, getter_AddRefs(newNode));
         NS_ENSURE_SUCCESS(rv, rv);
 
         node = newNode;
       }
     }
   }
 
   return NS_OK;
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -844,25 +844,21 @@ nsTextInputListener::EditAction()
   nsTextControlFrame* frame = static_cast<nsTextControlFrame*> (frameBase);
   NS_ASSERTION(frame, "Where is our frame?");
   //
   // Update the undo / redo menus
   //
   nsCOMPtr<nsIEditor> editor;
   frame->GetEditor(getter_AddRefs(editor));
 
-  nsCOMPtr<nsITransactionManager> manager;
-  editor->GetTransactionManager(getter_AddRefs(manager));
-  NS_ENSURE_TRUE(manager, NS_ERROR_FAILURE);
-
   // Get the number of undo / redo items
   PRInt32 numUndoItems = 0;
   PRInt32 numRedoItems = 0;
-  manager->GetNumberOfUndoItems(&numUndoItems);
-  manager->GetNumberOfRedoItems(&numRedoItems);
+  editor->GetNumberOfUndoItems(&numUndoItems);
+  editor->GetNumberOfRedoItems(&numRedoItems);
   if ((numUndoItems && !mHadUndoItems) || (!numUndoItems && mHadUndoItems) ||
       (numRedoItems && !mHadRedoItems) || (!numRedoItems && mHadRedoItems)) {
     // Modify the menu if undo or redo items are different
     UpdateTextInputCommands(NS_LITERAL_STRING("undo"));
 
     mHadUndoItems = numUndoItems != 0;
     mHadRedoItems = numRedoItems != 0;
   }
--- a/content/smil/nsSMILAnimationFunction.cpp
+++ b/content/smil/nsSMILAnimationFunction.cpp
@@ -89,17 +89,18 @@ nsSMILAnimationFunction::nsSMILAnimation
     mBeginTime(LL_MININT),
     mAnimationElement(nsnull),
     mErrorFlags(0),
     mIsActive(false),
     mIsFrozen(false),
     mLastValue(false),
     mHasChanged(true),
     mValueNeedsReparsingEverySample(false),
-    mPrevSampleWasSingleValueAnimation(false)
+    mPrevSampleWasSingleValueAnimation(false),
+    mWasSkippedInPrevSample(false)
 {
 }
 
 void
 nsSMILAnimationFunction::SetAnimationElement(
     nsISMILAnimationElement* aAnimationElement)
 {
   mAnimationElement = aAnimationElement;
@@ -228,16 +229,17 @@ nsSMILAnimationFunction::Inactivate(bool
 }
 
 void
 nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr,
                                        nsSMILValue& aResult)
 {
   mHasChanged = false;
   mPrevSampleWasSingleValueAnimation = false;
+  mWasSkippedInPrevSample = false;
 
   // Skip animations that are inactive or in error
   if (!IsActiveOrFrozen() || mErrorFlags != 0)
     return;
 
   // Get the animation values
   nsSMILValueArray values;
   nsresult rv = GetValues(aSMILAttr, values);
--- a/content/smil/nsSMILAnimationFunction.h
+++ b/content/smil/nsSMILAnimationFunction.h
@@ -242,16 +242,34 @@ public:
    *
    * @param aNewTarget A nsSMILTargetIdentifier representing the animation
    *                   target of this function for this sample.
    * @return  true if |aNewTarget| is different from the old cached value;
    *          otherwise, false.
    */
   bool UpdateCachedTarget(const nsSMILTargetIdentifier& aNewTarget);
 
+  /**
+   * Returns true if this function was skipped in the previous sample (because
+   * there was a higher-priority non-additive animation). If a skipped animation
+   * function is later used, then the animation sandwich must be recomposited.
+   */
+  bool WasSkippedInPrevSample() const {
+    return mWasSkippedInPrevSample;
+  }
+
+  /**
+   * Mark this animation function as having been skipped. By marking the
+   * function as skipped, if it is used in a subsequent sample we'll know to
+   * recomposite the sandwich.
+   */
+  void SetWasSkipped() {
+    mWasSkippedInPrevSample = true;
+  }
+
   // Comparator utility class, used for sorting nsSMILAnimationFunctions
   class Comparator {
     public:
       bool Equals(const nsSMILAnimationFunction* aElem1,
                     const nsSMILAnimationFunction* aElem2) const {
         return (aElem1->CompareTo(aElem2) == 0);
       }
       bool LessThan(const nsSMILAnimationFunction* aElem1,
@@ -461,17 +479,18 @@ protected:
   nsSMILValue                   mFrozenValue;
 
   // Allows us to check whether an animation function has changed target from
   // sample to sample (because if neither target nor animated value have
   // changed, we don't have to do anything).
   nsSMILWeakTargetIdentifier    mLastTarget;
 
   // Boolean flags
-  bool                          mIsActive:1;
-  bool                          mIsFrozen:1;
-  bool                          mLastValue:1;
-  bool                          mHasChanged:1;
-  bool                          mValueNeedsReparsingEverySample:1;
-  bool                          mPrevSampleWasSingleValueAnimation:1;
+  bool mIsActive:1;
+  bool mIsFrozen:1;
+  bool mLastValue:1;
+  bool mHasChanged:1;
+  bool mValueNeedsReparsingEverySample:1;
+  bool mPrevSampleWasSingleValueAnimation:1;
+  bool mWasSkippedInPrevSample:1;
 };
 
 #endif // NS_SMILANIMATIONFUNCTION_H_
--- a/content/smil/nsSMILCompositor.cpp
+++ b/content/smil/nsSMILCompositor.cpp
@@ -168,26 +168,41 @@ nsSMILCompositor::CreateSMILAttr()
 }
 
 PRUint32
 nsSMILCompositor::GetFirstFuncToAffectSandwich()
 {
   PRUint32 i;
   for (i = mAnimationFunctions.Length(); i > 0; --i) {
     nsSMILAnimationFunction* curAnimFunc = mAnimationFunctions[i-1];
-    if (curAnimFunc->UpdateCachedTarget(mKey) ||
-        (!mForceCompositing && curAnimFunc->HasChanged())) {
-      mForceCompositing = true;
-    }
+    // In the following, the lack of short-circuit behavior of |= means that we
+    // will ALWAYS run UpdateCachedTarget (even if mForceCompositing is true)
+    // but only call HasChanged and WasSkippedInPrevSample if necessary.  This
+    // is important since we need UpdateCachedTarget to run in order to detect
+    // changes to the target in subsequent samples.
+    mForceCompositing |=
+      curAnimFunc->UpdateCachedTarget(mKey) ||
+      curAnimFunc->HasChanged() ||
+      curAnimFunc->WasSkippedInPrevSample();
 
     if (curAnimFunc->WillReplace()) {
       --i;
       break;
     }
   }
+  // Mark remaining animation functions as having been skipped so if we later
+  // use them we'll know to force compositing.
+  // Note that we only really need to do this if something has changed
+  // (otherwise we would have set the flag on a previous sample) and if
+  // something has changed mForceCompositing will be true.
+  if (mForceCompositing) {
+    for (PRUint32 j = i; j > 0; --j) {
+      mAnimationFunctions[j-1]->SetWasSkipped();
+    }
+  }
   return i;
 }
 
 void
 nsSMILCompositor::UpdateCachedBaseValue(const nsSMILValue& aBaseValue)
 {
   if (!mCachedBaseValue) {
     // We don't have last sample's base value cached. Assume it's changed.
--- a/content/smil/nsSMILCompositor.h
+++ b/content/smil/nsSMILCompositor.h
@@ -126,14 +126,14 @@ public:
 
   // Member data for detecting when we need to force-recompose
   // ---------------------------------------------------------
   // Flag for tracking whether we need to compose. Initialized to false, but
   // gets flipped to true if we detect that something has changed.
   bool mForceCompositing;
 
   // Cached base value, so we can detect & force-recompose when it changes
-  // from one sample to the next.  (nsSMILAnimationController copies this
+  // from one sample to the next. (nsSMILAnimationController copies this
   // forward from the previous sample's compositor.)
   nsAutoPtr<nsSMILValue> mCachedBaseValue;
 };
 
 #endif // NS_SMILCOMPOSITOR_H_
--- a/content/smil/nsSMILParserUtils.cpp
+++ b/content/smil/nsSMILParserUtils.cpp
@@ -610,21 +610,16 @@ nsSMILParserUtils::ParseValuesGeneric(co
 
   while (tokenizer.hasMoreTokens()) {
     nsresult rv = aParser.Parse(tokenizer.nextToken());
     if (NS_FAILED(rv)) {
       return NS_ERROR_FAILURE;
     }
   }
 
-  // Disallow ;-terminated values lists.
-  if (tokenizer.lastTokenEndedWithSeparator()) {
-    return NS_ERROR_FAILURE;
-  }
-
   return NS_OK;
 }
 
 nsresult
 nsSMILParserUtils::ParseRepeatCount(const nsAString& aSpec,
                                     nsSMILRepeatCount& aResult)
 {
   nsresult rv = NS_OK;
--- a/content/smil/nsSMILTimedElement.cpp
+++ b/content/smil/nsSMILTimedElement.cpp
@@ -50,16 +50,17 @@
 #include "nsThreadUtils.h"
 #include "nsIPresShell.h"
 #include "prdtoa.h"
 #include "plstr.h"
 #include "prtime.h"
 #include "nsString.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/Util.h"
+#include "nsCharSeparatedTokenizer.h"
 
 using namespace mozilla;
 
 //----------------------------------------------------------------------
 // Helper class: InstanceTimeComparator
 
 // Upon inserting an instance time into one of our instance time lists we assign
 // it a serial number. This allows us to sort the instance times in such a way
@@ -1266,38 +1267,37 @@ nsSMILTimedElement::Unlink()
 // Implementation helpers
 
 nsresult
 nsSMILTimedElement::SetBeginOrEndSpec(const nsAString& aSpec,
                                       Element* aContextNode,
                                       bool aIsBegin,
                                       RemovalTestFunction aRemove)
 {
-  PRInt32 start;
-  PRInt32 end = -1;
-  PRInt32 length;
-  nsresult rv = NS_OK;
   TimeValueSpecList& timeSpecsList = aIsBegin ? mBeginSpecs : mEndSpecs;
   InstanceTimeList& instances = aIsBegin ? mBeginInstances : mEndInstances;
 
   ClearSpecs(timeSpecsList, instances, aRemove);
 
   AutoIntervalUpdateBatcher updateBatcher(*this);
 
-  do {
-    start = end + 1;
-    end = aSpec.FindChar(';', start);
-    length = (end == -1) ? -1 : end - start;
+  nsCharSeparatedTokenizer tokenizer(aSpec, ';');
+  if (!tokenizer.hasMoreTokens()) { // Empty list
+    return NS_ERROR_FAILURE;
+  }
+
+  nsresult rv = NS_OK;
+  while (tokenizer.hasMoreTokens() && NS_SUCCEEDED(rv)) {
     nsAutoPtr<nsSMILTimeValueSpec>
       spec(new nsSMILTimeValueSpec(*this, aIsBegin));
-    rv = spec->SetSpec(Substring(aSpec, start, length), aContextNode);
+    rv = spec->SetSpec(tokenizer.nextToken(), aContextNode);
     if (NS_SUCCEEDED(rv)) {
       timeSpecsList.AppendElement(spec.forget());
     }
-  } while (end != -1 && NS_SUCCEEDED(rv));
+  }
 
   if (NS_FAILED(rv)) {
     ClearSpecs(timeSpecsList, instances, aRemove);
   }
 
   return rv;
 }
 
--- a/content/smil/test/Makefile.in
+++ b/content/smil/test/Makefile.in
@@ -86,16 +86,17 @@ include $(topsrcdir)/config/rules.mk
 	  test_smilSync.xhtml \
 	  test_smilSyncbaseTarget.xhtml \
 	  test_smilSyncTransform.xhtml \
 	  test_smilTextZoom.xhtml \
 	  test_smilTimeEvents.xhtml \
 	  test_smilTiming.xhtml \
 	  test_smilTimingZeroIntervals.xhtml \
 	  test_smilUpdatedInterval.xhtml \
+	  test_smilValues.xhtml \
 	  test_smilXHR.xhtml \
 	  $(NULL)
 
 # Tests disabled due to intermittent orange
 # test_smilCSSInherit.xhtml disabled until bug 501183 is fixed
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $^ $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
--- a/content/smil/test/smilAnimateMotionValueLists.js
+++ b/content/smil/test/smilAnimateMotionValueLists.js
@@ -35,26 +35,27 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* Lists of valid & invalid values for the various <animateMotion> attributes */
 const gValidValues = [
   "10 10",
+  "10 10;",  // Trailing semicolons are allowed
+  "10 10;  ",
   "   10   10em  ",
   "1 2  ; 3,4",
   "1,2;3,4",
   "0 0",
   "0,0",
 ];
 
 const gInvalidValues = [
   ";10 10",
-  "10 10;",  // We treat semicolon-terminated value-lists as failure cases
   "10 10;;",
   "1 2 3",
   "1 2 3 4",
   "1,2;3,4 ,",
   ",", " , ",
   ";", " ; ",
   "a", " a; ", ";a;",
   "", " ",
@@ -123,8 +124,35 @@ const gInvalidPath = [
 
 // paths that at least start with a valid "M" segment are valid - the spec says
 // to parse everything up to the first invalid token
 const gValidPathWithErrors = [
  "M20 20em",
  "m0 0 L30,,30",
  "M10 10 L50 50 abc",
 ];
+
+const gValidKeyPoints = [
+  "0; 0.5; 1",
+  "0;.5;1",
+  "0; 0; 1",
+  "0; 1; 1",
+  "0; 0; 1;", // Trailing semicolons are allowed
+  "0; 0; 1; ",
+  "0; 0.000; 1",
+  "0; 0.000001; 1",
+];
+
+const gInvalidKeyPoints = [
+  "0; 1",
+  "0; 1;",
+  "0",
+  "1",
+  "a",
+  "",
+  "  ",
+  "0; -0.1; 1",
+  "0; 1.1; 1",
+  "0; 0.1; 1.1",
+  "-0.1; 0.1; 1",
+  "0; a; 1",
+  "0;;1",
+];
--- a/content/smil/test/test_smilAnimateMotionInvalidValues.xhtml
+++ b/content/smil/test/test_smilAnimateMotionInvalidValues.xhtml
@@ -59,16 +59,23 @@ function testAttr(aAttrName, aAttrValueA
       // and just test the rotation matrix components
       anim.setAttribute("values", "0 0; 50 50");
       componentsToCheck = CTMUtil.CTM_COMPONENTS_ROTATE;
     } else {
       // Apply a supplementary rotation to make sure that we don't apply it if
       // our value is rejected.
       anim.setAttribute("rotate", Math.PI/4);
       componentsToCheck = CTMUtil.CTM_COMPONENTS_ALL;
+      if (aAttrName == "keyPoints") {
+        // Add three times so we can test a greater range of values for
+        // keyPoints
+        anim.setAttribute("values", "0 0; 25 25; 50 50");
+        anim.setAttribute("keyTimes", "0; 0.5; 1");
+        anim.setAttribute("calcMode", "discrete");
+      }
     }
 
     var curCTM = gRect.getCTM();
     if (aIsValid) {
       var errMsg = "CTM should have changed when applying animateMotion " +
         "with '" + aAttrName + "' set to valid value '" + curVal + "'";
       CTMUtil.assertCTMNotEqual(curCTM, gUnAnimatedCTM, componentsToCheck,
                                 errMsg, aIsTodo);
@@ -153,16 +160,19 @@ function main()
 
   testAttr("by", gValidToBy, true, false);
   testAttr("by", gInvalidToBy, false, false);
 
   testAttr("path", gValidPath, true, false);
   testAttr("path", gInvalidPath, false, false);
   testAttr("path", gValidPathWithErrors, true, false);
 
+  testAttr("keyPoints", gValidKeyPoints, true, false);
+  testAttr("keyPoints", gInvalidKeyPoints, false, false);
+
   testMpathElem(gValidPath, true, false);
   testMpathElem(gInvalidPath, false, false);
 
   SimpleTest.finish();
 }
 
 window.addEventListener("load", main, false);
 ]]>
--- a/content/smil/test/test_smilTiming.xhtml
+++ b/content/smil/test/test_smilTiming.xhtml
@@ -13,101 +13,278 @@
 </svg>
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 <![CDATA[
 /** Test for SMIL timing **/
 
 /* Global Variables */
-const svgns="http://www.w3.org/2000/svg";
-var svg = document.getElementById("svg");
-var circle = document.getElementById('circle');
+const svgns = "http://www.w3.org/2000/svg";
+var gSvg    = document.getElementById("svg");
+var gCircle = document.getElementById('circle');
 
 SimpleTest.waitForExplicitFinish();
 
-function createAnim() {
+function main() {
+  ok(gSvg.animationsPaused(), "should be paused by <svg> load handler");
+  is(gSvg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
+
+  var testCases = Array();
+
+  const secPerMin = 60;
+  const secPerHour = secPerMin * 60;
+
+  // In the following tests that compare start times, getStartTime will round
+  // the start time to three decimal places since we expect our implementation
+  // to be millisecond accurate.
+
+  // Offset syntax
+  // -- Basic tests, sign and whitespace
+  testCases.push(StartTimeTest('3s', 3));
+  testCases.push(StartTimeTest('0s', 0));
+  testCases.push(StartTimeTest('+2s', 2));
+  testCases.push(StartTimeTest('-1s\t\r', -1));
+  testCases.push(StartTimeTest('- 1s', -1));
+  testCases.push(StartTimeTest('  -1s', -1));
+  testCases.push(StartTimeTest(' - 1s', -1));
+  testCases.push(StartTimeTest(' \t\n\r-1s', -1));
+  testCases.push(StartTimeTest('+\n5s', 5));
+  testCases.push(StartTimeTest('-\n5s', -5));
+  testCases.push(StartTimeTest('\t 5s', 5));
+  // -- These tests are from SMILANIM 3.6.7
+  testCases.push(StartTimeTest('02:30:03', 2*secPerHour + 30*secPerMin + 3));
+  testCases.push(StartTimeTest('50:00:10.25', 50*secPerHour + 10.25));
+  testCases.push(StartTimeTest('02:33', 2*secPerMin + 33));
+  testCases.push(StartTimeTest('00:10.5', 10.5));
+  testCases.push(StartTimeTest('3.2h', 3.2*secPerHour));
+  testCases.push(StartTimeTest('45min', 45*secPerMin));
+  testCases.push(StartTimeTest('30s', 30));
+  testCases.push(StartTimeTest('5ms', 0.005));
+  testCases.push(StartTimeTest('12.467', 12.467));
+  testCases.push(StartTimeTest('00.5s', 0.5));
+  testCases.push(StartTimeTest('00:00.005', 0.005));
+  // -- Additional tests
+  testCases.push(StartTimeTest('61:59:59', 61*secPerHour + 59*secPerMin + 59));
+  testCases.push(StartTimeTest('02:59.999999999999999999999', 3*secPerMin));
+  testCases.push(StartTimeTest('1234:23:45',
+                               1234*secPerHour + 23*secPerMin + 45));
+  testCases.push(StartTimeTest('61min', 61*secPerMin));
+  testCases.push(StartTimeTest('0:30:03', 30*secPerMin + 3));
+  // -- Fractional precision
+  testCases.push(StartTimeTest('25.4567', 25.457));
+  testCases.push(StartTimeTest('0.123456789', 0.123));
+  testCases.push(StartTimeTest('0.00000000000000000000001', 0));
+  testCases.push(StartTimeTest('-0.00000000000000000000001', 0));
+  testCases.push(StartTimeTest('0.0009', 0.001));
+  testCases.push(StartTimeTest('0.99999999999999999999999999999999999999', 1));
+  testCases.push(StartTimeTest('23.4567ms', 0.023));
+  testCases.push(StartTimeTest('23.7ms', 0.024));
+  // -- Test errors
+  testCases.push(StartTimeTest(' + +3s', 'none'));
+  testCases.push(StartTimeTest(' +-3s', 'none'));
+  testCases.push(StartTimeTest('1:12:12:12', 'none'));
+  testCases.push(StartTimeTest('4:50:60', 'none'));
+  testCases.push(StartTimeTest('4:60:0', 'none'));
+  testCases.push(StartTimeTest('4:60', 'none'));
+  testCases.push(StartTimeTest('4:-1:00', 'none'));
+  testCases.push(StartTimeTest('4 5m', 'none'));
+  testCases.push(StartTimeTest('4 5ms', 'none'));
+  testCases.push(StartTimeTest('02:3:03', 'none'));
+  testCases.push(StartTimeTest('45.7 s', 'none'));
+  testCases.push(StartTimeTest(' 3 h ', 'none'));
+  testCases.push(StartTimeTest('2:33 ', 'none'));
+  testCases.push(StartTimeTest('02:33 2', 'none'));
+  testCases.push(StartTimeTest('\u000B 02:33', 'none'));
+  testCases.push(StartTimeTest('h', 'none'));
+  testCases.push(StartTimeTest('23.s', 'none'));
+  testCases.push(StartTimeTest('23.', 'none'));
+  testCases.push(StartTimeTest('23.54.2s', 'none'));
+  testCases.push(StartTimeTest('23sec', 'none'));
+  testCases.push(StartTimeTest('five', 'none'));
+  testCases.push(StartTimeTest('', 'none'));
+  testCases.push(StartTimeTest('02:33s', 'none'));
+  testCases.push(StartTimeTest('02:33 s', 'none'));
+  testCases.push(StartTimeTest('2.54e6', 'none'));
+  testCases.push(StartTimeTest('02.5:33', 'none'));
+  testCases.push(StartTimeTest('2:-45:33', 'none'));
+  testCases.push(StartTimeTest('2:4.5:33', 'none'));
+  testCases.push(StartTimeTest('45m', 'none'));
+  testCases.push(StartTimeTest(':20:30', 'none'));
+  testCases.push(StartTimeTest('1.5:30', 'none'));
+  testCases.push(StartTimeTest('15:-30', 'none'));
+  testCases.push(StartTimeTest('::30', 'none'));
+  testCases.push(StartTimeTest('15:30s', 'none'));
+  testCases.push(StartTimeTest('2:1.:30', 'none'));
+  testCases.push(StartTimeTest('2:.1:30', 'none'));
+  testCases.push(StartTimeTest('2.0:15:30', 'none'));
+  testCases.push(StartTimeTest('2.:15:30', 'none'));
+  testCases.push(StartTimeTest('.2:15:30', 'none'));
+  testCases.push(StartTimeTest('70:15', 'none'));
+  testCases.push(StartTimeTest('media', 'none'));
+  testCases.push(StartTimeTest('5mi', 'none'));
+  testCases.push(StartTimeTest('5hours', 'none'));
+  testCases.push(StartTimeTest('h05:30', 'none'));
+  testCases.push(StartTimeTest('05:40\x9A', 'none'));
+  testCases.push(StartTimeTest('05:40\u30D5', 'none'));
+  testCases.push(StartTimeTest('05:40β', 'none'));
+
+  // List syntax
+  testCases.push(StartTimeTest('3', 3));
+  testCases.push(StartTimeTest('3;', 3));
+  testCases.push(StartTimeTest('3; ', 3));
+  testCases.push(StartTimeTest('3 ; ', 3));
+  testCases.push(StartTimeTest('3;;', 'none'));
+  testCases.push(StartTimeTest('3;; ', 'none'));
+  testCases.push(StartTimeTest(';3', 'none'));
+  testCases.push(StartTimeTest(' ;3', 'none'));
+  testCases.push(StartTimeTest('3;4', 3));
+  testCases.push(StartTimeTest(' 3 ; 4 ', 3));
+
+  // List syntax on end times
+  testCases.push({
+    'attr' : { 'begin': '0s',
+               'end': '1s; 2s' },
+    'times': [ [ 0, 0 ],
+               [ 1, -100 ] ]
+  });
+  testCases.push({
+    'attr' : { 'begin': '0s',
+               'end': '1s; 2s; ' },
+    'times': [ [ 0, 0 ],
+               [ 1, -100 ] ]
+  });
+  testCases.push({
+    'attr' : { 'begin': '0s',
+               'end': '3s; 2s' },
+    'times': [ [ 0, 0 ],
+               [ 1, 10 ],
+               [ 2, -100 ] ]
+  });
+
+  // Simple case
+  testCases.push({
+    'attr' : { 'begin': '3s' },
+    'times': [ [ 0, -100 ],
+               [ 4, 10 ] ]
+  });
+
+  // Multiple begins
+  testCases.push({
+    'attr' : { 'begin': '2s; 6s',
+               'dur': '2s' },
+    'times': [ [ 0, -100 ],
+               [ 3, 50 ],
+               [ 4, -100 ],
+               [ 7, 50 ],
+               [ 8, -100 ] ]
+  });
+
+  // Negative begins
+  testCases.push({
+    'attr' : { 'begin': '-3s; 1s ; 4s',
+               'dur': '2s ',
+               'fill': 'freeze' },
+    'times': [ [ 0, -100 ],
+               [ 0.5, -100 ],
+               [ 1, 0 ],
+               [ 2, 50 ],
+               [ 3, 100 ],
+               [ 5, 50 ] ]
+  });
+
+  // Sorting
+  testCases.push({
+    'attr' : { 'begin': '-3s; 110s; 1s; 4s; -5s; -10s',
+               'end': '111s; -5s; -15s; 6s; -5s; 1.2s',
+               'dur': '2s ',
+               'fill': 'freeze' },
+    'times': [ [ 0, -100 ],
+               [ 1, 0 ],
+               [ 2, 10 ],
+               [ 4, 0 ],
+               [ 5, 50 ],
+               [ 109, 100 ],
+               [ 110, 0 ],
+               [ 112, 50 ] ]
+  });
+
+  for (var i = 0; i < testCases.length; i++) {
+    gSvg.setCurrentTime(0);
+    var test = testCases[i];
+
+    // Generate string version of params for output messages
+    var params = "";
+    for (var name in test.attr) {
+      params += name + '="' + test.attr[name] + '" ';
+    }
+    params = params.trim();
+
+    // Create animation elements
+    var anim = createAnim(test.attr);
+
+    // Run samples
+    if ('times' in test) {
+      for (var j = 0; j < test.times.length; j++) {
+        var curSample = test.times[j];
+        checkSample(curSample[0], curSample[1], params);
+      }
+    }
+
+    // Check start time
+    if ('startTime' in test) {
+      is(getStartTime(anim), test.startTime,
+         "Got unexpected start time for " + params);
+    }
+
+    anim.parentNode.removeChild(anim);
+  }
+
+  SimpleTest.finish();
+}
+
+function createAnim(attr) {
   var anim = document.createElementNS(svgns,'animate');
   anim.setAttribute('attributeName','cx');
   anim.setAttribute('from','0');
   anim.setAttribute('to','100');
   anim.setAttribute('dur','10s');
   anim.setAttribute('begin','indefinite');
-  return circle.appendChild(anim);
-}
-
-function removeAnim(anim) {
-  anim.parentNode.removeChild(anim);
+  for (name in attr) {
+    anim.setAttribute(name, attr[name]);
+  }
+  return gCircle.appendChild(anim);
 }
 
-function main() {
-  ok(svg.animationsPaused(), "should be paused by <svg> load handler");
-  is(svg.getCurrentTime(), 0, "should be paused at 0 in <svg> load handler");
-
-  var tests =
-    [ testOffsetStartup,
-      testMultipleBegins,
-      testNegativeBegins,
-      testSorting
-    ];
-  for (var i = 0; i < tests.length; i++) {
-    var anim = createAnim();
-    svg.setCurrentTime(0);
-    tests[i](anim);
-    removeAnim(anim);
-  }
-  SimpleTest.finish();
-}
-
-function checkSample(time, expectedValue) {
-  svg.setCurrentTime(time);
-  is(circle.cx.animVal.value, expectedValue);
+function checkSample(time, expectedValue, params) {
+  gSvg.setCurrentTime(time);
+  var msg = "Unexpected sample value for " + params +
+    " at t=" + time + ": ";
+  is(gCircle.cx.animVal.value, expectedValue);
 }
 
-function testOffsetStartup(anim) {
-  anim.setAttribute('begin', '3s');
-  checkSample(0,-100);
-  checkSample(4,10);
-}
-
-function testMultipleBegins(anim) {
-  anim.setAttribute('begin', '2s; 6s');
-  anim.setAttribute('dur', ' 2s');
-  checkSample(0,-100);
-  checkSample(3,50);
-  checkSample(4,-100);
-  checkSample(7,50);
-  checkSample(8,-100);
+function getStartTime(anim) {
+  var startTime;
+  try {
+    startTime = anim.getStartTime();
+    // We round start times to 3 decimal places to make comparisons simpler
+    startTime = parseFloat(startTime.toFixed(3));
+  } catch(e) {
+    if (e.code == DOMException.INVALID_STATE_ERR) {
+      startTime = 'none';
+    } else {
+      ok(false, "Unexpected exception: " + e);
+    }
+  }
+  return startTime;
 }
 
-function testNegativeBegins(anim) {
-  anim.setAttribute('begin', '-3s; 1s ; 4s');
-  anim.setAttribute('dur', '2s ');
-  anim.setAttribute('fill', 'freeze');
-  checkSample(0,-100);
-  checkSample(0.5,-100);
-  checkSample(1,0);
-  checkSample(2,50);
-  checkSample(3,100);
-  checkSample(5,50);
-}
-
-function testSorting(anim) {
-  anim.setAttribute('begin', '-3s; 110s; 1s; 4s; -5s; -10s');
-  anim.setAttribute('end', '111s; -5s; -15s; 6s; -5s; 1.2s');
-  anim.setAttribute('dur', '2s ');
-  anim.setAttribute('fill', 'freeze');
-  checkSample(0,-100);
-  checkSample(1,0);
-  checkSample(2,10);
-  checkSample(4,0);
-  checkSample(5,50);
-  checkSample(109,100);
-  checkSample(110,0);
-  checkSample(112,50);
+function StartTimeTest(beginSpec, expectedStartTime) {
+  return { 'attr'     : { 'begin': beginSpec },
+           'startTime': expectedStartTime };
 }
 
 window.addEventListener("load", main, false);
 ]]>
 </script>
 </pre>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/smil/test/test_smilValues.xhtml
@@ -0,0 +1,170 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <title>Test for SMIL values</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank"
+  href="https://bugzilla.mozilla.org/show_bug.cgi?id=557885">Mozilla Bug
+  474742</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="120px" height="120px">
+  <circle cx="-100" cy="20" r="15" fill="blue" id="circle"/>
+</svg>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+/** Test for SMIL values **/
+
+var gSvg = document.getElementById("svg");
+SimpleTest.waitForExplicitFinish();
+
+function main()
+{
+  gSvg.pauseAnimations();
+
+  var testCases = Array();
+
+  // Single value
+  testCases.push({
+    'attr' : { 'values': 'a' },
+    'times': [ [ 0, 'a' ] ]
+  });
+
+  // The parsing below is based on the following discussion:
+  //
+  //   http://lists.w3.org/Archives/Public/www-svg/2011Nov/0136.html
+  //
+  // In summary:
+  // * Values lists are semi-colon delimited and semi-colon terminated.
+  // * However, if there are extra non-whitespace characters after the final
+  //   semi-colon then there's an implied semi-colon at the end.
+  //
+  // This differs to what is specified in SVG 1.1 but is consistent with the
+  // majority of browsers and with existing content (particularly that generated
+  // by Ikivo Animator).
+
+  // Trailing semi-colon
+  testCases.push({
+    'attr' : { 'values': 'a;' },
+    'times': [ [ 0, 'a' ], [ 10, 'a' ] ]
+  });
+
+  // Trailing semi-colon + whitespace
+  testCases.push({
+    'attr' : { 'values': 'a; ' },
+    'times': [ [ 0, 'a' ], [ 10, 'a' ] ]
+  });
+
+  // Whitespace + trailing semi-colon
+  testCases.push({
+    'attr' : { 'values': 'a ;' },
+    'times': [ [ 0, 'a' ], [ 10, 'a' ] ]
+  });
+
+  // Empty at end
+  testCases.push({
+    'attr' : { 'values': 'a;;' },
+    'times': [ [ 0, 'a' ], [ 5, '' ], [ 10, '' ] ]
+  });
+
+  // Empty at end + whitespace
+  testCases.push({
+    'attr' : { 'values': 'a;; ' },
+    'times': [ [ 0, 'a' ], [ 4, 'a' ], [ 5, '' ], [ 10, '' ] ]
+  });
+
+  // Empty in middle
+  testCases.push({
+    'attr' : { 'values': 'a;;b' },
+    'times': [ [ 0, 'a' ], [ 5, '' ], [ 10, 'b' ] ]
+  });
+
+  // Empty in middle + trailing semi-colon
+  testCases.push({
+    'attr' : { 'values': 'a;;b;' },
+    'times': [ [ 0, 'a' ], [ 5, '' ], [ 10, 'b' ] ]
+  });
+
+  // Whitespace in middle
+  testCases.push({
+    'attr' : { 'values': 'a; ;b' },
+    'times': [ [ 0, 'a' ], [ 5, '' ], [ 10, 'b' ] ]
+  });
+
+  // Empty at start
+  testCases.push({
+    'attr' : { 'values': ';a' },
+    'times': [ [ 0, '' ], [ 5, 'a' ], [ 10, 'a' ] ]
+  });
+
+  // Whitespace at start
+  testCases.push({
+    'attr' : { 'values': ' ;a' },
+    'times': [ [ 0, '' ], [ 5, 'a' ], [ 10, 'a' ] ]
+  });
+
+  // Embedded whitespace
+  testCases.push({
+    'attr' : { 'values': ' a b ; c d ' },
+    'times': [ [ 0, 'a b' ], [ 5, 'c d' ], [ 10, 'c d' ] ]
+  });
+
+  // Whitespace only
+  testCases.push({
+    'attr' : { 'values': '  ' },
+    'times': [ [ 0, '' ], [ 10, '' ] ]
+  });
+
+  for (var i = 0; i < testCases.length; i++) {
+    gSvg.setCurrentTime(0);
+    var test = testCases[i];
+
+    // Create animation elements
+    var anim = createAnim(test.attr);
+
+    // Run samples
+    for (var j = 0; j < test.times.length; j++) {
+      var curSample = test.times[j];
+      gSvg.setCurrentTime(curSample[0]);
+      checkSample(anim, curSample[1], curSample[0], i);
+    }
+
+    anim.parentNode.removeChild(anim);
+  }
+
+  SimpleTest.finish();
+}
+
+function createAnim(attr)
+{
+  const svgns = "http://www.w3.org/2000/svg";
+  var anim = document.createElementNS(svgns, 'animate');
+  anim.setAttribute('attributeName','class');
+  anim.setAttribute('dur','10s');
+  anim.setAttribute('begin','0s');
+  anim.setAttribute('fill','freeze');
+  for (name in attr) {
+    anim.setAttribute(name, attr[name]);
+  }
+  return document.getElementById('circle').appendChild(anim);
+}
+
+function checkSample(anim, expectedValue, sampleTime, caseNum)
+{
+  var msg = "Test case " + caseNum +
+    " (values: '" + anim.getAttribute('values') + "')," +
+    "t=" + sampleTime +
+    ": Unexpected sample value:";
+  is(anim.targetElement.className.animVal, expectedValue, msg);
+}
+
+window.addEventListener("load", main, false);
+]]>
+</script>
+</pre>
+</body>
+</html>
--- a/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp
+++ b/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp
@@ -442,17 +442,17 @@ SVGMotionSMILAnimationFunction::SetKeyPo
   mHasChanged = true;
 
   return NS_OK;
 }
 
 void
 SVGMotionSMILAnimationFunction::UnsetKeyPoints()
 {
-  mKeyTimes.Clear();
+  mKeyPoints.Clear();
   SetKeyPointsErrorFlag(false);
   mHasChanged = true;
 }
 
 nsresult
 SVGMotionSMILAnimationFunction::SetRotate(const nsAString& aRotate,
                                           nsAttrValue& aResult)
 {
--- a/content/xslt/src/xpath/nsXPathNamespace.cpp
+++ b/content/xslt/src/xpath/nsXPathNamespace.cpp
@@ -148,17 +148,17 @@ NS_IMETHODIMP nsXPathNamespace::AppendCh
 
 /* boolean hasChildNodes (); */
 NS_IMETHODIMP nsXPathNamespace::HasChildNodes(bool *aResult)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* nsIDOMNode cloneNode (in boolean deep); */
-NS_IMETHODIMP nsXPathNamespace::CloneNode(bool deep, nsIDOMNode **aResult)
+NS_IMETHODIMP nsXPathNamespace::CloneNode(bool deep, PRUint8 aOptionalArgc, nsIDOMNode **aResult)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 /* void normalize (); */
 NS_IMETHODIMP nsXPathNamespace::Normalize()
 {
     return NS_ERROR_NOT_IMPLEMENTED;
--- a/content/xul/templates/src/nsXULContentBuilder.cpp
+++ b/content/xul/templates/src/nsXULContentBuilder.cpp
@@ -672,17 +672,17 @@ nsXULContentBuilder::BuildContentFromTem
         }
         else if (tmplKid->IsNodeOfType(nsINode::eTEXT)) {
             nsCOMPtr<nsIDOMNode> tmplTextNode = do_QueryInterface(tmplKid);
             if (!tmplTextNode) {
                 NS_ERROR("textnode not implementing nsIDOMNode??");
                 return NS_ERROR_FAILURE;
             }
             nsCOMPtr<nsIDOMNode> clonedNode;
-            tmplTextNode->CloneNode(false, getter_AddRefs(clonedNode));
+            tmplTextNode->CloneNode(false, 1, getter_AddRefs(clonedNode));
             nsCOMPtr<nsIContent> clonedContent = do_QueryInterface(clonedNode);
             if (!clonedContent) {
                 NS_ERROR("failed to clone textnode");
                 return NS_ERROR_FAILURE;
             }
             rv = aRealNode->AppendChildTo(clonedContent, aNotify);
             if (NS_FAILED(rv)) return rv;
         }
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2305,44 +2305,16 @@ nsDocShell::HistoryTransactionRemoved(PR
             static_cast<nsDocShell*>(shell.get())->
                 HistoryTransactionRemoved(aIndex);
         }
     }
 
     return NS_OK;
 }
 
-static
-nsresult
-GetPrincipalDomain(nsIPrincipal* aPrincipal, nsACString& aDomain)
-{
-  aDomain.Truncate();
-
-  nsCOMPtr<nsIURI> codebaseURI;
-  nsresult rv = aPrincipal->GetDomain(getter_AddRefs(codebaseURI));
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!codebaseURI) {
-     rv = aPrincipal->GetURI(getter_AddRefs(codebaseURI));
-     NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  if (!codebaseURI)
-     return NS_OK;
-
-  nsCOMPtr<nsIURI> innerURI = NS_GetInnermostURI(codebaseURI);
-  NS_ASSERTION(innerURI, "Failed to get innermost URI");
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = innerURI->GetAsciiHost(aDomain);
-  if (NS_FAILED(rv))
-      return rv;
-
-  return NS_OK;
-}
-
 NS_IMETHODIMP
 nsDocShell::GetSessionStorageForPrincipal(nsIPrincipal* aPrincipal,
                                           const nsAString& aDocumentURI,
                                           bool aCreate,
                                           nsIDOMStorage** aStorage)
 {
     NS_ENSURE_ARG_POINTER(aStorage);
     *aStorage = nsnull;
@@ -2362,64 +2334,75 @@ nsDocShell::GetSessionStorageForPrincipa
 
     nsDocShell* topDocShell = static_cast<nsDocShell*>(topItem.get());
     if (topDocShell != this)
         return topDocShell->GetSessionStorageForPrincipal(aPrincipal,
                                                           aDocumentURI,
                                                           aCreate,
                                                           aStorage);
 
-    nsCAutoString currentDomain;
-    rv = GetPrincipalDomain(aPrincipal, currentDomain);
+    nsXPIDLCString origin;
+    rv = aPrincipal->GetOrigin(getter_Copies(origin));
     if (NS_FAILED(rv))
         return rv;
 
-    if (currentDomain.IsEmpty())
+    if (origin.IsEmpty())
         return NS_OK;
 
-    if (!mStorages.Get(currentDomain, aStorage) && aCreate) {
+    if (!mStorages.Get(origin, aStorage) && aCreate) {
         nsCOMPtr<nsIDOMStorage> newstorage =
             do_CreateInstance("@mozilla.org/dom/storage;2");
         if (!newstorage)
             return NS_ERROR_OUT_OF_MEMORY;
 
         nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(newstorage);
         if (!pistorage)
             return NS_ERROR_FAILURE;
+
         rv = pistorage->InitAsSessionStorage(aPrincipal, aDocumentURI);
         if (NS_FAILED(rv))
             return rv;
 
-        if (!mStorages.Put(currentDomain, newstorage))
+        if (!mStorages.Put(origin, newstorage))
             return NS_ERROR_OUT_OF_MEMORY;
 
         newstorage.swap(*aStorage);
 #if defined(PR_LOGGING) && defined(DEBUG)
         PR_LOG(gDocShellLog, PR_LOG_DEBUG,
                ("nsDocShell[%p]: created a new sessionStorage %p",
                 this, *aStorage));
 #endif
     }
     else if (*aStorage) {
-      nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(*aStorage);
-      if (piStorage) {
-          bool canAccess = piStorage->CanAccess(aPrincipal);
-          NS_ASSERTION(canAccess,
-                       "GetSessionStorageForPrincipal got a storage "
-                       "that could not be accessed!");
-          if (!canAccess) {
-              NS_RELEASE(*aStorage);
-              return NS_ERROR_DOM_SECURITY_ERR;
-          }
-      }
+        nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(*aStorage);
+        if (piStorage) {
+            nsCOMPtr<nsIPrincipal> storagePrincipal = piStorage->Principal();
+
+            // The origin string used to map items in the hash table is 
+            // an implicit security check. That check is double-confirmed 
+            // by checking the principal a storage was demanded for 
+            // really is the principal for which that storage was originally 
+            // created. Originally, the check was hidden in the CanAccess 
+            // method but it's implementation has changed.
+            bool equals;
+            nsresult rv = aPrincipal->EqualsIgnoringDomain(storagePrincipal, &equals);
+            NS_ASSERTION(NS_SUCCEEDED(rv) && equals,
+                         "GetSessionStorageForPrincipal got a storage "
+                         "that could not be accessed!");
+
+            if (NS_FAILED(rv) || !equals) {
+                NS_RELEASE(*aStorage);
+                return NS_ERROR_DOM_SECURITY_ERR;
+            }
+        }
 
 #if defined(PR_LOGGING) && defined(DEBUG)
-      PR_LOG(gDocShellLog, PR_LOG_DEBUG,
-             ("nsDocShell[%p]: returns existing sessionStorage %p",
-              this, *aStorage));
+        PR_LOG(gDocShellLog, PR_LOG_DEBUG,
+               ("nsDocShell[%p]: returns existing sessionStorage %p",
+                this, *aStorage));
 #endif
     }
 
     if (aCreate) {
         // We are asked to create a new storage object. This indicates
         // that a new windows wants it. At this moment we "fork" the existing
         // storage object (what it means is described in the paragraph bellow).
         // We must create a single object per a single window to distinguish
@@ -2494,34 +2477,34 @@ nsDocShell::AddSessionStorage(nsIPrincip
     nsCOMPtr<nsIDocShellTreeItem> topItem;
     nsresult rv = GetSameTypeRootTreeItem(getter_AddRefs(topItem));
     if (NS_FAILED(rv))
         return rv;
 
     if (topItem) {
         nsCOMPtr<nsIDocShell> topDocShell = do_QueryInterface(topItem);
         if (topDocShell == this) {
-            nsCAutoString currentDomain;
-            rv = GetPrincipalDomain(aPrincipal, currentDomain);
+            nsXPIDLCString origin;
+            rv = aPrincipal->GetOrigin(getter_Copies(origin));
             if (NS_FAILED(rv))
                 return rv;
 
-            if (currentDomain.IsEmpty())
+            if (origin.IsEmpty())
                 return NS_ERROR_FAILURE;
 
             // Do not replace an existing session storage.
-            if (mStorages.GetWeak(currentDomain))
+            if (mStorages.GetWeak(origin))
                 return NS_ERROR_NOT_AVAILABLE;
 
 #if defined(PR_LOGGING) && defined(DEBUG)
             PR_LOG(gDocShellLog, PR_LOG_DEBUG,
                    ("nsDocShell[%p]: was added a sessionStorage %p",
                     this, aStorage));
 #endif
-            if (!mStorages.Put(currentDomain, aStorage))
+            if (!mStorages.Put(origin, aStorage))
                 return NS_ERROR_OUT_OF_MEMORY;
         }
         else {
             return topDocShell->AddSessionStorage(aPrincipal, aStorage);
         }
     }
 
     return NS_OK;
new file mode 100644
--- /dev/null
+++ b/dom/base/DOMRequest.cpp
@@ -0,0 +1,173 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DOMRequest.h"
+
+#include "mozilla/Util.h"
+#include "nsDOMClassInfo.h"
+#include "DOMError.h"
+#include "nsEventDispatcher.h"
+#include "nsIPrivateDOMEvent.h"
+#include "nsDOMEvent.h"
+
+using mozilla::dom::DOMRequest;
+using mozilla::dom::DOMRequestService;
+
+DOMRequest::DOMRequest(nsIDOMWindow* aWindow)
+  : mDone(false)
+  , mResult(JSVAL_VOID)
+  , mRooted(false)
+{
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
+  mOwner = window->IsInnerWindow() ? window.get() :
+                                     window->GetCurrentInnerWindow();
+
+  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aWindow);
+  mScriptContext = sgo->GetContext();
+}
+
+DOMCI_DATA(DOMRequest, DOMRequest)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(DOMRequest)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMRequest,
+                                                  nsDOMEventTargetHelper)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(success)
+  NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(error)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMRequest,
+                                                nsDOMEventTargetHelper)
+  tmp->mResult = JSVAL_VOID;
+  tmp->UnrootResultVal();
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(success)
+  NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(error)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DOMRequest,
+                                               nsDOMEventTargetHelper)
+  // Don't need NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER because
+  // nsDOMEventTargetHelper does it for us.
+  if (JSVAL_IS_GCTHING(tmp->mResult)) {
+    void *gcThing = JSVAL_TO_GCTHING(tmp->mResult);
+    NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(gcThing, "mResult")
+  }
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMRequest)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMDOMRequest)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DOMRequest)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(DOMRequest, nsDOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(DOMRequest, nsDOMEventTargetHelper)
+
+NS_IMPL_EVENT_HANDLER(DOMRequest, success);
+NS_IMPL_EVENT_HANDLER(DOMRequest, error);
+
+NS_IMETHODIMP
+DOMRequest::GetReadyState(nsAString& aReadyState)
+{
+  mDone ? aReadyState.AssignLiteral("done") :
+          aReadyState.AssignLiteral("pending");
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMRequest::GetResult(jsval* aResult)
+{
+  NS_ASSERTION(mDone || mResult == JSVAL_VOID,
+               "Result should be undefined when pending");
+  *aResult = mResult;
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMRequest::GetError(nsIDOMDOMError** aError)
+{
+  NS_ASSERTION(mDone || !mError,
+               "Error should be null when pending");
+
+  NS_IF_ADDREF(*aError = mError);
+
+  return NS_OK;
+}
+
+void
+DOMRequest::FireSuccess(jsval aResult)
+{
+  NS_ABORT_IF_FALSE(!mDone, "Already fired success/error");
+
+  mDone = true;
+  RootResultVal();
+  mResult = aResult;
+
+  FireEvent(NS_LITERAL_STRING("success"));
+}
+
+void
+DOMRequest::FireError(const nsAString& aError)
+{
+  NS_ABORT_IF_FALSE(!mDone, "Already fired success/error");
+
+  mDone = true;
+  mError = DOMError::CreateWithName(aError);
+
+  FireEvent(NS_LITERAL_STRING("error"));
+}
+
+void
+DOMRequest::FireEvent(const nsAString& aType)
+{
+  if (NS_FAILED(CheckInnerWindowCorrectness())) {
+    return;
+  }
+
+  nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
+  nsresult rv = event->InitEvent(aType, false, false);
+  if (NS_FAILED(rv)) {
+    return;
+  }
+
+  rv = event->SetTrusted(PR_TRUE);
+  if (NS_FAILED(rv)) {
+    return;
+  }
+
+  bool dummy;
+  DispatchEvent(event, &dummy);
+}
+
+NS_IMPL_ISUPPORTS1(DOMRequestService, nsIDOMRequestService)
+
+NS_IMETHODIMP
+DOMRequestService::CreateRequest(nsIDOMWindow* aWindow,
+                                 nsIDOMDOMRequest** aRequest)
+{
+  NS_ADDREF(*aRequest = new DOMRequest(aWindow));
+  
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMRequestService::FireSuccess(nsIDOMDOMRequest* aRequest,
+                               const jsval& aResult)
+{
+  static_cast<DOMRequest*>(aRequest)->FireSuccess(aResult);
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DOMRequestService::FireError(nsIDOMDOMRequest* aRequest,
+                             const nsAString& aError)
+{
+  static_cast<DOMRequest*>(aRequest)->FireError(aError);
+
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/dom/base/DOMRequest.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_domrequest_h__
+#define mozilla_dom_domrequest_h__
+
+#include "nsIDOMDOMRequest.h"
+#include "nsIDOMDOMError.h"
+#include "nsDOMEventTargetHelper.h"
+#include "nsContentUtils.h"
+
+#include "nsCOMPtr.h"
+
+namespace mozilla {
+namespace dom {
+
+class DOMRequest : public nsDOMEventTargetHelper,
+                   public nsIDOMDOMRequest
+{
+  bool mDone;
+  jsval mResult;
+  nsCOMPtr<nsIDOMDOMError> mError;
+  bool mRooted;
+
+  NS_DECL_EVENT_HANDLER(success)
+  NS_DECL_EVENT_HANDLER(error)
+
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_NSIDOMDOMREQUEST
+  NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
+
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DOMRequest,
+                                                         nsDOMEventTargetHelper)
+
+  void FireSuccess(jsval aResult);
+  void FireError(const nsAString& aError);
+
+  DOMRequest(nsIDOMWindow* aWindow);
+
+  virtual ~DOMRequest()
+  {
+    UnrootResultVal();
+  }
+
+private:
+  void FireEvent(const nsAString& aType);
+
+  void RootResultVal()
+  {
+    if (!mRooted) {
+      NS_HOLD_JS_OBJECTS(this, DOMRequest);
+      mRooted = true;
+    }
+  }
+
+  void UnrootResultVal()
+  {
+    if (mRooted) {
+      NS_DROP_JS_OBJECTS(this, DOMRequest);
+      mRooted = false;
+    }
+  }
+};
+
+class DOMRequestService : public nsIDOMRequestService
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIDOMREQUESTSERVICE
+
+  // Returns an owning reference! No one should call this but the factory.
+  static DOMRequestService* FactoryCreate()
+  {
+    DOMRequestService* res = new DOMRequestService;
+    NS_ADDREF(res);
+    return res;
+  }
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#define DOMREQUEST_SERVICE_CONTRACTID "@mozilla.org/dom/dom-request-service;1"
+
+#endif // mozilla_dom_domrequest_h__
--- a/dom/base/Makefile.in
+++ b/dom/base/Makefile.in
@@ -42,16 +42,20 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= dom
 LIBRARY_NAME	= jsdombase_s
 LIBXUL_LIBRARY	= 1
 FORCE_STATIC_LIB = 1
 
+DIRS = \
+  test \
+  $(NULL)
+
 EXTRA_PP_COMPONENTS = \
 		ConsoleAPI.js \
 		ConsoleAPI.manifest \
 		$(NULL)
 
 EXTRA_JS_MODULES = ConsoleAPIStorage.jsm \
 		$(NULL)
 
@@ -62,16 +66,17 @@ EXTRA_COMPONENTS = \
 		$(NULL)
 
 EXTRA_JS_MODULES += Webapps.jsm \
 		$(NULL)
 endif
 
 XPIDLSRCS = \
   nsIDOMDOMError.idl \
+  nsIDOMDOMRequest.idl \
   nsIEntropyCollector.idl \
   nsIScriptChannel.idl \
   $(NULL)
 
 EXPORTS = \
   nsDOMCID.h \
   nsDOMClassInfoClasses.h \
   nsDOMClassInfoID.h \
@@ -100,16 +105,17 @@ EXPORTS = \
   nsContentPermissionHelper.h \
   nsStructuredCloneContainer.h \
   nsDOMMemoryReporter.h \
   $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom
 EXPORTS_mozilla/dom = \
   DOMError.h \
+  DOMRequest.h \
   StructuredCloneTags.h \
   $(NULL)
 
 CPPSRCS =			\
 	nsBarProps.cpp          \
 	nsDOMException.cpp 	\
 	nsDOMWindowUtils.cpp 	\
 	nsJSEnvironment.cpp	\
@@ -130,16 +136,17 @@ CPPSRCS =			\
 	nsDOMScriptObjectFactory.cpp \
 	nsQueryContentEventResult.cpp \
 	nsContentPermissionHelper.cpp \
 	nsStructuredCloneContainer.cpp \
 	nsDOMNavigationTiming.cpp \
 	nsPerformance.cpp	\
 	nsDOMMemoryReporter.cpp \
 	DOMError.cpp \
+	DOMRequest.cpp \
 	Navigator.cpp \
 	$(NULL)
 
 include $(topsrcdir)/dom/dom-config.mk
 
 ifdef MOZ_JSDEBUGGER
 DEFINES += -DMOZ_JSDEBUGGER
 endif
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -532,16 +532,17 @@ using mozilla::dom::indexedDB::IDBWrappe
 #include "CallEvent.h"
 #endif
 
 #ifdef MOZ_B2G_BT
 #include "BluetoothAdapter.h"
 #endif
 
 #include "DOMError.h"
+#include "DOMRequest.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
   "chrome://global/locale/dom/dom.properties";
@@ -1538,16 +1539,18 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(WebGLShaderPrecisionFormat, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLActiveInfo, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLExtension, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLExtensionStandardDerivatives, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(WebGLExtensionTextureFilterAnisotropic, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLExtensionLoseContext, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PaintRequestList, nsPaintRequestListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
@@ -1633,16 +1636,19 @@ static nsDOMClassInfoData sClassInfoData
 
 #ifdef MOZ_B2G_BT
   NS_DEFINE_CLASSINFO_DATA(BluetoothAdapter, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
   NS_DEFINE_CLASSINFO_DATA(DOMError, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
+  NS_DEFINE_CLASSINFO_DATA(DOMRequest, nsEventTargetSH,
+                           EVENTTARGET_SCRIPTABLE_FLAGS)
 };
 
 // Objects that should be constructable through |new Name();|
 struct nsContractIDMapData
 {
   PRInt32 mDOMClassInfoID;
   const char *mContractID;
 };
@@ -4199,16 +4205,20 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLExtension, nsIWebGLExtension)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtension)
   DOM_CLASSINFO_MAP_END
   
   DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionStandardDerivatives, nsIWebGLExtensionStandardDerivatives)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionStandardDerivatives)
   DOM_CLASSINFO_MAP_END
+  
+  DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionTextureFilterAnisotropic, nsIWebGLExtensionTextureFilterAnisotropic)
+    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionTextureFilterAnisotropic)
+  DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLExtensionLoseContext, nsIWebGLExtensionLoseContext)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLExtensionLoseContext)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
    DOM_CLASSINFO_MAP_END
@@ -4376,16 +4386,21 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMBluetoothAdapter)
   DOM_CLASSINFO_MAP_END
 #endif
 
   DOM_CLASSINFO_MAP_BEGIN(DOMError, nsIDOMDOMError)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMError)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN(DOMRequest, nsIDOMDOMRequest)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMRequest)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
+  DOM_CLASSINFO_MAP_END
+
 #ifdef NS_DEBUG
   {
     PRUint32 i = ArrayLength(sClassInfoData);
 
     if (i != eDOMClassInfoIDCount) {
       NS_ERROR("The number of items in sClassInfoData doesn't match the "
                "number of nsIDOMClassInfo ID's, this is bad! Fix it!");
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -481,16 +481,17 @@ DOMCI_CLASS(WebGLProgram)
 DOMCI_CLASS(WebGLShader)
 DOMCI_CLASS(WebGLFramebuffer)
 DOMCI_CLASS(WebGLRenderbuffer)
 DOMCI_CLASS(WebGLUniformLocation)
 DOMCI_CLASS(WebGLShaderPrecisionFormat)
 DOMCI_CLASS(WebGLActiveInfo)
 DOMCI_CLASS(WebGLExtension)
 DOMCI_CLASS(WebGLExtensionStandardDerivatives)
+DOMCI_CLASS(WebGLExtensionTextureFilterAnisotropic)
 DOMCI_CLASS(WebGLExtensionLoseContext)
 
 DOMCI_CLASS(PaintRequest)
 DOMCI_CLASS(PaintRequestList)
 
 DOMCI_CLASS(ScrollAreaEvent)
 DOMCI_CLASS(PopStateEvent)
 DOMCI_CLASS(HashChangeEvent)
@@ -540,8 +541,9 @@ DOMCI_CLASS(TelephonyCall)
 DOMCI_CLASS(CallEvent)
 #endif
 
 #ifdef MOZ_B2G_BT
 DOMCI_CLASS(BluetoothAdapter)
 #endif
 
 DOMCI_CLASS(DOMError)
+DOMCI_CLASS(DOMRequest)
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -2338,18 +2338,27 @@ nsFocusManager::DetermineElementToMoveFo
 {
   *aNextContent = nsnull;
 
   nsCOMPtr<nsIDocShell> docShell = aWindow->GetDocShell();
   if (!docShell)
     return NS_OK;
 
   nsCOMPtr<nsIContent> startContent = aStartContent;
-  if (!startContent && aType != MOVEFOCUS_CARET)
-    startContent = aWindow->GetFocusedNode();
+  if (!startContent && aType != MOVEFOCUS_CARET) {
+    if (aType == MOVEFOCUS_FORWARDDOC || aType == MOVEFOCUS_BACKWARDDOC) {
+      // When moving between documents, make sure to get the right
+      // starting content in a descendant.
+      nsCOMPtr<nsPIDOMWindow> focusedWindow;
+      startContent = GetFocusedDescendant(aWindow, true, getter_AddRefs(focusedWindow));
+    }
+    else {
+      startContent = aWindow->GetFocusedNode();
+    }
+  }
 
   nsCOMPtr<nsIDocument> doc;
   if (startContent)
     doc = startContent->GetCurrentDoc();
   else
     doc = do_QueryInterface(aWindow->GetExtantDocument());
   if (!doc)
     return NS_OK;
@@ -2357,21 +2366,21 @@ nsFocusManager::DetermineElementToMoveFo
   LookAndFeel::GetInt(LookAndFeel::eIntID_TabFocusModel,
                       &nsIContent::sTabFocusModel);
 
   if (aType == MOVEFOCUS_ROOT) {
     NS_IF_ADDREF(*aNextContent = GetRootForFocus(aWindow, doc, false, false));
     return NS_OK;
   }
   if (aType == MOVEFOCUS_FORWARDDOC) {
-    NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(true));
+    NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(startContent, true));
     return NS_OK;
   }
   if (aType == MOVEFOCUS_BACKWARDDOC) {
-    NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(false));
+    NS_IF_ADDREF(*aNextContent = GetNextTabbableDocument(startContent, false));
     return NS_OK;
   }
   
   nsIContent* rootContent = doc->GetRootElement();
   NS_ENSURE_TRUE(rootContent, NS_OK);
 
   nsIPresShell *presShell = doc->GetShell();
   NS_ENSURE_TRUE(presShell, NS_OK);
@@ -3131,76 +3140,202 @@ nsFocusManager::GetPreviousDocShell(nsID
 
   if (prevItem)
     GetLastDocShell(prevItem, aResult);
   else
     NS_ADDREF(*aResult = parentItem);
 }
 
 nsIContent*
-nsFocusManager::GetNextTabbableDocument(bool aForward)
+nsFocusManager::GetNextTabbablePanel(nsIDocument* aDocument, nsIFrame* aCurrentPopup, bool aForward)
 {
+  nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
+  if (!pm)
+    return nsnull;
+
+  // Iterate through the array backwards if aForward is false.
+  nsTArray<nsIFrame *> popups = pm->GetVisiblePopups();
+  PRInt32 i = aForward ? 0 : popups.Length() - 1;
+  PRInt32 end = aForward ? popups.Length() : -1;
+
+  for (; i != end; aForward ? i++ : i--) {
+    nsIFrame* popupFrame = popups[i];
+    if (aCurrentPopup) {
+      // If the current popup is set, then we need to skip over this popup and
+      // wait until the currently focused popup is found. Once found, the
+      // current popup will be cleared so that the next popup is used.
+      if (aCurrentPopup == popupFrame)
+        aCurrentPopup = nsnull;
+      continue;
+    }
+
+    // Skip over non-panels
+    if (popupFrame->GetContent()->Tag() != nsGkAtoms::panel ||
+        (aDocument && popupFrame->GetContent()->GetCurrentDoc() != aDocument)) {
+      continue;
+    }
+
+    // Find the first focusable content within the popup. If there isn't any
+    // focusable content in the popup, skip to the next popup.
+    nsIPresShell* presShell = popupFrame->PresContext()->GetPresShell();
+    if (presShell) {
+      nsCOMPtr<nsIContent> nextFocus;
+      nsIContent* popup = popupFrame->GetContent();
+      nsresult rv = GetNextTabbableContent(presShell, popup,
+                                           nsnull, popup,
+                                           true, 1, false,
+                                           getter_AddRefs(nextFocus));
+      if (NS_SUCCEEDED(rv) && nextFocus) {
+        return nextFocus.get();
+      }
+    }
+  }
+
+  return nsnull;
+}
+
+nsIContent*
+nsFocusManager::GetNextTabbableDocument(nsIContent* aStartContent, bool aForward)
+{
+  // If currentPopup is set, then the starting content is in a panel.
+  nsIFrame* currentPopup = nsnull;
+  nsCOMPtr<nsIDocument> doc;
   nsCOMPtr<nsIDocShellTreeItem> startItem;
-  if (mFocusedWindow) {
+
+  if (aStartContent) {
+    doc = aStartContent->GetCurrentDoc();
+    if (doc) {
+      startItem = do_QueryInterface(doc->GetWindow()->GetDocShell());
+    }
+
+    // Check if the starting content is inside a panel. Document navigation
+    // must start from this panel instead of the document root.
+    nsIContent* content = aStartContent;
+    while (content) {
+      if (content->NodeInfo()->Equals(nsGkAtoms::panel, kNameSpaceID_XUL)) {
+        currentPopup = content->GetPrimaryFrame();
+        break;
+      }
+      content = content->GetParent();
+    }
+  }
+  else if (mFocusedWindow) {
     startItem = do_QueryInterface(mFocusedWindow->GetDocShell());
+    doc = do_QueryInterface(mFocusedWindow->GetExtantDocument());
   }
   else {
     nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(mActiveWindow);
     startItem = do_QueryInterface(webnav);
+
+    if (mActiveWindow) {
+      doc = do_QueryInterface(mActiveWindow->GetExtantDocument());
+    }
   }
+
   if (!startItem)
     return nsnull;
 
   // perform a depth first search (preorder) of the docshell tree
   // looking for an HTML Frame or a chrome document
-  nsIContent* content = nsnull;
+  nsIContent* content = aStartContent;
   nsCOMPtr<nsIDocShellTreeItem> curItem = startItem;
   nsCOMPtr<nsIDocShellTreeItem> nextItem;
   do {
-    if (aForward) {
-      GetNextDocShell(curItem, getter_AddRefs(nextItem));
-      if (!nextItem) {
-        // wrap around to the beginning, which is the top of the tree
-        startItem->GetRootTreeItem(getter_AddRefs(nextItem));
+    // If moving forward, check for a panel in the starting document. If one
+    // exists with focusable content, return that content instead of the next
+    // document. If currentPopup is set, then, another panel may exist. If no
+    // such panel exists, then continue on to check the next document.
+    // When moving backwards, and the starting content is in a panel, then
+    // check for additional panels in the starting document. If the starting
+    // content is not in a panel, move back to the previous document and check
+    // for panels there.
+
+    bool checkPopups = false;
+    nsCOMPtr<nsPIDOMWindow> nextFrame = nsnull;
+
+    if (doc && (aForward || currentPopup)) {
+      nsIContent* popupContent = GetNextTabbablePanel(doc, currentPopup, aForward);
+      if (popupContent)
+        return popupContent;
+
+      if (!aForward && currentPopup) {
+        // The starting content was in a popup, yet no other popups were
+        // found. Move onto the starting content's document.
+        nextFrame = doc->GetWindow();
       }
     }
-    else {
-      GetPreviousDocShell(curItem, getter_AddRefs(nextItem));
-      if (!nextItem) {
-        // wrap around to the end, which is the last item in the tree
-        nsCOMPtr<nsIDocShellTreeItem> rootItem;
-        startItem->GetRootTreeItem(getter_AddRefs(rootItem));
-        GetLastDocShell(rootItem, getter_AddRefs(nextItem));
+
+    // Look for the next or previous document.
+    if (!nextFrame) {
+      if (aForward) {
+        GetNextDocShell(curItem, getter_AddRefs(nextItem));
+        if (!nextItem) {
+          // wrap around to the beginning, which is the top of the tree
+          startItem->GetRootTreeItem(getter_AddRefs(nextItem));
+        }
       }
+      else {
+        GetPreviousDocShell(curItem, getter_AddRefs(nextItem));
+        if (!nextItem) {
+          // wrap around to the end, which is the last item in the tree
+          nsCOMPtr<nsIDocShellTreeItem> rootItem;
+          startItem->GetRootTreeItem(getter_AddRefs(rootItem));
+          GetLastDocShell(rootItem, getter_AddRefs(nextItem));
+        }
+
+        // When going back to the previous document, check for any focusable
+        // popups in that previous document first.
+        checkPopups = true;
+      }
+
+      curItem = nextItem;
+      nextFrame = do_GetInterface(nextItem);
     }
 
-    curItem = nextItem;
-    nsCOMPtr<nsPIDOMWindow> nextFrame = do_GetInterface(nextItem);
     if (!nextFrame)
       return nsnull;
 
-    nsCOMPtr<nsIDocument> doc = do_QueryInterface(nextFrame->GetExtantDocument());
-    if (doc && !doc->EventHandlingSuppressed()) {
-      content = GetRootForFocus(nextFrame, doc, true, true);
-      if (content && !GetRootForFocus(nextFrame, doc, false, false)) {
-        // if the found content is in a chrome shell or a frameset, navigate
-        // forward one tabbable item so that the first item is focused. Note
-        // that we always go forward and not back here.
-        nsCOMPtr<nsIContent> nextFocus;
-        Element* rootElement = doc->GetRootElement();
-        nsIPresShell* presShell = doc->GetShell();
-        if (presShell) {
-          nsresult rv = GetNextTabbableContent(presShell, rootElement,
-                                               nsnull, rootElement,
-                                               true, 1, false,
-                                               getter_AddRefs(nextFocus));
-          return NS_SUCCEEDED(rv) ? nextFocus.get() : nsnull;
-        }
+    // Clear currentPopup for the next iteration
+    currentPopup = nsnull;
+
+    // If event handling is suppressed, move on to the next document. Set
+    // content to null so that the popup check will be skipped on the next
+    // loop iteration.
+    doc = do_QueryInterface(nextFrame->GetExtantDocument());
+    if (!doc || doc->EventHandlingSuppressed()) {
+      content = nsnull;
+      continue;
+    }
+
+    if (checkPopups) {
+      // When iterating backwards, check the panels of the previous document
+      // first. If a panel exists that has focusable content, focus that.
+      // Otherwise, continue on to focus the document.
+      nsIContent* popupContent = GetNextTabbablePanel(doc, nsnull, false);
+      if (popupContent)
+        return popupContent;
+    }
+
+    content = GetRootForFocus(nextFrame, doc, true, true);
+    if (content && !GetRootForFocus(nextFrame, doc, false, false)) {
+      // if the found content is in a chrome shell or a frameset, navigate
+      // forward one tabbable item so that the first item is focused. Note
+      // that we always go forward and not back here.
+      nsCOMPtr<nsIContent> nextFocus;
+      Element* rootElement = doc->GetRootElement();
+      nsIPresShell* presShell = doc->GetShell();
+      if (presShell) {
+        nsresult rv = GetNextTabbableContent(presShell, rootElement,
+                                             nsnull, rootElement,
+                                             true, 1, false,
+                                             getter_AddRefs(nextFocus));
+        return NS_SUCCEEDED(rv) ? nextFocus.get() : nsnull;
       }
     }
+
   } while (!content);
 
   return content;
 }
 
 void
 nsFocusManager::GetFocusInSelection(nsPIDOMWindow* aWindow,
                                     nsIContent* aStartSelection,
--- a/dom/base/nsFocusManager.h
+++ b/dom/base/nsFocusManager.h
@@ -454,26 +454,41 @@ protected:
 
   /**
    * Get the previous docshell child of aItem and return it in aResult.
    */
   void GetPreviousDocShell(nsIDocShellTreeItem* aItem,
                            nsIDocShellTreeItem** aResult);
 
   /**
-   * Get the tabbable next document from the currently focused frame if
-   * aForward is true, or the previously tabbable document if aForward is
-   * false. If this document is a chrome or frameset document, returns
-   * the first focusable element within this document, otherwise, returns
-   * the root node of the document.
+   * Determine the first panel with focusable content in document tab order
+   * from the given document. aForward indicates the direction to scan. If
+   * aCurrentPopup is set to a panel, the next or previous popup after
+   * aCurrentPopup after it is used. If aCurrentPopup is null, then the first
+   * or last popup is used. If a panel has no focusable content, it is skipped.
+   * Null is returned if no panel is open or no open panel contains a focusable
+   * element.
+   */
+  nsIContent* GetNextTabbablePanel(nsIDocument* aDocument, nsIFrame* aCurrentPopup, bool aForward);
+
+  /**
+   * Get the tabbable next document from aStartContent or, if null, the
+   * currently focused frame if aForward is true, or the previously tabbable
+   * document if aForward is false. If this document is a chrome or frameset
+   * document, returns the first focusable element within this document,
+   * otherwise, returns the root node of the document.
+   *
+   *
+   * Panels with focusable content are also placed in the cycling order, just
+   * after the document containing that panel.
    *
    * This method would be used for document navigation, which is typically
    * invoked by pressing F6.
    */
-  nsIContent* GetNextTabbableDocument(bool aForward);
+  nsIContent* GetNextTabbableDocument(nsIContent* aStartContent, bool aForward);
 
   /**
    * Retreives a focusable element within the current selection of aWindow.
    * Currently, this only detects links.
    *  
    * This is used when MoveFocus is called with a type of MOVEFOCUS_CARET,
    * which is used, for example, to focus links as the caret is moved over
    * them.
new file mode 100644
--- /dev/null
+++ b/dom/base/nsIDOMDOMRequest.idl
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDOMEventTarget.idl"
+
+interface nsIDOMDOMError;
+interface nsIDOMWindow;
+
+[scriptable, builtinclass, uuid(a3ad2846-ffb2-48d7-a786-2254cb82560d)]
+interface nsIDOMDOMRequest : nsIDOMEventTarget
+{
+  readonly attribute DOMString readyState; // "pending" or "done"
+
+  readonly attribute jsval result;
+  readonly attribute nsIDOMDOMError error;
+
+           attribute nsIDOMEventListener onsuccess;
+           attribute nsIDOMEventListener onerror;
+};
+
+[scriptable, builtinclass, uuid(eebcdf29-f8fa-4c36-bbc7-2146b1cbaf7b)]
+interface nsIDOMRequestService : nsISupports
+{
+  nsIDOMDOMRequest createRequest(in nsIDOMWindow window);
+
+  void fireSuccess(in nsIDOMDOMRequest request, in jsval result);
+  void fireError(in nsIDOMDOMRequest request, in DOMString error);
+};
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -3270,18 +3270,19 @@ nsJSContext::CycleCollectNow(nsICycleCol
   for (PRInt32 i = 0; i < aExtraForgetSkippableCalls; ++i) {
     nsCycleCollector_forgetSkippable();
   }
 
   // nsCycleCollector_forgetSkippable may mark some gray js to black.
   if (!sCleanupSinceLastGC && aExtraForgetSkippableCalls >= 0) {
     nsCycleCollector_forgetSkippable();
   }
-  PRUint32 collected = nsCycleCollector_collect(aListener);
-  sCCollectedWaitingForGC += collected;
+  nsCycleCollectorResults ccResults;
+  nsCycleCollector_collect(&ccResults, aListener);
+  sCCollectedWaitingForGC += ccResults.mFreedRefCounted + ccResults.mFreedGCed;
 
   // If we collected a substantial amount of cycles, poke the GC since more objects
   // might be unreachable now.
   if (sCCollectedWaitingForGC > 250) {
     PokeGC(js::gcreason::CC_WAITING);
   }
 
   PRTime now = PR_Now();
@@ -3298,26 +3299,33 @@ nsJSContext::CycleCollectNow(nsICycleCol
   if (sPostGCEventsToConsole) {
     PRTime delta = 0;
     if (sFirstCollectionTime) {
       delta = now - sFirstCollectionTime;
     } else {
       sFirstCollectionTime = now;
     }
 
+    nsString gcmsg;
+    if (ccResults.mForcedGC) {
+      gcmsg.AssignLiteral(", forced a GC");
+    }
+
     NS_NAMED_MULTILINE_LITERAL_STRING(kFmt,
-      NS_LL("CC(T+%.1f) collected: %lu (%lu waiting for GC), suspected: %lu, duration: %llu ms.\n")
+      NS_LL("CC(T+%.1f) duration: %llums, suspected: %lu, visited: %lu RCed and %lu GCed, collected: %lu RCed and %lu GCed (%lu waiting for GC)%s\n")
       NS_LL("ForgetSkippable %lu times before CC, min: %lu ms, max: %lu ms, avg: %lu ms, total: %lu ms, removed: %lu"));
     nsString msg;
     PRUint32 cleanups = sForgetSkippableBeforeCC ? sForgetSkippableBeforeCC : 1;
     sMinForgetSkippableTime = (sMinForgetSkippableTime == PR_UINT32_MAX)
       ? 0 : sMinForgetSkippableTime;
     msg.Adopt(nsTextFormatter::smprintf(kFmt.get(), double(delta) / PR_USEC_PER_SEC,
-                                        collected, sCCollectedWaitingForGC, suspected,
-                                        (now - start) / PR_USEC_PER_MSEC,
+                                        (now - start) / PR_USEC_PER_MSEC, suspected,
+                                        ccResults.mVisitedRefCounted, ccResults.mVisitedGCed,
+                                        ccResults.mFreedRefCounted, ccResults.mFreedGCed,
+                                        sCCollectedWaitingForGC, gcmsg.get(),
                                         sForgetSkippableBeforeCC,
                                         sMinForgetSkippableTime / PR_USEC_PER_MSEC,
                                         sMaxForgetSkippableTime / PR_USEC_PER_MSEC,
                                         (sTotalForgetSkippableTime / cleanups) /
                                           PR_USEC_PER_MSEC,
                                         sTotalForgetSkippableTime / PR_USEC_PER_MSEC,
                                         sRemovedPurples));
     nsCOMPtr<nsIConsoleService> cs =
--- a/dom/base/nsScreen.cpp
+++ b/dom/base/nsScreen.cpp
@@ -40,16 +40,17 @@
 #include "nsScreen.h"
 #include "nsIDocShell.h"
 #include "nsPresContext.h"
 #include "nsCOMPtr.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsLayoutUtils.h"
+#include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
 /* static */ bool nsScreen::sInitialized = false;
 /* static */ bool nsScreen::sAllowScreenEnabledProperty = false;
 /* static */ bool nsScreen::sAllowScreenBrightnessProperty = false;
 
@@ -257,71 +258,83 @@ nsScreen::GetAvailRect(nsRect& aRect)
   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height);
   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width);
 
   return NS_OK;
 }
 
 namespace {
 
-bool
-IsChromeType(nsIDocShell *aDocShell)
-{
+bool IsWhiteListed(nsIDocShell *aDocShell) {
   nsCOMPtr<nsIDocShellTreeItem> ds = do_QueryInterface(aDocShell);
   if (!ds) {
     return false;
   }
 
   PRInt32 itemType;
   ds->GetItemType(&itemType);
-  return itemType == nsIDocShellTreeItem::typeChrome;
+  if (itemType == nsIDocShellTreeItem::typeChrome) {
+    return true;
+  }
+
+  nsCOMPtr<nsIDocument> doc = do_GetInterface(aDocShell);
+  nsIPrincipal *principal = doc->NodePrincipal();
+
+  nsCOMPtr<nsIURI> principalURI;
+  principal->GetURI(getter_AddRefs(principalURI));
+  if (nsContentUtils::URIIsChromeOrInPref(principalURI,
+                                          "dom.mozScreenWhitelist")) {
+    return true;
+  }
+
+  return false;
 }
 
 } // anonymous namespace
 
 nsresult
 nsScreen::GetMozEnabled(bool *aEnabled)
 {
-  if (!sAllowScreenEnabledProperty || !IsChromeType(mDocShell)) {
+  if (!sAllowScreenEnabledProperty || !IsWhiteListed(mDocShell)) {
     *aEnabled = true;
     return NS_OK;
   }
 
   *aEnabled = hal::GetScreenEnabled();
   return NS_OK;
 }
 
 nsresult
 nsScreen::SetMozEnabled(bool aEnabled)
 {
-  if (!sAllowScreenEnabledProperty || !IsChromeType(mDocShell)) {
+  if (!sAllowScreenEnabledProperty || !IsWhiteListed(mDocShell)) {
     return NS_OK;
   }
 
   // TODO bug 707589: When the screen's state changes, all visible windows
   // should fire a visibility change event.
   hal::SetScreenEnabled(aEnabled);
   return NS_OK;
 }
 
 nsresult
 nsScreen::GetMozBrightness(double *aBrightness)
 {
-  if (!sAllowScreenBrightnessProperty || !IsChromeType(mDocShell)) {
+  if (!sAllowScreenEnabledProperty || !IsWhiteListed(mDocShell)) {
     *aBrightness = 1;
     return NS_OK;
   }
 
   *aBrightness = hal::GetScreenBrightness();
   return NS_OK;
 }
 
 nsresult
 nsScreen::SetMozBrightness(double aBrightness)
 {
-  if (!sAllowScreenBrightnessProperty || !IsChromeType(mDocShell)) {
+  if (!sAllowScreenEnabledProperty || !IsWhiteListed(mDocShell)) {
     return NS_OK;
   }
 
   NS_ENSURE_TRUE(0 <= aBrightness && aBrightness <= 1, NS_ERROR_INVALID_ARG);
   hal::SetScreenBrightness(aBrightness);
   return NS_OK;
 }
new file mode 100644
--- /dev/null
+++ b/dom/base/test/Makefile.in
@@ -0,0 +1,53 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Indexed Database Test Code.
+#
+# The Initial Developer of the Original Code is
+# The Mozilla Foundation.
+# Portions created by the Initial Developer are Copyright (C) 2010
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Shawn Wilsher <me@shawnwilsher.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+relativesrcdir = dom/base/test
+
+include $(DEPTH)/config/autoconf.mk
+include $(topsrcdir)/config/rules.mk
+
+TEST_FILES = \
+  test_domrequest.html \
+  $(NULL)
+
+libs:: $(TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
+
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_domrequest.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for XMLHttpRequest</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+"use strict";
+
+var reqserv = SpecialPowers.getDOMRequestService();
+ok("createRequest" in reqserv, "appears to be a service");
+
+// create a request
+var req = reqserv.createRequest(window);
+ok("result" in req, "request has result");
+ok("error" in req, "request has error");
+ok("onsuccess" in req, "request has onsuccess");
+ok("onerror" in req, "request has onerror");
+ok("readyState" in req, "request has readyState");
+
+is(req.readyState, "pending", "readyState is pending");
+is(req.result, undefined, "result is undefined");
+is(req.onsuccess, null, "onsuccess is null");
+is(req.onerror, null, "onerror is null");
+
+// fire success
+var ev = null;
+req.onsuccess = function(e) {
+  ev = e;
+}
+reqserv.fireSuccess(req, "my result");
+ok(ev, "got success event");
+is(ev.type, "success", "correct type during success");
+is(ev.target, req, "correct target during success");
+is(req.readyState, "done", "correct readyState after success");
+is(req.error, null, "correct error after success");
+is(req.result, "my result", "correct result after success");
+
+// fire error
+req = reqserv.createRequest(window);
+ev = null;
+req.onerror = function(e) {
+  ev = e;
+}
+reqserv.fireError(req, "OhMyError");
+ok(ev, "got success event");
+is(ev.type, "error", "correct type during error");
+is(ev.target, req, "correct target during error");
+is(req.readyState, "done", "correct readyState after error");
+is(req.error.name, "OhMyError", "correct error after error");
+is(req.result, undefined, "correct result after error");
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -1,39 +1,163 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=40: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "nsDOMClassInfo.h"
+#include "nsDOMEvent.h"
+#include "nsThreadUtils.h"
+#include "nsXPCOMCIDInternal.h"
+#include "mozilla/LazyIdleThread.h"
+
 #include "BluetoothAdapter.h"
-#include "nsDOMClassInfo.h"
+
+#if defined(MOZ_WIDGET_GONK)
+#include <bluedroid/bluetooth.h>
+#endif
+
+#define POWERED_EVENT_NAME NS_LITERAL_STRING("powered")
+
+BEGIN_BLUETOOTH_NAMESPACE
+
+class ToggleBtResultTask : public nsRunnable
+{
+  public:
+    ToggleBtResultTask(bool result, nsRefPtr<BluetoothAdapter>& adapterPtr)
+      : mResult(result)
+    {
+      MOZ_ASSERT(!NS_IsMainThread()); // This should be running on the worker thread
+
+      mAdapterPtr.swap(adapterPtr);
+    }
+
+    NS_IMETHOD Run() {
+      MOZ_ASSERT(NS_IsMainThread()); // This method is supposed to run on the main thread!
+      mAdapterPtr->FirePowered();
+
+      return NS_OK;
+    }
+
+  private:
+    bool mResult;
+    nsRefPtr<BluetoothAdapter> mAdapterPtr;
+};
+
+class ToggleBtTask : public nsRunnable
+{
+  public:
+    ToggleBtTask(bool onOff, BluetoothAdapter* adapterPtr)
+      : mOnOff(onOff),
+      mAdapterPtr(adapterPtr)
+    {
+      MOZ_ASSERT(NS_IsMainThread()); // The constructor should be running on the main thread.
+    }
+
+    NS_IMETHOD Run() {
+      bool result;
+
+      MOZ_ASSERT(!NS_IsMainThread()); // This should be running on the worker thread.
+
+      //Toggle BT here
+#if defined(MOZ_WIDGET_GONK)  
+      if (mOnOff) {
+        result = bt_enable();
+      } else {
+        result = bt_disable();
+      }
+#else
+      result = true;
+#endif
+
+      // Create a result thread and pass it to Main Thread, 
+      nsCOMPtr<nsIRunnable> resultRunnable = new ToggleBtResultTask(result, mAdapterPtr);
+      NS_DispatchToMainThread(resultRunnable);
+
+      return NS_OK;
+    }
+
+  private:
+    nsRefPtr<BluetoothAdapter> mAdapterPtr;
+    bool mOnOff;
+};
+
+END_BLUETOOTH_NAMESPACE
+
+DOMCI_DATA(BluetoothAdapter, mozilla::dom::bluetooth::BluetoothAdapter)
 
 USING_BLUETOOTH_NAMESPACE
 
+NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothAdapter)
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(BluetoothAdapter,
+    nsDOMEventTargetHelper)
+NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(powered)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(BluetoothAdapter,
+    nsDOMEventTargetHelper)
+NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(powered)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+  NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothAdapter)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
+
+NS_IMPL_ADDREF_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
+NS_IMPL_RELEASE_INHERITED(BluetoothAdapter, nsDOMEventTargetHelper)
+
 BluetoothAdapter::BluetoothAdapter() : mPower(false)
 {
 }
 
-NS_INTERFACE_MAP_BEGIN(BluetoothAdapter)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMBluetoothAdapter)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(BluetoothAdapter)
-NS_INTERFACE_MAP_END
-  
-NS_IMPL_ADDREF(BluetoothAdapter)
-NS_IMPL_RELEASE(BluetoothAdapter)
-
-DOMCI_DATA(BluetoothAdapter, BluetoothAdapter)
-  
 NS_IMETHODIMP
 BluetoothAdapter::GetPower(bool* aPower)
 {
+#if defined(MOZ_WIDGET_GONK)  
+  *aPower = bt_is_enabled();
+#else
   *aPower = mPower;
+#endif
   return NS_OK;
 }
 
 NS_IMETHODIMP
 BluetoothAdapter::SetPower(bool aPower)
 {
-  mPower = aPower;
+  if (mPower != aPower) {
+    mPower = aPower;
+
+    ToggleBluetoothAsync();
+  }
+
   return NS_OK;
 }
+
+void 
+BluetoothAdapter::ToggleBluetoothAsync()
+{
+  if (!mToggleBtThread) {
+    mToggleBtThread = new LazyIdleThread(15000);
+  }
+
+  nsCOMPtr<nsIRunnable> r = new ToggleBtTask(mPower, this);
+
+  mToggleBtThread->Dispatch(r, 0);
+}
+
+nsresult
+BluetoothAdapter::FirePowered()
+{
+  nsRefPtr<nsDOMEvent> event = new nsDOMEvent(nsnull, nsnull);
+  nsresult rv = event->InitEvent(POWERED_EVENT_NAME, false, false);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool dummy;
+  rv = DispatchEvent(event, &dummy);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+NS_IMPL_EVENT_HANDLER(BluetoothAdapter, powered)
--- a/dom/bluetooth/BluetoothAdapter.h
+++ b/dom/bluetooth/BluetoothAdapter.h
@@ -3,26 +3,41 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothadapter_h__
 #define mozilla_dom_bluetooth_bluetoothadapter_h__
 
 #include "BluetoothCommon.h"
+#include "nsDOMEventTargetHelper.h"
 #include "nsIDOMBluetoothAdapter.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothAdapter : public nsIDOMBluetoothAdapter
+                        ,public nsDOMEventTargetHelper
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMBLUETOOTHADAPTER
 
+  NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
+
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BluetoothAdapter,
+                                           nsDOMEventTargetHelper)
+
   BluetoothAdapter();
 
+  nsresult FirePowered();
+
 protected:
   bool mPower;
+
+  NS_DECL_EVENT_HANDLER(powered)
+
+private:
+  nsCOMPtr<nsIEventTarget> mToggleBtThread;
+  void ToggleBluetoothAsync();
 };
 
 END_BLUETOOTH_NAMESPACE
 #endif
--- a/dom/bluetooth/nsIDOMBluetoothAdapter.idl
+++ b/dom/bluetooth/nsIDOMBluetoothAdapter.idl
@@ -1,13 +1,17 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=40: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsISupports.idl"
+#include "nsIDOMEventTarget.idl"
 
-[scriptable, builtinclass, uuid(29689a22-45ff-4ccf-b552-5364ce3a3642)]
-interface nsIDOMBluetoothAdapter : nsISupports
+interface nsIDOMEventListener;
+
+[scriptable, builtinclass, uuid(3dbaa9f4-5c93-11e1-8592-ff9bfcc3ab4b)]
+interface nsIDOMBluetoothAdapter : nsIDOMEventTarget
 {
   attribute boolean power;
+
+  attribute nsIDOMEventListener onpowered;
 };
--- a/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
+++ b/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
@@ -163,16 +163,23 @@ interface nsIWebGLExtensionStandardDeriv
 
 [scriptable, uuid(b0afc2eb-0895-4509-98de-5c383d160694)]
 interface nsIWebGLExtensionLoseContext : nsIWebGLExtension
 {
   void loseContext();
   void restoreContext();
 };
 
+[scriptable, uuid(73bfb64d-94bd-4a7a-9eab-6b6d32e57aa0)]
+interface nsIWebGLExtensionTextureFilterAnisotropic : nsIWebGLExtension
+{
+  const WebGLenum TEXTURE_MAX_ANISOTROPY = 0x84FE;
+  const WebGLenum MAX_TEXTURE_MAX_ANISOTROPY = 0x84FF;
+};
+
 [scriptable, builtinclass, uuid(f000afac-11b3-4c06-a35f-8db411f1cf54)]
 interface nsIDOMWebGLRenderingContext : nsISupports
 {
   //
   //  CONSTANTS
   //
 
   /* ClearBufferMask */
--- a/dom/interfaces/core/nsIDOMNode.idl
+++ b/dom/interfaces/core/nsIDOMNode.idl
@@ -47,17 +47,17 @@ interface nsIDOMUserDataHandler;
  * The nsIDOMNode interface is the primary datatype for the entire 
  * Document Object Model.
  * It represents a single node in the document tree.
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[scriptable, uuid(ce82fb71-60f2-4c38-be31-de5f2f90dada)]
+[scriptable, uuid(5e9bcec9-5928-4f77-8a9c-424ef01c20e1)]
 interface nsIDOMNode : nsISupports
 {
   const unsigned short      ELEMENT_NODE       = 1;
   const unsigned short      ATTRIBUTE_NODE     = 2;
   const unsigned short      TEXT_NODE          = 3;
   const unsigned short      CDATA_SECTION_NODE = 4;
   const unsigned short      ENTITY_REFERENCE_NODE = 5;
   const unsigned short      ENTITY_NODE        = 6;
@@ -89,17 +89,18 @@ interface nsIDOMNode : nsISupports
   nsIDOMNode                replaceChild(in nsIDOMNode newChild, 
                                          in nsIDOMNode oldChild)
                                           raises(DOMException);
   nsIDOMNode                removeChild(in nsIDOMNode oldChild)
                                          raises(DOMException);
   nsIDOMNode                appendChild(in nsIDOMNode newChild)
                                          raises(DOMException);
   boolean                   hasChildNodes();
-  nsIDOMNode                cloneNode(in boolean deep);
+  // Modified in DOM Level 4:
+  [optional_argc] nsIDOMNode                cloneNode([optional] in boolean deep);
   // Modified in DOM Level 2:
   void                      normalize();
   // Introduced in DOM Level 2:
   boolean                   isSupported(in DOMString feature, 
                                         in DOMString version);
   // Introduced in DOM Level 2:
   readonly attribute DOMString        namespaceURI;
   // Modified in DOM Core
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -348,26 +348,16 @@ nsNPAPIPlugin::RunPluginOOP(const nsPlug
       }
       if (versionPrefix.EqualsASCII("10.1") && GMA9XXGraphics()) {
         return false;
       }
     }
   }
 #endif
 
-#ifdef XP_WIN
-  OSVERSIONINFO osVerInfo = {0};
-  osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo);
-  GetVersionEx(&osVerInfo);
-  // Always disabled on 2K or less. (bug 536303)
-  if (osVerInfo.dwMajorVersion < 5 ||
-      (osVerInfo.dwMajorVersion == 5 && osVerInfo.dwMinorVersion == 0))
-    return false;
-#endif
-
   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (!prefs) {
     return false;
   }
 
   // Get per-library whitelist/blacklist pref string
   // "dom.ipc.plugins.enabled.filename.dll" and fall back to the default value
   // of "dom.ipc.plugins.enabled"
--- a/dom/plugins/base/nsPluginsDirWin.cpp
+++ b/dom/plugins/base/nsPluginsDirWin.cpp
@@ -52,17 +52,16 @@
 #include "prprf.h"
 
 #include "windows.h"
 #include "winbase.h"
 
 #include "nsString.h"
 #include "nsILocalFile.h"
 #include "nsUnicharUtils.h"
-#include "nsSetDllDirectory.h"
 
 using namespace mozilla;
 
 /* Local helper functions */
 
 static char* GetKeyValue(void* verbuf, const WCHAR* key,
                          UINT language, UINT codepage)
 {
@@ -298,25 +297,25 @@ nsresult nsPluginFile::LoadPlugin(PRLibr
   NS_ASSERTION(dwCheck <= MAX_PATH + 1, "Error in Loading plugin");
 
   if (dwCheck <= MAX_PATH + 1) {
     restoreOrigDir = SetCurrentDirectoryW(pluginFolderPath.get());
     NS_ASSERTION(restoreOrigDir, "Error in Loading plugin");
   }
 
   if (protectCurrentDirectory) {
-    mozilla::NS_SetDllDirectory(NULL);
+    SetDllDirectory(NULL);
   }
 
   nsresult rv = plugin->Load(outLibrary);
   if (NS_FAILED(rv))
       *outLibrary = NULL;
 
   if (protectCurrentDirectory) {
-    mozilla::NS_SetDllDirectory(L"");
+    SetDllDirectory(L"");
   }
 
   if (restoreOrigDir) {
     BOOL bCheck = SetCurrentDirectoryW(aOrigDir);
     NS_ASSERTION(bCheck, "Error in Loading plugin");
   }
 
   return rv;
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -142,17 +142,17 @@ PluginProcessChild::Init()
     const std::string shockwaveDirectorPluginFilename("\\np32dsw.dll");
     std::size_t index = caseInsensitiveFind(pluginFilename, shockwaveDirectorPluginFilename);
     if (index != std::string::npos &&
         index + shockwaveDirectorPluginFilename.length() == pluginFilename.length()) {
         protectCurrentDirectory = false;
     }
     if (protectCurrentDirectory) {
         SanitizeEnvironmentVariables();
-        NS_SetDllDirectory(L"");
+        SetDllDirectory(L"");
     }
 
 #else
 #  error Sorry
 #endif
 
     if (NS_FAILED(nsRegion::InitStatic())) {
       NS_ERROR("Could not initialize nsRegion");
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -1843,18 +1843,17 @@ nsDOMStorage2::nsDOMStorage2(nsDOMStorag
 
 nsresult
 nsDOMStorage2::InitAsSessionStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
 {
   mStorage = new nsDOMStorage();
   if (!mStorage)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  // Leave security checks only for domain (nsDOMStorage implementation)
-  mStorage->mSecurityChecker = mStorage;
+  mStorage->mSecurityChecker = this;
   mPrincipal = aPrincipal;
   mDocumentURI = aDocumentURI;
 
   return mStorage->InitAsSessionStorage(aPrincipal, aDocumentURI);
 }
 
 nsresult
 nsDOMStorage2::InitAsLocalStorage(nsIPrincipal *aPrincipal, const nsSubstring &aDocumentURI)
@@ -1944,17 +1943,17 @@ nsDOMStorage2::CanAccess(nsIPrincipal *a
     return mStorage->mSecurityChecker->CanAccess(aPrincipal);
 
   // Allow C++ callers to access the storage
   if (!aPrincipal)
     return true;
 
   // Allow more powerful principals (e.g. system) to access the storage
   bool subsumes;
-  nsresult rv = aPrincipal->Subsumes(mPrincipal, &subsumes);
+  nsresult rv = aPrincipal->SubsumesIgnoringDomain(mPrincipal, &subsumes);
   if (NS_FAILED(rv))
     return false;
 
   return subsumes;
 }
 
 nsPIDOMStorage::nsDOMStorageType
 nsDOMStorage2::StorageType()
--- a/dom/system/b2g/AudioManager.cpp
+++ b/dom/system/b2g/AudioManager.cpp
@@ -71,16 +71,20 @@ AudioManager::GetMasterVolume(float* aMa
 }
 
 NS_IMETHODIMP
 AudioManager::SetMasterVolume(float aMasterVolume)
 {
   if (AudioSystem::setMasterVolume(aMasterVolume)) {
     return NS_ERROR_FAILURE;
   }
+  // For now, just set the voice volume at the same level
+  if (AudioSystem::setVoiceVolume(aMasterVolume)) {
+    return NS_ERROR_FAILURE;
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 AudioManager::GetMasterMuted(bool* aMasterMuted)
 {
   if (AudioSystem::getMasterMute(aMasterMuted)) {
     return NS_ERROR_FAILURE;
--- a/dom/tests/browser/browser_ConsoleStorageAPITests.js
+++ b/dom/tests/browser/browser_ConsoleStorageAPITests.js
@@ -19,17 +19,16 @@ var ConsoleObserver = {
     apiCallCount = 0;
   },
 
   observe: function CO_observe(aSubject, aTopic, aData)
   {
     if (aTopic == "console-storage-cache-event") {
       apiCallCount ++;
       if (apiCallCount == 4) {
-        // remove the observer so we don't trigger this test again
         Services.obs.removeObserver(this, "console-storage-cache-event");
 
         try {
         let tab = gBrowser.selectedTab;
         let browser = gBrowser.selectedBrowser;
         let win = XPCNativeWrapper.unwrap(browser.contentWindow);
         let windowID = getWindowId(win);
         let messages = ConsoleAPIStorage.getEvents(windowID);
@@ -37,22 +36,23 @@ var ConsoleObserver = {
 
         ConsoleAPIStorage.clearEvents();
         messages = ConsoleAPIStorage.getEvents(windowID);
         is(messages.length, 0, "Cleared Storage");
 
         // make sure a closed window's events are in fact removed from the
         // storage cache
         win.console.log("adding a new event");
-
-        // close the window - the storage cache should now be empty
+        // Close the window.
         gBrowser.removeTab(tab, {animate: false});
-
+        // Ensure actual window destruction is not delayed (too long).
         window.QueryInterface(Ci.nsIInterfaceRequestor)
               .getInterface(Ci.nsIDOMWindowUtils).garbageCollect();
+        // Ensure "inner-window-destroyed" event is processed,
+        // so the storage cache is cleared.
         executeSoon(function () {
           // use the old windowID again to see if we have any stray cached messages
           messages = ConsoleAPIStorage.getEvents(windowID);
           is(messages.length, 0, "tab close is clearing the cache");
           finish();
         });
         } catch (ex) {
           dump(ex + "\n\n\n");
@@ -66,16 +66,22 @@ var ConsoleObserver = {
 function tearDown()
 {
   while (gBrowser.tabs.length > 1)
     gBrowser.removeCurrentTab();
 }
 
 function test()
 {
+  // Don't cache removed tabs, so "clear console cache on tab close" triggers.
+  Services.prefs.setIntPref("browser.tabs.max_tabs_undo", 0);
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("browser.tabs.max_tabs_undo");
+  });
+
   registerCleanupFunction(tearDown);
 
   ConsoleObserver.init();
 
   waitForExplicitFinish();
 
   var tab = gBrowser.addTab(TEST_URI);
   gBrowser.selectedTab = tab;
--- a/dom/tests/mochitest/chrome/Makefile.in
+++ b/dom/tests/mochitest/chrome/Makefile.in
@@ -69,16 +69,18 @@ include $(topsrcdir)/config/rules.mk
 		DOMWindowCreated_content.html \
 		test_sandbox_image.xul \
 		test_cyclecollector.xul \
 		test_resize_move_windows.xul \
 		test_popup_blocker_chrome.xul \
 		test_moving_xhr.xul \
 		test_nodesFromRect.html \
 		489127.html \
+		test_focus_docnav.xul \
+		window_focus_docnav.xul \
 		$(NULL)
 
 ifeq (WINNT,$(OS_ARCH))
 _TEST_FILES += \
 		test_sizemode_attribute.xul \
 		sizemode_attribute.xul \
 		$(NULL)
 endif
--- a/dom/tests/mochitest/chrome/focus_frameset.html
+++ b/dom/tests/mochitest/chrome/focus_frameset.html
@@ -1,14 +1,15 @@
 <html id="outer">
 
 <script type="application/javascript"
         src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
 <script>
-SimpleTest.waitForFocus(function () opener.framesetWindowLoaded(window));
+if (opener)
+  SimpleTest.waitForFocus(function () opener.framesetWindowLoaded(window));
 </script>
 
 <frameset rows="30%, 70%">
   <frame src="data:text/html,&lt;html id='f1' &gt;&lt;body id='framebody1'&gt;&lt;input id='f2'&gt;&lt;body&gt;&lt;/html&gt;">
   <frameset cols="30%, 33%, 34%">
     <frame src="data:text/html,&lt;html id='f3'&gt;&lt;body id='framebody2'&gt;&lt;input id='f4'&gt;&lt;body&gt;&lt;/html&gt;">
     <frame src="data:text/html,&lt;html id='f5'&gt;&lt;body id='framebody3'&gt;&lt;input id='f6' tabindex='2'&gt;&lt;body&gt;&lt;/html&gt;">
     <frame src="data:text/html,&lt;html id='f7'&gt;&lt;body id='framebody4'&gt;&lt;input id='f8'&gt;&lt;body&gt;&lt;/html&gt;">
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/test_focus_docnav.xul
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
+
+<window onload="runTest();"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
+
+<script>
+SimpleTest.waitForExplicitFinish();
+function runTest()
+{
+  window.open("window_focus_docnav.xul", "_blank", "chrome,width=600,height=550");
+}
+</script>
+
+<body xmlns="http://www.w3.org/1999/xhtml">
+<p id="display">
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+
+</window>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/chrome/window_focus_docnav.xul
@@ -0,0 +1,104 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+
+<window onload="start()"
+        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script type="application/javascript"
+        src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"/>
+
+<textbox id="textbox"/>
+
+<panel id="panel2" onpopupshown="runTests(this, 2);" onpopuphidden="document.getElementById('panel').hidePopup()">
+  <textbox id="p2textbox" value="Popup2"/>
+</panel>
+<panel id="panel" onpopupshown="runTests(this, 1);"
+                  onpopuphidden="done()">
+  <textbox id="p1textbox" value="Popup1"/>
+</panel>
+
+<browser id="browser" type="content" src="focus_frameset.html" width="500" height="400"/>
+
+<script type="application/javascript">
+<![CDATA[
+
+var fm = Components.classes["@mozilla.org/focus-manager;1"].
+           getService(Components.interfaces.nsIFocusManager);
+
+function is(l, r, n) { window.opener.wrappedJSObject.SimpleTest.is(l,r,n); }
+function ok(v, n) { window.opener.wrappedJSObject.SimpleTest.ok(v,n); }
+
+function done()
+{
+  var opener = window.opener;
+  window.close();
+  opener.wrappedJSObject.SimpleTest.finish();
+}
+
+function previous(expectedWindow, expectedElement, desc)
+{
+  synthesizeKey("VK_F6", { shiftKey: true });
+  is(fm.focusedWindow, expectedWindow, desc);
+  is(fm.focusedElement, expectedElement, desc + " element");
+}
+
+function next(expectedWindow, expectedElement, desc)
+{
+  synthesizeKey("VK_F6", { });
+  is(fm.focusedWindow, expectedWindow, desc);
+  is(fm.focusedElement, expectedElement, desc + " element" + "::" + (fm.focusedElement ? fm.focusedElement.parentNode.id : "<none>"));
+}
+
+// This test runs through three cases. Document navigation forward and
+// backward using the F6 key when no popups are open, with one popup open and
+// with two popups open.
+function runTests(panel, popupCount)
+{
+  if (!popupCount || popupCount > 2)
+    popupCount = 0;
+
+  fm.clearFocus(window);
+
+  var childwin = document.getElementById("browser").contentWindow;
+
+  if (popupCount) {
+    if (popupCount == 2) {
+      next(window, document.getElementById("p2textbox").inputField, "First into popup 2 with " + popupCount);
+    }
+
+    next(window, document.getElementById("p1textbox").inputField, "First into popup 1 with " + popupCount);
+  }
+
+  next(childwin.frames[0], childwin.frames[0].document.documentElement, "First with " + popupCount);
+  next(childwin.frames[1], childwin.frames[1].document.documentElement, "Second with " + popupCount);
+  previous(childwin.frames[0], childwin.frames[0].document.documentElement, "Second back with " + popupCount);
+
+  if (popupCount) {
+    previous(window, document.getElementById("p1textbox").inputField, "First back from popup 1 with " + popupCount);
+
+    if (popupCount == 2) {
+      previous(window, document.getElementById("p2textbox").inputField, "First back from popup 2 with " + popupCount);
+    }
+  }
+
+  previous(window, document.getElementById("textbox").inputField, "First back with " + popupCount);
+
+  if (panel == document.getElementById("panel"))
+    document.getElementById("panel2").openPopup(null, "after_start", 100, 20);
+  else if (panel == document.getElementById("panel2"))
+    panel.hidePopup();
+  else
+    document.getElementById("panel").openPopup(null, "after_start");
+}
+
+function start()
+{
+  window.opener.wrappedJSObject.SimpleTest.waitForExplicitFinish();
+  window.opener.wrappedJSObject.SimpleTest.waitForFocus(
+    function() { runTests(null, 0); },
+    document.getElementById("browser").contentWindow);
+}
+
+]]></script>
+
+</window>
--- a/dom/tests/mochitest/sessionstorage/test_sessionStorageFromChrome.xhtml
+++ b/dom/tests/mochitest/sessionstorage/test_sessionStorageFromChrome.xhtml
@@ -11,17 +11,17 @@ function startTest()
 {
   // Check that we do not crash when we access the sessionStorage object from
   // chrome and that we throw.  See bug 404453.
   var exceptionCaught = false;
   try {
     sessionStorage;
   }
   catch (e) {
-    is(e.result, 2152923145,
+    is(e.result, Components.results.NS_ERROR_NOT_AVAILABLE,
        "Testing that we get the expected exception.");
     exceptionCaught = true;
   }
   is(exceptionCaught, true, "Testing that an exception was thrown.");
 
   SimpleTest.finish();
 }
 
--- a/editor/idl/nsIEditor.idl
+++ b/editor/idl/nsIEditor.idl
@@ -50,17 +50,17 @@ interface nsIDocumentStateListener;
 interface nsIOutputStream;
 interface nsITransactionManager;
 interface nsITransaction;
 interface nsIEditorObserver;
 interface nsIEditActionListener;
 interface nsIInlineSpellChecker;
 interface nsITransferable;
 
-[scriptable, uuid(94479B76-7FD7-47D3-BB1E-5B77846339D2)]
+[scriptable, uuid(656005d2-d900-4839-81bf-6274a3c38537)]
 
 interface nsIEditor  : nsISupports
 {
 %{C++
   typedef short EDirection;
 %}
   const short eNone = 0;
   const short eNext = 1;
@@ -200,16 +200,26 @@ interface nsIEditor  : nsISupports
     *                 if PR_FALSE the undo system is turned off if it
     *                 was previously on
     * @return         if aEnable is PR_TRUE, returns NS_OK if
     *                 the undo system could be initialized properly
     *                 if aEnable is PR_FALSE, returns NS_OK.
     */
   void enableUndo(in boolean enable);
 
+  /**
+   * The number of items on the undo stack.
+   */
+  readonly attribute long numberOfUndoItems;
+
+  /**
+   * The number of items on the redo stack.
+   */
+  readonly attribute long numberOfRedoItems;
+
   /** undo reverses the effects of the last Do operation,
     * if Undo is enabled in the editor.
     * It is provided here so clients need no knowledge of whether
     * the editor has a transaction manager or not.
     * If a transaction manager is present, it is told to undo,
     * and the result of that undo is returned.  
     * Otherwise, the Undo request is ignored and an
     * error NS_ERROR_NOT_AVAILABLE is returned.
--- a/editor/libeditor/base/SplitElementTxn.cpp
+++ b/editor/libeditor/base/SplitElementTxn.cpp
@@ -93,17 +93,17 @@ NS_IMETHODIMP SplitElementTxn::DoTransac
            mOffset);
   }
 #endif
 
   NS_ASSERTION(mExistingRightNode && mEditor, "bad state");
   if (!mExistingRightNode || !mEditor) { return NS_ERROR_NOT_INITIALIZED; }
 
   // create a new node
-  nsresult result = mExistingRightNode->CloneNode(false, getter_AddRefs(mNewLeftNode));
+  nsresult result = mExistingRightNode->CloneNode(false, 1, getter_AddRefs(mNewLeftNode));
   NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewLeftNode)), "could not create element.");
   NS_ENSURE_SUCCESS(result, result);
   NS_ENSURE_TRUE(mNewLeftNode, NS_ERROR_NULL_POINTER);
   mEditor->MarkNodeDirty(mExistingRightNode);
 
 #ifdef NS_DEBUG
   if (gNoisy)
   {
--- a/editor/libeditor/base/nsEditor.cpp
+++ b/editor/libeditor/base/nsEditor.cpp
@@ -745,16 +745,29 @@ nsEditor::EnableUndo(bool aEnable)
       mTxnMgr->Clear();
       mTxnMgr->SetMaxTransactionCount(0);
     }
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsEditor::GetNumberOfUndoItems(PRInt32* aNumItems)
+{
+  *aNumItems = 0;
+  return mTxnMgr ? mTxnMgr->GetNumberOfUndoItems(aNumItems) : NS_OK;
+}
+
+NS_IMETHODIMP
+nsEditor::GetNumberOfRedoItems(PRInt32* aNumItems)
+{
+  *aNumItems = 0;
+  return mTxnMgr ? mTxnMgr->GetNumberOfRedoItems(aNumItems) : NS_OK;
+}
 
 NS_IMETHODIMP
 nsEditor::GetTransactionManager(nsITransactionManager* *aTxnManager)
 {
   NS_ENSURE_ARG_POINTER(aTxnManager);
   
   *aTxnManager = NULL;
   NS_ENSURE_TRUE(mTxnMgr, NS_ERROR_FAILURE);
--- a/editor/libeditor/base/tests/test_dragdrop.html
+++ b/editor/libeditor/base/tests/test_dragdrop.html
@@ -112,16 +112,22 @@ function doTest()
 
   // -------- Test dragging regular text of text/plain to <textarea>
 
 // XXXndeakin Can't test textareas due to some event handling issue
 //  selection.selectAllChildren(text);
 //  synthesizeDrop(text, textarea, [[{type: "text/plain", data: "Somewhat Longer Text"}]], "copy");
 //  is(textarea.value, "Somewhat Longer Text", "Drag text/plain onto textarea");
 
+  // -------- Test dragging special text type of text/plain to contenteditable
+
+  selection.selectAllChildren(text);
+  synthesizeDrop(text, input, [[{type: "text/x-moz-text-internal", data: "Some Special Text"}]], "copy");
+  is(input.value, "Some Plain Text", "Drag text/x-moz-text-internal onto input");
+
   // -------- Test dragging regular text of text/plain to contenteditable
 
   selection.selectAllChildren(text);
   synthesizeDrop(text, contenteditable, [[{type: "text/plain", data: "Sample Text"}]], "copy");
   is(contenteditable.childNodes.length, 3, "Drag text/plain onto contenteditable child nodes");
   is(contenteditable.textContent, "This is some editable text.Sample Text",
                                   "Drag text/plain onto contenteditable text");
 
--- a/editor/libeditor/text/nsPlaintextDataTransfer.cpp
+++ b/editor/libeditor/text/nsPlaintextDataTransfer.cpp
@@ -164,22 +164,26 @@ nsresult nsPlaintextEditor::InsertFromDa
                                                    nsIDOMDocument *aSourceDoc,
                                                    nsIDOMNode *aDestinationNode,
                                                    PRInt32 aDestOffset,
                                                    bool aDoDeleteSelection)
 {
   nsCOMPtr<nsIVariant> data;
   aDataTransfer->MozGetDataAt(NS_LITERAL_STRING("text/plain"), aIndex,
                               getter_AddRefs(data));
-  nsAutoString insertText;
-  data->GetAsAString(insertText);
-  nsContentUtils::PlatformToDOMLineBreaks(insertText);
+  if (data) {
+    nsAutoString insertText;
+    data->GetAsAString(insertText);
+    nsContentUtils::PlatformToDOMLineBreaks(insertText);
 
-  nsAutoEditBatch beginBatching(this);
-  return InsertTextAt(insertText, aDestinationNode, aDestOffset, aDoDeleteSelection);
+    nsAutoEditBatch beginBatching(this);
+    return InsertTextAt(insertText, aDestinationNode, aDestOffset, aDoDeleteSelection);
+  }
+
+  return NS_OK;
 }
 
 nsresult nsPlaintextEditor::InsertFromDrop(nsIDOMEvent* aDropEvent)
 {
   ForceCompositionEnd();
 
   nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aDropEvent));
   NS_ENSURE_TRUE(dragEvent, NS_ERROR_FAILURE);
--- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
+++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp
@@ -2965,17 +2965,17 @@ nsresult nsWebBrowserPersist::OnWalkDOMN
     return NS_OK;
 }
 
 nsresult
 nsWebBrowserPersist::GetNodeToFixup(nsIDOMNode *aNodeIn, nsIDOMNode **aNodeOut)
 {
     if (!(mPersistFlags & PERSIST_FLAGS_FIXUP_ORIGINAL_DOM))
     {
-        nsresult rv = aNodeIn->CloneNode(false, aNodeOut);
+        nsresult rv = aNodeIn->CloneNode(false, 1, aNodeOut);
         NS_ENSURE_SUCCESS(rv, rv);
     }
     else
     {
         NS_ADDREF(*aNodeOut = aNodeIn);
     }
     nsCOMPtr<nsIDOMHTMLElement> element(do_QueryInterface(*aNodeOut));
     if (element) {
--- a/extensions/auth/nsAuthSSPI.cpp
+++ b/extensions/auth/nsAuthSSPI.cpp
@@ -102,43 +102,24 @@ static const char *MapErrorCode(int rc)
     return "<unknown>";
 }
 #else
 #define MapErrorCode(_rc) ""
 #endif
 
 //-----------------------------------------------------------------------------
 
-static HINSTANCE                 sspi_lib; 
 static PSecurityFunctionTableW   sspi;
 
 static nsresult
 InitSSPI()
 {
-    PSecurityFunctionTableW (*initFun)(void);
-
     LOG(("  InitSSPI\n"));
 
-    sspi_lib = LoadLibraryW(L"secur32.dll");
-    if (!sspi_lib) {
-        sspi_lib = LoadLibraryW(L"security.dll");
-        if (!sspi_lib) {
-            LOG(("SSPI library not found"));
-            return NS_ERROR_UNEXPECTED;
-        }
-    }
-
-    initFun = (PSecurityFunctionTableW (*)(void))
-            GetProcAddress(sspi_lib, "InitSecurityInterfaceW");
-    if (!initFun) {
-        LOG(("InitSecurityInterfaceW not found"));
-        return NS_ERROR_UNEXPECTED;
-    }
-
-    sspi = initFun();
+    sspi = InitSecurityInterfaceW();
     if (!sspi) {
         LOG(("InitSecurityInterfaceW failed"));
         return NS_ERROR_UNEXPECTED;
     }
 
     return NS_OK;
 }
 
--- a/extensions/spellcheck/src/mozEnglishWordUtils.cpp
+++ b/extensions/spellcheck/src/mozEnglishWordUtils.cpp
@@ -36,38 +36,37 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozEnglishWordUtils.h"
 #include "nsICharsetAlias.h"
 #include "nsReadableUtils.h"
 #include "nsIServiceManager.h"
 #include "nsUnicharUtils.h"
 #include "nsUnicharUtilCIID.h"
+#include "nsUnicodeProperties.h"
 #include "nsCRT.h"
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozEnglishWordUtils)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozEnglishWordUtils)
 
 NS_INTERFACE_MAP_BEGIN(mozEnglishWordUtils)
   NS_INTERFACE_MAP_ENTRY(mozISpellI18NUtil)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellI18NUtil)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozEnglishWordUtils)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_2(mozEnglishWordUtils,
-                           mCategories,
+NS_IMPL_CYCLE_COLLECTION_1(mozEnglishWordUtils,
                            mURLDetector)
 
 mozEnglishWordUtils::mozEnglishWordUtils()
 {
   mLanguage.AssignLiteral("en");
 
   nsresult rv;
   mURLDetector = do_CreateInstance(MOZ_TXTTOHTMLCONV_CONTRACTID, &rv);
-  mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID);
 }
 
 mozEnglishWordUtils::~mozEnglishWordUtils()
 {
 }
 
 /* attribute wstring language; */
 NS_IMETHODIMP mozEnglishWordUtils::GetLanguage(PRUnichar * *aLanguage)
@@ -163,17 +162,17 @@ NS_IMETHODIMP mozEnglishWordUtils::GetRo
     }
   return NS_OK;
 }
 
 // This needs vast improvement
 bool mozEnglishWordUtils::ucIsAlpha(PRUnichar aChar)
 {
   // XXX we have to fix callers to handle the full Unicode range
-  return nsIUGenCategory::kLetter == mCategories->Get(PRUint32(aChar));
+  return nsIUGenCategory::kLetter == mozilla::unicode::GetGenCategory(aChar);
 }
 
 /* void FindNextWord (in wstring word, in PRUint32 length, in PRUint32 offset, out PRUint32 begin, out PRUint32 end); */
 NS_IMETHODIMP mozEnglishWordUtils::FindNextWord(const PRUnichar *word, PRUint32 length, PRUint32 offset, PRInt32 *begin, PRInt32 *end)
 {
   const PRUnichar *p = word + offset;
   const PRUnichar *endbuf = word + length;
   const PRUnichar *startWord=p;
--- a/extensions/spellcheck/src/mozEnglishWordUtils.h
+++ b/extensions/spellcheck/src/mozEnglishWordUtils.h
@@ -38,17 +38,16 @@
 #ifndef mozEnglishWordUtils_h__
 #define mozEnglishWordUtils_h__
 
 #include "nsCOMPtr.h"
 #include "mozISpellI18NUtil.h"
 #include "nsIUnicodeEncoder.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsString.h"
-#include "nsIUGenCategory.h"
 
 #include "mozITXTToHTMLConv.h" 
 #include "nsCycleCollectionParticipant.h"
 
 class mozEnglishWordUtils : public mozISpellI18NUtil
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -63,13 +62,12 @@ public:
   };  
 
 protected:
   mozEnglishWordUtils::myspCapitalization captype(const nsString &word);
   bool ucIsAlpha(PRUnichar aChar);
 
   nsString mLanguage;
   nsString mCharset;
-  nsCOMPtr<nsIUGenCategory>   mCategories;
   nsCOMPtr<mozITXTToHTMLConv> mURLDetector; // used to detect urls so the spell checker can skip them.
 };
 
 #endif
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -43,16 +43,17 @@
 #include "nsComponentManagerUtils.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMRange.h"
 #include "nsIEditor.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMHTMLBRElement.h"
 #include "nsUnicharUtilCIID.h"
+#include "nsUnicodeProperties.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIContent.h"
 #include "nsTextFragment.h"
 #include "mozilla/dom/Element.h"
 #include "nsIFrame.h"
 #include "nsRange.h"
 #include "nsContentUtils.h"
 
@@ -82,20 +83,16 @@ inline bool IsConditionalPunctuation(PRU
 
 // mozInlineSpellWordUtil::Init
 
 nsresult
 mozInlineSpellWordUtil::Init(nsWeakPtr aWeakEditor)
 {
   nsresult rv;
 
-  mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID, &rv);
-  if (NS_FAILED(rv))
-    return rv;
-  
   // getting the editor can fail commonly because the editor was detached, so
   // don't assert
   nsCOMPtr<nsIEditor> editor = do_QueryReferent(aWeakEditor, &rv);
   if (NS_FAILED(rv))
     return rv;
 
   nsCOMPtr<nsIDOMDocument> domDoc;
   rv = editor->GetDocument(getter_AddRefs(domDoc));
@@ -801,17 +798,17 @@ WordSplitState::ClassifyCharacter(PRInt3
   NS_ASSERTION(aIndex >= 0 && aIndex <= PRInt32(mDOMWordText.Length()),
                "Index out of range");
   if (aIndex == PRInt32(mDOMWordText.Length()))
     return CHAR_CLASS_SEPARATOR;
 
   // this will classify the character, we want to treat "ignorable" characters
   // such as soft hyphens as word characters.
   nsIUGenCategory::nsUGenCategory
-    charCategory = mWordUtil->GetCategories()->Get(PRUint32(mDOMWordText[aIndex]));
+    charCategory = mozilla::unicode::GetGenCategory(mDOMWordText[aIndex]);
   if (charCategory == nsIUGenCategory::kLetter ||
       IsIgnorableCharacter(mDOMWordText[aIndex]))
     return CHAR_CLASS_WORD;
 
   // If conditional punctuation is surrounded immediately on both sides by word
   // characters it also counts as a word character.
   if (IsConditionalPunctuation(mDOMWordText[aIndex])) {
     if (!aRecurse) {
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.h
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.h
@@ -35,17 +35,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCOMPtr.h"
 #include "nsIDOMDocument.h"
 #include "nsIDocument.h"
 #include "nsString.h"
 #include "nsTArray.h"
-#include "nsIUGenCategory.h"
 
 //#define DEBUG_SPELLCHECK
 
 class nsRange;
 class nsINode;
 
 /**
  *    This class extracts text from the DOM and builds it into a single string.
@@ -112,24 +111,22 @@ public:
 
   // Call to normalize some punctuation. This function takes an autostring
   // so we can access characters directly.
   static void NormalizeWord(nsSubstring& aWord);
 
   nsIDOMDocument* GetDOMDocument() const { return mDOMDocument; }
   nsIDocument* GetDocument() const { return mDocument; }
   nsINode* GetRootNode() { return mRootNode; }
-  nsIUGenCategory* GetCategories() { return mCategories; }
   
 private:
 
   // cached stuff for the editor, set by Init
   nsCOMPtr<nsIDOMDocument> mDOMDocument;
   nsCOMPtr<nsIDocument>         mDocument;
-  nsCOMPtr<nsIUGenCategory>     mCategories;
 
   // range to check, see SetPosition and SetEnd
   nsINode*    mRootNode;
   NodeOffset  mSoftBegin;
   NodeOffset  mSoftEnd;
 
   // DOM text covering the soft range, with newlines added at block boundaries
   nsString mSoftText;
--- a/gfx/angle/README.mozilla
+++ b/gfx/angle/README.mozilla
@@ -4,16 +4,17 @@ Current revision: r963
 
 == Applied local patches ==
 
 In this order:
   angle-renaming-debug.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
   angle-intrinsic-msvc2005.patch - work around a MSVC 2005 compile error
   angle-limit-identifiers-to-250-chars.patch - see bug 675625
   angle-use-xmalloc.patch - see bug 680840. Can drop this patch whenever the new preprocessor lands.
+  angle-castrate-bug-241.patch - see bug 699033 / angle bug 241
 
 In addition to these patches, the Makefile.in files are ours, they're not present in upsteam ANGLE.
 
 == How to update this ANGLE copy ==
 
 1. Unapply patches
 2. Apply diff with new ANGLE version
 3. Reapply patches.
new file mode 100644
--- /dev/null
+++ b/gfx/angle/angle-castrate-bug-241.patch
@@ -0,0 +1,47 @@
+# HG changeset patch
+# User Benoit Jacob <bjacob@mozilla.com>
+# Parent 7dcbce54a953090ae8e537f93c6c99ab8eb0dc62
+
+diff --git a/gfx/angle/README.mozilla b/gfx/angle/README.mozilla
+--- a/gfx/angle/README.mozilla
++++ b/gfx/angle/README.mozilla
+@@ -4,16 +4,17 @@ Current revision: r963
+ 
+ == Applied local patches ==
+ 
+ In this order:
+   angle-renaming-debug.patch - rename debug.h to compilerdebug.h to avoid conflict in our makefiles
+   angle-intrinsic-msvc2005.patch - work around a MSVC 2005 compile error
+   angle-limit-identifiers-to-250-chars.patch - see bug 675625
+   angle-use-xmalloc.patch - see bug 680840. Can drop this patch whenever the new preprocessor lands.
++  angle-castrate-bug-241.patch - see bug 699033 / angle bug 241
+ 
+ In addition to these patches, the Makefile.in files are ours, they're not present in upsteam ANGLE.
+ 
+ == How to update this ANGLE copy ==
+ 
+ 1. Unapply patches
+ 2. Apply diff with new ANGLE version
+ 3. Reapply patches.
+diff --git a/gfx/angle/src/compiler/Types.h b/gfx/angle/src/compiler/Types.h
+--- a/gfx/angle/src/compiler/Types.h
++++ b/gfx/angle/src/compiler/Types.h
+@@ -203,17 +203,17 @@ public:
+     bool isVector() const { return size > 1 && !matrix; }
+     bool isScalar() const { return size == 1 && !matrix && !structure; }
+ 
+     TTypeList* getStruct() const { return structure; }
+     void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
+ 
+     const TString& getTypeName() const
+     {
+-        assert(typeName);
++        if(!typeName) abort();
+         return *typeName;
+     }
+     void setTypeName(const TString& n)
+     {
+         typeName = NewPoolTString(n.c_str());
+     }
+ 
+     bool isField() const { return fieldName != 0; }
--- a/gfx/angle/src/compiler/Types.h
+++ b/gfx/angle/src/compiler/Types.h
@@ -203,17 +203,17 @@ public:
     bool isVector() const { return size > 1 && !matrix; }
     bool isScalar() const { return size == 1 && !matrix && !structure; }
 
     TTypeList* getStruct() const { return structure; }
     void setStruct(TTypeList* s) { structure = s; computeDeepestStructNesting(); }
 
     const TString& getTypeName() const
     {
-        assert(typeName);
+        if(!typeName) abort();
         return *typeName;
     }
     void setTypeName(const TString& n)
     {
         typeName = NewPoolTString(n.c_str());
     }
 
     bool isField() const { return fieldName != 0; }
--- a/gfx/gl/GLContext.cpp
+++ b/gfx/gl/GLContext.cpp
@@ -91,16 +91,17 @@ static const char *sExtensionNames[] = {
     "GL_APPLE_client_storage",
     "GL_ARB_texture_non_power_of_two",
     "GL_ARB_pixel_buffer_object",
     "GL_ARB_ES2_compatibility",
     "GL_OES_texture_float",
     "GL_ARB_texture_float",
     "GL_EXT_unpack_subimage",
     "GL_OES_standard_derivatives",
+    "GL_EXT_texture_filter_anisotropic",
     "GL_EXT_framebuffer_blit",
     "GL_ANGLE_framebuffer_blit",
     "GL_EXT_framebuffer_multisample",
     "GL_ANGLE_framebuffer_multisample",
     "GL_OES_rgb8_rgba8",
     "GL_ARB_robustness",
     "GL_EXT_robustness",
     NULL
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -1403,16 +1403,17 @@ public:
         APPLE_client_storage,
         ARB_texture_non_power_of_two,
         ARB_pixel_buffer_object,
         ARB_ES2_compatibility,
         OES_texture_float,
         ARB_texture_float,
         EXT_unpack_subimage,
         OES_standard_derivatives,
+        EXT_texture_filter_anisotropic,
         EXT_framebuffer_blit,
         ANGLE_framebuffer_blit,
         EXT_framebuffer_multisample,
         ANGLE_framebuffer_multisample,
         OES_rgb8_rgba8,
         ARB_robustness,
         EXT_robustness,
         Extensions_Max
--- a/gfx/thebes/Makefile.in
+++ b/gfx/thebes/Makefile.in
@@ -70,18 +70,16 @@ EXPORTS	= \
 	gfxPoint3D.h \
 	gfxPointH3D.h \
 	gfxQuad.h \
 	gfxQuaternion.h \
 	gfxRect.h \
 	gfxSkipChars.h \
 	gfxTeeSurface.h \
 	gfxTypes.h \
-	gfxUnicodeProperties.h \
-	gfxUnicodeScriptCodes.h \
 	gfxUtils.h \
 	gfxUserFontSet.h \
 	nsCoreAnimationSupport.h \
 	nsIOSurface.h \
 	gfxSharedImageSurface.h \
 	$(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),android)
@@ -199,17 +197,16 @@ CPPSRCS	= \
 	gfxPattern.cpp \
 	gfxPlatform.cpp \
 	gfxPlatformFontList.cpp \
 	gfxRect.cpp \
 	gfxSkipChars.cpp \
 	gfxTeeSurface.cpp \
 	gfxUserFontSet.cpp \
 	gfxUtils.cpp \
-	gfxUnicodeProperties.cpp \
 	gfxScriptItemizer.cpp \
 	gfxHarfBuzzShaper.cpp \
 	gfxSharedImageSurface.cpp \
 	$(NULL)
 
 ifdef MOZ_GRAPHITE
 DEFINES += -DGRAPHITE2_STATIC
 CPPSRCS	+= \
--- a/gfx/thebes/gfxDWriteFonts.cpp
+++ b/gfx/thebes/gfxDWriteFonts.cpp
@@ -77,38 +77,22 @@ GetCairoAntialiasOption(gfxFont::Antiali
 #ifndef SPI_GETFONTSMOOTHINGTYPE
 #define SPI_GETFONTSMOOTHINGTYPE 0x200a
 #endif
 #ifndef FE_FONTSMOOTHINGCLEARTYPE
 #define FE_FONTSMOOTHINGCLEARTYPE 2
 #endif
 
 static bool
-HasClearType()
-{
-    OSVERSIONINFO versionInfo;
-    versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-
-    return (GetVersionEx(&versionInfo) &&
-            (versionInfo.dwMajorVersion > 5 ||
-             (versionInfo.dwMajorVersion == 5 &&
-              versionInfo.dwMinorVersion >= 1))); // XP or newer
-}
-
-static bool
 UsingClearType()
 {
     BOOL fontSmoothing;
     if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothing, 0) ||
         !fontSmoothing)
     {
-        return false;    
-    }
-
-    if (!HasClearType()) {
         return false;
     }
 
     UINT type;
     if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &type, 0) &&
         type == FE_FONTSMOOTHINGCLEARTYPE)
     {
         return true;
--- a/gfx/thebes/gfxFT2Fonts.cpp
+++ b/gfx/thebes/gfxFT2Fonts.cpp
@@ -54,17 +54,16 @@
 #include "gfxFT2FontBase.h"
 #include "gfxFT2Utils.h"
 #include "gfxFT2FontList.h"
 #include <locale.h>
 #include "gfxHarfBuzzShaper.h"
 #ifdef MOZ_GRAPHITE
 #include "gfxGraphiteShaper.h"
 #endif
-#include "gfxUnicodeProperties.h"
 #include "gfxAtoms.h"
 #include "nsTArray.h"
 #include "nsUnicodeRange.h"
 #include "nsCRT.h"
 #include "nsXULAppAPI.h"
 
 #include "prlog.h"
 #include "prinit.h"
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -57,17 +57,17 @@
 #include "prtypes.h"
 #include "gfxTypes.h"
 #include "nsAlgorithm.h"
 #include "gfxContext.h"
 #include "gfxFontMissingGlyphs.h"
 #include "gfxUserFontSet.h"
 #include "gfxPlatformFontList.h"
 #include "gfxScriptItemizer.h"
-#include "gfxUnicodeProperties.h"
+#include "nsUnicodeProperties.h"
 #include "nsMathUtils.h"
 #include "nsBidiUtils.h"
 #include "nsUnicodeRange.h"
 #include "nsCompressedCharMap.h"
 #include "nsStyleConsts.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "mozilla/Telemetry.h"
@@ -78,16 +78,17 @@
 #include "harfbuzz/hb-blob.h"
 
 #include "nsCRT.h"
 
 #include <algorithm>
 
 using namespace mozilla;
 using namespace mozilla::gfx;
+using namespace mozilla::unicode;
 using mozilla::services::GetObserverService;
 
 gfxFontCache *gfxFontCache::gGlobalCache = nsnull;
 
 #ifdef DEBUG_roc
 #define DEBUG_TEXT_RUN_STORAGE_METRICS
 #endif
 
@@ -718,17 +719,17 @@ gfxFontFamily::FindFontForChar(FontSearc
             rank += 20;
             aMatchData->mCount++;
 #ifdef PR_LOGGING
             PRLogModuleInfo *log = gfxPlatform::GetLog(eGfxLog_textrun);
         
             if (NS_UNLIKELY(log)) {
                 PRUint32 charRange = gfxFontUtils::CharRangeBit(aMatchData->mCh);
                 PRUint32 unicodeRange = FindCharUnicodeRange(aMatchData->mCh);
-                PRUint32 script = gfxUnicodeProperties::GetScriptCode(aMatchData->mCh);
+                PRUint32 script = GetScriptCode(aMatchData->mCh);
                 PR_LOG(log, PR_LOG_DEBUG,\
                        ("(textrun-systemfallback-fonts) char: u+%6.6x "
                         "char-range: %d unicode-range: %d script: %d match: [%s]\n",
                         aMatchData->mCh,
                         charRange, unicodeRange, script,
                         NS_ConvertUTF16toUTF8(fe->Name()).get()));
             }
 #endif
@@ -1873,17 +1874,17 @@ gfxFont::Measure(gfxTextRun *aTextRun,
 #define BACKTRACK_LIMIT  1024 // If we can't find a space or a cluster start
                               // within 1K chars, just chop arbitrarily.
                               // Limiting backtrack here avoids pathological
                               // behavior on long runs with no whitespace.
 
 static bool
 IsClusterExtender(PRUint32 aUSV)
 {
-    PRUint8 category = gfxUnicodeProperties::GetGeneralCategory(aUSV);
+    PRUint8 category = GetGeneralCategory(aUSV);
     return ((category >= HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK &&
              category <= HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK) ||
             (aUSV >= 0x200c && aUSV <= 0x200d) || // ZWJ, ZWNJ
             (aUSV >= 0xff9e && aUSV <= 0xff9f));  // katakana sound marks
 }
 
 static bool
 IsBoundarySpace(PRUnichar aChar, PRUnichar aNextChar)
@@ -3327,17 +3328,17 @@ gfxFontGroup::FindFontForChar(PRUint32 a
                               PRUint8 *aMatchType)
 {
     nsRefPtr<gfxFont>    selectedFont;
 
     if (aPrevMatchedFont) {
         // Don't switch fonts for control characters, regardless of
         // whether they are present in the current font, as they won't
         // actually be rendered (see bug 716229)
-        PRUint8 category = gfxUnicodeProperties::GetGeneralCategory(aCh);
+        PRUint8 category = GetGeneralCategory(aCh);
         if (category == HB_UNICODE_GENERAL_CATEGORY_CONTROL) {
             selectedFont = aPrevMatchedFont;
             return selectedFont.forget();
         }
 
         // if this character is a join-control or the previous is a join-causer,
         // use the same font as the previous range if we can
         if (gfxFontUtils::IsJoinControl(aCh) ||
@@ -3401,17 +3402,17 @@ gfxFontGroup::FindFontForChar(PRUint32 a
     if (!selectedFont && aPrevMatchedFont && aPrevMatchedFont->HasCharacter(aCh)) {
         *aMatchType = gfxTextRange::kSystemFallback;
         selectedFont = aPrevMatchedFont;
         return selectedFont.forget();
     }
 
     // for known "space" characters, don't do a full system-fallback search;
     // we'll synthesize appropriate-width spaces instead of missing-glyph boxes
-    if (gfxUnicodeProperties::GetGeneralCategory(aCh) ==
+    if (GetGeneralCategory(aCh) ==
             HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR &&
         GetFontAt(0)->SynthesizeSpaceWidth(aCh) >= 0.0)
     {
         return nsnull;
     }
 
     // -- otherwise look for other stuff
     if (!selectedFont) {
@@ -3791,30 +3792,30 @@ gfxFontStyle::ComputeWeight() const
 // anything but still need to set cluster info.
 /*static*/ void
 gfxShapedWord::SetupClusterBoundaries(CompressedGlyph *aGlyphs,
                                       const PRUnichar *aString, PRUint32 aLength)
 {
     gfxTextRun::CompressedGlyph extendCluster;
     extendCluster.SetComplex(false, true, 0);
 
-    gfxUnicodeProperties::HSType hangulState = gfxUnicodeProperties::HST_NONE;
+    HSType hangulState = HST_NONE;
 
     for (PRUint32 i = 0; i < aLength; ++i) {
         bool surrogatePair = false;
         PRUint32 ch = aString[i];
         if (NS_IS_HIGH_SURROGATE(ch) &&
             i < aLength - 1 && NS_IS_LOW_SURROGATE(aString[i+1]))
         {
             ch = SURROGATE_TO_UCS4(ch, aString[i+1]);
             surrogatePair = true;
         }
 
-        PRUint8 category = gfxUnicodeProperties::GetGeneralCategory(ch);
-        gfxUnicodeProperties::HSType hangulType = gfxUnicodeProperties::HST_NONE;
+        PRUint8 category = GetGeneralCategory(ch);
+        HSType hangulType = HST_NONE;
 
         // combining marks extend the cluster
         if (IsClusterExtender(ch)) {
             aGlyphs[i] = extendCluster;
         } else if (category == HB_UNICODE_GENERAL_CATEGORY_OTHER_LETTER) {
             // handle special cases in Letter_Other category
 #if 0
             // Currently disabled. This would follow the UAX#29 specification
@@ -3845,35 +3846,35 @@ gfxShapedWord::SetupClusterBoundaries(Co
                 }
             } else
 #endif
             if ((ch & ~0xff) == 0x1100 ||
                 (ch >= 0xa960 && ch <= 0xa97f) ||
                 (ch >= 0xac00 && ch <= 0xd7ff))
             {
                 // no break within Hangul syllables
-                hangulType = gfxUnicodeProperties::GetHangulSyllableType(ch);
+                hangulType = GetHangulSyllableType(ch);
                 switch (hangulType) {
-                case gfxUnicodeProperties::HST_L:
-                case gfxUnicodeProperties::HST_LV:
-                case gfxUnicodeProperties::HST_LVT:
-                    if (hangulState == gfxUnicodeProperties::HST_L) {
+                case HST_L:
+                case HST_LV:
+                case HST_LVT:
+                    if (hangulState == HST_L) {
                         aGlyphs[i] = extendCluster;
                     }
                     break;
-                case gfxUnicodeProperties::HST_V:
-                    if ( (hangulState != gfxUnicodeProperties::HST_NONE) &&
-                        !(hangulState & gfxUnicodeProperties::HST_T))
+                case HST_V:
+                    if ( (hangulState != HST_NONE) &&
+                        !(hangulState & HST_T))
                     {
                         aGlyphs[i] = extendCluster;
                     }
                     break;
-                case gfxUnicodeProperties::HST_T:
-                    if (hangulState & (gfxUnicodeProperties::HST_V |
-                                       gfxUnicodeProperties::HST_T))
+                case HST_T:
+                    if (hangulState & (HST_V |
+                                       HST_T))
                     {
                         aGlyphs[i] = extendCluster;
                     }
                     break;
                 default:
                     break;
                 }
             }
@@ -5016,17 +5017,17 @@ gfxTextRun::SetGlyphs(PRUint32 aIndex, C
         memcpy(details, aGlyphs, sizeof(DetailedGlyph)*glyphCount);
     }
     mCharacterGlyphs[aIndex] = aGlyph;
 }
 
 void
 gfxTextRun::SetMissingGlyph(PRUint32 aIndex, PRUint32 aChar)
 {
-    PRUint8 category = gfxUnicodeProperties::GetGeneralCategory(aChar);
+    PRUint8 category = GetGeneralCategory(aChar);
     if (category >= HB_UNICODE_GENERAL_CATEGORY_SPACING_MARK &&
         category <= HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
     {
         mCharacterGlyphs[aIndex].SetComplex(false, true, 0);
     }
 
     DetailedGlyph *details = AllocateDetailedGlyphs(aIndex, 1);
     if (!details)
--- a/gfx/thebes/gfxGDIFont.cpp
+++ b/gfx/thebes/gfxGDIFont.cpp
@@ -43,17 +43,16 @@
 #include "gfxGDIShaper.h"
 #include "gfxUniscribeShaper.h"
 #include "gfxHarfBuzzShaper.h"
 #ifdef MOZ_GRAPHITE
 #include "gfxGraphiteShaper.h"
 #endif
 #include "gfxWindowsPlatform.h"
 #include "gfxContext.h"
-#include "gfxUnicodeProperties.h"
 
 #include "cairo-win32.h"
 
 #define ROUND(x) floor((x) + 0.5)
 
 static inline cairo_antialias_t
 GetCairoAntialiasOption(gfxFont::AntialiasOption anAntialiasOption)
 {
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -60,16 +60,17 @@
 #include "nsDirectoryServiceDefs.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIWindowsRegKey.h"
 
 #include "mozilla/Telemetry.h"
 
 #include <usp10.h>
+#include <t2embapi.h>
 
 using namespace mozilla;
 
 #define ROUND(x) floor((x) + 0.5)
 
 
 #ifndef CLEARTYPE_QUALITY
 #define CLEARTYPE_QUALITY 5
@@ -97,72 +98,28 @@ BuildKeyNameFromFontName(nsAString &aNam
     if (aName.Length() >= LF_FACESIZE)
         aName.Truncate(LF_FACESIZE - 1);
     ToLowerCase(aName);
 }
 
 // Implementation of gfxPlatformFontList for Win32 GDI,
 // using GDI font enumeration APIs to get the list of fonts
 
-// from t2embapi.h, included in Platform SDK 6.1 but not 6.0
-
-#ifndef __t2embapi__
-
-#define TTLOAD_PRIVATE                  0x00000001
-#define LICENSE_PREVIEWPRINT            0x0004
-#define E_NONE                          0x0000L
-
-typedef unsigned long( WINAPIV *READEMBEDPROC ) ( void*, void*, const unsigned long );
-
-typedef struct
-{
-    unsigned short usStructSize;    // size in bytes of structure client should set to sizeof(TTLOADINFO)
-    unsigned short usRefStrSize;    // size in wide characters of pusRefStr including NULL terminator
-    unsigned short *pusRefStr;      // reference or actual string.
-}TTLOADINFO;
-
-LONG WINAPI TTLoadEmbeddedFont
-(
-    HANDLE*  phFontReference,           // on completion, contains handle to identify embedded font installed
-                                        // on system
-    ULONG    ulFlags,                   // flags specifying the request 
-    ULONG*   pulPrivStatus,             // on completion, contains the embedding status
-    ULONG    ulPrivs,                   // allows for the reduction of licensing privileges
-    ULONG*   pulStatus,                 // on completion, may contain status flags for request 
-    READEMBEDPROC lpfnReadFromStream,   // callback function for doc/disk reads
-    LPVOID   lpvReadStream,             // the input stream tokin
-    LPWSTR   szWinFamilyName,           // the new 16 bit windows family name can be NULL
-    LPSTR    szMacFamilyName,           // the new 8 bit mac family name can be NULL
-    TTLOADINFO* pTTLoadInfo             // optional security
-);
-
-#endif // __t2embapi__
-
-typedef LONG( WINAPI *TTLoadEmbeddedFontProc ) (HANDLE* phFontReference, ULONG ulFlags, ULONG* pulPrivStatus, ULONG ulPrivs, ULONG* pulStatus, 
-                                             READEMBEDPROC lpfnReadFromStream, LPVOID lpvReadStream, LPWSTR szWinFamilyName, 
-                                             LPSTR szMacFamilyName, TTLOADINFO* pTTLoadInfo);
-
-typedef LONG( WINAPI *TTDeleteEmbeddedFontProc ) (HANDLE hFontReference, ULONG ulFlags, ULONG* pulStatus);
-
-
-static TTLoadEmbeddedFontProc TTLoadEmbeddedFontPtr = nsnull;
-static TTDeleteEmbeddedFontProc TTDeleteEmbeddedFontPtr = nsnull;
-
 class WinUserFontData : public gfxUserFontData {
 public:
     WinUserFontData(HANDLE aFontRef, bool aIsEmbedded)
         : mFontRef(aFontRef), mIsEmbedded(aIsEmbedded)
     { }
 
     virtual ~WinUserFontData()
     {
         if (mIsEmbedded) {
             ULONG pulStatus;
             LONG err;
-            err = TTDeleteEmbeddedFontPtr(mFontRef, 0, &pulStatus);
+            err = TTDeleteEmbeddedFont(mFontRef, 0, &pulStatus);
 #if DEBUG
             if (err != E_NONE) {
                 char buf[256];
                 sprintf(buf, "error deleting embedded font handle (%p) - TTDeleteEmbeddedFont returned %8.8x", mFontRef, err);
                 NS_ASSERTION(err == E_NONE, buf);
             }
 #endif
         } else {
@@ -601,18 +558,16 @@ GDIFontFamily::FindStyleVariations()
  *
  * gfxGDIFontList
  *
  */
 
 gfxGDIFontList::gfxGDIFontList()
 {
     mFontSubstitutes.Init(50);
-
-    InitializeFontEmbeddingProcs();
 }
 
 static void
 RemoveCharsetFromFontSubstitute(nsAString &aName)
 {
     PRInt32 comma = aName.FindChar(PRUnichar(','));
     if (comma >= 0)
         aName.Truncate(comma);
@@ -789,25 +744,16 @@ gfxGDIFontList::LookupLocalFont(const gf
     if (!fe)
         return nsnull;
 
     fe->mIsUserFont = true;
     fe->mIsLocalUserFont = true;
     return fe;
 }
 
-void gfxGDIFontList::InitializeFontEmbeddingProcs()
-{
-    HMODULE fontlib = LoadLibraryW(L"t2embed.dll");
-    if (!fontlib)
-        return;
-    TTLoadEmbeddedFontPtr = (TTLoadEmbeddedFontProc) GetProcAddress(fontlib, "TTLoadEmbeddedFont");
-    TTDeleteEmbeddedFontPtr = (TTDeleteEmbeddedFontProc) GetProcAddress(fontlib, "TTDeleteEmbeddedFont");
-}
-
 // used to control stream read by Windows TTLoadEmbeddedFont API
 
 class EOTFontStreamReader {
 public:
     EOTFontStreamReader(const PRUint8 *aFontData, PRUint32 aLength, PRUint8 *aEOTHeader, 
                            PRUint32 aEOTHeaderLen, FontDataOverlay *aNameOverlay)
         : mCurrentChunk(0), mChunkOffset(0)
     {
@@ -901,20 +847,16 @@ gfxGDIFontList::MakePlatformFont(const g
     struct FontDataDeleter {
         FontDataDeleter(const PRUint8 *aFontData)
             : mFontData(aFontData) { }
         ~FontDataDeleter() { NS_Free((void*)mFontData); }
         const PRUint8 *mFontData;
     };
     FontDataDeleter autoDelete(aFontData);
 
-    // if calls aren't available, bail
-    if (!TTLoadEmbeddedFontPtr || !TTDeleteEmbeddedFontPtr)
-        return nsnull;
-
     bool hasVertical;
     bool isCFF = gfxFontUtils::IsCffFont(aFontData, hasVertical);
 
     nsresult rv;
     HANDLE fontRef = nsnull;
     bool isEmbedded = false;
 
     nsAutoString uniqueName;
@@ -943,21 +885,21 @@ gfxGDIFontList::MakePlatformFont(const g
             eotlen = eotHeader.Length();
             buffer = reinterpret_cast<PRUint8*> (eotHeader.Elements());
             
             PRInt32 ret;
             ULONG privStatus, pulStatus;
             EOTFontStreamReader eotReader(aFontData, aLength, buffer, eotlen,
                                           &overlayNameData);
 
-            ret = TTLoadEmbeddedFontPtr(&fontRef, TTLOAD_PRIVATE, &privStatus,
-                                       LICENSE_PREVIEWPRINT, &pulStatus,
-                                       EOTFontStreamReader::ReadEOTStream,
-                                       &eotReader,
-                                       (PRUnichar*)(fontName.get()), 0, 0);
+            ret = TTLoadEmbeddedFont(&fontRef, TTLOAD_PRIVATE, &privStatus,
+                                     LICENSE_PREVIEWPRINT, &pulStatus,
+                                     EOTFontStreamReader::ReadEOTStream,
+                                     &eotReader,
+                                     (PRUnichar*)(fontName.get()), 0, 0);
             if (ret != E_NONE) {
                 fontRef = nsnull;
                 char buf[256];
                 sprintf(buf, "font (%s) not loaded using TTLoadEmbeddedFont - error %8.8x", NS_ConvertUTF16toUTF8(aProxyEntry->FamilyName()).get(), ret);
                 NS_WARNING(buf);
             }
         }
     }
--- a/gfx/thebes/gfxGraphiteShaper.cpp
+++ b/gfx/thebes/gfxGraphiteShaper.cpp
@@ -43,17 +43,16 @@
 #include "nsHashSets.h"
 
 #include "gfxTypes.h"
 
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxGraphiteShaper.h"
 #include "gfxFontUtils.h"
-#include "gfxUnicodeProperties.h"
 
 #include "graphite2/Font.h"
 #include "graphite2/Segment.h"
 
 #include "harfbuzz/hb-blob.h"
 
 #include "cairo.h"
 
--- a/gfx/thebes/gfxHarfBuzzShaper.cpp
+++ b/gfx/thebes/gfxHarfBuzzShaper.cpp
@@ -44,17 +44,18 @@
 #include "nsMathUtils.h"
 
 #include "gfxTypes.h"
 
 #include "gfxContext.h"
 #include "gfxPlatform.h"
 #include "gfxHarfBuzzShaper.h"
 #include "gfxFontUtils.h"
-#include "gfxUnicodeProperties.h"
+#include "nsUnicodeProperties.h"
+#include "nsUnicodeScriptCodes.h"
 #include "nsUnicodeNormalizer.h"
 
 #include "harfbuzz/hb-unicode.h"
 #include "harfbuzz/hb-ot.h"
 
 #include "cairo.h"
 
 #include "nsCRT.h"
@@ -67,16 +68,17 @@
 #define FixedToFloat(f) ((f) * (1.0 / 65536.0))
 // Right shifts of negative (signed) integers are undefined, as are overflows
 // when converting unsigned to negative signed integers.
 // (If speed were an issue we could make some 2's complement assumptions.)
 #define FixedToIntRound(f) ((f) > 0 ?  ((32768 + (f)) >> 16) \
                                     : -((32767 - (f)) >> 16))
 
 using namespace mozilla; // for AutoSwap_* types
+using namespace mozilla::unicode; // for Unicode property lookup
 
 /*
  * Creation and destruction; on deletion, release any font tables we're holding
  */
 
 gfxHarfBuzzShaper::gfxHarfBuzzShaper(gfxFont *aFont)
     : gfxFontShaper(aFont),
       mHBFace(nsnull),
@@ -667,42 +669,42 @@ HBGetHKerning(hb_font_t *font, void *fon
 
 /*
  * HarfBuzz unicode property callbacks
  */
 
 static hb_codepoint_t
 HBGetMirroring(hb_unicode_funcs_t *ufuncs, hb_codepoint_t aCh, void *user_data)
 {
-    return gfxUnicodeProperties::GetMirroredChar(aCh);
+    return GetMirroredChar(aCh);
 }
 
 static hb_unicode_general_category_t
 HBGetGeneralCategory(hb_unicode_funcs_t *ufuncs, hb_codepoint_t aCh, void *user_data)
 {
-    return hb_unicode_general_category_t(gfxUnicodeProperties::GetGeneralCategory(aCh));
+    return hb_unicode_general_category_t(GetGeneralCategory(aCh));
 }
 
 static hb_script_t
 HBGetScript(hb_unicode_funcs_t *ufuncs, hb_codepoint_t aCh, void *user_data)
 {
-    return hb_script_t(gfxUnicodeProperties::GetScriptTagForCode
-        (gfxUnicodeProperties::GetScriptCode(aCh)));
+    return hb_script_t(GetScriptTagForCode
+        (GetScriptCode(aCh)));
 }
 
 static unsigned int
 HBGetCombiningClass(hb_unicode_funcs_t *ufuncs, hb_codepoint_t aCh, void *user_data)
 {
-    return gfxUnicodeProperties::GetCombiningClass(aCh);
+    return GetCombiningClass(aCh);
 }
 
 static unsigned int
 HBGetEastAsianWidth(hb_unicode_funcs_t *ufuncs, hb_codepoint_t aCh, void *user_data)
 {
-    return gfxUnicodeProperties::GetEastAsianWidth(aCh);
+    return GetEastAsianWidth(aCh);
 }
 
 // Hebrew presentation forms with dagesh, for characters 0x05D0..0x05EA;
 // note that some letters do not have a dagesh presForm encoded
 static const PRUnichar sDageshForms[0x05EA - 0x05D0 + 1] = {
     0xFB30, // ALEF
     0xFB31, // BET
     0xFB32, // GIMEL
@@ -1000,17 +1002,17 @@ gfxHarfBuzzShaper::ShapeWord(gfxContext 
     hb_buffer_set_direction(buffer, isRightToLeft ? HB_DIRECTION_RTL :
                                                     HB_DIRECTION_LTR);
     // For unresolved "common" or "inherited" runs, default to Latin for now.
     // (Should we somehow use the language or locale to try and infer
     // a better default?)
     PRInt32 scriptCode = aShapedWord->Script();
     hb_script_t scriptTag = (scriptCode <= MOZ_SCRIPT_INHERITED) ?
         HB_SCRIPT_LATIN :
-        hb_script_t(gfxUnicodeProperties::GetScriptTagForCode(scriptCode));
+        hb_script_t(GetScriptTagForCode(scriptCode));
     hb_buffer_set_script(buffer, scriptTag);
 
     hb_language_t language;
     if (style->languageOverride) {
         language = hb_ot_tag_to_language(style->languageOverride);
     } else if (entry->mLanguageOverride) {
         language = hb_ot_tag_to_language(entry->mLanguageOverride);
     } else {
--- a/gfx/thebes/gfxMacFont.cpp
+++ b/gfx/thebes/gfxMacFont.cpp
@@ -41,17 +41,16 @@
 #include "gfxMacFont.h"
 #include "gfxCoreTextShaper.h"
 #include "gfxHarfBuzzShaper.h"
 #ifdef MOZ_GRAPHITE
 #include "gfxGraphiteShaper.h"
 #endif
 #include "gfxPlatformMac.h"
 #include "gfxContext.h"
-#include "gfxUnicodeProperties.h"
 #include "gfxFontUtils.h"
 
 #include "cairo-quartz.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 gfxMacFont::gfxMacFont(MacOSFontEntry *aFontEntry, const gfxFontStyle *aFontStyle,
--- a/gfx/thebes/gfxPangoFonts.cpp
+++ b/gfx/thebes/gfxPangoFonts.cpp
@@ -64,17 +64,18 @@
 #include "gfxFT2FontBase.h"
 #include "gfxFT2Utils.h"
 #include "harfbuzz/hb-unicode.h"
 #include "harfbuzz/hb-ot-tag.h"
 #include "gfxHarfBuzzShaper.h"
 #ifdef MOZ_GRAPHITE
 #include "gfxGraphiteShaper.h"
 #endif
-#include "gfxUnicodeProperties.h"
+#include "nsUnicodeProperties.h"
+#include "nsUnicodeScriptCodes.h"
 #include "gfxFontconfigUtils.h"
 #include "gfxUserFontSet.h"
 #include "gfxAtoms.h"
 
 #include <cairo.h>
 #include <cairo-ft.h>
 
 #include <fontconfig/fcfreetype.h>
@@ -85,16 +86,17 @@
 
 #ifdef MOZ_WIDGET_GTK2
 #include <gdk/gdk.h>
 #endif
 
 #include <math.h>
 
 using namespace mozilla;
+using namespace mozilla::unicode;
 
 #define FLOAT_PANGO_SCALE ((gfxFloat)PANGO_SCALE)
 
 #ifndef PANGO_VERSION_CHECK
 #define PANGO_VERSION_CHECK(x,y,z) 0
 #endif
 #ifndef PANGO_GLYPH_UNKNOWN_FLAG
 #define PANGO_GLYPH_UNKNOWN_FLAG ((PangoGlyph)0x10000000)
@@ -324,17 +326,17 @@ gfxFcFontEntry::ShouldUseHarfBuzz(PRInt3
     {
         mSkipGraphiteCheck = true;
         return true;
     }
 
     // Mimicing gfxHarfBuzzShaper::ShapeWord
     hb_script_t script = (aRunScript <= MOZ_SCRIPT_INHERITED) ?
         HB_SCRIPT_LATIN :
-        hb_script_t(gfxUnicodeProperties::GetScriptTagForCode(aRunScript));
+        hb_script_t(GetScriptTagForCode(aRunScript));
 
     // Prefer HarfBuzz if the font also has support for OpenType shaping of
     // this script.
     const FcChar8 otCapTemplate[] = "otlayout:XXXX";
     FcChar8 otCap[NS_ARRAY_LENGTH(otCapTemplate)];
     memcpy(otCap, otCapTemplate, ArrayLength(otCapTemplate));
     // Subtract 5, for 4 characters and NUL. 
     const PRUint32 scriptOffset = ArrayLength(otCapTemplate) - 5;
@@ -2048,17 +2050,17 @@ gfxPangoFontGroup::FindFontForChar(PRUin
                                    PRInt32 aRunScript,
                                    gfxFont *aPrevMatchedFont,
                                    PRUint8 *aMatchType)
 {
     if (aPrevMatchedFont) {
         // Don't switch fonts for control characters, regardless of
         // whether they are present in the current font, as they won't
         // actually be rendered (see bug 716229)
-        PRUint8 category = gfxUnicodeProperties::GetGeneralCategory(aCh);
+        PRUint8 category = GetGeneralCategory(aCh);
         if (category == HB_UNICODE_GENERAL_CATEGORY_CONTROL) {
             return nsRefPtr<gfxFont>(aPrevMatchedFont).forget();
         }
 
         // if this character is a join-control or the previous is a join-causer,
         // use the same font as the previous range if we can
         if (gfxFontUtils::IsJoinControl(aCh) ||
             gfxFontUtils::IsJoinCauser(aPrevCh)) {
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -57,26 +57,25 @@
 #include "gfxAndroidPlatform.h"
 #endif
 
 #include "gfxAtoms.h"
 #include "gfxPlatformFontList.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "gfxUserFontSet.h"
-#include "gfxUnicodeProperties.h"
+#include "nsUnicodeProperties.h"
 #include "harfbuzz/hb-unicode.h"
 #ifdef MOZ_GRAPHITE
 #include "gfxGraphiteShaper.h"
 #endif
 
 #include "nsUnicodeRange.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
-#include "nsIUGenCategory.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsILocaleService.h"
 
 #include "nsWeakReference.h"
 
 #include "cairo.h"
 #include "qcms.h"
 
@@ -144,17 +143,17 @@ SRGBOverrideObserver::Observe(nsISupport
     ShutdownCMS();
     return NS_OK;
 }
 
 #define GFX_DOWNLOADABLE_FONTS_ENABLED "gfx.downloadable_fonts.enabled"
 #define GFX_DOWNLOADABLE_FONTS_SANITIZE "gfx.downloadable_fonts.sanitize"
 
 #define GFX_PREF_HARFBUZZ_SCRIPTS "gfx.font_rendering.harfbuzz.scripts"
-#define HARFBUZZ_SCRIPTS_DEFAULT  gfxUnicodeProperties::SHAPING_DEFAULT
+#define HARFBUZZ_SCRIPTS_DEFAULT  mozilla::unicode::SHAPING_DEFAULT
 
 #ifdef MOZ_GRAPHITE
 #define GFX_PREF_GRAPHITE_SHAPING "gfx.font_rendering.graphite.enabled"
 #endif
 
 #define BIDI_NUMERAL_PREF "bidi.numeral"
 
 static const char* kObservedPrefs[] = {
@@ -692,17 +691,17 @@ gfxPlatform::UseGraphiteShaping()
 
 bool
 gfxPlatform::UseHarfBuzzForScript(PRInt32 aScriptCode)
 {
     if (mUseHarfBuzzScripts == UNINITIALIZED_VALUE) {
         mUseHarfBuzzScripts = Preferences::GetInt(GFX_PREF_HARFBUZZ_SCRIPTS, HARFBUZZ_SCRIPTS_DEFAULT);
     }
 
-    PRInt32 shapingType = gfxUnicodeProperties::ScriptShapingType(aScriptCode);
+    PRInt32 shapingType = mozilla::unicode::ScriptShapingType(aScriptCode);
 
     return (mUseHarfBuzzScripts & shapingType) != 0;
 }
 
 gfxFontEntry*
 gfxPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
                               const PRUint8 *aFontData,
                               PRUint32 aLength)
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -68,17 +68,17 @@
 #define FORCE_PR_LOG /* Allow logging in the release build */
 #endif
 #include "prlog.h"
 
 #include "gfxPlatformFontList.h"
 
 #include "nsUnicharUtils.h"
 #include "nsUnicodeRange.h"
-#include "gfxUnicodeProperties.h"
+#include "nsUnicodeProperties.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 
 using namespace mozilla;
 
 // font info loader constants
@@ -417,17 +417,17 @@ gfxPlatformFontList::FindFontForChar(con
     TimeDuration elapsed = TimeStamp::Now() - start;
 
 #ifdef PR_LOGGING
     PRLogModuleInfo *log = gfxPlatform::GetLog(eGfxLog_textrun);
 
     if (NS_UNLIKELY(log)) {
         PRUint32 charRange = gfxFontUtils::CharRangeBit(aCh);
         PRUint32 unicodeRange = FindCharUnicodeRange(aCh);
-        PRInt32 script = gfxUnicodeProperties::GetScriptCode(aCh);
+        PRInt32 script = mozilla::unicode::GetScriptCode(aCh);
         PR_LOG(log, PR_LOG_DEBUG,\
                ("(textrun-systemfallback) char: u+%6.6x "
                 "char-range: %d unicode-range: %d script: %d match: [%s]"
                 " count: %d time: %dus\n",
                 aCh,
                 charRange, unicodeRange, script,
                 (data.mBestMatch ?
                  NS_ConvertUTF16toUTF8(data.mBestMatch->Name()).get() :
--- a/gfx/thebes/gfxScriptItemizer.cpp
+++ b/gfx/thebes/gfxScriptItemizer.cpp
@@ -73,18 +73,18 @@
  * dealings in this Software without prior written authorization of the
  * copyright holder.
  *
  * All trademarks and registered trademarks mentioned herein are the property
  * of their respective owners. 
  */
 
 #include "gfxScriptItemizer.h"
-#include "gfxUnicodeProperties.h"
 #include "gfxFontUtils.h" // for the FindHighestBit function
+#include "nsUnicodeProperties.h"
 
 #include "nsCharTraits.h"
 
 #define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
 
 #define MOD(sp) ((sp) % PAREN_STACK_DEPTH)
 #define LIMIT_INC(sp) (((sp) < PAREN_STACK_DEPTH)? (sp) + 1 : PAREN_STACK_DEPTH)
 #define INC(sp,count) (MOD((sp) + (count)))
@@ -276,17 +276,17 @@ gfxScriptItemizer::Next(PRUint32& aRunSt
             if (NS_IS_HIGH_SURROGATE(ch) && scriptLimit < textLength - 1) {
                 PRUint32 low = textPtr[scriptLimit + 1];
                 if (NS_IS_LOW_SURROGATE(low)) {
                     ch = SURROGATE_TO_UCS4(ch, low);
                     scriptLimit += 1;
                 }
             }
 
-            sc = gfxUnicodeProperties::GetScriptCode(ch);
+            sc = mozilla::unicode::GetScriptCode(ch);
 
             pairIndex = getPairIndex(ch);
 
             /*
              * Paired character handling:
              *
              * if it's an open character, push it onto the stack.
              * if it's a close character, find the matching open on the
--- a/gfx/thebes/gfxScriptItemizer.h
+++ b/gfx/thebes/gfxScriptItemizer.h
@@ -78,17 +78,17 @@
  */
 
 #ifndef GFX_SCRIPTITEMIZER_H
 #define GFX_SCRIPTITEMIZER_H
 
 #include "mozilla/StdInt.h"
 #include "prtypes.h"
 #include "harfbuzz/hb.h"
-#include "gfxUnicodeScriptCodes.h"
+#include "nsUnicodeScriptCodes.h"
 
 #define PAREN_STACK_DEPTH 32
 
 class gfxScriptItemizer
 {
 public:
     gfxScriptItemizer(const PRUnichar *src, PRUint32 length);
 
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -220,17 +220,16 @@ public:
     // if either of these prefs are enabled and apply, use ClearType rendering
     bool UseClearTypeForDownloadableFonts();
     bool UseClearTypeAlways();
 
     // OS version in 16.16 major/minor form
     // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
     enum {
         kWindowsUnknown = 0,
-        kWindows2000 = 0x50000,
         kWindowsXP = 0x50001,
         kWindowsServer2003 = 0x50002,
         kWindowsVista = 0x60000,
         kWindows7 = 0x60001
     };
 
     static PRInt32 WindowsOSVersion(PRInt32 *aBuildNum = nsnull);
 
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -407,16 +407,17 @@ SetScreenBrightness(double brightness)
   uint32_t color = (0xff<<24) + (val<<16) + (val<<8) + val;
 
   hal::LightConfiguration aConfig;
   aConfig.mode() = hal::eHalLightMode_User;
   aConfig.flash() = hal::eHalLightFlash_None;
   aConfig.flashOnMS() = aConfig.flashOffMS() = 0;
   aConfig.color() = color;
   hal::SetLight(hal::eHalLightID_Backlight, aConfig);
+  hal::SetLight(hal::eHalLightID_Buttons, aConfig);
 }
 
 static light_device_t* sLights[hal::eHalLightID_Count];	// will be initialized to NULL
 
 light_device_t* GetDevice(hw_module_t* module, char const* name)
 {
   int err;
   hw_device_t* device;
--- a/hal/windows/WindowsBattery.cpp
+++ b/hal/windows/WindowsBattery.cpp
@@ -153,17 +153,17 @@ EnableBatteryNotifications()
                                         &GUID_ACDC_POWER_SOURCE,
                                         DEVICE_NOTIFY_WINDOW_HANDLE);
     sCapacityHandle =
       sRegisterPowerSettingNotification(sHWnd,
                                         &GUID_BATTERY_PERCENTAGE_REMAINING,
                                         DEVICE_NOTIFY_WINDOW_HANDLE);
   } else
   {
-    // for Windows 2000 and Windwos XP.  If we remove Windows XP support,
+    // for Windows XP.  If we remove Windows XP support,
     // we should remove timer-based power notification
     sUpdateTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
     if (sUpdateTimer) {
       sUpdateTimer->InitWithFuncCallback(UpdateHandler,
                                          nsnull,
                                          Preferences::GetInt("dom.battery.timer",
                                                              30000 /* 30s */),
                                          nsITimer::TYPE_REPEATING_SLACK);
--- a/intl/hyphenation/public/nsHyphenator.h
+++ b/intl/hyphenation/public/nsHyphenator.h
@@ -38,17 +38,16 @@
 #ifndef nsHyphenator_h__
 #define nsHyphenator_h__
 
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsTArray.h"
 
 class nsIURI;
-class nsIUGenCategory;
 
 class nsHyphenator
 {
 public:
   nsHyphenator(nsIURI *aURI);
 
   NS_INLINE_DECL_REFCOUNTING(nsHyphenator)
 
@@ -56,12 +55,11 @@ public:
 
   nsresult Hyphenate(const nsAString& aText, nsTArray<bool>& aHyphens);
 
 private:
   ~nsHyphenator();
 
 protected:
   void                      *mDict;
-  nsCOMPtr<nsIUGenCategory>  mCategories;
 };
 
 #endif // nsHyphenator_h__
--- a/intl/hyphenation/src/nsHyphenator.cpp
+++ b/intl/hyphenation/src/nsHyphenator.cpp
@@ -33,17 +33,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsHyphenator.h"
 #include "nsIFile.h"
 #include "nsUTF8Utils.h"
-#include "nsIUGenCategory.h"
+#include "nsUnicodeProperties.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsIURI.h"
 
 #include "hyphen.h"
 
 nsHyphenator::nsHyphenator(nsIURI *aURI)
   : mDict(nsnull)
 {
@@ -53,32 +53,30 @@ nsHyphenator::nsHyphenator(nsIURI *aURI)
     return;
   }
   mDict = hnj_hyphen_load(uriSpec.get());
 #ifdef DEBUG
   if (mDict) {
     printf("loaded hyphenation patterns from %s\n", uriSpec.get());
   }
 #endif
-  mCategories = do_GetService(NS_UNICHARCATEGORY_CONTRACTID, &rv);
-  NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get category service");
 }
 
 nsHyphenator::~nsHyphenator()
 {
   if (mDict != nsnull) {
     hnj_hyphen_free((HyphenDict*)mDict);
     mDict = nsnull;
   }
 }
 
 bool
 nsHyphenator::IsValid()
 {
-  return (mDict != nsnull) && (mCategories != nsnull);
+  return (mDict != nsnull);
 }
 
 nsresult
 nsHyphenator::Hyphenate(const nsAString& aString,
                         nsTArray<bool>& aHyphens)
 {
   if (!aHyphens.SetLength(aString.Length())) {
     return NS_ERROR_OUT_OF_MEMORY;
@@ -96,17 +94,17 @@ nsHyphenator::Hyphenate(const nsAString&
       if (i + 1 < aString.Length() && NS_IS_LOW_SURROGATE(aString[i+1])) {
         ch = SURROGATE_TO_UCS4(ch, aString[i+1]);
         chLen = 2;
       } else {
         NS_WARNING("unpaired surrogate found during hyphenation");
       }
     }
 
-    nsIUGenCategory::nsUGenCategory cat = mCategories->Get(ch);
+    nsIUGenCategory::nsUGenCategory cat = mozilla::unicode::GetGenCategory(ch);
     if (cat == nsIUGenCategory::kLetter || cat == nsIUGenCategory::kMark) {
       if (!inWord) {
         inWord = true;
         wordStart = i;
       }
       wordLimit = i + chLen;
       if (i + chLen < aString.Length()) {
         continue;
--- a/intl/unicharutil/public/Makefile.in
+++ b/intl/unicharutil/public/Makefile.in
@@ -44,12 +44,14 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE		= unicharutil
 
 EXPORTS		= \
 		nsICaseConversion.h \
 		nsIUGenCategory.h \
 		nsUnicharUtilCIID.h \
 		nsUnicodeNormalizer.h \
+		nsUnicodeProperties.h \
+		nsUnicodeScriptCodes.h \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
deleted file mode 100644
--- a/intl/unicharutil/public/nsIUGenDetailCategory.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-#ifndef nsIUGenDetailCategory_h__
-#define nsIUGenDetailCategory_h__
-
-
-#include "nsISupports.h"
-#include "nscore.h"
-
-// {E86B3372-BF89-11d2-B3AF-00805F8A6670}
-#define NS_IUGENDETAILCATEGORY_IID \
-{ 0xe86b3372, 0xbf89, 0x11d2, \
-    { 0xb3, 0xaf, 0x0, 0x80, 0x5f, 0x8a, 0x66, 0x70 } };
-
-
-
-class nsIUGenDetailCategory : public nsISupports {
-
-public: 
-
-  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IUGENDETAILCATEGORY_IID)
-
-   /**
-    *  Read ftp://ftp.unicode.org/Public/UNIDATA/ReadMe-Latest.txt
-    *  section GENERAL CATEGORY
-    *  for the detail defintation of the following categories
-    */
-   typedef enum {
-              
-     kUGDC_M  = (kUGenCategory_Mark << 4) | 0, // Mark- return only when kUGDC_DetailMark bit is clear
-     kUGDC_Mn = (kUGenCategory_Mark << 4) | 1, // Mark, Non-Spacing - return only when kUGDC_DetailMark bit is set
-     kUGDC_Mc = (kUGenCategory_Mark << 4) | 2, // Mark, Spacing Combining - return only when kUGDC_DetailMark bit is set
-     kUGDC_Me = (kUGenCategory_Mark << 4) | 3, // Mark, Enclosing - return only when kUGDC_DetailMark bit is set
-
-     kUGDC_N  = (kUGenCategory_Number << 4) | 0, // Number- return only when kUGDC_DetailNumber bit is clear
-     kUGDC_Nd = (kUGenCategory_Number << 4) | 1, // Number, Decimal Digit - return only when kUGDC_DetailNumber bit is set
-     kUGDC_Nl = (kUGenCategory_Number << 4) | 2, // Number, Letter - return only when kUGDC_DetailNumber bit is set
-     kUGDC_No = (kUGenCategory_Number << 4) | 3, // Number, Other - return only when kUGDC_DetailNumber bit is set
-
-     kUGDC_Z  = (kUGenCategory_Separator << 4) | 0, // Separator- return only when kUGDC_DetailSeparator bit is clear
-     kUGDC_Zs = (kUGenCategory_Separator << 4) | 1, // Separator, Space - return only when kUGDC_DetailSeparator bit is set
-     kUGDC_Zl = (kUGenCategory_Separator << 4) | 2, // Separator, Line - return only when kUGDC_DetailSeparator bit is set
-     kUGDC_Zp = (kUGenCategory_Separator << 4) | 3, // Separator, Paragraph - return only when kUGDC_DetailSeparator bit is set
-
-     kUGDC_C  = (kUGenCategory_Other << 4) | 0, // Other- return only when kUGDC_DetailOther bit is clear
-     kUGDC_Cc = (kUGenCategory_Other << 4) | 1, // Other, Control - return only when kUGDC_DetailOther bit is set
-     kUGDC_Cf = (kUGenCategory_Other << 4) | 2, // Other, Format - return only when kUGDC_DetailOther bit is set
-     kUGDC_Cs = (kUGenCategory_Other << 4) | 3, // Other, Surrogate - return only when kUGDC_DetailOther bit is set
-     kUGDC_Co = (kUGenCategory_Other << 4) | 4, // Other, Private Use - return only when kUGDC_DetailOther bit is set
-     kUGDC_Cn = (kUGenCategory_Other << 4) | 5, // Other, Not Assigned - return only when kUGDC_DetailOther bit is set
-
-     kUGDC_L  = (kUGenCategory_Letter << 4) | 0, // Letter- return only when kUGDC_DetailLetter bit is clear
-     kUGDC_Lu = (kUGenCategory_Letter << 4) | 1, // Letter, Uppercase - return only when kUGDC_DetailLetter bit is set
-     kUGDC_Ll = (kUGenCategory_Letter << 4) | 2, // Letter, Lowercase - return only when kUGDC_DetailLetter bit is set
-     kUGDC_Lt = (kUGenCategory_Letter << 4) | 3, // Letter, Titlecase - return only when kUGDC_DetailLetter bit is set
-     kUGDC_Lm = (kUGenCategory_Letter << 4) | 4, // Letter, Modifier - return only when kUGDC_DetailLetter bit is set
-     kUGDC_Lo = (kUGenCategory_Letter << 4) | 5, // Letter, Other - return only when kUGDC_DetailLetter bit is set
-
-     kUGDC_P  = (kUGenCategory_Punctuation << 4) | 0, // Punctuation- return only when kUGDC_DetailPunctuation bit is clear
-     kUGDC_Pc = (kUGenCategory_Punctuation << 4) | 1, // Punctuation, Connector - return only when kUGDC_DetailPunctuation bit is set
-     kUGDC_Pd = (kUGenCategory_Punctuation << 4) | 2, // Punctuation, Dash - return only when kUGDC_DetailPunctuation bit is set
-     kUGDC_Ps = (kUGenCategory_Punctuation << 4) | 3, // Punctuation, Open - return only when kUGDC_DetailPunctuation bit is set
-     kUGDC_Pe = (kUGenCategory_Punctuation << 4) | 4, // Punctuation, Close - return only when kUGDC_DetailPunctuation bit is set
-     kUGDC_Pi = (kUGenCategory_Punctuation << 4) | 5, // Punctuation, Initial quote - return only when kUGDC_DetailPunctuation bit is set
-     kUGDC_Pf = (kUGenCategory_Punctuation << 4) | 6, // Punctuation, Final quote - return only when kUGDC_DetailPunctuation bit is set
-     kUGDC_Po = (kUGenCategory_Punctuation << 4) | 7, // Punctuation, Other - return only when kUGDC_DetailPunctuation bit is set
-
-     kUGDC_S  = (kUGenCategory_Symbol << 4) | 0, // Symbol- return only when kUGDC_DetailSymbol bit is clear
-     kUGDC_Sm = (kUGenCategory_Symbol << 4) | 1, // Symbol, Math - return only when kUGDC_DetailSymbol bit is set
-     kUGDC_Sc = (kUGenCategory_Symbol << 4) | 2, // Symbol, Currency - return only when kUGDC_DetailSymbol bit is set
-     kUGDC_Sk = (kUGenCategory_Symbol << 4) | 3, // Symbol, Modifier - return only when kUGDC_DetailSymbol bit is set
-     kUGDC_So = (kUGenCategory_Symbol << 4) | 4, // Symbol, Other - return only when kUGDC_DetailSymbol bit is set
-   } nsUGDC;
-
-   /**
-    * Sometimes, we want the Get method only return detail in certain 
-    * area. It help to ignore unnecessary detail to improve performance
-    **/
-   typedef enum {
-     kUGDC_DetailNone          = 0,
-     kUGDC_DetailMark          = ( 1 << 0),
-     kUGDC_DetailNumber        = ( 1 << 1),
-     kUGDC_DetailSeparator     = ( 1 << 2),
-     kUGDC_DetailOther         = ( 1 << 3),
-     kUGDC_DetailLetter        = ( 1 << 4),
-     kUGDC_DetailPunctuation   = ( 1 << 5),
-     kUGDC_DetailSymbol        = ( 1 << 6),
-     kUGDC_DetailNormative     = ( kUGDC_DetailMark | 
-                                   kUGDC_DetailNumber | 
-                                   kUGDC_DetailSeparator | 
-                                   kUGDC_DetailOther  ),
-     kUGDC_DetailInformative   = ( kUGDC_DetailLetter | 
-                                   kUGDC_DetailPunctuation | 
-                                   kUGDC_DetailSymbol);
-     kUGDC_DetailAll           = ( kUGDC_DetailNormative | kUGDC_Informative );
-   } nsUGDC_Detail;
-
-   /**
-    * Give a Unichar, return a nsUGDC
-    */
-   NS_IMETHOD Get( PRUnichar aChar, nsUGDC_Detail aDetailSpec, nsUGDC* oResult) = 0 ;
-    
-   /**
-    * Give a Unichar, and a nsUGenDetailCategory, 
-    * return true if the Unichar is in that category, 
-    * return false, otherwise
-    */
-   NS_IMETHOD Is( PRUnichar aChar, nsUGDC aDetailCategory, bool* oResult) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIUGenDetailCategory,
-                              NS_IUGENDETAILCATEGORY_IID)
-
-#endif  /* nsIUGenDetailCategory_h__ */
rename from gfx/thebes/gfxUnicodeProperties.h
rename to intl/unicharutil/public/nsUnicodeProperties.h
--- a/gfx/thebes/gfxUnicodeProperties.h
+++ b/intl/unicharutil/public/nsUnicodeProperties.h
@@ -30,55 +30,66 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#ifndef GFX_UNICODEPROPERTIES_H
-#define GFX_UNICODEPROPERTIES_H
+#ifndef NS_UNICODEPROPERTIES_H
+#define NS_UNICODEPROPERTIES_H
 
 #include "prtypes.h"
-#include "gfxTypes.h"
-#include "gfxUnicodeScriptCodes.h"
+#include "nsIUGenCategory.h"
 
-class THEBES_API gfxUnicodeProperties
-{
-public:
-    static PRUint32 GetMirroredChar(PRUint32 aCh);
+namespace mozilla {
+
+namespace unicode {
 
-    static PRUint8 GetCombiningClass(PRUint32 aCh);
+extern nsIUGenCategory::nsUGenCategory sDetailedToGeneralCategory[];
 
-    static PRUint8 GetGeneralCategory(PRUint32 aCh);
+PRUint32 GetMirroredChar(PRUint32 aCh);
 
-    static PRUint8 GetEastAsianWidth(PRUint32 aCh);
+PRUint8 GetCombiningClass(PRUint32 aCh);
 
-    static PRInt32 GetScriptCode(PRUint32 aCh);
-
-    static PRUint32 GetScriptTagForCode(PRInt32 aScriptCode);
+// returns the detailed General Category in terms of HB_UNICODE_* values
+PRUint8 GetGeneralCategory(PRUint32 aCh);
 
-    enum HSType {
-        HST_NONE = 0x00,
-        HST_L    = 0x01,
-        HST_V    = 0x02,
-        HST_T    = 0x04,
-        HST_LV   = 0x03,
-        HST_LVT  = 0x07
-    };
+// returns the simplified Gen Category as defined in nsIUGenCategory
+inline nsIUGenCategory::nsUGenCategory GetGenCategory(PRUint32 aCh) {
+  return sDetailedToGeneralCategory[GetGeneralCategory(aCh)];
+}
 
-    static HSType GetHangulSyllableType(PRUint32 aCh);
+PRUint8 GetEastAsianWidth(PRUint32 aCh);
+
+PRInt32 GetScriptCode(PRUint32 aCh);
 
-    enum ShapingType {
-        SHAPING_DEFAULT   = 0x0001,
-        SHAPING_ARABIC    = 0x0002,
-        SHAPING_HEBREW    = 0x0004,
-        SHAPING_HANGUL    = 0x0008,
-        SHAPING_MONGOLIAN = 0x0010,
-        SHAPING_INDIC     = 0x0020,
-        SHAPING_THAI      = 0x0040
-    };
+PRUint32 GetScriptTagForCode(PRInt32 aScriptCode);
 
-    static PRInt32 ScriptShapingType(PRInt32 aScriptCode);
+enum HSType {
+    HST_NONE = 0x00,
+    HST_L    = 0x01,
+    HST_V    = 0x02,
+    HST_T    = 0x04,
+    HST_LV   = 0x03,
+    HST_LVT  = 0x07
 };
 
-#endif /* GFX_UNICODEPROPERTIES_H */
+HSType GetHangulSyllableType(PRUint32 aCh);
+
+enum ShapingType {
+    SHAPING_DEFAULT   = 0x0001,
+    SHAPING_ARABIC    = 0x0002,
+    SHAPING_HEBREW    = 0x0004,
+    SHAPING_HANGUL    = 0x0008,
+    SHAPING_MONGOLIAN = 0x0010,
+    SHAPING_INDIC     = 0x0020,
+    SHAPING_THAI      = 0x0040
+};
+
+PRInt32 ScriptShapingType(PRInt32 aScriptCode);
+
+} // end namespace unicode
+
+} // end namespace mozilla
+
+#endif /* NS_UNICODEPROPERTIES_H */
rename from gfx/thebes/gfxUnicodeScriptCodes.h
rename to intl/unicharutil/public/nsUnicodeScriptCodes.h
--- a/gfx/thebes/gfxUnicodeScriptCodes.h
+++ b/intl/unicharutil/public/nsUnicodeScriptCodes.h
@@ -29,24 +29,24 @@
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
- * Derived from the Unicode Character Database by genUnicodeScriptData.pl
+ * Derived from the Unicode Character Database by genUnicodePropertyData.pl
  *
  * For Unicode terms of use, see http://www.unicode.org/terms_of_use.html
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
- * Created on Mon Feb 13 09:25:50 2012 from UCD data files with version info:
+ * Created on Thu Feb 23 13:15:51 2012 from UCD data files with version info:
  *
 
 # Date: 2012-01-26, 22:03:00 GMT [KW]
 #
 # Unicode Character Database
 # Copyright (c) 1991-2012 Unicode, Inc.
 # For terms of use, see http://www.unicode.org/terms_of_use.html
 #
@@ -69,18 +69,18 @@ for the Unicode Character Database (UCD)
 
 # HangulSyllableType-6.1.0.txt
 # Date: 2011-08-25, 00:02:18 GMT [MD]
 
  *
  * * * * * This file contains MACHINE-GENERATED DATA, do not edit! * * * * *
  */
 
-#ifndef GFX_UNICODE_SCRIPT_CODES
-#define GFX_UNICODE_SCRIPT_CODES
+#ifndef NS_UNICODE_SCRIPT_CODES
+#define NS_UNICODE_SCRIPT_CODES
 enum {
   MOZ_SCRIPT_COMMON = 0,
   MOZ_SCRIPT_INHERITED = 1,
   MOZ_SCRIPT_ARABIC = 2,
   MOZ_SCRIPT_ARMENIAN = 3,
   MOZ_SCRIPT_BENGALI = 4,
   MOZ_SCRIPT_BOPOMOFO = 5,
   MOZ_SCRIPT_CHEROKEE = 6,
--- a/intl/unicharutil/src/Makefile.in
+++ b/intl/unicharutil/src/Makefile.in
@@ -42,18 +42,20 @@ VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= unicharutil
 LIBRARY_NAME	= ucharucomp_s
 FORCE_STATIC_LIB = 1
 LIBXUL_LIBRARY = 1
 
+DEFINES += -DHB_DONT_DEFINE_STDINT
 
 CPPSRCS		= \
 		nsCaseConversionImp2.cpp \
 		nsCategoryImp.cpp \
 		nsEntityConverter.cpp \
 		nsSaveAsCharset.cpp \
 		nsUnicodeNormalizer.cpp \
+		nsUnicodeProperties.cpp \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/intl/unicharutil/src/cattable.h
+++ /dev/null
@@ -1,4384 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1999
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-/* 
-    DO NOT EDIT THIS DOCUMENT !!! THIS DOCUMENT IS GENERATED BY
-    mozilla/intl/unicharutil/tools/gencattable.pl
- */
-#include "nscore.h" 
-
-static const PRUint8 gGenCatIdx1[928] = {
-      0,  // U+000000 - U+000007 : 0x44444444
-      0,  // U+000008 - U+00000F : 0x44444444
-      0,  // U+000010 - U+000017 : 0x44444444
-      0,  // U+000018 - U+00001F : 0x44444444
-      1,  // U+000020 - U+000027 : 0x66676663
-      2,  // U+000028 - U+00002F : 0x66667666
-      3,  // U+000030 - U+000037 : 0x22222222
-      4,  // U+000038 - U+00003F : 0x67776622
-      5,  // U+000040 - U+000047 : 0x55555556
-      6,  // U+000048 - U+00004F : 0x55555555
-      6,  // U+000050 - U+000057 : 0x55555555
-      7,  // U+000058 - U+00005F : 0x67666555
-      8,  // U+000060 - U+000067 : 0x55555557
-      6,  // U+000068 - U+00006F : 0x55555555
-      6,  // U+000070 - U+000077 : 0x55555555
-      9,  // U+000078 - U+00007F : 0x47676555
-      0,  // U+000080 - U+000087 : 0x44444444
-      0,  // U+000088 - U+00008F : 0x44444444
-      0,  // U+000090 - U+000097 : 0x44444444
-      0,  // U+000098 - U+00009F : 0x44444444
-     10,  // U+0000A0 - U+0000A7 : 0x67777763
-     11,  // U+0000A8 - U+0000AF : 0x77476577
-     12,  // U+0000B0 - U+0000B7 : 0x66572277
-     13,  // U+0000B8 - U+0000BF : 0x62226527
-      6,  // U+0000C0 - U+0000C7 : 0x55555555
-      6,  // U+0000C8 - U+0000CF : 0x55555555
-     14,  // U+0000D0 - U+0000D7 : 0x75555555
-      6,  // U+0000D8 - U+0000DF : 0x55555555
-      6,  // U+0000E0 - U+0000E7 : 0x55555555
-      6,  // U+0000E8 - U+0000EF : 0x55555555
-     14,  // U+0000F0 - U+0000F7 : 0x75555555
-      6,  // U+0000F8 - U+0000FF : 0x55555555
-      6,  // U+000100 - U+000107 : 0x55555555
-      6,  // U+000108 - U+00010F : 0x55555555
-      6,  // U+000110 - U+000117 : 0x55555555
-      6,  // U+000118 - U+00011F : 0x55555555
-      6,  // U+000120 - U+000127 : 0x55555555
-      6,  // U+000128 - U+00012F : 0x55555555
-      6,  // U+000130 - U+000137 : 0x55555555
-      6,  // U+000138 - U+00013F : 0x55555555
-      6,  // U+000140 - U+000147 : 0x55555555
-      6,  // U+000148 - U+00014F : 0x55555555
-      6,  // U+000150 - U+000157 : 0x55555555
-      6,  // U+000158 - U+00015F : 0x55555555
-      6,  // U+000160 - U+000167 : 0x55555555
-      6,  // U+000168 - U+00016F : 0x55555555
-      6,  // U+000170 - U+000177 : 0x55555555
-      6,  // U+000178 - U+00017F : 0x55555555
-      6,  // U+000180 - U+000187 : 0x55555555
-      6,  // U+000188 - U+00018F : 0x55555555
-      6,  // U+000190 - U+000197 : 0x55555555
-      6,  // U+000198 - U+00019F : 0x55555555
-      6,  // U+0001A0 - U+0001A7 : 0x55555555
-      6,  // U+0001A8 - U+0001AF : 0x55555555
-      6,  // U+0001B0 - U+0001B7 : 0x55555555
-      6,  // U+0001B8 - U+0001BF : 0x55555555
-      6,  // U+0001C0 - U+0001C7 : 0x55555555
-      6,  // U+0001C8 - U+0001CF : 0x55555555
-      6,  // U+0001D0 - U+0001D7 : 0x55555555
-      6,  // U+0001D8 - U+0001DF : 0x55555555
-      6,  // U+0001E0 - U+0001E7 : 0x55555555
-      6,  // U+0001E8 - U+0001EF : 0x55555555
-      6,  // U+0001F0 - U+0001F7 : 0x55555555
-      6,  // U+0001F8 - U+0001FF : 0x55555555
-      6,  // U+000200 - U+000207 : 0x55555555
-      6,  // U+000208 - U+00020F : 0x55555555
-      6,  // U+000210 - U+000217 : 0x55555555
-      6,  // U+000218 - U+00021F : 0x55555555
-      6,  // U+000220 - U+000227 : 0x55555555
-      6,  // U+000228 - U+00022F : 0x55555555
-      6,  // U+000230 - U+000237 : 0x55555555
-      6,  // U+000238 - U+00023F : 0x55555555
-      6,  // U+000240 - U+000247 : 0x55555555
-      6,  // U+000248 - U+00024F : 0x55555555
-      6,  // U+000250 - U+000257 : 0x55555555
-      6,  // U+000258 - U+00025F : 0x55555555
-      6,  // U+000260 - U+000267 : 0x55555555
-      6,  // U+000268 - U+00026F : 0x55555555
-      6,  // U+000270 - U+000277 : 0x55555555
-      6,  // U+000278 - U+00027F : 0x55555555
-      6,  // U+000280 - U+000287 : 0x55555555
-      6,  // U+000288 - U+00028F : 0x55555555
-      6,  // U+000290 - U+000297 : 0x55555555
-      6,  // U+000298 - U+00029F : 0x55555555
-      6,  // U+0002A0 - U+0002A7 : 0x55555555
-      6,  // U+0002A8 - U+0002AF : 0x55555555
-      6,  // U+0002B0 - U+0002B7 : 0x55555555
-      6,  // U+0002B8 - U+0002BF : 0x55555555
-     15,  // U+0002C0 - U+0002C7 : 0x55777755
-      6,  // U+0002C8 - U+0002CF : 0x55555555
-     16,  // U+0002D0 - U+0002D7 : 0x77777755
-     17,  // U+0002D8 - U+0002DF : 0x77777777
-     18,  // U+0002E0 - U+0002E7 : 0x77755555
-     19,  // U+0002E8 - U+0002EF : 0x75757777
-     17,  // U+0002F0 - U+0002F7 : 0x77777777
-     17,  // U+0002F8 - U+0002FF : 0x77777777
-     20,  // U+000300 - U+000307 : 0x11111111
-     20,  // U+000308 - U+00030F : 0x11111111
-     20,  // U+000310 - U+000317 : 0x11111111
-     20,  // U+000318 - U+00031F : 0x11111111
-     20,  // U+000320 - U+000327 : 0x11111111
-     20,  // U+000328 - U+00032F : 0x11111111
-     20,  // U+000330 - U+000337 : 0x11111111
-     20,  // U+000338 - U+00033F : 0x11111111
-     20,  // U+000340 - U+000347 : 0x11111111
-     20,  // U+000348 - U+00034F : 0x11111111
-     20,  // U+000350 - U+000357 : 0x11111111
-     20,  // U+000358 - U+00035F : 0x11111111
-     20,  // U+000360 - U+000367 : 0x11111111
-     20,  // U+000368 - U+00036F : 0x11111111
-     21,  // U+000370 - U+000377 : 0x55755555
-     22,  // U+000378 - U+00037F : 0x06555500
-     23,  // U+000380 - U+000387 : 0x65770000
-     24,  // U+000388 - U+00038F : 0x55050555
-      6,  // U+000390 - U+000397 : 0x55555555
-      6,  // U+000398 - U+00039F : 0x55555555
-     25,  // U+0003A0 - U+0003A7 : 0x55555055
-      6,  // U+0003A8 - U+0003AF : 0x55555555
-      6,  // U+0003B0 - U+0003B7 : 0x55555555
-      6,  // U+0003B8 - U+0003BF : 0x55555555
-      6,  // U+0003C0 - U+0003C7 : 0x55555555
-      6,  // U+0003C8 - U+0003CF : 0x55555555
-      6,  // U+0003D0 - U+0003D7 : 0x55555555
-      6,  // U+0003D8 - U+0003DF : 0x55555555
-      6,  // U+0003E0 - U+0003E7 : 0x55555555
-      6,  // U+0003E8 - U+0003EF : 0x55555555
-     26,  // U+0003F0 - U+0003F7 : 0x57555555
-      6,  // U+0003F8 - U+0003FF : 0x55555555
-      6,  // U+000400 - U+000407 : 0x55555555
-      6,  // U+000408 - U+00040F : 0x55555555
-      6,  // U+000410 - U+000417 : 0x55555555
-      6,  // U+000418 - U+00041F : 0x55555555
-      6,  // U+000420 - U+000427 : 0x55555555
-      6,  // U+000428 - U+00042F : 0x55555555
-      6,  // U+000430 - U+000437 : 0x55555555
-      6,  // U+000438 - U+00043F : 0x55555555
-      6,  // U+000440 - U+000447 : 0x55555555
-      6,  // U+000448 - U+00044F : 0x55555555
-      6,  // U+000450 - U+000457 : 0x55555555
-      6,  // U+000458 - U+00045F : 0x55555555
-      6,  // U+000460 - U+000467 : 0x55555555
-      6,  // U+000468 - U+00046F : 0x55555555
-      6,  // U+000470 - U+000477 : 0x55555555
-      6,  // U+000478 - U+00047F : 0x55555555
-     27,  // U+000480 - U+000487 : 0x11111755
-     28,  // U+000488 - U+00048F : 0x55555511
-      6,  // U+000490 - U+000497 : 0x55555555
-      6,  // U+000498 - U+00049F : 0x55555555
-      6,  // U+0004A0 - U+0004A7 : 0x55555555
-      6,  // U+0004A8 - U+0004AF : 0x55555555
-      6,  // U+0004B0 - U+0004B7 : 0x55555555
-      6,  // U+0004B8 - U+0004BF : 0x55555555
-      6,  // U+0004C0 - U+0004C7 : 0x55555555
-      6,  // U+0004C8 - U+0004CF : 0x55555555
-      6,  // U+0004D0 - U+0004D7 : 0x55555555
-      6,  // U+0004D8 - U+0004DF : 0x55555555
-      6,  // U+0004E0 - U+0004E7 : 0x55555555
-      6,  // U+0004E8 - U+0004EF : 0x55555555
-      6,  // U+0004F0 - U+0004F7 : 0x55555555
-      6,  // U+0004F8 - U+0004FF : 0x55555555
-      6,  // U+000500 - U+000507 : 0x55555555
-      6,  // U+000508 - U+00050F : 0x55555555
-      6,  // U+000510 - U+000517 : 0x55555555
-      6,  // U+000518 - U+00051F : 0x55555555
-      6,  // U+000520 - U+000527 : 0x55555555
-     29,  // U+000528 - U+00052F : 0x00000000
-     30,  // U+000530 - U+000537 : 0x55555550
-      6,  // U+000538 - U+00053F : 0x55555555
-      6,  // U+000540 - U+000547 : 0x55555555
-      6,  // U+000548 - U+00054F : 0x55555555
-     31,  // U+000550 - U+000557 : 0x05555555
-     32,  // U+000558 - U+00055F : 0x66666650
-     30,  // U+000560 - U+000567 : 0x55555550
-      6,  // U+000568 - U+00056F : 0x55555555
-      6,  // U+000570 - U+000577 : 0x55555555
-      6,  // U+000578 - U+00057F : 0x55555555
-      6,  // U+000580 - U+000587 : 0x55555555
-     33,  // U+000588 - U+00058F : 0x70000660
-     34,  // U+000590 - U+000597 : 0x11111110
-     20,  // U+000598 - U+00059F : 0x11111111
-     20,  // U+0005A0 - U+0005A7 : 0x11111111
-     20,  // U+0005A8 - U+0005AF : 0x11111111
-     20,  // U+0005B0 - U+0005B7 : 0x11111111
-     35,  // U+0005B8 - U+0005BF : 0x16111111
-     36,  // U+0005C0 - U+0005C7 : 0x16116116
-     29,  // U+0005C8 - U+0005CF : 0x00000000
-      6,  // U+0005D0 - U+0005D7 : 0x55555555
-      6,  // U+0005D8 - U+0005DF : 0x55555555
-      6,  // U+0005E0 - U+0005E7 : 0x55555555
-     37,  // U+0005E8 - U+0005EF : 0x00000555
-     38,  // U+0005F0 - U+0005F7 : 0x00066555
-     29,  // U+0005F8 - U+0005FF : 0x00000000
-     39,  // U+000600 - U+000607 : 0x77044444
-     40,  // U+000608 - U+00060F : 0x77667667
-     20,  // U+000610 - U+000617 : 0x11111111
-     41,  // U+000618 - U+00061F : 0x66006111
-      6,  // U+000620 - U+000627 : 0x55555555
-      6,  // U+000628 - U+00062F : 0x55555555
-      6,  // U+000630 - U+000637 : 0x55555555
-      6,  // U+000638 - U+00063F : 0x55555555
-      6,  // U+000640 - U+000647 : 0x55555555
-     42,  // U+000648 - U+00064F : 0x11111555
-     20,  // U+000650 - U+000657 : 0x11111111
-     20,  // U+000658 - U+00065F : 0x11111111
-      3,  // U+000660 - U+000667 : 0x22222222
-     43,  // U+000668 - U+00066F : 0x55666622
-     44,  // U+000670 - U+000677 : 0x55555551
-      6,  // U+000678 - U+00067F : 0x55555555
-      6,  // U+000680 - U+000687 : 0x55555555
-      6,  // U+000688 - U+00068F : 0x55555555
-      6,  // U+000690 - U+000697 : 0x55555555
-      6,  // U+000698 - U+00069F : 0x55555555
-      6,  // U+0006A0 - U+0006A7 : 0x55555555
-      6,  // U+0006A8 - U+0006AF : 0x55555555
-      6,  // U+0006B0 - U+0006B7 : 0x55555555
-      6,  // U+0006B8 - U+0006BF : 0x55555555
-      6,  // U+0006C0 - U+0006C7 : 0x55555555
-      6,  // U+0006C8 - U+0006CF : 0x55555555
-     45,  // U+0006D0 - U+0006D7 : 0x11565555
-     46,  // U+0006D8 - U+0006DF : 0x17411111
-     47,  // U+0006E0 - U+0006E7 : 0x15511111
-     48,  // U+0006E8 - U+0006EF : 0x55111171
-      3,  // U+0006F0 - U+0006F7 : 0x22222222
-     49,  // U+0006F8 - U+0006FF : 0x57755522
-     50,  // U+000700 - U+000707 : 0x66666666
-     51,  // U+000708 - U+00070F : 0x40666666
-     52,  // U+000710 - U+000717 : 0x55555515
-      6,  // U+000718 - U+00071F : 0x55555555
-      6,  // U+000720 - U+000727 : 0x55555555
-      6,  // U+000728 - U+00072F : 0x55555555
-     20,  // U+000730 - U+000737 : 0x11111111
-     20,  // U+000738 - U+00073F : 0x11111111
-     20,  // U+000740 - U+000747 : 0x11111111
-     53,  // U+000748 - U+00074F : 0x55500111
-      6,  // U+000750 - U+000757 : 0x55555555
-      6,  // U+000758 - U+00075F : 0x55555555
-      6,  // U+000760 - U+000767 : 0x55555555
-      6,  // U+000768 - U+00076F : 0x55555555
-      6,  // U+000770 - U+000777 : 0x55555555
-      6,  // U+000778 - U+00077F : 0x55555555
-      6,  // U+000780 - U+000787 : 0x55555555
-      6,  // U+000788 - U+00078F : 0x55555555
-      6,  // U+000790 - U+000797 : 0x55555555
-      6,  // U+000798 - U+00079F : 0x55555555
-     54,  // U+0007A0 - U+0007A7 : 0x11555555
-     20,  // U+0007A8 - U+0007AF : 0x11111111
-     55,  // U+0007B0 - U+0007B7 : 0x00000051
-     29,  // U+0007B8 - U+0007BF : 0x00000000
-      3,  // U+0007C0 - U+0007C7 : 0x22222222
-     56,  // U+0007C8 - U+0007CF : 0x55555522
-      6,  // U+0007D0 - U+0007D7 : 0x55555555
-      6,  // U+0007D8 - U+0007DF : 0x55555555
-      6,  // U+0007E0 - U+0007E7 : 0x55555555
-     42,  // U+0007E8 - U+0007EF : 0x11111555
-     57,  // U+0007F0 - U+0007F7 : 0x67551111
-     58,  // U+0007F8 - U+0007FF : 0x00000566
-      6,  // U+000800 - U+000807 : 0x55555555
-      6,  // U+000808 - U+00080F : 0x55555555
-     54,  // U+000810 - U+000817 : 0x11555555
-     59,  // U+000818 - U+00081F : 0x11111511
-     60,  // U+000820 - U+000827 : 0x11151111
-     61,  // U+000828 - U+00082F : 0x00111115
-     50,  // U+000830 - U+000837 : 0x66666666
-     62,  // U+000838 - U+00083F : 0x06666666
-      6,  // U+000840 - U+000847 : 0x55555555
-      6,  // U+000848 - U+00084F : 0x55555555
-      6,  // U+000850 - U+000857 : 0x55555555
-     63,  // U+000858 - U+00085F : 0x06001115
-     29,  // U+000860 - U+000867 : 0x00000000
-     29,  // U+000868 - U+00086F : 0x00000000
-     29,  // U+000870 - U+000877 : 0x00000000
-     29,  // U+000878 - U+00087F : 0x00000000
-     29,  // U+000880 - U+000887 : 0x00000000
-     29,  // U+000888 - U+00088F : 0x00000000
-     29,  // U+000890 - U+000897 : 0x00000000
-     29,  // U+000898 - U+00089F : 0x00000000
-     64,  // U+0008A0 - U+0008A7 : 0x55555505
-     65,  // U+0008A8 - U+0008AF : 0x00055555
-     29,  // U+0008B0 - U+0008B7 : 0x00000000
-     29,  // U+0008B8 - U+0008BF : 0x00000000
-     29,  // U+0008C0 - U+0008C7 : 0x00000000
-     29,  // U+0008C8 - U+0008CF : 0x00000000
-     29,  // U+0008D0 - U+0008D7 : 0x00000000
-     29,  // U+0008D8 - U+0008DF : 0x00000000
-     66,  // U+0008E0 - U+0008E7 : 0x11110000
-     20,  // U+0008E8 - U+0008EF : 0x11111111
-     20,  // U+0008F0 - U+0008F7 : 0x11111111
-     67,  // U+0008F8 - U+0008FF : 0x01111111
-     68,  // U+000900 - U+000907 : 0x55551111
-      6,  // U+000908 - U+00090F : 0x55555555
-      6,  // U+000910 - U+000917 : 0x55555555
-      6,  // U+000918 - U+00091F : 0x55555555
-      6,  // U+000920 - U+000927 : 0x55555555
-      6,  // U+000928 - U+00092F : 0x55555555
-      6,  // U+000930 - U+000937 : 0x55555555
-     69,  // U+000938 - U+00093F : 0x11511155
-     20,  // U+000940 - U+000947 : 0x11111111
-     20,  // U+000948 - U+00094F : 0x11111111
-     70,  // U+000950 - U+000957 : 0x11111115
-      6,  // U+000958 - U+00095F : 0x55555555
-     71,  // U+000960 - U+000967 : 0x22661155
-      3,  // U+000968 - U+00096F : 0x22222222
-      5,  // U+000970 - U+000977 : 0x55555556
-     30,  // U+000978 - U+00097F : 0x55555550
-     72,  // U+000980 - U+000987 : 0x55501110
-     73,  // U+000988 - U+00098F : 0x50055555
-     74,  // U+000990 - U+000997 : 0x55555005
-      6,  // U+000998 - U+00099F : 0x55555555
-      6,  // U+0009A0 - U+0009A7 : 0x55555555
-     64,  // U+0009A8 - U+0009AF : 0x55555505
-     75,  // U+0009B0 - U+0009B7 : 0x55000505
-     76,  // U+0009B8 - U+0009BF : 0x11510055
-     77,  // U+0009C0 - U+0009C7 : 0x10011111
-     78,  // U+0009C8 - U+0009CF : 0x05111001
-     79,  // U+0009D0 - U+0009D7 : 0x10000000
-     80,  // U+0009D8 - U+0009DF : 0x50550000
-     81,  // U+0009E0 - U+0009E7 : 0x22001155
-      3,  // U+0009E8 - U+0009EF : 0x22222222
-     82,  // U+0009F0 - U+0009F7 : 0x22227755
-     83,  // U+0009F8 - U+0009FF : 0x00007722
-     72,  // U+000A00 - U+000A07 : 0x55501110
-     84,  // U+000A08 - U+000A0F : 0x50000555
-     74,  // U+000A10 - U+000A17 : 0x55555005
-      6,  // U+000A18 - U+000A1F : 0x55555555
-      6,  // U+000A20 - U+000A27 : 0x55555555
-     64,  // U+000A28 - U+000A2F : 0x55555505
-     85,  // U+000A30 - U+000A37 : 0x05505505
-     86,  // U+000A38 - U+000A3F : 0x11010055
-     87,  // U+000A40 - U+000A47 : 0x10000111
-     88,  // U+000A48 - U+000A4F : 0x00111001
-     89,  // U+000A50 - U+000A57 : 0x00000010
-     90,  // U+000A58 - U+000A5F : 0x05055550
-     91,  // U+000A60 - U+000A67 : 0x22000000
-      3,  // U+000A68 - U+000A6F : 0x22222222
-     92,  // U+000A70 - U+000A77 : 0x00155511
-     29,  // U+000A78 - U+000A7F : 0x00000000
-     72,  // U+000A80 - U+000A87 : 0x55501110
-     93,  // U+000A88 - U+000A8F : 0x50555555
-     25,  // U+000A90 - U+000A97 : 0x55555055
-      6,  // U+000A98 - U+000A9F : 0x55555555
-      6,  // U+000AA0 - U+000AA7 : 0x55555555
-     64,  // U+000AA8 - U+000AAF : 0x55555505
-     94,  // U+000AB0 - U+000AB7 : 0x55505505
-     76,  // U+000AB8 - U+000ABF : 0x11510055
-     95,  // U+000AC0 - U+000AC7 : 0x10111111
-     96,  // U+000AC8 - U+000ACF : 0x00111011
-     97,  // U+000AD0 - U+000AD7 : 0x00000005
-     29,  // U+000AD8 - U+000ADF : 0x00000000
-     81,  // U+000AE0 - U+000AE7 : 0x22001155
-      3,  // U+000AE8 - U+000AEF : 0x22222222
-     98,  // U+000AF0 - U+000AF7 : 0x00000076
-     29,  // U+000AF8 - U+000AFF : 0x00000000
-     72,  // U+000B00 - U+000B07 : 0x55501110
-     73,  // U+000B08 - U+000B0F : 0x50055555
-     74,  // U+000B10 - U+000B17 : 0x55555005
-      6,  // U+000B18 - U+000B1F : 0x55555555
-      6,  // U+000B20 - U+000B27 : 0x55555555
-     64,  // U+000B28 - U+000B2F : 0x55555505
-     94,  // U+000B30 - U+000B37 : 0x55505505
-     76,  // U+000B38 - U+000B3F : 0x11510055
-     77,  // U+000B40 - U+000B47 : 0x10011111
-     88,  // U+000B48 - U+000B4F : 0x00111001
-     99,  // U+000B50 - U+000B57 : 0x11000000
-     80,  // U+000B58 - U+000B5F : 0x50550000
-     81,  // U+000B60 - U+000B67 : 0x22001155
-      3,  // U+000B68 - U+000B6F : 0x22222222
-    100,  // U+000B70 - U+000B77 : 0x22222257
-     29,  // U+000B78 - U+000B7F : 0x00000000
-    101,  // U+000B80 - U+000B87 : 0x55505100
-    102,  // U+000B88 - U+000B8F : 0x55000555
-    103,  // U+000B90 - U+000B97 : 0x00555505
-    104,  // U+000B98 - U+000B9F : 0x55050550
-    105,  // U+000BA0 - U+000BA7 : 0x00055000
-    102,  // U+000BA8 - U+000BAF : 0x55000555
-      6,  // U+000BB0 - U+000BB7 : 0x55555555
-    106,  // U+000BB8 - U+000BBF : 0x11000055
-    107,  // U+000BC0 - U+000BC7 : 0x11000111
-    108,  // U+000BC8 - U+000BCF : 0x00111101
-    109,  // U+000BD0 - U+000BD7 : 0x10000005
-     29,  // U+000BD8 - U+000BDF : 0x00000000
-     91,  // U+000BE0 - U+000BE7 : 0x22000000
-      3,  // U+000BE8 - U+000BEF : 0x22222222
-    110,  // U+000BF0 - U+000BF7 : 0x77777222
-    111,  // U+000BF8 - U+000BFF : 0x00000777
-     72,  // U+000C00 - U+000C07 : 0x55501110
-    112,  // U+000C08 - U+000C0F : 0x55055555
-     64,  // U+000C10 - U+000C17 : 0x55555505
-      6,  // U+000C18 - U+000C1F : 0x55555555
-      6,  // U+000C20 - U+000C27 : 0x55555555
-     64,  // U+000C28 - U+000C2F : 0x55555505
-    113,  // U+000C30 - U+000C37 : 0x55505555
-    114,  // U+000C38 - U+000C3F : 0x11500055
-    115,  // U+000C40 - U+000C47 : 0x11011111
-    108,  // U+000C48 - U+000C4F : 0x00111101
-    116,  // U+000C50 - U+000C57 : 0x01100000
-    117,  // U+000C58 - U+000C5F : 0x00000055
-     81,  // U+000C60 - U+000C67 : 0x22001155
-      3,  // U+000C68 - U+000C6F : 0x22222222
-     29,  // U+000C70 - U+000C77 : 0x00000000
-    118,  // U+000C78 - U+000C7F : 0x72222222
-    119,  // U+000C80 - U+000C87 : 0x55501100
-    112,  // U+000C88 - U+000C8F : 0x55055555
-     64,  // U+000C90 - U+000C97 : 0x55555505
-      6,  // U+000C98 - U+000C9F : 0x55555555
-      6,  // U+000CA0 - U+000CA7 : 0x55555555
-     64,  // U+000CA8 - U+000CAF : 0x55555505
-    113,  // U+000CB0 - U+000CB7 : 0x55505555
-     76,  // U+000CB8 - U+000CBF : 0x11510055
-    115,  // U+000CC0 - U+000CC7 : 0x11011111
-    108,  // U+000CC8 - U+000CCF : 0x00111101
-    116,  // U+000CD0 - U+000CD7 : 0x01100000
-    120,  // U+000CD8 - U+000CDF : 0x05000000
-     81,  // U+000CE0 - U+000CE7 : 0x22001155
-      3,  // U+000CE8 - U+000CEF : 0x22222222
-    121,  // U+000CF0 - U+000CF7 : 0x00000550
-     29,  // U+000CF8 - U+000CFF : 0x00000000
-    119,  // U+000D00 - U+000D07 : 0x55501100
-    112,  // U+000D08 - U+000D0F : 0x55055555
-     64,  // U+000D10 - U+000D17 : 0x55555505
-      6,  // U+000D18 - U+000D1F : 0x55555555
-      6,  // U+000D20 - U+000D27 : 0x55555555
-      6,  // U+000D28 - U+000D2F : 0x55555555
-      6,  // U+000D30 - U+000D37 : 0x55555555
-    122,  // U+000D38 - U+000D3F : 0x11500555
-    115,  // U+000D40 - U+000D47 : 0x11011111
-    123,  // U+000D48 - U+000D4F : 0x05111101
-     79,  // U+000D50 - U+000D57 : 0x10000000
-     29,  // U+000D58 - U+000D5F : 0x00000000
-     81,  // U+000D60 - U+000D67 : 0x22001155
-      3,  // U+000D68 - U+000D6F : 0x22222222
-    124,  // U+000D70 - U+000D77 : 0x00222222
-    125,  // U+000D78 - U+000D7F : 0x55555570
-    119,  // U+000D80 - U+000D87 : 0x55501100
-      6,  // U+000D88 - U+000D8F : 0x55555555
-     31,  // U+000D90 - U+000D97 : 0x05555555
-    126,  // U+000D98 - U+000D9F : 0x55555500
-      6,  // U+000DA0 - U+000DA7 : 0x55555555
-      6,  // U+000DA8 - U+000DAF : 0x55555555
-     25,  // U+000DB0 - U+000DB7 : 0x55555055
-    127,  // U+000DB8 - U+000DBF : 0x00505555
-     31,  // U+000DC0 - U+000DC7 : 0x05555555
-    128,  // U+000DC8 - U+000DCF : 0x10000100
-    129,  // U+000DD0 - U+000DD7 : 0x01011111
-     20,  // U+000DD8 - U+000DDF : 0x11111111
-     29,  // U+000DE0 - U+000DE7 : 0x00000000
-     29,  // U+000DE8 - U+000DEF : 0x00000000
-    130,  // U+000DF0 - U+000DF7 : 0x00061100
-     29,  // U+000DF8 - U+000DFF : 0x00000000
-     30,  // U+000E00 - U+000E07 : 0x55555550
-      6,  // U+000E08 - U+000E0F : 0x55555555
-      6,  // U+000E10 - U+000E17 : 0x55555555
-      6,  // U+000E18 - U+000E1F : 0x55555555
-      6,  // U+000E20 - U+000E27 : 0x55555555
-      6,  // U+000E28 - U+000E2F : 0x55555555
-    131,  // U+000E30 - U+000E37 : 0x11115515
-    132,  // U+000E38 - U+000E3F : 0x70000111
-    133,  // U+000E40 - U+000E47 : 0x15555555
-    134,  // U+000E48 - U+000E4F : 0x61111111
-      3,  // U+000E50 - U+000E57 : 0x22222222
-    135,  // U+000E58 - U+000E5F : 0x00006622
-     29,  // U+000E60 - U+000E67 : 0x00000000
-     29,  // U+000E68 - U+000E6F : 0x00000000
-     29,  // U+000E70 - U+000E77 : 0x00000000
-     29,  // U+000E78 - U+000E7F : 0x00000000
-    136,  // U+000E80 - U+000E87 : 0x50050550
-    137,  // U+000E88 - U+000E8F : 0x00500505
-    138,  // U+000E90 - U+000E97 : 0x55550000
-     30,  // U+000E98 - U+000E9F : 0x55555550
-    139,  // U+000EA0 - U+000EA7 : 0x50505550
-    140,  // U+000EA8 - U+000EAF : 0x55505500
-    131,  // U+000EB0 - U+000EB7 : 0x11115515
-    141,  // U+000EB8 - U+000EBF : 0x00511011
-    142,  // U+000EC0 - U+000EC7 : 0x05055555
-    143,  // U+000EC8 - U+000ECF : 0x00111111
-      3,  // U+000ED0 - U+000ED7 : 0x22222222
-    144,  // U+000ED8 - U+000EDF : 0x55550022
-     29,  // U+000EE0 - U+000EE7 : 0x00000000
-     29,  // U+000EE8 - U+000EEF : 0x00000000
-     29,  // U+000EF0 - U+000EF7 : 0x00000000
-     29,  // U+000EF8 - U+000EFF : 0x00000000
-    145,  // U+000F00 - U+000F07 : 0x66667775