Merge from mozilla-central.
authorDavid Anderson <danderson@mozilla.com>
Fri, 24 Feb 2012 13:26:30 -0800
changeset 109482 1a9e91a88a5488d15b39a0530c326fdb1e1ce77b
parent 109481 d85d370124470821649071bcc537fdb96eeed133 (current diff)
parent 89141 58dd942011a81f3149d9bc34e808806bda099056 (diff)
child 109483 ebd61b600176d9fe2cfef187ae028515ee4f722a
push id2248
push userakeybl@mozilla.com
push dateMon, 08 Oct 2012 19:23:44 +0000
treeherdermozilla-aurora@118a3b748323 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone13.0a1
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
-     50,  // U+000F08 - U+000F0F : 0x66666666
-    146,  // U+000F10 - U+000F17 : 0x77767666
-    147,  // U+000F18 - U+000F1F : 0x77777711
-      3,  // U+000F20 - U+000F27 : 0x22222222
-      3,  // U+000F28 - U+000F2F : 0x22222222
-    148,  // U+000F30 - U+000F37 : 0x17172222
-    149,  // U+000F38 - U+000F3F : 0x11666617
-      6,  // U+000F40 - U+000F47 : 0x55555555
-     30,  // U+000F48 - U+000F4F : 0x55555550
-      6,  // U+000F50 - U+000F57 : 0x55555555
-      6,  // U+000F58 - U+000F5F : 0x55555555