Merge m-c to s-c.
authorRichard Newman <rnewman@mozilla.com>
Wed, 28 Mar 2012 20:50:09 -0700
changeset 94028 ac83018cd960b1b5cf1e9ba40889911f99ee5694
parent 94027 79d0a46d47b87556506b126f27983477d1c25f84 (current diff)
parent 93819 1965a2c89d61a4d4e3ce156d6713c346f4624247 (diff)
child 94029 cf60d15e88040da8b309ec376ef2fbc84aa97ce6
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 m-c to s-c.
browser/modules/KeywordURLResetPrompter.jsm
browser/modules/test/browser_keywordURLReset.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgb.dxt1.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgba.dxt1.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgba.dxt3.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgba.dxt5.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgba.raw.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgb.dxt1.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.dxt1.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.dxt3.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.dxt5.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.pvrtc4bpp.js
content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.raw.js
content/canvas/test/webgl/conformance/extensions/webgl-experimental-compressed-textures.html
content/canvas/test/webgl/conformance/more/conformance/quickCheckAPI.html
content/canvas/test/webgl/conformance/shaders/00_shaders.txt
content/canvas/test/webgl/conformance/shaders/00_test_list.txt
content/canvas/test/webgl/conformance/shaders/glsl-features/00_test_list.txt
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec2-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec2-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec2.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec2.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec3-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec3-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec3.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec3.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec4-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec4-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec4.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/abs-vec4.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/abs.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/abs.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/base.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/base.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec2-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec2-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec2.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec2.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec3-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec3-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec3.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec3.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec4-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec4-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec4.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil-vec4.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/ceil.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec2-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec2-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec2.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec2.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec3-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec3-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec3.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec3.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec4-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec4-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec4.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/floor-vec4.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/floor.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/floor.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec2-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec2-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec2.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec2.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec3-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec3-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec3.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec3.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec4-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec4-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec4.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/fract-vec4.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/fract.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/fract.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec2-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec2-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec2.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec2.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec3-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec3-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec3.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec3.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec4-ref.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec4-ref.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec4.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/sign-vec4.vert
content/canvas/test/webgl/conformance/shaders/glsl-features/sign.frag
content/canvas/test/webgl/conformance/shaders/glsl-features/sign.vert
content/canvas/test/webgl/conformance/shaders/implicit/00_shaders.txt
content/canvas/test/webgl/conformance/shaders/implicit/add_int_float.vert
content/canvas/test/webgl/conformance/shaders/implicit/add_int_mat2.vert
content/canvas/test/webgl/conformance/shaders/implicit/add_int_mat3.vert
content/canvas/test/webgl/conformance/shaders/implicit/add_int_mat4.vert
content/canvas/test/webgl/conformance/shaders/implicit/add_int_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/add_int_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/add_int_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/add_ivec2_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/add_ivec3_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/add_ivec4_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/assign_int_to_float.vert
content/canvas/test/webgl/conformance/shaders/implicit/assign_ivec2_to_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/assign_ivec3_to_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/assign_ivec4_to_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/construct_struct.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_int_float.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_int_mat2.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_int_mat3.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_int_mat4.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_int_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_int_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_int_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_ivec2_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_ivec3_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/divide_ivec4_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/equal_int_float.vert
content/canvas/test/webgl/conformance/shaders/implicit/equal_ivec2_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/equal_ivec3_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/equal_ivec4_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/function_int_float.vert
content/canvas/test/webgl/conformance/shaders/implicit/function_ivec2_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/function_ivec3_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/function_ivec4_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/greater_than.vert
content/canvas/test/webgl/conformance/shaders/implicit/greater_than_equal.vert
content/canvas/test/webgl/conformance/shaders/implicit/less_than.vert
content/canvas/test/webgl/conformance/shaders/implicit/less_than_equal.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_int_float.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_int_mat2.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_int_mat3.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_int_mat4.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_int_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_int_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_int_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_ivec2_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_ivec3_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/multiply_ivec4_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/not_equal_int_float.vert
content/canvas/test/webgl/conformance/shaders/implicit/not_equal_ivec2_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/not_equal_ivec3_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/not_equal_ivec4_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_int_float.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_int_mat2.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_int_mat3.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_int_mat4.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_int_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_int_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_int_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_ivec2_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_ivec3_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/subtract_ivec4_vec4.vert
content/canvas/test/webgl/conformance/shaders/implicit/ternary_int_float.vert
content/canvas/test/webgl/conformance/shaders/implicit/ternary_ivec2_vec2.vert
content/canvas/test/webgl/conformance/shaders/implicit/ternary_ivec3_vec3.vert
content/canvas/test/webgl/conformance/shaders/implicit/ternary_ivec4_vec4.vert
content/canvas/test/webgl/conformance/shaders/misc/00_shaders.txt
content/canvas/test/webgl/conformance/shaders/misc/non-ascii-comments.vert
content/canvas/test/webgl/conformance/shaders/misc/non-ascii.vert
content/canvas/test/webgl/conformance/shaders/misc/shared-a.frag
content/canvas/test/webgl/conformance/shaders/misc/shared-b.frag
content/canvas/test/webgl/conformance/shaders/misc/shared.vert
content/canvas/test/webgl/conformance/shaders/reserved/00_shaders.txt
content/canvas/test/webgl/conformance/shaders/reserved/_webgl_field.vert
content/canvas/test/webgl/conformance/shaders/reserved/_webgl_function.vert
content/canvas/test/webgl/conformance/shaders/reserved/_webgl_struct.vert
content/canvas/test/webgl/conformance/shaders/reserved/_webgl_variable.vert
content/canvas/test/webgl/conformance/shaders/reserved/webgl_field.vert
content/canvas/test/webgl/conformance/shaders/reserved/webgl_function.vert
content/canvas/test/webgl/conformance/shaders/reserved/webgl_struct.vert
content/canvas/test/webgl/conformance/shaders/reserved/webgl_variable.vert
content/canvas/test/webgl/remove-uniqueObjectTest.patch
editor/libeditor/text/tests/test_bug717147.html
js/src/jit-test/tests/basic/testInitDictionary.js
js/src/jsfun.cpp
mobile/android/base/resources/layout/awesomebar_folder_header_row.xml
mobile/android/base/sync/repositories/android/PasswordColumns.java
--- a/accessible/src/atk/Makefile.in
+++ b/accessible/src/atk/Makefile.in
@@ -94,12 +94,14 @@ CXXFLAGS	+= $(MOZ_GTK2_CFLAGS)
 
 ifdef MOZ_ENABLE_DBUS
 CXXFLAGS += $(MOZ_DBUS_CFLAGS)
 endif
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
+  -I$(srcdir)/../xpcom \
   -I$(srcdir)/../xul \
   -I$(topsrcdir)/other-licenses/atk-1.0 \
   $(NULL)
--- a/accessible/src/atk/nsMaiInterfaceTable.cpp
+++ b/accessible/src/atk/nsMaiInterfaceTable.cpp
@@ -37,22 +37,24 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "InterfaceInitFuncs.h"
 
 #include "nsAccessibleWrap.h"
 #include "nsAccUtils.h"
 #include "nsIAccessibleTable.h"
+#include "TableAccessible.h"
 #include "nsMai.h"
 
 #include "nsArrayUtils.h"
 
+using namespace mozilla::a11y;
+
 extern "C" {
-
 static AtkObject*
 refAtCB(AtkTable *aTable, gint aRow, gint aColumn)
 {
     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
     if (!accWrap)
         return nsnull;
 
     nsCOMPtr<nsIAccessibleTable> accTable;
@@ -203,33 +205,27 @@ getRowExtentAtCB(AtkTable *aTable,
     PRInt32 extent;
     nsresult rv = accTable->GetRowExtentAt(aRow, aColumn, &extent);
     NS_ENSURE_SUCCESS(rv, -1);
 
     return static_cast<gint>(extent);
 }
 
 static AtkObject*
-getCaptionCB(AtkTable *aTable)
+getCaptionCB(AtkTable* aTable)
 {
-    nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
-    if (!accWrap)
-        return nsnull;
+  nsAccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
+  if (!accWrap)
+    return nsnull;
 
-    nsCOMPtr<nsIAccessibleTable> accTable;
-    accWrap->QueryInterface(NS_GET_IID(nsIAccessibleTable),
-                            getter_AddRefs(accTable));
-    NS_ENSURE_TRUE(accTable, nsnull);
+  TableAccessible* table = accWrap->AsTable();
+  NS_ENSURE_TRUE(table, nsnull);
 
-    nsCOMPtr<nsIAccessible> caption;
-    nsresult rv = accTable->GetCaption(getter_AddRefs(caption));
-    if (NS_FAILED(rv) || !caption)
-        return nsnull;
-
-    return nsAccessibleWrap::GetAtkObject(caption);
+  nsAccessible* caption = table->Caption();
+  return caption ? nsAccessibleWrap::GetAtkObject(caption) : nsnull;
 }
 
 static const gchar*
 getColumnDescriptionCB(AtkTable *aTable, gint aColumn)
 {
     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
     if (!accWrap)
         return nsnull;
--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -39,19 +39,16 @@
 
 #include "AccEvent.h"
 
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsApplicationAccessibleWrap.h"
 #include "nsDocAccessible.h"
 #include "nsIAccessibleText.h"
-#ifdef MOZ_XUL
-#include "nsXULTreeAccessible.h"
-#endif
 #include "nsAccEvent.h"
 #include "States.h"
 
 #include "nsIDOMDocument.h"
 #include "nsEventStateManager.h"
 #include "nsIServiceManager.h"
 #ifdef MOZ_XUL
 #include "nsIDOMXULMultSelectCntrlEl.h"
--- a/accessible/src/base/Makefile.in
+++ b/accessible/src/base/Makefile.in
@@ -99,18 +99,19 @@ EXPORTS_mozilla/a11y = \
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
+  -I$(srcdir)/../generic \
+  -I$(srcdir)/../html \
   -I$(srcdir)/../xpcom \
-  -I$(srcdir)/../html \
   -I$(srcdir)/../xul \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/style \
   -I$(srcdir)/../../../layout/xul/base/src \
   -I$(srcdir)/../xforms \
   $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
--- a/accessible/src/base/nsARIAGridAccessible.cpp
+++ b/accessible/src/base/nsARIAGridAccessible.cpp
@@ -53,42 +53,39 @@ using namespace mozilla::a11y;
 ////////////////////////////////////////////////////////////////////////////////
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor
 
 nsARIAGridAccessible::
   nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
-  nsAccessibleWrap(aContent, aDoc)
+  nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsARIAGridAccessible,
                              nsAccessible,
                              nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsIAccessibleTable
+//nsAccessNode
 
-NS_IMETHODIMP
-nsARIAGridAccessible::GetCaption(nsIAccessible **aCaption)
+void
+nsARIAGridAccessible::Shutdown()
 {
-  NS_ENSURE_ARG_POINTER(aCaption);
-  *aCaption = nsnull;
+  mTable = nsnull;
+  nsAccessibleWrap::Shutdown();
+}
 
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
-  // XXX: should be pointed by aria-labelledby on grid?
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleTable
 
 NS_IMETHODIMP
 nsARIAGridAccessible::GetSummary(nsAString &aSummary)
 {
   aSummary.Truncate();
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
@@ -705,25 +702,16 @@ nsARIAGridAccessible::UnselectColumn(PRI
       nsresult rv = SetARIASelected(cell, false);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsARIAGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
-{
-  NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
-  *aIsProbablyForLayout = false;
-
-  return NS_OK;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Protected
 
 bool
 nsARIAGridAccessible::IsValidRow(PRInt32 aRow)
 {
   if (aRow < 0)
     return false;
--- a/accessible/src/base/nsARIAGridAccessible.h
+++ b/accessible/src/base/nsARIAGridAccessible.h
@@ -37,31 +37,41 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsARIAGridAccessible_h_
 #define nsARIAGridAccessible_h_
 
 #include "nsIAccessibleTable.h"
 
 #include "nsHyperTextAccessibleWrap.h"
+#include "TableAccessible.h"
+#include "xpcAccessibleTable.h"
 
 /**
  * Accessible for ARIA grid and treegrid.
  */
 class nsARIAGridAccessible : public nsAccessibleWrap,
-                             public nsIAccessibleTable
+                             public xpcAccessibleTable,
+                             public nsIAccessibleTable,
+                             public mozilla::a11y::TableAccessible
 {
 public:
   nsARIAGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessibleTable
-  NS_DECL_NSIACCESSIBLETABLE
+  NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
+
+  // nsAccessible
+  virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
+
+  // nsAccessNode
+  virtual void Shutdown();
 
 protected:
   /**
    * Return true if the given row index is valid.
    */
   bool IsValidRow(PRInt32 aRow);
 
   /**
--- a/accessible/src/base/nsARIAMap.cpp
+++ b/accessible/src/base/nsARIAMap.cpp
@@ -168,16 +168,25 @@ nsRoleMapEntry nsARIAMap::gWAIRoleMap[] 
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     kNoReqStates,
     eReadonlyUntilEditable
   },
   {
+    "form",
+    roles::FORM,
+    kUseMapRole,
+    eNoValue,
+    eNoAction,
+    eNoLiveAttr,
+    kNoReqStates
+  },
+  {
     "grid",
     roles::TABLE,
     kUseMapRole,
     eNoValue,
     eNoAction,
     eNoLiveAttr,
     states::FOCUSABLE,
     eARIAMultiSelectable,
--- a/accessible/src/base/nsAccUtils.cpp
+++ b/accessible/src/base/nsAccUtils.cpp
@@ -42,19 +42,17 @@
 #include "nsIAccessibleTypes.h"
 #include "Role.h"
 #include "States.h"
 
 #include "nsAccessibilityService.h"
 #include "nsARIAMap.h"
 #include "nsDocAccessible.h"
 #include "nsHyperTextAccessible.h"
-#include "nsHTMLTableAccessible.h"
 #include "nsTextAccessible.h"
-#include "nsXULTreeGridAccessible.h"
 
 #include "nsIDOMXULContainerElement.h"
 #include "nsIDOMXULSelectCntrlEl.h"
 #include "nsIDOMXULSelectCntrlItemEl.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsComponentManagerUtils.h"
 
 namespace dom = mozilla::dom;
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -61,16 +61,21 @@ class EmbeddedObjCollector;
 class KeyBinding;
 class nsAccessible;
 class nsHyperTextAccessible;
 class nsHTMLImageAccessible;
 class nsHTMLImageMapAccessible;
 class nsHTMLLIAccessible;
 struct nsRoleMapEntry;
 class Relation;
+namespace mozilla {
+namespace a11y {
+class TableAccessible;
+}
+}
 class nsTextAccessible;
 
 struct nsRect;
 class nsIContent;
 class nsIFrame;
 class nsIAtom;
 class nsIView;
 
@@ -466,16 +471,18 @@ public:
 
   inline bool IsMenuButton() const { return mFlags & eMenuButtonAccessible; }
 
   inline bool IsMenuPopup() const { return mFlags & eMenuPopupAccessible; }
 
   inline bool IsRoot() const { return mFlags & eRootAccessible; }
   nsRootAccessible* AsRoot();
 
+  virtual mozilla::a11y::TableAccessible* AsTable() { return nsnull; }
+
   inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
   nsTextAccessible* AsTextLeaf();
 
   //////////////////////////////////////////////////////////////////////////////
   // ActionAccessible
 
   /**
    * Return the number of actions that can be performed on this accessible.
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -36,25 +36,23 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsRootAccessible_H_
 #define _nsRootAccessible_H_
 
 #include "nsCaretAccessible.h"
 #include "nsDocAccessibleWrap.h"
 
-#ifdef MOZ_XUL
-#include "nsXULTreeAccessible.h"
-#endif
 
 #include "nsHashtable.h"
 #include "nsCaretAccessible.h"
 #include "nsIDocument.h"
 #include "nsIDOMEventListener.h"
 
+class nsXULTreeAccessible;
 class Relation;
 
 #define NS_ROOTACCESSIBLE_IMPL_CID                      \
 {  /* eaba2cf0-21b1-4e2b-b711-d3a89dcd5e1a */           \
   0xeaba2cf0,                                           \
   0x21b1,                                               \
   0x4e2b,                                               \
   { 0xb7, 0x11, 0xd3, 0xa8, 0x9d, 0xcd, 0x5e, 0x1a }    \
new file mode 100644
--- /dev/null
+++ b/accessible/src/generic/TableAccessible.h
@@ -0,0 +1,170 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef TABLE_ACCESSIBLE_H
+#define TABLE_ACCESSIBLE_H
+
+#include "nsString.h"
+#include "nsTArray.h"
+#include "prtypes.h"
+
+class nsAccessible;
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * Accessible table interface.
+ */
+class TableAccessible
+{
+public:
+
+  /**
+   * Return the caption accessible if any for this table.
+   */
+  virtual nsAccessible* Caption() { return nsnull; }
+
+  /**
+   * Get the summary for this table.
+   */
+  virtual void Summary(nsString& aSummary) { aSummary.Truncate(); }
+
+  /**
+   * Return the number of columns in the table.
+   */
+  virtual PRUint32 ColCount() { return 0; }
+
+  /**
+   * Return the number of rows in the table.
+   */
+  virtual PRUint32 RowCount() { return 0; }
+
+  /**
+   * Return the accessible for the cell at the given row and column indices.
+   */
+  virtual nsAccessible* CellAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return nsnull; }
+
+  /**
+   * Return the index of the cell at the given row and column.
+   */
+  virtual PRInt32 CellIndexAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return -1; }
+
+  /**
+   * Return the column index of the cell with the given index.
+   */
+  virtual PRInt32 ColIndexAt(PRUint32 aCellIdx) { return -1; }
+
+  /**
+   * Return the row index of the cell with the given index.
+   */
+  virtual PRInt32 RowIndexAt(PRUint32 aCellIdx) { return -1; }
+
+  /**
+   * Get the row and column indices for the cell at the given index.
+   */
+  virtual void RowAndColIndicesAt(PRUint32 aCellIdx, PRInt32* aRowIdx,
+                                  PRInt32* aColIdx) {}
+
+  /**
+   * Return the number of columns occupied by the cell at the given row and
+   * column indices.
+   */
+  virtual PRUint32 ColExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
+
+  /**
+   * Return the number of rows occupied by the cell at the given row and column
+   * indices.
+   */
+  virtual PRUint32 RowExtentAt(PRUint32 aRowIdx, PRUint32 aColIdx) { return 1; }
+
+  /**
+   * Get the description of the given column.
+   */
+  virtual void ColDescription(PRUint32 aColIdx, nsString& aDescription)
+    { aDescription.Truncate(); }
+
+  /**
+   * Get the description for the given row.
+   */
+  virtual void RowDescription(PRUint32 aRowIdx, nsString& aDescription)
+    { aDescription.Truncate(); }
+
+  /**
+   * Return true if the given column is selected.
+   */
+  virtual bool IsColSelected(PRUint32 aColIdx) { return false; }
+
+  /**
+   * Return true if the given row is selected.
+   */
+  virtual bool IsRowSelected(PRUint32 aRowIdx) { return false; }
+
+  /**
+   * Return true if the given cell is selected.
+   */
+  virtual bool IsCellSelected(PRUint32 aRowIdx, PRUint32 aColIdx) { return false; }
+
+  /**
+   * Return the number of selected cells.
+   */
+  virtual PRUint32 SelectedCellCount() { return 0; }
+
+  /**
+   * Return the number of selected columns.
+   */
+  virtual PRUint32 SelectedColCount() { return 0; }
+
+  /**
+   * Return the number of selected rows.
+   */
+  virtual PRUint32 SelectedRowCount() { return 0; }
+
+  /**
+   * Get the set of selected cells.
+   */
+  virtual void SelectedCells(nsTArray<nsAccessible*>* aCells) {}
+
+  /**
+   * Get the set of selected column indices.
+   */
+  virtual void SelectedColIndices(nsTArray<PRUint32>* aCols) {}
+
+  /**
+   * Get the set of selected row indices.
+   */
+  virtual void SelectedRowIndices(nsTArray<PRUint32>* aRows) {}
+
+  /**
+   * Select the given column unselecting any other selected columns.
+   */
+  virtual void SelectCol(PRUint32 aColIdx) {}
+
+  /**
+   * Select the given row unselecting all other previously selected rows.
+   */
+  virtual void SelectRow(PRUint32 aRowIdx) {}
+
+  /**
+   * Unselect the given column leaving other selected columns selected.
+   */
+  virtual void UnselectCol(PRUint32 aColIdx) {}
+
+  /**
+   * Unselect the given row leaving other selected rows selected.
+   */
+  virtual void UnselectRow(PRUint32 aRowIdx) {}
+
+  /**
+   * Return true if the table is probably for layout.
+   */
+  virtual bool IsProbablyLayoutTable() { return false; }
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
--- a/accessible/src/html/Makefile.in
+++ b/accessible/src/html/Makefile.in
@@ -68,11 +68,13 @@ EXPORTS = \
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
+  -I$(srcdir)/../xpcom \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/xul/base/src \
   $(NULL)
--- a/accessible/src/html/nsHTMLTableAccessible.cpp
+++ b/accessible/src/html/nsHTMLTableAccessible.cpp
@@ -431,26 +431,36 @@ nsHTMLTableHeaderCellAccessible::NativeR
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsHTMLTableAccessible::
   nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
-  nsAccessibleWrap(aContent, aDoc)
+  nsAccessibleWrap(aContent, aDoc), xpcAccessibleTable(this)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsISupports implementation
 
 NS_IMPL_ISUPPORTS_INHERITED2(nsHTMLTableAccessible, nsAccessible,
                              nsHTMLTableAccessible, nsIAccessibleTable)
 
+////////////////////////////////////////////////////////////////////////////////
+//nsAccessNode
+
+void
+nsHTMLTableAccessible::Shutdown()
+{
+  mTable = nsnull;
+  nsAccessibleWrap::Shutdown();
+}
+
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsAccessible implementation
 
 void
 nsHTMLTableAccessible::CacheChildren()
 {
   // Move caption accessible so that it's the first child. Check for the first
@@ -506,19 +516,17 @@ nsHTMLTableAccessible::GetNameInternal(n
 }
 
 nsresult
 nsHTMLTableAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
 {
   nsresult rv = nsAccessibleWrap::GetAttributesInternal(aAttributes);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  bool isProbablyForLayout;
-  IsProbablyForLayout(&isProbablyForLayout);
-  if (isProbablyForLayout) {
+  if (IsProbablyLayoutTable()) {
     nsAutoString oldValueUnused;
     aAttributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
                                    NS_LITERAL_STRING("true"), oldValueUnused);
   }
   
   return NS_OK;
 }
 
@@ -533,23 +541,21 @@ nsHTMLTableAccessible::RelationByType(PR
     rel.AppendTarget(Caption());
 
   return rel;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsHTMLTableAccessible: nsIAccessibleTable implementation
 
-NS_IMETHODIMP
-nsHTMLTableAccessible::GetCaption(nsIAccessible **aCaption)
+nsAccessible*
+nsHTMLTableAccessible::Caption()
 {
-  NS_ENSURE_ARG_POINTER(aCaption);
-
-  NS_IF_ADDREF(*aCaption = Caption());
-  return NS_OK;
+  nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
+  return child && child->Role() == roles::CAPTION ? child : nsnull;
 }
 
 NS_IMETHODIMP
 nsHTMLTableAccessible::GetSummary(nsAString &aSummary)
 {
   nsCOMPtr<nsIDOMHTMLTableElement> table(do_QueryInterface(mContent));
   NS_ENSURE_TRUE(table, NS_ERROR_FAILURE);
 
@@ -1302,18 +1308,17 @@ nsHTMLTableAccessible::Description(nsStr
         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary,
                           aDescription);
       }
     }
   }
 
 #ifdef SHOW_LAYOUT_HEURISTIC
   if (aDescription.IsEmpty()) {
-    bool isProbablyForLayout;
-    IsProbablyForLayout(&isProbablyForLayout);
+    bool isProbablyForLayout = IsProbablyLayoutTable();
     aDescription = mLayoutHeuristic;
   }
 #ifdef DEBUG_A11Y
   printf("\nTABLE: %s\n", NS_ConvertUTF16toUTF8(mLayoutHeuristic).get());
 #endif
 #endif
 }
 
@@ -1352,41 +1357,39 @@ nsHTMLTableAccessible::HasDescendant(con
   // performance problems only. Note, currently 'aAllowEmpty' flag is used for
   // caption element only. On another hand we create accessible object for
   // the first entry of caption element (see
   // nsHTMLTableAccessible::CacheChildren).
   nodeList->Item(1, getter_AddRefs(foundItem));
   return !!foundItem;
 }
 
-NS_IMETHODIMP
-nsHTMLTableAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
+bool
+nsHTMLTableAccessible::IsProbablyLayoutTable()
 {
   // Implement a heuristic to determine if table is most likely used for layout
   // XXX do we want to look for rowspan or colspan, especialy that span all but a couple cells
   // at the beginning or end of a row/col, and especially when they occur at the edge of a table?
   // XXX expose this info via object attributes to AT-SPI
 
   // XXX For now debugging descriptions are always on via SHOW_LAYOUT_HEURISTIC
   // This will allow release trunk builds to be used by testers to refine the algorithm
   // Change to |#define SHOW_LAYOUT_HEURISTIC DEBUG| before final release
 #ifdef SHOW_LAYOUT_HEURISTIC
 #define RETURN_LAYOUT_ANSWER(isLayout, heuristic) \
-  { *aIsProbablyForLayout = isLayout; \
-    mLayoutHeuristic = isLayout ? NS_LITERAL_STRING("layout table: ") : NS_LITERAL_STRING("data table: "); \
-    mLayoutHeuristic += NS_LITERAL_STRING(heuristic); return NS_OK; }
+  { \
+    mLayoutHeuristic = isLayout ? \
+      NS_LITERAL_STRING("layout table: " heuristic) : \
+      NS_LITERAL_STRING("data table: " heuristic); \
+    return isLayout; \
+  }
 #else
-#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { *aIsProbablyForLayout = isLayout; return NS_OK; }
+#define RETURN_LAYOUT_ANSWER(isLayout, heuristic) { return isLayout; }
 #endif
 
-  *aIsProbablyForLayout = false;
-
-  if (IsDefunct())
-    return NS_ERROR_FAILURE;
-
   nsDocAccessible* docAccessible = Document();
   if (docAccessible) {
     PRUint64 docState = docAccessible->State();
     if (docState & states::EDITABLE) {  // Need to see all elements while document is being edited
       RETURN_LAYOUT_ANSWER(false, "In editable document");
     }
   }
 
--- a/accessible/src/html/nsHTMLTableAccessible.h
+++ b/accessible/src/html/nsHTMLTableAccessible.h
@@ -36,16 +36,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _nsHTMLTableAccessible_H_
 #define _nsHTMLTableAccessible_H_
 
 #include "nsHyperTextAccessibleWrap.h"
 #include "nsIAccessibleTable.h"
+#include "TableAccessible.h"
+#include "xpcAccessibleTable.h"
 
 class nsITableLayout;
 class nsITableCellLayout;
 
 /**
  * HTML table cell accessible (html:td).
  */
 class nsHTMLTableCellAccessible : public nsHyperTextAccessibleWrap,
@@ -116,40 +118,45 @@ public:
 {  /* 8d6d9c40-74bd-47ac-88dc-4a23516aa23d */           \
   0x8d6d9c40,                                           \
   0x74bd,                                               \
   0x47ac,                                               \
   { 0x88, 0xdc, 0x4a, 0x23, 0x51, 0x6a, 0xa2, 0x3d }    \
 }
 
 class nsHTMLTableAccessible : public nsAccessibleWrap,
-                              public nsIAccessibleTable
+                              public xpcAccessibleTable,
+                              public nsIAccessibleTable,
+                              public mozilla::a11y::TableAccessible
 {
 public:
   nsHTMLTableAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
 
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIACCESSIBLETABLE
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_TABLEACCESSIBLE_IMPL_CID)
 
+  // nsIAccessible Table
+  NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
+
+  // TableAccessible
+  virtual nsAccessible* Caption();
+  virtual bool IsProbablyLayoutTable();
+
+  // nsAccessNode
+  virtual void Shutdown();
+
   // nsAccessible
+  virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
   virtual void Description(nsString& aDescription);
   virtual nsresult GetNameInternal(nsAString& aName);
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
   virtual nsresult GetAttributesInternal(nsIPersistentProperties *aAttributes);
   virtual Relation RelationByType(PRUint32 aRelationType);
 
-  // TableAccessible
-  inline nsAccessible* Caption() const
-  {
-    nsAccessible* child = mChildren.SafeElementAt(0, nsnull);
-    return child && child->Role() == mozilla::a11y::roles::CAPTION ? child : nsnull;
-  }
-
   // nsHTMLTableAccessible
 
   /**
    * Retun cell element at the given row and column index.
    */
   nsresult GetCellAt(PRInt32 aRowIndex, PRInt32 aColIndex,
                      nsIDOMElement* &aCell);
 
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -127,17 +127,17 @@ role
 nsHyperTextAccessible::NativeRole()
 {
   nsIAtom *tag = mContent->Tag();
 
   if (tag == nsGkAtoms::form)
     return roles::FORM;
 
   if (tag == nsGkAtoms::blockquote || tag == nsGkAtoms::div ||
-      tag == nsGkAtoms::nav)
+      tag == nsGkAtoms::section || tag == nsGkAtoms::nav)
     return roles::SECTION;
 
   if (tag == nsGkAtoms::h1 || tag == nsGkAtoms::h2 ||
       tag == nsGkAtoms::h3 || tag == nsGkAtoms::h4 ||
       tag == nsGkAtoms::h5 || tag == nsGkAtoms::h6)
     return roles::HEADING;
 
   if (tag == nsGkAtoms::article)
@@ -775,33 +775,32 @@ nsHyperTextAccessible::GetRelativeOffset
   const bool kIsVisualBidi = false;          // use visual order for bidi text
 
   EWordMovementType wordMovementType = aNeedsStart ? eStartWord : eEndWord;
   if (aAmount == eSelectLine) {
     aAmount = (aDirection == eDirNext) ? eSelectEndLine : eSelectBeginLine;
   }
 
   // Ask layout for the new node and offset, after moving the appropriate amount
-  nsPeekOffsetStruct pos;
 
   nsresult rv;
   PRInt32 contentOffset = aFromOffset;
   if (nsAccUtils::IsText(aFromAccessible)) {
     nsIFrame *frame = aFromAccessible->GetFrame();
     NS_ENSURE_TRUE(frame, -1);
 
     if (frame->GetType() == nsGkAtoms::textFrame) {
       rv = RenderedToContentOffset(frame, aFromOffset, &contentOffset);
       NS_ENSURE_SUCCESS(rv, -1);
     }
   }
 
-  pos.SetData(aAmount, aDirection, contentOffset,
-              0, kIsJumpLinesOk, kIsScrollViewAStop, kIsKeyboardSelect, kIsVisualBidi,
-              wordMovementType);
+  nsPeekOffsetStruct pos(aAmount, aDirection, contentOffset,
+                         0, kIsJumpLinesOk, kIsScrollViewAStop, kIsKeyboardSelect, kIsVisualBidi,
+                         wordMovementType);
   rv = aFromFrame->PeekOffset(&pos);
   if (NS_FAILED(rv)) {
     if (aDirection == eDirPrevious) {
       // Use passed-in frame as starting point in failure case for now,
       // this is a hack to deal with starting on a list bullet frame,
       // which fails in PeekOffset() because the line iterator doesn't see it.
       // XXX Need to look at our overall handling of list bullets, which are an odd case
       pos.mResultContent = aFromFrame->GetContent();
@@ -1235,16 +1234,19 @@ nsHyperTextAccessible::GetAttributesInte
 
   // For the html landmark elements we expose them like we do aria landmarks to
   // make AT navigation schemes "just work". Note html:header is redundant as
   // a landmark since it usually contains headings. We're not yet sure how the
   // web will use html:footer but our best bet right now is as contentinfo.
   if (mContent->Tag() == nsGkAtoms::nav)
     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("navigation"));
+  else if (mContent->Tag() == nsGkAtoms::section) 
+    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
+                           NS_LITERAL_STRING("region"));
   else if (mContent->Tag() == nsGkAtoms::footer) 
     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("contentinfo"));
   else if (mContent->Tag() == nsGkAtoms::aside) 
     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::xmlroles,
                            NS_LITERAL_STRING("complementary"));
 
   return  NS_OK;
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -109,13 +109,15 @@ FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/config.mk
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES += \
   -I$(srcdir) \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
+  -I$(srcdir)/../xpcom \
   -I$(srcdir)/../xul \
   -I$(srcdir)/../../../content/base/src \
   -I$(srcdir)/../../../content/events/src \
   $(NULL)
--- a/accessible/src/xpcom/Makefile.in
+++ b/accessible/src/xpcom/Makefile.in
@@ -45,18 +45,20 @@ include $(DEPTH)/config/autoconf.mk
 
 MODULE = accessibility
 LIBRARY_NAME = accessibility_xpcom_s
 LIBXUL_LIBRARY = 1
 
 CPPSRCS = \
   nsAccEvent.cpp \
   nsAccessibleRelation.cpp \
+  xpcAccessibleTable.cpp \
   $(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/accessible/src/xpcom/xpcAccessibleTable.cpp
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xpcAccessibleTable.h"
+
+#include "nsAccessible.h"
+#include "TableAccessible.h"
+
+nsresult
+xpcAccessibleTable::GetCaption(nsIAccessible** aCaption)
+{
+  NS_ENSURE_ARG_POINTER(aCaption);
+  *aCaption = nsnull;
+  if (!mTable)
+    return NS_ERROR_FAILURE;
+
+  NS_IF_ADDREF(*aCaption = mTable->Caption());
+  return NS_OK;
+}
+
+nsresult
+xpcAccessibleTable::IsProbablyForLayout(bool* aResult)
+{
+  NS_ENSURE_ARG_POINTER(aResult);
+  *aResult = false;
+  if (!mTable)
+    return NS_ERROR_FAILURE;
+
+  *aResult = mTable->IsProbablyLayoutTable();
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/src/xpcom/xpcAccessibleTable.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
+#define MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
+
+#include "nscore.h"
+
+class nsIAccessible;
+namespace mozilla {
+namespace a11y {
+class TableAccessible;
+}
+}
+
+class xpcAccessibleTable
+{
+public:
+  xpcAccessibleTable(mozilla::a11y::TableAccessible* aTable) : mTable(aTable) { }
+
+  nsresult GetCaption(nsIAccessible** aCaption);
+  nsresult IsProbablyForLayout(bool* aIsForLayout);
+
+protected:
+  mozilla::a11y::TableAccessible* mTable;
+};
+
+#define NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE \
+  NS_IMETHOD GetCaption(nsIAccessible** aCaption) \
+    { return xpcAccessibleTable::GetCaption(aCaption); } \
+  NS_SCRIPTABLE NS_IMETHOD GetSummary(nsAString & aSummary); \
+  NS_SCRIPTABLE NS_IMETHOD GetColumnCount(PRInt32 *aColumnCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowCount(PRInt32 *aRowCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetCellAt(PRInt32 rowIndex, PRInt32 columnIndex, nsIAccessible * *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetCellIndexAt(PRInt32 rowIndex, PRInt32 columnIndex, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetColumnIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowIndexAt(PRInt32 cellIndex, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowAndColumnIndicesAt(PRInt32 cellIndex, PRInt32 *rowIndex NS_OUTPARAM, PRInt32 *columnIndex NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetColumnExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowExtentAt(PRInt32 row, PRInt32 column, PRInt32 *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetColumnDescription(PRInt32 columnIndex, nsAString & _retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetRowDescription(PRInt32 rowIndex, nsAString & _retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD IsColumnSelected(PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD IsRowSelected(PRInt32 rowIndex, bool *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD IsCellSelected(PRInt32 rowIndex, PRInt32 columnIndex, bool *_retval NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedCellCount(PRUint32 *aSelectedCellCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnCount(PRUint32 *aSelectedColumnCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedRowCount(PRUint32 *aSelectedRowCount); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedCells(nsIArray * *aSelectedCells); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedCellIndices(PRUint32 *cellsArraySize NS_OUTPARAM, PRInt32 **cellsArray NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedColumnIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD GetSelectedRowIndices(PRUint32 *rowsArraySize NS_OUTPARAM, PRInt32 **rowsArray NS_OUTPARAM); \
+  NS_SCRIPTABLE NS_IMETHOD SelectRow(PRInt32 rowIndex); \
+  NS_SCRIPTABLE NS_IMETHOD SelectColumn(PRInt32 columnIndex); \
+  NS_SCRIPTABLE NS_IMETHOD UnselectColumn(PRInt32 columnIndex); \
+  NS_IMETHOD UnselectRow(PRInt32 aRowIdx); \
+  NS_IMETHOD IsProbablyForLayout(bool* aResult) \
+  { return xpcAccessibleTable::IsProbablyForLayout(aResult); } \
+
+#endif // MOZILLA_A11Y_XPCOM_XPACCESSIBLETABLE_H_
--- a/accessible/src/xul/Makefile.in
+++ b/accessible/src/xul/Makefile.in
@@ -67,12 +67,14 @@ CPPSRCS = \
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES = \
   -I$(srcdir) \
   -I$(srcdir)/../base \
+  -I$(srcdir)/../generic \
   -I$(srcdir)/../html \
+  -I$(srcdir)/../xpcom \
   -I$(srcdir)/../../../layout/generic \
   -I$(srcdir)/../../../layout/xul/base/src \
   $(NULL)
--- a/accessible/src/xul/nsXULListboxAccessible.cpp
+++ b/accessible/src/xul/nsXULListboxAccessible.cpp
@@ -129,17 +129,17 @@ nsXULColumnItemAccessible::DoAction(PRUi
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULListboxAccessible::
   nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
-  XULSelectControlAccessible(aContent, aDoc)
+  XULSelectControlAccessible(aContent, aDoc), xpcAccessibleTable(this)
 {
   nsIContent* parentContent = mContent->GetParent();
   if (parentContent) {
     nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
       do_QueryInterface(parentContent);
     if (autoCompletePopupElm)
       mFlags |= eAutoCompletePopupAccessible;
   }
@@ -159,16 +159,26 @@ nsXULListboxAccessible::QueryInterface(R
     *aInstancePtr = static_cast<nsIAccessibleTable*>(this);
     NS_ADDREF_THIS();
     return NS_OK;
   }
 
   return NS_ERROR_NO_INTERFACE;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+//nsAccessNode
+
+void
+nsXULListboxAccessible::Shutdown()
+{
+  mTable = nsnull;
+  XULSelectControlAccessible::Shutdown();
+}
+
 bool
 nsXULListboxAccessible::IsMulticolumn()
 {
   PRInt32 numColumns = 0;
   nsresult rv = GetColumnCount(&numColumns);
   if (NS_FAILED(rv))
     return false;
 
@@ -225,25 +235,16 @@ nsXULListboxAccessible::NativeRole()
 
   return IsMulticolumn() ? roles::TABLE : roles::LISTBOX;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListboxAccessible. nsIAccessibleTable
 
 NS_IMETHODIMP
-nsXULListboxAccessible::GetCaption(nsIAccessible **aCaption)
-{
-  NS_ENSURE_ARG_POINTER(aCaption);
-  *aCaption = nsnull;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
 nsXULListboxAccessible::GetSummary(nsAString &aSummary)
 {
   aSummary.Truncate();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -815,25 +816,16 @@ nsXULListboxAccessible::UnselectRow(PRIn
 
 NS_IMETHODIMP
 nsXULListboxAccessible::UnselectColumn(PRInt32 aColumn)
 {
   // xul:listbox and xul:richlistbox support row selection only.
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULListboxAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
-{
-  NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
-  *aIsProbablyForLayout = false;
-
-  return NS_OK;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListboxAccessible: Widgets
 
 bool
 nsXULListboxAccessible::IsWidget() const
 {
   return true;
 }
--- a/accessible/src/xul/nsXULListboxAccessible.h
+++ b/accessible/src/xul/nsXULListboxAccessible.h
@@ -35,21 +35,22 @@
  * 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 __nsXULListboxAccessible_h__
 #define __nsXULListboxAccessible_h__
 
-#include "nsIAccessibleTable.h"
-
 #include "nsCOMPtr.h"
 #include "nsXULMenuAccessible.h"
 #include "nsBaseWidgetAccessible.h"
+#include "nsIAccessibleTable.h"
+#include "TableAccessible.h"
+#include "xpcAccessibleTable.h"
 #include "XULSelectControlAccessible.h"
 
 class nsIWeakReference;
 
 /**
  * nsXULColumnsAccessible are accessible for list and tree columns elements
  * (xul:treecols and xul:listcols).
  */
@@ -85,29 +86,37 @@ public:
 
   enum { eAction_Click = 0 };
 };
 
 /*
  * A class the represents the XUL Listbox widget.
  */
 class nsXULListboxAccessible : public XULSelectControlAccessible,
-                               public nsIAccessibleTable
+                               public xpcAccessibleTable,
+                               public nsIAccessibleTable,
+                               public mozilla::a11y::TableAccessible
 {
 public:
   nsXULListboxAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
   virtual ~nsXULListboxAccessible() {}
 
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIACCESSIBLETABLE
+
+  // nsIAccessibleTable
+  NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
 
   // nsIAccessible
   NS_IMETHOD GetValue(nsAString& aValue);
 
+  // nsAccessNode
+  virtual void Shutdown();
+
   // nsAccessible
+  virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
   virtual mozilla::a11y::role NativeRole();
   virtual PRUint64 NativeState();
 
   // Widgets
   virtual bool IsWidget() const;
   virtual bool IsActiveWidget() const;
   virtual bool AreItemsOperable() const;
 
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -53,40 +53,31 @@
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULTreeGridAccessible::
   nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
-  nsXULTreeAccessible(aContent, aDoc)
+  nsXULTreeAccessible(aContent, aDoc), xpcAccessibleTable(this)
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible: nsISupports implementation
 
 NS_IMPL_ISUPPORTS_INHERITED1(nsXULTreeGridAccessible,
                              nsXULTreeAccessible,
                              nsIAccessibleTable)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible: nsIAccessibleTable implementation
 
 NS_IMETHODIMP
-nsXULTreeGridAccessible::GetCaption(nsIAccessible **aCaption)
-{
-  NS_ENSURE_ARG_POINTER(aCaption);
-  *aCaption = nsnull;
-
-  return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
-}
-
-NS_IMETHODIMP
 nsXULTreeGridAccessible::GetSummary(nsAString &aSummary)
 {
   aSummary.Truncate();
   return IsDefunct() ? NS_ERROR_FAILURE : NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeGridAccessible::GetColumnCount(PRInt32 *aColumnCount)
@@ -565,23 +556,24 @@ nsXULTreeGridAccessible::UnselectRow(PRI
 }
 
 NS_IMETHODIMP
 nsXULTreeGridAccessible::UnselectColumn(PRInt32 aColumnIndex)
 {
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsXULTreeGridAccessible::IsProbablyForLayout(bool *aIsProbablyForLayout)
+////////////////////////////////////////////////////////////////////////////////
+// nsXULTreeGridAccessible: nsAccessNode implementation
+
+void
+nsXULTreeGridAccessible::Shutdown()
 {
-  NS_ENSURE_ARG_POINTER(aIsProbablyForLayout);
-  *aIsProbablyForLayout = false;
-
-  return NS_OK;
+  mTable = nsnull;
+  nsXULTreeAccessible::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridAccessible: nsAccessible implementation
 
 role
 nsXULTreeGridAccessible::NativeRole()
 {
--- a/accessible/src/xul/nsXULTreeGridAccessible.h
+++ b/accessible/src/xul/nsXULTreeGridAccessible.h
@@ -34,36 +34,42 @@
  * 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 __nsXULTreeGridAccessible_h__
 #define __nsXULTreeGridAccessible_h__
 
-#include "nsIAccessibleTable.h"
-
 #include "nsXULTreeAccessible.h"
+#include "TableAccessible.h"
+#include "xpcAccessibleTable.h"
 
 /**
  * Represents accessible for XUL tree in the case when it has multiple columns.
  */
 class nsXULTreeGridAccessible : public nsXULTreeAccessible,
-                                public nsIAccessibleTable
+                                public xpcAccessibleTable,
+                                public nsIAccessibleTable,
+                                public mozilla::a11y::TableAccessible
 {
 public:
   nsXULTreeGridAccessible(nsIContent* aContent, nsDocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIAccessibleTable
-  NS_DECL_NSIACCESSIBLETABLE
+  NS_DECL_OR_FORWARD_NSIACCESSIBLETABLE_WITH_XPCACCESSIBLETABLE
+
+  // nsAccessNode
+  virtual void Shutdown();
 
   // nsAccessible
+  virtual mozilla::a11y::TableAccessible* AsTable() { return this; }
   virtual mozilla::a11y::role NativeRole();
 
 protected:
 
   // nsXULTreeAccessible
   virtual already_AddRefed<nsAccessible> CreateTreeItemAccessible(PRInt32 aRow);
 };
 
--- a/accessible/tests/mochitest/elm/test_landmarks.html
+++ b/accessible/tests/mochitest/elm/test_landmarks.html
@@ -19,64 +19,82 @@
 
     function doTest()
     {
       testRole("nav", ROLE_SECTION);
       testRole("header", ROLE_HEADER);
       testRole("footer", ROLE_FOOTER);
       testRole("article", ROLE_DOCUMENT);
       testRole("aside", ROLE_NOTE);
+      testRole("section", ROLE_SECTION); // XXX bug 739612: not a landmark
 
       testRole("main", ROLE_DOCUMENT);
+      testRole("form", ROLE_FORM);
 
       // Some AT may look for this
       testAttrs("nav", {"xml-roles" : "navigation"}, true);
       testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
       testAttrs("aside", {"xml-roles" : "complementary"}, true);
-      testAttrs("main", {"xml-roles" : "main"}, true); // ARIA override
+      testAttrs("section", {"xml-roles" : "region"}, true);
+      testAttrs("main", {"xml-roles" : "main"}, true); // // ARIA override
+      testAttrs("form", {"xml-roles" : "form"}, true);
 
       // And some AT may look for this
       testAttrs("nav", {"tag" : "nav"}, true);
       testAttrs("header", {"tag" : "header"}, true);
       testAttrs("footer", {"tag" : "footer"}, true);
       testAttrs("article", {"tag" : "article"}, true);
       testAttrs("aside", {"tag" : "aside"}, true);
-      testAttrs("main", {"tag" : "article"}, true); // no override expected
+      testAttrs("section", {"tag" : "section"}, true);
+      testAttrs("main", {"tag" : "article"}, true);
+      testAttrs("form", {"tag" : "article"}, true);
 
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 <body>
 
   <a target="_blank"
-    title="Provide mappings for html5 <nav> <header> <footer> <article>"
-    href="https://bugzilla.mozilla.org/show_bug.cgi?id=593368">
-     Mozilla Bug 593368
+     title="Provide mappings for html5 <nav> <header> <footer> <article>"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=593368">
+    Bug 593368
   </a><br/>
   <a target="_blank"
-    href="https://bugzilla.mozilla.org/show_bug.cgi?id=613502"
-    title="Map <article> like we do aria role article">
-     Mozilla Bug 613502
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=613502"
+     title="Map <article> like we do aria role article">
+    Bug 613502
   </a>
   <a target="_blank"
-    href="https://bugzilla.mozilla.org/show_bug.cgi?id=610650"
-    title="Change implementation of HTML5 landmark elements to conform">
-     Mozilla Bug 610650
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=610650"
+     title="Change implementation of HTML5 landmark elements to conform">
+    Bug 610650
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=614310"
+     title="Map section to pane (like role=region)">
+    Mozilla Bug 614310
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=734982"
+     title="Map ARIA role FORM">
+    Bug 734982
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <nav id="nav">a nav</nav>
   <header id="header">a header</header>
   <footer id="footer">a footer</footer>
   <aside id="aside">by the way I am an aside</aside>
+  <section id="section">a section</section>
 
   <article id="article">an article</article>
   <article id="main" role="main">a main area</article>
+  <article id="form" role="form">a form area</article>
 
 </body>
 </html>
--- a/accessible/tests/mochitest/role.js
+++ b/accessible/tests/mochitest/role.js
@@ -48,16 +48,17 @@ const ROLE_PAGETABLIST = nsIAccessibleRo
 const ROLE_PANE = nsIAccessibleRole.ROLE_PANE;
 const ROLE_PARAGRAPH = nsIAccessibleRole.ROLE_PARAGRAPH;
 const ROLE_PARENT_MENUITEM = nsIAccessibleRole.ROLE_PARENT_MENUITEM;
 const ROLE_PASSWORD_TEXT = nsIAccessibleRole.ROLE_PASSWORD_TEXT;
 const ROLE_PROGRESSBAR = nsIAccessibleRole.ROLE_PROGRESSBAR;
 const ROLE_PROPERTYPAGE = nsIAccessibleRole.ROLE_PROPERTYPAGE;
 const ROLE_PUSHBUTTON = nsIAccessibleRole.ROLE_PUSHBUTTON;
 const ROLE_RADIOBUTTON = nsIAccessibleRole.ROLE_RADIOBUTTON;
+const ROLE_RICH_OPTION = nsIAccessibleRole.ROLE_RICH_OPTION;
 const ROLE_ROW = nsIAccessibleRole.ROLE_ROW;
 const ROLE_ROWHEADER = nsIAccessibleRole.ROLE_ROWHEADER;
 const ROLE_SCROLLBAR = nsIAccessibleRole.ROLE_SCROLLBAR;
 const ROLE_SECTION = nsIAccessibleRole.ROLE_SECTION;
 const ROLE_SEPARATOR = nsIAccessibleRole.ROLE_SEPARATOR;
 const ROLE_SLIDER = nsIAccessibleRole.ROLE_SLIDER;
 const ROLE_STATICTEXT = nsIAccessibleRole.ROLE_STATICTEXT;
 const ROLE_TABLE = nsIAccessibleRole.ROLE_TABLE;
--- a/accessible/tests/mochitest/test_aria_roles.html
+++ b/accessible/tests/mochitest/test_aria_roles.html
@@ -30,16 +30,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       testRole("log_table", ROLE_TABLE);
       testRole("timer_div", ROLE_SECTION);
 
       // other roles that are forms of "live regions"
       testRole("marquee_h1", ROLE_ANIMATION);
 
       // strong landmark
       testRole("application", ROLE_APPLICATION);
+      testRole("form", ROLE_FORM);
 
       // weak landmarks
       var weak_landmarks = ["banner", "complementary", "contentinfo",
           "main", "navigation", "search"];
       for (l in weak_landmarks)
         testRole(weak_landmarks[l], ROLE_SECTION);
 
       for (l in weak_landmarks) {
@@ -88,31 +89,38 @@ https://bugzilla.mozilla.org/show_bug.cg
 </head>
 <body>
 
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481114">Mozilla Bug 481114</a>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469688">Mozilla Bug 469688</a>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=469688">Mozilla Bug 520188</a>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289">Mozilla Bug 529289</a>
   <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529289">Mozilla Bug 607219</a>
+  <a target="_blank"
+     title="Map ARIA role FORM"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=735645">
+    Bug 735645
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   
   <!-- "live" roles -->
   <table role="log" id="log_table">
     <tr><td>Table based log</td></tr>
   </table>
   <h1 role="marquee" id="marquee_h1">marquee</h1>
   <div role="timer" id="timer_div">timer</div>
 
   <!-- landmarks -->
   <div role="application" id="application">application</div>
+  <div role="form" id="form">form</div>
+
+  <!-- weak landmarks -->
   <div role="banner" id="banner">banner</div>
   <div role="complementary" id="complementary">complementary</div>
   <div role="contentinfo" id="contentinfo">contentinfo</div>
   <div role="main" id="main">main</div>
   <div role="navigation" id="navigation">navigation</div>
   <div role="search" id="search">search</div>
 
   <!-- landmarks are tables -->
--- a/accessible/tests/mochitest/treeupdate/Makefile.in
+++ b/accessible/tests/mochitest/treeupdate/Makefile.in
@@ -52,16 +52,17 @@ include $(topsrcdir)/config/rules.mk
 		test_cssoverflow.html \
 		test_contextmenu.xul \
 		test_doc.html \
 		test_gencontent.html \
 		test_hidden.html \
 		test_imagemap.html \
 		test_list_editabledoc.html \
 		test_list.html \
+		test_listbox.xul \
 		test_menu.xul \
 		test_menubutton.xul \
 		test_recreation.html \
 		test_select.html \
 		test_textleaf.html \
 		test_visibility.html \
 		test_whitespace.html \
 		$(NULL)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/treeupdate/test_listbox.xul
@@ -0,0 +1,180 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+        title="Accessible XUL listbox hierarchy tests">
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
+
+  <script type="application/javascript"
+          src="../common.js" />
+  <script type="application/javascript"
+          src="../role.js" />
+  <script type="application/javascript"
+          src="../events.js" />
+
+  <script type="application/javascript">
+  <![CDATA[
+    ////////////////////////////////////////////////////////////////////////////
+    // Test
+
+    function insertListitem(aListboxID)
+    {
+      this.listboxNode = getNode(aListboxID);
+
+      this.listitemNode = document.createElement("listitem");
+      this.listitemNode.setAttribute("label", "item1");
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_SHOW, this.listitemNode),
+        new invokerChecker(EVENT_REORDER, this.listboxNode)
+      ];
+
+      this.invoke = function insertListitem_invoke()
+      {
+        this.listboxNode.insertBefore(this.listitemNode,
+                                      this.listboxNode.firstChild);
+      }
+
+      this.finalCheck = function insertListitem_finalCheck()
+      {
+        var tree =
+          { LISTBOX: [
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item1"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item2"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item3"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item4"
+            }
+          ] };
+        testAccessibleTree(this.listboxNode, tree);
+      }
+
+      this.getID = function insertListitem_getID()
+      {
+        return "insert listitem ";
+      }
+    }
+
+    function removeListitem(aListboxID)
+    {
+      this.listboxNode = getNode(aListboxID);
+      this.listitemNode = null;
+      this.listitem;
+
+      function getListitem(aThisObj)
+      {
+        return aThisObj.listitem;
+      }
+
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, getListitem, this),
+        new invokerChecker(EVENT_REORDER, this.listboxNode)
+      ];
+
+      this.invoke = function removeListitem_invoke()
+      {
+        this.listitemNode = this.listboxNode.firstChild;
+        this.listitem = getAccessible(this.listitemNode);
+
+        this.listboxNode.removeChild(this.listitemNode);
+      }
+
+      this.finalCheck = function removeListitem_finalCheck()
+      {
+        var tree =
+          { LISTBOX: [
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item2"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item3"
+            },
+            {
+              role: ROLE_RICH_OPTION,
+              name: "item4"
+            }
+          ] };
+        testAccessibleTree(this.listboxNode, tree);
+      }
+
+      this.getID = function removeListitem_getID()
+      {
+        return "remove listitem ";
+      }
+    }
+
+    //gA11yEventDumpToConsole = true; // debug stuff
+
+    var gQueue = null;
+    function doTest()
+    {
+      var tree =
+        { LISTBOX: [
+          {
+            role: ROLE_RICH_OPTION,
+            name: "item2"
+          },
+          {
+            role: ROLE_RICH_OPTION,
+            name: "item3"
+          },
+          {
+            role: ROLE_RICH_OPTION,
+            name: "item4"
+          }
+        ] };
+      testAccessibleTree("listbox", tree);
+
+      gQueue = new eventQueue();
+      gQueue.push(new insertListitem("listbox"));
+      gQueue.push(new removeListitem("listbox"));
+      gQueue.invoke(); // Will call SimpleTest.finish()
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  ]]>
+  </script>
+
+  <hbox flex="1" style="overflow: auto;">
+    <body xmlns="http://www.w3.org/1999/xhtml">
+      <a target="_blank"
+         href="https://bugzilla.mozilla.org/show_bug.cgi?id=656225"
+         title="XUL listbox accessible tree doesn't get updated">
+        Mozilla Bug 656225
+      </a>
+      <br/>
+      <p id="display"></p>
+      <div id="content" style="display: none">
+      </div>
+      <pre id="test">
+      </pre>
+    </body>
+
+    <vbox flex="1">
+      <listbox id="listbox" rows="2">
+        <listitem label="item2"/>
+        <listitem label="item3"/>
+        <listitem label="item4"/>
+      </listbox>
+    </vbox>
+  </hbox>
+
+</window>
+
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -433,16 +433,19 @@ pref("dom.mozBrowserFramesWhitelist", "h
 // Temporary permission hack for WebSMS
 pref("dom.sms.enabled", true);
 pref("dom.sms.whitelist", "file://,http://homescreen.gaiamobile.org,http://sms.gaiamobile.org");
 
 // Temporary permission hack for WebContacts
 pref("dom.mozContacts.enabled", true);
 pref("dom.mozContacts.whitelist", "http://dialer.gaiamobile.org,http://sms.gaiamobile.org");
 
+// WebSettings
+pref("dom.mozSettings.enabled", true);
+
 // Ignore X-Frame-Options headers.
 pref("b2g.ignoreXFrameOptions", true);
 
 // controls if we want camera support
 pref("device.camera.enabled", true);
 pref("media.realtime_decoder.enabled", true);
 
 // "Preview" landing of bug 710563, which is bogged down in analysis
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -41,16 +41,17 @@ XPCOMUtils.defineLazyServiceGetter(Servi
 
 // FIXME Bug 707625
 // until we have a proper security model, add some rights to
 // the pre-installed web applications
 // XXX never grant 'content-camera' to non-gaia apps
 function addPermissions(urls) {
   let permissions = [
     'indexedDB', 'indexedDB-unlimited', 'webapps-manage', 'offline-app',
+    'websettings-read', 'websettings-readwrite',
     'content-camera', 'webcontacts-manage', 'wifi-manage', 'desktop-notification',
     'geolocation'
   ];
   urls.forEach(function(url) {
     url = url.trim();
     dump("XxXxX adding permissions for " + url);
     let uri = Services.io.newURI(url, null, null);
     let allow = Ci.nsIPermissionManager.ALLOW_ACTION;
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -64,8 +64,9 @@ if test "$LIBXUL_SDK"; then
 MOZ_XULRUNNER=1
 else
 MOZ_XULRUNNER=
 MOZ_PLACES=1
 fi
 
 MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 MOZ_EXTENSION_MANAGER=1
+ENABLE_MARIONETTE=1
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -164,16 +164,17 @@
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
 @BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
+@BINPATH@/components/dom_settings.xpt
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_sms.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_threads.xpt
 @BINPATH@/components/dom_traversal.xpt
 @BINPATH@/components/dom_views.xpt
 @BINPATH@/components/dom_xbl.xpt
@@ -396,16 +397,18 @@
 @BINPATH@/components/nsFormHistory.js
 @BINPATH@/components/nsInputListAutoComplete.js
 @BINPATH@/components/contentSecurityPolicy.manifest
 @BINPATH@/components/contentSecurityPolicy.js
 @BINPATH@/components/contentAreaDropListener.manifest
 @BINPATH@/components/contentAreaDropListener.js
 @BINPATH@/components/messageWakeupService.js
 @BINPATH@/components/messageWakeupService.manifest
+@BINPATH@/components/SettingsManager.js
+@BINPATH@/components/SettingsManager.manifest
 @BINPATH@/components/nsFilePicker.js
 @BINPATH@/components/nsFilePicker.manifest
 #ifdef MOZ_B2G_RIL
 @BINPATH@/components/RadioInterfaceLayer.manifest
 @BINPATH@/components/RadioInterfaceLayer.js
 @BINPATH@/components/SmsDatabaseService.manifest
 @BINPATH@/components/SmsDatabaseService.js
 @BINPATH@/components/WifiWorker.js
--- a/browser/Makefile.in
+++ b/browser/Makefile.in
@@ -51,23 +51,24 @@ PARALLEL_DIRS = \
   themes \
   $(NULL)
 
 DIRS = \
   devtools \
   app \
   $(NULL)
 
-ifeq ($(OS_ARCH),WINNT)
+ifdef MAKENSISU
 DIRS += installer/windows
 endif
 
 include $(topsrcdir)/config/rules.mk
 
-ifeq ($(OS_ARCH),WINNT)
+ifdef MAKENSISU
+
 # For Windows build the uninstaller during the application build since the
 # uninstaller is included with the application for mar file generation.
 libs::
 	$(MAKE) -C installer/windows uninstaller
 ifdef MOZ_MAINTENANCE_SERVICE
 	$(MAKE) -C installer/windows maintenanceservice_installer
 endif
 endif
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -200,17 +200,17 @@ int main(int argc, char* argv[])
 
   nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
   if (NS_FAILED(rv)) {
     Output("Couldn't calculate the application directory.\n");
     return 255;
   }
 
   char *lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]);
-  if (!lastSlash || (lastSlash - exePath > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
+  if (!lastSlash || (size_t(lastSlash - exePath) > MAXPATHLEN - sizeof(XPCOM_DLL) - 1))
     return 255;
 
   strcpy(++lastSlash, XPCOM_DLL);
 
   int gotCounters;
 #if defined(XP_UNIX)
   struct rusage initialRUsage;
   gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -4079,17 +4079,17 @@ var FullScreen = {
       if (fullScrToggler) {
         fullScrToggler.removeEventListener("mouseover", this._expandCallback, false);
         fullScrToggler.removeEventListener("dragenter", this._expandCallback, false);
       }
       this.cancelWarning();
       gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
       gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
       gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
-      if (this.useLionFullScreen) {
+      if (!this.useLionFullScreen) {
         window.removeEventListener("deactivate", this);
       }
     }
   },
 
   observe: function(aSubject, aTopic, aData)
   {
     if (aData == "browser.fullscreen.autohide") {
@@ -4408,32 +4408,29 @@ var FullScreen = {
       gNavToolbox.setAttribute("inFullscreen", true);
       document.documentElement.setAttribute("inFullscreen", true);
     }
 
     // In tabs-on-top mode, move window controls to the tab bar,
     // and in tabs-on-bottom mode, move them back to the navigation toolbar.
     // When there is a chance the tab bar may be collapsed, put window
     // controls on nav bar.
-    var fullscreenflex = document.getElementById("fullscreenflex");
     var fullscreenctls = document.getElementById("window-controls");
     var navbar = document.getElementById("nav-bar");
     var ctlsOnTabbar = window.toolbar.visible &&
                        (navbar.collapsed ||
                           (TabsOnTop.enabled &&
                            !gPrefService.getBoolPref("browser.tabs.autoHide")));
     if (fullscreenctls.parentNode == navbar && ctlsOnTabbar) {
+      fullscreenctls.removeAttribute("flex");
       document.getElementById("TabsToolbar").appendChild(fullscreenctls);
-      // we don't need this space in tabs-on-top mode, so prevent it from 
-      // being shown
-      fullscreenflex.removeAttribute("fullscreencontrol");
     }
     else if (fullscreenctls.parentNode.id == "TabsToolbar" && !ctlsOnTabbar) {
+      fullscreenctls.setAttribute("flex", "1");
       navbar.appendChild(fullscreenctls);
-      fullscreenflex.setAttribute("fullscreencontrol", "true");
     }
 
     var controls = document.getElementsByAttribute("fullscreencontrol", "true");
     for (var i = 0; i < controls.length; ++i)
       controls[i].hidden = aShow;
   }
 };
 XPCOMUtils.defineLazyGetter(FullScreen, "useLionFullScreen", function() {
@@ -8661,16 +8658,41 @@ let gPrivateBrowsingUI = {
         return;
 
     this._privateBrowsingService.privateBrowsingEnabled =
       !this.privateBrowsingEnabled;
   },
 
   get privateBrowsingEnabled() {
     return this._privateBrowsingService.privateBrowsingEnabled;
+  },
+
+  /**
+   * These accessors are used to support per-window Private Browsing mode.
+   * For now the getter returns nsIPrivateBrowsingService.privateBrowsingEnabled,
+   * and the setter should only be used in tests.
+   */
+  get privateWindow() {
+    return window.getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsIDocShellTreeItem)
+                 .treeOwner
+                 .QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIXULWindow)
+                 .docShell.QueryInterface(Ci.nsILoadContext)
+                 .usePrivateBrowsing;
+  },
+
+  set privateWindow(val) {
+    return window.getInterface(Ci.nsIWebNavigation)
+                 .QueryInterface(Ci.nsIDocShellTreeItem)
+                 .treeOwner
+                 .QueryInterface(Ci.nsIInterfaceRequestor)
+                 .getInterface(Ci.nsIXULWindow)
+                 .docShell.QueryInterface(Ci.nsILoadContext)
+                 .usePrivateBrowsing = val;
   }
 };
 
 var LightWeightThemeWebInstaller = {
   handleEvent: function (event) {
     switch (event.type) {
       case "InstallBrowserTheme":
       case "PreviewBrowserTheme":
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -470,17 +470,17 @@
       <hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000"/>
 #endif
     </toolbar>
 
     <toolbar id="nav-bar" class="toolbar-primary chromeclass-toolbar"
              toolbarname="&navbarCmd.label;" accesskey="&navbarCmd.accesskey;"
              fullscreentoolbar="true" mode="icons" customizable="true"
              iconsize="large"
-             defaultset="unified-back-forward-button,urlbar-container,reload-button,stop-button,search-container,home-button,bookmarks-menu-button-container,fullscreenflex,window-controls"
+             defaultset="unified-back-forward-button,urlbar-container,reload-button,stop-button,search-container,home-button,bookmarks-menu-button-container,window-controls"
              context="toolbar-context-menu">
 
       <toolbaritem id="unified-back-forward-button" class="chromeclass-toolbar-additional"
                    context="backForwardMenu" removable="true"
                    forwarddisabled="true"
                    title="&backForwardItem.title;">
         <toolbarbutton id="back-button" class="toolbarbutton-1"
                        label="&backCmd.label;"
@@ -692,18 +692,17 @@
             <menuitem id="BMB_unsortedBookmarks"
                       label="&bookmarksMenuButton.unsorted.label;"
                       oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"
                       class="menuitem-iconic"/>
           </menupopup>
         </toolbarbutton>
       </toolbaritem>
 
-      <hbox id="fullscreenflex" flex="1" hidden="true" fullscreencontrol="true"/>
-      <hbox id="window-controls" hidden="true" fullscreencontrol="true">
+      <hbox id="window-controls" hidden="true" fullscreencontrol="true" pack="end">
         <toolbarbutton id="minimize-button"
                        tooltiptext="&fullScreenMinimize.tooltip;"
                        oncommand="window.minimize();"/>
 
         <toolbarbutton id="restore-button"
                        tooltiptext="&fullScreenRestore.tooltip;"
                        oncommand="BrowserFullScreen();"/>
 
--- a/browser/base/content/newtab/drop.js
+++ b/browser/base/content/newtab/drop.js
@@ -39,31 +39,30 @@ let gDrop = {
       this._rearrange();
     }
   },
 
   /**
    * Handles the 'drop' event.
    * @param aCell The drop target cell.
    * @param aEvent The 'dragexit' event.
-   * @param aCallback The callback to call when the drop is finished.
    */
-  drop: function Drop_drop(aCell, aEvent, aCallback) {
+  drop: function Drop_drop(aCell, aEvent) {
     // The cell that is the drop target could contain a pinned site. We need
     // to find out where that site has gone and re-pin it there.
     if (aCell.containsPinnedSite())
       this._repinSitesAfterDrop(aCell);
 
     // Pin the dragged or insert the new site.
     this._pinDraggedSite(aCell, aEvent);
 
     this._cancelDelayedArrange();
 
     // Update the grid and move all sites to their new places.
-    gUpdater.updateGrid(aCallback);
+    gUpdater.updateGrid();
   },
 
   /**
    * Re-pins all pinned sites in their (new) positions.
    * @param aCell The drop target cell.
    */
   _repinSitesAfterDrop: function Drop_repinSitesAfterDrop(aCell) {
     let sites = gDropPreview.rearrange(aCell);
--- a/browser/base/content/newtab/sites.js
+++ b/browser/base/content/newtab/sites.js
@@ -56,46 +56,44 @@ Site.prototype = {
       aIndex = this.cell.index;
 
     this._updateAttributes(true);
     gPinnedLinks.pin(this._link, aIndex);
   },
 
   /**
    * Unpins the site and calls the given callback when done.
-   * @param aCallback The callback to be called when finished.
    */
-  unpin: function Site_unpin(aCallback) {
+  unpin: function Site_unpin() {
     if (this.isPinned()) {
       this._updateAttributes(false);
       gPinnedLinks.unpin(this._link);
-      gUpdater.updateGrid(aCallback);
+      gUpdater.updateGrid();
     }
   },
 
   /**
    * Checks whether this site is pinned.
    * @return Whether this site is pinned.
    */
   isPinned: function Site_isPinned() {
     return gPinnedLinks.isPinned(this._link);
   },
 
   /**
    * Blocks the site (removes it from the grid) and calls the given callback
    * when done.
-   * @param aCallback The function to be called when finished.
    */
-  block: function Site_block(aCallback) {
+  block: function Site_block() {
     if (gBlockedLinks.isBlocked(this._link)) {
       if (aCallback)
         aCallback();
     } else {
       gBlockedLinks.block(this._link);
-      gUpdater.updateGrid(aCallback);
+      gUpdater.updateGrid();
     }
   },
 
   /**
    * Gets the DOM node specified by the given query selector.
    * @param aSelector The query selector.
    * @return The DOM node we found.
    */
--- a/browser/base/content/test/newtab/browser_newtab_block.js
+++ b/browser/base/content/test/newtab/browser_newtab_block.js
@@ -10,52 +10,52 @@ function runTests() {
   // we remove sites and expect the gaps to be filled as long as there still
   // are some sites available
   setLinks("0,1,2,3,4,5,6,7,8,9");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7,8");
 
-  yield blockCell(cells[4]);
+  yield blockCell(4);
   checkGrid("0,1,2,3,5,6,7,8,9");
 
-  yield blockCell(cells[4]);
+  yield blockCell(4);
   checkGrid("0,1,2,3,6,7,8,9,");
 
-  yield blockCell(cells[4]);
+  yield blockCell(4);
   checkGrid("0,1,2,3,7,8,9,,");
 
   // we removed a pinned site
   yield restore();
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks(",1");
 
   yield addNewTabPageTab();
   checkGrid("0,1p,2,3,4,5,6,7,8");
 
-  yield blockCell(cells[1]);
+  yield blockCell(1);
   checkGrid("0,2,3,4,5,6,7,8,");
 
   // we remove the last site on the grid (which is pinned) and expect the gap
   // to be re-filled and the new site to be unpinned
   yield restore();
   setLinks("0,1,2,3,4,5,6,7,8,9");
   setPinnedLinks(",,,,,,,,8");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7,8p");
 
-  yield blockCell(cells[8]);
+  yield blockCell(8);
   checkGrid("0,1,2,3,4,5,6,7,9");
 
   // we remove the first site on the grid with the last one pinned. all cells
   // but the last one should shift to the left and a new site fades in
   yield restore();
   setLinks("0,1,2,3,4,5,6,7,8,9");
   setPinnedLinks(",,,,,,,,8");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7,8p");
 
-  yield blockCell(cells[0]);
+  yield blockCell(0);
   checkGrid("1,2,3,4,5,6,7,9,8p");
 }
--- a/browser/base/content/test/newtab/browser_newtab_bug722273.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug722273.js
@@ -15,31 +15,22 @@ let {NewTabUtils, Sanitizer} = tmp;
 let bhist = Cc["@mozilla.org/browser/global-history;2"]
   .getService(Ci.nsIBrowserHistory);
 
 function runTests() {
   clearHistory();
   fillHistory();
   yield addNewTabPageTab();
 
-  is(cells[0].site.url, URL, "first site is our fake site");
+  is(getCell(0).site.url, URL, "first site is our fake site");
 
-  let page = {
-    update: function () {
-      executeSoon(TestRunner.next);
-    },
-
-    observe: function () {}
-  };
-
-  NewTabUtils.allPages.register(page);
+  whenPagesUpdated();
   yield clearHistory();
 
-  NewTabUtils.allPages.unregister(page);
-  ok(!cells[0].site, "the fake site is gone");
+  ok(!getCell(0).site, "the fake site is gone");
 }
 
 function fillHistory() {
   let uri = makeURI(URL);
   for (let i = 59; i > 0; i--)
     bhist.addPageWithDetails(uri, "fake site", NOW - i * 60 * 1000000);
 }
 
--- a/browser/base/content/test/newtab/browser_newtab_bug723102.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug723102.js
@@ -9,10 +9,10 @@ function runTests() {
   yield addNewTabPageTab();
   let firstTab = gBrowser.selectedTab;
 
   yield addNewTabPageTab();
   gBrowser.removeTab(firstTab);
 
   ok(NewTabUtils.allPages.enabled, true, "page is enabled");
   NewTabUtils.allPages.enabled = false;
-  ok(cw.gGrid.node.hasAttribute("page-disabled"), "page is disabled");
+  ok(getGrid().node.hasAttribute("page-disabled"), "page is disabled");
 }
--- a/browser/base/content/test/newtab/browser_newtab_bug723121.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug723121.js
@@ -3,46 +3,28 @@
 
 function runTests() {
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
   checkGridLocked(false, "grid is unlocked");
 
-  let cell = cells[0].node;
-  let site = cells[0].site.node;
+  let cell = getCell(0).node;
+  let site = getCell(0).site.node;
   let link = site.querySelector(".newtab-link");
 
-  sendDragEvent(link, "dragstart");
+  sendDragEvent("dragstart", link);
   checkGridLocked(true, "grid is now locked");
 
-  sendDragEvent(link, "dragend");
+  sendDragEvent("dragend", link);
   checkGridLocked(false, "grid isn't locked anymore");
 
-  sendDragEvent(cell, "dragstart");
+  sendDragEvent("dragstart", cell);
   checkGridLocked(false, "grid isn't locked - dragstart was ignored");
 
-  sendDragEvent(site, "dragstart");
+  sendDragEvent("dragstart", site);
   checkGridLocked(false, "grid isn't locked - dragstart was ignored");
 }
 
 function checkGridLocked(aLocked, aMessage) {
-  is(cw.gGrid.node.hasAttribute("locked"), aLocked, aMessage);
+  is(getGrid().node.hasAttribute("locked"), aLocked, aMessage);
 }
-
-function sendDragEvent(aNode, aType) {
-  let ifaceReq = cw.QueryInterface(Ci.nsIInterfaceRequestor);
-  let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils);
-
-  let dataTransfer = {
-    mozUserCancelled: false,
-    setData: function () null,
-    setDragImage: function () null,
-    getData: function () "about:blank"
-  };
-
-  let event = cw.document.createEvent("DragEvents");
-  event.initDragEvent(aType, true, true, cw, 0, 0, 0, 0, 0,
-                      false, false, false, false, 0, null, dataTransfer);
-
-  windowUtils.dispatchDOMEventViaPresShell(aNode, event, true);
-}
--- a/browser/base/content/test/newtab/browser_newtab_bug725996.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug725996.js
@@ -3,50 +3,21 @@
 
 function runTests() {
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7,8");
 
-  let cell = cells[0].node;
+  let cell = getCell(0).node;
 
-  sendDropEvent(cell, "about:blank#99\nblank");
+  sendDragEvent("drop", cell, "about:blank#99\nblank");
   is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99",
      "first cell is pinned and contains the dropped site");
 
   yield whenPagesUpdated();
   checkGrid("99p,0,1,2,3,4,5,6,7");
 
-  sendDropEvent(cell, "");
+  sendDragEvent("drop", cell, "");
   is(NewTabUtils.pinnedLinks.links[0].url, "about:blank#99",
      "first cell is still pinned with the site we dropped before");
 }
-
-function sendDropEvent(aNode, aData) {
-  let ifaceReq = cw.QueryInterface(Ci.nsIInterfaceRequestor);
-  let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils);
-
-  let dataTransfer = {
-    mozUserCancelled: false,
-    setData: function () null,
-    setDragImage: function () null,
-    getData: function () aData,
-
-    types: {
-      contains: function (aType) aType == "text/x-moz-url"
-    },
-
-    mozGetDataAt: function (aType, aIndex) {
-      if (aIndex || aType != "text/x-moz-url")
-        return null;
-
-      return aData;
-    },
-  };
-
-  let event = cw.document.createEvent("DragEvents");
-  event.initDragEvent("drop", true, true, cw, 0, 0, 0, 0, 0,
-                      false, false, false, false, 0, null, dataTransfer);
-
-  windowUtils.dispatchDOMEventViaPresShell(aNode, event, true);
-}
--- a/browser/base/content/test/newtab/browser_newtab_bug734043.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug734043.js
@@ -4,22 +4,23 @@
 function runTests() {
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7,8");
 
   let receivedError = false;
-  let block = cw.document.querySelector(".newtab-control-block");
+  let block = getContentDocument().querySelector(".newtab-control-block");
 
   function onError() {
     receivedError = true;
   }
 
+  let cw = getContentWindow();
   cw.addEventListener("error", onError);
 
   for (let i = 0; i < 3; i++)
     EventUtils.synthesizeMouseAtCenter(block, {}, cw);
 
   yield whenPagesUpdated();
   ok(!receivedError, "we got here without any errors");
   cw.removeEventListener("error", onError);
--- a/browser/base/content/test/newtab/browser_newtab_bug735987.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug735987.js
@@ -3,20 +3,20 @@
 
 function runTests() {
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7,8");
 
-  yield simulateDrop(cells[1]);
+  yield simulateDrop(1);
   checkGrid("0,99p,1,2,3,4,5,6,7");
 
-  yield blockCell(cells[1]);
+  yield blockCell(1);
   checkGrid("0,1,2,3,4,5,6,7,8");
 
-  yield simulateDrop(cells[1]);
+  yield simulateDrop(1);
   checkGrid("0,99p,1,2,3,4,5,6,7");
 
-  yield blockCell(cells[1]);
+  yield blockCell(1);
   checkGrid("0,1,2,3,4,5,6,7,8");
 }
--- a/browser/base/content/test/newtab/browser_newtab_disable.js
+++ b/browser/base/content/test/newtab/browser_newtab_disable.js
@@ -6,29 +6,29 @@
  * decides not to use it.
  */
 function runTests() {
   // create a new tab page and hide it.
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
-  let gridNode = cw.gGrid.node;
+  let gridNode = getGrid().node;
 
   ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled");
 
   NewTabUtils.allPages.enabled = false;
   ok(gridNode.hasAttribute("page-disabled"), "page is disabled");
 
-  let oldGridNode = cw.gGrid.node;
+  let oldGridNode = gridNode;
 
   // create a second new tage page and make sure it's disabled. enable it
   // again and check if the former page gets enabled as well.
   yield addNewTabPageTab();
   ok(gridNode.hasAttribute("page-disabled"), "page is disabled");
 
   // check that no sites have been rendered
-  is(0, cw.document.querySelectorAll(".site").length, "no sites have been rendered");
+  is(0, getContentDocument().querySelectorAll(".site").length, "no sites have been rendered");
 
   NewTabUtils.allPages.enabled = true;
   ok(!gridNode.hasAttribute("page-disabled"), "page is not disabled");
   ok(!oldGridNode.hasAttribute("page-disabled"), "old page is not disabled");
 }
--- a/browser/base/content/test/newtab/browser_newtab_drag_drop.js
+++ b/browser/base/content/test/newtab/browser_newtab_drag_drop.js
@@ -10,106 +10,106 @@
 function runTests() {
   // test a simple drag-and-drop scenario
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7,8");
 
-  yield simulateDrop(cells[1], cells[0]);
+  yield simulateDrop(1, 0);
   checkGrid("1,0p,2,3,4,5,6,7,8");
 
   // drag a cell to its current cell and make sure it's not pinned afterwards
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7,8");
 
-  yield simulateDrop(cells[0], cells[0]);
+  yield simulateDrop(0, 0);
   checkGrid("0,1,2,3,4,5,6,7,8");
 
   // ensure that pinned pages aren't moved if that's not necessary
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks(",1,2");
 
   yield addNewTabPageTab();
   checkGrid("0,1p,2p,3,4,5,6,7,8");
 
-  yield simulateDrop(cells[3], cells[0]);
+  yield simulateDrop(3, 0);
   checkGrid("3,1p,2p,0p,4,5,6,7,8");
 
   // pinned sites should always be moved around as blocks. if a pinned site is
   // moved around, neighboring pinned are affected as well
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("0,1");
 
   yield addNewTabPageTab();
   checkGrid("0p,1p,2,3,4,5,6,7,8");
 
-  yield simulateDrop(cells[0], cells[2]);
+  yield simulateDrop(0, 2);
   checkGrid("2p,0p,1p,3,4,5,6,7,8");
 
   // pinned sites should not be pushed out of the grid (unless there are only
   // pinned ones left on the grid)
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks(",,,,,,,7,8");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7p,8p");
 
-  yield simulateDrop(cells[8], cells[2]);
+  yield simulateDrop(8, 2);
   checkGrid("0,1,3,4,5,6,7p,8p,2p");
 
   // make sure that pinned sites are re-positioned correctly
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("0,1,2,,,5");
 
   yield addNewTabPageTab();
   checkGrid("0p,1p,2p,3,4,5p,6,7,8");
 
-  yield simulateDrop(cells[4], cells[0]);
+  yield simulateDrop(4, 0);
   checkGrid("3,1p,2p,4,0p,5p,6,7,8");
 
   // drag a new site onto the very first cell
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks(",,,,,,,7,8");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7p,8p");
 
-  yield simulateDrop(cells[0]);
+  yield simulateDrop(0);
   checkGrid("99p,0,1,2,3,4,5,7p,8p");
 
   // drag a new site onto the grid and make sure that pinned cells don't get
   // pushed out
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks(",,,,,,,7,8");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7p,8p");
 
-  yield simulateDrop(cells[7]);
+  yield simulateDrop(7);
   checkGrid("0,1,2,3,4,5,7p,99p,8p");
 
   // drag a new site beneath a pinned cell and make sure the pinned cell is
   // not moved
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks(",,,,,,,,8");
 
   yield addNewTabPageTab();
   checkGrid("0,1,2,3,4,5,6,7,8p");
 
-  yield simulateDrop(cells[7]);
+  yield simulateDrop(7);
   checkGrid("0,1,2,3,4,5,6,99p,8p");
 
   // drag a new site onto a block of pinned sites and make sure they're shifted
   // around accordingly
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("0,1,2,,,,,,");
 
   yield addNewTabPageTab();
   checkGrid("0p,1p,2p");
 
-  yield simulateDrop(cells[1]);
+  yield simulateDrop(1);
   checkGrid("0p,99p,1p,2p,3,4,5,6,7");
 }
--- a/browser/base/content/test/newtab/browser_newtab_drop_preview.js
+++ b/browser/base/content/test/newtab/browser_newtab_drop_preview.js
@@ -8,14 +8,15 @@
 function runTests() {
   // the first three sites are pinned - make sure they're re-arranged correctly
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("0,1,2,,,5");
 
   yield addNewTabPageTab();
   checkGrid("0p,1p,2p,3,4,5p,6,7,8");
 
-  cw.gDrag._draggedSite = cells[0].site;
-  let sites = cw.gDropPreview.rearrange(cells[4]);
+  let cw = getContentWindow();
+  cw.gDrag._draggedSite = getCell(0).site;
+  let sites = cw.gDropPreview.rearrange(getCell(4));
   cw.gDrag._draggedSite = null;
 
   checkGrid("3,1p,2p,4,0p,5p,6,7,8", sites);
 }
--- a/browser/base/content/test/newtab/browser_newtab_private_browsing.js
+++ b/browser/base/content/test/newtab/browser_newtab_private_browsing.js
@@ -11,31 +11,31 @@ let pb = Cc["@mozilla.org/privatebrowsin
          .getService(Ci.nsIPrivateBrowsingService);
 
 function runTests() {
   // prepare the grid
   setLinks("0,1,2,3,4,5,6,7,8,9");
   ok(!pb.privateBrowsingEnabled, "private browsing is disabled");
 
   yield addNewTabPageTab();
-  pinCell(cells[0]);
+  pinCell(0);
   checkGrid("0p,1,2,3,4,5,6,7,8");
 
   // enter private browsing mode
   yield togglePrivateBrowsing();
   ok(pb.privateBrowsingEnabled, "private browsing is enabled");
 
   yield addNewTabPageTab();
   checkGrid("0p,1,2,3,4,5,6,7,8");
 
   // modify the grid while we're in pb mode
-  yield blockCell(cells[1]);
+  yield blockCell(1);
   checkGrid("0p,2,3,4,5,6,7,8");
 
-  yield unpinCell(cells[0]);
+  yield unpinCell(0);
   checkGrid("0,2,3,4,5,6,7,8");
 
   // exit private browsing mode
   yield togglePrivateBrowsing();
   ok(!pb.privateBrowsingEnabled, "private browsing is disabled");
 
   // check that the grid is the same as before entering pb mode
   yield addNewTabPageTab();
--- a/browser/base/content/test/newtab/browser_newtab_reset.js
+++ b/browser/base/content/test/newtab/browser_newtab_reset.js
@@ -8,21 +8,21 @@ function runTests() {
   // Disabled until bug 716543 is fixed.
   return;
 
   // create a new tab page and check its modified state after blocking a site
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield addNewTabPageTab();
-  let resetButton = cw.document.getElementById("toolbar-button-reset");
+  let resetButton = getContentDocument().getElementById("toolbar-button-reset");
 
   checkGrid("0,1,2,3,4,5,6,7,8");
   ok(!resetButton.hasAttribute("modified"), "page is not modified");
 
-  yield blockCell(cells[4]);
+  yield blockCell(4);
   checkGrid("0,1,2,3,5,6,7,8,");
   ok(resetButton.hasAttribute("modified"), "page is modified");
 
-  yield cw.gToolbar.reset(TestRunner.next);
+  yield getContentWindow().gToolbar.reset(TestRunner.next);
   checkGrid("0,1,2,3,4,5,6,7,8");
   ok(!resetButton.hasAttribute("modified"), "page is not modified");
 }
--- a/browser/base/content/test/newtab/browser_newtab_tabsync.js
+++ b/browser/base/content/test/newtab/browser_newtab_tabsync.js
@@ -12,50 +12,50 @@ function runTests() {
   return;
 
   setLinks("0,1,2,3,4,5,6,7,8,9");
   setPinnedLinks(",1");
 
   yield addNewTabPageTab();
   checkGrid("0,1p,2,3,4,5,6,7,8");
 
-  let resetButton = cw.document.getElementById("toolbar-button-reset");
+  let resetButton = getContentDocument().getElementById("toolbar-button-reset");
   ok(!resetButton.hasAttribute("modified"), "page is not modified");
 
-  let oldCw = cw;
+  let oldSites = getGrid().sites;
   let oldResetButton = resetButton;
 
   // create the new tab page
   yield addNewTabPageTab();
   checkGrid("0,1p,2,3,4,5,6,7,8");
 
-  resetButton = cw.document.getElementById("toolbar-button-reset");
+  resetButton = getContentDocument().getElementById("toolbar-button-reset");
   ok(!resetButton.hasAttribute("modified"), "page is not modified");
 
   // unpin a cell
-  yield unpinCell(cells[1]);
+  yield unpinCell(1);
   checkGrid("0,1,2,3,4,5,6,7,8");
-  checkGrid("0,1,2,3,4,5,6,7,8", oldCw.gGrid.sites);
+  checkGrid("0,1,2,3,4,5,6,7,8", oldSites);
 
   // remove a cell
-  yield blockCell(cells[1]);
+  yield blockCell(1);
   checkGrid("0,2,3,4,5,6,7,8,9");
-  checkGrid("0,2,3,4,5,6,7,8,9", oldCw.gGrid.sites);
+  checkGrid("0,2,3,4,5,6,7,8,9", oldSites);
   ok(resetButton.hasAttribute("modified"), "page is modified");
   ok(oldResetButton.hasAttribute("modified"), "page is modified");
 
   // insert a new cell by dragging
-  yield simulateDrop(cells[1]);
+  yield simulateDrop(1);
   checkGrid("0,99p,2,3,4,5,6,7,8");
-  checkGrid("0,99p,2,3,4,5,6,7,8", oldCw.gGrid.sites);
+  checkGrid("0,99p,2,3,4,5,6,7,8", oldSites);
 
   // drag a cell around
-  yield simulateDrop(cells[1], cells[2]);
+  yield simulateDrop(1, 2);
   checkGrid("0,2p,99p,3,4,5,6,7,8");
-  checkGrid("0,2p,99p,3,4,5,6,7,8", oldCw.gGrid.sites);
+  checkGrid("0,2p,99p,3,4,5,6,7,8", oldSites);
 
   // reset the new tab page
-  yield cw.gToolbar.reset(TestRunner.next);
+  yield getContentWindow().gToolbar.reset(TestRunner.next);
   checkGrid("0,1,2,3,4,5,6,7,8");
-  checkGrid("0,1,2,3,4,5,6,7,8", oldCw.gGrid.sites);
+  checkGrid("0,1,2,3,4,5,6,7,8", oldSites);
   ok(!resetButton.hasAttribute("modified"), "page is not modified");
   ok(!oldResetButton.hasAttribute("modified"), "page is not modified");
 }
--- a/browser/base/content/test/newtab/browser_newtab_unpin.js
+++ b/browser/base/content/test/newtab/browser_newtab_unpin.js
@@ -9,48 +9,48 @@ function runTests() {
   // we have a pinned link that didn't change its position since it was pinned.
   // nothing should happend when we unpin it.
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks(",1");
 
   yield addNewTabPageTab();
   checkGrid("0,1p,2,3,4,5,6,7,8");
 
-  yield unpinCell(cells[1]);
+  yield unpinCell(1);
   checkGrid("0,1,2,3,4,5,6,7,8");
 
   // we have a pinned link that is not anymore in the list of the most-visited
   // links. this should disappear, the remaining links adjust their positions
   // and a new link will appear at the end of the grid.
   setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks(",99");
 
   yield addNewTabPageTab();
   checkGrid("0,99p,1,2,3,4,5,6,7");
 
-  yield unpinCell(cells[1]);
+  yield unpinCell(1);
   checkGrid("0,1,2,3,4,5,6,7,8");
 
   // we have a pinned link that changed its position since it was pinned. it
   // should be moved to its new position after being unpinned.
   setLinks("0,1,2,3,4,5,6,7");
   setPinnedLinks(",1,,,,,,,0");
 
   yield addNewTabPageTab();
   checkGrid("2,1p,3,4,5,6,7,,0p");
 
-  yield unpinCell(cells[1]);
+  yield unpinCell(1);
   checkGrid("1,2,3,4,5,6,7,,0p");
 
-  yield unpinCell(cells[8]);
+  yield unpinCell(8);
   checkGrid("0,1,2,3,4,5,6,7,");
 
   // we have pinned link that changed its position since it was pinned. the
   // link will disappear from the grid because it's now a much lower priority
   setLinks("0,1,2,3,4,5,6,7,8,9");
   setPinnedLinks("9");
 
   yield addNewTabPageTab();
   checkGrid("9p,0,1,2,3,4,5,6,7");
 
-  yield unpinCell(cells[0]);
+  yield unpinCell(0);
   checkGrid("0,1,2,3,4,5,6,7,8");
 }
--- a/browser/base/content/test/newtab/head.js
+++ b/browser/base/content/test/newtab/head.js
@@ -12,22 +12,16 @@ let NewTabUtils = tmp.NewTabUtils;
 registerCleanupFunction(function () {
   while (gBrowser.tabs.length > 1)
     gBrowser.removeTab(gBrowser.tabs[1]);
 
   Services.prefs.clearUserPref(PREF_NEWTAB_ENABLED);
 });
 
 /**
- * Global variables that are accessed by tests.
- */
-let cw;
-let cells;
-
-/**
  * We'll want to restore the original links provider later.
  */
 let originalProvider = NewTabUtils.links._provider;
 
 /**
  * Provide the default test function to start our test runner.
  */
 function test() {
@@ -77,16 +71,49 @@ let TestRunner = {
     if (numCallbacks)
       callbacks.splice(0, numCallbacks, cleanupAndFinish);
     else
       cleanupAndFinish();
   }
 };
 
 /**
+ * Returns the selected tab's content window.
+ * @return The content window.
+ */
+function getContentWindow() {
+  return gBrowser.selectedBrowser.contentWindow;
+}
+
+/**
+ * Returns the selected tab's content document.
+ * @return The content document.
+ */
+function getContentDocument() {
+  return gBrowser.selectedBrowser.contentDocument;
+}
+
+/**
+ * Returns the newtab grid of the selected tab.
+ * @return The newtab grid.
+ */
+function getGrid() {
+  return getContentWindow().gGrid;
+}
+
+/**
+ * Returns the cell at the given index of the selected tab's newtab grid.
+ * @param aIndex The cell index.
+ * @return The newtab cell.
+ */
+function getCell(aIndex) {
+  return getGrid().cells[aIndex];
+}
+
+/**
  * Allows to provide a list of links that is used to construct the grid.
  * @param aLinksPattern the pattern (see below)
  *
  * Example: setLinks("1,2,3")
  * Result: [{url: "about:blank#1", title: "site#1"},
  *          {url: "about:blank#2", title: "site#2"}
  *          {url: "about:blank#3", title: "site#3"}]
  */
@@ -138,154 +165,150 @@ function restore() {
 function addNewTabPageTab() {
   let tab = gBrowser.selectedTab = gBrowser.addTab("about:newtab");
   let browser = tab.linkedBrowser;
 
   // Wait for the new tab page to be loaded.
   browser.addEventListener("load", function onLoad() {
     browser.removeEventListener("load", onLoad, true);
 
-    cw = browser.contentWindow;
-
     if (NewTabUtils.allPages.enabled) {
       // Continue when the link cache has been populated.
       NewTabUtils.links.populateCache(function () {
-        cells = cw.gGrid.cells;
         executeSoon(TestRunner.next);
       });
     } else {
       TestRunner.next();
     }
-
   }, true);
 }
 
 /**
  * Compares the current grid arrangement with the given pattern.
  * @param the pattern (see below)
  * @param the array of sites to compare with (optional)
  *
  * Example: checkGrid("3p,2,,1p")
  * Result: We expect the first cell to contain the pinned site 'about:blank#3'.
  *         The second cell contains 'about:blank#2'. The third cell is empty.
  *         The fourth cell contains the pinned site 'about:blank#4'.
  */
 function checkGrid(aSitesPattern, aSites) {
-  let valid = true;
-
-  aSites = aSites || cw.gGrid.sites;
-
-  aSitesPattern.split(/\s*,\s*/).forEach(function (id, index) {
-    let site = aSites[index];
-    let match = id.match(/^\d+/);
-
-    // We expect the cell to be empty.
-    if (!match) {
-      if (site) {
-        valid = false;
-        ok(false, "expected cell#" + index + " to be empty");
-      }
-
-      return;
-    }
-
-    // We expect the cell to contain a site.
-    if (!site) {
-      valid = false;
-      ok(false, "didn't expect cell#" + index + " to be empty");
-
-      return;
-    }
-
-    let num = match[0];
+  let length = aSitesPattern.split(",").length;
+  let sites = (aSites || getGrid().sites).slice(0, length);
+  let expected = sites.map(function (aSite) {
+    if (!aSite)
+      return "";
 
-    // Check the site's url.
-    if (site.url != "about:blank#" + num) {
-      valid = false;
-      is(site.url, "about:blank#" + num, "cell#" + index + " has the wrong url");
-    }
-
-    let shouldBePinned = /p$/.test(id);
-    let cellContainsPinned = site.isPinned();
-    let cssClassPinned = site.node && site.node.querySelector(".newtab-control-pin").hasAttribute("pinned");
+    let pinned = aSite.isPinned();
+    let pinButton = aSite.node.querySelector(".newtab-control-pin");
+    let hasPinnedAttr = pinButton.hasAttribute("pinned");
 
-    // Check if the site should be and is pinned.
-    if (shouldBePinned) {
-      if (!cellContainsPinned) {
-        valid = false;
-        ok(false, "expected cell#" + index + " to be pinned");
-      } else if (!cssClassPinned) {
-        valid = false;
-        ok(false, "expected cell#" + index + " to have css class 'pinned'");
-      }
-    } else {
-      if (cellContainsPinned) {
-        valid = false;
-        ok(false, "didn't expect cell#" + index + " to be pinned");
-      } else if (cssClassPinned) {
-        valid = false;
-        ok(false, "didn't expect cell#" + index + " to have css class 'pinned'");
-      }
-    }
+    if (pinned != hasPinnedAttr)
+      ok(false, "invalid state (site.isPinned() != site[pinned])");
+
+    return aSite.url.replace(/^about:blank#(\d+)$/, "$1") + (pinned ? "p" : "");
   });
 
-  // If every test passed, say so.
-  if (valid)
-    ok(true, "grid status = " + aSitesPattern);
+  is(aSitesPattern, expected, "grid status = " + aSitesPattern);
 }
 
 /**
- * Blocks the given cell's site from the grid.
- * @param aCell the cell that contains the site to block
+ * Blocks a site from the grid.
+ * @param aIndex The cell index.
  */
-function blockCell(aCell) {
-  aCell.site.block(function () executeSoon(TestRunner.next));
+function blockCell(aIndex) {
+  whenPagesUpdated();
+  getCell(aIndex).site.block();
 }
 
 /**
- * Pins a given cell's site on a given position.
- * @param aCell the cell that contains the site to pin
- * @param aIndex the index the defines where the site should be pinned
+ * Pins a site on a given position.
+ * @param aIndex The cell index.
+ * @param aPinIndex The index the defines where the site should be pinned.
  */
-function pinCell(aCell, aIndex) {
-  aCell.site.pin(aIndex);
+function pinCell(aIndex, aPinIndex) {
+  getCell(aIndex).site.pin(aPinIndex);
 }
 
 /**
  * Unpins the given cell's site.
- * @param aCell the cell that contains the site to unpin
+ * @param aIndex The cell index.
  */
-function unpinCell(aCell) {
-  aCell.site.unpin(function () executeSoon(TestRunner.next));
+function unpinCell(aIndex) {
+  whenPagesUpdated();
+  getCell(aIndex).site.unpin();
 }
 
 /**
  * Simulates a drop and drop operation.
- * @param aDropTarget the cell that is the drop target
- * @param aDragSource the cell that contains the dragged site (optional)
+ * @param aDropIndex The cell index of the drop target.
+ * @param aDragIndex The cell index containing the dragged site (optional).
+ */
+function simulateDrop(aDropIndex, aDragIndex) {
+  let draggedSite;
+  let {gDrag: drag, gDrop: drop} = getContentWindow();
+  let event = createDragEvent("drop", "about:blank#99\nblank");
+
+  if (typeof aDragIndex != "undefined")
+    draggedSite = getCell(aDragIndex).site;
+
+  if (draggedSite)
+    drag.start(draggedSite, event);
+
+  whenPagesUpdated();
+  drop.drop(getCell(aDropIndex), event);
+
+  if (draggedSite)
+    drag.end(draggedSite);
+}
+
+/**
+ * Sends a custom drag event to a given DOM element.
+ * @param aEventType The drag event's type.
+ * @param aTarget The DOM element that the event is dispatched to.
+ * @param aData The event's drag data (optional).
  */
-function simulateDrop(aDropTarget, aDragSource) {
-  let event = {
-    clientX: 0,
-    clientY: 0,
-    dataTransfer: {
-      mozUserCancelled: false,
-      setData: function () null,
-      setDragImage: function () null,
-      getData: function () "about:blank#99\nblank"
+function sendDragEvent(aEventType, aTarget, aData) {
+  let event = createDragEvent(aEventType, aData);
+  let ifaceReq = getContentWindow().QueryInterface(Ci.nsIInterfaceRequestor);
+  let windowUtils = ifaceReq.getInterface(Ci.nsIDOMWindowUtils);
+  windowUtils.dispatchDOMEventViaPresShell(aTarget, event, true);
+}
+
+/**
+ * Creates a custom drag event.
+ * @param aEventType The drag event's type.
+ * @param aData The event's drag data (optional).
+ * @return The drag event.
+ */
+function createDragEvent(aEventType, aData) {
+  let dataTransfer = {
+    mozUserCancelled: false,
+    setData: function () null,
+    setDragImage: function () null,
+    getData: function () aData,
+
+    types: {
+      contains: function (aType) aType == "text/x-moz-url"
+    },
+
+    mozGetDataAt: function (aType, aIndex) {
+      if (aIndex || aType != "text/x-moz-url")
+        return null;
+
+      return aData;
     }
   };
 
-  if (aDragSource)
-    cw.gDrag.start(aDragSource.site, event);
+  let event = getContentDocument().createEvent("DragEvents");
+  event.initDragEvent(aEventType, true, true, getContentWindow(), 0, 0, 0, 0, 0,
+                      false, false, false, false, 0, null, dataTransfer);
 
-  cw.gDrop.drop(aDropTarget, event, function () executeSoon(TestRunner.next));
-
-  if (aDragSource)
-    cw.gDrag.end(aDragSource.site);
+  return event;
 }
 
 /**
  * Resumes testing when all pages have been updated.
  */
 function whenPagesUpdated(aCallback) {
   let page = {
     update: function () {
--- a/browser/components/migration/src/nsBrowserProfileMigratorUtils.cpp
+++ b/browser/components/migration/src/nsBrowserProfileMigratorUtils.cpp
@@ -49,20 +49,16 @@
 #include "nsNetUtil.h"
 #include "nsISupportsPrimitives.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIRDFService.h"
 #include "nsIStringBundle.h"
 #include "nsXPCOMCID.h"
 
-#define MIGRATION_BUNDLE "chrome://browser/locale/migration/migration.properties"
-
-#define DEFAULT_BOOKMARKS NS_LITERAL_CSTRING("resource:///defaults/profile/bookmarks.html")
-
 void SetUnicharPref(const char* aPref, const nsAString& aValue,
                     nsIPrefBranch* aPrefs)
 {
   nsCOMPtr<nsISupportsString> supportsString =
     do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);    
   if (supportsString) {
      supportsString->SetData(aValue); 
      aPrefs->SetComplexValue(aPref, NS_GET_IID(nsISupportsString),
--- a/browser/components/nsBrowserContentHandler.js
+++ b/browser/components/nsBrowserContentHandler.js
@@ -742,20 +742,16 @@ nsDefaultCommandLineHandler.prototype = 
   QueryInterface : function dch_QI(iid) {
     if (!iid.equals(nsISupports) &&
         !iid.equals(nsICommandLineHandler))
       throw Components.results.NS_ERROR_NO_INTERFACE;
 
     return this;
   },
 
-  // List of uri's that were passed via the command line without the app
-  // running and have already been handled. This is compared against uri's
-  // opened using DDE on Win32 so we only open one of the requests.
-  _handledURIs: [ ],
 #ifdef XP_WIN
   _haveProfile: false,
 #endif
 
   /* nsICommandLineHandler */
   handle : function dch_handle(cmdLine) {
     var urilist = [];
 
@@ -779,35 +775,18 @@ nsDefaultCommandLineHandler.prototype = 
         cmdLine.preventDefault = true;
       }
     }
 #endif
 
     try {
       var ar;
       while ((ar = cmdLine.handleFlagWithParam("url", false))) {
-        var found = false;
         var uri = resolveURIInternal(cmdLine, ar);
-        // count will never be greater than zero except on Win32.
-        var count = this._handledURIs.length;
-        for (var i = 0; i < count; ++i) {
-          if (this._handledURIs[i].spec == uri.spec) {
-            this._handledURIs.splice(i, 1);
-            found = true;
-            cmdLine.preventDefault = true;
-            break;
-          }
-        }
-        if (!found) {
-          urilist.push(uri);
-          // The requestpending command line flag is only used on Win32.
-          if (cmdLine.handleFlag("requestpending", false) &&
-              cmdLine.state == nsICommandLine.STATE_INITIAL_LAUNCH)
-            this._handledURIs.push(uri)
-        }
+        urilist.push(uri);
       }
     }
     catch (e) {
       Components.utils.reportError(e);
     }
 
     count = cmdLine.length;
 
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -60,19 +60,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/NetUtil.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
                                   "resource://gre/modules/PlacesUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "BookmarkHTMLUtils",
                                   "resource://gre/modules/BookmarkHTMLUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "KeywordURLResetPrompter",
-                                  "resource:///modules/KeywordURLResetPrompter.jsm");
-
 XPCOMUtils.defineLazyModuleGetter(this, "webappsUI", 
                                   "resource:///modules/webappsUI.jsm");
 
 const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
 const PREF_PLUGINS_UPDATEURL  = "plugins.update.url";
 
 // We try to backup bookmarks at idle times, to avoid doing that at shutdown.
 // Number of idle seconds before trying to backup bookmarks.  15 minutes.
@@ -268,23 +265,16 @@ BrowserGlue.prototype = {
           this._distributionCustomizer.applyPrefDefaults();
           this._distributionCustomizer.applyCustomizations();
           // To apply distribution bookmarks use "places-init-complete".
         }
         else if (data == "force-places-init") {
           this._initPlaces();
         }
         break;
-      case "defaultURIFixup-using-keyword-pref":
-        if (KeywordURLResetPrompter.shouldPrompt) {
-          let keywordURI = subject.QueryInterface(Ci.nsIURI);
-          KeywordURLResetPrompter.prompt(this.getMostRecentBrowserWindow(),
-                                         keywordURI);
-        }
-        break;
       case "initial-migration":
         this._initialMigrationPerformed = true;
         break;
     }
   }, 
 
   // initialization (called on application startup) 
   _init: function BG__init() {
@@ -307,17 +297,16 @@ BrowserGlue.prototype = {
     os.addObserver(this, "session-save", false);
     os.addObserver(this, "places-init-complete", false);
     this._isPlacesInitObserver = true;
     os.addObserver(this, "places-database-locked", false);
     this._isPlacesLockedObserver = true;
     os.addObserver(this, "distribution-customization-complete", false);
     os.addObserver(this, "places-shutdown", false);
     this._isPlacesShutdownObserver = true;
-    os.addObserver(this, "defaultURIFixup-using-keyword-pref", false);
   },
 
   // cleanup (called on application shutdown)
   _dispose: function BG__dispose() {
     let os = Services.obs;
     os.removeObserver(this, "xpcom-shutdown");
     os.removeObserver(this, "prefservice:after-app-defaults");
     os.removeObserver(this, "final-ui-startup");
@@ -336,17 +325,16 @@ BrowserGlue.prototype = {
     if (this._isIdleObserver)
       this._idleService.removeIdleObserver(this, BOOKMARKS_BACKUP_IDLE_TIME);
     if (this._isPlacesInitObserver)
       os.removeObserver(this, "places-init-complete");
     if (this._isPlacesLockedObserver)
       os.removeObserver(this, "places-database-locked");
     if (this._isPlacesShutdownObserver)
       os.removeObserver(this, "places-shutdown");
-    os.removeObserver(this, "defaultURIFixup-using-keyword-pref");
     webappsUI.uninit();
   },
 
   _onAppDefaults: function BG__onAppDefaults() {
     // apply distribution customizations (prefs)
     // other customizations are applied in _onProfileStartup()
     this._distributionCustomizer.applyPrefDefaults();
   },
@@ -1250,23 +1238,17 @@ BrowserGlue.prototype = {
     if (currentUIVersion < 2) {
       // This code adds the customizable bookmarks button.
       let currentsetResource = this._rdf.GetResource("currentset");
       let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
       let currentset = this._getPersist(toolbarResource, currentsetResource);
       // Need to migrate only if toolbar is customized and the element is not found.
       if (currentset &&
           currentset.indexOf("bookmarks-menu-button-container") == -1) {
-        if (currentset.indexOf("fullscreenflex") != -1) {
-          currentset = currentset.replace(/(^|,)fullscreenflex($|,)/,
-                                          "$1bookmarks-menu-button-container,fullscreenflex$2")
-        }
-        else {
-          currentset += ",bookmarks-menu-button-container";
-        }
+        currentset += ",bookmarks-menu-button-container";
         this._setPersist(toolbarResource, currentsetResource, currentset);
       }
     }
 
     if (currentUIVersion < 3) {
       // This code merges the reload/stop/go button into the url bar.
       let currentsetResource = this._rdf.GetResource("currentset");
       let toolbarResource = this._rdf.GetResource(BROWSER_DOCURL + "nav-bar");
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -188,19 +188,19 @@ PrivateBrowsingService.prototype = {
           }
         }
         win.close();
       }
 
       if (!this._quitting && this._saveSession) {
         let browserWindow = this._getBrowserWindow();
 
-	// if there are open browser windows, load a dummy session to get a distinct 
+        // if there are open browser windows, load a dummy session to get a distinct 
         // separation between private and non-private sessions
-	if (browserWindow) {
+        if (browserWindow) {
           // set an empty session to transition from/to pb mode, see bug 476463
           ss.setBrowserState(blankState);
 
           // just in case the only remaining window after setBrowserState is different.
           // it probably shouldn't be with the current sessionstore impl, but we shouldn't
           // rely on behaviour the API doesn't guarantee
           browserWindow = this._getBrowserWindow();
           let browser = browserWindow.gBrowser;
@@ -212,17 +212,19 @@ PrivateBrowsingService.prototype = {
           browser.removeTab(browser.tabContainer.firstChild);
           browserWindow.getInterface(Ci.nsIWebNavigation)
                        .QueryInterface(Ci.nsIDocShellTreeItem)
                        .treeOwner
                        .QueryInterface(Ci.nsIInterfaceRequestor)
                        .getInterface(Ci.nsIXULWindow)
                        .docShell.contentViewer.resetCloseWindow();
         }
+      }
 
+      if (!this._quitting) {
         var windowsEnum = Services.wm.getEnumerator("navigator:browser");
         while (windowsEnum.hasMoreElements()) {
           var window = windowsEnum.getNext();
           window.getInterface(Ci.nsIWebNavigation)
                 .QueryInterface(Ci.nsIDocShellTreeItem)
                 .treeOwner
                 .QueryInterface(Ci.nsIInterfaceRequestor)
                 .getInterface(Ci.nsIXULWindow)
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_ui.js
@@ -53,31 +53,41 @@ function test() {
   // add a new blank tab to ensure the title can be meaningfully compared later
   gBrowser.selectedTab = gBrowser.addTab();
   let originalTitle = document.title;
 
   // test the gPrivateBrowsingUI object
   ok(gPrivateBrowsingUI, "The gPrivateBrowsingUI object exists");
   is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started initially");
   is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
+  is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
   ok(pbMenuItem, "The Private Browsing menu item exists");
   is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
   gPrivateBrowsingUI.toggleMode();
   is(pb.privateBrowsingEnabled, true, "The private browsing mode should be started");
   is(gPrivateBrowsingUI.privateBrowsingEnabled, true, "gPrivateBrowsingUI should expose the correct private browsing status");
+  is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
   // check to see if the Private Browsing mode was activated successfully
   is(observerData, "enter", "Private Browsing mode was activated using the gPrivateBrowsingUI object");
   is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("stoplabel"), "The Private Browsing menu item should read \"Stop Private Browsing\"");
   gPrivateBrowsingUI.toggleMode()
   is(pb.privateBrowsingEnabled, false, "The private browsing mode should not be started");
   is(gPrivateBrowsingUI.privateBrowsingEnabled, false, "gPrivateBrowsingUI should expose the correct private browsing status");
+  is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should expose the correct per-window private browsing status");
   // check to see if the Private Browsing mode was deactivated successfully
   is(observerData, "exit", "Private Browsing mode was deactivated using the gPrivateBrowsingUI object");
   is(pbMenuItem.getAttribute("label"), pbMenuItem.getAttribute("startlabel"), "The Private Browsing menu item should read \"Start Private Browsing\"");
 
+  // These are tests for the privateWindow setter.  Note that the setter should
+  // not be used anywhere else for now!
+  gPrivateBrowsingUI.privateWindow = true;
+  is(gPrivateBrowsingUI.privateWindow, true, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
+  gPrivateBrowsingUI.privateWindow = false;
+  is(gPrivateBrowsingUI.privateWindow, false, "gPrivateBrowsingUI should accept the correct per-window private browsing status");
+
   // now, test using the <command> object
   let cmd = document.getElementById("Tools:PrivateBrowsing");
   isnot(cmd, null, "XUL command object for the private browsing service exists");
   var func = new Function("", cmd.getAttribute("oncommand"));
   func.call(cmd);
   // check to see if the Private Browsing mode was activated successfully
   is(observerData, "enter", "Private Browsing mode was activated using the command object");
   // check to see that the window title has been changed correctly
--- a/browser/components/shell/src/nsWindowsShellService.cpp
+++ b/browser/components/shell/src/nsWindowsShellService.cpp
@@ -72,17 +72,20 @@
 
 #ifdef _WIN32_WINNT
 #undef _WIN32_WINNT
 #endif
 #define _WIN32_WINNT 0x0600
 #define INITGUID
 #include <shlobj.h>
 
+#pragma comment(lib, "shlwapi.lib") // for SHDeleteKeyW
+
 #include <mbstring.h>
+#include <shlwapi.h>
 
 #ifndef MAX_BUF
 #define MAX_BUF 4096
 #endif
 
 #define REG_SUCCEEDED(val) \
   (val == ERROR_SUCCESS)
 
@@ -124,49 +127,40 @@ OpenKeyForReading(HKEY aKeyRoot, const n
 //   are mapped like so:
 //
 //   HKCU\SOFTWARE\Classes\.<ext>\      (default)         REG_SZ     FirefoxHTML
 //
 //   as aliases to the class:
 //
 //   HKCU\SOFTWARE\Classes\FirefoxHTML\
 //     DefaultIcon                      (default)         REG_SZ     <apppath>,1
-//     shell\open\command               (default)         REG_SZ     <apppath> -requestPending -osint -url "%1"
-//     shell\open\ddeexec               (default)         REG_SZ     "%1",,0,0,,,,
-//     shell\open\ddeexec               NoActivateHandler REG_SZ
-//                       \Application   (default)         REG_SZ     Firefox
-//                       \Topic         (default)         REG_SZ     WWW_OpenURL
+//     shell\open\command               (default)         REG_SZ     <apppath> -osint -url "%1"
+//     shell\open\ddeexec               (default)         REG_SZ     <empty string>
 //
-// - Windows Vista Protocol Handler
+// - Windows Vista and above Protocol Handler
 //
 //   HKCU\SOFTWARE\Classes\FirefoxURL\  (default)         REG_SZ     <appname> URL
 //                                      EditFlags         REG_DWORD  2
 //                                      FriendlyTypeName  REG_SZ     <appname> URL
 //     DefaultIcon                      (default)         REG_SZ     <apppath>,1
-//     shell\open\command               (default)         REG_SZ     <apppath> -requestPending -osint -url "%1"
-//     shell\open\ddeexec               (default)         REG_SZ     "%1",,0,0,,,,
-//     shell\open\ddeexec               NoActivateHandler REG_SZ
-//                       \Application   (default)         REG_SZ     Firefox
-//                       \Topic         (default)         REG_SZ     WWW_OpenURL
+//     shell\open\command               (default)         REG_SZ     <apppath> -osint -url "%1"
+//     shell\open\ddeexec               (default)         REG_SZ     <empty string>
 //
 // - Protocol Mappings
 //   -----------------
 //   The following protocols:
 //    HTTP, HTTPS, FTP
 //   are mapped like so:
 //
 //   HKCU\SOFTWARE\Classes\<protocol>\
 //     DefaultIcon                      (default)         REG_SZ     <apppath>,1
-//     shell\open\command               (default)         REG_SZ     <apppath> -requestPending -osint -url "%1"
-//     shell\open\ddeexec               (default)         REG_SZ     "%1",,0,0,,,,
-//     shell\open\ddeexec               NoActivateHandler REG_SZ
-//                       \Application   (default)         REG_SZ     Firefox
-//                       \Topic         (default)         REG_SZ     WWW_OpenURL
+//     shell\open\command               (default)         REG_SZ     <apppath> -osint -url "%1"
+//     shell\open\ddeexec               (default)         REG_SZ     <empty string>
 //
-// - Windows Start Menu (Win2K SP2, XP SP1, and newer)
+// - Windows Start Menu (XP SP1 and newer)
 //   -------------------------------------------------
 //   The following keys are set to make Firefox appear in the Start Menu as the
 //   browser:
 //   
 //   HKCU\SOFTWARE\Clients\StartMenuInternet\FIREFOX.EXE\
 //                                      (default)         REG_SZ     <appname>
 //     DefaultIcon                      (default)         REG_SZ     <apppath>,0
 //     InstallInfo                      HideIconsCommand  REG_SZ     <uninstpath> /HideShortcuts
@@ -175,50 +169,71 @@ OpenKeyForReading(HKEY aKeyRoot, const n
 //     InstallInfo                      ShowIconsCommand  REG_SZ     <uninstpath> /ShowShortcuts
 //     shell\open\command               (default)         REG_SZ     <apppath>
 //     shell\properties                 (default)         REG_SZ     <appname> &Options
 //     shell\properties\command         (default)         REG_SZ     <apppath> -preferences
 //     shell\safemode                   (default)         REG_SZ     <appname> &Safe Mode
 //     shell\safemode\command           (default)         REG_SZ     <apppath> -safe-mode
 //
 
+// The values checked are all default values so the value name is not needed.
 typedef struct {
   char* keyName;
-  char* valueName;
   char* valueData;
+  char* oldValueData;
 } SETTING;
 
 #define APP_REG_NAME L"Firefox"
-#define CLS_HTML "FirefoxHTML"
-#define CLS_URL "FirefoxURL"
-#define VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
 #define VAL_FILE_ICON "%APPPATH%,1"
+#define VAL_OPEN "\"%APPPATH%\" -osint -url \"%1\""
+#define OLD_VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
 #define DI "\\DefaultIcon"
-#define SOP "\\shell\\open\\command"
+#define SOC "\\shell\\open\\command"
+#define SOD "\\shell\\open\\ddeexec"
+// Used for updating the FTP protocol handler's shell open command under HKCU.
+#define FTP_SOC L"Software\\Classes\\ftp\\shell\\open\\command"
 
 #define MAKE_KEY_NAME1(PREFIX, MID) \
   PREFIX MID
 
 // The DefaultIcon registry key value should never be used when checking if
 // Firefox is the default browser for file handlers since other applications
 // (e.g. MS Office) may modify the DefaultIcon registry key value to add Icon
 // Handlers. see http://msdn2.microsoft.com/en-us/library/aa969357.aspx for
-// more info.
+// more info. The FTP protocol is not checked so advanced users can set the FTP
+// handler to another application and still have Firefox check if it is the
+// default HTTP and HTTPS handler.
 static SETTING gSettings[] = {
   // File Handler Class
-  { MAKE_KEY_NAME1(CLS_HTML, SOP), "", VAL_OPEN },
+  { MAKE_KEY_NAME1("FirefoxHTML", SOC), VAL_OPEN, OLD_VAL_OPEN },
 
   // Protocol Handler Class - for Vista and above
-  { MAKE_KEY_NAME1(CLS_URL, SOP), "", VAL_OPEN },
+  { MAKE_KEY_NAME1("FirefoxURL", SOC), VAL_OPEN, OLD_VAL_OPEN },
 
   // Protocol Handlers
-  { MAKE_KEY_NAME1("HTTP", DI),    "", VAL_FILE_ICON },
-  { MAKE_KEY_NAME1("HTTP", SOP),   "", VAL_OPEN },
-  { MAKE_KEY_NAME1("HTTPS", DI),   "", VAL_FILE_ICON },
-  { MAKE_KEY_NAME1("HTTPS", SOP),  "", VAL_OPEN }
+  { MAKE_KEY_NAME1("HTTP", DI), VAL_FILE_ICON },
+  { MAKE_KEY_NAME1("HTTP", SOC), VAL_OPEN, OLD_VAL_OPEN },
+  { MAKE_KEY_NAME1("HTTPS", DI), VAL_FILE_ICON },
+  { MAKE_KEY_NAME1("HTTPS", SOC), VAL_OPEN, OLD_VAL_OPEN }
+};
+
+// The settings to disable DDE are separate from the default browser settings
+// since they are only checked when Firefox is the default browser and if they
+// are incorrect they are fixed without notifying the user.
+static SETTING gDDESettings[] = {
+  // File Handler Class
+  { MAKE_KEY_NAME1("Software\\Classes\\FirefoxHTML", SOD) },
+
+  // Protocol Handler Class - for Vista and above
+  { MAKE_KEY_NAME1("Software\\Classes\\FirefoxURL", SOD) },
+
+  // Protocol Handlers
+  { MAKE_KEY_NAME1("Software\\Classes\\FTP", SOD) },
+  { MAKE_KEY_NAME1("Software\\Classes\\HTTP", SOD) },
+  { MAKE_KEY_NAME1("Software\\Classes\\HTTPS", SOD) }
 };
 
 nsresult
 GetHelperPath(nsAutoString& aPath)
 {
   nsresult rv;
   nsCOMPtr<nsIProperties> directoryService = 
     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
@@ -240,21 +255,20 @@ GetHelperPath(nsAutoString& aPath)
 }
 
 nsresult
 LaunchHelper(nsAutoString& aPath)
 {
   STARTUPINFOW si = {sizeof(si), 0};
   PROCESS_INFORMATION pi = {0};
 
-  BOOL ok = CreateProcessW(NULL, (LPWSTR)aPath.get(), NULL, NULL,
-                           FALSE, 0, NULL, NULL, &si, &pi);
-
-  if (!ok)
+  if (!CreateProcessW(NULL, (LPWSTR)aPath.get(), NULL, NULL, FALSE, 0, NULL,
+                      NULL, &si, &pi)) {
     return NS_ERROR_FAILURE;
+  }
 
   CloseHandle(pi.hProcess);
   CloseHandle(pi.hThread);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindowsShellService::ShortcutMaintenance()
@@ -362,66 +376,194 @@ nsWindowsShellService::IsDefaultBrowser(
                                         bool* aIsDefaultBrowser)
 {
   // If this is the first browser window, maintain internal state that we've
   // checked this session (so that subsequent window opens don't show the 
   // default browser dialog).
   if (aStartupCheck)
     mCheckedThisSession = true;
 
-  SETTING* settings;
-  SETTING* end = gSettings + sizeof(gSettings)/sizeof(SETTING);
-
   *aIsDefaultBrowser = true;
 
   PRUnichar exePath[MAX_BUF];
   if (!::GetModuleFileNameW(0, exePath, MAX_BUF))
     return NS_ERROR_FAILURE;
 
   // Convert the path to a long path since GetModuleFileNameW returns the path
   // that was used to launch Firefox which is not necessarily a long path.
   if (!::GetLongPathNameW(exePath, exePath, MAX_BUF))
     return NS_ERROR_FAILURE;
 
   nsAutoString appLongPath(exePath);
 
+  HKEY theKey;
+  DWORD res;
   nsresult rv;
   PRUnichar currValue[MAX_BUF];
+
+  SETTING* settings;
+  SETTING* end = gSettings + sizeof(gSettings) / sizeof(SETTING);
+
   for (settings = gSettings; settings < end; ++settings) {
-    NS_ConvertUTF8toUTF16 dataLongPath(settings->valueData);
-    NS_ConvertUTF8toUTF16 key(settings->keyName);
-    NS_ConvertUTF8toUTF16 value(settings->valueName);
-    PRInt32 offset = dataLongPath.Find("%APPPATH%");
-    dataLongPath.Replace(offset, 9, appLongPath);
+    NS_ConvertUTF8toUTF16 keyName(settings->keyName);
+    NS_ConvertUTF8toUTF16 valueData(settings->valueData);
+    PRInt32 offset = valueData.Find("%APPPATH%");
+    valueData.Replace(offset, 9, appLongPath);
 
-    ::ZeroMemory(currValue, sizeof(currValue));
-    HKEY theKey;
-    rv = OpenKeyForReading(HKEY_CLASSES_ROOT, key, &theKey);
+    rv = OpenKeyForReading(HKEY_CLASSES_ROOT, keyName, &theKey);
     if (NS_FAILED(rv)) {
       *aIsDefaultBrowser = false;
       return NS_OK;
     }
 
+    ::ZeroMemory(currValue, sizeof(currValue));
     DWORD len = sizeof currValue;
-    DWORD res = ::RegQueryValueExW(theKey, PromiseFlatString(value).get(),
-                                   NULL, NULL, (LPBYTE)currValue, &len);
-    // Close the key we opened.
+    res = ::RegQueryValueExW(theKey, L"", NULL, NULL, (LPBYTE)currValue, &len);
+    // Close the key that was opened.
     ::RegCloseKey(theKey);
     if (REG_FAILED(res) ||
-        !dataLongPath.Equals(currValue, CaseInsensitiveCompare)) {
-      // Key wasn't set, or was set to something other than our registry entry
-      *aIsDefaultBrowser = false;
-      return NS_OK;
+        !valueData.Equals(currValue, CaseInsensitiveCompare)) {
+      // Key wasn't set or was set to something other than our registry entry.
+      NS_ConvertUTF8toUTF16 oldValueData(settings->oldValueData);
+      offset = oldValueData.Find("%APPPATH%");
+      oldValueData.Replace(offset, 9, appLongPath);
+      // The current registry value doesn't match the current or the old format.
+      if (!oldValueData.Equals(currValue, CaseInsensitiveCompare)) {
+        *aIsDefaultBrowser = false;
+        return NS_OK;
+      }
+
+      res = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, PromiseFlatString(keyName).get(),
+                            0, KEY_SET_VALUE, &theKey);
+      if (REG_FAILED(res)) {
+        // If updating the open command fails try to update it using the helper
+        // application when setting Firefox as the default browser.
+        *aIsDefaultBrowser = false;
+        return NS_OK;
+      }
+
+      const nsString &flatValue = PromiseFlatString(valueData);
+      res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
+                             (const BYTE *) flatValue.get(),
+                             (flatValue.Length() + 1) * sizeof(PRUnichar));
+      // Close the key that was created.
+      ::RegCloseKey(theKey);
+      if (REG_FAILED(res)) {
+        // If updating the open command fails try to update it using the helper
+        // application when setting Firefox as the default browser.
+        *aIsDefaultBrowser = false;
+        return NS_OK;
+      }
     }
   }
 
-  // Only check if Firefox is the default browser on Vista if the previous
-  // checks show that Firefox is the default browser.
-  if (*aIsDefaultBrowser)
+  // Only check if Firefox is the default browser on Vista and above if the
+  // previous checks show that Firefox is the default browser.
+  if (*aIsDefaultBrowser) {
     IsDefaultBrowserVista(aIsDefaultBrowser);
+  }
+
+  // To handle the case where DDE isn't disabled due for a user because there
+  // account didn't perform a Firefox update this will check if Firefox is the
+  // default browser and if dde is disabled for each handler
+  // and if it isn't disable it. When Firefox is not the default browser the
+  // helper application will disable dde for each handler.
+  if (*aIsDefaultBrowser) {
+    // Check ftp settings
+
+    end = gDDESettings + sizeof(gDDESettings) / sizeof(SETTING);
+
+    for (settings = gDDESettings; settings < end; ++settings) {
+      NS_ConvertUTF8toUTF16 keyName(settings->keyName);
+
+      rv = OpenKeyForReading(HKEY_CURRENT_USER, keyName, &theKey);
+      if (NS_FAILED(rv)) {
+        ::RegCloseKey(theKey);
+        // If disabling DDE fails try to disable it using the helper
+        // application when setting Firefox as the default browser.
+        *aIsDefaultBrowser = false;
+        return NS_OK;
+      }
+
+      ::ZeroMemory(currValue, sizeof(currValue));
+      DWORD len = sizeof currValue;
+      res = ::RegQueryValueExW(theKey, L"", NULL, NULL, (LPBYTE)currValue,
+                               &len);
+      // Close the key that was opened.
+      ::RegCloseKey(theKey);
+      if (REG_FAILED(res) || PRUnichar('\0') != *currValue) {
+        // Key wasn't set or was set to something other than our registry entry.
+        // Delete the key along with all of its childrean and then recreate it.
+        const nsString &flatName = PromiseFlatString(keyName);
+        ::SHDeleteKeyW(HKEY_CURRENT_USER, flatName.get());
+        res = ::RegCreateKeyExW(HKEY_CURRENT_USER, flatName.get(), 0, NULL,
+                                REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL,
+                                &theKey, NULL);
+        if (REG_FAILED(res)) {
+          // If disabling DDE fails try to disable it using the helper
+          // application when setting Firefox as the default browser.
+          *aIsDefaultBrowser = false;
+          return NS_OK;
+        }
+
+        res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, (const BYTE *) L"",
+                               sizeof(PRUnichar));
+        // Close the key that was created.
+        ::RegCloseKey(theKey);
+        if (REG_FAILED(res)) {
+          // If disabling DDE fails try to disable it using the helper
+          // application when setting Firefox as the default browser.
+          *aIsDefaultBrowser = false;
+          return NS_OK;
+        }
+      }
+    }
+
+    // Update the FTP protocol handler's shell open command if it is the old
+    // format.
+    res = ::RegOpenKeyExW(HKEY_CURRENT_USER, FTP_SOC, 0, KEY_ALL_ACCESS,
+                          &theKey);
+    // Don't update the FTP protocol handler's shell open command when opening
+    // its registry key fails under HKCU since it most likely doesn't exist.
+    if (NS_FAILED(rv)) {
+      return NS_OK;
+    }
+
+    NS_ConvertUTF8toUTF16 oldValueOpen(OLD_VAL_OPEN);
+    PRInt32 offset = oldValueOpen.Find("%APPPATH%");
+    oldValueOpen.Replace(offset, 9, appLongPath);
+
+    ::ZeroMemory(currValue, sizeof(currValue));
+    DWORD len = sizeof currValue;
+    res = ::RegQueryValueExW(theKey, L"", NULL, NULL, (LPBYTE)currValue,
+                             &len);
+
+    // Don't update the FTP protocol handler's shell open command when the
+    // current registry value doesn't exist or matches the old format.
+    if (REG_FAILED(res) ||
+        !oldValueOpen.Equals(currValue, CaseInsensitiveCompare)) {
+      ::RegCloseKey(theKey);
+      return NS_OK;
+    }
+
+    NS_ConvertUTF8toUTF16 valueData(VAL_OPEN);
+    valueData.Replace(offset, 9, appLongPath);
+    const nsString &flatValue = PromiseFlatString(valueData);
+    res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
+                           (const BYTE *) flatValue.get(),
+                           (flatValue.Length() + 1) * sizeof(PRUnichar));
+    // Close the key that was created.
+    ::RegCloseKey(theKey);
+    // If updating the FTP protocol handlers shell open command fails try to
+    // update it using the helper application when setting Firefox as the
+    // default browser.
+    if (REG_FAILED(res)) {
+      *aIsDefaultBrowser = false;
+    }
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers)
 {
   nsAutoString appHelperPath;
--- a/browser/components/thumbnails/PageThumbsProtocol.js
+++ b/browser/components/thumbnails/PageThumbsProtocol.js
@@ -20,19 +20,16 @@
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Cr = Components.results;
 const Ci = Components.interfaces;
 
 Cu.import("resource:///modules/PageThumbs.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
-  "resource://gre/modules/NetUtil.jsm");
-
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
   "resource://gre/modules/Services.jsm");
 
 /**
  * Implements the thumbnail protocol handler responsible for moz-page-thumb: URIs.
  */
 function Protocol() {
 }
@@ -99,345 +96,294 @@ function Channel(aURI) {
   // nsIChannel
   this.originalURI = aURI;
 
   // nsIHttpChannel
   this._responseHeaders = {"content-type": PageThumbs.contentType};
 }
 
 Channel.prototype = {
-  /**
-   * Tracks if the channel has been opened, yet.
-   */
+  _uri: null,
+  _referrer: null,
+  _canceled: false,
+  _status: Cr.NS_OK,
+  _isPending: false,
   _wasOpened: false,
+  _responseText: "OK",
+  _responseStatus: 200,
+  _responseHeaders: null,
+  _requestMethod: "GET",
+  _requestStarted: false,
+  _allowPipelining: true,
+  _requestSucceeded: true,
+
+  /* :::::::: nsIChannel ::::::::::::::: */
+
+  get URI() this._uri,
+  owner: null,
+  notificationCallbacks: null,
+  get securityInfo() null,
+
+  contentType: PageThumbs.contentType,
+  contentCharset: null,
+  contentLength: -1,
 
-  /**
-   * Opens this channel asynchronously.
-   * @param aListener The listener that receives the channel data when available.
-   * @param aContext A custom context passed to the listener's methods.
-   */
+  get contentDisposition() {
+    throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
+  },
+
+  get contentDispositionFilename() {
+    throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
+  },
+
+  get contentDispositionHeader() {
+    throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
+  },
+
+  open: function Channel_open() {
+    throw (Components.returnCode = Cr.NS_ERROR_NOT_IMPLEMENTED);
+  },
+
   asyncOpen: function Channel_asyncOpen(aListener, aContext) {
+    if (this._isPending)
+      throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
+
     if (this._wasOpened)
-      throw Cr.NS_ERROR_ALREADY_OPENED;
+      throw (Components.returnCode = Cr.NS_ERROR_ALREADY_OPENED);
 
-    if (this.canceled)
-      return;
-
-    this._listener = aListener;
-    this._context = aContext;
+    if (this._canceled)
+      return (Components.returnCode = this._status);
 
     this._isPending = true;
     this._wasOpened = true;
 
-    // Try to read the data from the thumbnail cache.
-    this._readCache(function (aData) {
-      let telemetryThumbnailFound = true;
+    this._listener = aListener;
+    this._context = aContext;
 
-      // Update response if there's no data.
-      if (!aData) {
-        this._responseStatus = 404;
-        this._responseText = "Not Found";
-        telemetryThumbnailFound = false;
-      }
-
-      Services.telemetry.getHistogramById("FX_THUMBNAILS_HIT_OR_MISS")
-        .add(telemetryThumbnailFound);
-
-      this._startRequest();
-
-      if (!this.canceled) {
-        this._addToLoadGroup();
+    if (this.loadGroup)
+      this.loadGroup.addRequest(this, null);
 
-        if (aData)
-          this._serveData(aData);
-
-        if (!this.canceled)
-          this._stopRequest();
-      }
-    }.bind(this));
-  },
+    if (this._canceled)
+      return;
 
-  /**
-   * Reads a data stream from the cache entry.
-   * @param aCallback The callback the data is passed to.
-   */
-  _readCache: function Channel_readCache(aCallback) {
     let {url} = parseURI(this._uri);
-
-    // Return early if there's no valid URL given.
     if (!url) {
-      aCallback(null);
+      this._serveThumbnailNotFound();
       return;
     }
 
-    // Try to get a cache entry.
     PageThumbsCache.getReadEntry(url, function (aEntry) {
       let inputStream = aEntry && aEntry.openInputStream(0);
-
-      function closeEntryAndFinish(aData) {
-        if (aEntry) {
+      if (!inputStream || !inputStream.available()) {
+        if (aEntry)
           aEntry.close();
-        }
-        aCallback(aData);
-      }
-
-      // Check if we have a valid entry and if it has any data.
-      if (!inputStream || !inputStream.available()) {
-        closeEntryAndFinish();
+        this._serveThumbnailNotFound();
         return;
       }
 
-      try {
-        // Read the cache entry's data.
-        NetUtil.asyncFetch(inputStream, function (aData, aStatus) {
-          // We might have been canceled while waiting.
-          if (this.canceled)
-            return;
+      this._entry = aEntry;
+      this._pump = Cc["@mozilla.org/network/input-stream-pump;1"].
+                   createInstance(Ci.nsIInputStreamPump);
 
-          // Check if we have a valid data stream.
-          if (!Components.isSuccessCode(aStatus) || !aData.available())
-            aData = null;
+      this._pump.init(inputStream, -1, -1, 0, 0, true);
+      this._pump.asyncRead(this, null);
 
-          closeEntryAndFinish(aData);
-        }.bind(this));
-      } catch (e) {
-        closeEntryAndFinish();
-      }
+      this._trackThumbnailHitOrMiss(true);
     }.bind(this));
   },
 
   /**
-   * Calls onStartRequest on the channel listener.
-   */
-  _startRequest: function Channel_startRequest() {
-    try {
-      this._listener.onStartRequest(this, this._context);
-    } catch (e) {
-      // The listener might throw if the request has been canceled.
-      this.cancel(Cr.NS_BINDING_ABORTED);
-    }
-  },
-
-  /**
-   * Calls onDataAvailable on the channel listener and passes the data stream.
-   * @param aData The data to be delivered.
+   * Serves a "404 Not Found" if we didn't find the requested thumbnail.
    */
-  _serveData: function Channel_serveData(aData) {
-    try {
-      let available = aData.available();
-      this._listener.onDataAvailable(this, this._context, aData, 0, available);
-    } catch (e) {
-      // The listener might throw if the request has been canceled.
-      this.cancel(Cr.NS_BINDING_ABORTED);
-    }
-  },
+  _serveThumbnailNotFound: function Channel_serveThumbnailNotFound() {
+    this._responseStatus = 404;
+    this._responseText = "Not Found";
+    this._requestSucceeded = false;
 
-  /**
-   * Calls onStopRequest on the channel listener.
-   */
-  _stopRequest: function Channel_stopRequest() {
-    try {
-      this._listener.onStopRequest(this, this._context, this.status);
-    } catch (e) {
-      // This might throw but is generally ignored.
-    }
+    this.onStartRequest(this, null);
+    this.onStopRequest(this, null, Cr.NS_OK);
 
-    // The request has finished, clean up after ourselves.
-    this._cleanup();
+    this._trackThumbnailHitOrMiss(false);
   },
 
   /**
-   * Adds this request to the load group, if any.
+   * Implements telemetry tracking for thumbnail cache hits and misses.
+   * @param aFound Whether the thumbnail was found.
    */
-  _addToLoadGroup: function Channel_addToLoadGroup() {
-    if (this.loadGroup)
-      this.loadGroup.addRequest(this, this._context);
+  _trackThumbnailHitOrMiss: function Channel_trackThumbnailHitOrMiss(aFound) {
+    Services.telemetry.getHistogramById("FX_THUMBNAILS_HIT_OR_MISS")
+      .add(aFound);
   },
 
-  /**
-   * Removes this request from its load group, if any.
-   */
-  _removeFromLoadGroup: function Channel_removeFromLoadGroup() {
-    if (!this.loadGroup)
-      return;
+  /* :::::::: nsIStreamListener ::::::::::::::: */
+
+  onStartRequest: function Channel_onStartRequest(aRequest, aContext) {
+    if (!this.canceled && Components.isSuccessCode(this._status))
+      this._status = aRequest.status;
 
-    try {
-      this.loadGroup.removeRequest(this, this._context, this.status);
-    } catch (e) {
-      // This might throw but is ignored.
-    }
+    this._requestStarted = true;
+    this._listener.onStartRequest(this, this._context);
+  },
+
+  onDataAvailable: function Channel_onDataAvailable(aRequest, aContext,
+                                                    aInStream, aOffset, aCount) {
+    this._listener.onDataAvailable(this, this._context, aInStream, aOffset, aCount);
   },
 
-  /**
-   * Cleans up the channel when the request has finished.
-   */
-  _cleanup: function Channel_cleanup() {
-    this._removeFromLoadGroup();
-    this.loadGroup = null;
+  onStopRequest: function Channel_onStopRequest(aRequest, aContext, aStatus) {
+    this._isPending = false;
+    this._status = aStatus;
 
-    this._isPending = false;
+    this._listener.onStopRequest(this, this._context, aStatus);
+    this._listener = null;
+    this._context = null;
 
-    delete this._listener;
-    delete this._context;
+    if (this._entry)
+      this._entry.close();
+
+    if (this.loadGroup)
+      this.loadGroup.removeRequest(this, null, aStatus);
   },
 
-  /* :::::::: nsIChannel ::::::::::::::: */
+  /* :::::::: nsIRequest ::::::::::::::: */
+
+  get status() this._status,
+  get name() this._uri.spec,
+  isPending: function Channel_isPending() this._isPending,
 
-  contentType: PageThumbs.contentType,
-  contentLength: -1,
-  owner: null,
-  contentCharset: null,
-  notificationCallbacks: null,
+  loadFlags: Ci.nsIRequest.LOAD_NORMAL,
+  loadGroup: null,
+
+  cancel: function Channel_cancel(aStatus) {
+    if (this._canceled)
+      return;
 
-  get URI() this._uri,
-  get securityInfo() null,
+    this._canceled = true;
+    this._status = aStatus;
+
+    if (this._pump)
+      this._pump.cancel(aStatus);
+  },
 
-  /**
-   * Opens this channel synchronously. Not supported.
-   */
-  open: function Channel_open() {
-    // Synchronous data delivery is not implemented.
-    throw Cr.NS_ERROR_NOT_IMPLEMENTED;
+  suspend: function Channel_suspend() {
+    if (this._pump)
+      this._pump.suspend();
+  },
+
+  resume: function Channel_resume() {
+    if (this._pump)
+      this._pump.resume();
   },
 
   /* :::::::: nsIHttpChannel ::::::::::::::: */
 
-  redirectionLimit: 10,
-  requestMethod: "GET",
-  allowPipelining: true,
-  referrer: null,
+  get referrer() this._referrer,
 
-  get requestSucceeded() true,
+  set referrer(aReferrer) {
+    if (this._wasOpened)
+      throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
 
-  _responseStatus: 200,
-  get responseStatus() this._responseStatus,
+    this._referrer = aReferrer;
+  },
 
-  _responseText: "OK",
-  get responseStatusText() this._responseText,
+  get requestMethod() this._requestMethod,
 
-  /**
-   * Checks if the server sent the equivalent of a "Cache-control: no-cache"
-   * response header.
-   * @return Always false.
-   */
-  isNoCacheResponse: function () false,
+  set requestMethod(aMethod) {
+    if (this._wasOpened)
+      throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
+
+    this._requestMethod = aMethod.toUpperCase();
+  },
 
-  /**
-   * Checks if the server sent the equivalent of a "Cache-control: no-cache"
-   * response header.
-   * @return Always false.
-   */
-  isNoStoreResponse: function () false,
+  get allowPipelining() this._allowPipelining,
 
-  /**
-   * Returns the value of a particular request header. Not implemented.
-   */
-  getRequestHeader: function Channel_getRequestHeader() {
-    throw Cr.NS_ERROR_NOT_AVAILABLE;
+  set allowPipelining(aAllow) {
+    if (this._wasOpened)
+      throw (Components.returnCode = Cr.NS_ERROR_FAILURE);
+
+    this._allowPipelining = aAllow;
   },
 
-  /**
-   * This method is called to set the value of a particular request header.
-   * Not implemented.
-   */
-  setRequestHeader: function Channel_setRequestHeader() {
-    if (this._wasOpened)
-      throw Cr.NS_ERROR_IN_PROGRESS;
+  redirectionLimit: 10,
+
+  get responseStatus() {
+    if (this._requestStarted)
+      throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
+
+    return this._responseStatus;
+  },
+
+  get responseStatusText() {
+    if (this._requestStarted)
+      throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
+
+    return this._responseText;
   },
 
-  /**
-   * Call this method to visit all request headers. Not implemented.
-   */
-  visitRequestHeaders: function () {},
+  get requestSucceeded() {
+    if (this._requestStarted)
+      throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
+
+    return this._requestSucceeded;
+  },
+
+  isNoCacheResponse: function Channel_isNoCacheResponse() false,
+  isNoStoreResponse: function Channel_isNoStoreResponse() false,
 
-  /**
-   * Gets the value of a particular response header.
-   * @param aHeader The case-insensitive name of the response header to query.
-   * @return The header value.
-   */
+  getRequestHeader: function Channel_getRequestHeader() {
+    throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
+  },
+
+  setRequestHeader: function Channel_setRequestHeader() {
+    if (this._wasOpened)
+      throw (Components.returnCode = Cr.NS_ERROR_IN_PROGRESS);
+  },
+
+  visitRequestHeaders: function Channel_visitRequestHeaders() {},
+
   getResponseHeader: function Channel_getResponseHeader(aHeader) {
     let name = aHeader.toLowerCase();
     if (name in this._responseHeaders)
       return this._responseHeaders[name];
 
-    throw Cr.NS_ERROR_NOT_AVAILABLE;
+    throw (Components.returnCode = Cr.NS_ERROR_NOT_AVAILABLE);
   },
 
-  /**
-   * This method is called to set the value of a particular response header.
-   * @param aHeader The case-insensitive name of the response header to query.
-   * @param aValue The response header value to set.
-   */
   setResponseHeader: function Channel_setResponseHeader(aHeader, aValue, aMerge) {
     let name = aHeader.toLowerCase();
     if (!aValue && !aMerge)
       delete this._responseHeaders[name];
     else
       this._responseHeaders[name] = aValue;
   },
 
-  /**
-   * Call this method to visit all response headers.
-   * @param aVisitor The header visitor.
-   */
   visitResponseHeaders: function Channel_visitResponseHeaders(aVisitor) {
     for (let name in this._responseHeaders) {
       let value = this._responseHeaders[name];
 
       try {
         aVisitor.visitHeader(name, value);
       } catch (e) {
         // The visitor can throw to stop the iteration.
         return;
       }
     }
   },
 
-  /* :::::::: nsIRequest ::::::::::::::: */
-
-  loadFlags: Ci.nsIRequest.LOAD_NORMAL,
-  loadGroup: null,
-
-  get name() this._uri.spec,
-
-  _status: Cr.NS_OK,
-  get status() this._status,
-
-  _isPending: false,
-  isPending: function () this._isPending,
-
-  resume: function () {},
-  suspend: function () {},
-
-  /**
-   * Cancels this request.
-   * @param aStatus The reason for cancelling.
-   */
-  cancel: function Channel_cancel(aStatus) {
-    if (this.canceled)
-      return;
-
-    this._isCanceled = true;
-    this._status = aStatus;
-
-    this._cleanup();
-  },
-
   /* :::::::: nsIHttpChannelInternal ::::::::::::::: */
 
   documentURI: null,
-
-  _isCanceled: false,
-  get canceled() this._isCanceled,
+  get canceled() this._canceled,
+  allowSpdy: false,
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIChannel,
                                          Ci.nsIHttpChannel,
                                          Ci.nsIHttpChannelInternal,
                                          Ci.nsIRequest])
-};
+}
 
 /**
  * Parses a given URI and extracts all parameters relevant to this protocol.
  * @param aURI The URI to parse.
  * @return The parsed parameters.
  */
 function parseURI(aURI) {
   let {scheme, staticHost} = PageThumbs;
--- a/browser/config/mozconfigs/linux32/nightly
+++ b/browser/config/mozconfigs/linux32/nightly
@@ -6,27 +6,27 @@ ac_add_options --enable-signmar
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
 
+# PGO
+mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
+
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# PGO
-mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
+# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+ac_add_options --enable-warnings-as-errors
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
-#Use ccache
+# Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
-ac_add_options --enable-warnings-as-errors
-
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
--- a/browser/config/mozconfigs/linux64/nightly
+++ b/browser/config/mozconfigs/linux64/nightly
@@ -6,27 +6,27 @@ ac_add_options --enable-signmar
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 . $topsrcdir/build/unix/mozconfig.linux
 
 # Avoid dependency on libstdc++ 4.5
 ac_add_options --enable-stdcxx-compat
 
+# PGO
+mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
+
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
-# PGO
-mk_add_options PROFILE_GEN_SCRIPT='$(PYTHON) @MOZ_OBJDIR@/_profile/pgo/profileserver.py 10'
+# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
+ac_add_options --enable-warnings-as-errors
 
 # Enable parallel compiling
 mk_add_options MOZ_MAKE_FLAGS="-j4"
 
-#Use ccache
+# Use ccache
 ac_add_options --with-ccache=/usr/bin/ccache
 
-# Treat warnings as errors in directories with FAIL_ON_WARNINGS.
-ac_add_options --enable-warnings-as-errors
-
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
--- a/browser/devtools/styleinspector/CssRuleView.jsm
+++ b/browser/devtools/styleinspector/CssRuleView.jsm
@@ -62,17 +62,18 @@ const CSS_LINE_RE = /(?:[^;\(]*(?:\([^\)
 // Used to parse a single property line.
 const CSS_PROP_RE = /\s*([^:\s]*)\s*:\s*(.*?)\s*(?:! (important))?;?$/;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/devtools/CssLogic.jsm");
 
 var EXPORTED_SYMBOLS = ["CssRuleView",
                         "_ElementStyle",
-                        "_editableField"];
+                        "_editableField",
+                        "_getInplaceEditorForSpan"];
 
 /**
  * Our model looks like this:
  *
  * ElementStyle:
  *   Responsible for keeping track of which properties are overridden.
  *   Maintains a list of Rule objects that apply to the element.
  * Rule:
@@ -1470,16 +1471,24 @@ InplaceEditor.prototype = {
 
     // Call the user's change handler if available.
     if (this.change) {
       this.change(this.input.value.trim());
     }
   }
 };
 
+/*
+ * Various API consumers (especially tests) sometimes want to grab the
+ * inplaceEditor expando off span elements. However, when each global has its
+ * own compartment, those expandos live on Xray wrappers that are only visible
+ * within this JSM. So we provide a little workaround here.
+ */
+function _getInplaceEditorForSpan(aSpan) { return aSpan.inplaceEditor; };
+
 /**
  * Store of CSSStyleDeclarations mapped to properties that have been changed by
  * the user.
  */
 function UserProperties()
 {
   this.weakMap = new WeakMap();
 }
--- a/browser/devtools/styleinspector/test/browser_ruleview_editor.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_editor.js
@@ -2,16 +2,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 let tempScope = {}
 Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
 let CssRuleView = tempScope.CssRuleView;
 let _ElementStyle = tempScope._ElementStyle;
 let _editableField = tempScope._editableField;
+let inplaceEditor = tempScope._getInplaceEditorForSpan;
 
 let doc = content.document;
 
 function expectDone(aValue, aCommit, aNext)
 {
   return function(aDoneValue, aDoneCommit) {
     dump("aDoneValue: " + aDoneValue + " commit: " + aDoneCommit + "\n");
 
@@ -38,50 +39,50 @@ function createSpan()
 function testReturnCommit()
 {
   clearBody();
   let span = createSpan();
   _editableField({
     element: span,
     initial: "explicit initial",
     start: function() {
-      is(span.inplaceEditor.input.value, "explicit initial", "Explicit initial value should be used.");
-      span.inplaceEditor.input.value = "Test Value";
+      is(inplaceEditor(span).input.value, "explicit initial", "Explicit initial value should be used.");
+      inplaceEditor(span).input.value = "Test Value";
       EventUtils.sendKey("return");
     },
     done: expectDone("Test Value", true, testBlurCommit)
   });
   span.focus();
 }
 
 function testBlurCommit()
 {
   clearBody();
   let span = createSpan();
   _editableField({
     element: span,
     start: function() {
-      is(span.inplaceEditor.input.value, "Edit Me!", "textContent of the span used.");
-      span.inplaceEditor.input.value = "Test Value";
-      span.inplaceEditor.input.blur();
+      is(inplaceEditor(span).input.value, "Edit Me!", "textContent of the span used.");
+      inplaceEditor(span).input.value = "Test Value";
+      inplaceEditor(span).input.blur();
     },
     done: expectDone("Test Value", true, testAdvanceCharCommit)
   });
   span.focus();
 }
 
 function testAdvanceCharCommit()
 {
   clearBody();
   let span = createSpan();
   _editableField({
     element: span,
     advanceChars: ":",
     start: function() {
-      let input = span.inplaceEditor.input;
+      let input = inplaceEditor(span).input;
       for each (let ch in "Test:") {
         EventUtils.sendChar(ch);
       }
     },
     done: expectDone("Test", true, testEscapeCancel)
   });
   span.focus();
 }
@@ -89,17 +90,17 @@ function testAdvanceCharCommit()
 function testEscapeCancel()
 {
   clearBody();
   let span = createSpan();
   _editableField({
     element: span,
     initial: "initial text",
     start: function() {
-      span.inplaceEditor.input.value = "Test Value";
+      inplaceEditor(span).input.value = "Test Value";
       EventUtils.sendKey("escape");
     },
     done: expectDone("initial text", false, finishTest)
   });
   span.focus();
 }
 
 
--- a/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_editor_changedvalues.js
@@ -2,27 +2,28 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 let tempScope = {};
 Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
 let CssRuleView = tempScope.CssRuleView;
 let _ElementStyle = tempScope._ElementStyle;
 let _editableField = tempScope._editableField;
+let inplaceEditor = tempScope._getInplaceEditorForSpan;
 
 let doc;
 let ruleDialog;
 let ruleView;
 
 function waitForEditorFocus(aParent, aCallback)
 {
   aParent.addEventListener("focus", function onFocus(evt) {
-    if (evt.target.inplaceEditor) {
+    if (inplaceEditor(evt.target)) {
       aParent.removeEventListener("focus", onFocus, true);
-      let editor = evt.target.inplaceEditor;
+      let editor = inplaceEditor(evt.target);
       executeSoon(function() {
         aCallback(editor);
       });
     }
   }, true);
 }
 
 function waitForEditorBlur(aEditor, aCallback)
@@ -78,17 +79,17 @@ function startTest()
 
 function testCancelNew()
 {
   // Start at the beginning: start to add a rule to the element's style
   // declaration, but leave it empty.
 
   let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
   waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor.");
+    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
     let input = aEditor.input;
     waitForEditorBlur(aEditor, function () {
       ok(!gRuleViewChanged, "Shouldn't get a change event after a cancel.");
       is(elementRuleEditor.rule.textProps.length,  0, "Should have canceled creating a new text property.");
       ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties.");
       testCreateNew();
     });
     aEditor.input.blur();
@@ -99,26 +100,26 @@ function testCancelNew()
                              ruleDialog);
 }
 
 function testCreateNew()
 {
   // Create a new property.
   let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
   waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor.");
+    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
     let input = aEditor.input;
     input.value = "background-color";
 
     waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) {
       expectChange();
       is(elementRuleEditor.rule.textProps.length,  1, "Should have created a new text property.");
       is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor.");
       let textProp = elementRuleEditor.rule.textProps[0];
-      is(aEditor, textProp.editor.valueSpan.inplaceEditor, "Should be editing the value span now.");
+      is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now.");
 
       aEditor.input.value = "#XYZ";
       waitForEditorBlur(aEditor, function() {
         expectChange();
         is(textProp.value, "#XYZ", "Text prop should have been changed.");
         is(textProp.editor._validate(), false, "#XYZ should not be a valid entry");
         testEditProperty();
       });
@@ -132,22 +133,22 @@ function testCreateNew()
                              ruleDialog);
 }
 
 function testEditProperty()
 {
   let idRuleEditor = ruleView.element.children[1]._ruleEditor;
   let propEditor = idRuleEditor.rule.textProps[0].editor;
   waitForEditorFocus(propEditor.element, function onNewElement(aEditor) {
-    is(propEditor.nameSpan.inplaceEditor, aEditor, "Next focused editor should be the name editor.");
+    is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor.");
     let input = aEditor.input;
     waitForEditorFocus(propEditor.element, function onNewName(aEditor) {
       expectChange();
       input = aEditor.input;
-      is(propEditor.valueSpan.inplaceEditor, aEditor, "Focus should have moved to the value.");
+      is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value.");
 
       waitForEditorBlur(aEditor, function() {
         expectChange();
         let value = idRuleEditor.rule.style.getPropertyValue("border-color");
         is(value, "red", "border-color should have been set.");
         is(propEditor._validate(), true, "red should be a valid entry");
         finishTest();
       });
--- a/browser/devtools/styleinspector/test/browser_ruleview_focus.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_focus.js
@@ -1,15 +1,18 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that focus doesn't leave the style editor when adding a property
 // (bug 719916)
 
+let tempScope = {};
+Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
+let inplaceEditor = tempScope._getInplaceEditorForSpan;
 let doc;
 let stylePanel;
 
 function waitForRuleView(aCallback)
 {
   if (InspectorUI.ruleView) {
     aCallback();
     return;
@@ -22,19 +25,19 @@ function waitForRuleView(aCallback)
       aCallback();
     });
   }, true);
 }
 
 function waitForEditorFocus(aParent, aCallback)
 {
   aParent.addEventListener("focus", function onFocus(evt) {
-    if (evt.target.inplaceEditor) {
+    if (inplaceEditor(evt.target)) {
       aParent.removeEventListener("focus", onFocus, true);
-      let editor = evt.target.inplaceEditor;
+      let editor = inplaceEditor(evt.target);
       executeSoon(function() {
         aCallback(editor);
       });
     }
   }, true);
 }
 
 function openRuleView()
--- a/browser/devtools/styleinspector/test/browser_ruleview_ui.js
+++ b/browser/devtools/styleinspector/test/browser_ruleview_ui.js
@@ -2,27 +2,28 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 let tempScope = {}
 Cu.import("resource:///modules/devtools/CssRuleView.jsm", tempScope);
 let CssRuleView = tempScope.CssRuleView;
 let _ElementStyle = tempScope._ElementStyle;
 let _editableField = tempScope._editableField;
+let inplaceEditor = tempScope._getInplaceEditorForSpan;
 
 let doc;
 let ruleDialog;
 let ruleView;
 
 function waitForEditorFocus(aParent, aCallback)
 {
   aParent.addEventListener("focus", function onFocus(evt) {
-    if (evt.target.inplaceEditor) {
+    if (inplaceEditor(evt.target)) {
       aParent.removeEventListener("focus", onFocus, true);
-      let editor = evt.target.inplaceEditor;
+      let editor = inplaceEditor(evt.target);
       executeSoon(function() {
         aCallback(editor);
       });
     }
   }, true);
 }
 
 function waitForEditorBlur(aEditor, aCallback)
@@ -78,17 +79,17 @@ function startTest()
 
 function testCancelNew()
 {
   // Start at the beginning: start to add a rule to the element's style
   // declaration, but leave it empty.
 
   let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
   waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor.");
+    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
     let input = aEditor.input;
     waitForEditorBlur(aEditor, function () {
       ok(!gRuleViewChanged, "Shouldn't get a change event after a cancel.");
       is(elementRuleEditor.rule.textProps.length,  0, "Should have canceled creating a new text property.");
       ok(!elementRuleEditor.propertyList.hasChildNodes(), "Should not have any properties.");
       testCreateNew();
     });
     aEditor.input.blur();
@@ -99,26 +100,26 @@ function testCancelNew()
                              ruleDialog);
 }
 
 function testCreateNew()
 {
   // Create a new property.
   let elementRuleEditor = ruleView.element.children[0]._ruleEditor;
   waitForEditorFocus(elementRuleEditor.element, function onNewElement(aEditor) {
-    is(elementRuleEditor.newPropSpan.inplaceEditor, aEditor, "Next focused editor should be the new property editor.");
+    is(inplaceEditor(elementRuleEditor.newPropSpan), aEditor, "Next focused editor should be the new property editor.");
     let input = aEditor.input;
     input.value = "background-color";
 
     waitForEditorFocus(elementRuleEditor.element, function onNewValue(aEditor) {
       expectChange();
       is(elementRuleEditor.rule.textProps.length,  1, "Should have created a new text property.");
       is(elementRuleEditor.propertyList.children.length, 1, "Should have created a property editor.");
       let textProp = elementRuleEditor.rule.textProps[0];
-      is(aEditor, textProp.editor.valueSpan.inplaceEditor, "Should be editing the value span now.");
+      is(aEditor, inplaceEditor(textProp.editor.valueSpan), "Should be editing the value span now.");
 
       aEditor.input.value = "purple";
       waitForEditorBlur(aEditor, function() {
         expectChange();
         is(textProp.value, "purple", "Text prop should have been changed.");
         testEditProperty();
       });
 
@@ -132,22 +133,22 @@ function testCreateNew()
                              ruleDialog);
 }
 
 function testEditProperty()
 {
   let idRuleEditor = ruleView.element.children[1]._ruleEditor;
   let propEditor = idRuleEditor.rule.textProps[0].editor;
   waitForEditorFocus(propEditor.element, function onNewElement(aEditor) {
-    is(propEditor.nameSpan.inplaceEditor, aEditor, "Next focused editor should be the name editor.");
+    is(inplaceEditor(propEditor.nameSpan), aEditor, "Next focused editor should be the name editor.");
     let input = aEditor.input;
     waitForEditorFocus(propEditor.element, function onNewName(aEditor) {
       expectChange();
       input = aEditor.input;
-      is(propEditor.valueSpan.inplaceEditor, aEditor, "Focus should have moved to the value.");
+      is(inplaceEditor(propEditor.valueSpan), aEditor, "Focus should have moved to the value.");
 
       waitForEditorBlur(aEditor, function() {
         expectChange();
         is(idRuleEditor.rule.style.getPropertyValue("border-color"), "red",
            "border-color should have been set.");
         testDisableProperty();
       });
 
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -168,16 +168,17 @@
 @BINPATH@/components/dom_network.xpt
 @BINPATH@/components/dom_notification.xpt
 @BINPATH@/components/dom_html.xpt
 @BINPATH@/components/dom_indexeddb.xpt
 @BINPATH@/components/dom_offline.xpt
 @BINPATH@/components/dom_json.xpt
 @BINPATH@/components/dom_power.xpt
 @BINPATH@/components/dom_range.xpt
+@BINPATH@/components/dom_settings.xpt
 @BINPATH@/components/dom_sidebar.xpt
 @BINPATH@/components/dom_sms.xpt
 @BINPATH@/components/dom_storage.xpt
 @BINPATH@/components/dom_stylesheets.xpt
 @BINPATH@/components/dom_traversal.xpt
 @BINPATH@/components/dom_xbl.xpt
 @BINPATH@/components/dom_xpath.xpt
 @BINPATH@/components/dom_xul.xpt
@@ -414,16 +415,18 @@
 #ifdef MOZ_SERVICES_SYNC
 @BINPATH@/components/SyncComponents.manifest
 @BINPATH@/components/Weave.js
 #endif
 @BINPATH@/components/TelemetryPing.js
 @BINPATH@/components/TelemetryPing.manifest
 @BINPATH@/components/messageWakeupService.js
 @BINPATH@/components/messageWakeupService.manifest
+@BINPATH@/components/SettingsManager.js
+@BINPATH@/components/SettingsManager.manifest
 @BINPATH@/components/Webapps.js
 @BINPATH@/components/Webapps.manifest
 
 @BINPATH@/components/ContactManager.js
 @BINPATH@/components/ContactManager.manifest
 
 ; Modules
 @BINPATH@/modules/*
--- a/browser/installer/windows/nsis/installer.nsi
+++ b/browser/installer/windows/nsis/installer.nsi
@@ -98,17 +98,17 @@ Var PageName
 !include locales.nsi
 
 VIAddVersionKey "FileDescription" "${BrandShortName} Installer"
 VIAddVersionKey "OriginalFilename" "setup.exe"
 
 ; Must be inserted before other macros that use logging
 !insertmacro _LoggingCommon
 
-!insertmacro AddDDEHandlerValues
+!insertmacro AddDisabledDDEHandlerValues
 !insertmacro ChangeMUIHeaderImage
 !insertmacro CheckForFilesInUse
 !insertmacro CleanUpdatesDir
 !insertmacro CopyFilesFromDir
 !insertmacro CreateRegKey
 !insertmacro GetPathFromString
 !insertmacro GetParent
 !insertmacro InitHashAppModelId
@@ -347,27 +347,25 @@ Section "-Application" APP_IDX
 
   ${FixClassKeys}
 
   ; Uninstall keys can only exist under HKLM on some versions of windows. Since
   ; it doesn't cause problems always add them.
   ${SetUninstallKeys}
 
   ; On install always add the FirefoxHTML and FirefoxURL keys.
-  ; An empty string is used for the 5th param because FirefoxHTML and FirefoxURL
-  ; are not protocol handlers.
+  ; An empty string is used for the 5th param because FirefoxHTML is not a
+  ; protocol handler.
   ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
-  StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\""
-  StrCpy $3 "$\"%1$\",,0,0,,,,"
+  StrCpy $2 "$\"$8$\" -osint -url $\"%1$\""
 
-  ${AddDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" "${AppRegName} Document" "" \
-                         "${DDEApplication}" "$3" "WWW_OpenURL"
-
-  ${AddDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" "true" \
-                         "${DDEApplication}" "$3" "WWW_OpenURL"
+  ${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \
+                                 "${AppRegName} Document" ""
+  ${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" \
+                                 "true"
 
   ; The following keys should only be set if we can write to HKLM
   ${If} $TmpVal == "HKLM"
     ; Set the Start Menu Internet and Vista Registered App HKLM registry keys.
     ${SetStartMenuInternet}
     ${FixShellIconHandler}
 
     ; If we are writing to HKLM and create either the desktop or start menu
--- a/browser/installer/windows/nsis/shared.nsh
+++ b/browser/installer/windows/nsis/shared.nsh
@@ -74,17 +74,17 @@
     ${StrFilter} "${FileMainEXE}" "+" "" "" $1
     ReadRegStr $0 HKLM "Software\Clients\StartMenuInternet\$1\DefaultIcon" ""
     ${GetPathFromString} "$0" $0
     ${GetParent} "$0" $0
     ${If} ${FileExists} "$0"
       ${GetLongPath} "$0" $0
     ${EndIf}
     ${If} "$0" == "$INSTDIR"
-      ${SetStartMenuInternet}
+      ${SetStartMenuInternet} ; Does not use SHCTX
     ${EndIf}
 
     ReadRegStr $0 HKLM "Software\mozilla.org\Mozilla" "CurrentVersion"
     ${If} "$0" != "${GREVersion}"
       WriteRegStr HKLM "Software\mozilla.org\Mozilla" "CurrentVersion" "${GREVersion}"
     ${EndIf}
   ${EndIf}
 
@@ -151,22 +151,22 @@
     ${EndIf}
   ${EndIf}
 !endif
 
 !macroend
 !define PostUpdate "!insertmacro PostUpdate"
 
 !macro SetAsDefaultAppGlobal
-  ${RemoveDeprecatedKeys}
+  ${RemoveDeprecatedKeys} ; Does not use SHCTX
 
   SetShellVarContext all      ; Set SHCTX to all users (e.g. HKLM)
-  ${SetHandlers}
-  ${SetStartMenuInternet}
-  ${FixShellIconHandler}
+  ${SetHandlers} ; Uses SHCTX
+  ${SetStartMenuInternet} ; Does not use SHCTX
+  ${FixShellIconHandler} ; Does not use SHCTX
   ${ShowShortcuts}
   ${StrFilter} "${FileMainEXE}" "+" "" "" $R9
   WriteRegStr HKLM "Software\Clients\StartMenuInternet" "" "$R9"
 !macroend
 !define SetAsDefaultAppGlobal "!insertmacro SetAsDefaultAppGlobal"
 
 ; Removes shortcuts for this installation. This should also remove the
 ; application from Open With for the file types the application handles
@@ -301,17 +301,17 @@
 !define ShowShortcuts "!insertmacro ShowShortcuts"
 
 ; Adds the protocol and file handler registry entries for making Firefox the
 ; default handler (uses SHCTX).
 !macro SetHandlers
   ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
 
   StrCpy $0 "SOFTWARE\Classes"
-  StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\""
+  StrCpy $2 "$\"$8$\" -osint -url $\"%1$\""
 
   ; Associate the file handlers with FirefoxHTML
   ReadRegStr $6 SHCTX "$0\.htm" ""
   ${If} "$6" != "FirefoxHTML"
     WriteRegStr SHCTX "$0\.htm"   "" "FirefoxHTML"
   ${EndIf}
 
   ReadRegStr $6 SHCTX "$0\.html" ""
@@ -335,35 +335,30 @@
   ${EndIf}
 
   ; Only add webm if it's not present
   ${CheckIfRegistryKeyExists} "$0" ".webm" $7
   ${If} $7 == "false"
     WriteRegStr SHCTX "$0\.webm"  "" "FirefoxHTML"
   ${EndIf}
 
-  StrCpy $3 "$\"%1$\",,0,0,,,,"
-
   ; An empty string is used for the 5th param because FirefoxHTML is not a
   ; protocol handler
-  ${AddDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" "${AppRegName} HTML Document" "" \
-                         "${DDEApplication}" "$3" "WWW_OpenURL"
+  ${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \
+                                 "${AppRegName} HTML Document" ""
 
-  ${AddDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" "true" \
-                         "${DDEApplication}" "$3" "WWW_OpenURL"
+  ${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" \
+                                 "true"
 
   ; An empty string is used for the 4th & 5th params because the following
   ; protocol handlers already have a display name and the additional keys
   ; required for a protocol handler.
-  ${AddDDEHandlerValues} "ftp" "$2" "$8,1" "" "" \
-                         "${DDEApplication}" "$3" "WWW_OpenURL"
-  ${AddDDEHandlerValues} "http" "$2" "$8,1" "" "" \
-                         "${DDEApplication}" "$3" "WWW_OpenURL"
-  ${AddDDEHandlerValues} "https" "$2" "$8,1" "" "" \
-                         "${DDEApplication}" "$3" "WWW_OpenURL"
+  ${AddDisabledDDEHandlerValues} "ftp" "$2" "$8,1" "" ""
+  ${AddDisabledDDEHandlerValues} "http" "$2" "$8,1" "" ""
+  ${AddDisabledDDEHandlerValues} "https" "$2" "$8,1" "" ""
 !macroend
 !define SetHandlers "!insertmacro SetHandlers"
 
 ; Adds the HKLM\Software\Clients\StartMenuInternet\FIREFOX.EXE registry
 ; entries (does not use SHCTX).
 ;
 ; The values for StartMenuInternet are only valid under HKLM and there can only
 ; be one installation registerred under StartMenuInternet per application since
@@ -562,52 +557,51 @@
 !macroend
 !define FixClassKeys "!insertmacro FixClassKeys"
 
 ; Updates protocol handlers if their registry open command value is for this
 ; install location (uses SHCTX).
 !macro UpdateProtocolHandlers
   ; Store the command to open the app with an url in a register for easy access.
   ${GetLongPath} "$INSTDIR\${FileMainEXE}" $8
-  StrCpy $2 "$\"$8$\" -requestPending -osint -url $\"%1$\""
-  StrCpy $3 "$\"%1$\",,0,0,,,,"
+  StrCpy $2 "$\"$8$\" -osint -url $\"%1$\""
 
   ; Only set the file and protocol handlers if the existing one under HKCR is
   ; for this install location.
 
   ${IsHandlerForInstallDir} "FirefoxHTML" $R9
   ${If} "$R9" == "true"
     ; An empty string is used for the 5th param because FirefoxHTML is not a
     ; protocol handler.
-    ${AddDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" "${AppRegName} HTML Document" "" \
-                           "${DDEApplication}" "$3" "WWW_OpenURL"
+    ${AddDisabledDDEHandlerValues} "FirefoxHTML" "$2" "$8,1" \
+                                   "${AppRegName} HTML Document" ""
   ${EndIf}
 
   ${IsHandlerForInstallDir} "FirefoxURL" $R9
   ${If} "$R9" == "true"
-    ${AddDDEHandlerValues} "FirefoxURL" "$2" "$8,1" "${AppRegName} URL" "true" \
-                           "${DDEApplication}" "$3" "WWW_OpenURL"
+    ${AddDisabledDDEHandlerValues} "FirefoxURL" "$2" "$8,1" \
+                                   "${AppRegName} URL" "true"
   ${EndIf}
 
+  ; An empty string is used for the 4th & 5th params because the following
+  ; protocol handlers already have a display name and the additional keys
+  ; required for a protocol handler.
   ${IsHandlerForInstallDir} "ftp" $R9
   ${If} "$R9" == "true"
-    ${AddDDEHandlerValues} "ftp" "$2" "$8,1" "" "" \
-                           "${DDEApplication}" "$3" "WWW_OpenURL"
+    ${AddDisabledDDEHandlerValues} "ftp" "$2" "$8,1" "" ""
   ${EndIf}
 
   ${IsHandlerForInstallDir} "http" $R9
   ${If} "$R9" == "true"
-    ${AddDDEHandlerValues} "http" "$2" "$8,1" "" "" \
-                           "${DDEApplication}" "$3" "WWW_OpenURL"
+    ${AddDisabledDDEHandlerValues} "http" "$2" "$8,1" "" ""
   ${EndIf}
 
   ${IsHandlerForInstallDir} "https" $R9
   ${If} "$R9" == "true"
-    ${AddDDEHandlerValues} "https" "$2" "$8,1" "" "" \
-                           "${DDEApplication}" "$3" "WWW_OpenURL"
+    ${AddDisabledDDEHandlerValues} "https" "$2" "$8,1" "" ""
   ${EndIf}
 !macroend
 !define UpdateProtocolHandlers "!insertmacro UpdateProtocolHandlers"
 
 !ifdef MOZ_MAINTENANCE_SERVICE
 ; Adds maintenance service certificate keys for the install dir.
 ; For the cert to work, it must also be signed by a trusted cert for the user.
 !macro AddMaintCertKeys
@@ -1159,21 +1153,23 @@ Function SetAsDefaultAppUser
   ${EndUnless}
 
   ; The code after ElevateUAC won't be executed on Vista and above when the
   ; user:
   ; a) is a member of the administrators group (e.g. elevation is required)
   ; b) is not a member of the administrators group and chooses to elevate
   ${ElevateUAC}
 
-  ${SetStartMenuInternet}
+  ${SetStartMenuInternet} ; Does not use SHCTX
 
   SetShellVarContext all  ; Set SHCTX to all users (e.g. HKLM)
-  ${FixShellIconHandler}
-  ${RemoveDeprecatedKeys}
+
+  ${FixClassKeys} ; Does not use SHCTX
+  ${FixShellIconHandler} ; Does not use SHCTX
+  ${RemoveDeprecatedKeys} ; Does not use SHCTX
 
   ClearErrors
   ${GetParameters} $0
   ${GetOptions} "$0" "/UAC:" $0
   ${If} ${Errors}
     Call SetAsDefaultAppUserHKCU
   ${Else}
     GetFunctionAddress $0 SetAsDefaultAppUserHKCU
--- a/browser/installer/windows/nsis/uninstaller.nsi
+++ b/browser/installer/windows/nsis/uninstaller.nsi
@@ -87,17 +87,17 @@ Var MaintCertKey
 !include common.nsh
 !include locales.nsi
 
 ; This is named BrandShortName helper because we use this for software update
 ; post update cleanup.
 VIAddVersionKey "FileDescription" "${BrandShortName} Helper"
 VIAddVersionKey "OriginalFilename" "helper.exe"
 
-!insertmacro AddDDEHandlerValues
+!insertmacro AddDisabledDDEHandlerValues
 !insertmacro CleanVirtualStore
 !insertmacro ElevateUAC
 !insertmacro GetLongPath
 !insertmacro GetPathFromString
 !insertmacro InitHashAppModelId
 !insertmacro IsHandlerForInstallDir
 !insertmacro IsPinnedToTaskBar
 !insertmacro IsUserAdmin
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -336,27 +336,12 @@ telemetryNoButtonLabel = No
 telemetryNoButtonAccessKey = N
 
 # Webapps notification popup
 webapps.install = Install
 webapps.install.accesskey = I
 #LOCALIZATION NOTE (webapps.requestInstall) %1$S is the web app name, %2$S is the site from which the web app is installed
 webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
 
-# Keyword.URL reset prompt
-# LOCALIZATION NOTE (keywordPrompt.message):
-#  - %1$S is brandShortName
-#  - %2$S is a host name (e.g. "somewebsearch.com") from the current value of keyword.URL
-#  - %3$S is the name of the default search engine (e.g. "Google")
-keywordPrompt.message = %1$S is using '%2$S' for searches from the location bar. Would you like to restore the default search (%3$S)?
-
-# LOCALIZATION NOTE (keywordPrompt.yesButton): %1$S is the name of the default search engine
-keywordPrompt.yesButton = Yes, use %1$S
-keywordPrompt.yesButton.accessKey = Y
-
-# LOCALIZATION NOTE (keywordPrompt.noButton): %1$S is a host name (e.g. "somewebsearch.com") from the current value of keyword.URL
-keywordPrompt.noButton = No, continue using '%1$S'
-keywordPrompt.noButton.accessKey  = N
-
 # Telemetry opt-out prompt for Aurora and Nightly
 # LOCALIZATION NOTE (telemetryOptOutPrompt): %1$S and %3$S will be replaced by
 # brandFullName, and %2$S by the value of the toolkit.telemetry.server_owner preference.
 telemetryOptOutPrompt = %1$S sends information about performance, hardware, usage and customizations back to %2$S to help improve %3$S.
--- a/browser/makefiles.sh
+++ b/browser/makefiles.sh
@@ -97,17 +97,17 @@ security/manager/locales/Makefile
 "
 
 if [ "$MOZ_SAFE_BROWSING" ]; then
   add_makefiles "
     browser/components/safebrowsing/Makefile
   "
 fi
 
-if [ "$MOZ_WIDGET_TOOLKIT" = "windows" ]; then
+if [ "$MAKENSISU" ]; then
   add_makefiles "
     browser/installer/windows/Makefile
   "
 fi
 
 if [ "$MOZ_WIDGET_TOOLKIT" = "gtk2" -o "$MOZ_WIDGET_TOOLKIT" = "qt" ]; then
   add_makefiles "
     browser/themes/gnomestripe/Makefile
deleted file mode 100644
--- a/browser/modules/KeywordURLResetPrompter.jsm
+++ /dev/null
@@ -1,106 +0,0 @@
-/* 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/. */
-
-let EXPORTED_SYMBOLS = [ "KeywordURLResetPrompter" ];
-
-const Ci = Components.interfaces;
-const Cc = Components.classes;
-const Cu = Components.utils;
-
-Cu.import("resource://gre/modules/Services.jsm");
-
-const KEYWORD_PROMPT_REV = 1;
-
-let KeywordURLResetPrompter = {
-  get shouldPrompt() {
-    let keywordURLUserSet = Services.prefs.prefHasUserValue("keyword.URL");
-    let declinedRev;
-    try {
-      declinedRev = Services.prefs.getIntPref("browser.keywordURLPromptDeclined");
-    } catch (ex) {}
-
-    return keywordURLUserSet && declinedRev != KEYWORD_PROMPT_REV;
-  },
-
-  prompt: function KeywordURLResetPrompter_prompt(win, keywordURI) {
-    let tabbrowser = win.gBrowser;
-    let notifyBox = tabbrowser.getNotificationBox();
-
-    let existingNotification = notifyBox.getNotificationWithValue("keywordURL-reset");
-    if (existingNotification)
-      return;
-
-    // Find the name/URI of this build's original default engine.
-    // XXX: Can't use originalDefaultEngine getter here, because that doesn't
-    //      use the default pref branch.
-    let defaultURI;
-    let defaultEngine;
-    try {
-      let defaultPB = Services.prefs.getDefaultBranch(null);
-      let defaultName = defaultPB.getComplexValue("browser.search.defaultenginename",
-                                                  Ci.nsIPrefLocalizedString).data;
-      defaultEngine = Services.search.getEngineByName(defaultName);
-      defaultURI = defaultEngine.getSubmission("foo").uri;
-    } catch (ex) {
-      // Something went horribly wrong! bail out
-      return;
-    }
-
-    // If the user-set value has the same base domain as the default, don't
-    // prompt.
-    let keywordBaseDomain;
-    try {
-      keywordBaseDomain = Services.eTLD.getBaseDomain(keywordURI);
-      if (keywordBaseDomain == Services.eTLD.getBaseDomain(defaultURI))
-        return;
-    } catch (ex) {}
-
-    if (!keywordBaseDomain)
-      return;
-
-    let brandBundle  = Services.strings.createBundle("chrome://branding/locale/brand.properties");
-    let brandShortName = brandBundle.GetStringFromName("brandShortName");
-
-    let browserBundle = win.gNavigatorBundle;
-    let msg = browserBundle.getFormattedString("keywordPrompt.message",
-                                               [brandShortName, keywordBaseDomain,
-                                                defaultEngine.name]);
-    let buttons = [
-      {
-        label: browserBundle.getFormattedString("keywordPrompt.yesButton",
-                                                [defaultEngine.name]),
-        accessKey: browserBundle.getString("keywordPrompt.yesButton.accessKey"),
-        popup:     null,
-        callback: function(aNotificationBar, aButton) {
-          Services.prefs.clearUserPref("keyword.URL");
-          Services.prefs.clearUserPref("browser.search.defaultenginename");
-          try {
-            // If the currently loaded URI still has the same base domain as the
-            // keyword URI (this is used as a rough approximation of whether the
-            // user is still seeing search results as opposed to having clicked
-            // on a result link), load the default engine's searchForm URL so
-            // that they can re-do their search.
-            let currentBaseDomain = Services.eTLD.getBaseDomain(tabbrowser.currentURI);
-            if (currentBaseDomain == keywordBaseDomain)
-              tabbrowser.loadURI(defaultEngine.searchForm);
-          } catch (ex) {}
-        }
-      },
-      {
-        label: browserBundle.getFormattedString("keywordPrompt.noButton",
-                                                [keywordBaseDomain]),
-        accessKey: browserBundle.getString("keywordPrompt.noButton.accessKey"),
-        popup:     null,
-        callback: function(aNotificationBar, aButton) {
-          Services.prefs.setIntPref("browser.keywordURLPromptDeclined", KEYWORD_PROMPT_REV);
-        }
-      }
-    ];
-    
-    let notification = notifyBox.appendNotification(msg, "keywordURL-reset", null, notifyBox.PRIORITY_WARNING_HIGH, buttons);
-    notification.setAttribute("hideclose", true);
-    // stick around for a few page loads in case there are redirects involved
-    notification.persistence = 3;
-  }
-}
--- a/browser/modules/Makefile.in
+++ b/browser/modules/Makefile.in
@@ -47,17 +47,16 @@ include $(topsrcdir)/config/config.mk
 TEST_DIRS += test
 
 EXTRA_JS_MODULES = \
 	openLocationLastURL.jsm \
 	NetworkPrioritizer.jsm \
 	NewTabUtils.jsm \
 	offlineAppCache.jsm \
 	TelemetryTimestamps.jsm \
-	KeywordURLResetPrompter.jsm \
 	webappsUI.jsm \
 	$(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows) 
 EXTRA_JS_MODULES += \
 	WindowsPreviewPerTab.jsm \
 	WindowsJumpLists.jsm \
 	$(NULL)
--- a/browser/modules/test/Makefile.in
+++ b/browser/modules/test/Makefile.in
@@ -41,17 +41,16 @@ VPATH		= @srcdir@
 relativesrcdir  = browser/modules/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_FILES = \
                  browser_NetworkPrioritizer.js \
                  browser_TelemetryTimestamps.js \
-                 browser_keywordURLReset.js \
                  $(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows) 
 _BROWSER_FILES += \
                  browser_taskbar_preview.js \
                  $(NULL)
 endif
 
deleted file mode 100644
--- a/browser/modules/test/browser_keywordURLReset.js
+++ /dev/null
@@ -1,110 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-function test() {
-  waitForExplicitFinish();
-
-  let newTab = gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true});
-  registerCleanupFunction(function () {
-    gBrowser.removeTab(newTab);
-    Services.prefs.clearUserPref("keyword.URL");
-    Services.prefs.clearUserPref("browser.search.defaultenginename");
-  });
-
-  function onKeywordPrefUse(cb) {
-    Services.obs.addObserver(function obs() {
-      Services.obs.removeObserver(obs, "defaultURIFixup-using-keyword-pref");
-      executeSoon(function () {
-        let nbox = gBrowser.getNotificationBox();
-        let notification = nbox.getNotificationWithValue("keywordURL-reset");
-        cb(notification);
-      });
-    }, "defaultURIFixup-using-keyword-pref", false);
-  }
-
-  function testQuery(cb) {
-    onKeywordPrefUse(cb);
-    gURLBar.focus();
-    gURLBar.value = "foo bar";
-    gURLBar.handleCommand();
-  }
-
-  function setKeywordURL(value) {
-    Services.prefs.setCharPref("keyword.URL", value);
-    let keywordURI = XULBrowserWindow._uriFixup.keywordToURI("foo bar");
-    is(keywordURI.spec, value + "foo+bar", "keyword.URL was set to " + value);
-  }
-
-  // Before modifying any prefs, get a submission object for this build's
-  // actual default engine for verification of the "Reset" functionality.
-  let originalDefaultEngine = Services.search.originalDefaultEngine;
-  let defaultSubmission = originalDefaultEngine.getSubmission("foo bar", "application/x-moz-keywordsearch");
-  if (!defaultSubmission)
-    defaultSubmission = originalDefaultEngine.getSubmission("foo bar");
-
-  var tests = [
-    {
-      name: "similar URL that shouldn't trigger prompt",
-      setup: function () {
-        setKeywordURL(defaultSubmission.uri.prePath + "/othersearch");
-      },
-      check: function (notification) {
-        ok(!notification, "didn't get a search reset notification");
-      }
-    },
-    {
-      name: "URL that should trigger prompt",
-      setup: function () {
-        // First clear any values from the previous test so that we can verify
-        // that the dummy default engine we're adding below has an effect.
-        Services.prefs.clearUserPref("keyword.URL");
-
-        // Add a dummy "default engine" to verify that the "reset" actually
-        // resets the originalDefaultEngine too (and not just keyword.URL)
-        Services.search.addEngineWithDetails("TestEngine", "", "", "", "GET", "http://mochi.test/test?q={searchTerms}");
-        Services.prefs.setCharPref("browser.search.defaultenginename", "TestEngine");
-
-        // Check that it was added successfully
-        let engine = Services.search.getEngineByName("TestEngine");
-        ok(engine, "added engine successfully");
-        registerCleanupFunction(function () {
-          Services.search.removeEngine(engine);
-        });
-        is(Services.search.originalDefaultEngine, engine, "engine is now the originalDefaultEngine");
-        let keywordURI = XULBrowserWindow._uriFixup.keywordToURI("foo bar");
-        is(keywordURI.spec, "http://mochi.test/test?q=foo+bar", "default engine affects keywordToURI");
-
-        setKeywordURL("http://invalid.foo/search/");
-      },
-      check: function (notification) {
-        ok(notification, "got a search reset notification");
-
-        // Press the "reset" button
-        notification.getElementsByTagName("button").item(0).click();
-
-        // Check that the reset worked
-        let keywordURI = XULBrowserWindow._uriFixup.keywordToURI("foo bar");
-        is(keywordURI.spec, defaultSubmission.uri.spec,
-           "keyword.URL came from original default engine after reset");
-      }
-    }
-  ];
-
-  function nextTest() {
-    let test = tests.shift();
-    if (!test) {
-      finish();
-      return;
-    }
-
-    info("Running test: " + test.name);
-    test.setup();
-    testQuery(function (notification) {
-      test.check(notification);
-      executeSoon(nextTest);
-    });
-  }
-  
-  nextTest();
-}
-
--- a/browser/themes/winstripe/browser-aero.css
+++ b/browser/themes/winstripe/browser-aero.css
@@ -61,16 +61,20 @@
   }
 
   #main-window[tabsontop=false]:not([disablechrome]) .tabbrowser-tab[selected=true]:not(:-moz-lwtheme) {
     background-image: @toolbarShadowOnTab@,
                       -moz-linear-gradient(white, @toolbarHighlight@ 50%),
                       -moz-linear-gradient(@customToolbarColor@, @customToolbarColor@);
   }
 
+  #navigator-toolbox:not(:-moz-lwtheme)::after {
+    background-color: #aabccf;
+  }
+
   #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme),
   #navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme) {
     border-color: hsla(210,54%,20%,.25) hsla(210,54%,20%,.27) hsla(210,54%,20%,.3);
   }
 
   #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme):not([focused]):hover,
   #navigator-toolbox[tabsontop=true] .searchbar-textbox:not(:-moz-lwtheme):not([focused]):hover {
     border-color: hsla(210,54%,20%,.35) hsla(210,54%,20%,.37) hsla(210,54%,20%,.4);
@@ -205,17 +209,17 @@
   }
 
   /* Toolbar shadow behind tabs */
   /* This code is only needed for restored windows (i.e. sizemode=normal)
      because of the border radius on the toolbar below the tab bar. */
   #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar:not(:-moz-lwtheme),
   #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + toolbar:not(:-moz-lwtheme),
   #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > #nav-bar[collapsed=true]:not([customizing]) + #customToolbars + #PersonalToolbar:not(:-moz-lwtheme),
-  #main-window[sizemode=normal][tabsontop=true][disablechrome] #navigator-toolbox:not(:-moz-lwtheme)::after {
+  #main-window[sizemode=normal][disablechrome] #navigator-toolbox[tabsontop=true]:not(:-moz-lwtheme)::after {
     border-top: 1px solid @toolbarShadowColor@;
     border-top-left-radius: 2.5px;
     border-top-right-radius: 2.5px;
     background-clip: padding-box;
   }
   #main-window[sizemode=normal] #TabsToolbar[tabsontop=true]:not(:-moz-lwtheme) {
     margin-bottom: -1px;
     background-image: none !important;
@@ -239,17 +243,17 @@
   }
 
   #main-window[sizemode=normal] #TabsToolbar[tabsontop=false] {
     padding-left: 2px;
     padding-right: 2px;
   }
 
   /* Rounded corners for when chrome is disabled */
-  #main-window[sizemode=normal][tabsontop=true][disablechrome] #navigator-toolbox:not(:-moz-lwtheme)::after {
+  #main-window[sizemode=normal][disablechrome] #navigator-toolbox[tabsontop=true]:not(:-moz-lwtheme)::after {
     visibility: visible;
     background-color: @customToolbarColor@;
     background-image: -moz-linear-gradient(@toolbarHighlight@, @toolbarHighlight@);
     height: 4px;
   }
 
   /* Make the window draggable by glassed toolbars (bug 555081) */
   #toolbar-menubar:not([autohide="true"]),
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -1143,17 +1143,17 @@ toolbar[mode=full] .toolbarbutton-1 > .t
 /* feed button */
 
 #feed-button {
   -moz-image-region: rect(0, 342px, 18px, 324px);
 }
 
 /* ::::: fullscreen window controls ::::: */
 
-#TabsToolbar > #window-controls {
+#window-controls {
   -moz-margin-start: 4px;
 }
 
 #minimize-button,
 #restore-button,
 #close-button {
   list-style-image: url("chrome://global/skin/icons/windowControls.png");
   padding: 0;
--- a/build/mobile/robocop/Assert.java.in
+++ b/build/mobile/robocop/Assert.java.in
@@ -36,16 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package @ANDROID_PACKAGE_NAME@;
 
 public interface Assert {
     void dumpLog(String message);
+    void dumpLog(String message, Throwable t);
     void setLogFile(String filename);
     void setTestName(String testName);
 
     void finalize();
     void ok(boolean condition, String name, String diag);
     void is(Object a, Object b, String name);
     void isnot(Object a, Object b, String name);
     void todo(boolean condition, String name, String diag);
--- a/build/mobile/robocop/FennecMochitestAssert.java.in
+++ b/build/mobile/robocop/FennecMochitestAssert.java.in
@@ -61,16 +61,21 @@ public class FennecMochitestAssert imple
     public FennecMochitestAssert() {
     }
 
     /** Write information to a logfile and logcat */
     public void dumpLog(String message) {
         FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
     }
 
+    /** Write information to a logfile and logcat */
+    public void dumpLog(String message, Throwable t) {
+        FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
+    }
+
     /** Set the filename used for dumpLog. */
     public void setLogFile(String filename) {
         FennecNativeDriver.setLogFile(filename);
 
         String message;
         if (!mLogStarted) {
             dumpLog(Integer.toString(mLineNumber++) + " INFO SimpleTest START");
             mLogStarted = true;
--- a/build/mobile/robocop/FennecNativeDriver.java.in
+++ b/build/mobile/robocop/FennecNativeDriver.java.in
@@ -36,24 +36,24 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 package @ANDROID_PACKAGE_NAME@;
 
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
-import java.io.BufferedWriter;
 import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.PrintWriter;
 import java.nio.IntBuffer;
 import java.util.HashMap;
 import java.util.List;
 
 import java.lang.Class;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
@@ -454,46 +454,53 @@ public class FennecNativeDriver implemen
         }
     }
 
     public static void setLogLevel(LogLevel level) {
         mLogLevel = level;
     }
 
     public static void log(LogLevel level, String message) {
+        log(level, message, null);
+    }
+
+    public static void log(LogLevel level, Throwable t) {
+        log(level, null, t);
+    }
+
+    public static void log(LogLevel level, String message, Throwable t) {
         if (mLogFile == null) {
             assert(false);
         }
 
         if (level.isEnabled(mLogLevel)) {
-            File file = new File(mLogFile);
-            BufferedWriter bw = null;
-
+            PrintWriter pw = null;
             try {
-                bw = new BufferedWriter(new FileWriter(mLogFile, true));
-                bw.write(message);
-                bw.newLine();
-            } catch(IOException e) {
+                pw = new PrintWriter(new FileWriter(mLogFile, true));
+                if (message != null) {
+                    pw.println(message);
+                }
+                if (t != null) {
+                    t.printStackTrace(pw);
+                }
+            } catch (IOException ioe) {
                 Log.e("Robocop", "exception with file writer on: " + mLogFile);
             } finally {
-                try {
-                    if (bw != null) {
-                        bw.flush();
-                        bw.close();
-                    }
-                } catch (IOException ex) {
-                    ex.printStackTrace();
-                }
+                pw.close();
+            }
+            // PrintWriter doesn't throw IOE but sets an error flag instead,
+            // so check for that
+            if (pw.checkError()) {
+                Log.e("Robocop", "exception with file writer on: " + mLogFile);
             }
         }
 
         if (level == LogLevel.LOG_LEVEL_INFO) {
-            Log.i("Robocop", message);
+            Log.i("Robocop", message, t);
         } else if (level == LogLevel.LOG_LEVEL_DEBUG) {
-            Log.d("Robocop", message);
+            Log.d("Robocop", message, t);
         } else if (level == LogLevel.LOG_LEVEL_WARN) {
-            Log.w("Robocop", message);
+            Log.w("Robocop", message, t);
         } else if (level == LogLevel.LOG_LEVEL_ERROR) {
-            Log.e("Robocop", message);
+            Log.e("Robocop", message, t);
         }
     }
-
 }
--- a/build/mobile/robocop/FennecTalosAssert.java.in
+++ b/build/mobile/robocop/FennecTalosAssert.java.in
@@ -44,16 +44,21 @@ public class FennecTalosAssert implement
 
     /**
      *  Write information to a logfile and logcat
      */
     public void dumpLog(String message) {
         FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message);
     }
 
+    /** Write information to a logfile and logcat */
+    public void dumpLog(String message, Throwable t) {
+        FennecNativeDriver.log(FennecNativeDriver.LogLevel.LOG_LEVEL_INFO, message, t);
+    }
+
     /**
      *  Set the filename used for dumpLog.
      */
     public void setLogFile(String filename) {
         FennecNativeDriver.setLogFile(filename);
     }
 
     public void setTestName(String testName) { }
--- a/build/mobile/robocop/Makefile.in
+++ b/build/mobile/robocop/Makefile.in
@@ -122,18 +122,18 @@ tools:: robocop.apk
 classes.dex: robocop.ap_
 classes.dex: $(_ROBOCOP_TOOLS)
 classes.dex: $(_JAVA_HARNESS)
 classes.dex: $(_JAVA_TESTS)
 	$(NSINSTALL) -D classes
 	$(JAVAC) $(JAVAC_FLAGS) -d classes $(JAVAFILES) $(_JAVA_HARNESS) $(addprefix $(DEPTH)/mobile/android/base/tests/,$(_JAVA_TESTS))
 	$(DX) --dex --output=$@ classes $(ROBOTIUM_PATH)
 
-robocop.ap_: AndroidManifest.xml
-	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -F $@ -J ./
+robocop.ap_: AndroidManifest.xml $(TESTPATH)/assets/*
+	$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -I . -S res -A $(TESTPATH)/assets -F $@ -J ./
 
 robocop.apk: robocop.ap_ classes.dex
 	cp $(TESTPATH)/robocop.ini robocop.ini
 	cp $(srcdir)/parse_ids.py parse_ids.py
 
 export::
 	$(NSINSTALL) -D res
 	@(cd $(srcdir)/res && tar $(TAR_CREATE_FLAGS) - *) | (cd $(DEPTH)/build/mobile/robocop/res && tar -xf -)
--- a/build/unix/build-toolchain/build-gcc.py
+++ b/build/unix/build-toolchain/build-gcc.py
@@ -260,16 +260,16 @@ os.makedirs(build_dir)
 
 build_aux_tools(build_dir)
 
 stage1_dir = build_dir + '/stage1'
 build_one_stage({"CC": "gcc", "CXX" : "g++"}, stage1_dir, True)
 
 stage1_tool_inst_dir = stage1_dir + '/inst'
 stage2_dir = build_dir + '/stage2'
-build_one_stage({"CC"     : stage1_tool_inst_dir + "/bin/gcc -fgnu89-inline",
-                 "CXX"    : stage1_tool_inst_dir + "/bin/g++",
-                 "AR"     : stage1_tool_inst_dir + "/bin/ar",
+build_one_stage({"PATH"   : stage1_tool_inst_dir + "/bin:/bin:/usr/bin",
+                 "CC"     : "gcc -fgnu89-inline",
+                 "CXX"    : "g++",
                  "RANLIB" : "true" },
                 stage2_dir, False)
 
 build_tar_package(aux_inst_dir + "/bin/tar",
                   "toolchain.tar", stage2_dir, "inst")
--- a/configure.in
+++ b/configure.in
@@ -1618,23 +1618,25 @@ if test "$OS_TARGET" = "Android" -a -z "
     if test -n "$MOZ_ANDROID_LIBSTDCXX" ; then
        if test ! -e "$android_ndk/sources/cxx-stl/gnu-libstdc++/libs/$ANDROID_CPU_ARCH/libstdc++.a" ; then
           AC_MSG_ERROR([Cannot find path to libstdc++ (NDK version >= 5?)])
        fi
        STLPORT_CPPFLAGS="-I$android_ndk/sources/cxx-stl/gnu-libstdc++/include -I$android_ndk/sources/cxx-stl/gnu-libstdc++/libs/$ANDROID_CPU_ARCH/include -D_GLIBCXX_PERMIT_BACKWARD_HASH"
        STLPORT_LDFLAGS="-L$android_ndk/sources/cxx-stl/gnu-libstdc++/libs/$ANDROID_CPU_ARCH"
        STLPORT_LIBS="-lstdc++"
     elif test -e "$android_ndk/sources/cxx-stl/stlport/src/iostream.cpp" ; then
+       if test -e "$android_ndk/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/libstlport_static.a"; then
+          STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
+       elif test -e "$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/libstlport_static.a"; then
+          STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
+       else
+          AC_MSG_ERROR([Couldn't find path to stlport in the android ndk])
+       fi
        STLPORT_SOURCES="$android_ndk/sources/cxx-stl/stlport"
        STLPORT_CPPFLAGS="-I$_objdir/build/stlport -I$android_ndk/sources/cxx-stl/stlport/stlport"
-       STLPORT_LDFLAGS="-L$_objdir/build/stlport -L$android_ndk/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/"
-       STLPORT_LIBS="-lstlport_static"
-    elif  test -e "$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH/libstlport_static.a" ; then
-       STLPORT_CPPFLAGS="-I$android_ndk/sources/cxx-stl/stlport/stlport"
-       STLPORT_LDFLAGS="-L$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/$ANDROID_CPU_ARCH"
        STLPORT_LIBS="-lstlport_static"
     elif test "$target" != "arm-android-eabi"; then
        dnl fail if we're not building with NDKr4
        AC_MSG_ERROR([Couldn't find path to stlport in the android ndk])
     fi
     CXXFLAGS="$CXXFLAGS $STLPORT_CPPFLAGS"
     LDFLAGS="$LDFLAGS $STLPORT_LDFLAGS"
     LIBS="$LIBS $STLPORT_LIBS"
@@ -4962,30 +4964,50 @@ dnl ====================================
 if test "$MOZ_ENABLE_QT"
 then
     MOZ_ARG_WITH_STRING(qtdir,
     [  --with-qtdir=\$dir       Specify Qt directory ],
     [ QTDIR=$withval])
 
     if test -z "$QTDIR"; then
         PKG_CHECK_MODULES(MOZ_QT, QtGui QtNetwork QtCore QtOpenGL)
+        PKG_CHECK_MODULES(MOZ_QT5, QtWidgets QtMultimedia QtPrintSupport QtQuick1,
+                      MOZ_ENABLE_QT5=1,
+                      MOZ_ENABLE_QT5=)
+        if test "$MOZ_ENABLE_QT5"; then
+            echo "Using qt5"
+            MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS $MOZ_QT5_CFLAGS"
+            MOZ_QT_LIBS="$MOZ_QT_LIBS $MOZ_QT5_LIBS"
+        fi
+
         AC_CHECK_PROGS(HOST_MOC, $MOC moc, "")
         AC_CHECK_PROGS(HOST_RCC, $RCC rcc, "")
     else
         MOZ_QT_LIBS="-L$QTDIR/lib/ -lQtGui -lQtNetwork -lQtCore -lQtXml -lQtOpenGL"
 
         MOZ_QT_CFLAGS="-DQT_SHARED"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/Qt"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtGui"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtCore"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtNetwork"
         MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtXml"
+        MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtDeclarative"
         HOST_MOC="$QTDIR/bin/moc"
         HOST_RCC="$QTDIR/bin/rcc"
+
+        # QtWidgets was introduced only in Qt5
+        if test -d $QTDIR/include/QtWidgets; then
+            echo "Using qt5"
+            MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtWidgets"
+            MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtMultimedia"
+            MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtPrintSupport"
+            MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I$QTDIR/include/QtQuick1"
+            MOZ_QT_LIBS="$MOZ_QT_LIBS -lQtWidgets -lQtMultimedia -lQtPrintSupport -lQtQuick1"
+        fi
     fi
     if test -z "$HOST_MOC"; then
         AC_MSG_ERROR([No acceptable moc preprocessor found. Qt SDK is not installed or --with-qt is
 incorrect])
     fi
     if test -z "$HOST_RCC"; then
         AC_MSG_ERROR([No acceptable rcc preprocessor found. Qt SDK is not installed or --with-qt is
 incorrect])
@@ -6292,39 +6314,48 @@ if test -n "$MOZ_TREE_FREETYPE"; then
    AC_DEFINE(HAVE_FT_LOAD_SFNT_TABLE)
    AC_SUBST(CAIRO_FT_CFLAGS)
 fi
 
 dnl ========================================================
 dnl Installer
 dnl ========================================================
 dnl Abort Windows build if the required major version and
-dnl minimum minor version of Unicode NSIS isn't in the path.
+dnl minimum minor version of Unicode NSIS isn't in the path
+dnl (unless in case of cross compiling, for which Unicode
+dnl is not yet sufficient).
 if test "$OS_ARCH" = "WINNT"; then
     REQ_NSIS_MAJOR_VER=2
     MIN_NSIS_MINOR_VER=33
     MOZ_PATH_PROGS(MAKENSISU, $MAKENSISU makensisu-2.46 makensisu makensis)
-    if test -z "$MAKENSISU" -o "$MAKENSISU" = ":"; then
-        AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
-    fi
-    changequote(,)
-    MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
-    changequote([,])
-    if test ! "$MAKENSISU_VER" = ""; then
-        MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
-        MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
-    fi
-    AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
-    if test "$MAKENSISU_VER" = "" ||
-       test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
-            ! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
-        AC_MSG_RESULT([no])
-        AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
-    fi
-    AC_MSG_RESULT([yes])
+    if test -n "$MAKENSISU" -a "$MAKENSISU" != ":"; then
+      AC_MSG_RESULT([yes])
+      changequote(,)
+      MAKENSISU_VER=`"$MAKENSISU" -version 2>/dev/null | sed -e '/-Unicode/!s/.*//g' -e 's/^v\([0-9]\+\.[0-9]\+\)\-Unicode$/\1/g'`
+      changequote([,])
+      if test ! "$MAKENSISU_VER" = ""; then
+          MAKENSISU_MAJOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $1 }'`
+          MAKENSISU_MINOR_VER=`echo $MAKENSISU_VER | $AWK -F\. '{ print $2 }'`
+      fi
+      AC_MSG_CHECKING([for Unicode NSIS with major version == $REQ_NSIS_MAJOR_VER and minor version >= $MIN_NSIS_MINOR_VER])
+      if test "$MAKENSISU_VER" = "" || \
+         test ! "$MAKENSISU_MAJOR_VER" = "$REQ_NSIS_MAJOR_VER" -o \
+              ! "$MAKENSISU_MINOR_VER" -ge $MIN_NSIS_MINOR_VER; then
+          AC_MSG_RESULT([no])
+          if test -z "$CROSS_COMPILE"; then
+            AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
+          else
+            MAKENSISU=
+          fi
+      fi
+    elif test -z "$CROSS_COMPILE"; then
+      AC_MSG_ERROR([To build the installer you must have the latest MozillaBuild or Unicode NSIS with a major version of $REQ_NSIS_MAJOR_VER and a minimum minor version of $MIN_NSIS_MINOR_VER in your path.])
+    else
+      MAKENSISU=
+    fi
 fi
 
 AC_MSG_CHECKING([for tar archiver])
 AC_CHECK_PROGS(TAR, gnutar gtar tar, "")
 if test -z "$TAR"; then
     AC_MSG_ERROR([no tar archiver found in \$PATH])
 fi
 AC_MSG_RESULT([$TAR])
@@ -6432,24 +6463,16 @@ dnl ====================================
 dnl build the tests by default
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(tests,
 [  --disable-tests         Do not build test libraries & programs],
     ENABLE_TESTS=,
     ENABLE_TESTS=1 )
 
 dnl ========================================================
-dnl Marionette
-dnl ========================================================
-MOZ_ARG_ENABLE_BOOL(marionette,
-[  --enable-marionette     Enable Marionette for remote testing and control],
-    ENABLE_MARIONETTE=1,
-    ENABLE_MARIONETTE)
-
-dnl ========================================================
 dnl parental controls (for Windows Vista)
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(parental-controls,
 [  --disable-parental-controls
                           Do not build parental controls],
    MOZ_DISABLE_PARENTAL_CONTROLS=1,
    MOZ_DISABLE_PARENTAL_CONTROLS=)
 if test -n "$MOZ_DISABLE_PARENTAL_CONTROLS"; then
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1416,17 +1416,21 @@ public:
    */
   virtual already_AddRefed<nsIDocument>
   CreateStaticClone(nsISupports* aCloneContainer);
 
   /**
    * If this document is a static clone, this returns the original
    * document.
    */
-  nsIDocument* GetOriginalDocument() { return mOriginalDocument; }
+  nsIDocument* GetOriginalDocument()
+  {
+    MOZ_ASSERT(!mOriginalDocument || !mOriginalDocument->GetOriginalDocument());
+    return mOriginalDocument;
+  }
 
   /**
    * Called by nsParser to preload images. Can be removed and code moved
    * to nsPreloadURIs::PreloadURIs() in file nsParser.cpp whenever the
    * parser-module is linked with gklayout-module.  aCrossOriginAttr should
    * be a void string if the attr is not present.
    */
   virtual void MaybePreLoadImage(nsIURI* uri,
--- a/content/base/src/contentSecurityPolicy.js
+++ b/content/base/src/contentSecurityPolicy.js
@@ -14,16 +14,17 @@
  * The Original Code is the ContentSecurityPolicy module.
  *
  * The Initial Developer of the Original Code is
  *   Mozilla Corporation
  *
  * Contributor(s):
  *   Sid Stamm <sid@mozilla.com>
  *   Brandon Sterne <bsterne@mozilla.com>
+ *   Ian Melven <imelven@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
@@ -296,28 +297,32 @@ ContentSecurityPolicy.prototype = {
       // should be taken care of in CSPRep.fromString (where it converts any
       // relative URIs into absolute ones based on "self").
       for (let i in uris) {
         if (uris[i] === "")
           continue;
 
         var failure = function(aEvt) {  
           if (req.readyState == 4 && req.status != 200) {
-            CSPError("Failed to send report to " + reportURI);
+            CSPError("Failed to send report to " + uris[i]);
           }  
         };  
         var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]  
                     .createInstance(Ci.nsIXMLHttpRequest);  
 
         try {
           req.open("POST", uris[i], true);
           req.setRequestHeader('Content-Type', 'application/json');
           req.upload.addEventListener("error", failure, false);
           req.upload.addEventListener("abort", failure, false);
 
+          // we need to set an nsIChannelEventSink on the XHR object
+          // so we can tell it to not follow redirects when posting the reports
+          req.channel.notificationCallbacks = new CSPReportRedirectSink();
+
           req.send(JSON.stringify(report));
           CSPdebug("Sent violation report to " + uris[i]);
         } catch(e) {
           // it's possible that the URI was invalid, just log a
           // warning and skip over that.
           CSPWarning("Tried to send report to invalid URI: \"" + uris[i] + "\"");
         }
       }
@@ -489,9 +494,59 @@ ContentSecurityPolicy.prototype = {
                                      CSP_VIOLATION_TOPIC,
                                      violatedDirective);
         reportSender.sendReports(blockedContentSource, violatedDirective,
                                  aSourceFile, aScriptSample, aLineNum);
       }, Ci.nsIThread.DISPATCH_NORMAL);
   },
 };
 
+// The POST of the violation report (if it happens) should not follow
+// redirects, per the spec. hence, we implement an nsIChannelEventSink
+// with an object so we can tell XHR to abort if a redirect happens.
+function CSPReportRedirectSink() {
+}
+
+CSPReportRedirectSink.prototype = {
+  QueryInterface: function requestor_qi(iid) {
+    if (iid.equals(Ci.nsISupports) ||
+        iid.equals(Ci.nsIInterfaceRequestor) ||
+        iid.equals(Ci.nsIChannelEventSink))
+      return this;
+    throw Cr.NS_ERROR_NO_INTERFACE;
+  },
+
+  // nsIInterfaceRequestor
+  getInterface: function requestor_gi(iid) {
+    if (iid.equals(Ci.nsIChannelEventSink))
+      return this;
+
+    throw Components.results.NS_ERROR_NO_INTERFACE;
+  },
+
+  // nsIChannelEventSink
+  asyncOnChannelRedirect: function channel_redirect(oldChannel, newChannel,
+                                                    flags, callback) {
+    CSPWarning("Post of violation report to " + oldChannel.URI.asciiSpec +
+               " failed, as a redirect occurred");
+
+    // cancel the old channel so XHR failure callback happens
+    oldChannel.cancel(Cr.NS_ERROR_ABORT);
+
+    // notify an observer that we have blocked the report POST due to a redirect,
+    // used in testing, do this async since we're in an async call now to begin with
+    Services.tm.mainThread.dispatch(
+      function() {
+        observerSubject = Cc["@mozilla.org/supports-cstring;1"]
+                             .createInstance(Ci.nsISupportsCString);
+        observerSubject.data = oldChannel.URI.asciiSpec;
+
+        Services.obs.notifyObservers(observerSubject,
+                                     CSP_VIOLATION_TOPIC,
+                                     "denied redirect while sending violation report");
+      }, Ci.nsIThread.DISPATCH_NORMAL);
+
+    // throw to stop the redirect happening
+    throw Cr.NS_BINDING_REDIRECTED;
+  }
+};
+
 var NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentSecurityPolicy]);
--- a/content/base/src/nsCCUncollectableMarker.cpp
+++ b/content/base/src/nsCCUncollectableMarker.cpp
@@ -373,8 +373,34 @@ nsCCUncollectableMarker::Observe(nsISupp
   if (xulCache) {
     xulCache->MarkInCCGeneration(sGeneration);
   }
 #endif
 
   return NS_OK;
 }
 
+static PLDHashOperator
+TraceActiveWindowGlobal(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
+{
+  if (aWindow->GetDocShell() && aWindow->IsOuterWindow()) {
+    if (JSObject* global = aWindow->FastGetGlobalJSObject()) {
+      JSTracer* trc = static_cast<JSTracer *>(aClosure);
+      JS_CALL_OBJECT_TRACER(trc, global, "active window global");
+    }
+  }
+  return PL_DHASH_NEXT;
+}
+
+void
+mozilla::dom::TraceBlackJS(JSTracer* aTrc)
+{
+  if (!nsCCUncollectableMarker::sGeneration) {
+    return;
+  }
+
+  // Mark globals of active windows black.
+  nsGlobalWindow::WindowByIdTable* windowsById =
+    nsGlobalWindow::GetWindowsTable();
+  if (windowsById) {
+    windowsById->Enumerate(TraceActiveWindowGlobal, aTrc);
+  }
+}
--- a/content/base/src/nsCCUncollectableMarker.h
+++ b/content/base/src/nsCCUncollectableMarker.h
@@ -33,16 +33,18 @@
  * 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 "nsIObserver.h"
 #include "nsCycleCollectionParticipant.h"
 
+struct JSTracer;
+
 class nsCCUncollectableMarker : public nsIObserver
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   /**
    * Inits a global nsCCUncollectableMarker. Should only be called once.
    */
@@ -51,20 +53,26 @@ class nsCCUncollectableMarker : public n
   /**
    * Checks if we're collecting during a given generation
    */
   static bool InGeneration(PRUint32 aGeneration)
   {
     return aGeneration && aGeneration == sGeneration;
   }
 
-  static bool InGeneration(nsCycleCollectionTraversalCallback &cb,
+  static bool InGeneration(nsCycleCollectionTraversalCallback& aCb,
                            PRUint32 aGeneration)
   {
-    return InGeneration(aGeneration) && !cb.WantAllTraces();
+    return InGeneration(aGeneration) && !aCb.WantAllTraces();
   }
 
   static PRUint32 sGeneration;
 
 private:
   nsCCUncollectableMarker() {}
 
 };
+
+namespace mozilla {
+namespace dom {
+void TraceBlackJS(JSTracer* aTrc);
+}
+}
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2542,16 +2542,17 @@ nsDocument::InitCSP()
 #endif
   return NS_OK;
 }
 
 void
 nsDocument::StopDocumentLoad()
 {
   if (mParser) {
+    mParserAborted = true;
     mParser->Terminate();
   }
 }
 
 void
 nsDocument::SetDocumentURI(nsIURI* aURI)
 {
   nsCOMPtr<nsIURI> oldBase = GetDocBaseURI();
@@ -8081,19 +8082,22 @@ nsIDocument::CreateStaticClone(nsISuppor
   SetContainer(aCloneContainer);
   nsCOMPtr<nsIDOMNode> clonedNode;
   nsresult rv = domDoc->CloneNode(true, 1, getter_AddRefs(clonedNode));
   SetContainer(originalContainer);
 
   nsCOMPtr<nsIDocument> clonedDoc;
   if (NS_SUCCEEDED(rv)) {
     clonedDoc = do_QueryInterface(clonedNode);
-    nsCOMPtr<nsIDOMDocument> clonedDOMDoc = do_QueryInterface(clonedDoc);
-    if (clonedDOMDoc) {
-      clonedDoc->mOriginalDocument = this;
+    if (clonedDoc) {
+      if (IsStaticDocument()) {
+        clonedDoc->mOriginalDocument = mOriginalDocument;
+      } else {
+        clonedDoc->mOriginalDocument = this;
+      }
       PRInt32 sheetsCount = GetNumberOfStyleSheets();
       for (PRInt32 i = 0; i < sheetsCount; ++i) {
         nsRefPtr<nsCSSStyleSheet> sheet = do_QueryObject(GetStyleSheetAt(i));
         if (sheet) {
           if (sheet->IsApplicable()) {
             nsRefPtr<nsCSSStyleSheet> clonedSheet =
               sheet->Clone(nsnull, nsnull, clonedDoc, nsnull);
             NS_WARN_IF_FALSE(clonedSheet, "Cloning a stylesheet didn't work!");
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1183,16 +1183,20 @@ protected:
 
   // Whether we are currently in full-screen mode, as per the DOM API.
   bool mIsFullScreen:1;
 
   // Whether we're currently under a FlushPendingNotifications call to
   // our presshell.  This is used to handle flush reentry correctly.
   bool mInFlush:1;
 
+  // Parser aborted. True if the parser of this document was forcibly
+  // terminated instead of letting it finish at its own pace.
+  bool mParserAborted:1;
+
   PRUint8 mXMLDeclarationBits;
 
   nsInterfaceHashtable<nsPtrHashKey<nsIContent>, nsPIBoxObject> *mBoxObjectTable;
 
   // The channel that got passed to StartDocumentLoad(), if any
   nsCOMPtr<nsIChannel> mChannel;
   nsRefPtr<nsHTMLCSSStyleSheet> mStyleAttrStyleSheet;
   nsRefPtr<nsXMLEventsManager> mXMLEventsManager;
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1930,17 +1930,18 @@ GK_ATOM(Stop, "Stop")
 GK_ATOM(Search, "Search")
 GK_ATOM(Bookmarks, "Bookmarks")
 GK_ATOM(Home, "Home")
 GK_ATOM(Clear, "Clear")
 GK_ATOM(VolumeUp, "VolumeUp")
 GK_ATOM(VolumeDown, "VolumeDown")
 GK_ATOM(Menu, "Menu")
 
-// Smooth scroll profiles
+// Smooth scroll events origins
+GK_ATOM(mouseWheel, "mouseWheel")  // For discrete wheel events (e.g. not OSX magic mouse)
 GK_ATOM(pixels,     "pixels")
 GK_ATOM(lines,      "lines")
 GK_ATOM(pages,      "pages")
 GK_ATOM(scrollbars, "scrollbars")
 GK_ATOM(other,      "other")
 
 #ifdef ACCESSIBILITY
 GK_ATOM(anonid, "anonid")
--- a/content/base/src/nsImageLoadingContent.cpp
+++ b/content/base/src/nsImageLoadingContent.cpp
@@ -309,52 +309,42 @@ nsImageLoadingContent::OnStopDecode(imgI
   if (mCurrentRequestNeedsResetAnimation) {
     nsCOMPtr<imgIContainer> container;
     mCurrentRequest->GetImage(getter_AddRefs(container));
     if (container)
       container->ResetAnimation();
     mCurrentRequestNeedsResetAnimation = false;
   }
 
-  // We just loaded all the data we're going to get. If we haven't done an
-  // initial paint, we want to make sure the image starts decoding for 2
-  // reasons:
+  // We just loaded all the data we're going to get. If we're visible and
+  // haven't done an initial paint (*), we want to make sure the image starts
+  // decoding immediately, for two reasons:
   //
   // 1) This image is sitting idle but might need to be decoded as soon as we
   // start painting, in which case we've wasted time.
   //
   // 2) We want to block onload until all visible images are decoded. We do this
-  // by blocking onload until all in progress decodes get at least one frame
+  // by blocking onload until all in-progress decodes get at least one frame
   // decoded. However, if all the data comes in while painting is suppressed
   // (ie, before the initial paint delay is finished), we fire onload without
   // doing a paint first. This means that decode-on-draw images don't start
   // decoding, so we can't wait for them to finish. See bug 512435.
+  //
+  // (*) IsPaintingSuppressed returns false if we haven't gotten the initial
+  // reflow yet, so we have to test !DidInitialReflow || IsPaintingSuppressed.
+  // It's possible for painting to be suppressed for reasons other than the
+  // initial paint delay (for example, being in the bfcache), but we probably
+  // aren't loading images in those situations.
 
-  // We can only do this if we have a presshell
   nsIDocument* doc = GetOurDocument();
   nsIPresShell* shell = doc ? doc->GetShell() : nsnull;
-  if (shell) {
-    // We need to figure out whether to kick off decoding
-    bool doRequestDecode = false;
-
-    // If we haven't got the initial reflow yet, IsPaintingSuppressed actually
-    // returns false
-    if (!shell->DidInitialReflow())
-      doRequestDecode = true;
+  if (shell && shell->IsVisible() &&
+      (!shell->DidInitialReflow() || shell->IsPaintingSuppressed())) {
 
-    // Figure out if painting is suppressed. Note that it's possible for painting
-    // to be suppressed for reasons other than the initial paint delay (for
-    // example - being in the bfcache), but we probably aren't loading images in
-    // those situations.
-    if (shell->IsPaintingSuppressed())
-      doRequestDecode = true;
-
-    // If we're requesting a decode, do it
-    if (doRequestDecode)
-      mCurrentRequest->RequestDecode();
+    mCurrentRequest->RequestDecode();
   }
 
   // Fire the appropriate DOM event.
   if (NS_SUCCEEDED(aStatus)) {
     FireEvent(NS_LITERAL_STRING("load"));
   } else {
     FireEvent(NS_LITERAL_STRING("error"));
   }
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -2763,20 +2763,23 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
 
   // Hook us up to listen to redirects and the like
   mChannel->GetNotificationCallbacks(getter_AddRefs(mNotificationCallbacks));
   mChannel->SetNotificationCallbacks(this);
 
   // Create our listener
   nsCOMPtr<nsIStreamListener> listener = this;
   if (mState & XML_HTTP_REQUEST_MULTIPART) {
+    Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 1);
     listener = new nsMultipartProxyListener(listener);
     if (!listener) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
+  } else {
+    Telemetry::Accumulate(Telemetry::MULTIPART_XHR_RESPONSE, 0);
   }
 
   // Blocking gets are common enough out of XHR that we should mark
   // the channel slow by default for pipeline purposes
   AddLoadFlags(mChannel, nsIRequest::INHIBIT_PIPELINE);
 
   if (!IsSystemXHR()) {
     // Always create a nsCORSListenerProxy here even if it's
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -567,16 +567,22 @@ include $(topsrcdir)/config/rules.mk
 		test_bug696301-2.html \
 		bug696301-script-1.js \
 		bug696301-script-1.js^headers^ \
 		bug696301-script-2.js \
 		test_bug737565.html \
 		test_bug737612.html \
 		test_bug738108.html \
 		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 \
 		$(NULL)
 
 _CHROME_FILES =	\
 		test_bug357450.js \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_bug650386_content.sjs
@@ -0,0 +1,37 @@
+// SJS file for tests for bug650386, serves file_bug650386_content.html
+// with a CSP that will trigger a violation and that will report it
+// to file_bug650386_report.sjs
+//
+// This handles 301, 302, 303 and 307 redirects. The HTTP status code
+// returned/type of redirect to do comes from the query string
+// parameter passed in from the test_bug650386_* files and then also
+// uses that value in the report-uri parameter of the CSP
+function handleRequest(request, response) {
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  // this gets used in the CSP as part of the report URI.
+  var redirect = request.queryString;
+
+  if (redirect < 301 || (redirect > 303 && redirect <= 306) || redirect > 307) {
+    // if we somehow got some bogus redirect code here,
+    // do a 302 redirect to the same URL as the report URI
+    // redirects to - this will fail the test.
+    var loc = "http://example.com/some/fake/path";
+    response.setStatusLine("1.1", 302, "Found");
+    response.setHeader("Location", loc, false);
+    return;
+  }
+
+  var csp = "default-src \'self\';report-uri http://mochi.test:8888/tests/content/base/test/file_bug650386_report.sjs?" + redirect;
+
+  response.setHeader("X-Content-Security-Policy", csp, false);
+
+  // the actual file content.
+  // this image load will (intentionally) fail due to the CSP policy of default-src: 'self'
+  // specified by the CSP string above.
+  var content = "<!DOCTYPE HTML><html><body><img src = \"http://some.other.domain.example.com\"></body></html>";
+
+  response.write(content);
+
+  return;
+}
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_bug650386_report.sjs
@@ -0,0 +1,16 @@
+// SJS file for tests for bug650386, this serves as CSP violation report target
+// and issues a redirect, to make sure the browser does not post to the target
+// of the redirect, per CSP spec.
+// This handles 301, 302, 303 and 307 redirects. The HTTP status code
+// returned/type of redirect to do comes from the query string
+// parameter
+function handleRequest(request, response) {
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  var redirect = request.queryString;
+
+  var loc = "http://example.com/some/fake/path";
+  response.setStatusLine("1.1", redirect, "Found");
+  response.setHeader("Location", loc, false);
+  return;
+}
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug650386_redirect_301.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=650386
+Test that CSP violation reports are not sent when a 301 redirect is encountered
+-->
+<head>
+  <title>Test for Bug 650386</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id = "content_iframe"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 650386 **/
+
+// This is used to watch the redirect of the report POST get blocked
+function examiner() {
+  SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
+  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+}
+
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+    // subject should be an nsURI
+    if(!SpecialPowers.can_QI(subject))
+       return;
+
+    if (topic === "http-on-modify-request") {
+      // this is used to fail the test - if we see the POST to the target of the redirect
+      // we know this is a fail
+      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
+
+      if (asciiSpec == "http://example.com/some/fake/path")
+        window.done(false);
+    }
+
+    if(topic === "csp-on-violate-policy") {
+      // something was blocked, but we are looking specifically for the redirect being blocked
+      if (data == "denied redirect while sending violation report")
+        window.done(true);
+    }
+  },
+
+  // must eventually call this to remove the listener,
+  // or mochitests might get borked.
+  remove: function() {
+    SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+    SpecialPowers.removeObserver(this, "http-on-modify-request");
+  }
+}
+
+window.examiner = new examiner();
+
+// result == true if we saw the redirect blocked notify, false if we saw the post
+// to the redirect target go out
+window.done = function(result) {
+  ok(result, "a 301 redirect when posting violation report should be blocked");
+
+  // clean up observers and finish the test
+  window.examiner.remove();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// save this for last so that our listeners are registered.
+document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?301';
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug650386_redirect_302.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=650386
+Test that CSP violation reports are not sent when a 302 redirect is encountered
+-->
+<head>
+  <title>Test for Bug 650386</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id = "content_iframe"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 650386 **/
+
+// This is used to watch the redirect of the report POST get blocked
+function examiner() {
+  SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
+  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+}
+
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+    // subject should be an nsURI
+    if(!SpecialPowers.can_QI(subject))
+       return;
+
+    if (topic === "http-on-modify-request") {
+      // this is used to fail the test - if we see the POST to the target of the redirect
+      // we know this is a fail
+      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
+
+      if (asciiSpec == "http://example.com/some/fake/path")
+        window.done(false);
+    }
+
+    if(topic === "csp-on-violate-policy") {
+      // something was blocked, but we are looking specifically for the redirect being blocked
+      if (data == "denied redirect while sending violation report")
+        window.done(true);
+    }
+  },
+
+  // must eventually call this to remove the listener,
+  // or mochitests might get borked.
+  remove: function() {
+    SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+    SpecialPowers.removeObserver(this, "http-on-modify-request");
+  }
+}
+
+window.examiner = new examiner();
+
+// result == true if we saw the redirect blocked notify, false if we saw the post
+// to the redirect target go out
+window.done = function(result) {
+  ok(result, "a 302 redirect when posting violation report should be blocked");
+
+  // clean up observers and finish the test
+  window.examiner.remove();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// save this for last so that our listeners are registered.
+document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?302';
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug650386_redirect_303.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=650386
+Test that CSP violation reports are not sent when a 303 redirect is encountered
+-->
+<head>
+  <title>Test for Bug 650386</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id = "content_iframe"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 650386 **/
+
+// This is used to watch the redirect of the report POST get blocked
+function examiner() {
+  SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
+  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+}
+
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+    // subject should be an nsURI
+    if(!SpecialPowers.can_QI(subject))
+       return;
+
+    if (topic === "http-on-modify-request") {
+      // this is used to fail the test - if we see the POST to the target of the redirect
+      // we know this is a fail
+      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
+
+      if (asciiSpec == "http://example.com/some/fake/path")
+        window.done(false);
+    }
+
+    if(topic === "csp-on-violate-policy") {
+      // something was blocked, but we are looking specifically for the redirect being blocked
+      if (data == "denied redirect while sending violation report")
+        window.done(true);
+    }
+  },
+
+  // must eventually call this to remove the listener,
+  // or mochitests might get borked.
+  remove: function() {
+    SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+    SpecialPowers.removeObserver(this, "http-on-modify-request");
+  }
+}
+
+window.examiner = new examiner();
+
+// result == true if we saw the redirect blocked notify, false if we saw the post
+// to the redirect target go out
+window.done = function(result) {
+  ok(result, "a 303 redirect when posting violation report should be blocked");
+
+  // clean up observers and finish the test
+  window.examiner.remove();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// save this for last so that our listeners are registered.
+document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?303';
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug650386_redirect_307.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=650386
+Test that CSP violation reports are not sent when a 307 redirect is encountered
+-->
+<head>
+  <title>Test for Bug 650386</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=650386">Mozilla Bug 650386</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe id = "content_iframe"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 650386 **/
+
+// This is used to watch the redirect of the report POST get blocked
+function examiner() {
+  SpecialPowers.addObserver(this, "csp-on-violate-policy", false);
+  SpecialPowers.addObserver(this, "http-on-modify-request", false);
+}
+
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+    // subject should be an nsURI
+    if(!SpecialPowers.can_QI(subject))
+       return;
+
+    if (topic === "http-on-modify-request") {
+      // this is used to fail the test - if we see the POST to the target of the redirect
+      // we know this is a fail
+      var asciiSpec = SpecialPowers.getPrivilegedProps(SpecialPowers.do_QueryInterface(subject, "nsIHttpChannel"), "URI.asciiSpec");
+
+      if (asciiSpec == "http://example.com/some/fake/path")
+        window.done(false);
+    }
+
+    if(topic === "csp-on-violate-policy") {
+      // something was blocked, but we are looking specifically for the redirect being blocked
+      if (data == "denied redirect while sending violation report")
+        window.done(true);
+    }
+  },
+
+  // must eventually call this to remove the listener,
+  // or mochitests might get borked.
+  remove: function() {
+    SpecialPowers.removeObserver(this, "csp-on-violate-policy");
+    SpecialPowers.removeObserver(this, "http-on-modify-request");
+  }
+}
+
+window.examiner = new examiner();
+
+// result == true if we saw the redirect blocked notify, false if we saw the post
+// to the redirect target go out
+window.done = function(result) {
+  ok(result, "a 307 redirect when posting violation report should be blocked");
+
+  // clean up observers and finish the test
+  window.examiner.remove();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// save this for last so that our listeners are registered.
+document.getElementById('content_iframe').src = 'file_bug650386_content.sjs?307';
+</script>
+</pre>
+</body>
+</html>
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -47,16 +47,17 @@ include $(DEPTH)/config/autoconf.mk
 MODULE		= content
 LIBRARY_NAME	= gkconcvs_s
 LIBXUL_LIBRARY  = 1
 
 EXPORTS = \
 	CustomQS_Canvas.h \
 	CustomQS_Canvas2D.h \
 	CustomQS_WebGL.h \
+	WebGLContext.h \
 	$(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom
 
 EXPORTS_mozilla/dom = \
   ImageData.h \
   $(NULL)
 
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -89,16 +89,18 @@ NS_NewCanvasRenderingContextWebGL(nsIDOM
     NS_ADDREF(*aResult = ctx);
     return NS_OK;
 }
 
 WebGLContext::WebGLContext()
     : mCanvasElement(nsnull),
       gl(nsnull)
 {
+    mEnabledExtensions.SetLength(WebGLExtensionID_Max);
+
     mGeneration = 0;
     mInvalidated = false;
     mResetLayer = true;
     mVerbose = false;
     mOptionsFrozen = false;
 
     mActiveTexture = 0;
     mWebGLError = LOCAL_GL_NO_ERROR;
@@ -484,17 +486,17 @@ WebGLContext::SetDimensions(PRInt32 widt
         }
         LogMessage("Using software rendering via OSMesa (THIS WILL BE SLOW)");
     }
 
 #ifdef XP_WIN
     // if we want EGL, try it now
     if (!gl && (preferEGL || useANGLE) && !preferOpenGL) {
         gl = gl::GLContextProviderEGL::CreateOffscreen(gfxIntSize(width, height), format);
-        if (gl && !InitAndValidateGL()) {
+        if (!gl || !InitAndValidateGL()) {
             LogMessage("Error during ANGLE OpenGL ES initialization");
             return NS_ERROR_FAILURE;
         }
     }
 #endif
 
     // try the default provider, whatever that is
     if (!gl && useOpenGL) {
@@ -1163,19 +1165,21 @@ WebGLContext::ForceRestoreContext()
 //
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(WebGLContext)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCanvasElement)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mEnabledExtensions)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebGLContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCanvasElement)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mEnabledExtensions)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 DOMCI_DATA(WebGLRenderingContext, WebGLContext)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLContext)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWebGLRenderingContext)
   NS_INTERFACE_MAP_ENTRY(nsICanvasRenderingContextInternal)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
@@ -1291,54 +1295,44 @@ NS_IMETHODIMP base::SetName(WebGLuint aN
 
 NAME_NOT_SUPPORTED(WebGLTexture)
 NAME_NOT_SUPPORTED(WebGLBuffer)
 NAME_NOT_SUPPORTED(WebGLProgram)
 NAME_NOT_SUPPORTED(WebGLShader)
 NAME_NOT_SUPPORTED(WebGLFramebuffer)
 NAME_NOT_SUPPORTED(WebGLRenderbuffer)
 
-NS_IMPL_ADDREF(WebGLExtension)
-NS_IMPL_RELEASE(WebGLExtension)
+// WebGLExtension
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(WebGLExtension)
+
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WebGLExtension)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WebGLExtension)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebGLExtension)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+  
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WebGLExtension)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtension)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtension)
+NS_INTERFACE_MAP_END 
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLExtension)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLExtension)
 
 DOMCI_DATA(WebGLExtension, WebGLExtension)
 
-NS_INTERFACE_MAP_BEGIN(WebGLExtension)
-  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtension)
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtension)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_ADDREF(WebGLExtensionStandardDerivatives)
-NS_IMPL_RELEASE(WebGLExtensionStandardDerivatives)
-
-DOMCI_DATA(WebGLExtensionStandardDerivatives, WebGLExtensionStandardDerivatives)
-
-NS_INTERFACE_MAP_BEGIN(WebGLExtensionStandardDerivatives)
-  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionStandardDerivatives)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionStandardDerivatives)
-NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
-
-NS_IMPL_ADDREF(WebGLExtensionTextureFilterAnisotropic)
-NS_IMPL_RELEASE(WebGLExtensionTextureFilterAnisotropic)
-
-DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, WebGLExtensionTextureFilterAnisotropic)
-
-NS_IMPL_ADDREF(WebGLExtensionLoseContext)
-NS_IMPL_RELEASE(WebGLExtensionLoseContext)
-
-DOMCI_DATA(WebGLExtensionLoseContext, WebGLExtensionLoseContext)
-
-NS_INTERFACE_MAP_BEGIN(WebGLExtensionLoseContext)
-  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionLoseContext)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionLoseContext)
-NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
-
 /* readonly attribute WebGLsizei drawingBufferWidth; */
 NS_IMETHODIMP
 WebGLContext::GetDrawingBufferWidth(WebGLsizei *aWidth)
 {
     if (!IsContextStable())
         return NS_OK;
 
     *aWidth = mWidth;
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -53,16 +53,17 @@
 #include "nsIDOMWebGLRenderingContext.h"
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsHTMLCanvasElement.h"
 #include "nsWeakReference.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIMemoryReporter.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsContentUtils.h"
+#include "nsWrapperCache.h"
 
 #include "GLContextProvider.h"
 #include "Layers.h"
 
 #include "CheckedInt.h"
 #include "nsDataHashtable.h"
 
 #ifdef XP_MACOSX
@@ -532,16 +533,20 @@ public:
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebGLContext, nsIDOMWebGLRenderingContext)
 
     NS_DECL_NSIDOMWEBGLRENDERINGCONTEXT
 
     NS_DECL_NSITIMERCALLBACK
 
     // nsICanvasRenderingContextInternal
     NS_IMETHOD SetCanvasElement(nsHTMLCanvasElement* aParentCanvas);
+    nsHTMLCanvasElement* HTMLCanvasElement() {
+        return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
+    }
+
     NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
     NS_IMETHOD InitializeWithSurface(nsIDocShell *docShell, gfxASurface *surface, PRInt32 width, PRInt32 height)
         { return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Reset()
         { /* (InitializeWithSurface) */ return NS_ERROR_NOT_IMPLEMENTED; }
     NS_IMETHOD Render(gfxContext *ctx,
                       gfxPattern::GraphicsFilter f,
                       PRUint32 aFlags = RenderFlagPremultAlpha);
@@ -693,19 +698,16 @@ protected:
     nsresult BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage);
     nsresult BufferData_buf(WebGLenum target, JSObject* data, WebGLenum usage);
     nsresult BufferData_array(WebGLenum target, JSObject* data, WebGLenum usage);
 
     nsresult BufferSubData_buf(WebGLenum target, PRInt32 offset, JSObject* data);
     nsresult BufferSubData_array(WebGLenum target, PRInt32 offset, JSObject* data);
 
     nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
-    nsHTMLCanvasElement *HTMLCanvasElement() {
-        return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
-    }
 
     nsRefPtr<gl::GLContext> gl;
 
     CheckedUint32 mGeneration;
 
     WebGLContextOptions mOptions;
 
     bool mInvalidated;
@@ -758,17 +760,17 @@ protected:
     // extensions
     enum WebGLExtensionID {
         WebGL_OES_texture_float,
         WebGL_OES_standard_derivatives,
         WebGL_EXT_texture_filter_anisotropic,
         WebGL_MOZ_WEBGL_lose_context,
         WebGLExtensionID_Max
     };
-    nsRefPtr<WebGLExtension> mEnabledExtensions[WebGLExtensionID_Max];
+    nsAutoTArray<nsRefPtr<WebGLExtension>, WebGLExtensionID_Max> mEnabledExtensions;
     bool IsExtensionEnabled(WebGLExtensionID ext) const {
         NS_ABORT_IF_FALSE(ext >= 0 && ext < WebGLExtensionID_Max, "bogus index!");
         return mEnabledExtensions[ext] != nsnull;
     }
     bool IsExtensionSupported(WebGLExtensionID ei);
 
     bool InitAndValidateGL();
     bool ValidateBuffers(PRInt32* maxAllowedCount, const char *info);
@@ -992,16 +994,18 @@ public:
         mContextGeneration = context->Generation();
     }
 
     bool IsCompatibleWithContext(WebGLContext *other) {
         return mContext == other &&
             mContextGeneration == other->Generation();
     }
 
+    WebGLContext *Context() const { return mContext; }
+
 protected:
     WebGLContext *mContext;
     PRUint32 mContextGeneration;
 };
 
 struct WebGLVertexAttribData {
     // note that these initial values are what GL initializes vertex attribs to
     WebGLVertexAttribData()
@@ -2536,24 +2540,27 @@ protected:
     WebGLint mRangeMin;
     WebGLint mRangeMax;
     WebGLint mPrecision;
 };
 
 class WebGLExtension
     : public nsIWebGLExtension
     , public WebGLContextBoundObject
+    , public nsWrapperCache
 {
 public:
     WebGLExtension(WebGLContext *baseContext)
         : WebGLContextBoundObject(baseContext)
     {}
 
-    NS_DECL_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLExtension)
     NS_DECL_NSIWEBGLEXTENSION
+
     virtual ~WebGLExtension() {}
 };
 
 inline const WebGLRectangleObject *WebGLContext::FramebufferRectangleObject() const {
     return mBoundFramebuffer ? mBoundFramebuffer->RectangleObject()
                              : static_cast<const WebGLRectangleObject*>(this);
 }
 
--- a/content/canvas/src/WebGLExtensionLoseContext.cpp
+++ b/content/canvas/src/WebGLExtensionLoseContext.cpp
@@ -69,8 +69,19 @@ WebGLExtensionLoseContext::LoseContext()
 NS_IMETHODIMP 
 WebGLExtensionLoseContext::RestoreContext()
 {
     if (!mContext->RestoreContext())
         mContext->mWebGLError = LOCAL_GL_INVALID_OPERATION;
 
     return NS_OK;
 }
+
+NS_IMPL_ADDREF_INHERITED(WebGLExtensionLoseContext, WebGLExtension)
+NS_IMPL_RELEASE_INHERITED(WebGLExtensionLoseContext, WebGLExtension)
+
+DOMCI_DATA(WebGLExtensionLoseContext, WebGLExtensionLoseContext)
+
+NS_INTERFACE_MAP_BEGIN(WebGLExtensionLoseContext)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionLoseContext)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionLoseContext)
+NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
--- a/content/canvas/src/WebGLExtensionStandardDerivatives.cpp
+++ b/content/canvas/src/WebGLExtensionStandardDerivatives.cpp
@@ -51,8 +51,19 @@ WebGLExtensionStandardDerivatives::WebGL
 {
 
 }
 
 WebGLExtensionStandardDerivatives::~WebGLExtensionStandardDerivatives()
 {
 
 }
+
+NS_IMPL_ADDREF_INHERITED(WebGLExtensionStandardDerivatives, WebGLExtension)
+NS_IMPL_RELEASE_INHERITED(WebGLExtensionStandardDerivatives, WebGLExtension)
+
+DOMCI_DATA(WebGLExtensionStandardDerivatives, WebGLExtensionStandardDerivatives)
+
+NS_INTERFACE_MAP_BEGIN(WebGLExtensionStandardDerivatives)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionStandardDerivatives)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionStandardDerivatives)
+NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
--- a/content/canvas/src/WebGLExtensionTextureFilterAnisotropic.cpp
+++ b/content/canvas/src/WebGLExtensionTextureFilterAnisotropic.cpp
@@ -41,24 +41,29 @@
 #include "WebGLContext.h"
 #include "WebGLExtensions.h"
 
 #include "nsContentUtils.h"
 #include "mozilla/Preferences.h"
 
 using namespace mozilla;
 
-NS_INTERFACE_MAP_BEGIN(WebGLExtensionTextureFilterAnisotropic)
-  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionTextureFilterAnisotropic)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionTextureFilterAnisotropic)
-NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
-
 WebGLExtensionTextureFilterAnisotropic::WebGLExtensionTextureFilterAnisotropic(WebGLContext* context) :
     WebGLExtension(context)
 {
 
 }
 
 WebGLExtensionTextureFilterAnisotropic::~WebGLExtensionTextureFilterAnisotropic()
 {
 
 }
+
+NS_IMPL_ADDREF_INHERITED(WebGLExtensionTextureFilterAnisotropic, WebGLExtension)
+NS_IMPL_RELEASE_INHERITED(WebGLExtensionTextureFilterAnisotropic, WebGLExtension)
+
+DOMCI_DATA(WebGLExtensionTextureFilterAnisotropic, WebGLExtensionTextureFilterAnisotropic)
+
+NS_INTERFACE_MAP_BEGIN(WebGLExtensionTextureFilterAnisotropic)
+  NS_INTERFACE_MAP_ENTRY(nsIWebGLExtensionTextureFilterAnisotropic)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, WebGLExtension)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebGLExtensionTextureFilterAnisotropic)
+NS_INTERFACE_MAP_END_INHERITING(WebGLExtension)
--- a/content/canvas/src/WebGLExtensions.h
+++ b/content/canvas/src/WebGLExtensions.h
@@ -44,39 +44,39 @@ namespace mozilla {
 class WebGLExtensionLoseContext :
     public nsIWebGLExtensionLoseContext,
     public WebGLExtension
 {
 public:
     WebGLExtensionLoseContext(WebGLContext*);
     virtual ~WebGLExtensionLoseContext();
 
-    NS_DECL_ISUPPORTS
+    NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIWEBGLEXTENSIONLOSECONTEXT
 };
 
 class WebGLExtensionStandardDerivatives :
     public nsIWebGLExtensionStandardDerivatives,
     public WebGLExtension
 {
 public:
     WebGLExtensionStandardDerivatives(WebGLContext* context);
     virtual ~WebGLExtensionStandardDerivatives();
 
-    NS_DECL_ISUPPORTS
+    NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIWEBGLEXTENSION
 };
 
 class WebGLExtensionTextureFilterAnisotropic :
     public nsIWebGLExtensionTextureFilterAnisotropic,
     public WebGLExtension
 {
 public:
     WebGLExtensionTextureFilterAnisotropic(WebGLContext* context);
     virtual ~WebGLExtensionTextureFilterAnisotropic();
 
-    NS_DECL_ISUPPORTS
+    NS_DECL_ISUPPORTS_INHERITED
     NS_DECL_NSIWEBGLEXTENSION
 };
 
 }
 
 #endif // WEBGLEXTENSIONS_H_
--- a/content/canvas/test/webgl/00_test_list.txt
+++ b/content/canvas/test/webgl/00_test_list.txt
@@ -1,6 +1,6 @@
-// files that end in .txt list other tests
-// other lines are assumed to be .html files
-
-conformance/00_test_list.txt
-conformance/more/00_test_list.txt
-
+// files that end in .txt list other tests
+// other lines are assumed to be .html files
+
+conformance/00_test_list.txt
+conformance/more/00_test_list.txt
+
--- a/content/canvas/test/webgl/README.mozilla
+++ b/content/canvas/test/webgl/README.mozilla
@@ -1,14 +1,28 @@
-This is a local copy of the WebGL conformance suite, SVN revision 16776
+This is a local copy of the WebGL conformance suite, version 1.0.1, SVN revision 17159 (on the 1.0.1 branch, not on trunk)
+
+The canonical location for this 1.0.1 test suite is:
 
-The canonical location for this testsuite is:
+  https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/conformance-suites/1.0.1
+
+The canonical location of the development tree is:
 
   https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/tests
 
 All files and directories in this directory, with the exceptions listed below, come from
 upstream and should not be modified without corresponding upstream fixes and/or a
 patch file in this directory. The exceptions (the Mozilla-specific files) are:
  * README.mozilla (this file)
  * failing_tests_*.txt
  * Makefile.in
  * *.patch files, if any
 
+How to do an update:
+ 1. unapply local patches (the .patch files here)
+ 2. perform the update:
+   * method A: apply diff with new version
+   * method B: erase all files here, import copy of new version.
+ 3. edit CONFORMANCE_TEST_VERSION in test_webgl_conformance_test_suite.html. That's what
+    determines with tests to run, as some tests are only enabled in some not-yet-released
+    version.
+ 4. reapply local patches.
+ 5. update this readme and the .patch files
--- a/content/canvas/test/webgl/README.txt
+++ b/content/canvas/test/webgl/README.txt
@@ -1,28 +1,28 @@
-Welcome to the WebGL Conformance Test Suite
-===========================================
-
-This is the initial release of the WebGL conformance test suite.
-
-NOTE TO USERS: Unless you are a WebGL implementor, there is no need to submit
-a conformance result using this process.  Should you discover bugs in your
-browser's WebGL implementation, either via this test suite or otherwise,
-please report them to your browser vendor's bug tracking system.
-
-FOR WEBGL IMPLEMENTORS: Please follow the isntructions below to create
-a formal conformance submission.'
-
-1) Open webgl-conformance-tests.html in your target browser
-
-2) Press the "run tests" button
-
-3) At the end of the run, press "display text summary"
-
-4) Verify that the User Agent and WebGL renderer strings identify your browser and target correctly.
-
-5) Copy the contents of the text summary (starting with "WebGL Conformance Test Results") and send via email to
-   --- NEED ADDRESS HERE --- @khronos.org
-
-
-- Version 1.0.0
-- February 24, 2011
-
+Welcome to the WebGL Conformance Test Suite
+===========================================
+
+This is the initial release of the WebGL conformance test suite.
+
+NOTE TO USERS: Unless you are a WebGL implementor, there is no need to submit
+a conformance result using this process.  Should you discover bugs in your
+browser's WebGL implementation, either via this test suite or otherwise,
+please report them to your browser vendor's bug tracking system.
+
+FOR WEBGL IMPLEMENTORS: Please follow the isntructions below to create
+a formal conformance submission.'
+
+1) Open webgl-conformance-tests.html in your target browser
+
+2) Press the "run tests" button
+
+3) At the end of the run, press "display text summary"
+
+4) Verify that the User Agent and WebGL renderer strings identify your browser and target correctly.
+
+5) Copy the contents of the text summary (starting with "WebGL Conformance Test Results") and send via email to
+   --- NEED ADDRESS HERE --- @khronos.org
+
+
+- Version 1.0.0
+- February 24, 2011
+
--- a/content/canvas/test/webgl/conformance/00_readme.txt
+++ b/content/canvas/test/webgl/conformance/00_readme.txt
@@ -1,13 +1,13 @@
-This file "00_test_list.txt" lists which files the test harness should run.
-
-If you add new tests you can update it with
-
-on windows
-
-   dir /b *.html >00_test_list.txt
-
-on OSX / Linux
-
-   ls -1 *.html >00_test_list.txt
-
-
+This file "00_test_list.txt" lists which files the test harness should run.
+
+If you add new tests you can update it with
+
+on windows
+
+   dir /b *.html >00_test_list.txt
+
+on OSX / Linux
+
+   ls -1 *.html >00_test_list.txt
+
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/LICENSE_CHROMIUM
@@ -0,0 +1,30 @@
+// For files copyrighted by the Chromium Authors, the following
+// license applies:
+
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--- a/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib-zero-issues.html
+++ b/content/canvas/test/webgl/conformance/attribs/gl-vertex-attrib-zero-issues.html
@@ -32,25 +32,21 @@
         gl_FragColor = vec4(0.0,0.0,0.0,0.0);
     }
 </script>
 
 <script>
 description("Test some of the issues of the difference between attrib 0 on OpenGL vs WebGL");
 debug("");
 var wtu = WebGLTestUtils;
-var canvas = document.getElementById("example");
-var gl = wtu.create3DContext(canvas);
+var gl = wtu.create3DContext("example");
 
 function setup(numVerts, attribIndex) {
   var program = wtu.setupProgram(
-      gl,
-      [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
-       wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
-      ['vPosition'], [attribIndex]);
+      gl, ['vshader', 'fshader'], ['vPosition'], [attribIndex]);
   // draw with something on attrib zero with a small number of vertices
   var vertexObject = gl.createBuffer();
   g_program = program;
   g_attribLocation = attribIndex;
   shouldBe("g_attribLocation", "gl.getAttribLocation(g_program, 'vPosition')");
   gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
   gl.bufferData(
       gl.ARRAY_BUFFER, new Float32Array(numVerts * 3), gl.STATIC_DRAW);
--- a/content/canvas/test/webgl/conformance/canvas/buffer-offscreen-test.html
+++ b/content/canvas/test/webgl/conformance/canvas/buffer-offscreen-test.html
@@ -48,19 +48,18 @@ function timer() {
     }
 }
 
 function go() {
     description("This test ensures WebGL implementations correctly clear the drawing buffer on composite if preserveDrawingBuffer is false.");
 
     debug("");
 
-    gl1 = create3DContext(document.getElementById("c"));
-    c2 = document.createElement('canvas');
-    gl2 = create3DContext(c2);
+    gl1 = wtu.create3DContext("c");
+    gl2 = create3DContext();
     shouldBeTrue("gl1 != null");
     shouldBeTrue("gl2 != null");
 
     shouldBeTrue('gl1.getContextAttributes().preserveDrawingBuffer == false');
     shouldBeTrue('gl2.getContextAttributes().preserveDrawingBuffer == false');
 
     function init(gl) {
         gl.clearColor(1, 0, 0, 1);
--- a/content/canvas/test/webgl/conformance/canvas/buffer-preserve-test.html
+++ b/content/canvas/test/webgl/conformance/canvas/buffer-preserve-test.html
@@ -54,17 +54,17 @@ function timer() {
     setTimeout(timer, 500);
 }
 
 function go() {
     description("This test ensures WebGL implementations correctly clear the drawing buffer on composite if preserveDrawingBuffer is false.");
 
     debug("");
 
-    gl1 = create3DContext(document.getElementById("c"));
+    gl1 = wtu.create3DContext("c");
     if (!gl1) {
         finishTest();
         return;
     }
 
     shouldBeTrue("gl1 != null");
     shouldBeTrue('gl1.getContextAttributes().preserveDrawingBuffer == false');
 
--- a/content/canvas/test/webgl/conformance/canvas/drawingbuffer-static-canvas-test.html
+++ b/content/canvas/test/webgl/conformance/canvas/drawingbuffer-static-canvas-test.html
@@ -89,18 +89,17 @@ function drawTriangleTest(gl)
 
 description("This test ensures WebGL implementations correctly implement drawingbufferWidth/Height with compositing.");
 
 debug("");
 
 var wtu = WebGLTestUtils;
 var err;
 var maxSize;
-var canvas = document.getElementById("canvas");
-var gl =  wtu.create3DContext(canvas);
+var gl =  wtu.create3DContext("canvas");
 if (!gl) {
   testFailed("context does not exist");
 } else {
   testPassed("context exists");
 
   gl.program = createProgram(gl, "vshader", "fshader", ["vPosition"]);
   shouldBeNonNull("gl.program");
   gl.useProgram(gl.program);
@@ -109,37 +108,37 @@ if (!gl) {
   gl.clearColor(0, 0, 0, 1);
   gl.clearDepth(1);
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 
   debug("");
   debug("Checking drawingBufferWidth/drawingBufferHeight");
 
   // Check that a canvas with no width or height is 300x150 pixels
-  shouldBe('gl.drawingBufferWidth', 'canvas.width');
-  shouldBe('gl.drawingBufferHeight', 'canvas.height');
+  shouldBe('gl.drawingBufferWidth', 'gl.canvas.width');
+  shouldBe('gl.drawingBufferHeight', 'gl.canvas.height');
 
   // Check that changing the canvas size to something too large falls back to reasonable values.
   maxSize = gl.getParameter(gl.MAX_VIEWPORT_DIMS);
   shouldBeTrue('maxSize[0] > 0');
   shouldBeTrue('maxSize[1] > 0');
 
   // debug("MAX_VIEWPORT_DIMS = " + maxSize[0] + "x" + maxSize[1]);
-  canvas.width = maxSize[0] * 4;
-  canvas.height = maxSize[1] * 4;
+  gl.canvas.width = maxSize[0] * 4;
+  gl.canvas.height = maxSize[1] * 4;
   shouldBeTrue('gl.drawingBufferWidth > 0');
   shouldBeTrue('gl.drawingBufferHeight > 0');
   shouldBeTrue('gl.drawingBufferWidth <= maxSize[0]');
   shouldBeTrue('gl.drawingBufferHeight <= maxSize[1]');
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 
   debug("");
   debug("Checking scaling up then back down to 50/50, drawing still works.");
-  canvas.width = 50;
-  canvas.height = 50;
+  gl.canvas.width = 50;
+  gl.canvas.height = 50;
   shouldBeTrue('gl.drawingBufferWidth == 50');
   shouldBeTrue('gl.drawingBufferHeight == 50');
   shouldBe('gl.getError()', 'gl.NO_ERROR');
   drawTriangleTest(gl);
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 }
 debug("")
 successfullyParsed = true;
--- a/content/canvas/test/webgl/conformance/canvas/drawingbuffer-test.html
+++ b/content/canvas/test/webgl/conformance/canvas/drawingbuffer-test.html
@@ -88,18 +88,17 @@ function drawTriangleTest(gl)
 
 description("This test ensures WebGL implementations correctly implement drawingbufferWidth/Height.");
 
 debug("");
 
 var wtu = WebGLTestUtils;
 var err;
 var maxSize;
-var canvas = document.createElement("canvas");
-var gl = create3DContext(canvas);
+var gl = wtu.create3DContext();
 if (!gl) {
   testFailed("context does not exist");
 } else {
   testPassed("context exists");
 
   gl.program = createProgram(gl, "vshader", "fshader", ["vPosition"]);
   shouldBeNonNull("gl.program");
   gl.useProgram(gl.program);
@@ -108,37 +107,37 @@ if (!gl) {
   gl.clearColor(0, 0, 0, 1);
   gl.clearDepth(1);
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 
   debug("");
   debug("Checking drawingBufferWidth/drawingBufferHeight");
 
   // Check that a canvas with no width or height is 300x150 pixels
-  shouldBe('gl.drawingBufferWidth', 'canvas.width');
-  shouldBe('gl.drawingBufferHeight', 'canvas.height');
+  shouldBe('gl.drawingBufferWidth', 'gl.canvas.width');
+  shouldBe('gl.drawingBufferHeight', 'gl.canvas.height');
 
   // Check that changing the canvas size to something too large falls back to reasonable values.
   maxSize = gl.getParameter(gl.MAX_VIEWPORT_DIMS);
   shouldBeTrue('maxSize[0] > 0');
   shouldBeTrue('maxSize[1] > 0');
 
   // debug("MAX_VIEWPORT_DIMS = " + maxSize[0] + "x" + maxSize[1]);
-  canvas.width = maxSize[0] * 4;
-  canvas.height = maxSize[1] * 4;
+  gl.canvas.width = maxSize[0] * 4;
+  gl.canvas.height = maxSize[1] * 4;
   shouldBeTrue('gl.drawingBufferWidth > 0');
   shouldBeTrue('gl.drawingBufferHeight > 0');
   shouldBeTrue('gl.drawingBufferWidth <= maxSize[0]');
   shouldBeTrue('gl.drawingBufferHeight <= maxSize[1]');
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 
   debug("");
   debug("Checking scaling up then back down to 50/50, drawing still works.");
-  canvas.width = 50;
-  canvas.height = 50;
+  gl.canvas.width = 50;
+  gl.canvas.height = 50;
   shouldBeTrue('gl.drawingBufferWidth == 50');
   shouldBeTrue('gl.drawingBufferHeight == 50');
   shouldBe('gl.getError()', 'gl.NO_ERROR');
   drawTriangleTest(gl);
   shouldBe('gl.getError()', 'gl.NO_ERROR');
 }
 debug("")
 successfullyParsed = true;
--- a/content/canvas/test/webgl/conformance/context/constants.html
+++ b/content/canvas/test/webgl/conformance/context/constants.html
@@ -191,17 +191,16 @@ SAMPLE_COVERAGE_VALUE          : 0x80AA,
 SAMPLE_COVERAGE_INVERT         : 0x80AB,
     
     /* GetTextureParameter */
     /*      TEXTURE_MAG_FILTER */
     /*      TEXTURE_MIN_FILTER */
     /*      TEXTURE_WRAP_S */
     /*      TEXTURE_WRAP_T */
     
-NUM_COMPRESSED_TEXTURE_FORMATS : 0x86A2,
 COMPRESSED_TEXTURE_FORMATS     : 0x86A3,
     
     /* HintMode */
 DONT_CARE                      : 0x1100,
 FASTEST                        : 0x1101,
 NICEST                         : 0x1102,
     
     /* HintTarget */
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/context/context-attribute-preserve-drawing-buffer.html
@@ -0,0 +1,113 @@
+<!--
+Copyright (C) 2012 Opera Software ASA.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY OPERA SOFTWARE ASA. ''AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <link rel="stylesheet" href="../../resources/js-test-style.css"/>
+        <script src="../../resources/js-test-pre.js"></script>
+        <script src="../resources/webgl-test.js"></script>
+        <style>
+            canvas {
+                width:50px;
+                height:50px;
+            }
+            .square {
+                display:inline-block;
+                width:50px;
+                height:50px;
+                background-color:red;
+            }
+        </style>
+        <script>
+            function checkResult(ctx1, ctx2, preserve) {
+                var imgData1 = ctx1.getImageData(0,0,1,1);
+                var imgData2 = ctx2.getImageData(0,0,1,1);
+                var correct1 = [255,0,0,255];
+                var correct2 = preserve ? [255,0,0,255] : [0,0,0,255];
+                var ok1 = true;
+                var ok2 = true;
+                for (var p = 0; p < 4; ++p) {
+                    if (imgData1.data[p] != correct1[p])
+                        ok1 = false;
+                    if (imgData2.data[p] != correct2[p])
+                        ok2 = false;
+                }
+                if (ok1 && ok2)
+                    testPassed('Rendered ok with preserveDrawingBuffer ' + preserve +'.');
+                else
+                    testFailed('Did not render ok with preserveDrawingBuffer ' + preserve + '.');
+                if (preserve) {
+                    debug('<br /><span class="pass">TEST COMPLETE</span>');
+                    notifyFinishedToHarness()
+                } else {
+                    runTest(true);
+                }
+            }
+
+            function runTest(preserve) {
+                var c1 = document.getElementById('c' + (preserve * 3 + 1));
+                var c2 = document.getElementById('c' + (preserve * 3 + 2));
+                var c3 = document.getElementById('c' + (preserve * 3 + 3));
+                var ctx1 = c1.getContext('2d');
+                var ctx2 = c2.getContext('2d');
+                var gl = c3.getContext('experimental-webgl', { alpha:false, preserveDrawingBuffer:preserve });
+                gl.clearColor(1, 0, 0, 1);
+                gl.clear(gl.COLOR_BUFFER_BIT);
+                ctx1.drawImage(c3, 0, 0);
+                setTimeout(function() { ctx2.drawImage(c3, 0, 0); checkResult(ctx1, ctx2, preserve); }, 100);
+
+            }
+        </script>
+    </head>
+    <body>
+        <div>
+            <canvas id='c1'></canvas>
+            <canvas id='c2'></canvas>
+            <canvas id='c3'></canvas>
+            <span>should look as right pattern</span>
+            <div class='square'></div>
+            <div class='square' style='background-color:black'></div>
+            <div class='square'></div>
+        </div>
+        <div>
+            <canvas id='c4'></canvas>
+            <canvas id='c5'></canvas>
+            <canvas id='c6'></canvas>
+            <span>should look as right pattern</span>
+            <div class='square'></div>
+            <div class='square'></div>
+            <div class='square'></div>
+        </div>
+        <div id="description"></div>
+        <div id="console"></div>
+        <script>
+            description('Verify that preserveDrawingBuffer attribute is honored.');
+            runTest(false);
+            successfullyParsed = true;
+            shouldBeTrue("successfullyParsed");
+        </script>
+    </body>
+</html>
--- a/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
+++ b/content/canvas/test/webgl/conformance/extensions/00_test_list.txt
@@ -1,8 +1,8 @@
 oes-standard-derivatives.html
 ext-texture-filter-anisotropic.html
 oes-texture-float.html
 oes-vertex-array-object.html
 webgl-debug-renderer-info.html
 webgl-debug-shaders.html
---min-version 1.0.2 webgl-experimental-compressed-textures.html
+--min-version 1.0.2 webgl-compressed-texture-s3tc.html
 
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgb.dxt1.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_4x4_rgb_dxt1 = [
-0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgba.dxt1.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_4x4_rgba_dxt1 = [
-0xe0,0x07,0x00,0xf8,0x13,0x10,0x15,0x00,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgba.dxt3.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_4x4_rgba_dxt3 = [
-0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgba.dxt5.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_4x4_rgba_dxt5 = [
-0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/4x4.rgba.raw.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_4x4_rgba_raw = [
-0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgb.dxt1.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_8x8_rgb_dxt1 = [
-0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x40,0x55,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.dxt1.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_8x8_rgba_dxt1 = [
-0xe0,0x07,0x00,0xf8,0x13,0x13,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x43,0x57,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.dxt3.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_8x8_rgba_dxt3 = [
-0xf6,0xff,0xf6,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xf6,0xff,0xf6,0xff,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.dxt5.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_8x8_rgba_dxt5 = [
-0xff,0x69,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.pvrtc4bpp.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_8x8_rgba_pvrtc4bpp = [
-0x33,0x30,0x3f,0x00,0xe0,0x83,0x00,0xfc,0xcc,0xcf,0xc0,0xff,0xe0,0x83,0x1f,0xfc,0xcc,0xcf,0xc0,0xff,0xe0,0xff,0x1f,0x80,0x33,0x30,0x3f,0x00,0xfe,0x83,0x1f,0x80,
-];
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/compressed-textures/8x8.rgba.raw.js
+++ /dev/null
@@ -1,3 +0,0 @@
-var img_8x8_rgba_raw = [
-0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x69,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,
-];
--- a/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-standard-derivatives.html
@@ -115,18 +115,18 @@ if (!gl) {
     } else {
         testPassed("Successfully enabled OES_standard_derivatives extension");
 
         runSupportedTest(true);
 
         runHintTestEnabled();
         runShaderTests(true);
         runOutputTests();
-      // similar to bug 683216, see the discussion in bug 630672
-      // runUniqueObjectTest();
+        runUniqueObjectTest();
+        runReferenceCycleTest();
     }
 }
 
 function runSupportedTest(extensionEnabled) {
     var supported = gl.getSupportedExtensions();
     if (supported.indexOf("OES_standard_derivatives") >= 0) {
         if (extensionEnabled) {
             testPassed("OES_standard_derivatives listed as supported and getExtension succeeded");
@@ -252,21 +252,17 @@ function runOutputTests() {
     var e = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher
 
     debug("Testing various draws for valid built-in function behavior");
 
     canvas.width = 50; canvas.height = 50;
     gl.viewport(0, 0, canvas.width, canvas.height);
     gl.hint(ext.FRAGMENT_SHADER_DERIVATIVE_HINT_OES, gl.NICEST);
 
-    var shaders = [
-        wtu.loadShaderFromScript(gl, "outputVertexShader"),
-        wtu.loadShaderFromScript(gl, "outputFragmentShader")
-    ];
-    var program = wtu.setupProgram(gl, shaders, ['vPosition', 'texCoord0'], [0, 1]);
+    var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"], ['vPosition', 'texCoord0'], [0, 1]);
     var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
 
     function readLocation(x, y) {
         var pixels = new Uint8Array(1 * 1 * 4);
         var px = Math.floor(x * canvas.width);
         var py = Math.floor(y * canvas.height);
         gl.readPixels(px, py, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
         return pixels;
@@ -341,45 +337,38 @@ function runOutputTests() {
     setupBuffers(1.0, 0.5, 0.5, 0.0);
     wtu.drawQuad(gl);
     expectResult([3, 3, 5, 255],
                  "Draw 4 (variation in x & y) returned the correct data",
                  "Draw 4 (variation in x & y) returned incorrect data");
 
 }
 
-function attemptToForceGC()
-{
-    var holderArray = [];
-    var tempArray;
-    window.tempArray = holderArray;
-    for (var i = 0; i < 12; ++i) {
-        tempArray = [];
-        for (var j = 0; j < 1024 * 1024; ++j) {
-            tempArray.push(0);
-        }
-        holderArray.push(tempArray);
-    }
-    window.tempArray = null;
-}
-
 function runUniqueObjectTest()
 {
     debug("Testing that getExtension() returns the same object each time");
     gl.getExtension("OES_standard_derivatives").myProperty = 2;
-    if (window.GCController) {
-        window.GCController.collect();
-    } else if (window.opera && window.opera.collect) {
-        window.opera.collect();
-    } else {
-        attemptToForceGC();
-    }
+    gc();
     shouldBe('gl.getExtension("OES_standard_derivatives").myProperty', '2');
 }
 
+function runReferenceCycleTest()
+{
+    // create some reference cycles. The goal is to see if they cause leaks. The point is that
+    // some browser test runners have instrumentation to detect leaked refcounted objects.
+
+    debug("Testing reference cycles between context and extension objects");
+    var ext = gl.getExtension("OES_standard_derivatives");
+
+    // create cycle between extension and context, since the context has to hold a reference to the extension
+    ext.context = gl;
+
+    // create a self-cycle on the extension object
+    ext.ext = ext;
+}
 
 debug("");
 successfullyParsed = true;
 </script>
 <script src="../../resources/js-test-post.js"></script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
+++ b/content/canvas/test/webgl/conformance/extensions/oes-texture-float.html
@@ -61,17 +61,17 @@ var gl = create3DContext(canvas);
 
 if (!gl) {
   testFailed("WebGL context does not exist");
 } else {
   testPassed("WebGL context exists");
 
   var texturedShaders = [
       wtu.setupSimpleTextureVertexShader(gl),
-      wtu.loadShaderFromScript(gl, "testFragmentShader")
+      "testFragmentShader"
   ];
   var testProgram =
       wtu.setupProgram(gl,
                        texturedShaders,
                        ['vPosition', 'texCoord0'],
                        [0, 1]);
   var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
 
@@ -80,18 +80,18 @@ if (!gl) {
   runTextureCreationTest(testProgram, false);
 
   if (!gl.getExtension("OES_texture_float")) {
       testPassed("No OES_texture_float support -- this is legal");
   } else {
       testPassed("Successfully enabled OES_texture_float extension");
       runTextureCreationTest(testProgram, true);
       runRenderTargetTest(testProgram);
-      // bug 683216, see the discussion in bug 630672
-      // runUniqueObjectTest();
+      runUniqueObjectTest();
+      runReferenceCycleTest();
   }
 }
 
 // Needs to be global for shouldBe to see it.
 var pixels;
 
 function allocateTexture()
 {
@@ -160,67 +160,56 @@ function runRenderTargetTest(testProgram
     // While strictly speaking it is probably legal for a WebGL implementation to support
     // floating-point textures but not as attachments to framebuffer objects, any such
     // implementation is so poor that it arguably should not advertise support for the
     // OES_texture_float extension. For this reason the conformance test requires that the
     // framebuffer is complete here.
     if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)
         return;
 
-    var shaders = [
-        wtu.loadShaderFromScript(gl, "positionVertexShader"),
-        wtu.loadShaderFromScript(gl, "floatingPointFragmentShader")
-    ];
     var renderProgram =
         wtu.setupProgram(gl,
-                         shaders,
+                         ["positionVertexShader", "floatingPointFragmentShader"],
                          ['vPosition'],
                          [0]);
     wtu.drawQuad(gl);
     glErrorShouldBe(gl, gl.NO_ERROR, "rendering to floating-point texture should succeed");
 
     // Now sample from the floating-point texture and verify we got the correct values.
     gl.bindFramebuffer(gl.FRAMEBUFFER, null);
     gl.bindTexture(gl.TEXTURE_2D, texture);
     gl.useProgram(testProgram);
     gl.uniform1i(gl.getUniformLocation(testProgram, "tex"), 0);
     wtu.drawQuad(gl);
     glErrorShouldBe(gl, gl.NO_ERROR, "rendering from floating-point texture should succeed");
     checkRenderingResults();
 }
 
-function attemptToForceGC()
-{
-    var holderArray = [];
-    var tempArray;
-    window.tempArray = holderArray;
-    for (var i = 0; i < 12; ++i) {
-        tempArray = [];
-        for (var j = 0; j < 1024 * 1024; ++j) {
-            tempArray.push(0);
-        }
-        holderArray.push(tempArray);
-    }
-    window.tempArray = null;
-}
-
 function runUniqueObjectTest()
 {
     debug("Testing that getExtension() returns the same object each time");
     gl.getExtension("OES_texture_float").myProperty = 2;
-    if (window.GCController) {
-        window.GCController.collect();
-    } else if (window.opera && window.opera.collect) {
-        window.opera.collect();
-    } else {
-        attemptToForceGC();
-    }
+    gc();
     shouldBe('gl.getExtension("OES_texture_float").myProperty', '2');
 }
 
+function runReferenceCycleTest()
+{
+    // create some reference cycles. The goal is to see if they cause leaks. The point is that
+    // some browser test runners have instrumentation to detect leaked refcounted objects.
+
+    debug("Testing reference cycles between context and extension objects");
+    var ext = gl.getExtension("OES_texture_float");
+
+    // create cycle between extension and context, since the context has to hold a reference to the extension
+    ext.context = gl;
+
+    // create a self-cycle on the extension object
+    ext.ext = ext;
+}
 
 debug("");
 successfullyParsed = true;
 </script>
 <script src="../../resources/js-test-post.js"></script>
 
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/extensions/webgl-compressed-texture-s3tc.html
@@ -0,0 +1,614 @@
+<!--
+Copyright (c) 2012 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../resources/js-test-pre.js"></script>
+<script src="../resources/webgl-test.js"></script>
+<script src="../resources/webgl-test-utils.js"></script>
+<title>WebGL WEBGL_compressed_texture_s3tc Conformance Tests</title>
+<style>
+img {
+ border: 1px solid black;
+ margin-right: 1em;
+}
+.testimages {
+}
+
+.testimages br {
+  clear: both;
+}
+
+.testimages > div {
+  float: left;
+  margin: 1em;
+}
+</style>
+</head>
+<body>
+<div id="description"></div>
+<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
+<div id="console"></div>
+<script>
+description("This test verifies the functionality of the WEBGL_compressed_texture_s3tc extension, if it is available.");
+
+debug("");
+
+var img_4x4_rgba_raw = new Uint8Array([
+    0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,
+]);
+var img_4x4_rgb_dxt1 = new Uint8Array([
+    0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,
+]);
+var img_4x4_rgba_dxt1 = new Uint8Array([
+    0xe0,0x07,0x00,0xf8,0x13,0x10,0x15,0x00,
+]);
+var img_4x4_rgba_dxt3 = new Uint8Array([
+    0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
+]);
+var img_4x4_rgba_dxt5 = new Uint8Array([
+    0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
+]);
+var img_8x8_rgba_raw = new Uint8Array([
+    0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x69,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,
+]);
+var img_8x8_rgb_dxt1 = new Uint8Array([
+    0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x40,0x55,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
+]);
+var img_8x8_rgba_dxt1 = new Uint8Array([
+    0xe0,0x07,0x00,0xf8,0x13,0x13,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x43,0x57,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
+]);
+var img_8x8_rgba_dxt3 = new Uint8Array([
+    0xf6,0xff,0xf6,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xf6,0xff,0xf6,0xff,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
+]);
+var img_8x8_rgba_dxt5 = new Uint8Array([
+    0xff,0x69,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
+]);
+
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("canvas");
+var gl = wtu.create3DContext(canvas, {antialias: false});
+var program = wtu.setupTexturedQuad(gl);
+var ext = null;
+var vao = null;
+var validFormats = {
+    COMPRESSED_RGB_S3TC_DXT1_EXT        : 0x83F0,
+    COMPRESSED_RGBA_S3TC_DXT1_EXT       : 0x83F1,
+    COMPRESSED_RGBA_S3TC_DXT3_EXT       : 0x83F2,
+    COMPRESSED_RGBA_S3TC_DXT5_EXT       : 0x83F3,
+};
+var name;
+var supportedFormats;
+
+if (!gl) {
+    testFailed("WebGL context does not exist");
+} else {
+    testPassed("WebGL context exists");
+
+    // Run tests with extension disabled
+    runTestDisabled();
+
+    // Query the extension and store globally so shouldBe can access it
+    ext = gl.getExtension("WEBGL_compressed_texture_s3tc");
+    if (!ext) {
+        ext = gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");
+    }
+    if (!ext) {
+        testPassed("No WEBGL_compressed_texture_s3tc support -- this is legal");
+        runSupportedTest(false);
+    } else {
+        testPassed("Successfully enabled WEBGL_compressed_texture_s3tc extension");
+
+        runSupportedTest(true);
+        runTestExtension();
+    }
+}
+
+function runSupportedTest(extensionEnabled) {
+    var supported = gl.getSupportedExtensions();
+    if (supported.indexOf("WEBGL_compressed_texture_s3tc") >= 0 ||
+        supported.indexOf("WEBKIT_WEBGL_compressed_texture_s3tc") >= 0) {
+        if (extensionEnabled) {
+            testPassed("WEBGL_compressed_texture_s3tc listed as supported and getExtension succeeded");
+        } else {
+            testFailed("WEBGL_compressed_texture_s3tc listed as supported but getExtension failed");
+        }
+    } else {
+        if (extensionEnabled) {
+            testFailed("WEBGL_compressed_texture_s3tc not listed as supported but getExtension succeeded");
+        } else {
+            testPassed("WEBGL_compressed_texture_s3tc not listed as supported and getExtension failed -- this is legal");
+        }
+    }
+}
+
+
+function runTestDisabled() {
+    debug("Testing binding enum with extension disabled");
+
+    shouldBe('gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)', '[]');
+}
+
+function formatExists(format, supportedFormats) {
+    for (var ii = 0; ii < supportedFormats.length; ++ii) {
+        if (format == supportedFormats[ii]) {
+            testPassed("supported format " + formatToString(format) + " is exists");
+            return;
+        }
+    }
+    testFailed("supported format " + formatToString(format) + " does not exist");
+}
+
+function formatToString(format) {
+    for (var p in ext) {
+        if (ext[p] == format) {
+            return p;
+        }
+    }
+    return "0x" + format.toString(16);
+}
+
+function runTestExtension() {
+    debug("Testing WEBGL_compressed_texture_s3tc");
+
+    // check that all format enums exist.
+    for (name in validFormats) {
+        var expected = "0x" + validFormats[name].toString(16);
+        var actual = "ext['" + name + "']";
+        shouldBe(actual, expected);
+    }
+
+    supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
+    // There should be exactly 4 formats
+    shouldBe("supportedFormats.length", "4");
+
+    // check that all 4 formats exist
+    for (var name in validFormats.length) {
+        formatExists(validFormats[name], supportedFormats);
+    }
+
+    // Test each format
+    testDXT1_RGB();
+    testDXT1_RGBA();
+    testDXT3_RGBA();
+    testDXT5_RGBA();
+}
+
+function testDXT1_RGB() {
+    var tests = [
+        {   width: 4,
+            height: 4,
+            channels: 3,
+            data: img_4x4_rgb_dxt1,
+            format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
+        },
+        {   width: 8,
+            height: 8,
+            channels: 3,
+            data: img_8x8_rgb_dxt1,
+            format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
+        }
+    ];
+    testDXTTextures(tests);
+}
+
+function testDXT1_RGBA() {
+    var tests = [
+        {   width: 4,
+            height: 4,
+            channels: 4,
+            data: img_4x4_rgba_dxt1,
+            format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
+        },
+        {   width: 8,
+            height: 8,
+            channels: 4,
+            data: img_8x8_rgba_dxt1,
+            format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
+        }
+    ];
+    testDXTTextures(tests);
+}
+
+function testDXT3_RGBA() {
+    var tests = [
+        {   width: 4,
+            height: 4,
+            channels: 4,
+            data: img_4x4_rgba_dxt3,
+            format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT
+        },
+        {   width: 8,
+            height: 8,
+            channels: 4,
+            data: img_8x8_rgba_dxt3,
+            format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT
+        }
+    ];
+    testDXTTextures(tests);
+}
+
+function testDXT5_RGBA() {
+    var tests = [
+        {   width: 4,
+            height: 4,
+            channels: 4,
+            data: img_4x4_rgba_dxt5,
+            format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
+        },
+        {   width: 8,
+            height: 8,
+            channels: 4,
+            data: img_8x8_rgba_dxt5,
+            format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
+        }
+    ];
+    testDXTTextures(tests);
+}
+
+function testDXTTextures(tests) {
+    debug("<hr/>");
+    for (var ii = 0; ii < tests.length; ++ii) {
+        testDXTTexture(tests[ii]);
+    }
+}
+
+function uncompressDXTBlock(
+    destBuffer, destX, destY, destWidth, src, srcOffset, format) {
+    function make565(src, offset) {
+        return src[offset + 0] + src[offset + 1] * 256;
+    }
+    function make8888From565(c) {
+        return [
+                Math.floor(((c >> 11) & 0x1F) * 255 / 31),
+                Math.floor(((c >>    5) & 0x3F) * 255 / 63),
+                Math.floor(((c >>    0) & 0x1F) * 255 / 31),
+                255
+            ];
+    }
+    function mix(mult, c0, c1, div) {
+        var r = [];
+        for (var ii = 0; ii < c0.length; ++ii) {
+            r[ii] = Math.floor((c0[ii] * mult + c1[ii]) / div);
+        }
+        return r;
+    }
+    var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
+                 format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+    var colorOffset = srcOffset + (isDXT1 ? 0 : 8);
+    var color0 = make565(src, colorOffset + 0);
+    var color1 = make565(src, colorOffset + 2);
+    var c0gtc1 = color0 > color1 || !isDXT1;
+    var rgba0 = make8888From565(color0);
+    var rgba1 = make8888From565(color1);
+    var colors = [
+            rgba0,
+            rgba1,
+            c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
+            c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255]
+        ];
+
+    // yea I know there is a lot of math in this inner loop.
+    // so sue me.
+    for (var yy = 0; yy < 4; ++yy) {
+        var pixels = src[colorOffset + 4 + yy];
+        for (var xx = 0; xx < 4; ++xx) {
+            var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
+            var code = (pixels >> (xx * 2)) & 0x3;
+            var srcColor = colors[code];
+            var alpha;
+            switch (format) {
+            case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
+                alpha = 255;
+                break;
+            case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
+                alpha = (code == 3 && !c0gtc1) ? 0 : 255;
+                break;
+            case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT:
+                {
+                    var alpha0 = src[srcOffset + yy * 2 + Math.floor(xx / 2)];
+                    var alpha1 = (alpha0 >> ((xx % 2) * 4)) & 0xF;
+                    alpha = alpha1 | (alpha1 << 4);
+                }
+                break;
+            case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
+                {
+                    var alpha0 = src[srcOffset + 0];
+                    var alpha1 = src[srcOffset + 1];
+                    var alphaOff = Math.floor(yy / 2) * 3 + 2;
+                    var alphaBits =
+                         src[srcOffset + alphaOff + 0] +
+                         src[srcOffset + alphaOff + 1] * 256 +
+                         src[srcOffset + alphaOff + 2] * 65536;
+                    var alphaShift = (yy % 2) * 12 + xx * 3;
+                    var alphaCode = (alphaBits >> alphaShift) & 0x7;
+                    if (alpha0 > alpha1) {
+                        switch (alphaCode) {
+                        case 0:
+                            alpha = alpha0;
+                            break;
+                        case 1:
+                            alpha = alpha1;
+                            break;
+                        default:
+                            alpha = ((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7;
+                            break;
+                        }
+                    } else {
+                        switch (alphaCode) {
+                        case 0:
+                            alpha = alpha0;
+                            break;
+                        case 1:
+                            alpha = alpha1;
+                            break;
+                        case 6:
+                            alpha = 0;
+                            break;
+                        case 7:
+                            alpha = 255;
+                            break;
+                        default:
+                            alpha = ((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5;
+                            break;
+                        }
+                    }
+                }
+                break;
+            default:
+                throw "bad format";
+            }
+            destBuffer[dstOff + 0] = srcColor[0];
+            destBuffer[dstOff + 1] = srcColor[1];
+            destBuffer[dstOff + 2] = srcColor[2];
+            destBuffer[dstOff + 3] = alpha;
+        }
+    }
+}
+
+function getBlockSize(format) {
+  var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
+               format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+  return isDXT1 ? 8 : 16;
+}
+
+function uncompressDXT(width, height, data, format) {
+    if (width % 4 || height % 4) throw "bad width or height";
+
+    var dest = new Uint8Array(width * height * 4);
+    var blocksAcross = width / 4;
+    var blocksDown = height / 4;
+    var blockSize = getBlockSize(format);
+    for (var yy = 0; yy < blocksDown; ++yy) {
+        for (var xx = 0; xx < blocksAcross; ++xx) {
+            uncompressDXTBlock(
+                dest, xx * 4, yy * 4, width, data,
+                (yy * blocksAcross + xx) * blockSize, format);
+        }
+    }
+    return dest;
+}
+
+function copyRect(data, srcX, srcY, dstX, dstY, width, height, stride) {
+  var bytesPerLine = width * 4;
+  var srcOffset = srcX * 4 + srcY * stride;
+  var dstOffset = dstX * 4 + dstY * stride;
+  for (; height > 0; --height) {
+    for (var ii = 0; ii < bytesPerLine; ++ii) {
+      data[dstOffset + ii] = data[srcOffset + ii];
+    }
+    srcOffset += stride;
+    dstOffset += stride;
+  }
+}
+
+function testDXTTexture(test) {
+    var data = new Uint8Array(test.data);
+    var width = test.width;
+    var height = test.height;
+    var format = test.format;
+
+    var uncompressedData = uncompressDXT(width, height, data, format);
+
+    canvas.width = width;
+    canvas.height = height;
+    gl.viewport(0, 0, width, height);
+    debug("testing " + formatToString(format) + " " + width + "x" + height);
+    var tex = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, tex);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
+    glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+    wtu.drawQuad(gl);
+    compareRect(width, height, test.channels, width, height, uncompressedData, data, format);
+
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
+
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
+    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
+    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
+    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
+    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+
+    if (width == 4) {
+      gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data);
+      glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+      gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data);
+      glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+    }
+    if (height == 4) {
+      gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data);
+      glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+      gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data);
+      glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
+    }
+
+    // pick a wrong format that uses the same amount of data.
+    var wrongFormat;
+    switch (format) {
+    case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
+      wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
+      break;
+    case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
+      wrongFormat = ext.COMPRESSED_RGB_S3TC_DXT1_EXT;
+      break;
+    case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT:
+      wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
+      break;
+    case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
+      wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT;
+      break;
+    }
+
+    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, wrongFormat, data);
+    glErrorShouldBe(gl, gl.INVALID_OPERATION, "format does not match");
+
+    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width + 4, height, format, data);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height + 4, format, data);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 4, height, format, data);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 4, format, data);
+    glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
+
+    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 1, height, format, data);
+    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
+    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 1, format, data);
+    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+    gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
+    glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
+
+    var subData = new Uint8Array(data.buffer, 0, getBlockSize(format));
+
+    if (width == 8 && height == 8) {
+        gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 0, 4, 4, format, subData);
+        glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
+        gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 1, 4, 4, format, subData);
+        glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
+    }
+
+    var stride = width * 4;
+    for (var yoff = 0; yoff < height; yoff += 4) {
+        for (var xoff = 0; xoff < width; xoff += 4) {
+            copyRect(uncompressedData, 0, 0, xoff, yoff, 4, 4, stride);
+            gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, xoff, yoff, 4, 4, format, subData);
+            glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
+            wtu.drawQuad(gl);
+            compareRect(width, height, test.channels, width, height, uncompressedData, data, format);
+        }
+    }
+}
+
+function insertImg(element, caption, img) {
+    var div = document.createElement("div");
+    div.appendChild(img);
+    var label = document.createElement("div");
+    label.appendChild(document.createTextNode(caption));
+    div.appendChild(label);
+    element.appendChild(div);
+}
+
+function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
+    var scale = 8;
+    var c = document.createElement("canvas");
+    c.width = imageWidth * scale;
+    c.height = imageHeight * scale;
+    var ctx = c.getContext("2d");
+    for (var yy = 0; yy < imageWidth; ++yy) {
+        for (var xx = 0; xx < imageHeight; ++xx) {
+            var offset = (yy * dataWidth + xx) * 4;
+            ctx.fillStyle = "rgba(" +
+                    data[offset + 0] + "," +
+                    data[offset + 1] + "," +
+                    data[offset + 2] + "," +
+                    (alpha ? data[offset + 3] / 255 : 1) + ")";
+            ctx.fillRect(xx * scale, yy * scale, scale, scale);
+        }
+    }
+    var img = document.createElement("img");
+    img.src = c.toDataURL();
+    return img;
+}
+function compareRect(
+        actualWidth, actualHeight, actualChannels,
+        dataWidth, dataHeight, expectedData,
+        testData, testFormat) {
+    var actual = new Uint8Array(actualWidth * actualHeight * 4);
+    gl.readPixels(
+            0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
+
+    var div = document.createElement("div");
+    div.className = "testimages";
+    insertImg(div, "expected", makeImage(
+            actualWidth, actualHeight, dataWidth, expectedData,
+            actualChannels == 4));
+    insertImg(div, "actual", makeImage(
+            actualWidth, actualHeight, actualWidth, actual,
+            actualChannels == 4));
+    div.appendChild(document.createElement('br'));
+    document.getElementById("console").appendChild(div);
+
+    var failed = false;
+    for (var yy = 0; yy < actualHeight; ++yy) {
+        for (var xx = 0; xx < actualWidth; ++xx) {
+            var actualOffset = (yy * actualWidth + xx) * 4;
+            var expectedOffset = (yy * dataWidth + xx) * 4;
+            var expected = [
+                    expectedData[expectedOffset + 0],
+                    expectedData[expectedOffset + 1],
+                    expectedData[expectedOffset + 2],
+                    (actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
+            ];
+            for (var jj = 0; jj < 4; ++jj) {
+                if (actual[actualOffset + jj] != expected[jj]) {
+                    failed = true;
+                    var was = actual[actualOffset + 0].toString();
+                    for (j = 1; j < 4; ++j) {
+                        was += "," + actual[actualOffset + j];
+                    }
+                    testFailed('at (' + xx + ', ' + yy +
+                                         ') expected: ' + expected + ' was ' + was);
+                }
+            }
+        }
+    }
+    if (!failed) {
+        testPassed("texture rendered correctly");
+    }
+}
+
+function testPVRTCTextures() {
+    testFailed("PVRTC test not yet implemented");
+}
+
+debug("");
+successfullyParsed = true;
+</script>
+<script src="../../resources/js-test-post.js"></script>
+
+</body>
+</html>
--- a/content/canvas/test/webgl/conformance/extensions/webgl-debug-renderer-info.html
+++ b/content/canvas/test/webgl/conformance/extensions/webgl-debug-renderer-info.html
@@ -21,18 +21,17 @@ found in the LICENSE file.
 <!-- Shaders for testing standard derivatives -->
 
 <script>
 description("This test verifies the functionality of the WEBGL_debug_renderer_info extension, if it is available.");
 
 debug("");
 
 var wtu = WebGLTestUtils;
-var canvas = document.getElementById("canvas");
-var gl = create3DContext(canvas);
+var gl = wtu.create3DContext("canvas");
 var ext = null;
 var vao = null;
 
 if (!gl) {
     testFailed("WebGL context does not exist");
 } else {
     testPassed("WebGL context exists");
 
--- a/content/canvas/test/webgl/conformance/extensions/webgl-debug-shaders.html
+++ b/content/canvas/test/webgl/conformance/extensions/webgl-debug-shaders.html
@@ -21,18 +21,17 @@ found in the LICENSE file.
 <!-- Shaders for testing standard derivatives -->
 
 <script>
 description("This test verifies the functionality of the WEBGL_debug_shaders extension, if it is available.");
 
 debug("");
 
 var wtu = WebGLTestUtils;
-var canvas = document.getElementById("canvas");
-var gl = create3DContext(canvas);
+var gl = wtu.create3DContext("canvas");
 var ext = null;
 var shader = null;
 
 if (!gl) {
     testFailed("WebGL context does not exist");
 } else {
     testPassed("WebGL context exists");
 
deleted file mode 100644
--- a/content/canvas/test/webgl/conformance/extensions/webgl-experimental-compressed-textures.html
+++ /dev/null
@@ -1,520 +0,0 @@
-<!--
-Copyright (c) 2011 The Chromium Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
- -->
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>WebGL WEBGL_EXPERIMENTAL_compressed_textures Conformance Tests</title>
-<link rel="stylesheet" href="../../resources/js-test-style.css"/>
-<style>
-img {
- border: 1px solid black;
- margin-right: 1em;
-}
-.testimages {
-}
-
-.testimages br {
-  clear: both;
-}
-
-.testimages > div {
-  float: left;
-  margin: 1em;
-}
-</style>
-<script src="../../resources/desktop-gl-constants.js" type="text/javascript"></script>
-<script src="../../resources/js-test-pre.js"></script>
-<script src="../resources/webgl-test.js"></script>
-<script src="../resources/webgl-test-utils.js"></script>
-<script src="compressed-textures/4x4.rgb.dxt1.js"></script>
-<script src="compressed-textures/4x4.rgba.dxt1.js"></script>
-<script src="compressed-textures/4x4.rgba.dxt5.js"></script>
-<script src="compressed-textures/8x8.rgb.dxt1.js"></script>
-<script src="compressed-textures/8x8.rgba.dxt1.js"></script>
-<script src="compressed-textures/8x8.rgba.dxt5.js"></script>
-<script src="compressed-textures/8x8.rgba.pvrtc4bpp.js"></script>
-</head>
-<body>
-<div id="description"></div>
-<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
-<div id="console"></div>
-<!-- Shaders for testing standard derivatives -->
-<script>
-description("This test verifies the functionality of the OES_vertex_array_object extension, if it is available.");
-
-debug("");
-
-var wtu = WebGLTestUtils;
-var canvas = document.getElementById("canvas");
-var gl = wtu.create3DContext(canvas, {antialias: false});
-var program = wtu.setupTexturedQuad(gl);
-var ext = null;
-var vao = null;
-var validFormats = {
-  COMPRESSED_RGB_S3TC_DXT1_EXT        : 0x83F0,
-  COMPRESSED_RGBA_S3TC_DXT1_EXT       : 0x83F1,
-  COMPRESSED_RGBA_S3TC_DXT5_EXT       : 0x83F3,
-  ETC1_RGB8_OES                       : 0x8D64,
-  COMPRESSED_RGB_PVRTC_4BPPV1_IMG     : 0x8C00,
-  COMPRESSED_RGBA_PVRTC_4BPPV1_IMG    : 0x8C02
-};
-var name;
-var supportedFormats;
-
-if (!gl) {
-  testFailed("WebGL context does not exist");
-} else {
-  testPassed("WebGL context exists");
-
-  // Run tests with extension disabled
-  runTestDisabled();
-
-  // Query the extension and store globally so shouldBe can access it
-  ext = gl.getExtension("WEBGL_EXPERIMENTAL_compressed_textures");
-  if (!ext) {
-    testPassed("No WEBGL_EXPERIMENTAL_compressed_textures support -- this is legal");
-    runSupportedTest(false);
-  } else {
-    testPassed("Successfully enabled WEBGL_EXPERIMENTAL_compressed_textures extension");
-
-    runSupportedTest(true);
-    runTestExtension();
-  }
-}
-
-function runSupportedTest(extensionEnabled) {
-  var supported = gl.getSupportedExtensions();
-  if (supported.indexOf("WEBGL_EXPERIMENTAL_compressed_textures") >= 0) {
-    if (extensionEnabled) {
-      testPassed("WEBGL_EXPERIMENTAL_compressed_textures listed as supported and getExtension succeeded");
-    } else {
-      testFailed("WEBGL_EXPERIMENTAL_compressed_textures listed as supported but getExtension failed");
-    }
-  } else {
-    if (extensionEnabled) {
-      testFailed("WEBGL_EXPERIMENTAL_compressed_textures not listed as supported but getExtension succeeded");
-    } else {
-      testPassed("WEBGL_EXPERIMENTAL_compressed_textures not listed as supported and getExtension failed -- this is legal");
-    }
-  }
-}
-
-
-function runTestDisabled() {
-  debug("Testing binding enum with extension disabled");
-
-  // Default value is null
-  if (gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS) === null) {
-    testPassed("Default value of COMPRESSED_TEXTURE_FORMATS is null");
-  } else {
-    testFailed("Default value of COMPRESSED_TEXTURE_FORMATS is not null");
-  }
-}
-
-function checkIsValidFormat(format) {
-  for (var name in validFormats) {
-    if (format == validFormats[name]) {
-      testPassed("supported format " + formatToString(format) + " is valid");
-      return;
-    }
-  }
-  testFailed("supported format " + formatToString(format) + " is not valid");
-}
-
-function formatToString(format) {
-  for (var p in ext) {
-    if (ext[p] == format) {
-      return p;
-    }
-  }
-  return "0x" + format.toString(16);
-}
-
-function runTestExtension() {
-  debug("Testing WEBGL_EXPERIMENTAL_compressed_textures");
-
-  // check that all format enums exist.
-  for (name in validFormats) {
-    var expected = "0x" + validFormats[name].toString(16);
-    var actual = "ext['" + name + "']";
-    shouldBe(actual, expected);
-  }
-
-  supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
-  // Even if no formats are supported this should return an array.
-  shouldBeTrue("supportedFormats.length !== undefined");
-
-  // check that each format is an allowed format
-  for (var ii = 0; ii < supportedFormats.length; ++ii) {
-    checkIsValidFormat(supportedFormats[ii]);
-  }
-
-  // Test each format
-  for (var ii = 0; ii < supportedFormats.length; ++ii) {
-    switch (supportedFormats[ii]) {
-    case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
-      testDXT1_RGB();
-      break;
-    case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
-      testDXT1_RGBA();
-      break;
-    case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
-      testDXT5_RGBA();
-      break;
-    case ext.ETC1_RGB8_OES:
-      testETC1_RGB8();
-      break;
-    case ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
-      testPVRTC_RGB_4BPPV1();
-      break;
-    case ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
-      testPVRTC_RGBA_4BPPV1();
-      break;
-    }
-  }
-}
-
-function testDXT1_RGB() {
-  var tests = [
-    { width: 4,
-      height: 4,
-      channels: 3,
-      data: img_4x4_rgb_dxt1,
-      format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
-    },
-    { width: 8,
-      height: 8,
-      channels: 3,
-      data: img_8x8_rgb_dxt1,
-      format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
-    }
-  ];
-  testDXTTextures(tests);
-}
-
-function testDXT1_RGBA() {
-  var tests = [
-    { width: 4,
-      height: 4,
-      channels: 4,
-      data: img_4x4_rgba_dxt1,
-      format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
-    },
-    { width: 8,
-      height: 8,
-      channels: 4,
-      data: img_8x8_rgba_dxt1,
-      format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
-    }
-  ];
-  testDXTTextures(tests);
-}
-
-function testDXT5_RGBA() {
-  var tests = [
-    { width: 4,
-      height: 4,
-      channels: 4,
-      data: img_4x4_rgba_dxt5,
-      format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
-    },
-    { width: 8,
-      height: 8,
-      channels: 4,
-      data: img_8x8_rgba_dxt5,
-      format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
-    }
-  ];
-  testDXTTextures(tests);
-}
-
-function testETC1_RGB8() {
-  testFailed("ETC1 test not yet implemented");
-}
-
-function testPVRTC_RGB_4BPPV1() {
-  var tests = [
-    { width: 8,
-      height: 8,
-      channels: 4,
-      data: img_8x8_rgba_pvrtc4bpp,
-      format: ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
-    }
-  ];
-  testPVRTCTextures(tests);
-}
-
-function testPVRTC_RGB_4BPPV1() {
-  var tests = [
-    { width: 8,
-      height: 8,
-      channels: 4,
-      data: img_8x8_rgba_pvrtc4bpp,
-      format: ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
-    }
-  ];
-  testPVRTCTextures(tests);
-}
-
-function testDXTTextures(tests) {
-  debug("<hr/>");
-  for (var ii = 0; ii < tests.length; ++ii) {
-    testDXTTexture(tests[ii]);
-  }
-}
-
-function uncompressDXTBlock(
-    destBuffer, destX, destY, destWidth, src, srcOffset, format) {
-  function make565(src, offset) {
-    return src[offset + 0] + src[offset + 1] * 256;
-  }
-  function make8888From565(c) {
-    return [
-        Math.floor(((c >> 11) & 0x1F) * 255 / 31),
-        Math.floor(((c >>  5) & 0x3F) * 255 / 63),
-        Math.floor(((c >>  0) & 0x1F) * 255 / 31),
-        255
-      ];
-  }
-  function mix(mult, c0, c1, div) {
-    var r = [];
-    for (var ii = 0; ii < c0.length; ++ii) {
-      r[ii] = Math.floor((c0[ii] * mult + c1[ii]) / div);
-    }
-    return r;
-  }
-  var colorOffset =
-      srcOffset + ((format == ext.COMPRESSED_RGBA_S3TC_DXT5_EXT) ? 8 : 0);
-  var color0 = make565(src, colorOffset + 0);
-  var color1 = make565(src, colorOffset + 2);
-  var c0gtc1 = color0 > color1 || format == ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
-  var rgba0 = make8888From565(color0);
-  var rgba1 = make8888From565(color1);
-  var colors = [
-      rgba0,
-      rgba1,
-      c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
-      c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255]
-    ];
-
-  // yea I know there is a lot of math in this inner loop.
-  // so sue me.
-  for (var yy = 0; yy < 4; ++yy) {
-    var pixels = src[colorOffset + 4 + yy];
-    for (var xx = 0; xx < 4; ++xx) {
-      var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
-      var code = (pixels >> (xx * 2)) & 0x3;
-      var srcColor = colors[code];
-      var alpha;
-      switch (format) {
-      case ext.COMPRESSED_RGB_S