Merge last green PGO from inbound to central
authorMarco Bonardo <mbonardo@mozilla.com>
Wed, 04 Apr 2012 13:36:36 +0200
changeset 94281 638769f8ec547d4e1f52164f0454db024e9511f0
parent 94222 6881fa89cfca09c19cdbe9085c1bf719fb824d86 (current diff)
parent 94280 f64f62213f61693a4f85e4c89a3191f83e388684 (diff)
child 94282 d9678c14dea97ff2a5aa2aa558219848dd02732e
child 94313 ba7f8495dd574a0d615898f15677d0cf1ddac663
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last green PGO from inbound to central
content/base/test/Makefile.in
dom/base/nsGlobalWindow.cpp
--- a/accessible/src/mac/mozTextAccessible.mm
+++ b/accessible/src/mac/mozTextAccessible.mm
@@ -325,39 +325,40 @@ ToNSString(id aValue)
 - (NSNumber*)caretLineNumber
 {
   PRInt32 lineNumber = mGeckoTextAccessible ?
     mGeckoTextAccessible->CaretLineNumber() - 1 : -1;
 
   return (lineNumber >= 0) ? [NSNumber numberWithInt:lineNumber] : nil;
 }
 
-- (void)setText:(NSString*)newString
+- (void)setText:(NSString*)aNewString
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
 
   if (mGeckoEditableTextAccessible) {
-    mGeckoEditableTextAccessible->SetTextContents(NS_ConvertUTF8toUTF16([newString UTF8String]));
+    nsString text;
+    nsCocoaUtils::GetStringForNSString(aNewString, text);
+    mGeckoEditableTextAccessible->SetTextContents(text);
   }
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 - (NSString*)text
 {
   if (!mGeckoTextAccessible)
     return nil;
     
   nsAutoString text;
-  nsresult rv = 
-    mGeckoTextAccessible->GetText(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT,
-				  text);
-  NS_ENSURE_SUCCESS(rv, nil);
+  nsresult rv = mGeckoTextAccessible->
+    GetText(0, nsIAccessibleText::TEXT_OFFSET_END_OF_TEXT, text);
+  NS_ENSURE_SUCCESS(rv, @"");
 
-  return text.IsEmpty() ? nil : nsCocoaUtils::ToNSString(text);
+  return nsCocoaUtils::ToNSString(text);
 }
 
 - (long)textLength
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
   return mGeckoTextAccessible ? mGeckoTextAccessible->CharacterCount() : 0;
 
@@ -387,17 +388,17 @@ ToNSString(id aValue)
 
   if (mGeckoTextAccessible) {
     PRInt32 start, end;
     start = end = 0;
     mGeckoTextAccessible->GetSelectionBounds(0, &start, &end);
     if (start != end) {
       nsAutoString selText;
       mGeckoTextAccessible->GetText(start, end, selText);
-      return selText.IsEmpty() ? nil : [NSString stringWithCharacters:selText.BeginReading() length:selText.Length()];
+      return nsCocoaUtils::ToNSString(selText);
     }
   }
   return nil;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 - (NSValue*)selectedTextRange
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -407,21 +407,16 @@ pref("browser.dom.window.dump.enabled", 
 // installable apps or wifi support.
 pref("security.fileuri.strict_origin_policy", false);
 
 // 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://homescreen.gaiamobile.org,http://settings.gaiamobile.org");
-
 // 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
 pref("browser.link.open_newwindow.restriction", 0);
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -280,33 +280,33 @@ var shell = {
 
 (function PowerManager() {
   // This will eventually be moved to content, so use content API as
   // much as possible here. TODO: Bug 738530
   let power = navigator.mozPower;
   let idleHandler = function idleHandler(subject, topic, time) {
     if (topic === "idle") {
       if (power.getWakeLockState("screen") != "locked-foreground") {
-        screen.mozEnabled = false;
+        navigator.mozPower.screenEnabled = false;
       }
     }
   }
   let wakeLockHandler = function wakeLockHandler(topic, state) {
     // Turn off the screen when no one needs the it or all of them are
     // invisible, otherwise turn the screen on. Note that the CPU
     // might go to sleep as soon as the screen is turned off and
     // acquiring wake lock will not bring it back (actually the code
     // is not executed at all).
     if (topic == "screen") {
       if (state != "locked-foreground") {
         if (Services.idle.idleTime > idleTimeout*1000) {
-          screen.mozEnabled = false;
+          navigator.mozPower.screenEnabled = false;
         }
       } else {
-        screen.mozEnabled = true;
+        navigator.mozPower.screenEnabled = true;
       }
     }
   }
   let idleTimeout = Services.prefs.getIntPref("power.screen.timeout");
   let request = navigator.mozSettings.getLock().get("power.screen.timeout");
   request.onsuccess = function onSuccess() {
     idleTimeout = request.result["power.screen.timeout"] || idleTimeout;
     if (idleTimeout) {
--- a/browser/components/privatebrowsing/test/browser/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/Makefile.in
@@ -51,16 +51,17 @@ include $(topsrcdir)/config/rules.mk
 		browser_privatebrowsing_commandline_toggle.js \
 		browser_privatebrowsing_crh.js \
 		browser_privatebrowsing_fastswitch.js \
 		browser_privatebrowsing_findbar.js \
 		browser_privatebrowsing_forgetthissite.js \
 		browser_privatebrowsing_geoprompt.js \
 		browser_privatebrowsing_geoprompt_page.html \
 		browser_privatebrowsing_import.js \
+		browser_privatebrowsing_lastpbcontextexited.js \
 		browser_privatebrowsing_localStorage.js \
 		browser_privatebrowsing_localStorage_page1.html \
 		browser_privatebrowsing_localStorage_page2.html \
 		browser_privatebrowsing_newwindow_stopcmd.js \
 		browser_privatebrowsing_opendir.js \
 		browser_privatebrowsing_openlocation.js \
 		browser_privatebrowsing_pageinfo.js \
 		browser_privatebrowsing_placestitle.js \
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_lastpbcontextexited.js
@@ -0,0 +1,66 @@
+/* ***** 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 Private Browsing Tests.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2012
+ * 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 ***** */
+
+function test() {
+  // We need to open a new window for this so that its docshell would get destroyed
+  // when clearing the PB mode flag.
+  let newWin = window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no");
+  waitForExplicitFinish();
+  SimpleTest.waitForFocus(function() {
+    let notificationCount = 0;
+    let observer = {
+      observe: function(aSubject, aTopic, aData) {
+        is(aTopic, "last-pb-context-exited", "Correct topic should be dispatched");
+        ++notificationCount;
+      }
+    };
+    Services.obs.addObserver(observer, "last-pb-context-exited", false);
+    newWin.gPrivateBrowsingUI.privateWindow = true;
+    SimpleTest.is(notificationCount, 0, "last-pb-context-exited should not be fired yet");
+    newWin.gPrivateBrowsingUI.privateWindow = false;
+    newWin.close();
+    newWin = null;
+    window.QueryInterface(Ci.nsIInterfaceRequestor)
+          .getInterface(Ci.nsIDOMWindowUtils)
+          .garbageCollect(); // Make sure that the docshell is destroyed
+    SimpleTest.is(notificationCount, 1, "last-pb-context-exited should be fired once");
+    Services.obs.removeObserver(observer, "last-pb-context-exited", false);
+
+    // cleanup
+    gPrefService.clearUserPref("browser.privatebrowsing.keep_current_session");
+    finish();
+  }, newWin);
+}
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -77,8 +77,54 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -
         fi
         rm -rf conftest*])
     if test "$GC_SECTIONS_BREAKS_DEBUG_RANGES" = no; then
         DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections"
     fi
 fi
 
 ])
+
+dnl GCC and clang will fail if given an unknown warning option like -Wfoobar. 
+dnl But later versions won't fail if given an unknown negated warning option
+dnl like -Wno-foobar.  So when we are check for support of negated warning 
+dnl options, we actually test the positive form, but add the negated form to 
+dnl the flags variable.
+
+AC_DEFUN([MOZ_C_SUPPORTS_WARNING],
+[
+    AC_CACHE_CHECK(whether the C compiler supports $1$2, $3,
+        [
+            AC_LANG_SAVE
+            AC_LANG_C
+            _SAVE_CFLAGS="$CFLAGS"
+            CFLAGS="$CFLAGS -Werror -W$2"
+            AC_TRY_COMPILE([],
+                           [return(0);],
+                           $3="yes",
+                           $3="no")
+            CFLAGS="$_SAVE_CFLAGS"
+            AC_LANG_RESTORE
+        ])
+    if test "${$3}" = "yes"; then
+        _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} $1$2"
+    fi
+])
+
+AC_DEFUN([MOZ_CXX_SUPPORTS_WARNING],
+[
+    AC_CACHE_CHECK(whether the C++ compiler supports $1$2, $3,
+        [
+            AC_LANG_SAVE
+            AC_LANG_CPLUSPLUS
+            _SAVE_CXXFLAGS="$CXXFLAGS"
+            CXXFLAGS="$CXXFLAGS -Werror -W$2"
+            AC_TRY_COMPILE([],
+                           [return(0);],
+                           $3="yes",
+                           $3="no")
+            CXXFLAGS="$_SAVE_CXXFLAGS"
+            AC_LANG_RESTORE
+        ])
+    if test "${$3}" = "yes"; then
+        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} $1$2"
+    fi
+])
--- a/build/mobile/devicemanagerSUT.py
+++ b/build/mobile/devicemanagerSUT.py
@@ -194,40 +194,42 @@ class DeviceManagerSUT(DeviceManager):
     shouldCloseSocket = False
     recvGuard = 1000
 
     if not self._sock:
       try:
         if self.debug >= 1:
           print "reconnecting socket"
         self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-      except:
+      except socket.error, msg:
         self._sock = None
-        raise AgentError("unable to create socket")
+        raise AgentError("unable to create socket: "+str(msg))
 
       try:
         self._sock.connect((self.host, int(self.port)))
         self._sock.recv(1024)
-      except:
+      except socket.error, msg:
         self._sock.close()
         self._sock = None
-        raise AgentError("unable to connect socket")
+        raise AgentError("unable to connect socket: "+str(msg))
 
     for cmd in cmdlist:
       if newline: cmd += '\r\n'
 
       try:
         numbytes = self._sock.send(cmd)
         if (numbytes != len(cmd)):
           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:
+      except socket.error, msg:
         self._sock.close()
         self._sock = None
+        if self.debug >= 1:
+          print "Error sending data to socket. cmd="+str(cmd)+"; err="+str(msg)
         return False
 
       # Check if the command should close the socket
       shouldCloseSocket = self._shouldCmdCloseSocket(cmd)
 
       # Handle responses from commands
       if (self._cmdNeedsResponse(cmd)):
         found = False
@@ -237,20 +239,20 @@ class DeviceManagerSUT(DeviceManager):
         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:
+          except socket.error, msg:
             self._sock.close()
             self._sock = None
-            raise AgentError("Error receiving data from socket")
+            raise AgentError("Error receiving data from socket. cmd="+str(cmd)+"; err="+str(msg))
 
           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):
             raise AgentError("Agent Error processing command: %s" % cmd, fatal=True)
 
--- a/configure.in
+++ b/configure.in
@@ -1702,46 +1702,55 @@ if test "$GNU_CC"; then
     fi
     WARNINGS_AS_ERRORS='-Werror -Wno-error=uninitialized'
     DSO_CFLAGS=''
     DSO_PIC_CFLAGS='-fPIC'
     ASFLAGS="$ASFLAGS -fPIC"
     _MOZ_RTTI_FLAGS_ON=-frtti
     _MOZ_RTTI_FLAGS_OFF=-fno-rtti
 
-    # Turn on GNU specific features
-    # -Wall - turn on all warnings
-    # -pedantic - make compiler warn about non-ANSI stuff, and
-    #             be a little bit stricter
+    # Turn on GNU-specific warnings:
+    # -Wall - turn on a lot of warnings
+    # -pedantic - this is turned on below
+    # -Wpointer-arith - enabled with -pedantic, but good to have even if not
     # -Wdeclaration-after-statement - MSVC doesn't like these
-    # Warnings slamm took out for now (these were giving more noise than help):
-    # -Wbad-function-cast - warns when casting a function to a new return type
-    # -Wshadow - removed because it generates more noise than help --pete
-    _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -W -Wno-unused -Wpointer-arith -Wdeclaration-after-statement"
+    # -Werror=return-type - catches missing returns, zero false positives
+    # -Wtype-limits - catches overflow bugs, few false positives
+    # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
+    #
+    _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement"
+    MOZ_C_SUPPORTS_WARNING(-W, error=return-type, ac_c_has_werror_return_type)
+    MOZ_C_SUPPORTS_WARNING(-W, type-limits, ac_c_has_wtype_limits)
+    MOZ_C_SUPPORTS_WARNING(-W, empty-body, ac_c_has_wempty_body)
+    
+    # Turn off the following warnings that -Wall/-pedantic turn on:
+    # -Wno-unused - lots of violations in third-party code
+    # -Wno-overlength-strings - we exceed the minimum maximum length frequently
+    #
+    _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wno-unused"
+    MOZ_C_SUPPORTS_WARNING(-Wno-, overlength-strings, ac_c_has_wno_overlength_strings)
+
     if test -z "$INTEL_CC" -a -z "$CLANG_CC"; then
        # Don't use -Wcast-align with ICC or clang
        case "$CPU_ARCH" in
            # And don't use it on hppa, ia64, sparc, arm, since it's noisy there
            hppa | ia64 | sparc | arm)
            ;;
            *)
         _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wcast-align"
            ;;
        esac
     fi
 
     dnl Turn pedantic on but disable the warnings for long long
     _PEDANTIC=1
 
-    if test -z "$INTEL_CC"; then
-      _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -W"
-    fi
-
     _DEFINES_CFLAGS='-include $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT'
     _USE_CPP_INCLUDE_FLAG=1
+
 elif test "$SOLARIS_SUNPRO_CC"; then
     DSO_CFLAGS=''
     if test "$CPU_ARCH" = "sparc"; then
         # for Sun Studio on Solaris/SPARC
         DSO_PIC_CFLAGS='-xcode=pic32'
     else
         DSO_PIC_CFLAGS='-KPIC'
     fi
@@ -1759,18 +1768,42 @@ else
     DSO_CFLAGS=''
     DSO_PIC_CFLAGS='-KPIC'
     _DEFINES_CFLAGS='$(ACDEFINES) -D_MOZILLA_CONFIG_H_ -DMOZILLA_CLIENT'
 fi
 
 if test "$GNU_CXX"; then
     # FIXME: Let us build with strict aliasing. bug 414641.
     CXXFLAGS="$CXXFLAGS -fno-exceptions -fno-strict-aliasing"
-    # Turn on GNU specific features
-    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor"
+
+    # Turn on GNU-specific warnings:
+    # -Wall - turn on a lot of warnings
+    # -pedantic - this is turned on below
+    # -Wpointer-arith - enabled with -pedantic, but good to have even if not
+    # -Woverloaded-virtual - ???
+    # -Werror=return-type - catches missing returns, zero false positives
+    # -Wtype-limits - catches overflow bugs, few false positives
+    # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
+    #
+    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual"
+    MOZ_CXX_SUPPORTS_WARNING(-W, error=return-type, ac_cxx_has_werror_return_type)
+    MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits)
+    MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body)
+
+    # Turn off the following warnings that -Wall/-pedantic turn on:
+    # -Wno-ctor-dtor-privacy - ???
+    # -Wno-overlength-strings - we exceed the minimum maximum length frequently 
+    # -Wno-invalid-offsetof - we use offsetof on non-POD types frequently
+    # -Wno-variadic-macros - ???
+    #
+    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-ctor-dtor-privacy"
+    MOZ_CXX_SUPPORTS_WARNING(-Wno-, overlength-strings, ac_cxx_has_wno_overlength_strings)
+    MOZ_CXX_SUPPORTS_WARNING(-Wno-, invalid-offsetof, ac_cxx_has_wno_invalid_offsetof)
+    MOZ_CXX_SUPPORTS_WARNING(-Wno-, variadic-macros, ac_cxx_has_wno_variadic_macros)
+
     if test -z "$INTEL_CXX" -a -z "$CLANG_CXX"; then
        # Don't use -Wcast-align with ICC or clang
        case "$CPU_ARCH" in
            # And don't use it on hppa, ia64, sparc, arm, since it's noisy there
            hppa | ia64 | sparc | arm)
            ;;
            *)
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wcast-align"
@@ -1784,91 +1817,17 @@ if test "$GNU_CXX"; then
     # Recent clang and gcc support C++11 deleted functions without warnings if
     # compiling with -std=c++0x or -std=gnu++0x (or c++11 or gnu++11 in very new
     # versions).  We can't use -std=c++0x yet, so gcc's support must remain
     # unused.  But clang's warning can be disabled, so when compiling with clang
     # we use it to opt out of the warning, enabling (macro-encapsulated) use of
     # deleted function syntax.
     if test "$CLANG_CXX"; then
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-c++0x-extensions"
-    fi
-
-    AC_CACHE_CHECK(whether the compiler supports -Wno-extended-offsetof,
-                   ac_has_wno_extended_offsetof,
-        [
-            AC_LANG_SAVE
-            AC_LANG_CPLUSPLUS
-            _SAVE_CXXFLAGS="$CXXFLAGS"
-            CXXFLAGS="$CXXFLAGS -Wno-extended-offsetof"
-            AC_TRY_COMPILE([$configure_static_assert_macros
-                            #ifndef __has_warning
-                            #define __has_warning(x) 0
-                            #endif],
-                           [CONFIGURE_STATIC_ASSERT(__has_warning("-Wextended-offsetof"))],
-                           ac_has_wno_extended_offsetof="yes",
-                           ac_has_wno_extended_offsetof="no")
-            CXXFLAGS="$_SAVE_CXXFLAGS"
-            AC_LANG_RESTORE
-        ])
-    if test "$ac_has_wno_extended_offsetof" = "yes"; then
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-extended-offsetof"
-    fi
-
-    AC_CACHE_CHECK(whether the compiler supports -Wno-invalid-offsetof,
-                   ac_has_wno_invalid_offsetof,
-        [
-            AC_LANG_SAVE
-            AC_LANG_CPLUSPLUS
-            _SAVE_CXXFLAGS="$CXXFLAGS"
-            CXXFLAGS="$CXXFLAGS -Wno-invalid-offsetof"
-            AC_TRY_COMPILE([],
-                           [return(0);],
-                           ac_has_wno_invalid_offsetof="yes",
-                           ac_has_wno_invalid_offsetof="no")
-            CXXFLAGS="$_SAVE_CXXFLAGS"
-            AC_LANG_RESTORE
-        ])
-    if test "$ac_has_wno_invalid_offsetof" = "yes"; then
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-invalid-offsetof"
-    fi
-
-    AC_CACHE_CHECK(whether the compiler supports -Wno-variadic-macros,
-                   ac_has_wno_variadic_macros,
-        [
-            AC_LANG_SAVE
-            AC_LANG_CPLUSPLUS
-            _SAVE_CXXFLAGS="$CXXFLAGS"
-            CXXFLAGS="$CXXFLAGS -Wno-variadic-macros"
-            AC_TRY_COMPILE([],
-                           [return(0);],
-                           ac_has_wno_variadic_macros="yes",
-                           ac_has_wno_variadic_macros="no")
-            CXXFLAGS="$_SAVE_CXXFLAGS"
-            AC_LANG_RESTORE
-        ])
-    if test "$ac_has_wno_variadic_macros" = "yes"; then
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-variadic-macros"
-    fi
-
-    AC_CACHE_CHECK(whether the compiler supports -Werror=return-type,
-                   ac_has_werror_return_type,
-        [
-            AC_LANG_SAVE
-            AC_LANG_CPLUSPLUS
-            _SAVE_CXXFLAGS="$CXXFLAGS"
-            CXXFLAGS="$CXXFLAGS -Werror=return-type"
-            AC_TRY_COMPILE([],
-                           [return(0);],
-                           ac_has_werror_return_type="yes",
-                           ac_has_werror_return_type="no")
-            CXXFLAGS="$_SAVE_CXXFLAGS"
-            AC_LANG_RESTORE
-        ])
-    if test "$ac_has_werror_return_type" = "yes"; then
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=return-type"
+        MOZ_CXX_SUPPORTS_WARNING(-Wno-, extended-offsetof, ac_cxx_has_wno_extended_offsetof)
     fi
 
 else
     _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_MOZILLA_CONFIG_H_ $(ACDEFINES)'
 fi
 
 dnl gcc can come with its own linker so it is better to use the pass-thru calls
 dnl MKSHLIB_FORCE_ALL is used to force the linker to include all object
--- a/content/base/src/nsScriptElement.cpp
+++ b/content/base/src/nsScriptElement.cpp
@@ -56,34 +56,21 @@ nsScriptElement::ScriptAvailable(nsresul
                                  bool aIsInline,
                                  nsIURI *aURI,
                                  PRInt32 aLineNo)
 {
   if (!aIsInline && NS_FAILED(aResult)) {
     nsCOMPtr<nsIContent> cont =
       do_QueryInterface((nsIScriptElement*) this);
 
-    nsRefPtr<nsPresContext> presContext =
-      nsContentUtils::GetContextForContent(cont);
-
-    nsEventStatus status = nsEventStatus_eIgnore;
-    nsScriptErrorEvent event(true, NS_LOAD_ERROR);
-
-    event.lineNr = aLineNo;
-
-    NS_NAMED_LITERAL_STRING(errorString, "Error loading script");
-    event.errorMsg = errorString.get();
-
-    nsCAutoString spec;
-    aURI->GetSpec(spec);
-
-    NS_ConvertUTF8toUTF16 fileName(spec);
-    event.fileName = fileName.get();
-
-    nsEventDispatcher::Dispatch(cont, presContext, &event, nsnull, &status);
+    return nsContentUtils::DispatchTrustedEvent(cont->OwnerDoc(),
+                                                cont,
+                                                NS_LITERAL_STRING("error"),
+                                                false /* bubbles */,
+                                                false /* cancelable */);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScriptElement::ScriptEvaluated(nsresult aResult,
                                  nsIScriptElement *aElement,
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -571,16 +571,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug366944.html \
 		test_bug650386_redirect_301.html \
 		test_bug650386_redirect_302.html \
 		test_bug650386_redirect_303.html \
 		test_bug650386_redirect_307.html \
 		file_bug650386_content.sjs \
 		file_bug650386_report.sjs \
 		test_bug719533.html \
+		test_bug737087.html \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
--- a/content/base/test/test_blobconstructor.html
+++ b/content/base/test/test_blobconstructor.html
@@ -58,16 +58,32 @@ ok(true, "a null options member should t
 
 try {
 blob = Blob([], undefined);
 ok(false, "NOT REACHED");
 } catch(e) {
 ok(true, "an undefined options member should throw");
 }
 
+/** Test for dictionary initialization order **/
+(function() {
+  var o = {};
+  var p = {type: "text/plain", endings: "transparent"};
+  var called = [];
+  function add_to_called(n) {
+    called.push(n);
+    return p[n];
+  }
+  ["type", "endings"].forEach(function(n) {
+    Object.defineProperty(o, n, { get: add_to_called.bind(null, n) });
+  });
+  var b = new Blob([], o);
+  is(JSON.stringify(called), JSON.stringify(["endings", "type"]), "dictionary members should be get in lexicographical order");
+})();
+
 let blob1 = Blob(["squiggle"]);
 ok(blob1 instanceof Blob, "Blob constructor should produce Blobs");
 ok(!(blob1 instanceof File), "Blob constructor should not produce Files");
 is(blob1.type, "", "Blob constructor with no options should return Blob with empty type");
 is(blob1.size, 8, "Blob constructor should return Blob with correct size");
 
 let blob2 = Blob(["steak"], {type: "content/type"});
 ok(blob2 instanceof Blob, "Blob constructor should produce Blobs");
--- a/content/base/test/test_bug696301-1.html
+++ b/content/base/test/test_bug696301-1.html
@@ -51,24 +51,24 @@ window.onerror = function(message, uri, 
 <script>
   is(errorFired, true, "Should have error in different origin script with CORS");
   is(global, "ran", "Different origin script with CORS should have run");
 </script>
 
 <script type="application/javascript">
 errorFired = false;
 global = "";
-window.onerror = function(message, uri, line) {
-  is(message, "Error loading script", "Should have correct error message");
-  is(uri,
-     "http://example.com/tests/content/base/test/bug696301-script-2.js",
-     "Should still have correct script URI even when failing CORS");
-  is(line, 1, "Load failures seem to count as line 1");
+window.addEventListener("error", function(e) {
+  is(Object.getPrototypeOf(e), Event.prototype,
+     "Object prototype should be Event");
+  var externalScripts = document.querySelectorAll("script[src]");
+  is(e.target, externalScripts[externalScripts.length - 1],
+     "Event's target should be the right <script>");
   errorFired = true;
-}
+}, true);
 </script>
 <script src="http://example.com/tests/content/base/test/bug696301-script-2.js"
         crossorigin></script>
 <script>
   is(errorFired, true,
      "Should have error when different origin script fails CORS check");
   is(global, "", "Different origin script that fails CORS should not have run");
 </script>
--- a/content/base/test/test_bug696301-2.html
+++ b/content/base/test/test_bug696301-2.html
@@ -53,24 +53,24 @@ window.onerror = function(message, uri, 
 <script>
   is(errorFired, true, "Should have error in different origin script with CORS");
   is(global, "ran", "Different origin script with CORS should have run");
 </script>
 
 <script type="application/javascript">
 errorFired = false;
 global = "";
-window.onerror = function(message, uri, line) {
-  is(message, "Error loading script", "Should have correct error message");
-  is(uri,
-     "http://example.com/tests/content/base/test/bug696301-script-2.js",
-     "Should still have correct script URI even when failing CORS");
-  is(line, 1, "Load failures seem to count as line 1");
+window.addEventListener("error", function(e) {
+  is(Object.getPrototypeOf(e), Event.prototype,
+     "Object prototype should be Event");
+  var scripts = document.querySelectorAll("script");
+  is(e.target, scripts[scripts.length - 1],
+     "Event's target should be the right &lt;script>");
   errorFired = true;
-}
+}, true);
 </script>
 <script xlink:href="http://example.com/tests/content/base/test/bug696301-script-2.js"
         crossorigin></script>
 <script>
   is(errorFired, true,
      "Should have error when different origin script fails CORS check");
   is(global, "", "Different origin script that fails CORS should not have run");
 </script>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug737087.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=737087
+-->
+<title>Test for Bug 737087</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=737087">Mozilla Bug 737087</a>
+<script>
+
+/** Test for Bug 737087 **/
+SimpleTest.waitForExplicitFinish();
+
+var bubbled = false;
+var capturedEvent = null;
+var inlineFiredEvent = null;
+
+addEventListener("error", function() { bubbled = true });
+addEventListener("error", function(e) {
+  capturedEvent = e;
+  is(typeof e, "object", "Error event must be object");
+  is(Object.getPrototypeOf(e), Event.prototype, "Error event must be Event");
+  is(e.bubbles, false, "e.bubbles must be false");
+  is(e.cancelable, false, "e.cancelable must be false");
+}, true);
+
+addLoadEvent(function() {
+  is(bubbled, false, "Error event must not bubble");
+  isnot(capturedEvent, null, "Error event must be captured");
+  isnot(inlineFiredEvent, null, "Inline error handler must fire");
+  is(capturedEvent, inlineFiredEvent,
+     "Same event must be handled by both handlers");
+  SimpleTest.finish();
+});
+</script>
+<script src=nonexistent
+  onerror="inlineFiredEvent = event"></script>
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -122,19 +122,20 @@ struct WebGLTexelFormat {
 };
 
 struct WebGLTexelPremultiplicationOp {
     enum { Generic, None, Premultiply, Unmultiply };
 };
 
 int GetWebGLTexelFormat(GLenum format, GLenum type);
 
+// Zero is not an integer power of two.
 inline bool is_pot_assuming_nonnegative(WebGLsizei x)
 {
-    return (x & (x-1)) == 0;
+    return x && (x & (x-1)) == 0;
 }
 
 /* Each WebGL object class WebGLFoo wants to:
  *  - inherit WebGLRefCountedObject<WebGLFoo>
  *  - implement a Delete() method
  *  - have its destructor call DeleteOnce()
  * 
  * This base class provides two features to WebGL object types:
@@ -580,16 +581,17 @@ public:
     nsresult ErrorInvalidValue(const char *fmt = 0, ...);
     nsresult ErrorInvalidFramebufferOperation(const char *fmt = 0, ...);
     nsresult ErrorInvalidEnumInfo(const char *info, PRUint32 enumvalue) {
         return ErrorInvalidEnum("%s: invalid enum value 0x%x", info, enumvalue);
     }
     nsresult ErrorOutOfMemory(const char *fmt = 0, ...);
 
     const char *ErrorName(GLenum error);
+    bool IsTextureFormatCompressed(GLenum format);
 
     nsresult DummyFramebufferOperation(const char *info);
 
     WebGLTexture *activeBoundTextureForTarget(WebGLenum target) {
         return target == LOCAL_GL_TEXTURE_2D ? mBound2DTextures[mActiveTexture]
                                              : mBoundCubeMapTextures[mActiveTexture];
     }
 
@@ -1242,24 +1244,36 @@ protected:
 
     // we store information about the various images that are part of
     // this texture (cubemap faces, mipmap levels)
 
 public:
 
     class ImageInfo : public WebGLRectangleObject {
     public:
-        ImageInfo() : mFormat(0), mType(0), mIsDefined(false) {}
+        ImageInfo()
+            : mFormat(0)
+            , mType(0)
+            , mIsDefined(false)
+        {}
+
         ImageInfo(WebGLsizei width, WebGLsizei height,
                   WebGLenum format, WebGLenum type)
-            : WebGLRectangleObject(width, height), mFormat(format), mType(type), mIsDefined(true) {}
+            : WebGLRectangleObject(width, height)
+            , mFormat(format)
+            , mType(type)
+            , mIsDefined(true)
+        {}
 
         bool operator==(const ImageInfo& a) const {
-            return mWidth == a.mWidth && mHeight == a.mHeight &&
-                   mFormat == a.mFormat && mType == a.mType;
+            return mIsDefined == a.mIsDefined &&
+                   mWidth     == a.mWidth &&
+                   mHeight    == a.mHeight &&
+                   mFormat    == a.mFormat &&
+                   mType      == a.mType;
         }
         bool operator!=(const ImageInfo& a) const {
             return !(*this == a);
         }
         bool IsSquare() const {
             return mWidth == mHeight;
         }
         bool IsPositive() const {
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -1906,25 +1906,30 @@ WebGLContext::GenerateMipmap(WebGLenum t
         return NS_OK;
 
     if (!ValidateTextureTargetEnum(target, "generateMipmap"))
         return NS_OK;
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
 
     if (!tex)
-        return ErrorInvalidOperation("generateMipmap: no texture is bound to this target");
-
-    if (!tex->IsFirstImagePowerOfTwo()) {
-        return ErrorInvalidOperation("generateMipmap: the width or height of this texture is not a power of two");
-    }
-
-    if (!tex->AreAllLevel0ImageInfosEqual()) {
-        return ErrorInvalidOperation("generateMipmap: the six faces of this cube map have different dimensions, format, or type.");
-    }
+        return ErrorInvalidOperation("generateMipmap: No texture is bound to this target.");
+
+    if (!tex->HasImageInfoAt(0, 0))
+        return ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
+
+    if (!tex->IsFirstImagePowerOfTwo())
+        return ErrorInvalidOperation("generateMipmap: Level zero of texture does not have power-of-two width and height.");
+
+    GLenum format = tex->ImageInfoAt(0, 0).Format();
+    if (IsTextureFormatCompressed(format))
+        return ErrorInvalidOperation("generateMipmap: Texture data at level zero is compressed.");
+
+    if (!tex->AreAllLevel0ImageInfosEqual())
+        return ErrorInvalidOperation("generateMipmap: The six faces of this cube map have different dimensions, format, or type.");
 
     tex->SetGeneratedMipmap();
 
     MakeContextCurrent();
     gl->fGenerateMipmap(target);
     return NS_OK;
 }
 
--- a/content/canvas/src/WebGLContextUtils.cpp
+++ b/content/canvas/src/WebGLContextUtils.cpp
@@ -234,9 +234,32 @@ WebGLContext::ErrorName(GLenum error)
         case LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION:
             return "INVALID_FRAMEBUFFER_OPERATION";
         case LOCAL_GL_NO_ERROR:
             return "NO_ERROR";
         default:
             NS_ABORT();
             return "[unknown WebGL error!]";
     }
-};
+}
+
+bool
+WebGLContext::IsTextureFormatCompressed(GLenum format)
+{
+    switch(format) {
+        case LOCAL_GL_RGB:
+        case LOCAL_GL_RGBA:
+        case LOCAL_GL_ALPHA:
+        case LOCAL_GL_LUMINANCE:
+        case LOCAL_GL_LUMINANCE_ALPHA:
+            return false;
+
+        case LOCAL_GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+        case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+        case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+        case LOCAL_GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+            return true;
+    }
+
+    NS_NOTREACHED("Invalid WebGL texture format?");
+    NS_ABORT();
+    return false;
+}
new file mode 100644
--- /dev/null
+++ b/content/html/content/crashtests/741250.xhtml
@@ -0,0 +1,9 @@
+<input form="f" id="x" xmlns="http://www.w3.org/1999/xhtml">
+<form id="f"></form>
+<script>
+window.addEventListener("load", function() {
+  var x = document.getElementById("x");
+  x.appendChild(x.cloneNode(true));
+}, false);
+</script>
+</input>
--- a/content/html/content/crashtests/crashtests.list
+++ b/content/html/content/crashtests/crashtests.list
@@ -29,8 +29,9 @@ load 614279.html
 load 614988-1.html
 load 620078-1.html
 load 620078-2.html
 load 680922-1.xul
 load 682058.xhtml
 load 682460.html
 load 673853.html
 load 738744.xhtml
+load 741250.xhtml
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -2361,17 +2361,20 @@ nsFormControlList::AddElementToTable(nsG
       if (content == aChild) {
         return NS_OK;
       }
 
       // Found an element, create a list, add the element to the list and put
       // the list in the hash
       nsSimpleContentList *list = new nsSimpleContentList(mForm);
 
-      NS_ASSERTION(content->GetParent(), "Item in list without parent");
+      // If an element has a @form, we can assume it *might* be able to not have
+      // a parent and still be in the form.
+      NS_ASSERTION(content->HasAttr(kNameSpaceID_None, nsGkAtoms::form) ||
+                   content->GetParent(), "Item in list without parent");
 
       // Determine the ordering between the new and old element.
       bool newFirst = nsContentUtils::PositionIsBefore(aChild, content);
 
       list->AppendElement(newFirst ? aChild : content);
       list->AppendElement(newFirst ? content : aChild);
 
 
--- a/content/html/content/test/test_bug408231.html
+++ b/content/html/content/test/test_bug408231.html
@@ -85,17 +85,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       ["justifyleft", "true"],
       ["justifyright", "false"],
       ["outdent", "exception"],
       //["paste", "exception"],
       ["redo", "exception"],
       ["removeformat", "exception"],
       ["selectall", "exception"],
       ["strikethrough", "false"],
-      ["styleWithCSS", "exception"],
+      ["styleWithCSS", "false"],
       ["subscript", "false"],
       ["superscript", "false"],
       ["underline", "false"],
       ["undo", "exception"],
       ["unlink", "false"],
       ["not-a-command", "exception"]
     ];
     
@@ -125,17 +125,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       ["justifyleft", "left"],
       ["justifyright", "left"],
       ["outdent", ""],
       //["paste", ""],
       ["redo", ""],
       ["removeformat", ""],
       ["selectall", ""],
       ["strikethrough", ""],
-      ["styleWithCSS", "exception"],
+      ["styleWithCSS", ""],
       ["subscript", ""],
       ["superscript", ""],
       ["underline", ""],
       ["undo", ""],
       ["unlink", ""],
       ["not-a-command", "exception"],
     ];
     
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -3228,16 +3228,23 @@ nsHTMLDocument::QueryCommandState(const 
   GetMidasCommandManager(getter_AddRefs(cmdMgr));
   if (!cmdMgr)
     return NS_ERROR_FAILURE;
 
   nsIDOMWindow *window = GetWindow();
   if (!window)
     return NS_ERROR_FAILURE;
 
+  if (commandID.LowerCaseEqualsLiteral("usecss")) {
+    // Per spec, state is supported for styleWithCSS but not useCSS, so we just
+    // return false always.
+    *_retval = false;
+    return NS_OK;
+  }
+
   nsCAutoString cmdToDispatch, paramToCheck;
   bool dummy, dummy2;
   if (!ConvertToMidasInternalCommand(commandID, commandID,
                                      cmdToDispatch, paramToCheck, dummy, dummy2))
     return NS_ERROR_NOT_IMPLEMENTED;
 
   nsresult rv;
   nsCOMPtr<nsICommandParams> cmdParams = do_CreateInstance(
--- a/content/smil/nsSMILAnimationFunction.cpp
+++ b/content/smil/nsSMILAnimationFunction.cpp
@@ -666,17 +666,17 @@ nsSMILAnimationFunction::ScaleSimpleProg
     return aProgress;
 
   PRUint32 numTimes = mKeyTimes.Length();
 
   if (numTimes < 2)
     return aProgress;
 
   PRUint32 i = 0;
-  for (; i < numTimes - 2 && aProgress >= mKeyTimes[i+1]; ++i);
+  for (; i < numTimes - 2 && aProgress >= mKeyTimes[i+1]; ++i) { }
 
   if (aCalcMode == CALC_DISCRETE) {
     // discrete calcMode behaviour differs in that each keyTime defines the time
     // from when the corresponding value is set, and therefore the last value
     // needn't be 1. So check if we're in the last 'interval', that is, the
     // space between the final value and 1.0.
     if (aProgress >= mKeyTimes[i+1]) {
       NS_ABORT_IF_FALSE(i == numTimes - 2,
--- a/content/smil/nsSMILTimedElement.cpp
+++ b/content/smil/nsSMILTimedElement.cpp
@@ -1762,17 +1762,17 @@ nsSMILTimedElement::GetNextInterval(cons
 
 nsSMILInstanceTime*
 nsSMILTimedElement::GetNextGreater(const InstanceTimeList& aList,
                                    const nsSMILTimeValue& aBase,
                                    PRInt32& aPosition) const
 {
   nsSMILInstanceTime* result = nsnull;
   while ((result = GetNextGreaterOrEqual(aList, aBase, aPosition)) &&
-         result->Time() == aBase);
+         result->Time() == aBase) { }
   return result;
 }
 
 nsSMILInstanceTime*
 nsSMILTimedElement::GetNextGreaterOrEqual(const InstanceTimeList& aList,
                                           const nsSMILTimeValue& aBase,
                                           PRInt32& aPosition) const
 {
--- a/content/xslt/src/base/txExpandedNameMap.h
+++ b/content/xslt/src/base/txExpandedNameMap.h
@@ -97,28 +97,26 @@ protected:
 
         bool next()
         {
             return ++mCurrentPos < mMap.mItems.Length();
         }
 
         const txExpandedName key()
         {
-            NS_ASSERTION(mCurrentPos >= 0 &&
-                         mCurrentPos < mMap.mItems.Length(),
+            NS_ASSERTION(mCurrentPos < mMap.mItems.Length(),
                          "invalid position in txExpandedNameMap::iterator");
             return txExpandedName(mMap.mItems[mCurrentPos].mNamespaceID,
                                   mMap.mItems[mCurrentPos].mLocalName);
         }
 
     protected:
         void* itemValue()
         {
-            NS_ASSERTION(mCurrentPos >= 0 &&
-                         mCurrentPos < mMap.mItems.Length(),
+            NS_ASSERTION(mCurrentPos < mMap.mItems.Length(),
                          "invalid position in txExpandedNameMap::iterator");
             return mMap.mItems[mCurrentPos].mValue;
         }
 
     private:
         txExpandedNameMap_base& mMap;
         PRUint32 mCurrentPos;
     };
--- a/content/xul/templates/src/nsXULTemplateBuilder.cpp
+++ b/content/xul/templates/src/nsXULTemplateBuilder.cpp
@@ -213,38 +213,48 @@ nsXULTemplateBuilder::InitGlobals()
 
     if (!mMatchMap.IsInitialized() && !mMatchMap.Init())
         return NS_ERROR_OUT_OF_MEMORY;
 
     const size_t bucketsizes[] = { sizeof(nsTemplateMatch) };
     return mPool.Init("nsXULTemplateBuilder", bucketsizes, 1, 256);
 }
 
+void
+nsXULTemplateBuilder::CleanUp(bool aIsFinal)
+{
+    for (PRInt32 q = mQuerySets.Length() - 1; q >= 0; q--) {
+        nsTemplateQuerySet* qs = mQuerySets[q];
+        delete qs;
+    }
+
+    mQuerySets.Clear();
+
+    mMatchMap.Enumerate(DestroyMatchList, &mPool);
+
+    // Setting mQueryProcessor to null will close connections. This would be
+    // handled by the cycle collector, but we want to close them earlier.
+    if (aIsFinal)
+        mQueryProcessor = nsnull;
+}
 
 void
 nsXULTemplateBuilder::Uninit(bool aIsFinal)
 {
     if (mObservedDocument && aIsFinal) {
         gObserverService->RemoveObserver(this, DOM_WINDOW_DESTROYED_TOPIC);
         gObserverService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
         mObservedDocument->RemoveObserver(this);
         mObservedDocument = nsnull;
     }
 
     if (mQueryProcessor)
         mQueryProcessor->Done();
 
-    for (PRInt32 q = mQuerySets.Length() - 1; q >= 0; q--) {
-        nsTemplateQuerySet* qs = mQuerySets[q];
-        delete qs;
-    }
-
-    mQuerySets.Clear();
-
-    mMatchMap.Enumerate(DestroyMatchList, &mPool);
+    CleanUp(aIsFinal);
 
     mRootResult = nsnull;
     mRefVariable = nsnull;
     mMemberVariable = nsnull;
 
     mQueriesCompiled = false;
 }
 
@@ -1183,16 +1193,18 @@ nsXULTemplateBuilder::ContentRemoved(nsI
             xuldoc->SetTemplateBuilderFor(mRoot, nsnull);
 
         // clear the template state when removing content so that template
         // content will be regenerated again if the content is reinserted
         nsXULElement *xulcontent = nsXULElement::FromContent(mRoot);
         if (xulcontent)
             xulcontent->ClearTemplateGenerated();
 
+        CleanUp(true);
+
         mDB = nsnull;
         mCompDB = nsnull;
         mDataSource = nsnull;
     }
 }
 
 void
 nsXULTemplateBuilder::NodeWillBeDestroyed(const nsINode* aNode)
--- a/content/xul/templates/src/nsXULTemplateBuilder.h
+++ b/content/xul/templates/src/nsXULTemplateBuilder.h
@@ -76,16 +76,18 @@ class nsIObserverService;
 /**
  * An object that translates an RDF graph into a presentation using a
  * set of rules.
  */
 class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
                              public nsIObserver,
                              public nsStubDocumentObserver
 {
+    void CleanUp(bool aIsFinal);
+
 public:
     nsXULTemplateBuilder();
     virtual ~nsXULTemplateBuilder();
 
     nsresult InitGlobals();
 
     /**
      * Clear the template builder structures. The aIsFinal flag is set to true
--- a/content/xul/templates/src/nsXULTreeBuilder.cpp
+++ b/content/xul/templates/src/nsXULTreeBuilder.cpp
@@ -1914,16 +1914,19 @@ nsXULTreeBuilder::CompareResults(nsIXULT
                 }
 
                 return lindex - rindex;
             }
         }
     }
 
     PRInt32 sortorder;
+    if (!mQueryProcessor)
+        return 0;
+
     mQueryProcessor->CompareResults(aLeft, aRight, mSortVariable, mSortHints, &sortorder);
 
     if (sortorder)
         sortorder = sortorder * mSortDirection;
     return sortorder;
 }
 
 nsresult
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -143,17 +143,16 @@
 #include "nsDOMString.h"
 #include "nsIEmbeddingSiteWindow2.h"
 #include "nsThreadUtils.h"
 #include "nsEventStateManager.h"
 #include "nsIHttpProtocolHandler.h"
 #include "nsIJSContextStack.h"
 #include "nsIJSRuntimeService.h"
 #include "nsIMarkupDocumentViewer.h"
-#include "nsIPrefBranch.h"
 #include "nsIPresShell.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIProgrammingLanguage.h"
 #include "nsIServiceManager.h"
 #include "nsIScriptGlobalObjectOwner.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollableFrame.h"
 #include "nsIView.h"
--- a/dom/base/nsScreen.cpp
+++ b/dom/base/nsScreen.cpp
@@ -37,30 +37,23 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/Hal.h"
 #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"
 #include "nsDOMEvent.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
-/* static */ bool nsScreen::sInitialized = false;
-/* static */ bool nsScreen::sAllowScreenEnabledProperty = false;
-/* static */ bool nsScreen::sAllowScreenBrightnessProperty = false;
-
 namespace {
 
 bool
 IsChromeType(nsIDocShell *aDocShell)
 {
   nsCOMPtr<nsIDocShellTreeItem> ds = do_QueryInterface(aDocShell);
   if (!ds) {
     return false;
@@ -68,47 +61,31 @@ IsChromeType(nsIDocShell *aDocShell)
 
   PRInt32 itemType;
   ds->GetItemType(&itemType);
   return itemType == nsIDocShellTreeItem::typeChrome;
 }
 
 } // anonymous namespace
 
-/* static */ void
-nsScreen::Initialize()
-{
-  MOZ_ASSERT(!sInitialized);
-  sInitialized = true;
-  Preferences::AddBoolVarCache(&sAllowScreenEnabledProperty,
-                               "dom.screenEnabledProperty.enabled");
-  Preferences::AddBoolVarCache(&sAllowScreenBrightnessProperty,
-                               "dom.screenBrightnessProperty.enabled");
-}
-
 /* static */ already_AddRefed<nsScreen>
 nsScreen::Create(nsPIDOMWindow* aWindow)
 {
   MOZ_ASSERT(aWindow);
 
-  if (!sInitialized) {
-    Initialize();
-  }
-
   if (!aWindow->GetDocShell()) {
     return nsnull;
   }
 
   nsCOMPtr<nsIScriptGlobalObject> sgo =
     do_QueryInterface(static_cast<nsPIDOMWindow*>(aWindow));
   NS_ENSURE_TRUE(sgo, nsnull);
 
   nsRefPtr<nsScreen> screen = new nsScreen();
   screen->BindToOwner(aWindow);
-  screen->mIsChrome = IsChromeType(aWindow->GetDocShell());
 
   hal::RegisterScreenOrientationObserver(screen);
   hal::GetCurrentScreenOrientation(&(screen->mOrientation));
 
   return screen.forget();
 }
 
 nsScreen::nsScreen()
@@ -143,38 +120,16 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Screen)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsScreen, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsScreen, nsDOMEventTargetHelper)
 
 NS_IMPL_EVENT_HANDLER(nsScreen, mozorientationchange)
 
-bool
-nsScreen::IsWhiteListed() {
-  if (mIsChrome) {
-    return true;
-  }
-
-  if (!GetOwner()) {
-    return false;
-  }
-
-  nsCOMPtr<nsIDocument> doc = do_GetInterface(GetOwner()->GetDocShell());
-  if (!doc) {
-    return false;
-  }
-
-  nsIPrincipal *principal = doc->NodePrincipal();
-  nsCOMPtr<nsIURI> principalURI;
-  principal->GetURI(getter_AddRefs(principalURI));
-  return nsContentUtils::URIIsChromeOrInPref(principalURI,
-                                             "dom.mozScreenWhitelist");
-}
-
 NS_IMETHODIMP
 nsScreen::GetTop(PRInt32* aTop)
 {
   nsRect rect;
   nsresult rv = GetRect(rect);
 
   *aTop = rect.y;
 
@@ -324,65 +279,16 @@ nsScreen::GetAvailRect(nsRect& aRect)
   aRect.x = nsPresContext::AppUnitsToIntCSSPixels(aRect.x);
   aRect.y = nsPresContext::AppUnitsToIntCSSPixels(aRect.y);
   aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height);
   aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width);
 
   return NS_OK;
 }
 
-nsresult
-nsScreen::GetMozEnabled(bool *aEnabled)
-{
-  if (!sAllowScreenEnabledProperty || !IsWhiteListed()) {
-    *aEnabled = true;
-    return NS_OK;
-  }
-
-  *aEnabled = hal::GetScreenEnabled();
-  return NS_OK;
-}
-
-nsresult
-nsScreen::SetMozEnabled(bool aEnabled)
-{
-  if (!sAllowScreenEnabledProperty || !IsWhiteListed()) {
-    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 (!sAllowScreenEnabledProperty || !IsWhiteListed()) {
-    *aBrightness = 1;
-    return NS_OK;
-  }
-
-  *aBrightness = hal::GetScreenBrightness();
-  return NS_OK;
-}
-
-nsresult
-nsScreen::SetMozBrightness(double aBrightness)
-{
-  if (!sAllowScreenEnabledProperty || !IsWhiteListed()) {
-    return NS_OK;
-  }
-
-  NS_ENSURE_TRUE(0 <= aBrightness && aBrightness <= 1, NS_ERROR_INVALID_ARG);
-  hal::SetScreenBrightness(aBrightness);
-  return NS_OK;
-}
-
 void
 nsScreen::Notify(const ScreenOrientationWrapper& aOrientation)
 {
   ScreenOrientation previousOrientation = mOrientation;
   mOrientation = aOrientation.orientation;
 
   NS_ASSERTION(mOrientation != eScreenOrientation_None &&
                mOrientation != eScreenOrientation_EndGuard &&
--- a/dom/base/nsScreen.h
+++ b/dom/base/nsScreen.h
@@ -69,39 +69,29 @@ public:
 
   void Notify(const mozilla::dom::ScreenOrientationWrapper& aOrientation);
 
 protected:
   nsDeviceContext* GetDeviceContext();
   nsresult GetRect(nsRect& aRect);
   nsresult GetAvailRect(nsRect& aRect);
 
-  bool mIsChrome;
-
   mozilla::dom::ScreenOrientation mOrientation;
 
 private:
   class FullScreenEventListener : public nsIDOMEventListener
   {
   public:
     FullScreenEventListener() {};
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIDOMEVENTLISTENER
   };
 
   nsScreen();
   virtual ~nsScreen();
 
-  static bool sInitialized;
-  static bool sAllowScreenEnabledProperty;
-  static bool sAllowScreenBrightnessProperty;
-
-  static void Initialize();
-
-  bool IsWhiteListed();
-
   nsRefPtr<FullScreenEventListener> mEventListener;
 
   NS_DECL_EVENT_HANDLER(mozorientationchange)
 };
 
 #endif /* nsScreen_h___ */
--- a/dom/interfaces/base/nsIDOMScreen.idl
+++ b/dom/interfaces/base/nsIDOMScreen.idl
@@ -34,54 +34,31 @@
  * 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 "nsIDOMEventTarget.idl"
 
-[scriptable, uuid(8a66b30c-9a32-4b17-ab4e-ca8b7b588243)]
+[scriptable, uuid(9b978f58-5bfe-409d-aa3f-946ca934e51d)]
 interface nsIDOMScreen : nsIDOMEventTarget
 {
   readonly attribute long             top;
   readonly attribute long             left;
   readonly attribute long             width;
   readonly attribute long             height;
   readonly attribute long             pixelDepth;
   readonly attribute long             colorDepth;
   readonly attribute long             availWidth;
   readonly attribute long             availHeight;
   readonly attribute long             availLeft;
   readonly attribute long             availTop;
 
   /**
-   * Is the device's screen currently enabled?  This attribute controls the
-   * device's screen, so setting it to false will turn off the screen.
-   */
-  attribute boolean mozEnabled;
-
-  /**
-   * How bright is the screen's backlight, on a scale from 0 (very dim) to 1
-   * (full brightness)?  Setting this attribute modifies the screen's
-   * brightness.
-   *
-   * You can read and write this attribute even when the screen is disabled,
-   * but the backlight is off while the screen is disabled.
-   *
-   * If you write a value of X into this attribute, the attribute may not have
-   * the same value X when you later read it.  Most screens don't support as
-   * many different brightness levels as there are doubles between 0 and 1, so
-   * we may reduce the value's precision before storing it.
-   *
-   * @throw NS_ERROR_INVALID_ARG if brightness is not in the range [0, 1].
-   */
-  attribute double mozBrightness;
-
-  /**
    * Returns the current screen orientation.
    * Can be: landscape-primary, landscape-secondary,
    *         portrait-primary or portrait-secondary.
    */
   readonly attribute DOMString       mozOrientation;
 
   attribute nsIDOMEventListener      onmozorientationchange;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -44,18 +44,16 @@
 #include "History.h"
 #include "mozilla/ipc/TestShellParent.h"
 #include "mozilla/net/NeckoParent.h"
 #include "mozilla/Preferences.h"
 #include "nsHashPropertyBag.h"
 #include "nsIFilePicker.h"
 #include "nsIWindowWatcher.h"
 #include "nsIDOMWindow.h"
-#include "nsIPrefBranch.h"
-#include "nsIPrefLocalizedString.h"
 #include "nsIObserverService.h"
 #include "nsContentUtils.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsChromeRegistryChrome.h"
 #include "nsExternalHelperAppService.h"
@@ -211,20 +209,17 @@ ContentParent::Init()
         obs->AddObserver(this, "child-memory-reporter-request", false);
         obs->AddObserver(this, "memory-pressure", false);
         obs->AddObserver(this, "child-gc-request", false);
         obs->AddObserver(this, "child-cc-request", false);
 #ifdef ACCESSIBILITY
         obs->AddObserver(this, "a11y-init-or-shutdown", false);
 #endif
     }
-    nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
-    if (prefs) {
-        prefs->AddObserver("", this, false);
-    }
+    Preferences::AddStrongObserver(this, "");
     nsCOMPtr<nsIThreadInternal>
             threadInt(do_QueryInterface(NS_GetCurrentThread()));
     if (threadInt) {
         threadInt->AddObserver(this);
     }
     if (obs) {
         obs->NotifyObservers(static_cast<nsIObserver*>(this), "ipc:content-created", nsnull);
     }
@@ -244,23 +239,18 @@ ContentParent::OnChannelConnected(int32 
     ProcessHandle handle;
     if (!base::OpenPrivilegedProcessHandle(pid, &handle)) {
         NS_WARNING("Can't open handle to child process.");
     }
     else {
         SetOtherProcess(handle);
 
 #if defined(ANDROID) || defined(LINUX)
-        EnsurePrefService();
-        nsCOMPtr<nsIPrefBranch> branch;
-        branch = do_QueryInterface(mPrefService);
-
         // Check nice preference
-        PRInt32 nice = 0;
-        branch->GetIntPref("dom.ipc.content.nice", &nice);
+        PRInt32 nice = Preferences::GetInt("dom.ipc.content.nice", 0);
 
         // Environment variable overrides preference
         char* relativeNicenessStr = getenv("MOZ_CHILD_PROCESS_RELATIVE_NICENESS");
         if (relativeNicenessStr) {
             nice = atoi(relativeNicenessStr);
         }
 
         /* make the GUI thread have higher priority on single-cpu devices */
@@ -324,21 +314,17 @@ ContentParent::ActorDestroy(ActorDestroy
 
     mMessageManager->Disconnect();
 
     // clear the child memory reporters
     InfallibleTArray<MemoryReport> empty;
     SetChildMemoryReporters(empty);
 
     // remove the global remote preferences observers
-    nsCOMPtr<nsIPrefBranch> prefs 
-            (do_GetService(NS_PREFSERVICE_CONTRACTID));
-    if (prefs) { 
-        prefs->RemoveObserver("", this);
-    }
+    Preferences::RemoveObserver(this, "");
 
     RecvRemoveGeolocationListener();
 
     nsCOMPtr<nsIThreadInternal>
         threadInt(do_QueryInterface(NS_GetCurrentThread()));
     if (threadInt)
         threadInt->RemoveObserver(this);
     if (mRunToCompletionDepth)
@@ -459,42 +445,29 @@ bool
 ContentParent::IsAlive()
 {
     return mIsAlive;
 }
 
 bool
 ContentParent::RecvReadPrefsArray(InfallibleTArray<PrefTuple> *prefs)
 {
-    EnsurePrefService();
     Preferences::MirrorPreferences(prefs);
     return true;
 }
 
 bool
 ContentParent::RecvReadFontList(InfallibleTArray<FontListEntry>* retValue)
 {
 #ifdef ANDROID
     gfxAndroidPlatform::GetPlatform()->GetFontList(retValue);
 #endif
     return true;
 }
 
-
-void
-ContentParent::EnsurePrefService()
-{
-    nsresult rv;
-    if (!mPrefService) {
-        mPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
-        NS_ASSERTION(NS_SUCCEEDED(rv), 
-                     "We lost prefService in the Chrome process !");
-    }
-}
-
 bool
 ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions)
 {
 #ifdef MOZ_PERMISSIONS
     nsCOMPtr<nsIPermissionManager> permissionManagerIface =
         do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
     nsPermissionManager* permissionManager =
         static_cast<nsPermissionManager*>(permissionManagerIface.get());
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -43,17 +43,16 @@
 
 #include "mozilla/dom/PContentParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/ipc/GeckoChildProcessHost.h"
 
 #include "nsIObserver.h"
 #include "nsIThreadInternal.h"
 #include "nsNetUtil.h"
-#include "nsIPrefService.h"
 #include "nsIPermissionManager.h"
 #include "nsIDOMGeoPositionCallback.h"
 #include "nsIMemoryReporter.h"
 #include "nsCOMArray.h"
 
 class nsFrameMessageManager;
 namespace mozilla {
 
@@ -162,18 +161,16 @@ private:
     virtual bool DeallocPSms(PSmsParent*);
 
     virtual PStorageParent* AllocPStorage(const StorageConstructData& aData);
     virtual bool DeallocPStorage(PStorageParent* aActor);
 
     virtual bool RecvReadPrefsArray(InfallibleTArray<PrefTuple> *retValue);
     virtual bool RecvReadFontList(InfallibleTArray<FontListEntry>* retValue);
 
-    void EnsurePrefService();
-
     virtual bool RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions);
 
     virtual bool RecvGetIndexedDBDirectory(nsString* aDirectory);
 
     virtual bool RecvSetClipboardText(const nsString& text, const PRInt32& whichClipboard);
     virtual bool RecvGetClipboardText(const PRInt32& whichClipboard, nsString* text);
     virtual bool RecvEmptyClipboard();
     virtual bool RecvClipboardHasText(bool* hasText);
@@ -233,18 +230,16 @@ private:
 
     // This is a cache of all of the memory reporters
     // registered in the child process.  To update this, one
     // can broadcast the topic "child-memory-reporter-request" using
     // the nsIObserverService.
     nsCOMArray<nsIMemoryReporter> mMemoryReporters;
 
     bool mIsAlive;
-    nsCOMPtr<nsIPrefService> mPrefService;
-
     bool mSendPermissionUpdates;
 
     nsRefPtr<nsFrameMessageManager> mMessageManager;
 
     friend class CrashReporterParent;
 };
 
 } // namespace dom
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -50,22 +50,21 @@
 
 #include "nsPluginHost.h"
 #include "nsNPAPIPlugin.h"
 #include "nsNPAPIPluginInstance.h"
 #include "nsNPAPIPluginStreamListener.h"
 #include "nsIServiceManager.h"
 #include "nsThreadUtils.h"
 #include "nsIPrivateBrowsingService.h"
+#include "mozilla/Preferences.h"
 
 #include "nsIPluginStreamListener.h"
 #include "nsPluginsDir.h"
 #include "nsPluginSafety.h"
-#include "nsIPrefService.h"
-#include "nsIPrefBranch.h"
 #include "nsPluginLogging.h"
 
 #include "nsIJSContextStack.h"
 
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDocument.h"
@@ -347,17 +346,17 @@ nsNPAPIPlugin::RunPluginOOP(const nsPlug
       }
       if (versionPrefix.EqualsASCII("10.1") && GMA9XXGraphics()) {
         return false;
       }
     }
   }
 #endif
 
-  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+  nsIPrefBranch* prefs = Preferences::GetRootBranch();
   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"
   // The "filename.dll" part can contain shell wildcard pattern
@@ -380,18 +379,17 @@ nsNPAPIPlugin::RunPluginOOP(const nsPlug
 #else
   nsCAutoString prefGroupKey("dom.ipc.plugins.enabled.");
 #endif
 
   // Java plugins include a number of different file names,
   // so use the mime type (mIsJavaPlugin) and a special pref.
   bool javaIsEnabled;
   if (aPluginTag->mIsJavaPlugin &&
-      NS_SUCCEEDED(prefs->GetBoolPref("dom.ipc.plugins.java.enabled", &javaIsEnabled)) &&
-      !javaIsEnabled) {
+      !Preferences::GetBool("dom.ipc.plugins.java.enabled", true)) {
     return false;
   }
 
   PRUint32 prefCount;
   char** prefNames;
   nsresult rv = prefs->GetChildList(prefGroupKey.get(),
                                     &prefCount, &prefNames);
 
@@ -412,37 +410,37 @@ nsNPAPIPlugin::RunPluginOOP(const nsPlug
       else if(valid == NON_SXP) {
         // mask is not a shell pattern, compare it as normal string
         match = (strcmp(prefFile.get(), maskStart) == 0);
       }
       else {
         match = (NS_WildCardMatch(prefFile.get(), maskStart, 0) == MATCH);
       }
 
-      if (match && NS_SUCCEEDED(prefs->GetBoolPref(prefNames[currentPref],
-                                                   &oopPluginsEnabled))) {
+      if (match && NS_SUCCEEDED(Preferences::GetBool(prefNames[currentPref],
+                                                     &oopPluginsEnabled))) {
         prefSet = true;
         break;
       }
     }
     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(prefCount, prefNames);
   }
 
   if (!prefSet) {
-    oopPluginsEnabled = false;
+    oopPluginsEnabled =
 #ifdef XP_MACOSX
 #if defined(__i386__)
-    prefs->GetBoolPref("dom.ipc.plugins.enabled.i386", &oopPluginsEnabled);
+    Preferences::GetBool("dom.ipc.plugins.enabled.i386", false);
 #elif defined(__x86_64__)
-    prefs->GetBoolPref("dom.ipc.plugins.enabled.x86_64", &oopPluginsEnabled);
+    Preferences::GetBool("dom.ipc.plugins.enabled.x86_64", false);
 #elif defined(__ppc__)
-    prefs->GetBoolPref("dom.ipc.plugins.enabled.ppc", &oopPluginsEnabled);
+    Preferences::GetBool("dom.ipc.plugins.enabled.ppc", false);
 #endif
 #else
-    prefs->GetBoolPref("dom.ipc.plugins.enabled", &oopPluginsEnabled);
+    Preferences::GetBool("dom.ipc.plugins.enabled", false);
 #endif
   }
 
   return oopPluginsEnabled;
 }
 
 inline PluginLibrary*
 GetNewPluginLibrary(nsPluginTag *aPluginTag)
@@ -2056,22 +2054,20 @@ NPError NP_CALLBACK
       return NPERR_NO_ERROR;
     }
     return NPERR_GENERIC_ERROR;
   }
 #endif
 
   case NPNVjavascriptEnabledBool: {
     *(NPBool*)result = false;
-    nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
-    if (prefs) {
-      bool js = false;;
-      res = prefs->GetBoolPref("javascript.enabled", &js);
-      if (NS_SUCCEEDED(res))
-        *(NPBool*)result = js;
+    bool js = false;
+    res = Preferences::GetBool("javascript.enabled", &js);
+    if (NS_SUCCEEDED(res)) {
+      *(NPBool*)result = js;
     }
     return NPERR_NO_ERROR;
   }
 
   case NPNVasdEnabledBool:
     *(NPBool*)result = false;
     return NPERR_NO_ERROR;
 
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -56,16 +56,18 @@
 #include "nsIScriptContext.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsJSNPRuntime.h"
 #include "nsPluginStreamListenerPeer.h"
 #include "nsSize.h"
 #include "nsNetCID.h"
 #include "nsIContent.h"
 
+#include "mozilla/Preferences.h"
+
 #ifdef MOZ_WIDGET_ANDROID
 #include "ANPBase.h"
 #include <android/log.h>
 #include "android_npapi.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/CondVar.h"
 #include "AndroidBridge.h"
 #endif
@@ -100,23 +102,18 @@ nsNPAPIPluginInstance::nsNPAPIPluginInst
     mUsePluginLayersPref(true)
 #else
     mUsePluginLayersPref(false)
 #endif
 {
   mNPP.pdata = NULL;
   mNPP.ndata = this;
 
-  nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  if (prefs) {
-    bool useLayersPref;
-    nsresult rv = prefs->GetBoolPref("plugins.use_layers", &useLayersPref);
-    if (NS_SUCCEEDED(rv))
-      mUsePluginLayersPref = useLayersPref;
-  }
+  mUsePluginLayersPref =
+    Preferences::GetBool("plugins.use_layers", mUsePluginLayersPref);
 
   PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance ctor: this=%p\n",this));
 }
 
 nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
 {
   PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance dtor: this=%p\n",this));
 
--- a/dom/plugins/base/nsPluginDirServiceProvider.cpp
+++ b/dom/plugins/base/nsPluginDirServiceProvider.cpp
@@ -36,26 +36,26 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsPluginDirServiceProvider.h"
 
 #include "nsCRT.h"
 #include "nsILocalFile.h"
-#include "nsIPrefBranch.h"
-#include "nsIPrefService.h"
 #include "nsDependentString.h"
-#include "nsXPIDLString.h"
 #include "prmem.h"
 #include "nsArrayEnumerator.h"
+#include "mozilla/Preferences.h"
 
 #include <windows.h>
 #include "nsIWindowsRegKey.h"
 
+using namespace mozilla;
+
 typedef struct structVer
 {
   WORD wMajor;
   WORD wMinor;
   WORD wRelease;
   WORD wBuild;
 } verBlock;
 
@@ -226,28 +226,25 @@ nsPluginDirServiceProvider::GetFile(cons
   nsCOMPtr<nsILocalFile>  localFile;
   nsresult rv = NS_ERROR_FAILURE;
 
   NS_ENSURE_ARG(charProp);
 
   *_retval = nsnull;
   *persistant = false;
 
-  nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  if (!prefs)
-    return NS_ERROR_FAILURE;
-
   nsCOMPtr<nsIWindowsRegKey> regKey =
     do_CreateInstance("@mozilla.org/windows-registry-key;1");
   NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
 
   if (nsCRT::strcmp(charProp, NS_WIN_JRE_SCAN_KEY) == 0) {
-    nsXPIDLCString strVer;
-    if (NS_FAILED(prefs->GetCharPref(charProp, getter_Copies(strVer))))
+    nsAdoptingCString strVer = Preferences::GetCString(charProp);
+    if (!strVer) {
       return NS_ERROR_FAILURE;
+    }
     verBlock minVer;
     TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
 
     rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
                       NS_LITERAL_STRING("Software\\JavaSoft\\Java Runtime Environment"),
                       nsIWindowsRegKey::ACCESS_READ);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -327,19 +324,20 @@ nsPluginDirServiceProvider::GetFile(cons
                          &currentVersionExists);
         if (!currentVersionExists) {
           newKey->WriteStringValue(NS_LITERAL_STRING("CurrentVersion"),
                                    NS_LITERAL_STRING(MOZILLA_VERSION));
         }
       }
     }
   } else if (nsCRT::strcmp(charProp, NS_WIN_QUICKTIME_SCAN_KEY) == 0) {
-    nsXPIDLCString strVer;
-    if (NS_FAILED(prefs->GetCharPref(charProp, getter_Copies(strVer))))
+    nsAdoptingCString strVer = Preferences::GetCString(charProp);
+    if (!strVer) {
       return NS_ERROR_FAILURE;
+    }
     verBlock minVer;
     TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
 
     // Look for the Quicktime system installation plugins directory
     verBlock qtVer;
     ClearVersion(&qtVer);
 
     // First we need to check the version of Quicktime via checking
@@ -366,19 +364,20 @@ nsPluginDirServiceProvider::GetFile(cons
       rv = regKey->ReadStringValue(NS_LITERAL_STRING("InstallDir"), path);
       if (NS_SUCCEEDED(rv)) {
         path += NS_LITERAL_STRING("\\Plugins");
         rv = NS_NewLocalFile(path, true,
                              getter_AddRefs(localFile));
       }
     }
   } else if (nsCRT::strcmp(charProp, NS_WIN_WMP_SCAN_KEY) == 0) {
-    nsXPIDLCString strVer;
-    if (NS_FAILED(prefs->GetCharPref(charProp, getter_Copies(strVer))))
+    nsAdoptingCString strVer = Preferences::GetCString(charProp);
+    if (!strVer) {
       return NS_ERROR_FAILURE;
+    }
     verBlock minVer;
     TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
 
     // Look for Windows Media Player system installation plugins directory
     verBlock wmpVer;
     ClearVersion(&wmpVer);
 
     // First we need to check the version of WMP
@@ -404,18 +403,18 @@ nsPluginDirServiceProvider::GetFile(cons
       rv = regKey->ReadStringValue(NS_LITERAL_STRING("Installation Directory"),
                                    path);
       if (NS_SUCCEEDED(rv)) {
         rv = NS_NewLocalFile(path, true,
                              getter_AddRefs(localFile));
       }
     }
   } else if (nsCRT::strcmp(charProp, NS_WIN_ACROBAT_SCAN_KEY) == 0) {
-    nsXPIDLCString strVer;
-    if (NS_FAILED(prefs->GetCharPref(charProp, getter_Copies(strVer)))) {
+    nsAdoptingCString strVer = Preferences::GetCString(charProp);
+    if (!strVer) {
       return NS_ERROR_FAILURE;
     }
 
     verBlock minVer;
     TranslateVersionStr(NS_ConvertASCIItoUTF16(strVer).get(), &minVer);
 
     // Look for Adobe Acrobat system installation plugins directory
     verBlock maxVer;
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -75,24 +75,24 @@
 #include "nsISeekableStream.h"
 #include "nsNetUtil.h"
 #include "nsIProgressEventSink.h"
 #include "nsIDocument.h"
 #include "nsICachingChannel.h"
 #include "nsHashtable.h"
 #include "nsIProxyInfo.h"
 #include "nsPluginLogging.h"
-#include "nsIPrefBranch.h"
 #include "nsIScriptChannel.h"
 #include "nsIBlocklistService.h"
 #include "nsVersionComparator.h"
 #include "nsIPrivateBrowsingService.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsIWritablePropertyBag2.h"
 #include "nsPluginStreamListenerPeer.h"
+#include "mozilla/Preferences.h"
 
 #include "nsEnumeratorUtils.h"
 #include "nsXPCOM.h"
 #include "nsXPCOMCID.h"
 #include "nsISupportsPrimitives.h"
 
 #include "nsXULAppAPI.h"
 #include "nsIXULRuntime.h"
@@ -331,49 +331,29 @@ NS_IMETHODIMP nsPluginDocReframeEvent::R
     }
   }
 
   return mDocs->Clear();
 }
 
 static bool UnloadPluginsASAP()
 {
-  nsresult rv;
-  nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
-  if (NS_SUCCEEDED(rv)) {
-    bool unloadPluginsASAP = false;
-    rv = pref->GetBoolPref("dom.ipc.plugins.unloadASAP", &unloadPluginsASAP);
-    if (NS_SUCCEEDED(rv)) {
-      return unloadPluginsASAP;
-    }
-  }
-
-  return false;
+  return Preferences::GetBool("dom.ipc.plugins.unloadASAP", false);
 }
 
 nsPluginHost::nsPluginHost()
   // No need to initialize members to nsnull, false etc because this class
   // has a zeroing operator new.
 {
   // check to see if pref is set at startup to let plugins take over in
   // full page mode for certain image mime types that we handle internally
-  mPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
-  if (mPrefService) {
-    bool tmp;
-    nsresult rv = mPrefService->GetBoolPref("plugin.override_internal_types",
-                                            &tmp);
-    if (NS_SUCCEEDED(rv)) {
-      mOverrideInternalTypes = tmp;
-    }
-
-    rv = mPrefService->GetBoolPref("plugin.disable", &tmp);
-    if (NS_SUCCEEDED(rv)) {
-      mPluginsDisabled = tmp;
-    }
-  }
+  mOverrideInternalTypes =
+    Preferences::GetBool("plugin.override_internal_types", false);
+
+  mPluginsDisabled = Preferences::GetBool("plugin.disable", false);
 
   nsCOMPtr<nsIObserverService> obsService =
     mozilla::services::GetObserverService();
   if (obsService) {
     obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
     obsService->AddObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC, false);
 #ifdef MOZ_WIDGET_ANDROID
     obsService->AddObserver(this, "application-foreground", false);
@@ -423,26 +403,26 @@ nsPluginHost::GetInst()
       return nsnull;
     NS_ADDREF(sInst);
   }
 
   NS_ADDREF(sInst);
   return sInst;
 }
 
-bool nsPluginHost::IsRunningPlugin(nsPluginTag * plugin)
+bool nsPluginHost::IsRunningPlugin(nsPluginTag * aPluginTag)
 {
-  if (!plugin || !plugin->mEntryPoint) {
+  if (!aPluginTag || !aPluginTag->mPlugin) {
     return false;
   }
 
   for (PRUint32 i = 0; i < mInstances.Length(); i++) {
     nsNPAPIPluginInstance *instance = mInstances[i].get();
     if (instance &&
-        instance->GetPlugin() == plugin->mEntryPoint &&
+        instance->GetPlugin() == aPluginTag->mPlugin &&
         instance->IsRunning()) {
       return true;
     }
   }
 
   return false;
 }
 
@@ -861,18 +841,16 @@ nsresult nsPluginHost::Destroy()
     nsCOMPtr<nsIDirectoryService> dirService =
       do_GetService(kDirectoryServiceContractID);
     if (dirService)
       dirService->UnregisterProvider(mPrivateDirServiceProvider);
     mPrivateDirServiceProvider = nsnull;
   }
 #endif /* XP_WIN */
 
-  mPrefService = nsnull; // release prefs service to avoid leaks!
-
   return NS_OK;
 }
 
 void nsPluginHost::OnPluginInstanceDestroyed(nsPluginTag* aPluginTag)
 {
   bool hasInstance = false;
   for (PRUint32 i = 0; i < mInstances.Length(); i++) {
     if (TagForPlugin(mInstances[i]->GetPlugin()) == aPluginTag) {
@@ -1193,62 +1171,56 @@ nsPluginHost::FindTagForLibrary(PRLibrar
   return nsnull;
 }
 
 nsPluginTag*
 nsPluginHost::TagForPlugin(nsNPAPIPlugin* aPlugin)
 {
   nsPluginTag* pluginTag;
   for (pluginTag = mPlugins; pluginTag; pluginTag = pluginTag->mNext) {
-    if (pluginTag->mEntryPoint == aPlugin) {
+    if (pluginTag->mPlugin == aPlugin) {
       return pluginTag;
     }
   }
   // a plugin should never exist without a corresponding tag
   NS_ERROR("TagForPlugin has failed");
   return nsnull;
 }
 
 nsresult nsPluginHost::SetUpPluginInstance(const char *aMimeType,
                                            nsIURI *aURL,
                                            nsIPluginInstanceOwner *aOwner)
 {
   NS_ENSURE_ARG_POINTER(aOwner);
 
-  nsresult rv = NS_OK;
-
-  rv = TrySetUpPluginInstance(aMimeType, aURL, aOwner);
-
-  // if we fail, refresh plugin list just in case the plugin has been
-  // just added and try to instantiate plugin instance again, see bug 143178
-  if (NS_FAILED(rv)) {
-    // we should also make sure not to do this more than once per page
-    // so if there are a few embed tags with unknown plugins,
-    // we don't get unnecessary overhead
-    // let's cache document to decide whether this is the same page or not
-    nsCOMPtr<nsIDocument> document;
-    aOwner->GetDocument(getter_AddRefs(document));
-
-    nsCOMPtr<nsIDocument> currentdocument = do_QueryReferent(mCurrentDocument);
-    if (document == currentdocument)
-      return rv;
-
-    mCurrentDocument = do_GetWeakReference(document);
-
-    // ReloadPlugins will do the job smartly: nothing will be done
-    // if no changes detected, in such a case just return
-    if (NS_ERROR_PLUGINS_PLUGINSNOTCHANGED == ReloadPlugins(false))
-      return rv;
-
-    // other failure return codes may be not fatal, so we can still try
-    aOwner->SetInstance(nsnull); // avoid assert about setting it twice
-    rv = TrySetUpPluginInstance(aMimeType, aURL, aOwner);
+  nsresult rv = TrySetUpPluginInstance(aMimeType, aURL, aOwner);
+  if (NS_SUCCEEDED(rv)) {
+    return rv;
   }
 
-  return rv;
+  // If we failed to load a plugin instance we'll try again after
+  // reloading our plugin list. Only do that once per document to
+  // avoid redundant high resource usage on pages with multiple
+  // unkown instance types. We'll do that by caching the document.
+  nsCOMPtr<nsIDocument> document;
+  aOwner->GetDocument(getter_AddRefs(document));
+
+  nsCOMPtr<nsIDocument> currentdocument = do_QueryReferent(mCurrentDocument);
+  if (document == currentdocument) {
+    return rv;
+  }
+
+  mCurrentDocument = do_GetWeakReference(document);
+
+  // Don't try to set up an instance again if nothing changed.
+  if (ReloadPlugins(false) == NS_ERROR_PLUGINS_PLUGINSNOTCHANGED) {
+    return rv;
+  }
+
+  return TrySetUpPluginInstance(aMimeType, aURL, aOwner);
 }
 
 nsresult
 nsPluginHost::TrySetUpPluginInstance(const char *aMimeType,
                                      nsIURI *aURL,
                                      nsIPluginInstanceOwner *aOwner)
 {
 #ifdef PLUGIN_LOGGING
@@ -1455,21 +1427,17 @@ public:
   NS_METHOD GetDescription(nsAString& aDescription)
   {
     CopyUTF8toUTF16(mPluginTag.mDescription, aDescription);
     return NS_OK;
   }
 
   NS_METHOD GetFilename(nsAString& aFilename)
   {
-    bool bShowPath;
-    nsCOMPtr<nsIPrefBranch> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
-    if (prefService &&
-        NS_SUCCEEDED(prefService->GetBoolPref("plugin.expose_full_path", &bShowPath)) &&
-        bShowPath) {
+    if (Preferences::GetBool("plugin.expose_full_path", false)) {
       CopyUTF8toUTF16(mPluginTag.mFullPath, aFilename);
     } else {
       CopyUTF8toUTF16(mPluginTag.mFileName, aFilename);
     }
 
     return NS_OK;
   }
 
@@ -1653,25 +1621,25 @@ static nsresult CreateNPAPIPlugin(nsPlug
   }
 
   nsresult rv;
   rv = nsNPAPIPlugin::CreatePlugin(aPluginTag, aOutNPAPIPlugin);
 
   return rv;
 }
 
-nsresult nsPluginHost::EnsurePluginLoaded(nsPluginTag* plugin)
+nsresult nsPluginHost::EnsurePluginLoaded(nsPluginTag* aPluginTag)
 {
-  nsRefPtr<nsNPAPIPlugin> entrypoint = plugin->mEntryPoint;
-  if (!entrypoint) {
-    nsresult rv = CreateNPAPIPlugin(plugin, getter_AddRefs(entrypoint));
+  nsRefPtr<nsNPAPIPlugin> plugin = aPluginTag->mPlugin;
+  if (!plugin) {
+    nsresult rv = CreateNPAPIPlugin(aPluginTag, getter_AddRefs(plugin));
     if (NS_FAILED(rv)) {
       return rv;
     }
-    plugin->mEntryPoint = entrypoint;
+    aPluginTag->mPlugin = plugin;
   }
   return NS_OK;
 }
 
 nsresult nsPluginHost::GetPlugin(const char *aMimeType, nsNPAPIPlugin** aPlugin)
 {
   nsresult rv = NS_ERROR_FAILURE;
   *aPlugin = NULL;
@@ -1694,17 +1662,17 @@ nsresult nsPluginHost::GetPlugin(const c
       printf("For %s found plugin %s\n", aMimeType, pluginTag->mFileName.get());
 #endif
 
     rv = EnsurePluginLoaded(pluginTag);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
-    NS_ADDREF(*aPlugin = pluginTag->mEntryPoint);
+    NS_ADDREF(*aPlugin = pluginTag->mPlugin);
     return NS_OK;
   }
 
   PLUGIN_LOG(PLUGIN_LOG_NORMAL,
   ("nsPluginHost::GetPlugin End mime=%s, rv=%d, plugin=%p name=%s\n",
   aMimeType, rv, *aPlugin,
   (pluginTag ? pluginTag->mFileName.get() : "(not found)")));
 
@@ -1818,27 +1786,27 @@ nsPluginHost::ClearSiteData(nsIPluginTag
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsPluginTag* tag = static_cast<nsPluginTag*>(plugin);
 
   // We only ensure support for clearing Flash site data for now.
   // We will also attempt to clear data for any plugin that happens
   // to be loaded already.
-  if (!tag->mIsFlashPlugin && !tag->mEntryPoint) {
+  if (!tag->mIsFlashPlugin && !tag->mPlugin) {
     return NS_ERROR_FAILURE;
   }
 
   // Make sure the plugin is loaded.
   nsresult rv = EnsurePluginLoaded(tag);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  PluginLibrary* library = tag->mEntryPoint->GetLibrary();
+  PluginLibrary* library = tag->mPlugin->GetLibrary();
 
   // If 'domain' is the null string, clear everything.
   if (domain.IsVoid()) {
     return library->NPP_ClearSiteData(NULL, flags, maxAge);
   }
 
   // Get the list of sites from the plugin.
   InfallibleTArray<nsCString> sites;
@@ -1869,27 +1837,27 @@ nsPluginHost::SiteHasData(nsIPluginTag* 
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsPluginTag* tag = static_cast<nsPluginTag*>(plugin);
 
   // We only ensure support for clearing Flash site data for now.
   // We will also attempt to clear data for any plugin that happens
   // to be loaded already.
-  if (!tag->mIsFlashPlugin && !tag->mEntryPoint) {
+  if (!tag->mIsFlashPlugin && !tag->mPlugin) {
     return NS_ERROR_FAILURE;
   }
 
   // Make sure the plugin is loaded.
   nsresult rv = EnsurePluginLoaded(tag);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
-  PluginLibrary* library = tag->mEntryPoint->GetLibrary();
+  PluginLibrary* library = tag->mPlugin->GetLibrary();
 
   // Get the list of sites from the plugin.
   InfallibleTArray<nsCString> sites;
   rv = library->NPP_GetSitesWithData(sites);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If there's no data, we're done.
   if (sites.IsEmpty()) {
@@ -2220,17 +2188,17 @@ nsresult nsPluginHost::ScanPluginsDirect
 
       if (pluginTag->IsEnabled()) {
         pluginTag->RegisterWithCategoryManager(mOverrideInternalTypes);
       }
     }
   }
 
   if (warnOutdated) {
-    mPrefService->SetBoolPref("plugins.update.notifyUser", true);
+    Preferences::SetBool("plugins.update.notifyUser", true);
   }
 
   return NS_OK;
 }
 
 nsresult nsPluginHost::ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum,
                                                 bool aCreatePluginList,
                                                 bool *aPluginsChanged)
@@ -2349,20 +2317,17 @@ nsresult nsPluginHost::FindPlugins(bool 
     LOG("getting plugins dir failed");
 #endif
   }
 
   mPluginsLoaded = true; // at this point 'some' plugins have been loaded,
                             // the rest is optional
 
 #ifdef XP_WIN
-  bool bScanPLIDs = false;
-
-  if (mPrefService)
-    mPrefService->GetBoolPref("plugin.scan.plid.all", &bScanPLIDs);
+  bool bScanPLIDs = Preferences::GetBool("plugin.scan.plid.all", false);
 
     // Now lets scan any PLID directories
   if (bScanPLIDs && mPrivateDirServiceProvider) {
     rv = mPrivateDirServiceProvider->GetPLIDDirectories(getter_AddRefs(dirList));
     if (NS_SUCCEEDED(rv)) {
       ScanPluginsDirectoryList(dirList, aCreatePluginList, &pluginschanged);
 
       if (pluginschanged)
@@ -3234,23 +3199,19 @@ nsPluginHost::StopPluginInstance(nsNPAPI
 
   Telemetry::AutoTimer<Telemetry::PLUGIN_SHUTDOWN_MS> timer;
   aInstance->Stop();
 
   // if the instance does not want to be 'cached' just remove it
   bool doCache = aInstance->ShouldCache();
   if (doCache) {
     // try to get the max cached instances from a pref or use default
-    PRUint32 cachedInstanceLimit;
-    nsresult rv = NS_ERROR_FAILURE;
-    if (mPrefService)
-      rv = mPrefService->GetIntPref(NS_PREF_MAX_NUM_CACHED_INSTANCES, (int*)&cachedInstanceLimit);
-    if (NS_FAILED(rv))
-      cachedInstanceLimit = DEFAULT_NUMBER_OF_STOPPED_INSTANCES;
-    
+    PRUint32 cachedInstanceLimit =
+      Preferences::GetUint(NS_PREF_MAX_NUM_CACHED_INSTANCES,
+                           DEFAULT_NUMBER_OF_STOPPED_INSTANCES);
     if (StoppedInstanceCount() >= cachedInstanceLimit) {
       nsNPAPIPluginInstance *oldestInstance = FindOldestStoppedInstance();
       if (oldestInstance) {
         nsPluginTag* pluginTag = TagForPlugin(oldestInstance->GetPlugin());
         oldestInstance->Destroy();
         mInstances.RemoveElement(oldestInstance);
         OnPluginInstanceDestroyed(pluginTag);
       }
@@ -3979,20 +3940,20 @@ nsPluginHost::PluginCrashed(nsNPAPIPlugi
 
       instance->Destroy();
       mInstances.RemoveElement(instance);
       OnPluginInstanceDestroyed(crashedPluginTag);
     }
   }
 
   // Only after all instances have been invalidated is it safe to null
-  // out nsPluginTag.mEntryPoint. The next time we try to create an
+  // out nsPluginTag.mPlugin. The next time we try to create an
   // instance of this plugin we reload it (launch a new plugin process).
 
-  crashedPluginTag->mEntryPoint = nsnull;
+  crashedPluginTag->mPlugin = nsnull;
 
 #ifdef XP_WIN
   CheckForDisabledWindows();
 #endif
 }
 
 nsNPAPIPluginInstance*
 nsPluginHost::FindInstance(const char *mimetype)
--- a/dom/plugins/base/nsPluginHost.h
+++ b/dom/plugins/base/nsPluginHost.h
@@ -48,17 +48,16 @@
 #include "nsNPAPIPluginInstance.h"
 #include "nsIPluginTag.h"
 #include "nsPluginsDir.h"
 #include "nsPluginDirServiceProvider.h"
 #include "nsAutoPtr.h"
 #include "nsWeakPtr.h"
 #include "nsIPrompt.h"
 #include "nsISupportsArray.h"
-#include "nsIPrefBranch.h"
 #include "nsWeakReference.h"
 #include "nsThreadUtils.h"
 #include "nsTArray.h"
 #include "nsTObserverArray.h"
 #include "nsITimer.h"
 #include "nsPluginTags.h"
 #include "nsIEffectiveTLDService.h"
 #include "nsIIDNService.h"
@@ -270,19 +269,19 @@ private:
                        bool aCreatePluginList,
                        bool *aPluginsChanged);
 
   nsresult
   ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum,
                            bool aCreatePluginList,
                            bool *aPluginsChanged);
 
-  nsresult EnsurePluginLoaded(nsPluginTag* plugin);
+  nsresult EnsurePluginLoaded(nsPluginTag* aPluginTag);
 
-  bool IsRunningPlugin(nsPluginTag * plugin);
+  bool IsRunningPlugin(nsPluginTag * aPluginTag);
 
   // Stores all plugins info into the registry
   nsresult WritePluginInfo();
 
   // Loads all cached plugins info into mCachedPlugins
   nsresult ReadPluginInfo();
 
   // Given a file path, returns the plugins info from our cache
@@ -317,17 +316,16 @@ private:
   // set by pref plugin.disable
   bool mPluginsDisabled;
 
   // Any instances in this array will have valid plugin objects via GetPlugin().
   // When removing an instance it might not die - be sure to null out it's plugin.
   nsTArray< nsRefPtr<nsNPAPIPluginInstance> > mInstances;
 
   nsCOMPtr<nsIFile> mPluginRegFile;
-  nsCOMPtr<nsIPrefBranch> mPrefService;
 #ifdef XP_WIN
   nsRefPtr<nsPluginDirServiceProvider> mPrivateDirServiceProvider;
 #endif
 
   nsCOMPtr<nsIEffectiveTLDService> mTLDService;
   nsCOMPtr<nsIIDNService> mIDNService;
 
   // Helpers for ClearSiteData and SiteHasData.
--- a/dom/plugins/base/nsPluginSafety.h
+++ b/dom/plugins/base/nsPluginSafety.h
@@ -35,36 +35,35 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsPluginSafety_h_
 #define nsPluginSafety_h_
 
 #include "npapi.h"
 #include "nsPluginHost.h"
-#include "nsIPrefBranch.h"
-#include "nsIPrefService.h"
 #include <prinrval.h>
 
 #if defined(XP_WIN)
 #define CALL_SAFETY_ON
 #endif
 
 void NS_NotifyPluginCall(PRIntervalTime);
 
 #ifdef CALL_SAFETY_ON
 
+#include "mozilla/Preferences.h"
+
 extern bool gSkipPluginSafeCalls;
 
-#define NS_INIT_PLUGIN_SAFE_CALLS                               \
-PR_BEGIN_MACRO                                                  \
-  nsresult res;                                                 \
-  nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &res)); \
-  if(NS_SUCCEEDED(res) && pref)                                 \
-    res = pref->GetBoolPref("plugin.dont_try_safe_calls", &gSkipPluginSafeCalls);\
+#define NS_INIT_PLUGIN_SAFE_CALLS                                  \
+PR_BEGIN_MACRO                                                     \
+  gSkipPluginSafeCalls =                                           \
+    ::mozilla::Preferences::GetBool("plugin.dont_try_safe_calls",  \
+                                    gSkipPluginSafeCalls);         \
 PR_END_MACRO
 
 #define NS_TRY_SAFE_CALL_RETURN(ret, fun, pluginInst) \
 PR_BEGIN_MACRO                                     \
   PRIntervalTime startTime = PR_IntervalNow();     \
   if(gSkipPluginSafeCalls)                         \
     ret = fun;                                     \
   else                                             \
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -40,28 +40,28 @@
 
 #include "nsPluginTags.h"
 
 #include "prlink.h"
 #include "plstr.h"
 #include "nsIPluginInstanceOwner.h"
 #include "nsIDocument.h"
 #include "nsServiceManagerUtils.h"
-#include "nsIPrefService.h"
-#include "nsIPrefBranch.h"
 #include "nsPluginsDir.h"
 #include "nsPluginHost.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsIPlatformCharset.h"
 #include "nsICharsetConverterManager.h"
 #include "nsPluginLogging.h"
 #include "nsICategoryManager.h"
 #include "nsNPAPIPlugin.h"
 #include "mozilla/TimeStamp.h"
+#include "mozilla/Preferences.h"
 
+using namespace mozilla;
 using mozilla::TimeStamp;
 
 inline char* new_str(const char* str)
 {
   if (str == nsnull)
     return nsnull;
   
   char* result = new char[strlen(str) + 1];
@@ -383,32 +383,28 @@ nsPluginTag::RegisterWithCategoryManager
               mFileName.get(), aType == ePluginUnregister ? "yes" : "no"));
   
   nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID);
   if (!catMan)
     return;
   
   const char *contractId = "@mozilla.org/content/plugin/document-loader-factory;1";
   
-  nsCOMPtr<nsIPrefBranch> psvc(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  if (!psvc)
-    return; // NS_ERROR_OUT_OF_MEMORY
-  
   // A preference controls whether or not the full page plugin is disabled for
   // a particular type. The string must be in the form:
   //   type1,type2,type3,type4
   // Note: need an actual interface to control this and subsequent disabling 
   // (and other plugin host settings) so applications can reliably disable 
   // plugins - without relying on implementation details such as prefs/category
   // manager entries.
-  nsXPIDLCString overrideTypes;
   nsCAutoString overrideTypesFormatted;
   if (aType != ePluginUnregister) {
-    psvc->GetCharPref("plugin.disable_full_page_plugin_for_types", getter_Copies(overrideTypes));
     overrideTypesFormatted.Assign(',');
+    nsAdoptingCString overrideTypes =
+      Preferences::GetCString("plugin.disable_full_page_plugin_for_types");
     overrideTypesFormatted += overrideTypes;
     overrideTypesFormatted.Append(',');
   }
   
   nsACString::const_iterator start, end;
   for (PRUint32 i = 0; i < mMimeTypes.Length(); i++) {
     if (aType == ePluginUnregister) {
       nsXPIDLCString value;
@@ -509,13 +505,13 @@ bool nsPluginTag::Equals(nsPluginTag *aP
 void nsPluginTag::TryUnloadPlugin(bool inShutdown)
 {
   // We never want to send NPP_Shutdown to an in-process plugin unless
   // this process is shutting down.
   if (mLibrary && !inShutdown) {
     return;
   }
 
-  if (mEntryPoint) {
-    mEntryPoint->Shutdown();
-    mEntryPoint = nsnull;
+  if (mPlugin) {
+    mPlugin->Shutdown();
+    mPlugin = nsnull;
   }
 }
--- a/dom/plugins/base/nsPluginTags.h
+++ b/dom/plugins/base/nsPluginTags.h
@@ -103,17 +103,17 @@ public:
   nsRefPtr<nsPluginTag> mNext;
   nsPluginHost *mPluginHost;
   nsCString     mName; // UTF-8
   nsCString     mDescription; // UTF-8
   nsTArray<nsCString> mMimeTypes; // UTF-8
   nsTArray<nsCString> mMimeDescriptions; // UTF-8
   nsTArray<nsCString> mExtensions; // UTF-8
   PRLibrary     *mLibrary;
-  nsRefPtr<nsNPAPIPlugin> mEntryPoint;
+  nsRefPtr<nsNPAPIPlugin> mPlugin;
   bool          mIsJavaPlugin;
   bool          mIsNPRuntimeEnabledJavaPlugin;
   bool          mIsFlashPlugin;
   nsCString     mFileName; // UTF-8
   nsCString     mFullPath; // UTF-8
   nsCString     mVersion;  // UTF-8
   PRInt64       mLastModifiedTime;
   nsCOMPtr<nsITimer> mUnloadTimer;
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -36,18 +36,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifdef MOZ_WIDGET_GTK2
 #include <glib.h>
 #elif XP_MACOSX
 #include "PluginInterposeOSX.h"
 #include "PluginUtilsOSX.h"
-#include "nsIPrefService.h"
-#include "nsIPrefBranch.h"
 #endif
 #ifdef MOZ_WIDGET_QT
 #include <QtCore/QCoreApplication>
 #include <QtCore/QEventLoop>
 #endif
 
 #include "base/process_util.h"
 
@@ -1158,25 +1156,18 @@ PluginModuleParent::RecvPopCursor()
 #endif
 }
 
 bool
 PluginModuleParent::RecvGetNativeCursorsSupported(bool* supported)
 {
     PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
 #if defined(XP_MACOSX)
-    bool nativeCursorsSupported = false;
-    nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
-    if (prefs) {
-      if (NS_FAILED(prefs->GetBoolPref("dom.ipc.plugins.nativeCursorSupport",
-          &nativeCursorsSupported))) {
-        nativeCursorsSupported = false;
-      }
-    }
-    *supported = nativeCursorsSupported;
+    *supported =
+      Preferences::GetBool("dom.ipc.plugins.nativeCursorSupport", false);
     return true;
 #else
     NS_NOTREACHED(
         "PluginInstanceParent::RecvGetNativeCursorSupportLevel not implemented!");
     return false;
 #endif
 }
 
--- a/dom/power/PowerManager.cpp
+++ b/dom/power/PowerManager.cpp
@@ -30,16 +30,17 @@
  * 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 "mozilla/Hal.h"
 #include "PowerManager.h"
 #include "WakeLock.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIDOMWakeLockListener.h"
 #include "nsIPowerManagerService.h"
 #include "nsIPrincipal.h"
 #include "nsPIDOMWindow.h"
@@ -82,97 +83,92 @@ PowerManager::Shutdown()
     do_GetService(POWERMANAGERSERVICE_CONTRACTID);
   NS_ENSURE_STATE(pmService);
 
   // Remove ourself from the global notification list.
   pmService->RemoveWakeLockListener(this);
   return NS_OK;
 }
 
-nsresult
+bool
 PowerManager::CheckPermission()
 {
   if (nsContentUtils::IsCallerChrome()) {
-    return NS_OK;
+    return true;
   }
 
   nsCOMPtr<nsPIDOMWindow> win = do_QueryReferent(mWindow);
-  NS_ENSURE_STATE(win);
+  NS_ENSURE_TRUE(win, false);
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(win->GetExtantDocument());
-  NS_ENSURE_STATE(doc);
+  NS_ENSURE_TRUE(doc, false);
 
   nsCOMPtr<nsIURI> uri;
   doc->NodePrincipal()->GetURI(getter_AddRefs(uri));
 
   if (!nsContentUtils::URIIsChromeOrInPref(uri, "dom.power.whitelist")) {
-    return NS_ERROR_DOM_SECURITY_ERR;
+    return false;
   }
 
-  return NS_OK;
+  return true;
 }
 
 NS_IMETHODIMP
 PowerManager::Reboot()
 {
-  nsresult rv = CheckPermission();
-  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR);
 
   nsCOMPtr<nsIPowerManagerService> pmService =
     do_GetService(POWERMANAGERSERVICE_CONTRACTID);
   NS_ENSURE_STATE(pmService);
 
   pmService->Reboot();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PowerManager::PowerOff()
 {
-  nsresult rv = CheckPermission();
-  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR);
 
   nsCOMPtr<nsIPowerManagerService> pmService =
     do_GetService(POWERMANAGERSERVICE_CONTRACTID);
   NS_ENSURE_STATE(pmService);
 
   pmService->PowerOff();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PowerManager::AddWakeLockListener(nsIDOMMozWakeLockListener *aListener)
 {
-  nsresult rv = CheckPermission();
-  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR);
 
   // already added? bail out.
   if (mListeners.Contains(aListener))
     return NS_OK;
 
   mListeners.AppendElement(aListener);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PowerManager::RemoveWakeLockListener(nsIDOMMozWakeLockListener *aListener)
 {
-  nsresult rv = CheckPermission();
-  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR);
 
   mListeners.RemoveElement(aListener);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 PowerManager::GetWakeLockState(const nsAString &aTopic, nsAString &aState)
 {
-  nsresult rv = CheckPermission();
-  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR);
 
   nsCOMPtr<nsIPowerManagerService> pmService =
     do_GetService(POWERMANAGERSERVICE_CONTRACTID);
   NS_ENSURE_STATE(pmService);
 
   return pmService->GetWakeLockState(aTopic, aState);
 }
 
@@ -190,11 +186,56 @@ PowerManager::Callback(const nsAString &
   nsAutoTArray<nsCOMPtr<nsIDOMMozWakeLockListener>, 2> listeners(mListeners);
   for (PRUint32 i = 0; i < listeners.Length(); ++i) {
     listeners[i]->Callback(aTopic, aState);
   }
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+PowerManager::GetScreenEnabled(bool *aEnabled)
+{
+  if (!CheckPermission()) {
+    *aEnabled = true;
+    return NS_OK;
+  }
+
+  *aEnabled = hal::GetScreenEnabled();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PowerManager::SetScreenEnabled(bool aEnabled)
+{
+  NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR);
+
+  // TODO bug 707589: When the screen's state changes, all visible windows
+  // should fire a visibility change event.
+  hal::SetScreenEnabled(aEnabled);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PowerManager::GetScreenBrightness(double *aBrightness)
+{
+  if (!CheckPermission()) {
+    *aBrightness = 1;
+    return NS_OK;
+  }
+
+  *aBrightness = hal::GetScreenBrightness();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PowerManager::SetScreenBrightness(double aBrightness)
+{
+  NS_ENSURE_TRUE(CheckPermission(), NS_ERROR_DOM_SECURITY_ERR);
+
+  NS_ENSURE_TRUE(0 <= aBrightness && aBrightness <= 1, NS_ERROR_INVALID_ARG);
+  hal::SetScreenBrightness(aBrightness);
+  return NS_OK;
+}
+
 } // power
 } // dom
 } // mozilla
--- a/dom/power/PowerManager.h
+++ b/dom/power/PowerManager.h
@@ -59,17 +59,17 @@ public:
 
   PowerManager() {};
   virtual ~PowerManager() {};
 
   nsresult Init(nsIDOMWindow *aWindow);
   nsresult Shutdown();
 
 private:
-  nsresult CheckPermission();
+  bool CheckPermission();
 
   nsWeakPtr mWindow;
   nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener> > mListeners;
 };
 
 } // namespace power
 } // namespace dom
 } // namespace mozilla
--- a/dom/power/nsIDOMPowerManager.idl
+++ b/dom/power/nsIDOMPowerManager.idl
@@ -37,17 +37,17 @@
 
 #include "nsISupports.idl"
 
 interface nsIDOMMozWakeLockListener;
 
 /**
  * This interface implements navigator.mozPower
  */
-[scriptable, uuid(abf4b2b1-139d-4eff-998d-8f24616910ae)]
+[scriptable, uuid(4586bed1-cf78-4436-b503-88277d645b68)]
 interface nsIDOMMozPowerManager : nsISupports
 {
     void    powerOff();
     void    reboot();
 
     /**
      * The listeners are notified when a resource changes its lock state to:
      *  - unlocked
@@ -68,9 +68,32 @@ interface nsIDOMMozPowerManager : nsISup
      *    and it is visible.
      *
      *  - "locked-background" - at least one window holds the wake lock,
      *    but all of them are hidden.
      *
      * @param aTopic The resource name related to the wake lock.
      */
     DOMString getWakeLockState(in DOMString aTopic);
+
+    /**
+     * Is the device's screen currently enabled?  This attribute controls the
+     * device's screen, so setting it to false will turn off the screen.
+     */
+    attribute boolean screenEnabled;
+
+    /**
+     * How bright is the screen's backlight, on a scale from 0 (very dim) to 1
+     * (full brightness)?  Setting this attribute modifies the screen's
+     * brightness.
+     *
+     * You can read and write this attribute even when the screen is disabled,
+     * but the backlight is off while the screen is disabled.
+     *
+     * If you write a value of X into this attribute, the attribute may not have
+     * the same value X when you later read it.  Most screens don't support as
+     * many different brightness levels as there are doubles between 0 and 1, so
+     * we may reduce the value's precision before storing it.
+     *
+     * @throw NS_ERROR_INVALID_ARG if brightness is not in the range [0, 1].
+     */
+    attribute double screenBrightness;
 };
--- a/dom/src/geolocation/nsGeolocation.cpp
+++ b/dom/src/geolocation/nsGeolocation.cpp
@@ -61,18 +61,16 @@
 #include "nsComponentManagerUtils.h"
 #include "nsICategoryManager.h"
 #include "nsISupportsPrimitives.h"
 #include "nsServiceManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsIURI.h"
 #include "nsIPermissionManager.h"
 #include "nsIObserverService.h"
-#include "nsIPrefService.h"
-#include "nsIPrefBranch.h"
 #include "nsIJSContextStack.h"
 #include "nsThreadUtils.h"
 #include "mozilla/Services.h"
 #include "mozilla/unused.h"
 #include "mozilla/Preferences.h"
 
 #include <math.h>
 
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -56,17 +56,16 @@ using mozilla::dom::StorageChild;
 #include "nsEscape.h"
 #include "nsContentUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIPrincipal.h"
 #include "nsIURI.h"
 #include "nsReadableUtils.h"
 #include "nsIObserverService.h"
 #include "nsNetUtil.h"
-#include "nsIPrefBranch.h"
 #include "nsICookiePermission.h"
 #include "nsIPermission.h"
 #include "nsIPermissionManager.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsIJSContextStack.h"
 #include "nsIPrivateBrowsingService.h"
 #include "nsDOMString.h"
--- a/dom/system/nsDeviceSensors.cpp
+++ b/dom/system/nsDeviceSensors.cpp
@@ -43,17 +43,18 @@
 #include "nsIDOMEvent.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIServiceManager.h"
 #include "nsIPrivateDOMEvent.h"
 #include "nsIServiceManager.h"
-#include "nsIPrefService.h"
+
+#include "mozilla/Preferences.h"
 
 using namespace mozilla;
 using namespace hal;
 
 // also see sDefaultSensorHint in mobile/android/base/GeckoAppShell.java
 #define DEFAULT_SENSOR_POLL 100
 
 static const nsTArray<nsIDOMWindow*>::index_type NoIndex =
@@ -117,27 +118,19 @@ NS_IMETHODIMP nsDeviceSensorData::GetZ(d
   NS_ENSURE_ARG_POINTER(aZ);
   *aZ = mZ;
   return NS_OK;
 }
 
 NS_IMPL_ISUPPORTS1(nsDeviceSensors, nsIDeviceSensors)
 
 nsDeviceSensors::nsDeviceSensors()
-: mEnabled(true)
 {
   mLastDOMMotionEventTime = TimeStamp::Now();
-
-  nsCOMPtr<nsIPrefBranch> prefSrv = do_GetService(NS_PREFSERVICE_CONTRACTID);
-  if (prefSrv) {
-    bool bvalue;
-    nsresult rv = prefSrv->GetBoolPref("device.motion.enabled", &bvalue);
-    if (NS_SUCCEEDED(rv) && bvalue == false)
-      mEnabled = false;
-  }
+  mEnabled = Preferences::GetBool("device.motion.enabled", true);
 
   for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
     nsTArray<nsIDOMWindow*> *windows = new nsTArray<nsIDOMWindow*>();
     mWindowListeners.AppendElement(windows);
   }
 
   mLastDOMMotionEventTime = TimeStamp::Now();
 }
--- a/dom/system/unix/MaemoLocationProvider.cpp
+++ b/dom/system/unix/MaemoLocationProvider.cpp
@@ -36,20 +36,21 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include <stdio.h>
 #include <math.h>
 #include "nsGeoPosition.h"
 #include "MaemoLocationProvider.h"
 #include "nsIClassInfo.h"
 #include "nsDOMClassInfoID.h"
-#include "nsIPrefService.h"
-#include "nsIPrefBranch.h"
 #include "nsIServiceManager.h"
 #include "nsServiceManagerUtils.h"
+#include "mozilla/Preferences.h"
+
+using namespace mozilla;
 
 NS_IMPL_ISUPPORTS2(MaemoLocationProvider, nsIGeolocationProvider, nsITimerCallback)
 
 MaemoLocationProvider::MaemoLocationProvider() :
   mLocationChanged(0),
   mControlError(0),
   mDeviceDisconnected(0),
   mControlStopped(0),
@@ -187,41 +188,41 @@ MaemoLocationProvider::StartDevice()
                                          G_CALLBACK(DeviceDisconnected), this);
   return NS_OK;
 }
 
 NS_IMETHODIMP MaemoLocationProvider::Startup()
 {
   nsresult rv(NS_OK);
 
-  nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
-  if (!prefs)
-    return NS_ERROR_FAILURE;
-
   rv = StartControl();
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = StartDevice();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  prefs->GetBoolPref("geo.herror.ignore.big", &mIgnoreBigHErr);
+  mIgnoreBigHErr =
+    Preferences::GetBool("geo.herror.ignore.big", mIgnoreBigHErr);
 
-  if (mIgnoreBigHErr)
-    prefs->GetIntPref("geo.herror.max.value", &mMaxHErr);
+  if (mIgnoreBigHErr) {
+    mMaxHErr = Preferences::GetInt("geo.herror.max.value", mMaxHErr);
+  }
 
-  prefs->GetBoolPref("geo.verror.ignore.big", &mIgnoreBigVErr);
+  mIgnoreBigVErr =
+    Preferences::GetBool("geo.verror.ignore.big", mIgnoreBigVErr);
 
-  if (mIgnoreBigVErr)
-    prefs->GetIntPref("geo.verror.max.value", &mMaxVErr);
+  if (mIgnoreBigVErr) {
+    mMaxVErr = Preferences::GetInt("geo.verror.max.value", mMaxVErr);
+  }
 
   if (mUpdateTimer)
     return NS_OK;
 
-  PRInt32 update = 0; //0 second no timer created
-  prefs->GetIntPref("geo.default.update", &update);
+  // 0 second no timer created
+  PRInt32 update = Preferences::GetInt("geo.default.update", 0);
 
   if (!update)
     return NS_OK;
 
   mUpdateTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
 
   if (NS_FAILED(rv))
     return NS_ERROR_FAILURE;
--- a/dom/workers/test/test_errorPropagation.html
+++ b/dom/workers/test/test_errorPropagation.html
@@ -11,17 +11,17 @@
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   </head>
   <body>
     <iframe id="workerFrame" src="errorPropagation_iframe.html"
             onload="workerFrameLoaded();"></iframe>
     <script type="text/javascript">
       const workerCount = 3;
 
-      const errorMessage = "expectedError";
+      const errorMessage = "Error: expectedError";
       const errorFilename = "http://mochi.test:8888/tests/dom/workers/test/" +
                             "errorPropagation_worker.js";
       const errorLineno = 48;
 
       var workerFrame;
 
       scopeErrorCount = 0;
       workerErrorCount = 0;
--- a/dom/workers/test/test_newError.html
+++ b/dom/workers/test/test_newError.html
@@ -15,17 +15,17 @@
   var worker = new Worker("newError_worker.js");
 
   worker.onmessage = function(event) {
     ok(false, "Shouldn't get a message!");
     SimpleTest.finish();
   }
 
   worker.onerror = function(event) {
-    is(event.message, "foo!", "Got wrong error message!");
+    is(event.message, "Error: foo!", "Got wrong error message!");
     event.preventDefault();
     SimpleTest.finish();
   }
 
   SimpleTest.waitForExplicitFinish();
 
 </script>
 </pre>
--- a/dom/workers/test/test_recursiveOnerror.html
+++ b/dom/workers/test/test_recursiveOnerror.html
@@ -9,18 +9,18 @@
     </script>
     <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   </head>
   <body>
     <script type="text/javascript">
       const filename = "http://mochi.test:8888/tests/dom/workers/test/" +
                        "recursiveOnerror_worker.js";
       const errors = [
-        { message: "2", lineno: 6 },
-        { message: "1", lineno: 10 }
+        { message: "Error: 2", lineno: 6 },
+        { message: "Error: 1", lineno: 10 }
       ]
 
       var errorCount = 0;
 
       var worker = new Worker("recursiveOnerror_worker.js");
       worker.postMessage("go");
 
       worker.onerror = function(event) {
--- a/editor/composer/src/nsComposerDocumentCommands.cpp
+++ b/editor/composer/src/nsComposerDocumentCommands.cpp
@@ -58,16 +58,17 @@
 #include "nsCOMPtr.h"
 
 #include "nsComposerCommands.h"
 #include "nsICommandParams.h"
 #include "nsCRT.h"
 
 //defines
 #define STATE_ENABLED  "state_enabled"
+#define STATE_ALL "state_all"
 #define STATE_ATTRIBUTE "state_attribute"
 #define STATE_DATA "state_data"
 
 static
 nsresult
 GetPresContextFromEditor(nsIEditor *aEditor, nsPresContext **aResult)
 {
   NS_ENSURE_ARG_POINTER(aResult);
@@ -373,17 +374,17 @@ nsSetDocumentStateCommand::GetCommandSta
   if (!nsCRT::strcmp(aCommandName, "cmd_setDocumentUseCSS"))
   {
     NS_ENSURE_ARG_POINTER(aParams);
     nsCOMPtr<nsIHTMLEditor> htmleditor = do_QueryInterface(refCon);
     NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG);
 
     bool isCSS;
     htmleditor->GetIsCSSEnabled(&isCSS);
-    return aParams->SetBooleanValue(STATE_ATTRIBUTE, isCSS);
+    return aParams->SetBooleanValue(STATE_ALL, isCSS);
   }
 
   if (!nsCRT::strcmp(aCommandName, "cmd_insertBrOnReturn"))
   {
     NS_ENSURE_ARG_POINTER(aParams);
     nsCOMPtr<nsIHTMLEditor> htmleditor = do_QueryInterface(refCon);
     NS_ENSURE_TRUE(htmleditor, NS_ERROR_INVALID_ARG);
 
--- a/editor/composer/test/Makefile.in
+++ b/editor/composer/test/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES = \
 		test_bug348497.html \
 		test_bug384147.html \
 		test_bug389350.html \
 		test_bug519928.html \
 		bug678842_subframe.html \
+		test_bug738440.html \
 		$(NULL)
 
 _CHROME_TEST_FILES = \
 		test_bug434998.xul \
 		test_bug338427.html \
 		test_bug678842.html \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/editor/composer/test/test_bug738440.html
@@ -0,0 +1,37 @@
+<!doctype html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=738440
+-->
+<title>Test for Bug 738440</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css" />
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=738440">Mozilla Bug 738440</a>
+<div contenteditable></div>
+<script>
+
+/** Test for Bug 738440 **/
+document.execCommand("stylewithcss", false, "true");
+is(document.queryCommandState("stylewithcss"), true,
+   "setting stylewithcss to true should cause its state to be true");
+is(document.queryCommandState("usecss"), false,
+   "usecss state should always be false");
+
+document.execCommand("stylewithcss", false, "false");
+is(document.queryCommandState("stylewithcss"), false,
+   "setting stylewithcss to false should cause its state to be false");
+is(document.queryCommandState("usecss"), false,
+   "usecss state should always be false");
+
+document.execCommand("usecss", false, "true");
+is(document.queryCommandState("stylewithcss"), false,
+   "setting usecss to true should cause stylewithcss state to be false");
+is(document.queryCommandState("usecss"), false,
+   "usecss state should always be false");
+
+document.execCommand("usecss", false, "false");
+is(document.queryCommandState("stylewithcss"), true,
+   "setting usecss to false should cause stylewithcss state to be true");
+is(document.queryCommandState("usecss"), false,
+   "usecss state should always be false");
+
+</script>
--- a/editor/libeditor/base/crashtests/633709.xhtml
+++ b/editor/libeditor/base/crashtests/633709.xhtml
@@ -4,22 +4,32 @@
 
 <script id="s">
 <![CDATA[
 
 function boom()
 {
   document.getElementById("i").focus();
 
+  try { document.execCommand("stylewithcss", false, "true") } catch(e) { }
   try { document.execCommand("inserthtml", false, "<x>X</x>"); } catch(e) { }
   try { document.execCommand("underline", false, null); } catch(e) { }
   try { document.execCommand("justifyfull", false, null); } catch(e) { }
   try { document.execCommand("underline", false, null); } catch(e) { }
   try { document.execCommand("insertParagraph", false, null); } catch(e) { }
   try { document.execCommand("delete", false, null); } catch(e) { }
+
+  try { document.execCommand("stylewithcss", false, "false") } catch(e) { }
+  try { document.execCommand("inserthtml", false, "<x>X</x>"); } catch(e) { }
+  try { document.execCommand("underline", false, null); } catch(e) { }
+  try { document.execCommand("justifyfull", false, null); } catch(e) { }
+  try { document.execCommand("underline", false, null); } catch(e) { }
+  try { document.execCommand("insertParagraph", false, null); } catch(e) { }
+  try { document.execCommand("delete", false, null); } catch(e) { }
+
   document.documentElement.removeAttribute("class");
 }
 
 setTimeout(boom, 10);
 
 ]]>
 </script>
 
--- a/editor/libeditor/base/crashtests/crashtests.list
+++ b/editor/libeditor/base/crashtests/crashtests.list
@@ -1,12 +1,12 @@
 load 336104.html
 load 382527-1.html
 load 402172-1.html
 load 407079-1.html
 load 407256-1.html
 load 430624-1.html
 load 459613.html
 load 475132-1.xhtml
-asserts-if(!Android,1) load 633709.xhtml # Bug 695364
+asserts-if(!Android,2) load 633709.xhtml # Bug 695364 and bug 671153
 asserts-if(!Android,6) load 636074-1.html # Bug 439258, charged to the wrong test due to bug 635550
 load 713427-1.html
 load 713427-2.xhtml
--- a/editor/libeditor/html/nsHTMLCSSUtils.cpp
+++ b/editor/libeditor/html/nsHTMLCSSUtils.cpp
@@ -294,17 +294,17 @@ const nsHTMLCSSUtils::CSSEquivTable tabl
 const nsHTMLCSSUtils::CSSEquivTable hrAlignEquivTable[] = {
   { nsHTMLCSSUtils::eCSSEditableProperty_margin_left, ProcessMarginLeftValue, nsnull, nsnull, nsnull, true, false },
   { nsHTMLCSSUtils::eCSSEditableProperty_margin_right, ProcessMarginRightValue, nsnull, nsnull, nsnull, true, false },
   { nsHTMLCSSUtils::eCSSEditableProperty_NONE, 0 }
 };
 
 nsHTMLCSSUtils::nsHTMLCSSUtils(nsHTMLEditor* aEditor)
   : mHTMLEditor(aEditor)
-  , mIsCSSPrefChecked(false)
+  , mIsCSSPrefChecked(true)
 {
   // let's retrieve the value of the "CSS editing" pref
   mIsCSSPrefChecked = Preferences::GetBool("editor.use_css", mIsCSSPrefChecked);
 }
 
 nsHTMLCSSUtils::~nsHTMLCSSUtils()
 {
 }
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -1619,16 +1619,19 @@ NS_IMETHODIMP nsHTMLEditor::PasteTransfe
                                 nsnull, 0, true);
 }
 
 // 
 // HTML PasteNoFormatting. Ignore any HTML styles and formating in paste source
 //
 NS_IMETHODIMP nsHTMLEditor::PasteNoFormatting(PRInt32 aSelectionType)
 {
+  if (!FireClipboardEvent(NS_PASTE))
+    return NS_OK;
+
   ForceCompositionEnd();
 
   // Get Clipboard Service
   nsresult rv;
   nsCOMPtr<nsIClipboard> clipboard(do_GetService("@mozilla.org/widget/clipboard;1", &rv));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get the nsITransferable interface for getting the data from the clipboard.
--- a/editor/libeditor/html/tests/Makefile.in
+++ b/editor/libeditor/html/tests/Makefile.in
@@ -97,16 +97,17 @@ include $(topsrcdir)/config/rules.mk
 		test_CF_HTML_clipboard.html \
 		test_contenteditable_focus.html \
 		test_dom_input_event_on_htmleditor.html \
 		test_htmleditor_keyevent_handling.html \
 		test_keypress_untrusted_event.html \
 		test_select_all_without_body.html \
 		file_select_all_without_body.html \
 		test_root_element_replacement.html \
+		test_bug738366.html \
 		$(NULL)
 
 ifneq (mobile,$(MOZ_BUILD_APP))
 _TEST_FILES +=  test_spellcheck_pref.html \
 		$(NULL)
 endif
 
 _DATA_FILES = \
--- a/editor/libeditor/html/tests/test_bug290026.html
+++ b/editor/libeditor/html/tests/test_bug290026.html
@@ -20,17 +20,17 @@ https://bugzilla.mozilla.org/show_bug.cg
 /** Test for Bug 290026 **/
 SimpleTest.waitForExplicitFinish();
 
 var editor = document.getElementById("editor");
 editor.innerHTML = '<p></p><ul><li>Item 1</li><li>Item 2</li></ul><p></p>';
 editor.focus();
 
 addLoadEvent(function() {
-
+  document.execCommand("stylewithcss", false, "true");
   var sel = window.getSelection();
   sel.removeAllRanges();
   var lis = document.getElementsByTagName("li");
   var range = document.createRange();
   range.setStart(lis[0], 0);
   range.setEnd(lis[1], lis[1].childNodes.length);
   sel.addRange(range);
   document.execCommand("indent", false, false);
--- a/editor/libeditor/html/tests/test_bug410986.html
+++ b/editor/libeditor/html/tests/test_bug410986.html
@@ -16,46 +16,53 @@ https://bugzilla.mozilla.org/show_bug.cg
   <div id="contents"><span style="color: green;">green text</span></div>
   <div id="editor" contenteditable="true"></div>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 410986 **/
 
+var gPasteEvents = 0;
+document.getElementById("editor").addEventListener("paste", function() {
+  ++gPasteEvents;
+}, false);
+
 SimpleTest.waitForExplicitFinish();
 SimpleTest.waitForFocus(function() {
   getSelection().selectAllChildren(document.getElementById("contents"));
   SimpleTest.waitForClipboard("green text",
     function() {
       synthesizeKey("C", {accelKey: true});
     },
     function() {
       var ed = document.getElementById("editor");
       ed.focus();
       if (navigator.platform.indexOf("Mac") >= 0) {
         synthesizeKey("V", {accelKey: true, shiftKey: true, altKey: true});
       } else {
         synthesizeKey("V", {accelKey: true, shiftKey: true});
       }
       is(ed.innerHTML, "green text", "Content should be pasted in plaintext format");
+      is(gPasteEvents, 1, "One paste event must be fired");
 
       ed.innerHTML = "";
       ed.blur();
       getSelection().selectAllChildren(document.getElementById("contents"));
       SimpleTest.waitForClipboard("green text",
         function() {
           synthesizeKey("C", {accelKey: true});
         },
         function() {
           var ed = document.getElementById("editor");
           ed.focus();
           synthesizeKey("V", {accelKey: true});
           isnot(ed.innerHTML.indexOf("<span style=\"color: green;\">green text</span>"), -1,
                 "Content should be pasted in HTML format");
+          is(gPasteEvents, 2, "Two paste events must be fired");
 
           SimpleTest.finish();
         },
         function() {
           ok(false, "Failed to copy the second item to the clipboard");
           SimpleTest.finish();
         }
       );
--- a/editor/libeditor/html/tests/test_bug442186.html
+++ b/editor/libeditor/html/tests/test_bug442186.html
@@ -49,16 +49,18 @@ function justify(textNode, pos) {
   range.setEnd(textNode, pos);
   sel.addRange(range);
 
   // align
   document.execCommand("justifyright", false, null);
 }
 
 function runTests() {
+  document.execCommand("stylewithcss", false, "true");
+
   const test1 = document.getElementById("test1");
   const test2 = document.getElementById("test2");
   const test3 = document.getElementById("test3");
 
   // #test1: two <div> containers
   const line1 = test1.querySelector("div").firstChild;
   test1.focus();
   justify(line1);
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/html/tests/test_bug738366.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=738366
+-->
+<title>Test for Bug 738366</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=738366">Mozilla Bug 738366</a>
+<div id="display" contenteditable>foobarbaz</div>
+<script>
+/** Test for Bug 738366 **/
+
+getSelection().collapse(document.getElementById("display").firstChild, 3);
+getSelection().extend(document.getElementById("display").firstChild, 6);
+document.execCommand("bold");
+is(document.getElementById("display").innerHTML, "foo<b>bar</b>baz",
+   "styleWithCSS must default to false");
+document.execCommand("stylewithcss", false, "true");
+document.execCommand("bold");
+document.execCommand("bold");
+is(document.getElementById("display").innerHTML,
+   'foo<span style="font-weight: bold;">bar</span>baz',
+   "styleWithCSS must be settable to true");
+</script>
--- a/editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html
+++ b/editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html
@@ -26,16 +26,17 @@ SimpleTest.waitForFocus(runTests, window
 var htmlEditor = document.getElementById("htmlEditor");
 
 const kIsMac = navigator.platform.indexOf("Mac") == 0;
 const kIsWin = navigator.platform.indexOf("Win") == 0;
 const kIsLinux = navigator.platform.indexOf("Linux") == 0 || navigator.platform.indexOf("SunOS") == 0 ;
 
 function runTests()
 {
+  document.execCommand("stylewithcss", false, "true");
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
 
   var fm = Components.classes["@mozilla.org/focus-manager;1"].
     getService(Components.interfaces.nsIFocusManager);
 
   var capturingPhase = { fired: false, prevented: false };
   var bubblingPhase = { fired: false, prevented: false };
 
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -824,16 +824,21 @@ public:
    * surface.
    */
   static TemporaryRef<DataSourceSurface>
     CreateDataSourceSurfaceFromData(unsigned char *aData, int32_t aStride,
                                     const IntSize &aSize, SurfaceFormat aFormat);
 
 #ifdef WIN32
   static TemporaryRef<DrawTarget> CreateDrawTargetForD3D10Texture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
+  static TemporaryRef<DrawTarget>
+    CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
+                                         ID3D10Texture2D *aTextureB,
+                                         SurfaceFormat aFormat);
+
   static void SetDirect3D10Device(ID3D10Device1 *aDevice);
   static ID3D10Device1 *GetDirect3D10Device();
 
   static TemporaryRef<GlyphRenderingOptions>
     CreateDWriteGlyphRenderingOptions(IDWriteRenderingParams *aParams);
 
 private:
   static ID3D10Device1 *mD3D10Device;
new file mode 100644
--- /dev/null
+++ b/gfx/2d/DrawTargetDual.cpp
@@ -0,0 +1,213 @@
+/* -*- Mode: C++; tab-width: 20; 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 Corporation code.
+  *
+  * The Initial Developer of the Original Code is Mozilla Foundation.
+  * Portions created by the Initial Developer are Copyright (C) 2011
+  * the Initial Developer. All Rights Reserved.
+  *
+  * Contributor(s):
+  *   Bas Schouten <bschouten@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 ***** */
+     
+#include "DrawTargetDual.h"
+#include "Tools.h"
+
+namespace mozilla {
+namespace gfx {
+
+class DualSurface
+{
+public:
+  inline DualSurface(SourceSurface *aSurface)
+  {
+    if (aSurface->GetType() != SURFACE_DUAL_DT) {
+      mA = mB = aSurface;
+      return;
+    }
+
+    SourceSurfaceDual *ssDual =
+      static_cast<SourceSurfaceDual*>(aSurface);
+    mA = ssDual->mA;
+    mB = ssDual->mB;
+  }
+
+  SourceSurface *mA;
+  SourceSurface *mB;
+};
+
+/* This only needs to split patterns up for SurfacePatterns. Only in that
+ * case can we be dealing with a 'dual' source (SourceSurfaceDual) and do
+ * we need to pass separate patterns into our destination DrawTargets.
+ */
+class DualPattern
+{
+public:
+  inline DualPattern(const Pattern &aPattern)
+    : mPatternsInitialized(false)
+  {
+    if (aPattern.GetType() != PATTERN_SURFACE) {
+      mA = mB = &aPattern;
+      return;
+    }
+
+    const SurfacePattern *surfPat =
+      static_cast<const SurfacePattern*>(&aPattern);
+
+    if (surfPat->mSurface->GetType() != SURFACE_DUAL_DT) {
+      mA = mB = &aPattern;
+      return;
+    }
+
+    const SourceSurfaceDual *ssDual =
+      static_cast<const SourceSurfaceDual*>(surfPat->mSurface.get());
+    mA = new (mSurfPatA.addr()) SurfacePattern(ssDual->mA, surfPat->mExtendMode,
+                                               surfPat->mMatrix, surfPat->mFilter);
+    mB = new (mSurfPatB.addr()) SurfacePattern(ssDual->mB, surfPat->mExtendMode,
+                                               surfPat->mMatrix, surfPat->mFilter);
+    mPatternsInitialized = true;
+  }
+
+  inline ~DualPattern()
+  {
+    if (mPatternsInitialized) {
+      mA->~Pattern();
+      mB->~Pattern();
+    }
+  }
+
+  ClassStorage<SurfacePattern> mSurfPatA;
+  ClassStorage<SurfacePattern> mSurfPatB;
+
+  const Pattern *mA;
+  const Pattern *mB;
+
+  bool mPatternsInitialized;
+};
+
+void
+DrawTargetDual::DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect &aSource,
+                            const DrawSurfaceOptions &aSurfOptions, const DrawOptions &aOptions)
+{
+  DualSurface surface(aSurface);
+  mA->DrawSurface(surface.mA, aDest, aSource, aSurfOptions, aOptions);
+  mB->DrawSurface(surface.mB, aDest, aSource, aSurfOptions, aOptions);
+}
+
+void
+DrawTargetDual::DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest,
+                                      const Color &aColor, const Point &aOffset,
+                                      Float aSigma, CompositionOp aOp)
+{
+  DualSurface surface(aSurface);
+  mA->DrawSurfaceWithShadow(surface.mA, aDest, aColor, aOffset, aSigma, aOp);
+  mB->DrawSurfaceWithShadow(surface.mB, aDest, aColor, aOffset, aSigma, aOp);
+}
+
+void
+DrawTargetDual::CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect,
+                            const IntPoint &aDestination)
+{
+  DualSurface surface(aSurface);
+  mA->CopySurface(surface.mA, aSourceRect, aDestination);
+  mB->CopySurface(surface.mB, aSourceRect, aDestination);
+}
+
+void
+DrawTargetDual::FillRect(const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions)
+{
+  DualPattern pattern(aPattern);
+  mA->FillRect(aRect, *pattern.mA, aOptions);
+  mB->FillRect(aRect, *pattern.mB, aOptions);
+}
+
+void
+DrawTargetDual::StrokeRect(const Rect &aRect, const Pattern &aPattern,
+                           const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions)
+{
+  DualPattern pattern(aPattern);
+  mA->StrokeRect(aRect, *pattern.mA, aStrokeOptions, aOptions);
+  mB->StrokeRect(aRect, *pattern.mB, aStrokeOptions, aOptions);
+}
+
+void
+DrawTargetDual::StrokeLine(const Point &aStart, const Point &aEnd, const Pattern &aPattern,
+                           const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions)
+{
+  DualPattern pattern(aPattern);
+  mA->StrokeLine(aStart, aEnd, *pattern.mA, aStrokeOptions, aOptions);
+  mB->StrokeLine(aStart, aEnd, *pattern.mB, aStrokeOptions, aOptions);
+}
+
+void
+DrawTargetDual::Stroke(const Path *aPath, const Pattern &aPattern,
+                       const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions)
+{
+  DualPattern pattern(aPattern);
+  mA->Stroke(aPath, *pattern.mA, aStrokeOptions, aOptions);
+  mB->Stroke(aPath, *pattern.mB, aStrokeOptions, aOptions);
+}
+
+void
+DrawTargetDual::Fill(const Path *aPath, const Pattern &aPattern, const DrawOptions &aOptions)
+{
+  DualPattern pattern(aPattern);
+  mA->Fill(aPath, *pattern.mA, aOptions);
+  mB->Fill(aPath, *pattern.mB, aOptions);
+}
+
+void
+DrawTargetDual::FillGlyphs(ScaledFont *aScaledFont, const GlyphBuffer &aBuffer,
+                           const Pattern &aPattern, const DrawOptions &aOptions,
+                           const GlyphRenderingOptions *aRenderingOptions)
+{
+  DualPattern pattern(aPattern);
+  mA->FillGlyphs(aScaledFont, aBuffer, *pattern.mA, aOptions, aRenderingOptions);
+  mB->FillGlyphs(aScaledFont, aBuffer, *pattern.mB, aOptions, aRenderingOptions);
+}
+
+void
+DrawTargetDual::Mask(const Pattern &aSource, const Pattern &aMask, const DrawOptions &aOptions)
+{
+  DualPattern source(aSource);
+  DualPattern mask(aMask);
+  mA->Mask(*source.mA, *mask.mA, aOptions);
+  mB->Mask(*source.mB, *mask.mB, aOptions);
+}
+
+TemporaryRef<DrawTarget>
+DrawTargetDual::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
+{
+  RefPtr<DrawTarget> dtA = mA->CreateSimilarDrawTarget(aSize, aFormat);
+  RefPtr<DrawTarget> dtB = mB->CreateSimilarDrawTarget(aSize, aFormat);
+
+  return new DrawTargetDual(dtA, dtB);
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/gfx/2d/DrawTargetDual.h
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 20; 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 Corporation code.
+  *
+  * The Initial Developer of the Original Code is Mozilla Foundation.
+  * Portions created by the Initial Developer are Copyright (C) 2011
+  * the Initial Developer. All Rights Reserved.
+  *
+  * Contributor(s):
+  *   Bas Schouten <bschouten@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 ***** */
+     
+#ifndef MOZILLA_GFX_DRAWTARGETDUAL_H_
+#define MOZILLA_GFX_DRAWTARGETDUAL_H_
+     
+#include <vector>
+#include <sstream>
+
+#include "SourceSurfaceDual.h"
+     
+#include "2D.h"
+     
+namespace mozilla {
+namespace gfx {
+     
+#define FORWARD_FUNCTION(funcName) \
+  virtual void funcName() { mA->funcName(); mB->funcName(); }
+#define FORWARD_FUNCTION1(funcName, var1Type, var1Name) \
+  virtual void funcName(var1Type var1Name) { mA->funcName(var1Name); mB->funcName(var1Name); }
+
+/* This is a special type of DrawTarget. It duplicates all drawing calls
+ * accross two drawtargets. An exception to this is when a snapshot of another
+ * dual DrawTarget is used as the source for any surface data. In this case
+ * the snapshot of the first source DrawTarget is used as a source for the call
+ * to the first destination DrawTarget (mA) and the snapshot of the second
+ * source DrawTarget is used at the source for the second destination
+ * DrawTarget (mB). This class facilitates black-background/white-background
+ * drawing for per-component alpha extraction for backends which do not support
+ * native component alpha.
+ */
+class DrawTargetDual : public DrawTarget
+{
+public:
+  DrawTargetDual(DrawTarget *aA, DrawTarget *aB)
+    : mA(aA)
+    , mB(aB)
+  { 
+    mFormat = aA->GetFormat();
+  }
+     
+  virtual BackendType GetType() const { return mA->GetType(); }
+  virtual TemporaryRef<SourceSurface> Snapshot() { return new SourceSurfaceDual(mA, mB); }
+  virtual IntSize GetSize() { return mA->GetSize(); }
+     
+  FORWARD_FUNCTION(Flush)
+  FORWARD_FUNCTION1(PushClip, const Path *, aPath)
+  FORWARD_FUNCTION1(PushClipRect, const Rect &, aRect)
+  FORWARD_FUNCTION(PopClip)
+  FORWARD_FUNCTION1(ClearRect, const Rect &, aRect)
+
+  virtual void SetTransform(const Matrix &aTransform) {
+    mTransform = aTransform;
+    mA->SetTransform(aTransform);
+    mB->SetTransform(aTransform);
+  }
+
+  virtual void DrawSurface(SourceSurface *aSurface, const Rect &aDest, const Rect & aSource,
+                           const DrawSurfaceOptions &aSurfOptions, const DrawOptions &aOptions);
+  
+  virtual void DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest,
+                                     const Color &aColor, const Point &aOffset,
+                                     Float aSigma, CompositionOp aOp);
+
+  virtual void CopySurface(SourceSurface *aSurface, const IntRect &aSourceRect,
+                           const IntPoint &aDestination);
+
+  virtual void FillRect(const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions);
+
+  virtual void StrokeRect(const Rect &aRect, const Pattern &aPattern,
+                          const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions);
+
+  virtual void StrokeLine(const Point &aStart, const Point &aEnd, const Pattern &aPattern,
+                          const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions);
+
+  virtual void Stroke(const Path *aPath, const Pattern &aPattern,
+                      const StrokeOptions &aStrokeOptions, const DrawOptions &aOptions);
+
+  virtual void Fill(const Path *aPath, const Pattern &aPattern, const DrawOptions &aOptions);
+
+  virtual void FillGlyphs(ScaledFont *aScaledFont, const GlyphBuffer &aBuffer,
+                          const Pattern &aPattern, const DrawOptions &aOptions,
+                          const GlyphRenderingOptions *aRenderingOptions);
+  
+  virtual void Mask(const Pattern &aSource, const Pattern &aMask, const DrawOptions &aOptions);
+     
+  virtual TemporaryRef<SourceSurface>
+    CreateSourceSurfaceFromData(unsigned char *aData,
+                                const IntSize &aSize,
+                                int32_t aStride,
+                                SurfaceFormat aFormat) const
+  {
+    return mA->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat);
+  }
+     
+  virtual TemporaryRef<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const
+  {
+    return mA->OptimizeSourceSurface(aSurface);
+  }
+     
+  virtual TemporaryRef<SourceSurface>
+    CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
+  {
+    return mA->CreateSourceSurfaceFromNativeSurface(aSurface);
+  }
+     
+  virtual TemporaryRef<DrawTarget>
+    CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const;
+     
+  virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const
+  {
+    return mA->CreatePathBuilder(aFillRule);
+  }
+     
+  virtual TemporaryRef<GradientStops>
+    CreateGradientStops(GradientStop *aStops,
+                        uint32_t aNumStops,
+                        ExtendMode aExtendMode = EXTEND_CLAMP) const
+  {
+    return mA->CreateGradientStops(aStops, aNumStops, aExtendMode);
+  }
+     
+  virtual void *GetNativeSurface(NativeSurfaceType aType)
+  {
+    return NULL;
+  }
+     
+private:
+  RefPtr<DrawTarget> mA;
+  RefPtr<DrawTarget> mB;
+};
+     
+}
+}
+     
+#endif /* MOZILLA_GFX_DRAWTARGETDUAL_H_ */ 
\ No newline at end of file
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -62,16 +62,17 @@
 #endif
 
 #ifdef WIN32
 #include "DrawTargetD2D.h"
 #include "ScaledFontDWrite.h"
 #include <d3d10_1.h>
 #endif
 
+#include "DrawTargetDual.h"
 
 #include "Logging.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo *sGFX2DLog = PR_NewLogModule("gfx2d");
 #endif
 
 namespace mozilla {
@@ -227,16 +228,42 @@ Factory::CreateDrawTargetForD3D10Texture
   }
 
   gfxWarning() << "Failed to create draw target for D3D10 texture.";
 
   // Failed
   return NULL;
 }
 
+TemporaryRef<DrawTarget>
+Factory::CreateDualDrawTargetForD3D10Textures(ID3D10Texture2D *aTextureA,
+                                              ID3D10Texture2D *aTextureB,
+                                              SurfaceFormat aFormat)
+{
+  RefPtr<DrawTargetD2D> newTargetA;
+  RefPtr<DrawTargetD2D> newTargetB;
+
+  newTargetA = new DrawTargetD2D();
+  if (!newTargetA->Init(aTextureA, aFormat)) {
+    gfxWarning() << "Failed to create draw target for D3D10 texture.";
+    return NULL;
+  }
+
+  newTargetB = new DrawTargetD2D();
+  if (!newTargetB->Init(aTextureB, aFormat)) {
+    gfxWarning() << "Failed to create draw target for D3D10 texture.";
+    return NULL;
+  }
+
+  RefPtr<DrawTarget> newTarget =
+    new DrawTargetDual(newTargetA, newTargetB);
+
+  return newTarget;
+}
+
 void
 Factory::SetDirect3D10Device(ID3D10Device1 *aDevice)
 {
   mD3D10Device = aDevice;
 }
 
 ID3D10Device1*
 Factory::GetDirect3D10Device()
--- a/gfx/2d/Makefile.in
+++ b/gfx/2d/Makefile.in
@@ -68,16 +68,17 @@ EXPORTS_mozilla/gfx	= \
 CPPSRCS	= \
 	Factory.cpp \
         Matrix.cpp \
         DrawTargetCairo.cpp \
         SourceSurfaceCairo.cpp \
         PathCairo.cpp \
         Blur.cpp \
         ScaledFontBase.cpp \
+        DrawTargetDual.cpp \
         $(NULL)
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 CPPSRCS	+= \
 	   SourceSurfaceCG.cpp \
 	   DrawTargetCG.cpp \
 	   PathCG.cpp \
 	   $(NULL)
new file mode 100644
--- /dev/null
+++ b/gfx/2d/SourceSurfaceDual.h
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 20; 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 Corporation code.
+  *
+  * The Initial Developer of the Original Code is Mozilla Foundation.
+  * Portions created by the Initial Developer are Copyright (C) 2011
+  * the Initial Developer. All Rights Reserved.
+  *
+  * Contributor(s):
+  *   Bas Schouten <bschouten@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 ***** */
+     
+#ifndef MOZILLA_GFX_SOURCESURFACEDUAL_H_
+#define MOZILLA_GFX_SOURCESURFACEDUAL_H_
+     
+#include "2D.h"
+     
+namespace mozilla {
+namespace gfx {
+
+class DualSurface;
+class DualPattern;
+
+class SourceSurfaceDual : public SourceSurface
+{
+public:
+  SourceSurfaceDual(DrawTarget *aDTA, DrawTarget *aDTB)
+    : mA(aDTA->Snapshot())
+    , mB(aDTB->Snapshot())
+  { }
+
+  virtual SurfaceType GetType() const { return SURFACE_DUAL_DT; }
+  virtual IntSize GetSize() const { return mA->GetSize(); }
+  virtual SurfaceFormat GetFormat() const { return mA->GetFormat(); }
+
+  /* Readback from this surface type is not supported! */
+  virtual TemporaryRef<DataSourceSurface> GetDataSurface() { return NULL; }
+private:
+  friend class DualSurface;
+  friend class DualPattern;
+
+  RefPtr<SourceSurface> mA;
+  RefPtr<SourceSurface> mB;
+};
+
+}
+}
+
+#endif /* MOZILLA_GFX_SOURCESURFACEDUAL_H_ */
--- a/gfx/2d/Tools.h
+++ b/gfx/2d/Tools.h
@@ -52,12 +52,21 @@ IsOperatorBoundByMask(CompositionOp aOp)
   case OP_DEST_ATOP:
   case OP_SOURCE:
     return false;
   default:
     return true;
   }
 }
 
+template <class T>
+struct ClassStorage
+{
+  char bytes[sizeof(T)];
+
+  const T *addr() const { return (const T *)bytes; }
+  T *addr() { return (T *)(void *)bytes; }
+};
+
 }
 }
 
 #endif /* MOZILLA_GFX_TOOLS_H_ */
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -51,17 +51,18 @@ enum SurfaceType
 {
   SURFACE_DATA, /* Data surface - bitmap in memory */
   SURFACE_D2D1_BITMAP, /* Surface wrapping a ID2D1Bitmap */
   SURFACE_D2D1_DRAWTARGET, /* Surface made from a D2D draw target */
   SURFACE_CAIRO, /* Surface wrapping a cairo surface */
   SURFACE_CAIRO_IMAGE, /* Data surface wrapping a cairo image surface */
   SURFACE_COREGRAPHICS_IMAGE, /* Surface wrapping a CoreGraphics Image */
   SURFACE_COREGRAPHICS_CGCONTEXT, /* Surface wrapping a CG context */
-  SURFACE_SKIA /* Surface wrapping a Skia bitmap */
+  SURFACE_SKIA, /* Surface wrapping a Skia bitmap */
+  SURFACE_DUAL_DT /* Snapshot of a dual drawtarget */
 };
 
 enum SurfaceFormat
 {
   FORMAT_B8G8R8A8,
   FORMAT_B8G8R8X8,
   FORMAT_R5G6B5,
   FORMAT_A8
--- a/gfx/layers/d3d10/LayerManagerD3D10.fx
+++ b/gfx/layers/d3d10/LayerManagerD3D10.fx
@@ -36,16 +36,25 @@ BlendState NonPremul
   DestBlend = Inv_Src_Alpha;
   BlendOp = Add;
   SrcBlendAlpha = One;
   DestBlendAlpha = Inv_Src_Alpha;
   BlendOpAlpha = Add;
   RenderTargetWriteMask[0] = 0x0F; // All
 };
 
+BlendState NoBlendDual
+{
+  AlphaToCoverageEnable = FALSE;
+  BlendEnable[0] = FALSE;
+  BlendEnable[1] = FALSE;
+  RenderTargetWriteMask[0] = 0x0F; // All
+  RenderTargetWriteMask[1] = 0x0F; // All
+};
+
 BlendState ComponentAlphaBlend
 {
   AlphaToCoverageEnable = FALSE;
   BlendEnable[0] = TRUE;
   SrcBlend = One;
   DestBlend = Inv_Src1_Color;
   BlendOp = Add;
   SrcBlendAlpha = One;
@@ -89,16 +98,21 @@ struct VS_OUTPUT {
   float2 vTexCoords : TEXCOORD0;
 };
 
 struct PS_OUTPUT {
   float4 vSrc;
   float4 vAlpha;
 };
 
+struct PS_DUAL_OUTPUT {
+  float4 vOutput1 : SV_Target0;
+  float4 vOutput2 : SV_Target1;
+};
+
 VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex)
 {
   VS_OUTPUT outp;
   outp.vPosition.z = 0;
   outp.vPosition.w = 1;
   
   // We use 4 component floats to uniquely describe a rectangle, by the structure
   // of x, y, width, height. This allows us to easily generate the 4 corners
@@ -180,16 +194,24 @@ PS_OUTPUT ComponentAlphaShader(const VS_
   return result;
 }
 
 float4 SolidColorShader(const VS_OUTPUT aVertex) : SV_Target
 {
   return fLayerColor;
 }
 
+PS_DUAL_OUTPUT AlphaExtractionPrepareShader(const VS_OUTPUT aVertex)
+{
+  PS_DUAL_OUTPUT result;
+  result.vOutput1 = float4(0, 0, 0, 1);
+  result.vOutput2 = float4(1, 1, 1, 1);
+  return result;
+}
+
 technique10 RenderRGBLayerPremul
 {
     pass P0
     {
         SetRasterizerState( LayerRast );
         SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
         SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
         SetGeometryShader( NULL );
@@ -288,8 +310,20 @@ technique10 RenderSolidColorLayer
     {
         SetRasterizerState( LayerRast );
         SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
         SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
         SetGeometryShader( NULL );
         SetPixelShader( CompileShader( ps_4_0_level_9_3, SolidColorShader() ) );
     }
 }
+
+technique10 PrepareAlphaExtractionTextures
+{
+    pass P0
+    {
+        SetRasterizerState( LayerRast );
+        SetBlendState( NoBlendDual, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
+        SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
+        SetGeometryShader( NULL );
+        SetPixelShader( CompileShader( ps_4_0_level_9_3, AlphaExtractionPrepareShader() ) );
+    }
+}
--- a/gfx/layers/d3d10/LayerManagerD3D10Effect.h
+++ b/gfx/layers/d3d10/LayerManagerD3D10Effect.h
@@ -20,17 +20,17 @@ cbuffer PerOccasionalLayer
 }
 
 cbuffer PerLayerManager
 {
     float4x4 mProjection;               // Offset:    0, size:   64
 }
 
 //
-// 11 local object(s)
+// 12 local object(s)
 //
 BlendState Premul
 {
     AlphaToCoverageEnable = bool(FALSE /* 0 */);
     BlendEnable[0] = bool(TRUE /* 1 */);
     SrcBlend[0] = uint(ONE /* 2 */);
     DestBlend[0] = uint(INV_SRC_ALPHA /* 6 */);
     BlendOp[0] = uint(ADD /* 1 */);
@@ -46,16 +46,24 @@ BlendState NonPremul
     SrcBlend[0] = uint(SRC_ALPHA /* 5 */);
     DestBlend[0] = uint(INV_SRC_ALPHA /* 6 */);
     BlendOp[0] = uint(ADD /* 1 */);
     SrcBlendAlpha[0] = uint(ONE /* 2 */);
     DestBlendAlpha[0] = uint(INV_SRC_ALPHA /* 6 */);
     BlendOpAlpha[0] = uint(ADD /* 1 */);
     RenderTargetWriteMask[0] = byte(0x0f);
 };
+BlendState NoBlendDual
+{
+    AlphaToCoverageEnable = bool(FALSE /* 0 */);
+    BlendEnable[0] = bool(FALSE /* 0 */);
+    BlendEnable[1] = bool(FALSE /* 0 */);
+    RenderTargetWriteMask[0] = byte(0x0f);
+    RenderTargetWriteMask[1] = byte(0x0f);
+};
 BlendState ComponentAlphaBlend
 {
     AlphaToCoverageEnable = bool(FALSE /* 0 */);
     BlendEnable[0] = bool(TRUE /* 1 */);
     SrcBlend[0] = uint(ONE /* 2 */);
     DestBlend[0] = uint(INV_SRC1_COLOR /* 17 */);
     BlendOp[0] = uint(ADD /* 1 */);
     SrcBlendAlpha[0] = uint(ONE /* 2 */);
@@ -82,17 +90,17 @@ SamplerState LayerTextureSamplerLinear
 SamplerState LayerTextureSamplerPoint
 {
     Filter   = uint(MIN_MAG_MIP_POINT /* 0 */);
     AddressU = uint(CLAMP /* 3 */);
     AddressV = uint(CLAMP /* 3 */);
 };
 
 //
-// 9 technique(s)
+// 10 technique(s)
 //
 technique10 RenderRGBLayerPremul
 {
     pass P0
     {
         RasterizerState = LayerRast;
         AB_BlendFactor = float4(0, 0, 0, 0);
         AB_SampleMask = uint(0xffffffff);
@@ -2046,40 +2054,214 @@ technique10 RenderSolidColorLayer
             ret 
             // Approximately 2 instruction slots used
                     
         };
     }
 
 }
 
+technique10 PrepareAlphaExtractionTextures
+{
+    pass P0
+    {
+        RasterizerState = LayerRast;
+        AB_BlendFactor = float4(0, 0, 0, 0);
+        AB_SampleMask = uint(0xffffffff);
+        BlendState = NoBlendDual;
+        VertexShader = asm {
+            //
+            // Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+            //
+            //
+            // Buffer Definitions: 
+            //
+            // cbuffer PerLayer
+            // {
+            //
+            //   float4 vTextureCoords;             // Offset:    0 Size:    16
+            //   float4 vLayerQuad;                 // Offset:   16 Size:    16
+            //   float fLayerOpacity;               // Offset:   32 Size:     4 [unused]
+            //   float4x4 mLayerTransform;          // Offset:   48 Size:    64
+            //
+            // }
+            //
+            // cbuffer PerOccasionalLayer
+            // {
+            //
+            //   float4 vRenderTargetOffset;        // Offset:    0 Size:    16
+            //   float4 fLayerColor;                // Offset:   16 Size:    16 [unused]
+            //
+            // }
+            //
+            // cbuffer PerLayerManager
+            // {
+            //
+            //   float4x4 mProjection;              // Offset:    0 Size:    64
+            //
+            // }
+            //
+            //
+            // Resource Bindings:
+            //
+            // Name                                 Type  Format         Dim Slot Elements
+            // ------------------------------ ---------- ------- ----------- ---- --------
+            // PerLayer                          cbuffer      NA          NA    0        1
+            // PerOccasionalLayer                cbuffer      NA          NA    1        1
+            // PerLayerManager                   cbuffer      NA          NA    2        1
+            //
+            //
+            //
+            // Input signature:
+            //
+            // Name                 Index   Mask Register SysValue Format   Used
+            // -------------------- ----- ------ -------- -------- ------ ------
+            // POSITION                 0   xy          0     NONE  float   xy  
+            //
+            //
+            // Output signature:
+            //
+            // Name                 Index   Mask Register SysValue Format   Used
+            // -------------------- ----- ------ -------- -------- ------ ------
+            // SV_Position              0   xyzw        0      POS  float   xyzw
+            // TEXCOORD                 0   xy          1     NONE  float   xy  
+            //
+            //
+            // Constant buffer to DX9 shader constant mappings:
+            //
+            // Target Reg Buffer  Start Reg # of Regs        Data Conversion
+            // ---------- ------- --------- --------- ----------------------
+            // c1         cb0             0         2  ( FLT, FLT, FLT, FLT)
+            // c3         cb0             3         2  ( FLT, FLT, FLT, FLT)
+            // c5         cb0             6         1  ( FLT, FLT, FLT, FLT)
+            // c6         cb1             0         1  ( FLT, FLT, FLT, FLT)
+            // c7         cb2             0         4  ( FLT, FLT, FLT, FLT)
+            //
+            //
+            // Runtime generated constant mappings:
+            //
+            // Target Reg                               Constant Description
+            // ---------- --------------------------------------------------
+            // c0                              Vertex Shader position offset
+            //
+            //
+            // Level9 shader bytecode:
+            //
+                vs_2_x
+                dcl_texcoord v0
+                mad oT0.xy, v0, c1.zwzw, c1
+                mad r0.xy, v0, c2.zwzw, c2
+                mul r1, r0.y, c4
+                mad r0, c3, r0.x, r1
+                add r0, r0, c5
+                rcp r1.x, r0.w
+                mul r0.xyz, r0, r1.x
+                add r0, r0, -c6
+                mul r0.xyz, r0.w, r0
+                mul r1, r0.y, c8
+                mad r1, c7, r0.x, r1
+                mad r1, c9, r0.z, r1
+                mad r0, c10, r0.w, r1
+                mad oPos.xy, r0.w, c0, r0
+                mov oPos.zw, r0
+            
+            // approximately 15 instruction slots used
+            vs_4_0
+            dcl_constantbuffer cb0[7], immediateIndexed
+            dcl_constantbuffer cb1[1], immediateIndexed
+            dcl_constantbuffer cb2[4], immediateIndexed
+            dcl_input v0.xy
+            dcl_output_siv o0.xyzw, position
+            dcl_output o1.xy
+            dcl_temps 2
+            mad r0.xy, v0.xyxx, cb0[1].zwzz, cb0[1].xyxx
+            mul r1.xyzw, r0.yyyy, cb0[4].xyzw
+            mad r0.xyzw, cb0[3].xyzw, r0.xxxx, r1.xyzw
+            add r0.xyzw, r0.xyzw, cb0[6].xyzw
+            div r0.xyz, r0.xyzx, r0.wwww
+            add r0.xyzw, r0.xyzw, -cb1[0].xyzw
+            mul r0.xyz, r0.wwww, r0.xyzx
+            mul r1.xyzw, r0.yyyy, cb2[1].xyzw
+            mad r1.xyzw, cb2[0].xyzw, r0.xxxx, r1.xyzw
+            mad r1.xyzw, cb2[2].xyzw, r0.zzzz, r1.xyzw
+            mad o0.xyzw, cb2[3].xyzw, r0.wwww, r1.xyzw
+            mad o1.xy, v0.xyxx, cb0[0].zwzz, cb0[0].xyxx
+            ret 
+            // Approximately 13 instruction slots used
+                    
+        };
+        GeometryShader = NULL;
+        PixelShader = asm {
+            //
+            // Generated by Microsoft (R) HLSL Shader Compiler 9.29.952.3111
+            //
+            //
+            //
+            // Input signature:
+            //
+            // Name                 Index   Mask Register SysValue Format   Used
+            // -------------------- ----- ------ -------- -------- ------ ------
+            // SV_Position              0   xyzw        0      POS  float       
+            // TEXCOORD                 0   xy          1     NONE  float       
+            //
+            //
+            // Output signature:
+            //
+            // Name                 Index   Mask Register SysValue Format   Used
+            // -------------------- ----- ------ -------- -------- ------ ------
+            // SV_Target                0   xyzw        0   TARGET  float   xyzw
+            // SV_Target                1   xyzw        1   TARGET  float   xyzw
+            //
+            //
+            // Level9 shader bytecode:
+            //
+                ps_2_x
+                def c0, 0, 0, 0, 1
+                mov oC0, c0
+                mov r0, c0.w
+                mov oC1, r0
+            
+            // approximately 3 instruction slots used
+            ps_4_0
+            dcl_output o0.xyzw
+            dcl_output o1.xyzw
+            mov o0.xyzw, l(0,0,0,1.000000)
+            mov o1.xyzw, l(1.000000,1.000000,1.000000,1.000000)
+            ret 
+            // Approximately 3 instruction slots used
+                    
+        };
+    }
+
+}
+
 #endif
 
 const BYTE g_main[] =
 {
-     68,  88,  66,  67,  17, 159, 
-     33, 161, 201, 116,  88,   5, 
-    211,  56, 199,  67, 199, 232, 
-    242,  72,   1,   0,   0,   0, 
-    215, 124,   0,   0,   1,   0, 
+     68,  88,  66,  67, 254, 183, 
+    204, 179, 168, 103,  33,  91, 
+      6,  38, 255, 118, 143,  81, 
+     10, 185,   1,   0,   0,   0, 
+    118, 136,   0,   0,   1,   0, 
       0,   0,  36,   0,   0,   0, 
-     70,  88,  49,  48, 171, 124, 
+     70,  88,  49,  48,  74, 136, 
       0,   0,   1,  16, 255, 254, 
       3,   0,   0,   0,   7,   0, 
-      0,   0,  11,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      9,   0,   0,   0, 103, 115, 
+      0,   0,  12,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     10,   0,   0,   0,  22, 126, 
       0,   0,   0,   0,   0,   0, 
       5,   0,   0,   0,   0,   0, 
-      0,   0,   3,   0,   0,   0, 
+      0,   0,   4,   0,   0,   0, 
       1,   0,   0,   0,   2,   0, 
       0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,  18,   0, 
-      0,   0,  18,   0,   0,   0, 
+      0,   0,   0,   0,  20,   0, 
+      0,   0,  20,   0,   0,   0, 
       0,   0,   0,   0,  80, 101, 
     114,  76,  97, 121, 101, 114, 
       0, 102, 108, 111,  97, 116, 
      52,   0,  13,   0,   0,   0, 
       1,   0,   0,   0,   0,   0, 
       0,   0,  16,   0,   0,   0, 
      16,   0,   0,   0,  16,   0, 
       0,   0,  10,  33,   0,   0, 
@@ -2157,16 +2339,28 @@ const BYTE g_main[] =
       1,   0,   0,   0,   1,   0, 
       0,   0,   2,   0,   0,   0, 
       2,   0,   0,   0,   1,   0, 
       0,   0,   2,   0,   0,   0, 
       6,   0,   0,   0,   1,   0, 
       0,   0,   2,   0,   0,   0, 
       1,   0,   0,   0,   1,   0, 
       0,   0,   3,   0,   0,   0, 
+     15,   0,   0,   0,  78, 111, 
+     66, 108, 101, 110, 100,  68, 
+    117,  97, 108,   0,   1,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   3,   0,   0,   0, 
+     15,   0,   0,   0,   1,   0, 
+      0,   0,   3,   0,   0,   0, 
      15,   0,   0,   0,  67, 111, 
     109, 112, 111, 110, 101, 110, 
     116,  65, 108, 112, 104,  97, 
      66, 108, 101, 110, 100,   0, 
       1,   0,   0,   0,   2,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   2,   0, 
       0,   0,   1,   0,   0,   0, 
@@ -2181,40 +2375,40 @@ const BYTE g_main[] =
       1,   0,   0,   0,   2,   0, 
       0,   0,   6,   0,   0,   0, 
       1,   0,   0,   0,   2,   0, 
       0,   0,   1,   0,   0,   0, 
       1,   0,   0,   0,   3,   0, 
       0,   0,  15,   0,   0,   0, 
      82,  97, 115, 116, 101, 114, 
     105, 122, 101, 114,  83, 116, 
-     97, 116, 101,   0, 142,   2, 
+     97, 116, 101,   0, 214,   2, 
       0,   0,   2,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   4,   0, 
       0,   0,  76,  97, 121, 101, 
     114,  82,  97, 115, 116,   0, 
       1,   0,   0,   0,   2,   0, 
       0,   0,   1,   0,   0,   0, 
       1,   0,   0,   0,   2,   0, 
       0,   0,   1,   0,   0,   0, 
      84, 101, 120, 116, 117, 114, 
-    101,  50,  68,   0, 220,   2, 
+    101,  50,  68,   0,  36,   3, 
       0,   0,   2,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,  12,   0, 
       0,   0, 116,  82,  71,  66, 
       0, 116,  89,   0, 116,  67, 
      98,   0, 116,  67, 114,   0, 
     116,  82,  71,  66,  87, 104, 
     105, 116, 101,   0,  83,  97, 
     109, 112, 108, 101, 114,  83, 
-    116,  97, 116, 101,   0,  28, 
+    116,  97, 116, 101,   0, 100, 
       3,   0,   0,   2,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,  21, 
       0,   0,   0,  76,  97, 121, 
     101, 114,  84, 101, 120, 116, 
     117, 114, 101,  83,  97, 109, 
     112, 108, 101, 114,  76, 105, 
@@ -2558,17 +2752,17 @@ const BYTE g_main[] =
      15,   0,   0,   0,  68,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   3,   0, 
       0,   0,   1,   0,   0,   0, 
       3,  12,   0,   0,  83,  86, 
      95,  80, 111, 115, 105, 116, 
     105, 111, 110,   0,  84,  69, 
      88,  67,  79,  79,  82,  68, 
-      0, 171, 171, 171,   8,   4, 
+      0, 171, 171, 171,  80,   4, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   2,   0, 
       0,   0,   0,   0,   0,   0, 
      84,   4,   0,   0,  68,  88, 
      66,  67, 243,   1, 145, 163, 
     244, 213, 142, 119,  56, 177, 
      66, 167, 121,  91, 183,  98, 
       1,   0,   0,   0,  84,   4, 
@@ -2747,17 +2941,17 @@ const BYTE g_main[] =
      71,  78,  44,   0,   0,   0, 
       1,   0,   0,   0,   8,   0, 
       0,   0,  32,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  83,  86,  95,  84, 
      97, 114, 103, 101, 116,   0, 
-    171, 171, 136,  11,   0,   0, 
+    171, 171, 208,  11,   0,   0, 
       0,   0,   0,   0,  82, 101, 
     110, 100, 101, 114,  82,  71, 
      66,  76,  97, 121, 101, 114, 
      80, 114, 101, 109, 117, 108, 
      80, 111, 105, 110, 116,   0, 
       4,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   0,   0, 
@@ -3077,17 +3271,17 @@ const BYTE g_main[] =
      15,   0,   0,   0,  68,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   3,   0, 
       0,   0,   1,   0,   0,   0, 
       3,  12,   0,   0,  83,  86, 
      95,  80, 111, 115, 105, 116, 
     105, 111, 110,   0,  84,  69, 
      88,  67,  79,  79,  82,  68, 
-      0, 171, 171, 171,  50,  16, 
+      0, 171, 171, 171, 122,  16, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   2,   0, 
       0,   0,   0,   0,   0,   0, 
      84,   4,   0,   0,  68,  88, 
      66,  67,  18,   7, 254,  25, 
     136,  32, 226,  82, 202, 102, 
      47, 221,  83,  73, 192, 155, 
       1,   0,   0,   0,  84,   4, 
@@ -3266,17 +3460,17 @@ const BYTE g_main[] =
      71,  78,  44,   0,   0,   0, 
       1,   0,   0,   0,   8,   0, 
       0,   0,  32,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  83,  86,  95,  84, 
      97, 114, 103, 101, 116,   0, 
-    171, 171, 178,  23,   0,   0, 
+    171, 171, 250,  23,   0,   0, 
       0,   0,   0,   0,  82, 101, 
     110, 100, 101, 114,  82,  71, 
      66,  65,  76,  97, 121, 101, 
     114,  80, 114, 101, 109, 117, 
     108,   0,   4,   0,   0,   0, 
       1,   0,   0,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
       0,   0,   0,   0,   1,   0, 
@@ -3596,17 +3790,17 @@ const BYTE g_main[] =
      68,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       3,   0,   0,   0,   1,   0, 
       0,   0,   3,  12,   0,   0, 
      83,  86,  95,  80, 111, 115, 
     105, 116, 105, 111, 110,   0, 
      84,  69,  88,  67,  79,  79, 
      82,  68,   0, 171, 171, 171, 
-     88,  28,   0,   0,   0,   0, 
+    160,  28,   0,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
       2,   0,   0,   0,   0,   0, 
       0,   0,  48,   4,   0,   0, 
      68,  88,  66,  67, 158, 107, 
      18, 255, 206, 164, 235, 111, 
     119,   9, 247, 201, 106, 179, 
      84,  67,   1,   0,   0,   0, 
      48,   4,   0,   0,   6,   0, 
@@ -3778,17 +3972,17 @@ const BYTE g_main[] =
      79,  83,  71,  78,  44,   0, 
       0,   0,   1,   0,   0,   0, 
       8,   0,   0,   0,  32,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   3,   0, 
       0,   0,   0,   0,   0,   0, 
      15,   0,   0,   0,  83,  86, 
      95,  84,  97, 114, 103, 101, 
-    116,   0, 171, 171, 216,  35, 
+    116,   0, 171, 171,  32,  36, 
       0,   0,   0,   0,   0,   0, 
      82, 101, 110, 100, 101, 114, 
      82,  71,  66,  65,  76,  97, 
     121, 101, 114,  78, 111, 110, 
      80, 114, 101, 109, 117, 108, 
       0,   4,   0,   0,   0,   1, 
       0,   0,   0,   0,   0,   0, 
       0,   1,   0,   0,   0,   0, 
@@ -4108,17 +4302,17 @@ const BYTE g_main[] =
       0,  15,   0,   0,   0,  68, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   3, 
       0,   0,   0,   1,   0,   0, 
       0,   3,  12,   0,   0,  83, 
      86,  95,  80, 111, 115, 105, 
     116, 105, 111, 110,   0,  84, 
      69,  88,  67,  79,  79,  82, 
-     68,   0, 171, 171, 171,  93, 
+     68,   0, 171, 171, 171, 165, 
      40,   0,   0,   0,   0,   0, 
       0,   1,   0,   0,   0,   2, 
       0,   0,   0,   0,   0,   0, 
       0,  48,   4,   0,   0,  68, 
      88,  66,  67, 158, 107,  18, 
     255, 206, 164, 235, 111, 119, 
       9, 247, 201, 106, 179,  84, 
      67,   1,   0,   0,   0,  48, 
@@ -4291,17 +4485,17 @@ const BYTE g_main[] =
      83,  71,  78,  44,   0,   0, 
       0,   1,   0,   0,   0,   8, 
       0,   0,   0,  32,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   3,   0,   0, 
       0,   0,   0,   0,   0,  15, 
       0,   0,   0,  83,  86,  95, 
      84,  97, 114, 103, 101, 116, 
-      0, 171, 171, 221,  47,   0, 
+      0, 171, 171,  37,  48,   0, 
       0,   0,   0,   0,   0,  82, 
     101, 110, 100, 101, 114,  82, 
      71,  66,  65,  76,  97, 121, 
     101, 114,  80, 114, 101, 109, 
     117, 108,  80, 111, 105, 110, 
     116,   0,   4,   0,   0,   0, 
       1,   0,   0,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
@@ -4622,17 +4816,17 @@ const BYTE g_main[] =
      68,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       3,   0,   0,   0,   1,   0, 
       0,   0,   3,  12,   0,   0, 
      83,  86,  95,  80, 111, 115, 
     105, 116, 105, 111, 110,   0, 
      84,  69,  88,  67,  79,  79, 
      82,  68,   0, 171, 171, 171, 
-    100,  52,   0,   0,   0,   0, 
+    172,  52,   0,   0,   0,   0, 
       0,   0,   1,   0,   0,   0, 
       2,   0,   0,   0,   0,   0, 
       0,   0,  48,   4,   0,   0, 
      68,  88,  66,  67,  61,  89, 
     104, 203, 112,  15, 192,   7, 
      21,  99, 104, 101,   1, 140, 
     240, 252,   1,   0,   0,   0, 
      48,   4,   0,   0,   6,   0, 
@@ -4804,17 +4998,17 @@ const BYTE g_main[] =
      79,  83,  71,  78,  44,   0, 
       0,   0,   1,   0,   0,   0, 
       8,   0,   0,   0,  32,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   3,   0, 
       0,   0,   0,   0,   0,   0, 
      15,   0,   0,   0,  83,  86, 
      95,  84,  97, 114, 103, 101, 
-    116,   0, 171, 171, 228,  59, 
+    116,   0, 171, 171,  44,  60, 
       0,   0,   0,   0,   0,   0, 
      82, 101, 110, 100, 101, 114, 
      82,  71,  66,  65,  76,  97, 
     121, 101, 114,  78, 111, 110, 
      80, 114, 101, 109, 117, 108, 
      80, 111, 105, 110, 116,   0, 
       4,   0,   0,   0,   1,   0, 
       0,   0,   0,   0,   0,   0, 
@@ -5135,17 +5329,17 @@ const BYTE g_main[] =
      15,   0,   0,   0,  68,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   3,   0, 
       0,   0,   1,   0,   0,   0, 
       3,  12,   0,   0,  83,  86, 
      95,  80, 111, 115, 105, 116, 
     105, 111, 110,   0,  84,  69, 
      88,  67,  79,  79,  82,  68, 
-      0, 171, 171, 171, 110,  64, 
+      0, 171, 171, 171, 182,  64, 
       0,   0,   0,   0,   0,   0, 
       1,   0,   0,   0,   2,   0, 
       0,   0,   0,   0,   0,   0, 
      48,   4,   0,   0,  68,  88, 
      66,  67,  61,  89, 104, 203, 
     112,  15, 192,   7,  21,  99, 
     104, 101,   1, 140, 240, 252, 
       1,   0,   0,   0,  48,   4, 
@@ -5318,17 +5512,17 @@ const BYTE g_main[] =
      71,  78,  44,   0,   0,   0, 
       1,   0,   0,   0,   8,   0, 
       0,   0,  32,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   3,   0,   0,   0, 
       0,   0,   0,   0,  15,   0, 
       0,   0,  83,  86,  95,  84, 
      97, 114, 103, 101, 116,   0, 
-    171, 171, 238,  71,   0,   0, 
+    171, 171,  54,  72,   0,   0, 
       0,   0,   0,   0,  82, 101, 
     110, 100, 101, 114,  89,  67, 
      98,  67, 114,  76,  97, 121, 
     101, 114,   0,   4,   0,   0, 
       0,   1,   0,   0,   0,   0, 
       0,   0,   0,   1,   0,   0, 
       0,   0,   0,   0,   0,   1, 
       0,   0,   0,   0,   0,   0, 
@@ -5647,17 +5841,17 @@ const BYTE g_main[] =
       0,  68,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   3,   0,   0,   0,   1, 
       0,   0,   0,   3,  12,   0, 
       0,  83,  86,  95,  80, 111, 
     115, 105, 116, 105, 111, 110, 
       0,  84,  69,  88,  67,  79, 
      79,  82,  68,   0, 171, 171, 
-    171, 107,  76,   0,   0,   0, 
+    171, 179,  76,   0,   0,   0, 
       0,   0,   0,   1,   0,   0, 
       0,   2,   0,   0,   0,   0, 
       0,   0,   0,  64,   7,   0, 
       0,  68,  88,  66,  67, 222, 
     117, 213, 158, 196,  73, 115, 
     238,  98,  73, 165, 136,  82, 
     215, 234,   7,   1,   0,   0, 
       0,  64,   7,   0,   0,   6, 
@@ -5960,17 +6154,17 @@ const BYTE g_main[] =
      83,  71,  78,  44,   0,   0, 
       0,   1,   0,   0,   0,   8, 
       0,   0,   0,  32,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   3,   0,   0, 
       0,   0,   0,   0,   0,  15, 
       0,   0,   0,  83,  86,  95, 
      84,  97, 114, 103, 101, 116, 
-      0, 171, 171, 235,  83,   0, 
+      0, 171, 171,  51,  84,   0, 
       0,   0,   0,   0,   0,  82, 
     101, 110, 100, 101, 114,  67, 
     111, 109, 112, 111, 110, 101, 
     110, 116,  65, 108, 112, 104, 
      97,  76,  97, 121, 101, 114, 
       0,   4,   0,   0,   0,   1, 
       0,   0,   0,   0,   0,   0, 
       0,   1,   0,   0,   0,   0, 
@@ -6290,17 +6484,17 @@ const BYTE g_main[] =
       0,  15,   0,   0,   0,  68, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   3, 
       0,   0,   0,   1,   0,   0, 
       0,   3,  12,   0,   0,  83, 
      86,  95,  80, 111, 115, 105, 
     116, 105, 111, 110,   0,  84, 
      69,  88,  67,  79,  79,  82, 
-     68,   0, 171, 171, 171, 129, 
+     68,   0, 171, 171, 171, 201, 
      91,   0,   0,   0,   0,   0, 
       0,   1,   0,   0,   0,   2, 
       0,   0,   0,   0,   0,   0, 
       0, 176,   5,   0,   0,  68, 
      88,  66,  67,  10, 232, 128, 
      36, 124, 206, 211, 130, 126, 
      20, 252, 175, 204,  95, 106, 
      47,   1,   0,   0,   0, 176, 
@@ -6537,17 +6731,17 @@ const BYTE g_main[] =
       0,   0,   0,   3,   0,   0, 
       0,   0,   0,   0,   0,  15, 
       0,   0,   0,  56,   0,   0, 
       0,   1,   0,   0,   0,   0, 
       0,   0,   0,   3,   0,   0, 
       0,   1,   0,   0,   0,  15, 
       0,   0,   0,  83,  86,  95, 
      84,  97, 114, 103, 101, 116, 
-      0, 171, 171,   1,  99,   0, 
+      0, 171, 171,  73,  99,   0, 
       0,   0,   0,   0,   0,  82, 
     101, 110, 100, 101, 114,  83, 
     111, 108, 105, 100,  67, 111, 
     108, 111, 114,  76,  97, 121, 
     101, 114,   0,   4,   0,   0, 
       0,   1,   0,   0,   0,   0, 
       0,   0,   0,   1,   0,   0, 
       0,   0,   0,   0,   0,   1, 
@@ -6867,17 +7061,17 @@ const BYTE g_main[] =
       0,  68,   0,   0,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   3,   0,   0,   0,   1, 
       0,   0,   0,   3,  12,   0, 
       0,  83,  86,  95,  80, 111, 
     115, 105, 116, 105, 111, 110, 
       0,  84,  69,  88,  67,  79, 
      79,  82,  68,   0, 171, 171, 
-    171,   3, 105,   0,   0,   0, 
+    171,  75, 105,   0,   0,   0, 
       0,   0,   0,   1,   0,   0, 
       0,   2,   0,   0,   0,   0, 
       0,   0,   0, 216,   2,   0, 
       0,  68,  88,  66,  67, 136, 
     106,  87,  29, 239,  32, 100, 
     138, 218,   2, 105,  91, 143, 
     165, 252,  49,   1,   0,   0, 
       0, 216,   2,   0,   0,   6, 
@@ -6992,394 +7186,878 @@ const BYTE g_main[] =
      83,  71,  78,  44,   0,   0, 
       0,   1,   0,   0,   0,   8, 
       0,   0,   0,  32,   0,   0, 
       0,   0,   0,   0,   0,   0, 
       0,   0,   0,   3,   0,   0, 
       0,   0,   0,   0,   0,  15, 
       0,   0,   0,  83,  86,  95, 
      84,  97, 114, 103, 101, 116, 
-      0, 171, 171, 131, 112,   0, 
-      0,   0,   0,   0,   0,   4, 
-      0,   0,   0, 112,   0,   0, 
-      0,   0,   0,   0,   0,   4, 
-      0,   0,   0, 255, 255, 255, 
-    255,   0,   0,   0,   0,  48, 
-      0,   0,   0,  20,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,  63,   0,   0, 
-      0,  20,   0,   0,   0,   0, 
-      0,   0,   0,  16,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0, 108,   0,   0,   0,  80, 
-      0,   0,   0,   0,   0,   0, 
-      0,  32,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0, 159, 
-      0,   0,   0, 131,   0,   0, 
-      0,   0,   0,   0,   0,  48, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0, 175,   0,   0, 
-      0,  32,   0,   0,   0,   0, 
-      0,   0,   0,   2,   0,   0, 
-      0, 255, 255, 255, 255,   0, 
-      0,   0,   0, 194,   0,   0, 
-      0,  20,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0, 214,   0,   0,   0,  20, 
-      0,   0,   0,   0,   0,   0, 
-      0,  16,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0, 226, 
-      0,   0,   0,  64,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 255, 255, 255, 
-    255,   0,   0,   0,   0, 242, 
-      0,   0,   0, 131,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,  37,   1,   0, 
-      0,   9,   1,   0,   0,   0, 
-      0,   0,   0, 255, 255, 255, 
-    255,   9,   0,   0,   0,  36, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,  44, 
-      1,   0,   0,  37,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0,  56,   1,   0, 
-      0,  38,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0,  68,   1,   0,   0,  39, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,  80, 
-      1,   0,   0,  40,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0,  92,   1,   0, 
-      0,  41,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 104,   1,   0,   0,  42, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 116, 
-      1,   0,   0,  43,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
+      0, 171, 171, 203, 112,   0, 
+      0,   0,   0,   0,   0,  80, 
+    114, 101, 112,  97, 114, 101, 
+     65, 108, 112, 104,  97,  69, 
+    120, 116, 114,  97,  99, 116, 
+    105, 111, 110,  84, 101, 120, 
+    116, 117, 114, 101, 115,   0, 
+      4,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   3,   0, 
+      0,   0, 255, 255, 255, 255, 
+    104,   7,   0,   0,  68,  88, 
+     66,  67, 148, 219,   9, 126, 
+     59, 247, 178, 128, 120,  37, 
+    163, 130,  38,  53, 191, 236, 
+      1,   0,   0,   0, 104,   7, 
+      0,   0,   6,   0,   0,   0, 
+     56,   0,   0,   0, 188,   1, 
+      0,   0, 228,   3,   0,   0, 
+     96,   4,   0,   0, 220,   6, 
+      0,   0,  16,   7,   0,   0, 
+     65, 111, 110,  57, 124,   1, 
+      0,   0, 124,   1,   0,   0, 
+      0,   2, 254, 255,  24,   1, 
+      0,   0, 100,   0,   0,   0, 
+      5,   0,  36,   0,   0,   0, 
+     96,   0,   0,   0,  96,   0, 
+      0,   0,  36,   0,   1,   0, 
+     96,   0,   0,   0,   0,   0, 
+      2,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      2,   0,   3,   0,   0,   0, 
+      0,   0,   0,   0,   6,   0, 
+      1,   0,   5,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      1,   0,   6,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+      4,   0,   7,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   2, 254, 255,  31,   0, 
+      0,   2,   5,   0,   0, 128, 
+      0,   0,  15, 144,   4,   0, 
+      0,   4,   0,   0,   3, 224, 
+      0,   0, 228, 144,   1,   0, 
+    238, 160,   1,   0, 228, 160, 
+      4,   0,   0,   4,   0,   0, 
+      3, 128,   0,   0, 228, 144, 
+      2,   0, 238, 160,   2,   0, 
+    228, 160,   5,   0,   0,   3, 
+      1,   0,  15, 128,   0,   0, 
+     85, 128,   4,   0, 228, 160, 
+      4,   0,   0,   4,   0,   0, 
+     15, 128,   3,   0, 228, 160, 
       0,   0,   0, 128,   1,   0, 
-      0,  44,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 140,   1,   0,   0,   0, 
-      0,   0,   0, 152,   1,   0, 
-      0,   9,   1,   0,   0,   0, 
-      0,   0,   0, 255, 255, 255, 
-    255,   9,   0,   0,   0,  36, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 162, 
-      1,   0,   0,  37,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 174,   1,   0, 
-      0,  38,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 186,   1,   0,   0,  39, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 198, 
-      1,   0,   0,  40,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 210,   1,   0, 
-      0,  41,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 222,   1,   0,   0,  42, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 234, 
-      1,   0,   0,  43,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 246,   1,   0, 
-      0,  44,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0,   2,   2,   0,   0,   0, 
-      0,   0,   0,  14,   2,   0, 
-      0,   9,   1,   0,   0,   0, 
-      0,   0,   0, 255, 255, 255, 
-    255,   9,   0,   0,   0,  36, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,  34, 
-      2,   0,   0,  37,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0,  46,   2,   0, 
-      0,  38,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0,  58,   2,   0,   0,  39, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,  70, 
-      2,   0,   0,  40,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0,  82,   2,   0, 
-      0,  41,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0,  94,   2,   0,   0,  42, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 106, 
-      2,   0,   0,  43,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 118,   2,   0, 
-      0,  44,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 130,   2,   0,   0,   0, 
-      0,   0,   0, 186,   2,   0, 
-      0, 158,   2,   0,   0,   0, 
-      0,   0,   0, 255, 255, 255, 
-    255,   2,   0,   0,   0,  19, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 196, 
-      2,   0,   0,  13,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 208,   2,   0, 
-      0,   0,   0,   0,   0,   2, 
-      3,   0,   0, 230,   2,   0, 
-      0,   0,   0,   0,   0, 255, 
-    255, 255, 255,   0,   0,   0, 
-      0,   7,   3,   0,   0, 230, 
-      2,   0,   0,   0,   0,   0, 
-      0, 255, 255, 255, 255,   0, 
-      0,   0,   0,  10,   3,   0, 
-      0, 230,   2,   0,   0,   0, 
-      0,   0,   0, 255, 255, 255, 
-    255,   0,   0,   0,   0,  14, 
-      3,   0,   0, 230,   2,   0, 
-      0,   0,   0,   0,   0, 255, 
-    255, 255, 255,   0,   0,   0, 
-      0,  18,   3,   0,   0, 230, 
+    228, 128,   2,   0,   0,   3, 
+      0,   0,  15, 128,   0,   0, 
+    228, 128,   5,   0, 228, 160, 
+      6,   0,   0,   2,   1,   0, 
+      1, 128,   0,   0, 255, 128, 
+      5,   0,   0,   3,   0,   0, 
+      7, 128,   0,   0, 228, 128, 
+      1,   0,   0, 128,   2,   0, 
+      0,   3,   0,   0,  15, 128, 
+      0,   0, 228, 128,   6,   0, 
+    228, 161,   5,   0,   0,   3, 
+      0,   0,   7, 128,   0,   0, 
+    255, 128,   0,   0, 228, 128, 
+      5,   0,   0,   3,   1,   0, 
+     15, 128,   0,   0,  85, 128, 
+      8,   0, 228, 160,   4,   0, 
+      0,   4,   1,   0,  15, 128, 
+      7,   0, 228, 160,   0,   0, 
+      0, 128,   1,   0, 228, 128, 
+      4,   0,   0,   4,   1,   0, 
+     15, 128,   9,   0, 228, 160, 
+      0,   0, 170, 128,   1,   0, 
+    228, 128,   4,   0,   0,   4, 
+      0,   0,  15, 128,  10,   0, 
+    228, 160,   0,   0, 255, 128, 
+      1,   0, 228, 128,   4,   0, 
+      0,   4,   0,   0,   3, 192, 
+      0,   0, 255, 128,   0,   0, 
+    228, 160,   0,   0, 228, 128, 
+      1,   0,   0,   2,   0,   0, 
+     12, 192,   0,   0, 228, 128, 
+    255, 255,   0,   0,  83,  72, 
+     68,  82,  32,   2,   0,   0, 
+     64,   0,   1,   0, 136,   0, 
+      0,   0,  89,   0,   0,   4, 
+     70, 142,  32,   0,   0,   0, 
+      0,   0,   7,   0,   0,   0, 
+     89,   0,   0,   4,  70, 142, 
+     32,   0,   1,   0,   0,   0, 
+      1,   0,   0,   0,  89,   0, 
+      0,   4,  70, 142,  32,   0, 
+      2,   0,   0,   0,   4,   0, 
+      0,   0,  95,   0,   0,   3, 
+     50,  16,  16,   0,   0,   0, 
+      0,   0, 103,   0,   0,   4, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    101,   0,   0,   3,  50,  32, 
+     16,   0,   1,   0,   0,   0, 
+    104,   0,   0,   2,   2,   0, 
+      0,   0,  50,   0,   0,  11, 
+     50,   0,  16,   0,   0,   0, 
+      0,   0,  70,  16,  16,   0, 
+      0,   0,   0,   0, 230, 138, 
+     32,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  70, 128, 
+     32,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  56,   0, 
+      0,   8, 242,   0,  16,   0, 
+      1,   0,   0,   0,  86,   5, 
+     16,   0,   0,   0,   0,   0, 
+     70, 142,  32,   0,   0,   0, 
+      0,   0,   4,   0,   0,   0, 
+     50,   0,   0,  10, 242,   0, 
+     16,   0,   0,   0,   0,   0, 
+     70, 142,  32,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      6,   0,  16,   0,   0,   0, 
+      0,   0,  70,  14,  16,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   8, 242,   0,  16,   0, 
+      0,   0,   0,   0,  70,  14, 
+     16,   0,   0,   0,   0,   0, 
+     70, 142,  32,   0,   0,   0, 
+      0,   0,   6,   0,   0,   0, 
+     14,   0,   0,   7, 114,   0, 
+     16,   0,   0,   0,   0,   0, 
+     70,   2,  16,   0,   0,   0, 
+      0,   0, 246,  15,  16,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   9, 242,   0,  16,   0, 
+      0,   0,   0,   0,  70,  14, 
+     16,   0,   0,   0,   0,   0, 
+     70, 142,  32, 128,  65,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,  56,   0, 
+      0,   7, 114,   0,  16,   0, 
+      0,   0,   0,   0, 246,  15, 
+     16,   0,   0,   0,   0,   0, 
+     70,   2,  16,   0,   0,   0, 
+      0,   0,  56,   0,   0,   8, 
+    242,   0,  16,   0,   1,   0, 
+      0,   0,  86,   5,  16,   0, 
+      0,   0,   0,   0,  70, 142, 
+     32,   0,   2,   0,   0,   0, 
+      1,   0,   0,   0,  50,   0, 
+      0,  10, 242,   0,  16,   0, 
+      1,   0,   0,   0,  70, 142, 
+     32,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   6,   0, 
+     16,   0,   0,   0,   0,   0, 
+     70,  14,  16,   0,   1,   0, 
+      0,   0,  50,   0,   0,  10, 
+    242,   0,  16,   0,   1,   0, 
+      0,   0,  70, 142,  32,   0, 
+      2,   0,   0,   0,   2,   0, 
+      0,   0, 166,  10,  16,   0, 
+      0,   0,   0,   0,  70,  14, 
+     16,   0,   1,   0,   0,   0, 
+     50,   0,   0,  10, 242,  32, 
+     16,   0,   0,   0,   0,   0, 
+     70, 142,  32,   0,   2,   0, 
+      0,   0,   3,   0,   0,   0, 
+    246,  15,  16,   0,   0,   0, 
+      0,   0,  70,  14,  16,   0, 
+      1,   0,   0,   0,  50,   0, 
+      0,  11,  50,  32,  16,   0, 
+      1,   0,   0,   0,  70,  16, 
+     16,   0,   0,   0,   0,   0, 
+    230, 138,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     70, 128,  32,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+     62,   0,   0,   1,  83,  84, 
+     65,  84, 116,   0,   0,   0, 
+     13,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   6,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,  82,  68,  69,  70, 
+    116,   2,   0,   0,   3,   0, 
+      0,   0, 168,   0,   0,   0, 
+      3,   0,   0,   0,  28,   0, 
+      0,   0,   0,   4, 254, 255, 
+      0,   1,   0,   0,  64,   2, 
+      0,   0, 124,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0, 133,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+    152,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,  80, 101, 114,  76, 
+     97, 121, 101, 114,   0,  80, 
+    101, 114,  79,  99,  99,  97, 
+    115, 105, 111, 110,  97, 108, 
+     76,  97, 121, 101, 114,   0, 
+     80, 101, 114,  76,  97, 121, 
+    101, 114,  77,  97, 110,  97, 
+    103, 101, 114,   0, 124,   0, 
+      0,   0,   4,   0,   0,   0, 
+    240,   0,   0,   0, 112,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 133,   0, 
+      0,   0,   2,   0,   0,   0, 
+    188,   1,   0,   0,  32,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 152,   0, 
+      0,   0,   1,   0,   0,   0, 
+     28,   2,   0,   0,  64,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  80,   1, 
+      0,   0,   0,   0,   0,   0, 
+     16,   0,   0,   0,   2,   0, 
+      0,   0,  96,   1,   0,   0, 
+      0,   0,   0,   0, 112,   1, 
+      0,   0,  16,   0,   0,   0, 
+     16,   0,   0,   0,   2,   0, 
+      0,   0,  96,   1,   0,   0, 
+      0,   0,   0,   0, 123,   1, 
+      0,   0,  32,   0,   0,   0, 
+      4,   0,   0,   0,   0,   0, 
+      0,   0, 140,   1,   0,   0, 
+      0,   0,   0,   0, 156,   1, 
+      0,   0,  48,   0,   0,   0, 
+     64,   0,   0,   0,   2,   0, 
+      0,   0, 172,   1,   0,   0, 
+      0,   0,   0,   0, 118,  84, 
+    101, 120, 116, 117, 114, 101, 
+     67, 111, 111, 114, 100, 115, 
+      0, 171,   1,   0,   3,   0, 
+      1,   0,   4,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    118,  76,  97, 121, 101, 114, 
+     81, 117,  97, 100,   0, 102, 
+     76,  97, 121, 101, 114,  79, 
+    112,  97,  99, 105, 116, 121, 
+      0, 171, 171, 171,   0,   0, 
+      3,   0,   1,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0, 109,  76,  97, 121, 
+    101, 114,  84, 114,  97, 110, 
+    115, 102, 111, 114, 109,   0, 
+      3,   0,   3,   0,   4,   0, 
+      4,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 236,   1, 
+      0,   0,   0,   0,   0,   0, 
+     16,   0,   0,   0,   2,   0, 
+      0,   0,   0,   2,   0,   0, 
+      0,   0,   0,   0,  16,   2, 
+      0,   0,  16,   0,   0,   0, 
+     16,   0,   0,   0,   0,   0, 
+      0,   0,   0,   2,   0,   0, 
+      0,   0,   0,   0, 118,  82, 
+    101, 110, 100, 101, 114,  84, 
+     97, 114, 103, 101, 116,  79, 
+    102, 102, 115, 101, 116,   0, 
+      1,   0,   3,   0,   1,   0, 
+      4,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 102,  76, 
+     97, 121, 101, 114,  67, 111, 
+    108, 111, 114,   0,  52,   2, 
+      0,   0,   0,   0,   0,   0, 
+     64,   0,   0,   0,   2,   0, 
+      0,   0, 172,   1,   0,   0, 
+      0,   0,   0,   0, 109,  80, 
+    114, 111, 106, 101,  99, 116, 
+    105, 111, 110,   0,  77, 105, 
+     99, 114, 111, 115, 111, 102, 
+    116,  32,  40,  82,  41,  32, 
+     72,  76,  83,  76,  32,  83, 
+    104,  97, 100, 101, 114,  32, 
+     67, 111, 109, 112, 105, 108, 
+    101, 114,  32,  57,  46,  50, 
+     57,  46,  57,  53,  50,  46, 
+     51,  49,  49,  49,   0, 171, 
+    171, 171,  73,  83,  71,  78, 
+     44,   0,   0,   0,   1,   0, 
+      0,   0,   8,   0,   0,   0, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,   3,   3,   0,   0, 
+     80,  79,  83,  73,  84,  73, 
+     79,  78,   0, 171, 171, 171, 
+     79,  83,  71,  78,  80,   0, 
+      0,   0,   2,   0,   0,   0, 
+      8,   0,   0,   0,  56,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+     15,   0,   0,   0,  68,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+      3,  12,   0,   0,  83,  86, 
+     95,  80, 111, 115, 105, 116, 
+    105, 111, 110,   0,  84,  69, 
+     88,  67,  79,  79,  82,  68, 
+      0, 171, 171, 171, 254, 115, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+    140,   2,   0,   0,  68,  88, 
+     66,  67, 120, 218, 197, 160, 
+     79, 160, 235,  82, 197,  10, 
+    155, 183,  41, 226,  48, 248, 
+      1,   0,   0,   0, 140,   2, 
+      0,   0,   6,   0,   0,   0, 
+     56,   0,   0,   0, 168,   0, 
+      0,   0,  20,   1,   0,   0, 
+    144,   1,   0,   0, 232,   1, 
+      0,   0,  64,   2,   0,   0, 
+     65, 111, 110,  57, 104,   0, 
+      0,   0, 104,   0,   0,   0, 
+      0,   2, 255, 255,  68,   0, 
+      0,   0,  36,   0,   0,   0, 
+      0,   0,  36,   0,   0,   0, 
+     36,   0,   0,   0,  36,   0, 
+      0,   0,  36,   0,   0,   0, 
+     36,   0,   1,   2, 255, 255, 
+     81,   0,   0,   5,   0,   0, 
+     15, 160,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 128,  63, 
+      1,   0,   0,   2,   0,   8, 
+     15, 128,   0,   0, 228, 160, 
+      1,   0,   0,   2,   0,   0, 
+     15, 128,   0,   0, 255, 160, 
+      1,   0,   0,   2,   1,   8, 
+     15, 128,   0,   0, 228, 128, 
+    255, 255,   0,   0,  83,  72, 
+     68,  82, 100,   0,   0,   0, 
+     64,   0,   0,   0,  25,   0, 
+      0,   0, 101,   0,   0,   3, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0, 101,   0,   0,   3, 
+    242,  32,  16,   0,   1,   0, 
+      0,   0,  54,   0,   0,   8, 
+    242,  32,  16,   0,   0,   0, 
+      0,   0,   2,  64,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0, 128,  63,  54,   0, 
+      0,   8, 242,  32,  16,   0, 
+      1,   0,   0,   0,   2,  64, 
+      0,   0,   0,   0, 128,  63, 
+      0,   0, 128,  63,   0,   0, 
+    128,  63,   0,   0, 128,  63, 
+     62,   0,   0,   1,  83,  84, 
+     65,  84, 116,   0,   0,   0, 
+      3,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
       2,   0,   0,   0,   0,   0, 
-      0, 255, 255, 255, 255,   0, 
-      0,   0,   0,  69,   3,   0, 
-      0,  41,   3,   0,   0,   0, 
-      0,   0,   0, 255, 255, 255, 
-    255,   3,   0,   0,   0,  45, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,  95, 
-      3,   0,   0,  46,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 107,   3,   0, 
-      0,  47,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 119,   3,   0,   0,   0, 
-      0,   0,   0, 131,   3,   0, 
-      0,  41,   3,   0,   0,   0, 
-      0,   0,   0, 255, 255, 255, 
-    255,   3,   0,   0,   0,  45, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 156, 
-      3,   0,   0,  46,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 168,   3,   0, 
-      0,  47,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 180,   3,   0,   0,   0, 
-      0,   0,   0, 192,   3,   0, 
-      0,   1,   0,   0,   0,   0, 
-      0,   0,   0, 213,   3,   0, 
-      0,   7,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   2, 
-      0,   0,   0, 186,   2,   0, 
-      0,  10,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 216,   3,   0,   0,  11, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 252, 
-      3,   0,   0,   2,   0,   0, 
-      0,   0,   0,   0,   0,   2, 
-      0,   0,   0,  37,   1,   0, 
-      0,   6,   0,   0,   0,   0, 
-      0,   0,   0,   7,   0,   0, 
-      0, 116,  11,   0,   0,   8, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 124, 
-     11,   0,   0,   7,   0,   0, 
-      0,   0,   0,   0,   0,   7, 
-      0,   0,   0, 224,  15,   0, 
-      0, 232,  15,   0,   0,   1, 
-      0,   0,   0,   0,   0,   0, 
-      0, 213,   3,   0,   0,   7, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   2,   0,   0, 
-      0, 186,   2,   0,   0,  10, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,   2, 
-     16,   0,   0,  11,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0,  38,  16,   0, 
-      0,   2,   0,   0,   0,   0, 
-      0,   0,   0,   2,   0,   0, 
-      0,  37,   1,   0,   0,   6, 
-      0,   0,   0,   0,   0,   0, 
-      0,   7,   0,   0,   0, 158, 
-     23,   0,   0,   8,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 166,  23,   0, 
-      0,   7,   0,   0,   0,   0, 
-      0,   0,   0,   7,   0,   0, 
-      0,  10,  28,   0,   0,  18, 
-     28,   0,   0,   1,   0,   0, 
-      0,   0,   0,   0,   0, 213, 
-      3,   0,   0,   7,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   2,   0,   0,   0, 186, 
-      2,   0,   0,  10,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0,  40,  28,   0, 
-      0,  11,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0,  76,  28,   0,   0,   2, 
-      0,   0,   0,   0,   0,   0, 
-      0,   2,   0,   0,   0,  37, 
-      1,   0,   0,   6,   0,   0, 
-      0,   0,   0,   0,   0,   7, 
-      0,   0,   0, 196,  35,   0, 
-      0,   8,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 204,  35,   0,   0,   7, 
-      0,   0,   0,   0,   0,   0, 
-      0,   7,   0,   0,   0,  12, 
-     40,   0,   0,  20,  40,   0, 
-      0,   1,   0,   0,   0,   0, 
-      0,   0,   0, 213,   3,   0, 
-      0,   7,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   2, 
-      0,   0,   0, 186,   2,   0, 
-      0,  10,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0,  45,  40,   0,   0,  11, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,  81, 
-     40,   0,   0,   2,   0,   0, 
-      0,   0,   0,   0,   0,   2, 
-      0,   0,   0, 152,   1,   0, 
-      0,   6,   0,   0,   0,   0, 
-      0,   0,   0,   7,   0,   0, 
-      0, 201,  47,   0,   0,   8, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 209, 
-     47,   0,   0,   7,   0,   0, 
-      0,   0,   0,   0,   0,   7, 
-      0,   0,   0,  17,  52,   0, 
-      0,  25,  52,   0,   0,   1, 
-      0,   0,   0,   0,   0,   0, 
-      0, 213,   3,   0,   0,   7, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   2,   0,   0, 
-      0, 186,   2,   0,   0,  10, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,  52, 
-     52,   0,   0,  11,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0,  88,  52,   0, 
-      0,   2,   0,   0,   0,   0, 
-      0,   0,   0,   2,   0,   0, 
-      0,  37,   1,   0,   0,   6, 
-      0,   0,   0,   0,   0,   0, 
-      0,   7,   0,   0,   0, 208, 
-     59,   0,   0,   8,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 216,  59,   0, 
-      0,   7,   0,   0,   0,   0, 
-      0,   0,   0,   7,   0,   0, 
-      0,  24,  64,   0,   0,  32, 
-     64,   0,   0,   1,   0,   0, 
-      0,   0,   0,   0,   0, 213, 
-      3,   0,   0,   7,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   2,   0,   0,   0, 186, 
-      2,   0,   0,  10,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0,  62,  64,   0, 
-      0,  11,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0,  98,  64,   0,   0,   2, 
-      0,   0,   0,   0,   0,   0, 
-      0,   2,   0,   0,   0, 152, 
-      1,   0,   0,   6,   0,   0, 
-      0,   0,   0,   0,   0,   7, 
-      0,   0,   0, 218,  71,   0, 
-      0,   8,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 226,  71,   0,   0,   7, 
-      0,   0,   0,   0,   0,   0, 
-      0,   7,   0,   0,   0,  34, 
-     76,   0,   0,  42,  76,   0, 
-      0,   1,   0,   0,   0,   0, 
-      0,   0,   0, 213,   3,   0, 
-      0,   7,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   2, 
-      0,   0,   0, 186,   2,   0, 
-      0,  10,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0,  59,  76,   0,   0,  11, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,  95, 
-     76,   0,   0,   2,   0,   0, 
-      0,   0,   0,   0,   0,   2, 
-      0,   0,   0,  37,   1,   0, 
-      0,   6,   0,   0,   0,   0, 
-      0,   0,   0,   7,   0,   0, 
-      0, 215,  83,   0,   0,   8, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0, 223, 
-     83,   0,   0,   7,   0,   0, 
-      0,   0,   0,   0,   0,   7, 
-      0,   0,   0,  47,  91,   0, 
-      0,  55,  91,   0,   0,   1, 
-      0,   0,   0,   0,   0,   0, 
-      0, 213,   3,   0,   0,   7, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   2,   0,   0, 
-      0, 186,   2,   0,   0,  10, 
-      0,   0,   0,   0,   0,   0, 
-      0,   1,   0,   0,   0,  81, 
-     91,   0,   0,  11,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 117,  91,   0, 
-      0,   2,   0,   0,   0,   0, 
-      0,   0,   0,   2,   0,   0, 
-      0,  14,   2,   0,   0,   6, 
-      0,   0,   0,   0,   0,   0, 
-      0,   7,   0,   0,   0, 237, 
-     98,   0,   0,   8,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 245,  98,   0, 
-      0,   7,   0,   0,   0,   0, 
-      0,   0,   0,   7,   0,   0, 
-      0, 181, 104,   0,   0, 189, 
-    104,   0,   0,   1,   0,   0, 
-      0,   0,   0,   0,   0, 213, 
-      3,   0,   0,   7,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   0,   0,   0,   0,   0, 
-      0,   2,   0,   0,   0, 186, 
-      2,   0,   0,  10,   0,   0, 
-      0,   0,   0,   0,   0,   1, 
-      0,   0,   0, 211, 104,   0, 
-      0,  11,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 247, 104,   0,   0,   2, 
-      0,   0,   0,   0,   0,   0, 
-      0,   2,   0,   0,   0,  37, 
-      1,   0,   0,   6,   0,   0, 
-      0,   0,   0,   0,   0,   7, 
-      0,   0,   0, 111, 112,   0, 
-      0,   8,   0,   0,   0,   0, 
-      0,   0,   0,   1,   0,   0, 
-      0, 119, 112,   0,   0,   7, 
-      0,   0,   0,   0,   0,   0, 
-      0,   7,   0,   0,   0,  95, 
-    115,   0,   0
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,  82,  68,  69,  70, 
+     80,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,  28,   0, 
+      0,   0,   0,   4, 255, 255, 
+      0,   1,   0,   0,  28,   0, 
+      0,   0,  77, 105,  99, 114, 
+    111, 115, 111, 102, 116,  32, 
+     40,  82,  41,  32,  72,  76, 
+     83,  76,  32,  83, 104,  97, 
+    100, 101, 114,  32,  67, 111, 
+    109, 112, 105, 108, 101, 114, 
+     32,  57,  46,  50,  57,  46, 
+     57,  53,  50,  46,  51,  49, 
+     49,  49,   0, 171, 171, 171, 
+     73,  83,  71,  78,  80,   0, 
+      0,   0,   2,   0,   0,   0, 
+      8,   0,   0,   0,  56,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,   3,   0, 
+      0,   0,   0,   0,   0,   0, 
+     15,   0,   0,   0,  68,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   3,   0, 
+      0,   0,   1,   0,   0,   0, 
+      3,   0,   0,   0,  83,  86, 
+     95,  80, 111, 115, 105, 116, 
+    105, 111, 110,   0,  84,  69, 
+     88,  67,  79,  79,  82,  68, 
+      0, 171, 171, 171,  79,  83, 
+     71,  78,  68,   0,   0,   0, 
+      2,   0,   0,   0,   8,   0, 
+      0,   0,  56,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      0,   0,   0,   0,  15,   0, 
+      0,   0,  56,   0,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,   3,   0,   0,   0, 
+      1,   0,   0,   0,  15,   0, 
+      0,   0,  83,  86,  95,  84, 
+     97, 114, 103, 101, 116,   0, 
+    171, 171, 126, 123,   0,   0, 
+      0,   0,   0,   0,   4,   0, 
+      0,   0, 112,   0,   0,   0, 
+      0,   0,   0,   0,   4,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0,  48,   0, 
+      0,   0,  20,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,  63,   0,   0,   0, 
+     20,   0,   0,   0,   0,   0, 
+      0,   0,  16,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    108,   0,   0,   0,  80,   0, 
+      0,   0,   0,   0,   0,   0, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 159,   0, 
+      0,   0, 131,   0,   0,   0, 
+      0,   0,   0,   0,  48,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0, 175,   0,   0,   0, 
+     32,   0,   0,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0, 194,   0,   0,   0, 
+     20,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+    214,   0,   0,   0,  20,   0, 
+      0,   0,   0,   0,   0,   0, 
+     16,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0, 226,   0, 
+      0,   0,  64,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0, 242,   0, 
+      0,   0, 131,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,  37,   1,   0,   0, 
+      9,   1,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      9,   0,   0,   0,  36,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  44,   1, 
+      0,   0,  37,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  56,   1,   0,   0, 
+     38,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     68,   1,   0,   0,  39,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  80,   1, 
+      0,   0,  40,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  92,   1,   0,   0, 
+     41,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    104,   1,   0,   0,  42,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 116,   1, 
+      0,   0,  43,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 128,   1,   0,   0, 
+     44,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    140,   1,   0,   0,   0,   0, 
+      0,   0, 152,   1,   0,   0, 
+      9,   1,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      9,   0,   0,   0,  36,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 162,   1, 
+      0,   0,  37,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 174,   1,   0,   0, 
+     38,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    186,   1,   0,   0,  39,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 198,   1, 
+      0,   0,  40,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 210,   1,   0,   0, 
+     41,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    222,   1,   0,   0,  42,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 234,   1, 
+      0,   0,  43,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 246,   1,   0,   0, 
+     44,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+      2,   2,   0,   0,   0,   0, 
+      0,   0,  14,   2,   0,   0, 
+      9,   1,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      5,   0,   0,   0,  36,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  26,   2, 
+      0,   0,  37,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  38,   2,   0,   0, 
+     37,   0,   0,   0,   1,   0, 
+      0,   0,   1,   0,   0,   0, 
+     50,   2,   0,   0,  44,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  62,   2, 
+      0,   0,  44,   0,   0,   0, 
+      1,   0,   0,   0,   1,   0, 
+      0,   0,  74,   2,   0,   0, 
+      0,   0,   0,   0,  86,   2, 
+      0,   0,   9,   1,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   9,   0,   0,   0, 
+     36,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    106,   2,   0,   0,  37,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 118,   2, 
+      0,   0,  38,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 130,   2,   0,   0, 
+     39,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    142,   2,   0,   0,  40,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 154,   2, 
+      0,   0,  41,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 166,   2,   0,   0, 
+     42,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    178,   2,   0,   0,  43,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 190,   2, 
+      0,   0,  44,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 202,   2,   0,   0, 
+      0,   0,   0,   0,   2,   3, 
+      0,   0, 230,   2,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   2,   0,   0,   0, 
+     19,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     12,   3,   0,   0,  13,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  24,   3, 
+      0,   0,   0,   0,   0,   0, 
+     74,   3,   0,   0,  46,   3, 
+      0,   0,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,  79,   3,   0,   0, 
+     46,   3,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0,  82,   3, 
+      0,   0,  46,   3,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   0,   0,   0,   0, 
+     86,   3,   0,   0,  46,   3, 
+      0,   0,   0,   0,   0,   0, 
+    255, 255, 255, 255,   0,   0, 
+      0,   0,  90,   3,   0,   0, 
+     46,   3,   0,   0,   0,   0, 
+      0,   0, 255, 255, 255, 255, 
+      0,   0,   0,   0, 141,   3, 
+      0,   0, 113,   3,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   3,   0,   0,   0, 
+     45,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    167,   3,   0,   0,  46,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 179,   3, 
+      0,   0,  47,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 191,   3,   0,   0, 
+      0,   0,   0,   0, 203,   3, 
+      0,   0, 113,   3,   0,   0, 
+      0,   0,   0,   0, 255, 255, 
+    255, 255,   3,   0,   0,   0, 
+     45,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    228,   3,   0,   0,  46,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 240,   3, 
+      0,   0,  47,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 252,   3,   0,   0, 
+      0,   0,   0,   0,   8,   4, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,  29,   4, 
+      0,   0,   7,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,   2,   3, 
+      0,   0,  10,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  32,   4,   0,   0, 
+     11,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     68,   4,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,  37,   1, 
+      0,   0,   6,   0,   0,   0, 
+      0,   0,   0,   0,   7,   0, 
+      0,   0, 188,  11,   0,   0, 
+      8,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    196,  11,   0,   0,   7,   0, 
+      0,   0,   0,   0,   0,   0, 
+      7,   0,   0,   0,  40,  16, 
+      0,   0,  48,  16,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,  29,   4,   0,   0, 
+      7,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   2,   3,   0,   0, 
+     10,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     74,  16,   0,   0,  11,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 110,  16, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,  37,   1,   0,   0, 
+      6,   0,   0,   0,   0,   0, 
+      0,   0,   7,   0,   0,   0, 
+    230,  23,   0,   0,   8,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 238,  23, 
+      0,   0,   7,   0,   0,   0, 
+      0,   0,   0,   0,   7,   0, 
+      0,   0,  82,  28,   0,   0, 
+     90,  28,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+     29,   4,   0,   0,   7,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+      2,   3,   0,   0,  10,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 112,  28, 
+      0,   0,  11,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 148,  28,   0,   0, 
+      2,   0,   0,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+     37,   1,   0,   0,   6,   0, 
+      0,   0,   0,   0,   0,   0, 
+      7,   0,   0,   0,  12,  36, 
+      0,   0,   8,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  20,  36,   0,   0, 
+      7,   0,   0,   0,   0,   0, 
+      0,   0,   7,   0,   0,   0, 
+     84,  40,   0,   0,  92,  40, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,  29,   4, 
+      0,   0,   7,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,   2,   3, 
+      0,   0,  10,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 117,  40,   0,   0, 
+     11,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    153,  40,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0, 152,   1, 
+      0,   0,   6,   0,   0,   0, 
+      0,   0,   0,   0,   7,   0, 
+      0,   0,  17,  48,   0,   0, 
+      8,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     25,  48,   0,   0,   7,   0, 
+      0,   0,   0,   0,   0,   0, 
+      7,   0,   0,   0,  89,  52, 
+      0,   0,  97,  52,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,  29,   4,   0,   0, 
+      7,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   2,   3,   0,   0, 
+     10,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    124,  52,   0,   0,  11,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 160,  52, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,  37,   1,   0,   0, 
+      6,   0,   0,   0,   0,   0, 
+      0,   0,   7,   0,   0,   0, 
+     24,  60,   0,   0,   8,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  32,  60, 
+      0,   0,   7,   0,   0,   0, 
+      0,   0,   0,   0,   7,   0, 
+      0,   0,  96,  64,   0,   0, 
+    104,  64,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+     29,   4,   0,   0,   7,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+      2,   3,   0,   0,  10,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 134,  64, 
+      0,   0,  11,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 170,  64,   0,   0, 
+      2,   0,   0,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+    152,   1,   0,   0,   6,   0, 
+      0,   0,   0,   0,   0,   0, 
+      7,   0,   0,   0,  34,  72, 
+      0,   0,   8,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  42,  72,   0,   0, 
+      7,   0,   0,   0,   0,   0, 
+      0,   0,   7,   0,   0,   0, 
+    106,  76,   0,   0, 114,  76, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,  29,   4, 
+      0,   0,   7,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,   2,   3, 
+      0,   0,  10,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 131,  76,   0,   0, 
+     11,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    167,  76,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,  37,   1, 
+      0,   0,   6,   0,   0,   0, 
+      0,   0,   0,   0,   7,   0, 
+      0,   0,  31,  84,   0,   0, 
+      8,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+     39,  84,   0,   0,   7,   0, 
+      0,   0,   0,   0,   0,   0, 
+      7,   0,   0,   0, 119,  91, 
+      0,   0, 127,  91,   0,   0, 
+      1,   0,   0,   0,   0,   0, 
+      0,   0,  29,   4,   0,   0, 
+      7,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,   2,   3,   0,   0, 
+     10,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    153,  91,   0,   0,  11,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0, 189,  91, 
+      0,   0,   2,   0,   0,   0, 
+      0,   0,   0,   0,   2,   0, 
+      0,   0,  86,   2,   0,   0, 
+      6,   0,   0,   0,   0,   0, 
+      0,   0,   7,   0,   0,   0, 
+     53,  99,   0,   0,   8,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  61,  99, 
+      0,   0,   7,   0,   0,   0, 
+      0,   0,   0,   0,   7,   0, 
+      0,   0, 253, 104,   0,   0, 
+      5, 105,   0,   0,   1,   0, 
+      0,   0,   0,   0,   0,   0, 
+     29,   4,   0,   0,   7,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+      2,   3,   0,   0,  10,   0, 
+      0,   0,   0,   0,   0,   0, 
+      1,   0,   0,   0,  27, 105, 
+      0,   0,  11,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0,  63, 105,   0,   0, 
+      2,   0,   0,   0,   0,   0, 
+      0,   0,   2,   0,   0,   0, 
+     37,   1,   0,   0,   6,   0, 
+      0,   0,   0,   0,   0,   0, 
+      7,   0,   0,   0, 183, 112, 
+      0,   0,   8,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 191, 112,   0,   0, 
+      7,   0,   0,   0,   0,   0, 
+      0,   0,   7,   0,   0,   0, 
+    167, 115,   0,   0, 175, 115, 
+      0,   0,   1,   0,   0,   0, 
+      0,   0,   0,   0,  29,   4, 
+      0,   0,   7,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,   2,   3, 
+      0,   0,  10,   0,   0,   0, 
+      0,   0,   0,   0,   1,   0, 
+      0,   0, 206, 115,   0,   0, 
+     11,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    242, 115,   0,   0,   2,   0, 
+      0,   0,   0,   0,   0,   0, 
+      2,   0,   0,   0,  14,   2, 
+      0,   0,   6,   0,   0,   0, 
+      0,   0,   0,   0,   7,   0, 
+      0,   0, 106, 123,   0,   0, 
+      8,   0,   0,   0,   0,   0, 
+      0,   0,   1,   0,   0,   0, 
+    114, 123,   0,   0,   7,   0, 
+      0,   0,   0,   0,   0,   0, 
+      7,   0,   0,   0,  14, 126, 
+      0,   0
 };
--- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp
@@ -189,18 +189,17 @@ ThebesLayerD3D10::Validate(ReadbackProce
   if (mVisibleRegion.IsEmpty()) {
     return;
   }
 
   nsIntRect newTextureRect = mVisibleRegion.GetBounds();
 
   SurfaceMode mode = GetSurfaceMode();
   if (mode == SURFACE_COMPONENT_ALPHA &&
-      (gfxPlatform::UseAzureContentDrawing() ||
-       !mParent || !mParent->SupportsComponentAlphaChildren())) {
+      (!mParent || !mParent->SupportsComponentAlphaChildren())) {
     mode = SURFACE_SINGLE_CHANNEL_ALPHA;
   }
   // If we have a transform that requires resampling of our texture, then
   // we need to make sure we don't sample pixels that haven't been drawn.
   // We clamp sample coordinates to the texture rect, but when the visible region
   // doesn't fill the entire texture rect we need to make sure we draw all the
   // pixels in the texture rect anyway in case they get sampled.
   nsIntRegion neededRegion = mVisibleRegion;
@@ -338,60 +337,145 @@ ThebesLayerD3D10::VerifyContentType(Surf
       if (!mD2DSurface || mD2DSurface->CairoStatus()) {
         NS_WARNING("Failed to create surface for ThebesLayerD3D10.");
         mD2DSurface = nsnull;
         return;
       }
 
       mValidRegion.SetEmpty();
     }
-        
-    if (aMode != SURFACE_COMPONENT_ALPHA && mTextureOnWhite) {
-      // If we've transitioned away from component alpha, we can delete those resources.
-      mD2DSurfaceOnWhite = nsnull;
-      mSRViewOnWhite = nsnull;
-      mTextureOnWhite = nsnull;
-      mValidRegion.SetEmpty();
+  } else if (mDrawTarget) {
+    SurfaceFormat format = aMode != SURFACE_SINGLE_CHANNEL_ALPHA ?
+      FORMAT_B8G8R8X8 : FORMAT_B8G8R8A8;
+
+    if (format != mDrawTarget->GetFormat()) {
+      mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, format);
+
+      if (!mDrawTarget) {
+        NS_WARNING("Failed to create drawtarget for ThebesLayerD3D10.");
+        return;
+      }
     }
+  }    
+
+  if (aMode != SURFACE_COMPONENT_ALPHA && mTextureOnWhite) {
+    // If we've transitioned away from component alpha, we can delete those resources.
+    mD2DSurfaceOnWhite = nsnull;
+    mSRViewOnWhite = nsnull;
+    mTextureOnWhite = nsnull;
+    mValidRegion.SetEmpty();
   }
 }
 
-static void
-FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
-            const nsIntPoint& aOffset, const gfxRGBA& aColor)
+void
+ThebesLayerD3D10::SetupDualViewports(const gfxIntSize &aSize)
+{
+    D3D10_VIEWPORT viewport;
+    viewport.MaxDepth = 1.0f;
+    viewport.MinDepth = 0;
+    viewport.Width = aSize.width;
+    viewport.Height = aSize.height;
+    viewport.TopLeftX = 0;
+    viewport.TopLeftY = 0;
+
+    D3D10_VIEWPORT vps[2] = { viewport, viewport };
+    device()->RSSetViewports(2, vps);
+
+    gfx3DMatrix projection;
+    /*
+     * Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
+     * <1.0, -1.0> bottomright)
+     */
+    projection._11 = 2.0f / aSize.width;
+    projection._22 = -2.0f / aSize.height;
+    projection._33 = 0.0f;
+    projection._41 = -1.0f;
+    projection._42 = 1.0f;
+    projection._44 = 1.0f;
+
+    effect()->GetVariableByName("mProjection")->
+      SetRawValue(&projection._11, 0, 64);
+}
+
+void
+ThebesLayerD3D10::FillTexturesBlackWhite(const nsIntRegion& aRegion, const nsIntPoint& aOffset)
 {
-  if (aSurface) {
-    nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
-    ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
-    gfxUtils::PathFromRegion(ctx, aRegion);
-    ctx->SetColor(aColor);
-    ctx->Fill();
+  if (mTexture && mTextureOnWhite) {
+    // It would be more optimal to draw the actual geometry, but more code
+    // and probably not worth the win here as this will often be a single
+    // rect.
+    nsRefPtr<ID3D10RenderTargetView> oldRT;
+    device()->OMGetRenderTargets(1, getter_AddRefs(oldRT), NULL);
+
+    nsRefPtr<ID3D10RenderTargetView> viewBlack;
+    nsRefPtr<ID3D10RenderTargetView> viewWhite;
+    device()->CreateRenderTargetView(mTexture, NULL, getter_AddRefs(viewBlack));
+    device()->CreateRenderTargetView(mTextureOnWhite, NULL, getter_AddRefs(viewWhite));
+
+    D3D10_TEXTURE2D_DESC desc;
+    mTexture->GetDesc(&desc);
+
+    nsIntSize oldVP = mD3DManager->GetViewport();
+
+    SetupDualViewports(gfxIntSize(desc.Width, desc.Height));
+
+    ID3D10RenderTargetView *views[2] = { viewBlack, viewWhite };
+    device()->OMSetRenderTargets(2, views, NULL);
+
+    gfx3DMatrix transform;
+    transform.Translate(gfxPoint3D(-aOffset.x, -aOffset.y, 0));
+    void* raw = &const_cast<gfx3DMatrix&>(transform)._11;
+    effect()->GetVariableByName("mLayerTransform")->SetRawValue(raw, 0, 64);
+
+    ID3D10EffectTechnique *technique =
+      effect()->GetTechniqueByName("PrepareAlphaExtractionTextures");
+
+    nsIntRegionRectIterator iter(aRegion);
+
+    const nsIntRect *iterRect;
+    while ((iterRect = iter.Next())) {
+      effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
+        ShaderConstantRectD3D10(
+          (float)iterRect->x,
+          (float)iterRect->y,
+          (float)iterRect->width,
+          (float)iterRect->height)
+        );
+
+      technique->GetPassByIndex(0)->Apply(0);
+      device()->Draw(4, 0);
+    }
+
+    views[0] = oldRT;
+    device()->OMSetRenderTargets(1, views, NULL);
+    mD3DManager->SetViewport(oldVP);
   }
 }
 
 void
 ThebesLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
 {
   nsIntRect visibleRect = mVisibleRegion.GetBounds();
 
   if (!mD2DSurface && !mDrawTarget) {
     return;
   }
 
   nsRefPtr<gfxASurface> destinationSurface;
   
   if (aMode == SURFACE_COMPONENT_ALPHA) {
-    FillSurface(mD2DSurface, aRegion, visibleRect.TopLeft(), gfxRGBA(0.0, 0.0, 0.0, 1.0));
-    FillSurface(mD2DSurfaceOnWhite, aRegion, visibleRect.TopLeft(), gfxRGBA(1.0, 1.0, 1.0, 1.0));
-    gfxASurface* surfaces[2] = { mD2DSurface.get(), mD2DSurfaceOnWhite.get() };
-    destinationSurface = new gfxTeeSurface(surfaces, ArrayLength(surfaces));
-    // Using this surface as a source will likely go horribly wrong, since
-    // only the onBlack surface will really be used, so alpha information will
-    // be incorrect.
-    destinationSurface->SetAllowUseAsSource(false);
+    FillTexturesBlackWhite(aRegion, visibleRect.TopLeft());
+    if (!gfxPlatform::UseAzureContentDrawing()) {
+      gfxASurface* surfaces[2] = { mD2DSurface.get(), mD2DSurfaceOnWhite.get() };
+      destinationSurface = new gfxTeeSurface(surfaces, ArrayLength(surfaces));
+      // Using this surface as a source will likely go horribly wrong, since
+      // only the onBlack surface will really be used, so alpha information will
+      // be incorrect.
+      destinationSurface->SetAllowUseAsSource(false);
+    }
   } else {
     destinationSurface = mD2DSurface;
   }
 
   nsRefPtr<gfxContext> context;
 
   if (mDrawTarget) {
     context = new gfxContext(mDrawTarget);
@@ -400,17 +484,17 @@ ThebesLayerD3D10::DrawRegion(nsIntRegion
   }
 
   nsIntRegionRectIterator iter(aRegion);
   context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y));
   context->NewPath();
   const nsIntRect *iterRect;
   while ((iterRect = iter.Next())) {
     context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));      
-    if (mDrawTarget) {
+    if (mDrawTarget && aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
       mDrawTarget->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
     }
   }
   context->Clip();
 
   if (!mDrawTarget && aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
     context->SetOperator(gfxContext::OPERATOR_CLEAR);
     context->Paint();
@@ -457,24 +541,17 @@ ThebesLayerD3D10::CreateNewTextures(cons
                                                 gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA);
 
       if (!mD2DSurface || mD2DSurface->CairoStatus()) {
         NS_WARNING("Failed to create surface for ThebesLayerD3D10.");
         mD2DSurface = NULL;
         return;
       }
     } else {
-      mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, aMode != SURFACE_SINGLE_CHANNEL_ALPHA ?
-        FORMAT_B8G8R8X8 : FORMAT_B8G8R8A8);
-
-      if (!mDrawTarget) {
-        NS_WARNING("Failed to create DrawTarget for ThebesLayerD3D10.");
-        mDrawTarget = nsnull;
-        return;
-      }
+      mDrawTarget = nsnull;
     }
   }
 
   if (aMode == SURFACE_COMPONENT_ALPHA && !mTextureOnWhite) {
     hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTextureOnWhite));
 
     if (FAILED(hr)) {
       NS_WARNING("Failed to create new texture for ThebesLayerD3D10!");
@@ -482,21 +559,40 @@ ThebesLayerD3D10::CreateNewTextures(cons
     }
 
     hr = device()->CreateShaderResourceView(mTextureOnWhite, NULL, getter_AddRefs(mSRViewOnWhite));
 
     if (FAILED(hr)) {
       NS_WARNING("Failed to create shader resource view for ThebesLayerD3D10.");
     }
 
-    mD2DSurfaceOnWhite = new gfxD2DSurface(mTextureOnWhite, gfxASurface::CONTENT_COLOR);
+    if (!gfxPlatform::UseAzureContentDrawing()) {
+      mD2DSurfaceOnWhite = new gfxD2DSurface(mTextureOnWhite, gfxASurface::CONTENT_COLOR);
 
-    if (!mD2DSurfaceOnWhite || mD2DSurfaceOnWhite->CairoStatus()) {
-      NS_WARNING("Failed to create surface for ThebesLayerD3D10.");
-      mD2DSurfaceOnWhite = nsnull;
+      if (!mD2DSurfaceOnWhite || mD2DSurfaceOnWhite->CairoStatus()) {
+        NS_WARNING("Failed to create surface for ThebesLayerD3D10.");
+        mD2DSurfaceOnWhite = nsnull;
+        return;
+      }
+    } else {
+      mDrawTarget = nsnull;
+    }
+  }
+
+  if (gfxPlatform::UseAzureContentDrawing() && !mDrawTarget) {
+    if (aMode == SURFACE_COMPONENT_ALPHA) {
+      mDrawTarget = Factory::CreateDualDrawTargetForD3D10Textures(mTexture, mTextureOnWhite, FORMAT_B8G8R8X8);
+    } else {
+      mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, aMode != SURFACE_SINGLE_CHANNEL_ALPHA ?
+        FORMAT_B8G8R8X8 : FORMAT_B8G8R8A8);
+    }
+
+    if (!mDrawTarget) {
+      NS_WARNING("Failed to create DrawTarget for ThebesLayerD3D10.");
+      mDrawTarget = nsnull;
       return;
     }
   }
 }
  
 ShadowThebesLayerD3D10::ShadowThebesLayerD3D10(LayerManagerD3D10* aManager)
   : ShadowThebesLayer(aManager, NULL)
   , LayerD3D10(aManager)
--- a/gfx/layers/d3d10/ThebesLayerD3D10.h
+++ b/gfx/layers/d3d10/ThebesLayerD3D10.h
@@ -92,16 +92,21 @@ private:
   nsRefPtr<gfxASurface> mD2DSurfaceOnWhite;
 
   /* Have a region of our layer drawn */
   void DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode);
 
   /* Create a new texture */
   void CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode);
 
+  void SetupDualViewports(const gfxIntSize &aSize);
+  
+  // Fill textures with opaque black and white in the specified region.
+  void FillTexturesBlackWhite(const nsIntRegion& aRegion, const nsIntPoint& aOffset);
+
   /* Copy a texture region */
   void CopyRegion(ID3D10Texture2D* aSrc, const nsIntPoint &aSrcOffset,
                   ID3D10Texture2D* aDest, const nsIntPoint &aDestOffset,
                   const nsIntRegion &aCopyRegion, nsIntRegion* aValidRegion);
 };
 
 class ShadowThebesLayerD3D10 : public ShadowThebesLayer,
                                public LayerD3D10
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -2331,29 +2331,29 @@ public:
     }
     bool CanHyphenateBefore(PRUint32 aPos) {
         NS_ASSERTION(aPos < mCharacterCount, "aPos out of range");
         return mCharacterGlyphs[aPos].CanBreakBefore() ==
             CompressedGlyph::FLAG_BREAK_TYPE_HYPHEN;
     }
 
     bool CharIsSpace(PRUint32 aPos) {
-        NS_ASSERTION(0 <= aPos && aPos < mCharacterCount, "aPos out of range");
+        NS_ASSERTION(aPos < mCharacterCount, "aPos out of range");
         return mCharacterGlyphs[aPos].CharIsSpace();
     }
     bool CharIsTab(PRUint32 aPos) {
-        NS_ASSERTION(0 <= aPos && aPos < mCharacterCount, "aPos out of range");
+        NS_ASSERTION(aPos < mCharacterCount, "aPos out of range");
         return mCharacterGlyphs[aPos].CharIsTab();
     }
     bool CharIsNewline(PRUint32 aPos) {
-        NS_ASSERTION(0 <= aPos && aPos < mCharacterCount, "aPos out of range");
+        NS_ASSERTION(aPos < mCharacterCount, "aPos out of range");
         return mCharacterGlyphs[aPos].CharIsNewline();
     }
     bool CharIsLowSurrogate(PRUint32 aPos) {
-        NS_ASSERTION(0 <= aPos && aPos < mCharacterCount, "aPos out of range");
+        NS_ASSERTION(aPos < mCharacterCount, "aPos out of range");
         return mCharacterGlyphs[aPos].CharIsLowSurrogate();
     }
 
     PRUint32 GetLength() { return mCharacterCount; }
 
     // All PRUint32 aStart, PRUint32 aLength ranges below are restricted to
     // grapheme cluster boundaries! All offsets are in terms of the string
     // passed into MakeTextRun.
new file mode 100644
--- /dev/null
+++ b/gfx/ycbcr/QuellGccWarnings.patch
@@ -0,0 +1,40 @@
+diff --git a/gfx/ycbcr/yuv_convert.cpp b/gfx/ycbcr/yuv_convert.cpp
+--- a/gfx/ycbcr/yuv_convert.cpp
++++ b/gfx/ycbcr/yuv_convert.cpp
+@@ -337,16 +337,17 @@ NS_GFX_(void) ScaleYCbCrToRGB32(const ui
+                                          source_dx_uv >> kFractionBits);
+         }
+       }
+       else {
+         ScaleYUVToRGB32Row_C(y_ptr, u_ptr, v_ptr,
+                              dest_pixel, width, source_dx);
+       }
+ #else
++      (void)source_dx_uv;
+       ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
+                          dest_pixel, width, source_dx);
+ #endif
+     }
+   }
+   // MMX used for FastConvertYUVToRGB32Row and FilterRows requires emms.
+   if (has_mmx)
+     EMMS();
+diff --git a/gfx/ycbcr/yuv_row.h b/gfx/ycbcr/yuv_row.h
+--- a/gfx/ycbcr/yuv_row.h
++++ b/gfx/ycbcr/yuv_row.h
+@@ -129,14 +129,14 @@ extern SIMD_ALIGNED(int16 kCoefficientsR
+ #if defined(ARCH_CPU_X86) && !defined(ARCH_CPU_X86_64)
+ #if defined(_MSC_VER)
+ #define EMMS() __asm emms
+ #pragma warning(disable: 4799)
+ #else
+ #define EMMS() asm("emms")
+ #endif
+ #else
+-#define EMMS()
++#define EMMS() ((void)0)
+ #endif
+ 
+ }  // extern "C"
+ 
+ #endif  // MEDIA_BASE_YUV_ROW_H_
--- a/gfx/ycbcr/README
+++ b/gfx/ycbcr/README
@@ -20,8 +20,10 @@ convert.patch contains the following cha
   * Add YCbCr 4:4:4 support
   * Bug 619178 - Update CPU detection in yuv_convert to new SSE.h interface.
   * Bug 616778 - Split yuv_convert FilterRows vectorized code into separate files so it can
     be properly guarded with cpuid() calls.
 
 win64.patch: SSE2 optimization for Microsoft Visual C++ x64 version
 
 TypeFromSize.patch: Bug 656185 - Add a method to detect YUVType from plane sizes.
+
+QuellGccWarnings.patch: Bug 711895 - Avoid some GCC compilation warnings.
--- a/gfx/ycbcr/update.sh
+++ b/gfx/ycbcr/update.sh
@@ -4,8 +4,9 @@ cp $1/media/base/yuv_convert.cc yuv_conv
 cp $1/media/base/yuv_row.h .
 cp $1/media/base/yuv_row_table.cc yuv_row_table.cpp
 cp $1/media/base/yuv_row_posix.cc yuv_row_posix.cpp
 cp $1/media/base/yuv_row_win.cc yuv_row_win.cpp
 cp $1/media/base/yuv_row_posix.cc yuv_row_c.cpp
 patch -p3 <convert.patch
 patch -p3 <win64.patch
 patch -p3 <TypeFromSize.patch
+patch -p3 <QuellGccWarnings.patch
--- a/gfx/ycbcr/yuv_convert.cpp
+++ b/gfx/ycbcr/yuv_convert.cpp
@@ -337,16 +337,17 @@ NS_GFX_(void) ScaleYCbCrToRGB32(const ui
                                          source_dx_uv >> kFractionBits);
         }
       }
       else {
         ScaleYUVToRGB32Row_C(y_ptr, u_ptr, v_ptr,
                              dest_pixel, width, source_dx);
       }
 #else
+      (void)source_dx_uv;
       ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr,
                          dest_pixel, width, source_dx);
 #endif
     }
   }
   // MMX used for FastConvertYUVToRGB32Row and FilterRows requires emms.
   if (has_mmx)
     EMMS();
--- a/gfx/ycbcr/yuv_row.h
+++ b/gfx/ycbcr/yuv_row.h
@@ -129,14 +129,14 @@ extern SIMD_ALIGNED(int16 kCoefficientsR
 #if defined(ARCH_CPU_X86) && !defined(ARCH_CPU_X86_64)
 #if defined(_MSC_VER)
 #define EMMS() __asm emms
 #pragma warning(disable: 4799)
 #else
 #define EMMS() asm("emms")
 #endif
 #else
-#define EMMS()
+#define EMMS() ((void)0)
 #endif
 
 }  // extern "C"
 
 #endif  // MEDIA_BASE_YUV_ROW_H_
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -875,31 +875,33 @@ RasterImage::GetFrame(PRUint32 aWhichFra
     return NS_ERROR_FAILURE;
 
   // Disallowed in the API
   if (mInDecoder && (aFlags & imgIContainer::FLAG_SYNC_DECODE))
     return NS_ERROR_FAILURE;
 
   nsresult rv = NS_OK;
 
-  // If we have decoded data, and it is not a perfect match for what we are
-  // looking for, we must discard to be able to generate the proper data.
-  PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
-  if (desiredDecodeFlags != mFrameDecodeFlags) {
-    // if we can't discard, then we're screwed; we have no way
-    // to re-decode.  Similarly if we aren't allowed to do a sync
-    // decode.
-    if (!(aFlags & FLAG_SYNC_DECODE))
-      return NS_ERROR_NOT_AVAILABLE;
-    if (!CanForciblyDiscard() || mDecoder || mAnim)
-      return NS_ERROR_NOT_AVAILABLE;
-
-    ForceDiscard();
-
-    mFrameDecodeFlags = desiredDecodeFlags;
+  if (mDecoded) {
+    // If we have decoded data, and it is not a perfect match for what we are
+    // looking for, we must discard to be able to generate the proper data.
+    PRUint32 desiredDecodeFlags = aFlags & DECODE_FLAGS_MASK;
+    if (desiredDecodeFlags != mFrameDecodeFlags) {
+      // if we can't discard, then we're screwed; we have no way
+      // to re-decode.  Similarly if we aren't allowed to do a sync
+      // decode.
+      if (!(aFlags & FLAG_SYNC_DECODE))
+        return NS_ERROR_NOT_AVAILABLE;
+      if (!CanForciblyDiscard() || mDecoder || mAnim)
+        return NS_ERROR_NOT_AVAILABLE;
+  
+      ForceDiscard();
+  
+      mFrameDecodeFlags = desiredDecodeFlags;
+    }
   }
 
   // If the caller requested a synchronous decode, do it
   if (aFlags & FLAG_SYNC_DECODE) {
     rv = SyncDecode();
     CONTAINER_ENSURE_SUCCESS(rv);
   }
 
--- a/js/jsd/jsd.h
+++ b/js/jsd/jsd.h
@@ -374,20 +374,16 @@ jsd_SetErrorReporter(JSDContext*       j
                      JSD_ErrorReporter reporter,
                      void*             callerdata);
 
 extern JSBool
 jsd_GetErrorReporter(JSDContext*        jsdc,
                      JSD_ErrorReporter* reporter,
                      void**             callerdata);
 
-static JSBool
-jsd_DebugErrorHook(JSContext *cx, const char *message,
-                   JSErrorReport *report, void *closure);
-
 /***************************************************************************/
 /* Script functions */
 
 extern JSBool
 jsd_InitScriptManager(JSDContext *jsdc);
 
 extern void
 jsd_DestroyScriptManager(JSDContext* jsdc);
--- a/js/jsd/jsd_high.c
+++ b/js/jsd/jsd_high.c
@@ -271,16 +271,20 @@ jsd_DebuggerPause(JSDContext* jsdc, JSBo
     if (forceAllHooksOff || !(jsdc->flags & JSD_COLLECT_PROFILE_DATA)) {
         JS_SetExecuteHook(jsdc->jsrt, NULL, NULL);
         JS_SetCallHook(jsdc->jsrt, NULL, NULL);
     }
     JS_SetThrowHook(jsdc->jsrt, NULL, NULL);
     JS_SetDebugErrorHook(jsdc->jsrt, NULL, NULL);
 }
 
+static JSBool
+jsd_DebugErrorHook(JSContext *cx, const char *message,
+                   JSErrorReport *report, void *closure);
+
 void
 jsd_DebuggerUnpause(JSDContext* jsdc)
 {
     JS_SetDebuggerHandler(jsdc->jsrt, jsd_DebuggerHandler, jsdc);
     JS_SetExecuteHook(jsdc->jsrt, jsd_TopLevelCallHook, jsdc);
     JS_SetCallHook(jsdc->jsrt, jsd_FunctionCallHook, jsdc);
     JS_SetThrowHook(jsdc->jsrt, jsd_ThrowHandler, jsdc);
     JS_SetDebugErrorHook(jsdc->jsrt, jsd_DebugErrorHook, jsdc);
--- a/js/src/build/autoconf/compiler-opts.m4
+++ b/js/src/build/autoconf/compiler-opts.m4
@@ -77,8 +77,54 @@ if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -
         fi
         rm -rf conftest*])
     if test "$GC_SECTIONS_BREAKS_DEBUG_RANGES" = no; then
         DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections"
     fi
 fi
 
 ])
+
+dnl GCC and clang will fail if given an unknown warning option like -Wfoobar. 
+dnl But later versions won't fail if given an unknown negated warning option
+dnl like -Wno-foobar.  So when we are check for support of negated warning 
+dnl options, we actually test the positive form, but add the negated form to 
+dnl the flags variable.
+
+AC_DEFUN([MOZ_C_SUPPORTS_WARNING],
+[
+    AC_CACHE_CHECK(whether the C compiler supports $1$2, $3,
+        [
+            AC_LANG_SAVE
+            AC_LANG_C
+            _SAVE_CFLAGS="$CFLAGS"
+            CFLAGS="$CFLAGS -Werror -W$2"
+            AC_TRY_COMPILE([],
+                           [return(0);],
+                           $3="yes",
+                           $3="no")
+            CFLAGS="$_SAVE_CFLAGS"
+            AC_LANG_RESTORE
+        ])
+    if test "${$3}" = "yes"; then
+        _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} $1$2"
+    fi
+])
+
+AC_DEFUN([MOZ_CXX_SUPPORTS_WARNING],
+[
+    AC_CACHE_CHECK(whether the C++ compiler supports $1$2, $3,
+        [
+            AC_LANG_SAVE
+            AC_LANG_CPLUSPLUS
+            _SAVE_CXXFLAGS="$CXXFLAGS"
+            CXXFLAGS="$CXXFLAGS -Werror -W$2"
+            AC_TRY_COMPILE([],
+                           [return(0);],
+                           $3="yes",
+                           $3="no")
+            CXXFLAGS="$_SAVE_CXXFLAGS"
+            AC_LANG_RESTORE
+        ])
+    if test "${$3}" = "yes"; then
+        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} $1$2"
+    fi
+])
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -1622,45 +1622,55 @@ if test "$GNU_CC"; then
     fi
     WARNINGS_AS_ERRORS='-Werror -Wno-error=uninitialized'
     DSO_CFLAGS=''
     DSO_PIC_CFLAGS='-fPIC'
     ASFLAGS="$ASFLAGS -fPIC"
     _MOZ_RTTI_FLAGS_ON=-frtti
     _MOZ_RTTI_FLAGS_OFF=-fno-rtti
 
-    # Turn on GNU specific features
-    # -Wall - turn on all warnings
-    # -pedantic - make compiler warn about non-ANSI stuff, and
-    #             be a little bit stricter
-    # Warnings slamm took out for now (these were giving more noise than help):
-    # -Wbad-function-cast - warns when casting a function to a new return type
-    # -Wshadow - removed because it generates more noise than help --pete
-    _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -W -Wno-unused -Wpointer-arith"
+    # Turn on GNU-specific warnings:
+    # -Wall - turn on a lot of warnings
+    # -pedantic - this is turned on below
+    # -Wpointer-arith - enabled with -pedantic, but good to have even if not
+    # -Wdeclaration-after-statement - MSVC doesn't like these
+    # -Werror=return-type - catches missing returns, zero false positives
+    # -Wtype-limits - catches overflow bugs, few false positives
+    # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
+    #
+    _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wall -Wpointer-arith -Wdeclaration-after-statement"
+    MOZ_C_SUPPORTS_WARNING(-W, error=return-type, ac_c_has_werror_return_type)
+    MOZ_C_SUPPORTS_WARNING(-W, type-limits, ac_c_has_wtype_limits)
+    MOZ_C_SUPPORTS_WARNING(-W, empty-body, ac_c_has_wempty_body)
+    
+    # Turn off the following warnings that -Wall/-pedantic turn on:
+    # -Wno-unused - lots of violations in third-party code
+    # -Wno-overlength-strings - we exceed the minimum maximum length frequently
+    #
+    _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wno-unused"
+    MOZ_C_SUPPORTS_WARNING(-Wno-, overlength-strings, ac_c_has_wno_overlength_strings)
+
     if test -z "$INTEL_CC" -a -z "$CLANG_CC"; then
        # Don't use -Wcast-align with ICC or clang
        case "$CPU_ARCH" in
            # And don't use it on hppa, ia64, sparc, arm, since it's noisy there
            hppa | ia64 | sparc | arm)
            ;;
            *)
         _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -Wcast-align"
            ;;
        esac
     fi
 
     dnl Turn pedantic on but disable the warnings for long long
     _PEDANTIC=1
 
-    if test -z "$INTEL_CC"; then
-      _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} -W"
-    fi
-
     _DEFINES_CFLAGS='-include $(DEPTH)/js-confdefs.h -DMOZILLA_CLIENT'
     _USE_CPP_INCLUDE_FLAG=1
+
 elif test "$SOLARIS_SUNPRO_CC"; then
     DSO_CFLAGS=''
     if test "$CPU_ARCH" = "sparc"; then
         # for Sun Studio on Solaris/SPARC
         DSO_PIC_CFLAGS='-xcode=pic32'
     else
         DSO_PIC_CFLAGS='-KPIC'
     fi
@@ -1676,18 +1686,41 @@ else
     fi
 
     DSO_CFLAGS=''
     DSO_PIC_CFLAGS='-KPIC'
     _DEFINES_CFLAGS='$(ACDEFINES) -D_JS_CONFDEFS_H_ -DMOZILLA_CLIENT'
 fi
 
 if test "$GNU_CXX"; then
-    # Turn on GNU specific features
-    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor"
+    # Turn on GNU-specific warnings:
+    # -Wall - turn on a lot of warnings
+    # -pedantic - this is turned on below
+    # -Wpointer-arith - enabled with -pedantic, but good to have even if not
+    # -Woverloaded-virtual - ???
+    # -Werror=return-type - catches missing returns, zero false positives
+    # -Wtype-limits - catches overflow bugs, few false positives
+    # -Wempty-body - catches bugs, e.g. "if (c); foo();", few false positives
+    #
+    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall -Wpointer-arith -Woverloaded-virtual"
+    MOZ_CXX_SUPPORTS_WARNING(-W, error=return-type, ac_cxx_has_werror_return_type)
+    MOZ_CXX_SUPPORTS_WARNING(-W, type-limits, ac_cxx_has_wtype_limits)
+    MOZ_CXX_SUPPORTS_WARNING(-W, empty-body, ac_cxx_has_wempty_body)
+
+    # Turn off the following warnings that -Wall/-pedantic turn on:
+    # -Wno-ctor-dtor-privacy - ???
+    # -Wno-overlength-strings - we exceed the minimum maximum length frequently
+    # -Wno-invalid-offsetof - we use offsetof on non-POD types frequently
+    # -Wno-variadic-macros - ???
+    #
+    _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-ctor-dtor-privacy"
+    MOZ_CXX_SUPPORTS_WARNING(-Wno-, overlength-strings, ac_cxx_has_wno_overlength_strings)
+    MOZ_CXX_SUPPORTS_WARNING(-Wno-, invalid-offsetof, ac_cxx_has_wno_invalid_offsetof)
+    MOZ_CXX_SUPPORTS_WARNING(-Wno-, variadic-macros, ac_cxx_has_wno_variadic_macros)
+
     if test -z "$INTEL_CXX" -a -z "$CLANG_CXX"; then
        # Don't use -Wcast-align with ICC or clang
        case "$CPU_ARCH" in
            # And don't use it on hppa, ia64, sparc, arm, since it's noisy there
            hppa | ia64 | sparc | arm)
            ;;
            *)
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wcast-align"
@@ -1701,91 +1734,17 @@ if test "$GNU_CXX"; then
     # Recent clang and gcc support C++11 deleted functions without warnings if
     # compiling with -std=c++0x or -std=gnu++0x (or c++11 or gnu++11 in very new
     # versions).  We can't use -std=c++0x yet, so gcc's support must remain
     # unused.  But clang's warning can be disabled, so when compiling with clang
     # we use it to opt out of the warning, enabling (macro-encapsulated) use of
     # deleted function syntax.
     if test "$CLANG_CXX"; then
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-c++0x-extensions"
-    fi
-
-    AC_CACHE_CHECK(whether the compiler supports -Wno-extended-offsetof,
-                   ac_has_wno_extended_offsetof,
-        [
-            AC_LANG_SAVE
-            AC_LANG_CPLUSPLUS
-            _SAVE_CXXFLAGS="$CXXFLAGS"
-            CXXFLAGS="$CXXFLAGS -Wno-extended-offsetof"
-            AC_TRY_COMPILE([$configure_static_assert_macros
-                            #ifndef __has_warning
-                            #define __has_warning(x) 0
-                            #endif],
-                           [CONFIGURE_STATIC_ASSERT(__has_warning("-Wextended-offsetof"))],
-                           ac_has_wno_extended_offsetof="yes",
-                           ac_has_wno_extended_offsetof="no")
-            CXXFLAGS="$_SAVE_CXXFLAGS"
-            AC_LANG_RESTORE
-        ])
-    if test "$ac_has_wno_extended_offsetof" = "yes"; then
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-extended-offsetof"
-    fi
-
-    AC_CACHE_CHECK(whether the compiler supports -Wno-invalid-offsetof,
-                   ac_has_wno_invalid_offsetof,
-        [
-            AC_LANG_SAVE
-            AC_LANG_CPLUSPLUS
-            _SAVE_CXXFLAGS="$CXXFLAGS"
-            CXXFLAGS="$CXXFLAGS -Wno-invalid-offsetof"
-            AC_TRY_COMPILE([],
-                           [return(0);],
-                           ac_has_wno_invalid_offsetof="yes",
-                           ac_has_wno_invalid_offsetof="no")
-            CXXFLAGS="$_SAVE_CXXFLAGS"
-            AC_LANG_RESTORE
-        ])
-    if test "$ac_has_wno_invalid_offsetof" = "yes"; then
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-invalid-offsetof"
-    fi
-
-    AC_CACHE_CHECK(whether the compiler supports -Wno-variadic-macros,
-                   ac_has_wno_variadic_macros,
-        [
-            AC_LANG_SAVE
-            AC_LANG_CPLUSPLUS
-            _SAVE_CXXFLAGS="$CXXFLAGS"
-            CXXFLAGS="$CXXFLAGS -Wno-variadic-macros"
-            AC_TRY_COMPILE([],
-                           [return(0);],
-                           ac_has_wno_variadic_macros="yes",
-                           ac_has_wno_variadic_macros="no")
-            CXXFLAGS="$_SAVE_CXXFLAGS"
-            AC_LANG_RESTORE
-        ])
-    if test "$ac_has_wno_variadic_macros" = "yes"; then
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-variadic-macros"
-    fi
-
-    AC_CACHE_CHECK(whether the compiler supports -Werror=return-type,
-                   ac_has_werror_return_type,
-        [
-            AC_LANG_SAVE
-            AC_LANG_CPLUSPLUS
-            _SAVE_CXXFLAGS="$CXXFLAGS"
-            CXXFLAGS="$CXXFLAGS -Werror=return-type"
-            AC_TRY_COMPILE([],
-                           [return(0);],
-                           ac_has_werror_return_type="yes",
-                           ac_has_werror_return_type="no")
-            CXXFLAGS="$_SAVE_CXXFLAGS"
-            AC_LANG_RESTORE
-        ])
-    if test "$ac_has_werror_return_type" = "yes"; then
-        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=return-type"
+        MOZ_CXX_SUPPORTS_WARNING(-Wno-, extended-offsetof, ac_cxx_has_wno_extended_offsetof)
     fi
 
 else
     _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -D_JS_CONFDEFS_H_ $(ACDEFINES)'
 fi
 
 dnl gcc can come with its own linker so it is better to use the pass-thru calls
 dnl MKSHLIB_FORCE_ALL is used to force the linker to include all object
--- a/js/src/ctypes/CTypes.cpp
+++ b/js/src/ctypes/CTypes.cpp
@@ -51,16 +51,22 @@
 #if defined(SOLARIS)
 #include <ieeefp.h>
 #endif
 
 #ifdef HAVE_SSIZE_T
 #include <sys/types.h>
 #endif
 
+#if defined(XP_UNIX)
+#include <errno.h>
+#elif defined(XP_WIN)
+#include <windows.h>
+#endif
+
 using namespace std;
 
 namespace js {
 namespace ctypes {
 
 /*******************************************************************************
 ** JSAPI function prototypes
 *******************************************************************************/
@@ -81,16 +87,27 @@ namespace CType {
     jsval* vp);
   static JSBool SizeGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
   static JSBool PtrGetter(JSContext* cx, JSObject* obj, jsid idval, jsval* vp);
   static JSBool CreateArray(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToString(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool HasInstance(JSContext* cx, JSObject* obj, const jsval* v, JSBool* bp);
+
+
+  /**
+   * Get the global "ctypes" object.
+   *
+   * |obj| must be a CType object.
+   *
+   * This function never returns NULL.
+   */
+  static JSObject* GetGlobalCTypes(JSContext* cx, JSObject* obj);
+
 }
 
 namespace PointerType {
   static JSBool Create(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ConstructData(JSContext* cx, JSObject* obj, unsigned argc, jsval* vp);
 
   static JSBool TargetTypeGetter(JSContext* cx, JSObject* obj, jsid idval,
     jsval* vp);
@@ -163,16 +180,24 @@ namespace CData {
 
   static JSBool ValueGetter(JSContext* cx, JSObject* obj, jsid idval,
                             jsval* vp);
   static JSBool ValueSetter(JSContext* cx, JSObject* obj, jsid idval,
                             JSBool strict, jsval* vp);
   static JSBool Address(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ReadString(JSContext* cx, unsigned argc, jsval* vp);
   static JSBool ToSource(JSContext* cx, unsigned argc, jsval* vp);
+
+  static JSBool ErrnoGetter(JSContext* cx, JSObject *obj, jsid idval,
+                            jsval* vp);
+
+#if defined(XP_WIN)
+  static JSBool LastErrorGetter(JSContext* cx, JSObject *obj, jsid idval,
+                                jsval* vp);
+#endif // defined(XP_WIN)
 }
 
 // Int64Base provides functions common to Int64 and UInt64.
 namespace Int64Base {
   JSObject* Construct(JSContext* cx, JSObject* proto, uint64_t data,
     bool isUnsigned);
 
   uint64_t GetInt(JSObject* obj);
@@ -437,16 +462,26 @@ static JSFunctionSpec sInt64Functions[] 
 };
 
 static JSFunctionSpec sUInt64Functions[] = {
   JS_FN("toString", UInt64::ToString, 0, CTYPESFN_FLAGS),
   JS_FN("toSource", UInt64::ToSource, 0, CTYPESFN_FLAGS),
   JS_FS_END
 };
 
+static JSPropertySpec sModuleProps[] = {
+  { "errno", 0, JSPROP_SHARED | JSPROP_PERMANENT,
+    CData::ErrnoGetter, NULL },
+#if defined(XP_WIN)
+  { "winLastError", 0, JSPROP_SHARED | JSPROP_PERMANENT,
+    CData::LastErrorGetter, NULL },
+#endif // defined(XP_WIN)
+  { 0, 0, 0, NULL, NULL }
+};
+
 static JSFunctionSpec sModuleFunctions[] = {
   JS_FN("open", Library::Open, 1, CTYPESFN_FLAGS),
   JS_FN("cast", CData::Cast, 2, CTYPESFN_FLAGS),
   JS_FN("getRuntime", CData::GetRuntime, 1, CTYPESFN_FLAGS),
   JS_FN("libraryName", Library::Name, 1, CTYPESFN_FLAGS),
   JS_FS_END
 };
 
@@ -724,19 +759,19 @@ InitInt64Class(JSContext* cx,
 
   return prototype;
 }
 
 static void
 AttachProtos(JSObject* proto, JSObject** protos)
 {
   // For a given 'proto' of [[Class]] "CTypeProto", attach each of the 'protos'
-  // to the appropriate CTypeProtoSlot. (SLOT_UINT64PROTO is the last slot
+  // to the appropriate CTypeProtoSlot. (SLOT_CTYPES is the last slot
   // of [[Class]] "CTypeProto" that we fill in this automated manner.)
-  for (uint32_t i = 0; i <= SLOT_UINT64PROTO; ++i)
+  for (uint32_t i = 0; i <= SLOT_CTYPES; ++i)
     JS_SetReservedSlot(proto, i, OBJECT_TO_JSVAL(protos[i]));
 }
 
 JSBool
 InitTypeClasses(JSContext* cx, JSObject* parent)
 {
   // Initialize the ctypes.CType class. This acts as an abstract base class for
   // the various types, and provides the common API functions. It has:
@@ -842,16 +877,20 @@ InitTypeClasses(JSContext* cx, JSObject*
     Int64::Construct, sInt64Functions, sInt64StaticFunctions);
   if (!protos[SLOT_INT64PROTO])
     return false;
   protos[SLOT_UINT64PROTO] = InitInt64Class(cx, parent, &sUInt64ProtoClass,
     UInt64::Construct, sUInt64Functions, sUInt64StaticFunctions);
   if (!protos[SLOT_UINT64PROTO])
     return false;
 
+  // Finally, store a pointer to the global ctypes object.
+  // Note that there is no other reliable manner of locating this object.
+  protos[SLOT_CTYPES] = parent;
+
   // Attach the prototypes just created to each of ctypes.CType.prototype,
   // and the special type constructors, so we can access them when constructing
   // instances of those types. 
   AttachProtos(CTypeProto, protos);
   AttachProtos(protos[SLOT_POINTERPROTO], protos);
   AttachProtos(protos[SLOT_ARRAYPROTO], protos);
   AttachProtos(protos[SLOT_STRUCTPROTO], protos);
   AttachProtos(protos[SLOT_FUNCTIONPROTO], protos);
@@ -937,18 +976,19 @@ JS_InitCTypesClass(JSContext* cx, JSObje
   if (!JS_DefineProperty(cx, global, "ctypes", OBJECT_TO_JSVAL(ctypes),
          JS_PropertyStub, JS_StrictPropertyStub, JSPROP_READONLY | JSPROP_PERMANENT)) {
     return false;
   }
 
   if (!InitTypeClasses(cx, ctypes))
     return false;
 
-  // attach API functions
-  if (!JS_DefineFunctions(cx, ctypes, sModuleFunctions))
+  // attach API functions and properties
+  if (!JS_DefineFunctions(cx, ctypes, sModuleFunctions) ||
+      !JS_DefineProperties(cx, ctypes, sModuleProps))
     return false;
 
   // Seal the ctypes object, to prevent modification.
   return JS_FreezeObject(cx, ctypes);
 }
 
 JS_PUBLIC_API(void)
 JS_SetCTypesCallbacks(JSObject* ctypesObj,
@@ -3221,16 +3261,33 @@ CType::HasInstance(JSContext* cx, JSObje
     if (proto == prototype) {
       *bp = JS_TRUE;
       break;
     }
   }
   return JS_TRUE;
 }
 
+static JSObject*
+CType::GetGlobalCTypes(JSContext* cx, JSObject* obj)
+{
+  JS_ASSERT(CType::IsCType(obj));
+
+  JSObject *objTypeProto = JS_GetPrototype(obj);
+  if (!objTypeProto) {
+  }
+  JS_ASSERT(objTypeProto);
+  JS_ASSERT(CType::IsCTypeProto(objTypeProto));
+
+  jsval valCTypes = JS_GetReservedSlot(objTypeProto, SLOT_CTYPES);
+  JS_ASSERT(!JSVAL_IS_PRIMITIVE(valCTypes));
+
+  return JSVAL_TO_OBJECT(valCTypes);
+}
+
 /*******************************************************************************
 ** PointerType implementation
 *******************************************************************************/
 
 JSBool
 PointerType::Create(JSContext* cx, unsigned argc, jsval* vp)
 {
   // Construct and return a new PointerType object.
@@ -5144,23 +5201,55 @@ FunctionType::Call(JSContext* cx,
   if (typeCode != TYPE_void_t &&
       !returnValue.SizeToType(cx, fninfo->mReturnType)) {
     JS_ReportAllocationOverflow(cx);
     return false;
   }
 
   uintptr_t fn = *reinterpret_cast<uintptr_t*>(CData::GetData(obj));
 
+#if defined(XP_WIN)
+  int32_t lastErrorStatus; // The status as defined by |GetLastError|
+  int32_t savedLastError = GetLastError();
+  SetLastError(0);
+#endif //defined(XP_WIN)
+  int errnoStatus;         // The status as defined by |errno|
+  int savedErrno = errno;
+  errno = 0;
+
   // suspend the request before we call into the function, since the call
   // may block or otherwise take a long time to return.
   {
     JSAutoSuspendRequest suspend(cx);
     ffi_call(&fninfo->mCIF, FFI_FN(fn), returnValue.mData,
              reinterpret_cast<void**>(values.begin()));
-  }
+
+    // Save error value.
+    // We need to save it before leaving the scope of |suspend| as destructing
+    // |suspend| has the side-effect of clearing |GetLastError|
+    // (see bug 684017).
+
+    errnoStatus = errno;
+#if defined(XP_WIN)
+    lastErrorStatus = GetLastError();
+#endif // defined(XP_WIN)
+  }
+#if defined(XP_WIN)
+  SetLastError(savedLastError);
+#endif // defined(XP_WIN)
+
+  errno = savedErrno;
+
+  // Store the error value for later consultation with |ctypes.getStatus|
+  JSObject *objCTypes = CType::GetGlobalCTypes(cx, typeObj);
+
+  JS_SetReservedSlot(objCTypes, SLOT_ERRNO, INT_TO_JSVAL(errnoStatus));
+#if defined(XP_WIN)
+  JS_SetReservedSlot(objCTypes, SLOT_LASTERROR, INT_TO_JSVAL(lastErrorStatus));
+#endif // defined(XP_WIN)
 
   // Small integer types get returned as a word-sized ffi_arg. Coerce it back
   // into the correct size for ConvertToJS.
   switch (typeCode) {
 #define DEFINE_INT_TYPE(name, type, ffiType)                                   \
   case TYPE_##name:                                                            \
     if (sizeof(type) < sizeof(ffi_arg)) {                                      \
       ffi_arg data = *static_cast<ffi_arg*>(returnValue.mData);                \
@@ -5971,16 +6060,43 @@ CData::ToSource(JSContext* cx, unsigned 
     result = JS_NewStringCopyZ(cx, "[CData proto object]");
   if (!result)
     return JS_FALSE;
 
   JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(result));
   return JS_TRUE;
 }
 
+JSBool
+CData::ErrnoGetter(JSContext* cx, JSObject* obj, jsid, jsval* vp)
+{
+  if (!IsCTypesGlobal(obj)) {
+    JS_ReportError(cx, "this is not not global object ctypes");
+    return JS_FALSE;
+  }
+
+  *vp = JS_GetReservedSlot(obj, SLOT_ERRNO);
+  return JS_TRUE;
+}
+
+#if defined(XP_WIN)
+JSBool
+CData::LastErrorGetter(JSContext* cx, JSObject* obj, jsid, jsval* vp)
+{
+  if (!IsCTypesGlobal(obj)) {
+    JS_ReportError(cx, "not global object ctypes");
+    return JS_FALSE;
+  }
+
+
+  *vp = JS_GetReservedSlot(obj, SLOT_LASTERROR);
+  return JS_TRUE;
+}
+#endif // defined(XP_WIN)
+
 /*******************************************************************************
 ** Int64 and UInt64 implementation
 *******************************************************************************/
 
 JSObject*
 Int64Base::Construct(JSContext* cx,
                      JSObject* proto,
                      uint64_t data,
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -364,16 +364,18 @@ JSBool ExplicitConvert(JSContext* cx, js
   void* buffer);
 
 /*******************************************************************************
 ** JSClass reserved slot definitions
 *******************************************************************************/
 
 enum CTypesGlobalSlot {
   SLOT_CALLBACKS = 0, // pointer to JSCTypesCallbacks struct
+  SLOT_ERRNO = 1,     // jsval for latest |errno|
+  SLOT_LASTERROR = 2, // jsval for latest |GetLastError|, used only with Windows
   CTYPESGLOBAL_SLOTS
 };
 
 enum CABISlot {
   SLOT_ABICODE = 0, // ABICode of the CABI object
   CABI_SLOTS
 };
 
@@ -384,18 +386,19 @@ enum CTypeProtoSlot {
   SLOT_FUNCTIONPROTO     = 3,  // ctypes.FunctionType.prototype object
   SLOT_CDATAPROTO        = 4,  // ctypes.CData.prototype object
   SLOT_POINTERDATAPROTO  = 5,  // common ancestor of all CData objects of PointerType
   SLOT_ARRAYDATAPROTO    = 6,  // common ancestor of all CData objects of ArrayType
   SLOT_STRUCTDATAPROTO   = 7,  // common ancestor of all CData objects of StructType
   SLOT_FUNCTIONDATAPROTO = 8,  // common ancestor of all CData objects of FunctionType
   SLOT_INT64PROTO        = 9,  // ctypes.Int64.prototype object
   SLOT_UINT64PROTO       = 10, // ctypes.UInt64.prototype object
-  SLOT_OURDATAPROTO      = 11, // the data prototype corresponding to this object
-  SLOT_CLOSURECX         = 12, // JSContext for use with FunctionType closures
+  SLOT_CTYPES            = 11, // ctypes object
+  SLOT_OURDATAPROTO      = 12, // the data prototype corresponding to this object
+  SLOT_CLOSURECX         = 13, // JSContext for use with FunctionType closures
   CTYPEPROTO_SLOTS
 };
 
 enum CTypeSlot {
   SLOT_PROTO     = 0, // 'prototype' property of the CType object
   SLOT_TYPECODE  = 1, // TypeCode of the CType object
   SLOT_FFITYPE   = 2, // ffi_type representing the type
   SLOT_NAME      = 3, // name of the type
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -400,20 +400,33 @@ DoGetElement(JSContext *cx, JSObject *ob
     *hole = !present;
     if (*hole)
         vp->setUndefined();
 
     return true;
 }
 
 template<typename IndexType>
+static void
+AssertGreaterThanZero(IndexType index)
+{
+    JS_ASSERT(index >= 0);
+}
+
+template<>
+void
+AssertGreaterThanZero(uint32_t index)
+{
+}
+
+template<typename IndexType>
 static JSBool
 GetElement(JSContext *cx, JSObject *obj, IndexType index, JSBool *hole, Value *vp)
 {
-    JS_ASSERT(index >= 0);
+    AssertGreaterThanZero(index);
     if (obj->isDenseArray() && index < obj->getDenseArrayInitializedLength() &&
         !(*vp = obj->getDenseArrayElement(uint32_t(index))).isMagic(JS_ARRAY_HOLE)) {
         *hole = JS_FALSE;
         return JS_TRUE;
     }
     if (obj->isArguments()) {
         if (obj->asArguments().getElement(uint32_t(index), vp)) {
             *hole = JS_FALSE;
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -1184,25 +1184,46 @@ js_ErrorToException(JSContext *cx, const
 
     JS_SetPendingException(cx, OBJECT_TO_JSVAL(errObject));
 
     /* Flag the error report passed in to indicate an exception was raised. */
     reportp->flags |= JSREPORT_EXCEPTION;
     return true;
 }
 
+static bool
+IsDuckTypedErrorObject(JSContext *cx, JSObject *exnObject, const char **filename_strp)
+{
+    JSBool found;
+    if (!JS_HasProperty(cx, exnObject, js_message_str, &found) || !found)
+        return false;
+
+    const char *filename_str = *filename_strp;
+    if (!JS_HasProperty(cx, exnObject, filename_str, &found) || !found) {
+        /* DOMException duck quacks "filename" (all lowercase) */
+        filename_str = "filename";
+        if (!JS_HasProperty(cx, exnObject, filename_str, &found) || !found)
+            return false;
+    }
+
+    if (!JS_HasProperty(cx, exnObject, js_lineNumber_str, &found) || !found)
+        return false;
+
+    *filename_strp = filename_str;
+    return true;
+}
+
 JSBool
 js_ReportUncaughtException(JSContext *cx)
 {
     jsval exn;
     JSObject *exnObject;
-    jsval roots[5];
+    jsval roots[6];
     JSErrorReport *reportp, report;
     JSString *str;
-    const char *bytes;
 
     if (!JS_IsExceptionPending(cx))
         return true;
 
     if (!JS_GetPendingException(cx, &exn))
         return false;
 
     PodArrayZero(roots);
@@ -1221,61 +1242,85 @@ js_ReportUncaughtException(JSContext *cx
         roots[0] = exn;
     }
 
     JS_ClearPendingException(cx);
     reportp = js_ErrorFromException(cx, exn);
 
     /* XXX L10N angels cry once again. see also everywhere else */
     str = ToString(cx, exn);
-    JSAutoByteString bytesStorage;
-    if (!str) {
-        bytes = "unknown (can't convert to string)";
-    } else {
+    if (str)
         roots[1] = StringValue(str);
-        if (!bytesStorage.encode(cx, str))
-            return false;
-        bytes = bytesStorage.ptr();
-    }
 
+    const char *filename_str = js_fileName_str;
     JSAutoByteString filename;
-    if (!reportp && exnObject && exnObject->isError()) {
-        if (!JS_GetProperty(cx, exnObject, js_message_str, &roots[2]))
-            return false;
-        if (JSVAL_IS_STRING(roots[2])) {
-            bytesStorage.clear();
-            if (!bytesStorage.encode(cx, str))
-                return false;
-            bytes = bytesStorage.ptr();
+    if (!reportp && exnObject &&
+        (exnObject->isError() ||
+         IsDuckTypedErrorObject(cx, exnObject, &filename_str)))
+    {
+        JSString *name = NULL;
+        if (JS_GetProperty(cx, exnObject, js_name_str, &roots[2]) &&
+            JSVAL_IS_STRING(roots[2]))
+        {
+            name = JSVAL_TO_STRING(roots[2]);
+        }
+
+        JSString *msg = NULL;
+        if (JS_GetProperty(cx, exnObject, js_message_str, &roots[3]) &&
+            JSVAL_IS_STRING(roots[3]))
+        {
+            msg = JSVAL_TO_STRING(roots[3]);
         }
 
-        if (!JS_GetProperty(cx, exnObject, js_fileName_str, &roots[3]))
-            return false;
-        str = ToString(cx, roots[3]);
-        if (!str || !filename.encode(cx, str))
-            return false;
+        if (name && msg) {
+            JSString *colon = JS_NewStringCopyZ(cx, ": ");
+            if (!colon)
+                return false;
+            JSString *nameColon = JS_ConcatStrings(cx, name, colon);
+            if (!nameColon)
+                return false;
+            str = JS_ConcatStrings(cx, nameColon, msg);
+            if (!str)
+                return false;
+        } else if (name) {
+            str = name;
+        } else if (msg) {
+            str = msg;
+        }
 
-        if (!JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[4]))
-            return false;
+        if (JS_GetProperty(cx, exnObject, filename_str, &roots[4])) {
+            JSString *tmp = ToString(cx, roots[4]);
+            if (tmp)
+                filename.encode(cx, tmp);
+        }
+
         uint32_t lineno;
-        if (!ToUint32(cx, roots[4], &lineno))
-            return false;
+        if (!JS_GetProperty(cx, exnObject, js_lineNumber_str, &roots[5]) ||
+            !ToUint32(cx, roots[5], &lineno))
+        {
+            lineno = 0;
+        }
 
         reportp = &report;
         PodZero(&report);
         report.filename = filename.ptr();
         report.lineno = (unsigned) lineno;
-        if (JSVAL_IS_STRING(roots[2])) {
-            JSFixedString *fixed = JSVAL_TO_STRING(roots[2])->ensureFixed(cx);
-            if (!fixed)
-                return false;
-            report.ucmessage = fixed->chars();
+        if (str) {
+            if (JSFixedString *fixed = str->ensureFixed(cx))
+                report.ucmessage = fixed->chars();
         }
     }
 
+    JSAutoByteString bytesStorage;
+    const char *bytes = NULL;
+    if (str)
+        bytes = bytesStorage.encode(cx, str);
+    if (!bytes)
+        bytes = "unknown (can't convert to string)";
+
     if (!reportp) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_UNCAUGHT_EXCEPTION, bytes);
     } else {
         /* Flag the error as an exception. */
         reportp->flags |= JSREPORT_EXCEPTION;
 
         /* Pass the exception object. */
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1362,17 +1362,17 @@ JSCompartment::setGCLastBytes(size_t las
     gcTriggerBytes = ComputeTriggerBytes(lastBytes, rt->gcMaxBytes, gckind);
     gcTriggerMallocAndFreeBytes = ComputeTriggerBytes(lastMallocBytes, SIZE_MAX, gckind);
 }
 
 void
 JSCompartment::reduceGCTriggerBytes(size_t amount)
 {
     JS_ASSERT(amount > 0);
-    JS_ASSERT(gcTriggerBytes - amount >= 0);
+    JS_ASSERT(gcTriggerBytes >= amount);
     if (gcTriggerBytes - amount < GC_ALLOCATION_THRESHOLD * GC_HEAP_GROWTH_FACTOR)
         return;
     gcTriggerBytes -= amount;
 }
 
 namespace js {
 namespace gc {
 
--- a/js/src/jsgcmark.cpp
+++ b/js/src/jsgcmark.cpp
@@ -769,29 +769,26 @@ ScanTypeObject(GCMarker *gcmarker, types
             if (prop && JSID_IS_STRING(prop->id))
                 PushMarkStack(gcmarker, JSID_TO_STRING(prop->id));
         }
     }
 
     if (type->proto)
         PushMarkStack(gcmarker, type->proto);
 
+    if (type->singleton && !type->lazy())
+        PushMarkStack(gcmarker, type->singleton);
+
     if (type->newScript) {
         PushMarkStack(gcmarker, type->newScript->fun);
         PushMarkStack(gcmarker, type->newScript->shape);
     }
 
     if (type->interpretedFunction)
         PushMarkStack(gcmarker, type->interpretedFunction);
-
-    if (type->singleton && !type->lazy())
-        PushMarkStack(gcmarker, type->singleton);
-
-    if (type->interpretedFunction)
-        PushMarkStack(gcmarker, type->interpretedFunction);
 }
 
 static void
 MarkChildren(JSTracer *trc, types::TypeObject *type)
 {
     if (!type->singleton) {
         unsigned count = type->getPropertyCount();
         for (unsigned i = 0; i < count; i++) {
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -1770,19 +1770,17 @@ class TypedArrayTemplate
 
     static void copyIndexToValue(JSContext *cx, JSObject *tarray, uint32_t index, Value *vp);
 
     static JSObject *
     createSubarray(JSContext *cx, JSObject *tarray, uint32_t begin, uint32_t end)
     {
         JS_ASSERT(tarray);
 
-        JS_ASSERT(0 <= begin);
         JS_ASSERT(begin <= getLength(tarray));
-        JS_ASSERT(0 <= end);
         JS_ASSERT(end <= getLength(tarray));
 
         JSObject *bufobj = getBuffer(tarray);
         JS_ASSERT(bufobj);
 
         JS_ASSERT(begin <= end);
         uint32_t length = end - begin;
 
--- a/layout/base/tests/font-inflation/consecutive-inline-ref.html
+++ b/layout/base/tests/font-inflation/consecutive-inline-ref.html
@@ -2,16 +2,17 @@
 <style>
   div {
     width: 450px;
   }
 
   a {
     font-weight: bold;
     line-height: 1.1em;
+    color: blue;
   }
 
   a#first {
     font-size: 34px;
     font-style: italic;
   }
 
   a#second {
--- a/layout/base/tests/font-inflation/consecutive-inline.html
+++ b/layout/base/tests/font-inflation/consecutive-inline.html
@@ -2,16 +2,17 @@
 <style>
   div {
     width: 450px;
   }
 
   a {
     font-weight: bold;
     line-height: 1.1em;
+    color: blue;
   }
 
   a#first {
     font-size: 12px;
     font-style: italic;
   }
 
   a#second {
@@ -21,9 +22,9 @@
 </style>
 <!--
 In a 450 px container, the minimum font size at 15em per line is 30px. This
 means we map 0px-45px into 30px-45px, so 12px gets mapped to 34px and 30px
 gets mapped to 40px.
 -->
 <div>
   <a id="first" href="">Hello</a><a id="second" href="">Worldz</a>
-</div>
\ No newline at end of file
+</div>
--- a/layout/generic/nsHTMLReflowMetrics.h
+++ b/layout/generic/nsHTMLReflowMetrics.h
@@ -66,21 +66,21 @@ enum nsOverflowType { eVisualOverflow, e
   for (nsOverflowType var_ = nsOverflowType(0); var_ < 2;                     \
        var_ = nsOverflowType(var_ + 1))
 
 struct nsOverflowAreas {
 private:
   nsRect mRects[2];
 public:
   nsRect& Overflow(size_t aIndex) {
-    NS_ASSERTION(0 <= aIndex && aIndex < 2, "index out of range");
+    NS_ASSERTION(aIndex < 2, "index out of range");
     return mRects[aIndex];
   }
   const nsRect& Overflow(size_t aIndex) const {
-    NS_ASSERTION(0 <= aIndex && aIndex < 2, "index out of range");
+    NS_ASSERTION(aIndex < 2, "index out of range");
     return mRects[aIndex];
   }
 
   nsRect& VisualOverflow() { return mRects[eVisualOverflow]; }
   const nsRect& VisualOverflow() const { return mRects[eVisualOverflow]; }
 
   nsRect& ScrollableOverflow() { return mRects[eScrollableOverflow]; }
   const nsRect& ScrollableOverflow() const { return mRects[eScrollableOverflow]; }
--- a/layout/reftests/mathml/semantics-1-ref.xhtml
+++ b/layout/reftests/mathml/semantics-1-ref.xhtml
@@ -18,17 +18,17 @@
       </munderover>
     </mstyle>
   </semantics>
 </math></p>
 
 <!-- embellished operator (bug 21479) -->
 <p><math xmlns="http://www.w3.org/1998/Math/MathML">
   <mover>
-    <mtext>■□■□■□■□■□■□</mtext>
+    <mspace width="300px" height="10px" mathbackground="black"></mspace>
     <mo>&#xaf;</mo>
   </mover>
 </math></p>
 
 <!-- unwanted whitespace (bug 512418) -->
 <p>■□■□■□<math xmlns="http://www.w3.org/1998/Math/MathML">
     <mrow>
       <mrow>
--- a/layout/reftests/mathml/semantics-1.xhtml
+++ b/layout/reftests/mathml/semantics-1.xhtml
@@ -16,17 +16,17 @@
         <mtext>■□■□■□</mtext>
       </munderover>
     </semantics>
 </math></p>
 
 <!-- embellished operator (bug 21479) -->
 <p><math xmlns="http://www.w3.org/1998/Math/MathML">
   <mover>
-    <mtext>■□■□■□■□■□■□</mtext>
+    <mspace width="300px" height="10px" mathbackground="black"></mspace>
     <semantics><mo>&#xaf;</mo></semantics>
   </mover>
 </math></p>
 
 <!-- unwanted whitespace (bug 512418) -->
 <p>■□■□■□<math xmlns="http://www.w3.org/1998/Math/MathML">
   <semantics>
     <mrow>
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -44,16 +44,17 @@
     <uses-feature android:name="android.hardware.camera" android:required="false"/>
     <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
 
     <!-- App requires OpenGL ES 2.0 -->
     <uses-feature android:glEsVersion="0x00020000" android:required="true" />
  
     <application android:label="@MOZ_APP_DISPLAYNAME@"
 		 android:icon="@drawable/icon"
+                 android:name="org.mozilla.gecko.GeckoApplication"
 #if MOZILLA_OFFICIAL
 		 android:debuggable="false">
 #else
 		 android:debuggable="true">
 #endif
 
         <activity android:name="App"
                   android:label="@MOZ_APP_DISPLAYNAME@"
--- a/mobile/android/base/AwesomeBar.java
+++ b/mobile/android/base/AwesomeBar.java
@@ -81,17 +81,17 @@ import java.net.URLEncoder;
 import java.util.Map;
 
 import org.mozilla.gecko.db.BrowserContract.Bookmarks;
 import org.mozilla.gecko.db.BrowserDB.URLColumns;
 import org.mozilla.gecko.db.BrowserDB;
 
 import org.json.JSONObject;
 
-public class AwesomeBar extends Activity implements GeckoEventListener {
+public class AwesomeBar extends GeckoActivity implements GeckoEventListener {
     private static final String LOGTAG = "GeckoAwesomeBar";
 
     static final String URL_KEY = "url";
     static final String CURRENT_URL_KEY = "currenturl";
     static final String TYPE_KEY = "type";
     static final String SEARCH_KEY = "search";
     static final String USER_ENTERED_KEY = "user_entered";
     static enum Type { ADD, EDIT };
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/GeckoActivity.java.in
@@ -0,0 +1,69 @@
+/* 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/. */
+
+#filter substitution
+package org.mozilla.gecko;
+
+import android.app.Activity;
+import android.app.Application;
+import android.os.Bundle;
+import android.content.Intent;
+import android.content.ComponentName;
+
+public class GeckoActivity extends Activity {
+    private boolean hasStarted = false;
+    private boolean isGeckoActivityOpened = false;
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        // Avoid pause notifications in destroy path.
+        if (!isFinishing() && (getApplication() instanceof GeckoApplication))
+            ((GeckoApplication) getApplication()).onActivityPause(this);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        // Avoid resume notifications in startup path.
+        if (hasStarted && (getApplication() instanceof GeckoApplication)) {
+            ((GeckoApplication) getApplication()).onActivityResume(this);
+            isGeckoActivityOpened = false;
+        } else {
+            hasStarted = true;
+        }
+    }
+
+    @Override
+    public void startActivity(Intent intent) {
+        checkIfGeckoActivity(intent);
+        super.startActivity(intent);
+    }
+
+    @Override
+    public void startActivityForResult(Intent intent, int request) {
+        checkIfGeckoActivity(intent);
+        super.startActivityForResult(intent, request);
+    }
+
+    private void checkIfGeckoActivity(Intent intent) {
+        // Whenever we call our own activity, the component and it's package name is set.
+        // If we call an activity from another package, or an open intent (leaving android to resolve)
+        // component has a different package name or it is null.
+        ComponentName component = intent.getComponent();
+        if (component == null)
+            isGeckoActivityOpened = false;
+
+        if (component.getPackageName().equals("@ANDROID_PACKAGE_NAME@"))
+            isGeckoActivityOpened = true;
+        else
+            isGeckoActivityOpened = false;
+    }
+
+    public boolean isApplicationInBackground() {
+        return !isGeckoActivityOpened;
+    } 
+}
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -88,18 +88,19 @@ import android.net.*;
 import android.database.*;
 import android.database.sqlite.*;
 import android.provider.*;
 import android.content.pm.*;
 import android.content.pm.PackageManager.*;
 import dalvik.system.*;
 
 abstract public class GeckoApp
-    extends Activity implements GeckoEventListener, SensorEventListener, LocationListener
-{
+                extends GeckoActivity 
+                implements GeckoEventListener, SensorEventListener, LocationListener,
+                           GeckoApplication.ApplicationLifecycleCallbacks {
     private static final String LOGTAG = "GeckoApp";
 
     public static enum StartupMode {
         NORMAL,
         NEW_VERSION,
         NEW_PROFILE
     }
 
@@ -136,17 +137,16 @@ abstract public class GeckoApp
     public Favicons mFavicons;
 
     private static LayerController mLayerController;
     private static GeckoLayerClient mLayerClient;
     private AboutHomeContent mAboutHomeContent;
     private static AbsoluteLayout mPluginContainer;
 
     public String mLastTitle;
-    private int mOwnActivityDepth = 0;
     private boolean mRestoreSession = false;
     private boolean mInitialized = false;
 
     private static final String HANDLER_MSG_TYPE = "type";
     private static final int HANDLER_MSG_TYPE_INITIALIZE = 1;
 
     static class ExtraMenuItem implements MenuItem.OnMenuItemClickListener {
         String label;
@@ -525,18 +525,16 @@ abstract public class GeckoApp
                 return true;
             default:
                 return super.onOptionsItemSelected(item);
         }
     }
 
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        if (mOwnActivityDepth > 0)
-            return; // we're showing one of our own activities and likely won't get paged out
 
         if (outState == null)
             outState = new Bundle();
 
         outState.putString(SAVED_STATE_TITLE, mLastTitle);
         outState.putBoolean(SAVED_STATE_SESSION, true);
     }
 
@@ -1193,16 +1191,21 @@ abstract public class GeckoApp
 
         mMainHandler.post(new Runnable() {
             public void run() {
                 if (Tabs.getInstance().isSelectedTab(tab))
                     mBrowserToolbar.setProgressVisibility(false);
                 Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.STOP);
             }
         });
+        GeckoAppShell.getHandler().postDelayed(new Runnable() {
+            public void run() {
+                getAndProcessThumbnailForTab(tab);
+            }
+        }, 500);
     }
 
     void handleShowToast(final String message, final String duration) {
         mMainHandler.post(new Runnable() {
             public void run() {
                 Toast toast;
                 if (duration.equals("long"))
                     toast = Toast.makeText(mAppContext, message, Toast.LENGTH_LONG);
@@ -1579,16 +1582,18 @@ abstract public class GeckoApp
         mBrowserToolbar = new BrowserToolbar(mAppContext);
         mBrowserToolbar.from(actionBar);
 
         // setup gecko layout
         mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout);
         mMainLayout = (LinearLayout) findViewById(R.id.main_layout);
 
         mConnectivityReceiver = new GeckoConnectivityReceiver();
+
+        ((GeckoApplication) getApplication()).addApplicationLifecycleCallbacks(this);
     }
 
     private void initialize() {
         mInitialized = true;
 
         Intent intent = getIntent();
         String action = intent.getAction();
         String args = intent.getStringExtra("args");
@@ -1966,17 +1971,16 @@ abstract public class GeckoApp
         return uri;
     }
 
     @Override
     public void onPause()
     {
         Log.i(LOGTAG, "pause");
 
-        GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(mOwnActivityDepth));
         // The user is navigating away from this activity, but nothing
         // has come to the foreground yet; for Gecko, we may want to
         // stop repainting, for example.
 
         // Whatever we do here should be fast, because we're blocking
         // the next activity from showing up until we finish.
 
         // onPause will be followed by either onResume or onStop.
@@ -1986,18 +1990,16 @@ abstract public class GeckoApp
         GeckoNetworkManager.getInstance().stop();
         GeckoScreenOrientationListener.getInstance().stop();
     }
 
     @Override
     public void onResume()
     {
         Log.i(LOGTAG, "resume");
-        if (checkLaunchState(LaunchState.GeckoRunning))
-            GeckoAppShell.sendEventToGecko(GeckoEvent.createResumeEvent(mOwnActivityDepth));
 
         // After an onPause, the activity is back in the foreground.
         // Undo whatever we did in onPause.
         super.onResume();
 
         /* We load the initial UI and wait until it is shown to the user
            to continue other initializations and loading about:home (if needed) */
         if (!mInitialized) {
@@ -2018,19 +2020,16 @@ abstract public class GeckoApp
 
         mMainHandler.post(new Runnable() {
             public void run() {
                 mConnectivityReceiver.registerFor(mAppContext);
                 GeckoNetworkManager.getInstance().start();
                 GeckoScreenOrientationListener.getInstance().start();
             }
         });
-
-        if (mOwnActivityDepth > 0)
-            mOwnActivityDepth--;
     }
 
     @Override
     public void onStop()
     {
         Log.i(LOGTAG, "stop");
         // We're about to be stopped, potentially in preparation for
         // being destroyed.  We're killable after this point -- as I
@@ -2038,34 +2037,34 @@ abstract public class GeckoApp
         // without going through onDestroy.
         //
         // We might also get an onRestart after this; not sure what
         // that would mean for Gecko if we were to kill it here.
         // Instead, what we should do here is save prefs, session,
         // etc., and generally mark the profile as 'clean', and then
         // dirty it again if we get an onResume.
 
-        GeckoAppShell.sendEventToGecko(GeckoEvent.createStoppingEvent(mOwnActivityDepth));
+        GeckoAppShell.sendEventToGecko(GeckoEvent.createStoppingEvent(isApplicationInBackground()));
         super.onStop();
     }
 
     @Override
     public void onRestart()
     {
         Log.i(LOGTAG, "restart");
         super.onRestart();
     }
 
     @Override
     public void onStart()
     {
         Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - onStart");
 
         Log.i(LOGTAG, "start");
-        GeckoAppShell.sendEventToGecko(GeckoEvent.createStartEvent(mOwnActivityDepth));
+        GeckoAppShell.sendEventToGecko(GeckoEvent.createStartEvent(isApplicationInBackground()));
         super.onStart();
     }
 
     @Override
     public void onDestroy()
     {
         Log.i(LOGTAG, "destroy");
 
@@ -2110,16 +2109,18 @@ abstract public class GeckoApp
 
         super.onDestroy();
 
         unregisterReceiver(mBatteryReceiver);
 
         if (mAboutHomeContent != null) {
             mAboutHomeContent.onDestroy();
         }
+
+        ((GeckoApplication) getApplication()).removeApplicationLifecycleCallbacks(this);
     }
 
     @Override
     public void onContentChanged() {
         super.onContentChanged();
         if (mAboutHomeContent != null)
             mAboutHomeContent.onActivityContentChanged(this);
     }
@@ -2143,16 +2144,29 @@ abstract public class GeckoApp
     public void onLowMemory()
     {
         Log.e(LOGTAG, "low memory");
         if (checkLaunchState(LaunchState.GeckoRunning))
             GeckoAppShell.onLowMemory();
         super.onLowMemory();
     }
 
+    @Override
+    public void onApplicationPause() {
+        Log.i(LOGTAG, "application paused");
+        GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true));
+    }
+
+    @Override
+    public void onApplicationResume() {
+        Log.i(LOGTAG, "application resumed");
+        if (checkLaunchState(LaunchState.GeckoRunning))
+            GeckoAppShell.sendEventToGecko(GeckoEvent.createResumeEvent(true));
+    }
+
     abstract public String getPackageName();
     abstract public String getContentProcessName();
 
     public void addEnvToIntent(Intent intent) {
         Map<String,String> envMap = System.getenv();
         Set<Map.Entry<String,String>> envSet = envMap.entrySet();
         Iterator<Map.Entry<String,String>> envIter = envSet.iterator();
         int c = 0;
@@ -2766,28 +2780,16 @@ abstract public class GeckoApp
             switch (type) {
                 case HANDLER_MSG_TYPE_INITIALIZE:
                     initialize();
                     break;
 
             }
         }
     } 
-
-    @Override
-    public void startActivity(Intent intent) {
-        mOwnActivityDepth++;
-        super.startActivity(intent);
-    }
-
-    @Override
-    public void startActivityForResult(Intent intent, int request) {
-        mOwnActivityDepth++;
-        super.startActivityForResult(intent, request);
-    }
 }
 
 class PluginLayoutParams extends AbsoluteLayout.LayoutParams
 {
     private static final int MAX_DIMENSION = 2048;
     private static final String LOGTAG = "GeckoApp.PluginLayoutParams";
 
     private int mOriginalX;
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/GeckoApplication.java
@@ -0,0 +1,57 @@
+/* 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/. */
+
+package org.mozilla.gecko;
+
+import java.util.ArrayList;
+
+import android.app.Activity;
+import android.app.Application;
+
+public class GeckoApplication extends Application {
+
+    private ArrayList<ApplicationLifecycleCallbacks> mListeners;
+
+    public interface ApplicationLifecycleCallbacks {
+        public void onApplicationPause();
+        public void onApplicationResume();
+    }
+
+    public void addApplicationLifecycleCallbacks(ApplicationLifecycleCallbacks callback) {
+        if (mListeners == null)
+            mListeners = new ArrayList<ApplicationLifecycleCallbacks>();
+
+        mListeners.add(callback);
+    }
+
+    public void removeApplicationLifecycleCallbacks(ApplicationLifecycleCallbacks callback) {
+        if (mListeners == null)
+            return;
+
+        mListeners.remove(callback);
+    }
+
+    public void onActivityPause(GeckoActivity activity) {
+        if (!activity.isApplicationInBackground())
+            return;
+
+        if (mListeners == null)
+            return;
+
+        for (ApplicationLifecycleCallbacks listener: mListeners)
+            listener.onApplicationPause();
+    }
+
+    public void onActivityResume(GeckoActivity activity) {
+        // This is a misnomer. Should have been "wasApplicationInBackground".
+        if (!activity.isApplicationInBackground())
+            return;
+
+        if (mListeners == null)
+            return;
+
+        for (ApplicationLifecycleCallbacks listener: mListeners)
+            listener.onApplicationResume();
+    }
+}
--- a/mobile/android/base/GeckoEvent.java
+++ b/mobile/android/base/GeckoEvent.java
@@ -145,37 +145,37 @@ public class GeckoEvent {
     public int mNativeWindow;
 
     public short mScreenOrientation;
 
     private GeckoEvent(int evType) {
         mType = evType;
     }
 
-    public static GeckoEvent createPauseEvent(int activityDepth) {
+    public static GeckoEvent createPauseEvent(boolean isApplicationInBackground) {
         GeckoEvent event = new GeckoEvent(ACTIVITY_PAUSING);
-        event.mFlags = activityDepth > 0 ? 1 : 0;
+        event.mFlags = isApplicationInBackground ? 0 : 1;
         return event;
     }
 
-    public static GeckoEvent createResumeEvent(int activityDepth) {
+    public static GeckoEvent createResumeEvent(boolean isApplicationInBackground) {
         GeckoEvent event = new GeckoEvent(ACTIVITY_RESUMING);
-        event.mFlags = activityDepth > 0 ? 1 : 0;
+        event.mFlags = isApplicationInBackground ? 0 : 1;
         return event;
     }
 
-    public static GeckoEvent createStoppingEvent(int activityDepth) {
+    public static GeckoEvent createStoppingEvent(boolean isApplicationInBackground) {
         GeckoEvent event = new GeckoEvent(ACTIVITY_STOPPING);
-        event.mFlags = activityDepth > 0 ? 1 : 0;
+        event.mFlags = isApplicationInBackground ? 0 : 1;
         return event;
     }
 
-    public static GeckoEvent createStartEvent(int activityDepth) {
+    public static GeckoEvent createStartEvent(boolean isApplicationInBackground) {
         GeckoEvent event = new GeckoEvent(ACTIVITY_START);
-        event.mFlags = activityDepth > 0 ? 1 : 0;
+        event.mFlags = isApplicationInBackground ? 0 : 1;
         return event;
     }
 
     public static GeckoEvent createShutdownEvent() {
         return new GeckoEvent(ACTIVITY_SHUTDOWN);
     }
 
     public static GeckoEvent createSyncEvent() {
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -74,16 +74,17 @@ FENNEC_JAVA_FILES = \
   db/LocalBrowserDB.java \
   db/DBUtils.java \
   DoorHanger.java \
   DoorHangerPopup.java \
   Favicons.java \
   FloatUtils.java \
   FormAssistPopup.java \
   GeckoActionBar.java \
+  GeckoApplication.java \
   GeckoApp.java \
   GeckoAppShell.java \
   GeckoAsyncTask.java \
   GeckoBatteryManager.java \
   GeckoBackgroundThread.java \
   GeckoConnectivityReceiver.java \
   GeckoEvent.java \
   GeckoEventListener.java \
@@ -156,16 +157,17 @@ FENNEC_JAVA_FILES = \
   $(NULL)
 
 ifdef MOZ_WEBSMS_BACKEND
 FENNEC_JAVA_FILES += GeckoSmsManager.java
 endif
 
 FENNEC_PP_JAVA_FILES = \
   App.java \
+  GeckoActivity.java \
   LauncherShortcuts.java \
   NotificationHandler.java \
   Restarter.java \
   db/BrowserContract.java \
   db/BrowserProvider.java \
   db/PasswordsProvider.java \
   db/FormHistoryProvider.java \
   db/TabsProvider.java \
--- a/mobile/android/base/RemoteTabs.java
+++ b/mobile/android/base/RemoteTabs.java
@@ -22,17 +22,17 @@ import android.util.DisplayMetrics;
 import android.view.View;
 import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.ExpandableListView;
 import android.widget.SimpleExpandableListAdapter;
 import android.text.TextUtils;
 import android.util.Log;
 
-public class RemoteTabs extends Activity
+public class RemoteTabs extends GeckoActivity
        implements ExpandableListView.OnGroupClickListener, ExpandableListView.OnChildClickListener, 
                   TabsAccessor.OnQueryTabsCompleteListener {
     private static final String LOGTAG = "GeckoRemoteTabs";
 
     private static int sPreferredHeight;
     private static int sChildItemHeight;
     private static int sGroupItemHeight;
     private static ExpandableListView mList;
--- a/mobile/android/base/TabsTray.java
+++ b/mobile/android/base/TabsTray.java
@@ -26,17 +26,17 @@ import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import org.mozilla.gecko.sync.setup.SyncAccounts;
 
-public class TabsTray extends Activity implements Tabs.OnTabsChangedListener {
+public class TabsTray extends GeckoActivity implements Tabs.OnTabsChangedListener {
 
     private static int sPreferredHeight;
     private static int sMaxHeight;
     private static int sListItemHeight;
     private static int sAddTabHeight;
     private static ListView mList;
     private static TabsListContainer mListContainer;
     private static LinkTextView mRemoteTabs;
--- a/mobile/android/base/sync/CryptoRecord.java
+++ b/mobile/android/base/sync/CryptoRecord.java
@@ -39,16 +39,17 @@ import org.mozilla.gecko.sync.repositori
 public class CryptoRecord extends Record {
 
   // JSON related constants.
   private static final String KEY_ID         = "id";
   private static final String KEY_COLLECTION = "collection";
   private static final String KEY_PAYLOAD    = "payload";
   private static final String KEY_MODIFIED   = "modified";
   private static final String KEY_SORTINDEX  = "sortindex";
+  private static final String KEY_TTL        = "ttl";
   private static final String KEY_CIPHERTEXT = "ciphertext";
   private static final String KEY_HMAC       = "hmac";
   private static final String KEY_IV         = "IV";
 
   /**
    * Helper method for doing actual decryption.
    *
    * Input: JSONObject containing a valid payload (cipherText, IV, HMAC),
@@ -92,24 +93,26 @@ public class CryptoRecord extends Record
 
   /**
    * Create a new CryptoRecord with the same metadata as an existing record.
    *
    * @param source
    */
   public CryptoRecord(Record source) {
     super(source.guid, source.collection, source.lastModified, source.deleted);
+    this.ttl = source.ttl;
   }
 
   @Override
   public Record copyWithIDs(String guid, long androidID) {
     CryptoRecord out = new CryptoRecord(this);
     out.guid         = guid;
     out.androidID    = androidID;
     out.sortIndex    = this.sortIndex;
+    out.ttl          = this.ttl;
     out.payload      = (this.payload == null) ? null : new ExtendedJSONObject(this.payload.object);
     out.keyBundle    = this.keyBundle;    // TODO: copy me?
     return out;
   }
 
   /**
    * Take a whole record as JSON -- i.e., something like
    *
@@ -143,16 +146,21 @@ public class CryptoRecord extends Record
     record.guid         = id;
     record.collection   = collection;
     if (jsonRecord.containsKey(KEY_MODIFIED)) {
       record.lastModified = jsonRecord.getTimestamp(KEY_MODIFIED);
     }
     if (jsonRecord.containsKey(KEY_SORTINDEX)) {
       record.sortIndex = jsonRecord.getLong(KEY_SORTINDEX);
     }
+    if (jsonRecord.containsKey(KEY_TTL)) {
+      // TTLs are never returned by the sync server, so should never be true if
+      // the record was fetched.
+      record.ttl = jsonRecord.getLong(KEY_TTL);
+    }
     // TODO: deleted?
     return record;
   }
 
   public void setKeyBundle(KeyBundle bundle) {
     this.keyBundle = bundle;
   }
 
@@ -224,16 +232,19 @@ public class CryptoRecord extends Record
     throw new IllegalStateException("Can't do this with a CryptoRecord.");
   }
 
   // TODO: this only works with encrypted object, and has other limitations.
   public JSONObject toJSONObject() {
     ExtendedJSONObject o = new ExtendedJSONObject();
     o.put(KEY_PAYLOAD, payload.toJSONString());
     o.put(KEY_ID,      this.guid);
+    if (this.ttl > 0) {
+      o.put(KEY_TTL, this.ttl);
+    }
     return o.object;
   }
 
   @Override
   public String toJSONString() {
     return toJSONObject().toJSONString();
   }
 }
--- a/mobile/android/base/sync/GlobalSession.java
+++ b/mobile/android/base/sync/GlobalSession.java
@@ -26,16 +26,17 @@ import org.mozilla.gecko.sync.delegates.
 import org.mozilla.gecko.sync.net.BaseResource;
 import org.mozilla.gecko.sync.net.HttpResponseObserver;
 import org.mozilla.gecko.sync.net.SyncResponse;
 import org.mozilla.gecko.sync.net.SyncStorageRecordRequest;
 import org.mozilla.gecko.sync.net.SyncStorageRequest;
 import org.mozilla.gecko.sync.net.SyncStorageRequestDelegate;
 import org.mozilla.gecko.sync.net.SyncStorageResponse;
 import org.mozilla.gecko.sync.stage.AndroidBrowserBookmarksServerSyncStage;
+import org.mozilla.gecko.sync.stage.FormHistoryServerSyncStage;
 import org.mozilla.gecko.sync.stage.AndroidBrowserHistoryServerSyncStage;
 import org.mozilla.gecko.sync.stage.CheckPreconditionsStage;
 import org.mozilla.gecko.sync.stage.CompletedStage;
 import org.mozilla.gecko.sync.stage.EnsureClusterURLStage;
 import org.mozilla.gecko.sync.stage.EnsureKeysStage;
 import org.mozilla.gecko.sync.stage.FennecTabsServerSyncStage;
 import org.mozilla.gecko.sync.stage.FetchInfoCollectionsStage;
 import org.mozilla.gecko.sync.stage.FetchMetaGlobalStage;
@@ -193,16 +194,17 @@ public class GlobalSession implements Cr
     stages.put(Stage.fetchMetaGlobal,         new FetchMetaGlobalStage());
     stages.put(Stage.ensureKeysStage,         new EnsureKeysStage());
     stages.put(Stage.syncClientsEngine,       new SyncClientsEngineStage());
 
     // TODO: more stages.
     stages.put(Stage.syncTabs,                new FennecTabsServerSyncStage());
     stages.put(Stage.syncBookmarks,           new AndroidBrowserBookmarksServerSyncStage());
     stages.put(Stage.syncHistory,             new AndroidBrowserHistoryServerSyncStage());
+    stages.put(Stage.syncFormHistory,         new FormHistoryServerSyncStage());
     stages.put(Stage.completed,               new CompletedStage());
   }
 
   protected GlobalSyncStage getStageByName(Stage next) throws NoSuchStageException {
     GlobalSyncStage stage = stages.get(next);
     if (stage == null) {
       throw new NoSuchStageException(next);
     }
--- a/mobile/android/base/sync/jpake/JPakeClient.java
+++ b/mobile/android/base/sync/jpake/JPakeClient.java
@@ -20,16 +20,17 @@ import org.mozilla.gecko.sync.crypto.Cry
 import org.mozilla.gecko.sync.crypto.KeyBundle;
 import org.mozilla.gecko.sync.crypto.NoKeyBundleException;
 import org.mozilla.gecko.sync.jpake.stage.CompleteStage;
 import org.mozilla.gecko.sync.jpake.stage.ComputeFinalStage;
 import org.mozilla.gecko.sync.jpake.stage.ComputeKeyVerificationStage;
 import org.mozilla.gecko.sync.jpake.stage.ComputeStepOneStage;
 import org.mozilla.gecko.sync.jpake.stage.ComputeStepTwoStage;
 import org.mozilla.gecko.sync.jpake.stage.DecryptDataStage;
+import org.mozilla.gecko.sync.jpake.stage.DeleteChannel;
 import org.mozilla.gecko.sync.jpake.stage.GetChannelStage;
 import org.mozilla.gecko.sync.jpake.stage.GetRequestStage;
 import org.mozilla.gecko.sync.jpake.stage.JPakeStage;
 import org.mozilla.gecko.sync.jpake.stage.PutRequestStage;
 import org.mozilla.gecko.sync.jpake.stage.VerifyPairingStage;
 import org.mozilla.gecko.sync.setup.Constants;
 import org.mozilla.gecko.sync.setup.activities.SetupSyncActivity;
 
@@ -232,16 +233,27 @@ public class JPakeClient {
   /**
    * Abort J-PAKE.
    *
    * @param reason
    *          Reason for abort.
    */
   public void abort(String reason) {
     finished = true;
+    if (Constants.JPAKE_ERROR_CHANNEL.equals(reason) ||
+        Constants.JPAKE_ERROR_NETWORK.equals(reason) ||
+        Constants.JPAKE_ERROR_NODATA.equals(reason)) {
+      displayAbort(reason);
+    } else {
+      // Delete channel, then call controller's displayAbort in callback.
+      new DeleteChannel().execute(this, reason);
+    }
+  }
+
+  public void displayAbort(String reason) {
     controllerActivity.displayAbort(reason);
   }
 
   /* Static helper methods used by stages. */
 
   /**
    * Run on a different thread from the thread pool.
    *
--- a/mobile/android/base/sync/jpake/stage/DecryptDataStage.java
+++ b/mobile/android/base/sync/jpake/stage/DecryptDataStage.java
@@ -64,16 +64,23 @@ public class DecryptDataStage extends JP
       jClient.abort(Constants.JPAKE_ERROR_INVALID);
       return;
     } catch (ParseException e) {
       Logger.error(LOG_TAG, "JSON parse error.", e);
       jClient.abort(Constants.JPAKE_ERROR_INVALID);
       return;
     }
 
+    // Check that credentials were actually sent over.
+    if (!checkCredentials(jClient.jCreds)) {
+      Logger.error(LOG_TAG, "Credentials contain nulls, setup cannot be completed.");
+      jClient.abort(Constants.JPAKE_ERROR_INTERNAL);
+      return;
+    }
+
     jClient.runNextStage();
   }
 
   /**
    * Helper method for doing actual decryption.
    *
    * Input: JSONObject containing a valid payload (cipherText, IV, HMAC),
    * KeyBundle with keys for decryption. Output: byte[] clearText
@@ -101,12 +108,27 @@ public class DecryptDataStage extends JP
    * @param jsonString
    *          String to be packaged as JSON object.
    * @return JSONObject
    * @throws ParseException
    * @throws IOException
    * @throws Exception
    */
   private JSONObject getJSONObject(String jsonString) throws IOException, ParseException{
-    Reader in = new StringReader(jsonString);
+    final Reader in = new StringReader(jsonString);
     return (JSONObject) new JSONParser().parse(in);
   }
+
+  private boolean checkCredentials(JSONObject creds) {
+    final String accountName = (String) creds.get(Constants.JSON_KEY_ACCOUNT);
+    final String password    = (String) creds.get(Constants.JSON_KEY_PASSWORD);
+    final String syncKey     = (String) creds.get(Constants.JSON_KEY_SYNCKEY);
+    final String serverUrl   = (String) creds.get(Constants.JSON_KEY_SERVER);
+
+    if (accountName == null || accountName.equals("") ||
+        password    == null || password.equals("")    ||
+        syncKey     == null || syncKey.equals("")     ||
+        serverUrl   == null || serverUrl.equals("")) {
+      return false;
+    }
+    return true;
+  }
 }
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/sync/jpake/stage/DeleteChannel.java
@@ -0,0 +1,90 @@
+/* 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/. */
+
+package org.mozilla.gecko.sync.jpake.stage;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.security.GeneralSecurityException;
+
+import org.mozilla.gecko.sync.Logger;
+import org.mozilla.gecko.sync.jpake.JPakeClient;
+import org.mozilla.gecko.sync.net.BaseResource;
+import org.mozilla.gecko.sync.net.SyncResourceDelegate;
+
+import ch.boye.httpclientandroidlib.HttpResponse;
+import ch.boye.httpclientandroidlib.client.ClientProtocolException;
+import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase;
+import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient;
+import ch.boye.httpclientandroidlib.message.BasicHeader;
+
+public class DeleteChannel {
+  private static final String LOG_TAG = "DeleteChannel";
+
+  public static final String KEYEXCHANGE_ID_HEADER  = "X-KeyExchange-Id";
+  public static final String KEYEXCHANGE_CID_HEADER = "X-KeyExchange-Cid";
+
+  public void execute(final JPakeClient jClient, final String reason) {
+    final BaseResource httpResource;
+    try {
+      httpResource = new BaseResource(jClient.channelUrl);
+    } catch (URISyntaxException e) {
+      Logger.debug(LOG_TAG, "Encountered URISyntax exception, displaying abort anyway.");
+      jClient.displayAbort(reason);
+      return;
+    }
+    httpResource.delegate = new SyncResourceDelegate(httpResource) {
+
+      @Override
+      public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
+        request.setHeader(new BasicHeader(KEYEXCHANGE_ID_HEADER,  jClient.clientId));
+        request.setHeader(new BasicHeader(KEYEXCHANGE_CID_HEADER, jClient.channel));
+      }
+
+      @Override
+      public void handleHttpResponse(HttpResponse response) {
+        try {
+          int statusCode = response.getStatusLine().getStatusCode();
+          switch (statusCode) {
+            case 200:
+              Logger.info(LOG_TAG, "Successfully reported error to server.");
+              break;
+            case 403:
+              Logger.info(LOG_TAG, "IP is blacklisted.");
+              break;
+            case 400:
+              Logger.info(LOG_TAG, "Bad request (missing logs, or bad ids");
+              break;
+            default:
+              Logger.info(LOG_TAG, "Server returned " + statusCode);
+          }
+        } finally {
+          BaseResource.consumeEntity(response);
+          // Always call displayAbort, even if abort fails. We can't do anything about it.
+          jClient.displayAbort(reason);
+        }
+      }
+
+      @Override
+      public void handleHttpProtocolException(ClientProtocolException e) {
+        Logger.debug(LOG_TAG, "Encountered HttpProtocolException, displaying abort anyway.");
+        jClient.displayAbort(reason);
+      }
+
+      @Override
+      public void handleHttpIOException(IOException e) {
+        Logger.debug(LOG_TAG, "Encountered IOException, displaying abort anyway.");
+        jClient.displayAbort(reason);
+      }
+
+      @Override
+      public void handleTransportException(GeneralSecurityException e) {
+        Logger.debug(LOG_TAG, "Encountered GeneralSecurityException, displaying abort anyway.");
+        jClient.displayAbort(reason);
+      }
+    };
+
+    httpResource.delete();
+  }
+}
--- a/mobile/android/base/sync/jpake/stage/GetChannelStage.java
+++ b/mobile/android/base/sync/jpake/stage/GetChannelStage.java
@@ -62,21 +62,21 @@ public class GetChannelStage extends JPa
         jClient.abort(Constants.JPAKE_ERROR_CHANNEL);
       }
     };
 
     try {
       makeChannelRequest(callbackDelegate, jClient.jpakeServer + "new_channel", jClient.clientId);
     } catch (URISyntaxException e) {
       Logger.error(LOG_TAG, "Incorrect URI syntax.", e);
-      jClient.abort(Constants.JPAKE_ERROR_INVALID);
+      jClient.abort(Constants.JPAKE_ERROR_CHANNEL);
       return;
     } catch (Exception e) {
       Logger.error(LOG_TAG, "Unexpected exception.", e);
-      jClient.abort(Constants.JPAKE_ERROR_INTERNAL);
+      jClient.abort(Constants.JPAKE_ERROR_CHANNEL);
       return;
     }
   }
 
   private void makeChannelRequest(final GetChannelStageDelegate callbackDelegate, String getChannelUrl, final String clientId) throws URISyntaxException {
     final BaseResource httpResource = new BaseResource(getChannelUrl);
     httpResource.delegate = new SyncResourceDelegate(httpResource) {
 
--- a/mobile/android/base/sync/net/SyncResponse.java
+++ b/mobile/android/base/sync/net/SyncResponse.java
@@ -66,24 +66,29 @@ public class SyncResponse {
    * @throws IllegalStateException
    * @throws IOException
    * @throws ParseException
    */
   public Object jsonBody() throws IllegalStateException, IOException,
                           ParseException {
     if (body != null) {
       // Do it from the cached String.
-      ExtendedJSONObject.parse(body);
+      return ExtendedJSONObject.parse(body);
     }
+
     HttpEntity entity = this.response.getEntity();
     if (entity == null) {
       return null;
     }
     InputStream content = entity.getContent();
-    return ExtendedJSONObject.parse(content);
+    try {
+      return ExtendedJSONObject.parse(content);
+    } finally {
+      content.close();
+    }
   }
 
   /**
    * Return the body as a <b>non-null</b> <code>ExtendedJSONObject</code>.
    *
    * @return A non-null <code>ExtendedJSONObject</code>.
    *
    * @throws IllegalStateException
--- a/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java
+++ b/mobile/android/base/sync/repositories/android/AndroidBrowserRepositoryDataAccessor.java
@@ -1,45 +1,11 @@
-/* ***** 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 Android Sync Client.
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Jason Voll <jvoll@mozilla.com>
- *   Richard Newman <rnewman@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 ***** */
+/* 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/. */
 
 package org.mozilla.gecko.sync.repositories.android;
 
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.repositories.NullCursorException;
 import org.mozilla.gecko.sync.repositories.domain.Record;
 
@@ -192,34 +158,20 @@ public abstract class AndroidBrowserRepo
    * <p>
    * The caller is responsible for closing the cursor.
    *
    * @param guids The GUIDs of the records to fetch.
    * @return A cursor. You <b>must</b> close this when you're done with it.
    * @throws NullCursorException
    */
   public Cursor fetch(String guids[]) throws NullCursorException {
-    String where = computeSQLInClause(guids.length, "guid");
+    String where = RepoUtils.computeSQLInClause(guids.length, "guid");
     return queryHelper.safeQuery(".fetch", getAllColumns(), where, guids, null);
   }
 
-  protected String computeSQLInClause(int items, String field) {
-    StringBuilder builder = new StringBuilder(field);
-    builder.append(" IN (");
-    int i = 0;
-    for (; i < items - 1; ++i) {
-      builder.append("?, ");
-    }
-    if (i < items) {
-      builder.append("?");
-    }
-    builder.append(")");
-    return builder.toString();
-  }
-
   public void updateByGuid(String guid, ContentValues cv) {
     String where  = BrowserContract.SyncColumns.GUID + " = ?";
     String[] args = new String[] { guid };
 
     int updated = context.getContentResolver().update(getUri(), cv, where, args);
     if (updated == 1) {
       return;
     }
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/sync/repositories/android/FormHistoryRepositorySession.java
@@ -0,0 +1,729 @@
+/* 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/. */
+
+package org.mozilla.gecko.sync.repositories.android;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.mozilla.gecko.db.BrowserContract.DeletedFormHistory;
+import org.mozilla.gecko.db.BrowserContract.FormHistory;
+import org.mozilla.gecko.sync.Logger;
+import org.mozilla.gecko.sync.repositories.InactiveSessionException;
+import org.mozilla.gecko.sync.repositories.NoContentProviderException;
+import org.mozilla.gecko.sync.repositories.NoStoreDelegateException;
+import org.mozilla.gecko.sync.repositories.NullCursorException;
+import org.mozilla.gecko.sync.repositories.RecordFilter;
+import org.mozilla.gecko.sync.repositories.Repository;
+import org.mozilla.gecko.sync.repositories.StoreTrackingRepositorySession;
+import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionCreationDelegate;
+import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFetchRecordsDelegate;
+import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionFinishDelegate;
+import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionGuidsSinceDelegate;
+import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionWipeDelegate;
+import org.mozilla.gecko.sync.repositories.domain.FormHistoryRecord;
+import org.mozilla.gecko.sync.repositories.domain.Record;
+
+import android.content.ContentProviderClient;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.RemoteException;
+
+public class FormHistoryRepositorySession extends
+    StoreTrackingRepositorySession {
+  public static String LOG_TAG = "FormHistoryRepoSess";
+
+  protected static Uri FORM_HISTORY_CONTENT_URI = BrowserContractHelpers.FORM_HISTORY_CONTENT_URI;
+  protected static Uri DELETED_FORM_HISTORY_CONTENT_URI = BrowserContractHelpers.DELETED_FORM_HISTORY_CONTENT_URI;
+
+  public static class FormHistoryRepository extends Repository {
+
+    @Override
+    public void createSession(RepositorySessionCreationDelegate delegate,
+                              Context context) {
+      try {
+        final FormHistoryRepositorySession session = new FormHistoryRepositorySession(this, context);
+        delegate.onSessionCreated(session);
+      } catch (Exception e) {
+        delegate.onSessionCreateFailed(e);
+      }
+    }
+  }
+
+  protected final ContentProviderClient formsProvider;
+  protected final RepoUtils.QueryHelper regularHelper;
+  protected final RepoUtils.QueryHelper deletedHelper;
+
+  /**
+   * Acquire the content provider client.
+   * <p>
+   * The caller is responsible for releasing the client.
+   *
+   * @param context The application context.
+   * @return The <code>ContentProviderClient</code>.
+   * @throws NoContentProviderException
+   */
+  public static ContentProviderClient acquireContentProvider(final Context context)
+      throws NoContentProviderException {
+    Uri uri = FormHistory.CONTENT_URI;
+    ContentProviderClient client = context.getContentResolver().acquireContentProviderClient(uri);
+    if (client == null) {
+      throw new NoContentProviderException(uri);
+    }
+    return client;
+  }
+
+  protected void releaseProviders() {
+    try {
+      formsProvider.release();
+    } catch (Exception e) {
+    }
+  }
+
+  // Only used for testing.
+  public ContentProviderClient getFormsProvider() {
+    return formsProvider;
+  }
+
+  public FormHistoryRepositorySession(Repository repository, Context context)
+      throws NoContentProviderException {
+    super(repository);
+    formsProvider = acquireContentProvider(context);
+    regularHelper = new RepoUtils.QueryHelper(context, BrowserContractHelpers.FORM_HISTORY_CONTENT_URI, LOG_TAG);
+    deletedHelper = new RepoUtils.QueryHelper(context, BrowserContractHelpers.DELETED_FORM_HISTORY_CONTENT_URI, LOG_TAG);
+  }
+
+  @Override
+  public void abort() {
+    releaseProviders();
+    super.abort();
+  }
+
+  @Override
+  public void finish(final RepositorySessionFinishDelegate delegate)
+      throws InactiveSessionException {
+    releaseProviders();
+    super.finish(delegate);
+  }
+
+  protected static String[] GUID_COLUMNS = new String[] { FormHistory.GUID };
+
+  @Override
+  public void guidsSince(final long timestamp, final RepositorySessionGuidsSinceDelegate delegate) {
+    Runnable command = new Runnable() {
+      public void run() {
+        if (!isActive()) {
+          delegate.onGuidsSinceFailed(new InactiveSessionException(null));
+          return;
+        }
+
+        ArrayList<String> guids = new ArrayList<String>();
+
+        final long sharedEnd = now();
+        Cursor cur = null;
+        try {
+          cur = regularHelper.safeQuery(formsProvider, "", GUID_COLUMNS, regularBetween(timestamp, sharedEnd), null, null);
+          cur.moveToFirst();
+          while (!cur.isAfterLast()) {
+            guids.add(cur.getString(0));
+            cur.moveToNext();
+          }
+        } catch (RemoteException e) {
+          delegate.onGuidsSinceFailed(e);
+          return;
+        } catch (NullCursorException e) {
+          delegate.onGuidsSinceFailed(e);
+          return;
+        } finally {
+          if (cur != null) {
+            cur.close();
+          }
+        }
+
+        try {
+          cur = deletedHelper.safeQuery(formsProvider, "", GUID_COLUMNS, deletedBetween(timestamp, sharedEnd), null, null);
+          cur.moveToFirst();
+          while (!cur.isAfterLast()) {
+            guids.add(cur.getString(0));
+            cur.moveToNext();
+          }
+        } catch (RemoteException e) {
+          delegate.onGuidsSinceFailed(e);
+          return;
+        } catch (NullCursorException e) {
+          delegate.onGuidsSinceFailed(e);
+          return;
+        } finally {
+          if (cur != null) {
+            cur.close();
+          }
+        }
+
+        String guidsArray[] = guids.toArray(new String[0]);
+        delegate.onGuidsSinceSucceeded(guidsArray);
+      }
+    };
+    delegateQueue.execute(command);
+  }
+
+  protected FormHistoryRecord retrieveDuringFetch(Cursor cursor) {
+    // A simple and efficient way to distinguish two tables.
+    if (cursor.getColumnCount() == BrowserContractHelpers.FormHistoryColumns.length) {
+      return formHistoryRecordFromCursor(cursor);
+    } else {
+      return deletedFormHistoryRecordFromCursor(cursor);
+    }
+  }
+
+  protected FormHistoryRecord formHistoryRecordFromCursor(Cursor cursor) {
+    String guid = RepoUtils.getStringFromCursor(cursor, FormHistory.GUID);
+    String collection = "forms";
+    FormHistoryRecord record = new FormHistoryRecord(guid, collection, 0, false);
+
+    record.fieldName = RepoUtils.getStringFromCursor(cursor, FormHistory.FIELD_NAME);
+    record.fieldValue = RepoUtils.getStringFromCursor(cursor, FormHistory.VALUE);
+    record.androidID = RepoUtils.getLongFromCursor(cursor, FormHistory.ID);
+    record.lastModified = RepoUtils.getLongFromCursor(cursor, FormHistory.FIRST_USED) / 1000; // Convert microseconds to milliseconds.
+    record.deleted = false;
+
+    record.log(LOG_TAG);
+    return record;
+  }
+
+  protected FormHistoryRecord deletedFormHistoryRecordFromCursor(Cursor cursor) {
+    String guid = RepoUtils.getStringFromCursor(cursor, DeletedFormHistory.GUID);
+    String collection = "forms";
+    FormHistoryRecord record = new FormHistoryRecord(guid, collection, 0, false);
+
+    record.guid = RepoUtils.getStringFromCursor(cursor, DeletedFormHistory.GUID);
+    record.androidID = RepoUtils.getLongFromCursor(cursor, DeletedFormHistory.ID);
+    record.lastModified = RepoUtils.getLongFromCursor(cursor, DeletedFormHistory.TIME_DELETED);
+    record.deleted = true;
+
+    record.log(LOG_TAG);
+    return record;
+  }
+
+  protected void fetchFromCursor(Cursor cursor, RecordFilter filter, final RepositorySessionFetchRecordsDelegate delegate)
+      throws NullCursorException {
+    Logger.debug(LOG_TAG, "Fetch from cursor");
+    if (cursor == null) {
+      throw new NullCursorException(null);
+    }
+    try {
+      if (!cursor.moveToFirst()) {
+        return;
+      }
+      while (!cursor.isAfterLast()) {
+        Record r = retrieveDuringFetch(cursor);
+        if (r != null) {
+          if (filter == null || !filter.excludeRecord(r)) {
+            Logger.trace(LOG_TAG, "Processing record " + r.guid);
+            delegate.onFetchedRecord(r);
+          } else {
+            Logger.debug(LOG_TAG, "Skipping filtered record " + r.guid);
+          }
+        }
+        cursor.moveToNext();
+      }
+    } finally {
+      Logger.trace(LOG_TAG, "Closing cursor after fetch.");
+      cursor.close();
+    }
+  }
+
+  protected void fetchHelper(final RepositorySessionFetchRecordsDelegate delegate, final long end, final List<Callable<Cursor>> cursorCallables) {
+    if (this.storeTracker == null) {
+      throw new IllegalStateException("Store tracker not yet initialized!");
+    }
+
+    final RecordFilter filter = this.storeTracker.getFilter();
+
+    Runnable command = new Runnable() {
+      @Override
+      public void run() {
+        if (!isActive()) {
+          delegate.onFetchFailed(new InactiveSessionException(null), null);
+          return;
+        }
+
+        for (Callable<Cursor> cursorCallable : cursorCallables) {
+          Cursor cursor = null;
+          try {
+            cursor = cursorCallable.call();
+            fetchFromCursor(cursor, filter, delegate); // Closes cursor.
+          } catch (Exception e) {
+            Logger.warn(LOG_TAG, "Exception during fetchHelper", e);
+            delegate.onFetchFailed(e, null);
+            return;
+          }
+        }
+
+        delegate.onFetchCompleted(end);
+      }
+    };
+
+    delegateQueue.execute(command);
+  }
+
+  protected String regularBetween(long start, long end) {
+    return FormHistory.FIRST_USED + " >= " + Long.toString(1000 * start) + " AND " +
+           FormHistory.FIRST_USED + " <= " + Long.toString(1000 * end); // Microseconds.
+  }
+
+  protected String deletedBetween(long start, long end) {
+    return DeletedFormHistory.TIME_DELETED + " >= " + Long.toString(start) + " AND " +
+           DeletedFormHistory.TIME_DELETED + " <= " + Long.toString(end); // Milliseconds.
+  }
+
+  @Override
+  public void fetchSince(final long timestamp, final RepositorySessionFetchRecordsDelegate delegate) {
+    Logger.info(LOG_TAG, "Running fetchSince(" + timestamp + ").");
+
+    /*
+     * We need to be careful about the timestamp we complete the fetch with. If
+     * the first cursor Callable takes a year, then the second could return
+     * records long after the first was kicked off. To protect against this, we
+     * set an end point and bound our search.
+     */
+    final long sharedEnd = now();
+
+    Callable<Cursor> regularCallable = new Callable<Cursor>() {
+      @Override
+      public Cursor call() throws Exception {
+        return regularHelper.safeQuery(formsProvider, ".fetchSince(regular)", null, regularBetween(timestamp, sharedEnd), null, null);
+      }
+    };
+
+    Callable<Cursor> deletedCallable = new Callable<Cursor>() {
+      @Override
+      public Cursor call() throws Exception {
+        return deletedHelper.safeQuery(formsProvider, ".fetchSince(deleted)", null, deletedBetween(timestamp, sharedEnd), null, null);
+      }
+    };
+
+    ArrayList<Callable<Cursor>> callableCursors = new ArrayList<Callable<Cursor>>();
+    callableCursors.add(regularCallable);
+    callableCursors.add(deletedCallable);
+    fetchHelper(delegate, sharedEnd, callableCursors);
+  }
+
+  @Override
+  public void fetchAll(RepositorySessionFetchRecordsDelegate delegate) {
+    Logger.info(LOG_TAG, "Running fetchAll.");
+    fetchSince(0, delegate);
+  }
+
+  @Override
+  public void fetch(final String[] guids, final RepositorySessionFetchRecordsDelegate delegate) {
+    Logger.info(LOG_TAG, "Running fetch.");
+
+    final long sharedEnd = now();
+    final String where = RepoUtils.computeSQLInClause(guids.length, FormHistory.GUID);
+
+    Callable<Cursor> regularCallable = new Callable<Cursor>() {
+      @Override
+      public Cursor call() throws Exception {
+        String regularWhere = where + " AND " + FormHistory.FIRST_USED + " <= " + Long.toString(1000 * sharedEnd); // Microseconds.
+        return regularHelper.safeQuery(formsProvider, ".fetch(regular)", null, regularWhere, guids, null);
+      }
+    };
+
+    Callable<Cursor> deletedCallable = new Callable<Cursor>() {
+      @Override
+      public Cursor call() throws Exception {
+        String deletedWhere = where + " AND " + DeletedFormHistory.TIME_DELETED + " <= " + Long.toString(sharedEnd); // Milliseconds.
+        return deletedHelper.safeQuery(formsProvider, ".fetch(deleted)", null, deletedWhere, guids, null);
+      }
+    };
+
+    ArrayList<Callable<Cursor>> callableCursors = new ArrayList<Callable<Cursor>>();
+    callableCursors.add(regularCallable);
+    callableCursors.add(deletedCallable);
+    fetchHelper(delegate, sharedEnd, callableCursors);
+  }
+
+  protected static final String GUID_IS = FormHistory.GUID + " = ?";
+
+  protected Record findExistingRecordByGuid(String guid)
+      throws RemoteException, NullCursorException {
+    Cursor cursor = null;
+    try {
+      cursor = regularHelper.safeQuery(formsProvider, ".findExistingRecordByGuid(regular)",
+          null, GUID_IS, new String[] { guid }, null);
+      if (cursor.moveToFirst()) {
+        return formHistoryRecordFromCursor(cursor);
+      }
+    } finally {
+      if (cursor != null) {
+        cursor.close();
+      }
+    }
+
+    try {
+      cursor = deletedHelper.safeQuery(formsProvider, ".findExistingRecordByGuid(deleted)",
+          null, GUID_IS, new String[] { guid }, null);
+      if (cursor.moveToFirst()) {
+        return deletedFormHistoryRecordFromCursor(cursor);
+      }
+    } finally {
+      if (cursor != null) {
+        cursor.close();
+      }
+    }
+
+    return null;
+  }
+
+  protected Record findExistingRecordByPayload(Record rawRecord)
+      throws RemoteException, NullCursorException {
+    if (!rawRecord.deleted) {
+      FormHistoryRecord record = (FormHistoryRecord) rawRecord;
+      Cursor cursor = null;
+      try {
+        String where = FormHistory.FIELD_NAME + " = ? AND " + FormHistory.VALUE + " = ?";
+        cursor = regularHelper.safeQuery(formsProvider, ".findExistingRecordByPayload",
+            null, where, new String[] { record.fieldName, record.fieldValue }, null);
+        if (cursor.moveToFirst()) {
+          return formHistoryRecordFromCursor(cursor);
+        }
+      } finally {
+        if (cursor != null) {
+          cursor.close();
+        }
+      }
+    }
+
+    return null;
+  }
+
+  /**
+   * Called when a record with locally known GUID has been reported deleted by
+   * the server.
+   * <p>
+   * We purge the record's GUID from the regular and deleted tables.
+   *
+   * @param existingRecord
+   *          The local <code>Record</code> to replace.
+   * @throws RemoteException
+   */
+  protected void deleteExistingRecord(Record existingRecord)
+      throws RemoteException {
+    if (existingRecord.deleted) {
+      formsProvider.delete(DELETED_FORM_HISTORY_CONTENT_URI, GUID_IS, new String[] { existingRecord.guid });
+      return;
+    }
+    formsProvider.delete(FORM_HISTORY_CONTENT_URI, GUID_IS, new String[] { existingRecord.guid });
+  }
+
+  protected ContentValues contentValuesForRegularRecord(Record rawRecord) {
+    if (rawRecord.deleted) {
+      throw new IllegalArgumentException("Deleted record passed to insertNewRegularRecord.");
+    }
+
+    FormHistoryRecord record = (FormHistoryRecord) rawRecord;
+    ContentValues cv = new ContentValues();
+    cv.put(FormHistory.GUID, record.guid);
+    cv.put(FormHistory.FIELD_NAME, record.fieldName);
+    cv.put(FormHistory.VALUE, record.fieldValue);
+    cv.put(FormHistory.FIRST_USED, 1000 * record.lastModified); // Microseconds.
+    return cv;
+  }
+
+  protected Object recordsBufferMonitor = new Object();
+  protected ArrayList<ContentValues> recordsBuffer = new ArrayList<ContentValues>();
+  private static final int INSERT_ITEM_THRESHOLD = 5;
+
+  protected void enqueueRegularRecord(Record record) {
+    synchronized (recordsBufferMonitor) {
+      if (recordsBuffer.size() >= INSERT_ITEM_THRESHOLD) {
+        // Insert the existing contents, then enqueue.
+        flushInsertQueue();
+      }
+      // Store the ContentValues, rather than the record.
+      recordsBuffer.add(contentValuesForRegularRecord(record));
+    }
+  }
+
+  public class RecordInsertRunnable implements Runnable {
+    ContentValues[] queue;
+
+    public RecordInsertRunnable(ArrayList<ContentValues> queue) {
+      ContentValues[] values = new ContentValues[queue.size()];
+      this.queue = queue.toArray(values);
+    }
+
+    @Override
+    public void run() {
+      if (queue == null || queue.length == 0) {
+        Logger.debug(LOG_TAG, "No form history items to insert: RecordInsertRunnable returning immediately.");
+        return;
+      }
+
+      try {
+        Logger.debug(LOG_TAG, "Inserting " + queue.length + " form history items...");
+        long before = System.currentTimeMillis();
+        formsProvider.bulkInsert(FORM_HISTORY_CONTENT_URI, queue);
+        long after = System.currentTimeMillis();
+        Logger.debug(LOG_TAG, "Inserting " + queue.length + " form history items... DONE (" + (after - before) + " milliseconds).");
+      } catch (RemoteException e) {
+        // TODO: REALLY HANDLE THIS ERROR by making this not be a Runnable and handling errors inline.
+        e.printStackTrace();
+      }
+    }
+  }
+
+  // Should always be called from storeWorkQueue.
+  protected void flushInsertQueue() {
+    synchronized (recordsBufferMonitor) {
+      if (recordsBuffer.size() > 0) {
+        final ArrayList<ContentValues> outgoing = recordsBuffer;
+        recordsBuffer = new ArrayList<ContentValues>();
+        new RecordInsertRunnable(outgoing).run();
+      }
+    }
+  }
+
+  @Override
+  public void storeDone() {
+    Runnable command = new Runnable() {
+      @Override
+      public void run() {
+        Logger.debug(LOG_TAG, "Checking for residual form history items to insert.");
+        synchronized (recordsBufferMonitor) {
+          flushInsertQueue();
+        }
+        storeDone(now()); // XXX?
+      }
+    };
+    storeWorkQueue.execute(command);
+  }
+
+  /**
+   * Called when a regular record with locally unknown GUID has been fetched
+   * from the server.
+   * <p>
+   * Since the record is regular, we insert it into the regular table.
+   *
+   * @param record The regular <code>Record</code> from the server.
+   * @throws RemoteException
+   */
+  protected void insertNewRegularRecord(Record record)
+      throws RemoteException {
+    enqueueRegularRecord(record);
+  }
+
+  /**
+   * Called when a regular record with has been fetched from the server and
+   * should replace an existing record.
+   * <p>
+   * We delete the existing record entirely, and then insert the new record into
+   * the regular table.
+   *
+   * @param toStore
+   *          The regular <code>Record</code> from the server.
+   * @param existingRecord
+   *          The local <code>Record</code> to replace.
+   * @throws RemoteException
+   */
+  protected void replaceExistingRecordWithRegularRecord(Record toStore, Record existingRecord)
+      throws RemoteException {
+    if (existingRecord.deleted) {
+      // Need two database operations -- purge from deleted table, insert into regular table.
+      deleteExistingRecord(existingRecord);
+      insertNewRegularRecord(toStore);
+      return;
+    }
+
+    final ContentValues cv = contentValuesForRegularRecord(toStore);
+    int updated = formsProvider.update(FORM_HISTORY_CONTENT_URI, cv, GUID_IS, new String[] { existingRecord.guid });
+    if (updated != 1) {
+      Logger.warn(LOG_TAG, "Expected to update 1 record with guid " + existingRecord.guid + " but updated " + updated + " records.");
+    }
+  }
+
+  @Override
+  public void store(Record rawRecord) throws NoStoreDelegateException {
+    if (delegate == null) {
+      Logger.warn(LOG_TAG, "No store delegate.");
+      throw new NoStoreDelegateException();
+    }
+    if (rawRecord == null) {
+      Logger.error(LOG_TAG, "Record sent to store was null");
+      throw new IllegalArgumentException("Null record passed to FormHistoryRepositorySession.store().");
+    }
+    if (!(rawRecord instanceof FormHistoryRecord)) {
+      Logger.error(LOG_TAG, "Can't store anything but a FormHistoryRecord");
+      throw new IllegalArgumentException("Non-FormHistoryRecord passed to FormHistoryRepositorySession.store().");
+    }
+    final FormHistoryRecord record = (FormHistoryRecord) rawRecord;
+
+    Runnable command = new Runnable() {
+      @Override
+      public void run() {
+        if (!isActive()) {
+          Logger.warn(LOG_TAG, "FormHistoryRepositorySession is inactive. Store failing.");
+          delegate.onRecordStoreFailed(new InactiveSessionException(null));
+          return;
+        }
+
+        // TODO: lift these into the session.
+        // Temporary: this matches prior syncing semantics, in which only
+        // the relationship between the local and remote record is considered.
+        // In the future we'll track these two timestamps and use them to
+        // determine which records have changed, and thus process incoming
+        // records more efficiently.
+        long lastLocalRetrieval  = 0;      // lastSyncTimestamp?
+        long lastRemoteRetrieval = 0;      // TODO: adjust for clock skew.
+        boolean remotelyModified = record.lastModified > lastRemoteRetrieval;
+
+        Record existingRecord;
+        try {
+          // GUID matching only: deleted records don't have a payload with which to search.
+          existingRecord = findExistingRecordByGuid(record.guid);
+          if (record.deleted) {
+            if (existingRecord == null) {
+              // We're done. Don't bother with a callback. That can change later
+              // if we want it to.
+              Logger.trace(LOG_TAG, "Incoming record " + record.guid + " is deleted, and no local version. Bye!");
+              return;
+            }
+
+            if (existingRecord.deleted) {
+              Logger.trace(LOG_TAG, "Local record already deleted. Purging local.");
+              deleteExistingRecord(existingRecord);
+              return;
+            }
+
+            // Which one wins?
+            if (!remotelyModified) {
+              Logger.trace(LOG_TAG, "Ignoring deleted record from the past.");
+              return;
+            }
+
+            boolean locallyModified = existingRecord.lastModified > lastLocalRetrieval;
+            if (!locallyModified) {
+              Logger.trace(LOG_TAG, "Remote modified, local not. Deleting.");
+              deleteExistingRecord(existingRecord);
+              trackRecord(record);
+              delegate.onRecordStoreSucceeded(record);
+              return;
+            }
+
+            Logger.trace(LOG_TAG, "Both local and remote records have been modified.");
+            if (record.lastModified > existingRecord.lastModified) {
+              Logger.trace(LOG_TAG, "Remote is newer, and deleted. Purging local.");
+              deleteExistingRecord(existingRecord);
+              trackRecord(record);
+              delegate.onRecordStoreSucceeded(record);
+              return;
+            }
+
+            Logger.trace(LOG_TAG, "Remote is older, local is not deleted. Ignoring.");
+            if (!locallyModified) {
+              Logger.warn(LOG_TAG, "Inconsistency: old remote record is deleted, but local record not modified!");
+              // Ensure that this is tracked for upload.
+            }
+            return;
+          }
+          // End deletion logic.
+
+          // Now we're processing a non-deleted incoming record.
+          if (existingRecord == null) {
+            Logger.trace(LOG_TAG, "Looking up match for record " + record.guid);
+            existingRecord = findExistingRecordByPayload(record);
+          }
+
+          if (existingRecord == null) {
+            // The record is new.
+            Logger.trace(LOG_TAG, "No match. Inserting.");
+            insertNewRegularRecord(record);
+            trackRecord(record);
+            delegate.onRecordStoreSucceeded(record);
+            return;
+          }
+
+          // We found a local duplicate.
+          Logger.trace(LOG_TAG, "Incoming record " + record.guid + " dupes to local record " + existingRecord.guid);
+
+          if (!RepoUtils.stringsEqual(record.guid, existingRecord.guid)) {
+            // We found a local record that does NOT have the same GUID -- keep the server's version.
+            Logger.trace(LOG_TAG, "Remote guid different from local guid. Storing to keep remote guid.");
+            replaceExistingRecordWithRegularRecord(record, existingRecord);
+            trackRecord(record);
+            delegate.onRecordStoreSucceeded(record);
+            return;
+          }
+
+          // We found a local record that does have the same GUID -- check modification times.
+          boolean locallyModified = existingRecord.lastModified > lastLocalRetrieval;
+          if (!locallyModified) {
+            Logger.trace(LOG_TAG, "Remote modified, local not. Storing.");
+            replaceExistingRecordWithRegularRecord(record, existingRecord);
+            trackRecord(record);
+            delegate.onRecordStoreSucceeded(record);
+            return;
+          }
+
+          Logger.trace(LOG_TAG, "Both local and remote records have been modified.");
+          if (record.lastModified > existingRecord.lastModified) {
+            Logger.trace(LOG_TAG, "Remote is newer, and not deleted. Storing.");
+            replaceExistingRecordWithRegularRecord(record, existingRecord);
+            trackRecord(record);
+            delegate.onRecordStoreSucceeded(record);
+            return;
+          }
+
+          Logger.trace(LOG_TAG, "Remote is older, local is not deleted. Ignoring.");
+          if (!locallyModified) {
+            Logger.warn(LOG_TAG, "Inconsistency: old remote record is not deleted, but local record not modified!");
+          }
+          return;
+        } catch (Exception e) {
+          Logger.error(LOG_TAG, "Store failed for " + record.guid, e);
+          delegate.onRecordStoreFailed(e);
+          return;
+        }
+      }
+    };
+
+    storeWorkQueue.execute(command);
+  }
+
+  /**
+   * Purge all data from the underlying databases.
+   */
+  public static void purgeDatabases(ContentProviderClient formsProvider)
+      throws RemoteException {
+    formsProvider.delete(FORM_HISTORY_CONTENT_URI, null, null);
+    formsProvider.delete(DELETED_FORM_HISTORY_CONTENT_URI, null, null);
+  }
+
+  @Override
+  public void wipe(final RepositorySessionWipeDelegate delegate) {
+    Runnable command = new Runnable() {
+      public void run() {
+        if (!isActive()) {
+          delegate.onWipeFailed(new InactiveSessionException(null));
+          return;
+        }
+
+        try {
+          Logger.debug(LOG_TAG, "Wiping form history and deleted form history...");
+          purgeDatabases(formsProvider);
+          Logger.debug(LOG_TAG, "Wiping form history and deleted form history... DONE");
+        } catch (Exception e) {
+          delegate.onWipeFailed(e);
+          return;
+        }
+
+        delegate.onWipeSucceeded();
+      }
+    };
+    storeWorkQueue.execute(command);
+  }
+}
--- a/mobile/android/base/sync/repositories/android/RepoUtils.java
+++ b/mobile/android/base/sync/repositories/android/RepoUtils.java
@@ -9,20 +9,22 @@ import org.json.simple.parser.JSONParser
 import org.json.simple.parser.ParseException;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.repositories.NullCursorException;
 import org.mozilla.gecko.sync.repositories.domain.ClientRecord;
 import org.mozilla.gecko.sync.repositories.domain.HistoryRecord;
 import org.mozilla.gecko.sync.repositories.domain.PasswordRecord;
 
+import android.content.ContentProviderClient;
 import android.content.Context;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.net.Uri;
+import android.os.RemoteException;
 
 public class RepoUtils {
 
   private static final String LOG_TAG = "RepoUtils";
 
   /**
    * A helper class for monotonous SQL querying. Does timing and logging,
    * offers a utility to throw on a null cursor.
@@ -48,16 +50,24 @@ public class RepoUtils {
       Cursor c = context.getContentResolver().query(uri, projection, selection, selectionArgs, sortOrder);
       return checkAndLogCursor(label, queryStart, c);
     }
 
     public Cursor safeQuery(String[] projection, String selection, String[] selectionArgs, String sortOrder) throws NullCursorException {
       return this.safeQuery(null, projection, selection, selectionArgs, sortOrder);
     }
 
+    // For ContentProviderClient queries.
+    public Cursor safeQuery(ContentProviderClient client, String label, String[] projection,
+                            String selection, String[] selectionArgs, String sortOrder) throws NullCursorException, RemoteException {
+      long queryStart = android.os.SystemClock.uptimeMillis();
+      Cursor c = client.query(uri, projection, selection, selectionArgs, sortOrder);
+      return checkAndLogCursor(label, queryStart, c);
+    }
+
     // For SQLiteOpenHelper queries.
     public Cursor safeQuery(SQLiteDatabase db, String label, String table, String[] columns,
                             String selection, String[] selectionArgs,
                             String groupBy, String having, String orderBy, String limit) throws NullCursorException {
       long queryStart = android.os.SystemClock.uptimeMillis();
       Cursor c = db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit);
       return checkAndLogCursor(label, queryStart, c);
     }
@@ -256,9 +266,23 @@ public class RepoUtils {
         System.out.print(dashes(columnWidth + 3));
       }
       System.out.print(dashes(columnWidth + 3 - 1));
       System.out.println("");
     } finally {
       cur.moveToPosition(originalPosition);
     }
   }
+
+  public static String computeSQLInClause(int items, String field) {
+    StringBuilder builder = new StringBuilder(field);
+    builder.append(" IN (");
+    int i = 0;
+    for (; i < items - 1; ++i) {
+      builder.append("?, ");
+    }
+    if (i < items) {
+      builder.append("?");
+    }
+    builder.append(")");
+    return builder.toString();
+  }
 }
--- a/mobile/android/base/sync/repositories/domain/BookmarkRecord.java
+++ b/mobile/android/base/sync/repositories/domain/BookmarkRecord.java
@@ -1,45 +1,11 @@
-/* ***** 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 Android Sync Client.
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Jason Voll <jvoll@mozilla.com>
- * Richard Newman <rnewman@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 ***** */
+/* 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/. */
 
 package org.mozilla.gecko.sync.repositories.domain;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.util.Map;
 
 import org.json.simple.JSONArray;
@@ -57,31 +23,33 @@ import android.util.Log;
  *
  */
 public class BookmarkRecord extends Record {
   public static final String PLACES_URI_PREFIX = "places:";
 
   private static final String LOG_TAG = "BookmarkRecord";
 
   public static final String COLLECTION_NAME = "bookmarks";
+  public static final long BOOKMARKS_TTL = -1; // Never ttl bookmarks.
 
   public BookmarkRecord(String guid, String collection, long lastModified, boolean deleted) {
     super(guid, collection, lastModified, deleted);
+    this.ttl = BOOKMARKS_TTL;
   }
   public BookmarkRecord(String guid, String collection, long lastModified) {
-    super(guid, collection, lastModified, false);
+    this(guid, collection, lastModified, false);
   }
   public BookmarkRecord(String guid, String collection) {
-    super(guid, collection, 0, false);
+    this(guid, collection, 0, false);
   }
   public BookmarkRecord(String guid) {
-    super(guid, COLLECTION_NAME, 0, false);
+    this(guid, COLLECTION_NAME, 0, false);
   }
   public BookmarkRecord() {
-    super(Utils.generateGuid(), COLLECTION_NAME, 0, false);
+    this(Utils.generateGuid(), COLLECTION_NAME, 0, false);
   }
 
   // Note: redundant accessors are evil. We're all grownups; let's just use
   // public fields.
   public String  title;
   public String  bookmarkURI;
   public String  description;
   public String  keyword;
@@ -121,16 +89,17 @@ public class BookmarkRecord extends Reco
     return tags;
   }
 
   @Override
   public Record copyWithIDs(String guid, long androidID) {
     BookmarkRecord out = new BookmarkRecord(guid, this.collection, this.lastModified, this.deleted);
     out.androidID = androidID;
     out.sortIndex = this.sortIndex;
+    out.ttl       = this.ttl;
 
     // Copy BookmarkRecord fields.
     out.title           = this.title;
     out.bookmarkURI     = this.bookmarkURI;
     out.description     = this.description;
     out.keyword         = this.keyword;
     out.parentID        = this.parentID;
     out.parentName      = this.parentName;
--- a/mobile/android/base/sync/repositories/domain/ClientRecord.java
+++ b/mobile/android/base/sync/repositories/domain/ClientRecord.java
@@ -11,24 +11,26 @@ import org.mozilla.gecko.sync.NonArrayJS
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.repositories.android.RepoUtils;
 
 public class ClientRecord extends Record {
   private static final String LOG_TAG = "ClientRecord";
 
   public static final String CLIENT_TYPE         = "mobile";
   public static final String COLLECTION_NAME     = "clients";
+  public static final long CLIENTS_TTL = 21 * 24 * 60 * 60; // 21 days in seconds.
   public static final String DEFAULT_CLIENT_NAME = "Default Name";
 
   public String name = ClientRecord.DEFAULT_CLIENT_NAME;
   public String type = ClientRecord.CLIENT_TYPE;
   public JSONArray commands;
 
   public ClientRecord(String guid, String collection, long lastModified, boolean deleted) {
     super(guid, collection, lastModified, deleted);
+    this.ttl = CLIENTS_TTL;
   }
 
   public ClientRecord(String guid, String collection, long lastModified) {
     this(guid, collection, lastModified, false);
   }
 
   public ClientRecord(String guid, String collection) {
     this(guid, collection, 0, false);
@@ -75,16 +77,17 @@ public class ClientRecord extends Record
     return true;
   }
 
   @Override
   public Record copyWithIDs(String guid, long androidID) {
     ClientRecord out = new ClientRecord(guid, this.collection, this.lastModified, this.deleted);
     out.androidID = androidID;
     out.sortIndex = this.sortIndex;
+    out.ttl       = this.ttl;
 
     out.name = this.name;
     out.type = this.type;
     return out;
   }
 
 /*
 Example record:
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/sync/repositories/domain/FormHistoryRecord.java
@@ -0,0 +1,137 @@
+/* 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/. */
+
+package org.mozilla.gecko.sync.repositories.domain;
+
+import org.mozilla.gecko.sync.ExtendedJSONObject;
+import org.mozilla.gecko.sync.Logger;
+import org.mozilla.gecko.sync.Utils;
+import org.mozilla.gecko.sync.repositories.android.RepoUtils;
+
+/**
+ * A FormHistoryRecord represents a saved form element.
+ *
+ * I map a <code>fieldName</code> string to a <code>value</code> string.
+ *
+ * {@link http://mxr.mozilla.org/services-central/source/services-central/services/sync/modules/engines/forms.js}
+ */
+public class FormHistoryRecord extends Record {
+  private static final String LOG_TAG = "FormHistoryRecord";
+
+  public static final String  COLLECTION_NAME = "forms";
+  private static final String PAYLOAD_NAME    = "name";
+  private static final String PAYLOAD_VALUE   = "value";
+
+  /**
+   * The name of the saved form field.
+   */
+  public String fieldName;
+
+  /**
+   * The value of the saved form field.
+   */
+  public String fieldValue;
+
+  public FormHistoryRecord(String guid, String collection, long lastModified, boolean deleted) {
+    super(guid, collection, lastModified, deleted);
+  }
+
+  public FormHistoryRecord(String guid, String collection, long lastModified) {
+    super(guid, collection, lastModified, false);
+  }
+
+  public FormHistoryRecord(String guid, String collection) {
+    super(guid, collection, 0, false);
+  }
+
+  public FormHistoryRecord(String guid) {
+    super(guid, COLLECTION_NAME, 0, false);
+  }
+
+  public FormHistoryRecord() {
+    super(Utils.generateGuid(), COLLECTION_NAME, 0, false);
+  }
+
+  @Override
+  public Record copyWithIDs(String guid, long androidID) {
+    FormHistoryRecord out = new FormHistoryRecord(guid, this.collection, this.lastModified, this.deleted);
+    out.androidID = androidID;
+    out.sortIndex = this.sortIndex;
+
+    // Copy FormHistoryRecord fields.
+    out.fieldName = this.fieldName;
+    out.fieldValue = this.fieldValue;
+
+    return out;
+  }
+
+  @Override
+  public void populatePayload(ExtendedJSONObject payload) {
+    putPayload(payload, PAYLOAD_NAME,  this.fieldName);
+    putPayload(payload, PAYLOAD_VALUE, this.fieldValue);
+  }
+
+  @Override
+  public void initFromPayload(ExtendedJSONObject payload) {
+    this.fieldName  = payload.getString(PAYLOAD_NAME);
+    this.fieldValue = payload.getString(PAYLOAD_VALUE);
+  }
+
+  /**
+   * We consider two form history records to be congruent if they represent the
+   * same form element regardless of times used.
+   */
+  @Override
+  public boolean congruentWith(Object o) {
+    if (o == null || !(o instanceof FormHistoryRecord)) {
+      return false;
+    }
+    FormHistoryRecord other = (FormHistoryRecord) o;
+    if (!super.congruentWith(other)) {
+      return false;
+    }
+    return RepoUtils.stringsEqual(this.fieldName, other.fieldName) &&
+           RepoUtils.stringsEqual(this.fieldValue, other.fieldValue);
+  }
+
+  @Override
+  public boolean equalPayloads(Object o) {
+    if (o == null || !(o instanceof FormHistoryRecord)) {
+      Logger.debug(LOG_TAG, "Not a FormHistoryRecord: " + o);
+      return false;
+    }
+    FormHistoryRecord other = (FormHistoryRecord) o;
+    if (!super.equalPayloads(other)) {
+      Logger.debug(LOG_TAG, "super.equalPayloads returned false.");
+      return false;
+    }
+
+    if (this.deleted) {
+      // FormHistoryRecords are equal if they are both deleted (which
+      // they are, since super.equalPayloads is true) and have the
+      // same GUID.
+      if (other.deleted) {
+        return RepoUtils.stringsEqual(this.guid, other.guid);
+      }
+      return false;
+    }
+
+    return RepoUtils.stringsEqual(this.fieldName,  other.fieldName) &&
+           RepoUtils.stringsEqual(this.fieldValue, other.fieldValue);
+  }
+
+  public FormHistoryRecord log(String logTag) {
+    try {
+      Logger.debug(logTag, "Returning form history record " + guid + " (" + androidID + ")");
+      Logger.debug(logTag, "> Last modified: " + lastModified);
+      if (Logger.LOG_PERSONAL_INFORMATION) {
+        Logger.pii(logTag, "> Field name:    " + fieldName);
+        Logger.pii(logTag, "> Field value:   " + fieldValue);
+      }
+    } catch (Exception e) {
+      Logger.debug(logTag, "Exception logging form history record " + this, e);
+    }
+    return this;
+  }
+}
--- a/mobile/android/base/sync/repositories/domain/HistoryRecord.java
+++ b/mobile/android/base/sync/repositories/domain/HistoryRecord.java
@@ -1,44 +1,11 @@
-/* ***** 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 Android Sync Client.
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Jason Voll <jvoll@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 ***** */
+/* 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/. */
 
 package org.mozilla.gecko.sync.repositories.domain;
 
 import java.util.HashMap;
 
 import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 import org.mozilla.gecko.sync.ExtendedJSONObject;
@@ -52,32 +19,33 @@ import org.mozilla.gecko.sync.repositori
  *
  * @author rnewman
  *
  */
 public class HistoryRecord extends Record {
   private static final String LOG_TAG = "HistoryRecord";
 
   public static final String COLLECTION_NAME = "history";
+  public static final long HISTORY_TTL = 60 * 24 * 60 * 60; // 60 days in seconds.
 
-  public HistoryRecord(String guid, String collection, long lastModified,
-      boolean deleted) {
+  public HistoryRecord(String guid, String collection, long lastModified, boolean deleted) {
     super(guid, collection, lastModified, deleted);
+    this.ttl = HISTORY_TTL;
   }
   public HistoryRecord(String guid, String collection, long lastModified) {
-    super(guid, collection, lastModified, false);
+    this(guid, collection, lastModified, false);
   }
   public HistoryRecord(String guid, String collection) {
-    super(guid, collection, 0, false);
+    this(guid, collection, 0, false);
   }
   public HistoryRecord(String guid) {
-    super(guid, COLLECTION_NAME, 0, false);
+    this(guid, COLLECTION_NAME, 0, false);
   }
   public HistoryRecord() {
-    super(Utils.generateGuid(), COLLECTION_NAME, 0, false);
+    this(Utils.generateGuid(), COLLECTION_NAME, 0, false);
   }
 
   public String    title;
   public String    histURI;
   public JSONArray visits;
   public long      fennecDateVisited;
   public long      fennecVisitCount;
 
@@ -91,16 +59,17 @@ public class HistoryRecord extends Recor
     return out;
   }
 
   @Override
   public Record copyWithIDs(String guid, long androidID) {
     HistoryRecord out = new HistoryRecord(guid, this.collection, this.lastModified, this.deleted);
     out.androidID = androidID;
     out.sortIndex = this.sortIndex;
+    out.ttl       = this.ttl;
 
     // Copy HistoryRecord fields.
     out.title             = this.title;
     out.histURI           = this.histURI;
     out.fennecDateVisited = this.fennecDateVisited;
     out.fennecVisitCount  = this.fennecVisitCount;
     out.visits            = this.copyVisits();
 
--- a/mobile/android/base/sync/repositories/domain/PasswordRecord.java
+++ b/mobile/android/base/sync/repositories/domain/PasswordRecord.java
@@ -1,70 +1,38 @@
-/* ***** 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 Android Sync Client.
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Jason Voll <jvoll@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 ***** */
+/* 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/. */
 
 package org.mozilla.gecko.sync.repositories.domain;
 
 import org.mozilla.gecko.sync.ExtendedJSONObject;
 import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.repositories.android.RepoUtils;
 
 public class PasswordRecord extends Record {
 
   public static final String COLLECTION_NAME = "passwords";
+  public static long PASSWORDS_TTL = -1; // Never expire passwords.
 
-  public PasswordRecord(String guid, String collection, long lastModified,
-      boolean deleted) {
+  public PasswordRecord(String guid, String collection, long lastModified, boolean deleted) {
     super(guid, collection, lastModified, deleted);
+    this.ttl = PASSWORDS_TTL;
   }
   public PasswordRecord(String guid, String collection, long lastModified) {
-    super(guid, collection, lastModified, false);
+    this(guid, collection, lastModified, false);
   }
   public PasswordRecord(String guid, String collection) {
-    super(guid, collection, 0, false);
+    this(guid, collection, 0, false);
   }
   public PasswordRecord(String guid) {
-    super(guid, COLLECTION_NAME, 0, false);
+    this(guid, COLLECTION_NAME, 0, false);
   }
   public PasswordRecord() {
-    super(Utils.generateGuid(), COLLECTION_NAME, 0, false);
+    this(Utils.generateGuid(), COLLECTION_NAME, 0, false);
   }
 
   public String hostname;
   public String formSubmitURL;
   public String httpRealm;
   // TODO these are encrypted in the passwords content provider,
   // need to figure out what we need to do here.
   public String username;
@@ -76,16 +44,17 @@ public class PasswordRecord extends Reco
   public long   timesUsed;
 
 
   @Override
   public Record copyWithIDs(String guid, long androidID) {
     PasswordRecord out = new PasswordRecord(guid, this.collection, this.lastModified, this.deleted);
     out.androidID = androidID;
     out.sortIndex = this.sortIndex;
+    out.ttl       = this.ttl;
 
     // Copy HistoryRecord fields.
     out.hostname      = this.hostname;
     out.formSubmitURL = this.formSubmitURL;
     out.httpRealm     = this.httpRealm;
     out.username      = this.username;
     out.password      = this.password;
     out.usernameField = this.usernameField;
--- a/mobile/android/base/sync/repositories/domain/Record.java
+++ b/mobile/android/base/sync/repositories/domain/Record.java
@@ -1,45 +1,11 @@
-/* ***** 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 Android Sync Client.
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Jason Voll <jvoll@mozilla.com>
- * Richard Newman <rnewman@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 ***** */
+/* 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/. */
 
 package org.mozilla.gecko.sync.repositories.domain;
 
 import java.io.UnsupportedEncodingException;
 
 import org.mozilla.gecko.sync.CryptoRecord;
 import org.mozilla.gecko.sync.ExtendedJSONObject;
 
@@ -99,24 +65,40 @@ import org.mozilla.gecko.sync.ExtendedJS
  */
 public abstract class Record {
 
   public String guid;
   public String collection;
   public long lastModified;
   public boolean deleted;
   public long androidID;
+  /**
+   * An integer indicating the relative importance of this item in the collection.
+   * <p>
+   * Default is 0.
+   */
   public long sortIndex;
+  /**
+   * The number of seconds to keep this record. After that time this item will
+   * no longer be returned in response to any request, and it may be pruned from
+   * the database.
+   * <p>
+   * Negative values mean never forget this record.
+   * <p>
+   * Default is 1 year.
+   */
+  public long ttl;
 
   public Record(String guid, String collection, long lastModified, boolean deleted) {
     this.guid         = guid;
     this.collection   = collection;
     this.lastModified = lastModified;
     this.deleted      = deleted;
     this.sortIndex    = 0;
+    this.ttl          = 365 * 24 * 60 * 60; // Seconds.
     this.androidID    = -1;
   }
 
   /**
    * Return true iff the input is a Record and has the same
    * collection and guid as this object.
    */
   public boolean equalIdentifiers(Object o) {
--- a/mobile/android/base/sync/repositories/domain/TabsRecord.java
+++ b/mobile/android/base/sync/repositories/domain/TabsRecord.java
@@ -82,31 +82,33 @@ public class TabsRecord extends Record {
       return out;
 
     }
   }
 
   private static final String LOG_TAG = "TabsRecord";
 
   public static final String COLLECTION_NAME = "tabs";
+  public static final long TABS_TTL = 7 * 24 * 60 * 60; // 7 days in seconds.
 
   public TabsRecord(String guid, String collection, long lastModified, boolean deleted) {
     super(guid, collection, lastModified, deleted);
+    this.ttl = TABS_TTL;
   }
   public TabsRecord(String guid, String collection, long lastModified) {
-    super(guid, collection, lastModified, false);
+    this(guid, collection, lastModified, false);
   }
   public TabsRecord(String guid, String collection) {
-    super(guid, collection, 0, false);
+    this(guid, collection, 0, false);
   }
   public TabsRecord(String guid) {
-    super(guid, COLLECTION_NAME, 0, false);
+    this(guid, COLLECTION_NAME, 0, false);
   }
   public TabsRecord() {
-    super(Utils.generateGuid(), COLLECTION_NAME, 0, false);
+    this(Utils.generateGuid(), COLLECTION_NAME, 0, false);
   }
 
   public String clientName;
   public ArrayList<Tab> tabs;
 
   @Override
   public void initFromPayload(ExtendedJSONObject payload) {
     clientName = (String) payload.get("clientName");
@@ -148,16 +150,17 @@ public class TabsRecord extends Record {
     payload.put("tabs", tabsToJSON(this.tabs));
   }
 
   @Override
   public Record copyWithIDs(String guid, long androidID) {
     TabsRecord out = new TabsRecord(guid, this.collection, this.lastModified, this.deleted);
     out.androidID = androidID;
     out.sortIndex = this.sortIndex;
+    out.ttl       = this.ttl;
 
     out.clientName = this.clientName;
     out.tabs = new ArrayList<Tab>(this.tabs);
 
     return out;
   }
 
   public ContentValues getClientsContentValues() {
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/sync/stage/FormHistoryServerSyncStage.java
@@ -0,0 +1,72 @@
+/* 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/. */
+
+package org.mozilla.gecko.sync.stage;
+
+import java.net.URISyntaxException;
+
+import org.mozilla.gecko.sync.CryptoRecord;
+import org.mozilla.gecko.sync.repositories.ConstrainedServer11Repository;
+import org.mozilla.gecko.sync.repositories.RecordFactory;
+import org.mozilla.gecko.sync.repositories.Repository;
+import org.mozilla.gecko.sync.repositories.android.FormHistoryRepositorySession;
+import org.mozilla.gecko.sync.repositories.domain.FormHistoryRecord;
+import org.mozilla.gecko.sync.repositories.domain.Record;
+
+public class FormHistoryServerSyncStage extends ServerSyncStage {
+
+  // Eventually this kind of sync stage will be data-driven,
+  // and all this hard-coding can go away.
+  private static final String FORM_HISTORY_SORT          = "index";
+  private static final long   FORM_HISTORY_REQUEST_LIMIT = 5000;         // Sanity limit.
+
+  @Override
+  public void execute(org.mozilla.gecko.sync.GlobalSession session) throws NoSuchStageException {
+    super.execute(session);
+  }
+
+  @Override
+  protected String getCollection() {
+    return "forms";
+  }
+  @Override
+  protected String getEngineName() {
+    return "forms";
+  }
+
+  @Override
+  protected Repository getRemoteRepository() throws URISyntaxException {
+    return new ConstrainedServer11Repository(session.config.getClusterURLString(),
+                                             session.config.username,
+                                             getCollection(),
+                                             session,
+                                             FORM_HISTORY_REQUEST_LIMIT,
+                                             FORM_HISTORY_SORT);
+  }
+
+  @Override
+  protected Repository getLocalRepository() {
+    return new FormHistoryRepositorySession.FormHistoryRepository();
+  }
+
+  public class FormHistoryRecordFactory extends RecordFactory {
+
+    @Override
+    public Record createRecord(Record record) {
+      FormHistoryRecord r = new FormHistoryRecord();
+      r.initFromEnvelope((CryptoRecord) record);
+      return r;
+    }
+  }
+
+  @Override
+  protected RecordFactory getRecordFactory() {
+    return new FormHistoryRecordFactory();
+  }
+
+  @Override
+  public boolean isEnabled() {
+    return false;
+  }
+}
--- a/mobile/android/base/sync/stage/GlobalSyncStage.java
+++ b/mobile/android/base/sync/stage/GlobalSyncStage.java
@@ -1,44 +1,11 @@
-/* ***** 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 Android Sync Client.
- *
- * The Initial Developer of the Original Code is
- * the Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2011
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *  Richard Newman <rnewman@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 ***** */
+/* 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/. */
 
 package org.mozilla.gecko.sync.stage;
 
 import org.mozilla.gecko.sync.GlobalSession;
 
 public interface GlobalSyncStage {
   public static enum Stage {
     idle,                       // Start state.
@@ -55,12 +22,13 @@ public interface GlobalSyncStage {
     /*
     processFirstSyncPref,
     processClientCommands,
     updateEnabledEngines,
     */
     syncTabs,
     syncBookmarks,
     syncHistory,
+    syncFormHistory,
     completed,
   }
   public void execute(GlobalSession session) throws NoSuchStageException;
 }
--- a/mobile/android/base/sync/stage/SyncClientsEngineStage.java
+++ b/mobile/android/base/sync/stage/SyncClientsEngineStage.java
@@ -13,16 +13,17 @@ import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 import org.mozilla.gecko.sync.CommandProcessor;
 import org.mozilla.gecko.sync.CryptoRecord;
 import org.mozilla.gecko.sync.ExtendedJSONObject;
 import org.mozilla.gecko.sync.GlobalSession;
 import org.mozilla.gecko.sync.HTTPFailureException;
 import org.mozilla.gecko.sync.Logger;
 import org.mozilla.gecko.sync.NoCollectionKeysSetException;
+import org.mozilla.gecko.sync.Utils;
 import org.mozilla.gecko.sync.crypto.CryptoException;
 import org.mozilla.gecko.sync.crypto.KeyBundle;
 import org.mozilla.gecko.sync.delegates.ClientsDataDelegate;
 import org.mozilla.gecko.sync.net.BaseResource;
 import org.mozilla.gecko.sync.net.SyncStorageCollectionRequest;
 import org.mozilla.gecko.sync.net.SyncStorageRecordRequest;
 import org.mozilla.gecko.sync.net.SyncStorageResponse;
 import org.mozilla.gecko.sync.net.WBOCollectionRequestDelegate;
@@ -60,31 +61,41 @@ public class SyncClientsEngineStage impl
    *
    * @author Marina Samuel
    *
    */
   public class ClientDownloadDelegate extends WBOCollectionRequestDelegate {
 
     // We use this on each WBO, so lift it out.
     final ClientsDataDelegate clientsDelegate = session.getClientsDelegate();
+    boolean localAccountGUIDDownloaded = false;
 
     @Override
     public String credentials() {
       return session.credentials();
     }
 
     @Override
     public String ifUnmodifiedSin