Merge mozilla-central with electrolysis.
authorBenjamin Smedberg <benjamin@smedbergs.us>
Mon, 25 Jan 2010 11:57:19 -0500
changeset 46576 a5db6b7b9c189a631a3c65777a28a9e3657435f7
parent 46575 69f4e7d5553c84d0bcd59c6e35ef1a2c83f2f407 (current diff)
parent 37483 fc6c823b524ae77fc56bc0dd447d86d4cf063310 (diff)
child 46577 38cbc1637ad32aa48ab9d3cb7ed63807366eac1f
push idunknown
push userunknown
push dateunknown
milestone1.9.3a1pre
Merge mozilla-central with electrolysis.
content/base/src/Makefile.in
content/base/src/nsGkAtomList.h
content/canvas/src/Makefile.in
content/canvas/src/SimpleBuffer.h
content/canvas/src/WebGLArrays.cpp
content/canvas/src/WebGLArrays.h
content/canvas/src/WebGLContext.h
dom/plugins/PluginInstanceChild.cpp
dom/plugins/PluginMessageUtils.h
dom/plugins/PluginModuleChild.cpp
modules/plugin/test/mochitest/test_npapi_timers.xul
modules/plugin/test/testplugin/nptest.cpp
--- a/Makefile.in
+++ b/Makefile.in
@@ -83,24 +83,38 @@ include $(topsrcdir)/config/config.mk
 
 GARBAGE_DIRS += dist _javagen _profile _tests staticlib
 DIST_GARBAGE = config.cache config.log config.status config-defs.h \
    dependencies.beos config/autoconf.mk config/myrules.mk config/myconfig.mk \
    unallmakefiles mozilla-config.h \
    netwerk/necko-config.h xpcom/xpcom-config.h xpcom/xpcom-private.h \
    $(topsrcdir)/.mozconfig.mk $(topsrcdir)/.mozconfig.out
 
-default alldep all::
+default alldep all:: $(topsrcdir)/configure config.status
 	$(RM) -rf $(DIST)/sdk
 	$(RM) -rf $(DIST)/include
 	$(RM) -rf $(DIST)/private
 	$(RM) -rf $(DIST)/public
 	$(RM) -rf $(DIST)/bin/components
 	$(RM) -rf _tests
 
+$(topsrcdir)/configure: $(topsrcdir)/configure.in
+	@echo "STOP!  configure.in has changed, and your configure is out of date."
+	@echo "Please rerun autoconf and re-configure your build directory."
+	@echo "To ignore this message, touch 'configure' in the source directory,"
+	@echo "but your build might not succeed."
+	@exit 1
+
+config.status: $(topsrcdir)/configure
+	@echo "STOP!  configure has changed and needs to be run in this build directory."
+	@echo "Please rerun configure."
+	@echo "To ignore this message, touch 'config.status' in the build directory,"
+	@echo "but your build might not succeed."
+	@exit 1
+
 # Build pseudo-external modules first when export is explicitly called
 export::
 	$(RM) -rf $(DIST)/sdk
 	$(MAKE) -C config export
 	$(MAKE) tier_nspr
 
 ifdef ENABLE_TESTS
 # Additional makefile targets to call automated test suites
--- a/accessible/public/nsIAccessibilityService.idl
+++ b/accessible/public/nsIAccessibilityService.idl
@@ -34,24 +34,22 @@
  * 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 "nsISupports.idl"
 #include "nsIAccessibleRetrieval.idl"
 
-interface nsIAccessibleEventListener;
 interface nsIDocument;
 interface nsIFrame;
 interface nsObjectFrame;
 interface nsIContent;
-interface nsITimer;
 
-[uuid(61098f48-4fcc-4b05-9cf3-c11b8efbe682)]
+[uuid(e0498def-1552-4763-8c47-6c6cc36c7aa0)]
 interface nsIAccessibilityService : nsIAccessibleRetrieval
 {
   nsIAccessible createOuterDocAccessible(in nsIDOMNode aNode);
   nsIAccessible createRootAccessible(in nsIPresShell aShell, in nsIDocument aDocument);
 
   nsIAccessible createHTML4ButtonAccessible(in nsIFrame aFrame);
   nsIAccessible createHyperTextAccessible(in nsIFrame aFrame);
   nsIAccessible createHTMLBRAccessible(in nsIFrame aFrame);
@@ -109,26 +107,16 @@ interface nsIAccessibilityService : nsIA
    * @param aPresShell   [in] the presShell where changes occured
    * @param aContent     [in] the affected DOM content
    * @param aChangeType  [in] the change type (see constants declared above)
    */
   void invalidateSubtreeFor(in nsIPresShell aPresShell, in nsIContent aContent,
                             in PRUint32 aChangeType);
 
   /**
-   *  An internal doc load event has occured. Handle the event and remove it from the list.
-   *  @param aTimer      The timer created to handle this doc load event
-   *  @param aClosure    The nsIWebProgress* for the load event
-   *  @param aEventType  The type of load event, one of: nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START,
-   *                                                     nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE or
-   *                                                     nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED
-   */
-  void processDocLoadEvent(in nsITimer aTimer, in voidPtr aClosure, in PRUint32 aEventType);
-
-  /**
    * Notify accessibility that anchor jump has been accomplished to the given
    * target. Used by layout.
    */
   void notifyOfAnchorJumpTo(in nsIContent aTarget);
 
   /**
    * Fire accessible event of the given type for the given target.
    *
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -59,28 +59,26 @@
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIFrame.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsPresContext.h"
 #include "nsIPresShell.h"
 #include "nsIServiceManager.h"
 #include "nsIStringBundle.h"
-#include "nsITimer.h"
 #include "nsRootAccessible.h"
 #include "nsFocusManager.h"
 #include "nsIObserverService.h"
 
 /* For documentation of the accessibility architecture, 
  * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
  */
 
 nsIStringBundle *nsAccessNode::gStringBundle = 0;
 nsIStringBundle *nsAccessNode::gKeyStringBundle = 0;
-nsITimer *nsAccessNode::gDoCommandTimer = 0;
 nsIDOMNode *nsAccessNode::gLastFocusedNode = 0;
 #ifdef DEBUG
 PRBool nsAccessNode::gIsAccessibilityActive = PR_FALSE;
 #endif
 PRBool nsAccessNode::gIsCacheDisabled = PR_FALSE;
 PRBool nsAccessNode::gIsFormFillEnabled = PR_FALSE;
 nsAccessNodeHashtable nsAccessNode::gGlobalDocAccessibleCache;
 
@@ -305,17 +303,16 @@ void nsAccessNode::ShutdownXPAccessibili
   // Called by nsAccessibilityService::Shutdown()
   // which happens when xpcom is shutting down
   // at exit of program
 
   NS_ASSERTION(gIsAccessibilityActive, "Accessibility was shutdown already!");
 
   NS_IF_RELEASE(gStringBundle);
   NS_IF_RELEASE(gKeyStringBundle);
-  NS_IF_RELEASE(gDoCommandTimer);
   NS_IF_RELEASE(gLastFocusedNode);
 
   nsApplicationAccessibleWrap::Unload();
   ClearCache(gGlobalDocAccessibleCache);
 
   // Release gApplicationAccessible after everything else is shutdown
   // so we don't accidently create it again while tearing down root accessibles
   NS_IF_RELEASE(gApplicationAccessible);
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -58,17 +58,16 @@
 #include "nsInterfaceHashtable.h"
 #include "nsIAccessibilityService.h"
 
 class nsIPresShell;
 class nsPresContext;
 class nsIAccessibleDocument;
 class nsIFrame;
 class nsIDOMNodeList;
-class nsITimer;
 class nsRootAccessible;
 class nsApplicationAccessibleWrap;
 class nsIDocShellTreeItem;
 
 #define ACCESSIBLE_BUNDLE_URL "chrome://global-platform/locale/accessible.properties"
 #define PLATFORM_KEYS_BUNDLE_URL "chrome://global-platform/locale/platformKeys.properties"
 
 typedef nsInterfaceHashtable<nsVoidPtrHashKey, nsIAccessNode>
@@ -186,17 +185,17 @@ protected:
     /**
      * Notify global nsIObserver's that a11y is getting init'd or shutdown
      */
     static void NotifyA11yInitOrShutdown(PRBool aIsInit);
 
     // Static data, we do our own refcounting for our static data
     static nsIStringBundle *gStringBundle;
     static nsIStringBundle *gKeyStringBundle;
-    static nsITimer *gDoCommandTimer;
+
 #ifdef DEBUG
     static PRBool gIsAccessibilityActive;
 #endif
     static PRBool gIsCacheDisabled;
     static PRBool gIsFormFillEnabled;
 
     static nsAccessNodeHashtable gGlobalDocAccessibleCache;
 
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -156,29 +156,16 @@ nsAccessibilityService::Observe(nsISuppo
       do_GetService("@mozilla.org/observer-service;1");
     if (observerService) {
       observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
     }
     nsCOMPtr<nsIWebProgress> progress(do_GetService(NS_DOCUMENTLOADER_SERVICE_CONTRACTID));
     if (progress)
       progress->RemoveProgressListener(static_cast<nsIWebProgressListener*>(this));
 
-    // Cancel and release load timers.
-    while (mLoadTimers.Count() > 0 ) {
-      nsCOMPtr<nsITimer> timer = mLoadTimers.ObjectAt(0);
-      void *closure = nsnull;
-      timer->GetClosure(&closure);
-      if (closure) {
-        nsIWebProgress *webProgress = static_cast<nsIWebProgress*>(closure);
-        NS_RELEASE(webProgress);  // Release nsIWebProgress for timer
-      }
-      timer->Cancel();
-      mLoadTimers.RemoveObjectAt(0);
-    }
-
     // Application is going to be closed, shutdown accessibility and mark
     // accessibility service as shutdown to prevent calls of its methods.
     // Don't null accessibility service static member at this point to be safe
     // if someone will try to operate with it.
 
     NS_ASSERTION(!gIsShutdown, "Accessibility was shutdown already");
 
     gIsShutdown = PR_TRUE;
@@ -201,72 +188,68 @@ NS_IMETHODIMP nsAccessibilityService::On
   
   nsCAutoString name;
   aRequest->GetName(name);
   if (name.EqualsLiteral("about:blank"))
     return NS_OK;
 
   if (NS_FAILED(aStatus) && (aStateFlags & STATE_START))
     return NS_OK;
- 
-  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
-  if (!timer)
-    return NS_OK;
-  mLoadTimers.AppendObject(timer);
-  NS_ADDREF(aWebProgress);
 
-  if (aStateFlags & STATE_START)
-    timer->InitWithFuncCallback(StartLoadCallback, aWebProgress, 0,
-                                nsITimer::TYPE_ONE_SHOT);
-  else if (NS_SUCCEEDED(aStatus)) 
-    timer->InitWithFuncCallback(EndLoadCallback, aWebProgress, 0,
-                                nsITimer::TYPE_ONE_SHOT);
-  else // Failed end load
-    timer->InitWithFuncCallback(FailedLoadCallback, aWebProgress, 0,
-                                nsITimer::TYPE_ONE_SHOT);
+  if (aStateFlags & STATE_START) {
+    NS_DISPATCH_RUNNABLEMETHOD_ARG2(ProcessDocLoadEvent, this, aWebProgress,
+                                    nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START)
+  } else if (NS_SUCCEEDED(aStatus)) {
+    NS_DISPATCH_RUNNABLEMETHOD_ARG2(ProcessDocLoadEvent, this, aWebProgress,
+                                    nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE)
+  } else { // Failed end load
+    NS_DISPATCH_RUNNABLEMETHOD_ARG2(ProcessDocLoadEvent, this, aWebProgress,
+                                    nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED)
+  }
+
   return NS_OK;
 }
 
-NS_IMETHODIMP nsAccessibilityService::ProcessDocLoadEvent(nsITimer *aTimer, void *aClosure, PRUint32 aEventType)
+void
+nsAccessibilityService::ProcessDocLoadEvent(nsIWebProgress *aWebProgress,
+                                            PRUint32 aEventType)
 {
+  if (gIsShutdown)
+    return;
+
   nsCOMPtr<nsIDOMWindow> domWindow;
-  nsIWebProgress *webProgress = static_cast<nsIWebProgress*>(aClosure);
-  webProgress->GetDOMWindow(getter_AddRefs(domWindow));
-  NS_RELEASE(webProgress);
-  mLoadTimers.RemoveObject(aTimer);
-  NS_ENSURE_STATE(domWindow);
+  aWebProgress->GetDOMWindow(getter_AddRefs(domWindow));
+  NS_ENSURE_TRUE(domWindow,);
 
   if (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START) {
     nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(domWindow));
     nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(webNav));
-    NS_ENSURE_STATE(docShell);
+    NS_ENSURE_TRUE(docShell,);
     PRUint32 loadType;
     docShell->GetLoadType(&loadType);
     if (loadType == LOAD_RELOAD_NORMAL ||
         loadType == LOAD_RELOAD_BYPASS_CACHE ||
         loadType == LOAD_RELOAD_BYPASS_PROXY ||
         loadType == LOAD_RELOAD_BYPASS_PROXY_AND_CACHE) {
       aEventType = nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD;
     }
   }
       
   nsCOMPtr<nsIDOMDocument> domDoc;
   domWindow->GetDocument(getter_AddRefs(domDoc));
   nsCOMPtr<nsIDOMNode> docNode = do_QueryInterface(domDoc);
-  NS_ENSURE_STATE(docNode);
+  NS_ENSURE_TRUE(docNode,);
 
   nsCOMPtr<nsIAccessible> accessible;
   GetAccessibleFor(docNode, getter_AddRefs(accessible));
   nsRefPtr<nsDocAccessible> docAcc =
     nsAccUtils::QueryAccessibleDocument(accessible);
-  NS_ENSURE_STATE(docAcc);
+  NS_ENSURE_TRUE(docAcc,);
 
   docAcc->FireDocLoadEvents(aEventType);
-
-  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessibilityService::NotifyOfAnchorJumpTo(nsIContent *aTarget)
 {
   nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(aTarget));
 
   nsCOMPtr<nsIAccessible> targetAcc;
@@ -296,40 +279,16 @@ nsAccessibilityService::NotifyOfAnchorJu
 NS_IMETHODIMP
 nsAccessibilityService::FireAccessibleEvent(PRUint32 aEvent,
                                             nsIAccessible *aTarget)
 {
   nsEventShell::FireEvent(aEvent, aTarget);
   return NS_OK;
 }
 
-void nsAccessibilityService::StartLoadCallback(nsITimer *aTimer, void *aClosure)
-{
-  if (gAccessibilityService)
-    gAccessibilityService->
-      ProcessDocLoadEvent(aTimer, aClosure,
-                          nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START);
-}
-
-void nsAccessibilityService::EndLoadCallback(nsITimer *aTimer, void *aClosure)
-{
-  if (gAccessibilityService)
-    gAccessibilityService->
-      ProcessDocLoadEvent(aTimer, aClosure,
-                          nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE);
-}
-
-void nsAccessibilityService::FailedLoadCallback(nsITimer *aTimer, void *aClosure)
-{
-  if (gAccessibilityService)
-    gAccessibilityService->
-      ProcessDocLoadEvent(aTimer, aClosure,
-                          nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
-}
-
 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
 NS_IMETHODIMP nsAccessibilityService::OnProgressChange(nsIWebProgress *aWebProgress,
   nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress,
   PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
 {
   NS_NOTREACHED("notification excluded in AddProgressListener(...)");
   return NS_OK;
 }
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -35,19 +35,21 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef __nsAccessibilityService_h__
 #define __nsAccessibilityService_h__
 
 #include "nsIAccessibilityService.h"
+
+#include "nsCoreUtils.h"
+
 #include "nsCOMArray.h"
 #include "nsIObserver.h"
-#include "nsITimer.h"
 #include "nsIWebProgress.h"
 #include "nsIWebProgressListener.h"
 #include "nsWeakReference.h"
 
 class nsIFrame;
 class nsIWeakReference;
 class nsIDOMNode;
 class nsObjectFrame;
@@ -152,20 +154,29 @@ private:
    * A universal ARIA property is one that can be defined on any element even if there is no role.
    *
    * @param aContent The content node to test
    * @param aWeakShell  A weak reference to the pres shell
    * @return PR_TRUE if there is a universal ARIA property set on the node
    */
   PRBool HasUniversalAriaProperty(nsIContent *aContent, nsIWeakReference *aWeakShell);
 
-  static void StartLoadCallback(nsITimer *aTimer, void *aClosure);
-  static void EndLoadCallback(nsITimer *aTimer, void *aClosure);
-  static void FailedLoadCallback(nsITimer *aTimer, void *aClosure);
-  nsCOMArray<nsITimer> mLoadTimers;
+  /**
+   *  Process the internal doc load event.
+   *
+   *  @param  aWebProgress  [in] the nsIWebProgress object for the load event
+   *  @param  aEventType    [in] the type of load event, one of:
+   *                          nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_START,
+   *                          nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE,
+   *                          nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED
+   */
+  void ProcessDocLoadEvent(nsIWebProgress *aWebProgress, PRUint32 aEventType);
+
+  NS_DECL_RUNNABLEMETHOD_ARG2(nsAccessibilityService, ProcessDocLoadEvent,
+                              nsCOMPtr<nsIWebProgress>, PRUint32)
 };
 
 /**
  * Map nsIAccessibleRole constants to strings. Used by
  * nsIAccessibleRetrieval::getStringRole() method.
  */
 static const char kRoleNames[][20] = {
   "nothing",             //ROLE_NOTHING
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -79,17 +79,16 @@
 #include "nsXPIDLString.h"
 #include "nsUnicharUtils.h"
 #include "nsReadableUtils.h"
 #include "prdtoa.h"
 #include "nsIAtom.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsIURI.h"
-#include "nsITimer.h"
 #include "nsArrayUtils.h"
 #include "nsIMutableArray.h"
 #include "nsIObserverService.h"
 #include "nsIServiceManager.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsAttrName.h"
 #include "nsNetUtil.h"
 
@@ -2115,18 +2114,18 @@ nsAccessible::DoAction(PRUint8 aIndex)
 {
   if (aIndex != 0)
     return NS_ERROR_INVALID_ARG;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   if (GetActionRule(nsAccUtils::State(this)) != eNoAction) {
-    nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
-    return DoCommand(content);
+    DoCommand();
+    return NS_OK;
   }
 
   return NS_ERROR_INVALID_ARG;
 }
 
 /* DOMString getHelp (); */
 NS_IMETHODIMP nsAccessible::GetHelp(nsAString& _retval)
 {
@@ -2487,54 +2486,25 @@ NS_IMETHODIMP nsAccessible::ExtendSelect
 }
 
 /* [noscript] void getNativeInterface(out voidPtr aOutAccessible); */
 NS_IMETHODIMP nsAccessible::GetNativeInterface(void **aOutAccessible)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-nsresult
+void
 nsAccessible::DoCommand(nsIContent *aContent, PRUint32 aActionIndex)
 {
-  if (gDoCommandTimer) {
-    // Already have timer going for another command
-    NS_WARNING("Doubling up on do command timers doesn't work. This wasn't expected.");
-    return NS_ERROR_FAILURE;
-  }
-
-  nsCOMPtr<nsITimer> timer = do_CreateInstance("@mozilla.org/timer;1");
-  NS_ENSURE_TRUE(timer, NS_ERROR_OUT_OF_MEMORY);
-
   nsCOMPtr<nsIContent> content = aContent;
   if (!content)
     content = do_QueryInterface(mDOMNode);
 
-  // Command closure object memory will be free in DoCommandCallback().
-  nsCommandClosure *closure =
-    new nsCommandClosure(this, content, aActionIndex);
-  NS_ENSURE_TRUE(closure, NS_ERROR_OUT_OF_MEMORY);
-
-  NS_ADDREF(gDoCommandTimer = timer);
-  return gDoCommandTimer->InitWithFuncCallback(DoCommandCallback,
-                                               static_cast<void*>(closure),
-                                               0, nsITimer::TYPE_ONE_SHOT);
-}
-
-void
-nsAccessible::DoCommandCallback(nsITimer *aTimer, void *aClosure)
-{
-  NS_ASSERTION(gDoCommandTimer,
-               "How did we get here if there was no gDoCommandTimer?");
-  NS_RELEASE(gDoCommandTimer);
-
-  nsCommandClosure *closure = static_cast<nsCommandClosure*>(aClosure);
-  closure->accessible->DispatchClickEvent(closure->content,
-                                          closure->actionIndex);
-  delete closure;
+  NS_DISPATCH_RUNNABLEMETHOD_ARG2(DispatchClickEvent, this,
+                                  content, aActionIndex)
 }
 
 void
 nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex)
 {
   if (IsDefunct())
     return;
 
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -370,56 +370,37 @@ protected:
 
   // Hyperlink helpers
   virtual nsresult GetLinkOffset(PRInt32* aStartOffset, PRInt32* aEndOffset);
 
   //////////////////////////////////////////////////////////////////////////////
   // Action helpers
 
   /**
-   * Used to describe click action target. See DoCommand() method.
-   */
-  struct nsCommandClosure
-  {
-    nsCommandClosure(nsAccessible *aAccessible, nsIContent *aContent,
-                     PRUint32 aActionIndex) :
-      accessible(aAccessible), content(aContent), actionIndex(aActionIndex) {}
-
-    nsRefPtr<nsAccessible> accessible;
-    nsCOMPtr<nsIContent> content;
-    PRUint32 actionIndex;
-  };
-
-  /**
    * Prepares click action that will be invoked in timeout.
    *
    * @note  DoCommand() prepares an action in timeout because when action
    *  command opens a modal dialog/window, it won't return until the
    *  dialog/window is closed. If executing action command directly in
    *  nsIAccessible::DoAction() method, it will block AT tools (e.g. GOK) that
    *  invoke action of mozilla accessibles direclty (see bug 277888 for details).
    *
    * @param  aContent      [in, optional] element to click
    * @param  aActionIndex  [in, optional] index of accessible action
    */
-  nsresult DoCommand(nsIContent *aContent = nsnull, PRUint32 aActionIndex = 0);
-
-  /**
-   * Dispatch click event to target by calling DispatchClickEvent() method.
-   *
-   * @param  aTimer    [in] timer object
-   * @param  aClosure  [in] nsCommandClosure object describing a target.
-   */
-  static void DoCommandCallback(nsITimer *aTimer, void *aClosure);
+  void DoCommand(nsIContent *aContent = nsnull, PRUint32 aActionIndex = 0);
 
   /**
    * Dispatch click event.
    */
   virtual void DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex);
 
+  NS_DECL_RUNNABLEMETHOD_ARG2(nsAccessible, DispatchClickEvent,
+                              nsCOMPtr<nsIContent>, PRUint32)
+
   //////////////////////////////////////////////////////////////////////////////
   // Helpers
 
   // Check the visibility across both parent content and chrome
   PRBool CheckVisibilityInParentChain(nsIDocument* aDocument, nsIView* aView);
 
   /**
    *  Get the container node for an atomic region, defined by aria-atomic="true"
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -51,17 +51,16 @@
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMRange.h"
 #include "nsIDOMViewCSS.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocShell.h"
-#include "nsIDocumentViewer.h"
 #include "nsIContentViewer.h"
 #include "nsIEventListenerManager.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIScrollableFrame.h"
 #include "nsIEventStateManager.h"
 #include "nsISelection2.h"
 #include "nsISelectionController.h"
@@ -555,27 +554,22 @@ nsCoreUtils::GetDOMNodeForContainer(nsID
   nsCOMPtr<nsIDocShell> shell = do_QueryInterface(aContainer);
 
   nsCOMPtr<nsIContentViewer> cv;
   shell->GetContentViewer(getter_AddRefs(cv));
 
   if (!cv)
     return nsnull;
 
-  nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(cv));
-  if (!docv)
-    return nsnull;
-
-  nsCOMPtr<nsIDocument> doc;
-  docv->GetDocument(getter_AddRefs(doc));
+  nsIDocument* doc = cv->GetDocument();
   if (!doc)
     return nsnull;
 
   nsIDOMNode* node = nsnull;
-  CallQueryInterface(doc.get(), &node);
+  CallQueryInterface(doc, &node);
   return node;
 }
 
 PRBool
 nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID)
 {
   nsIAtom *idAttribute = aContent->GetIDAttributeName();
   return idAttribute ? aContent->GetAttr(kNameSpaceID_None, idAttribute, aID) : PR_FALSE;
--- a/accessible/src/base/nsCoreUtils.h
+++ b/accessible/src/base/nsCoreUtils.h
@@ -459,10 +459,137 @@ public:
    *
    * @param aNode    [in] DOM node containing the menupopup element as a child
    * @param aIsAnon  [in] specifies whether popup should be searched inside of
    *                  anonymous or explicit content
    */
   static void GeneratePopupTree(nsIDOMNode *aNode, PRBool aIsAnon = PR_FALSE);
 };
 
+////////////////////////////////////////////////////////////////////////////////
+// nsRunnable helpers
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Use NS_DECL_RUNNABLEMETHOD_ macros to declare a runnable class for the given
+ * method of the given class. There are three macros:
+ *  NS_DECL_RUNNABLEMETHOD(Class, Method)
+ *  NS_DECL_RUNNABLEMETHOD_ARG1(Class, Method, Arg1Type)
+ *  NS_DECL_RUNNABLEMETHOD_ARG2(Class, Method, Arg1Type, Arg2Type)
+ * Note Arg1Type and Arg2Type must be types which keeps the objects alive.
+ *
+ * Use NS_DISPATCH_RUNNABLEMETHOD_ macros to create an instance of declared
+ * runnable class and dispatch it to main thread. Availabe macros are:
+ *  NS_DISPATCH_RUNNABLEMETHOD(Method, Object)
+ *  NS_DISPATCH_RUNNABLEMETHOD_ARG1(Method, Object, Arg1)
+ *  NS_DISPATCH_RUNNABLEMETHOD_ARG2(Method, Object, Arg1, Arg2)
+ */
+
+#define NS_DECL_RUNNABLEMETHOD_HELPER(ClassType, Method)                       \
+  void Revoke()                                                                \
+  {                                                                            \
+    NS_IF_RELEASE(mObj);                                                       \
+  }                                                                            \
+                                                                               \
+protected:                                                                     \
+  virtual ~nsRunnableMethod_##Method()                                         \
+  {                                                                            \
+    NS_IF_RELEASE(mObj);                                                       \
+  }                                                                            \
+                                                                               \
+private:                                                                       \
+  ClassType *mObj;                                                             \
+
+
+#define NS_DECL_RUNNABLEMETHOD(ClassType, Method)                              \
+class nsRunnableMethod_##Method : public nsRunnable                            \
+{                                                                              \
+public:                                                                        \
+  nsRunnableMethod_##Method(ClassType *aObj) : mObj(aObj)                      \
+  {                                                                            \
+    NS_IF_ADDREF(mObj);                                                        \
+  }                                                                            \
+                                                                               \
+  NS_IMETHODIMP Run()                                                          \
+  {                                                                            \
+    if (!mObj)                                                                 \
+      return NS_OK;                                                            \
+    (mObj-> Method)();                                                         \
+    return NS_OK;                                                              \
+  }                                                                            \
+                                                                               \
+  NS_DECL_RUNNABLEMETHOD_HELPER(ClassType, Method)                             \
+                                                                               \
+};
+
+#define NS_DECL_RUNNABLEMETHOD_ARG1(ClassType, Method, Arg1Type)               \
+class nsRunnableMethod_##Method : public nsRunnable                            \
+{                                                                              \
+public:                                                                        \
+  nsRunnableMethod_##Method(ClassType *aObj, Arg1Type aArg1) :                 \
+    mObj(aObj), mArg1(aArg1)                                                   \
+  {                                                                            \
+    NS_IF_ADDREF(mObj);                                                        \
+  }                                                                            \
+                                                                               \
+  NS_IMETHODIMP Run()                                                          \
+  {                                                                            \
+    if (!mObj)                                                                 \
+      return NS_OK;                                                            \
+    (mObj-> Method)(mArg1);                                                    \
+    return NS_OK;                                                              \
+  }                                                                            \
+                                                                               \
+  NS_DECL_RUNNABLEMETHOD_HELPER(ClassType, Method)                             \
+  Arg1Type mArg1;                                                              \
+};
+
+#define NS_DECL_RUNNABLEMETHOD_ARG2(ClassType, Method, Arg1Type, Arg2Type)     \
+class nsRunnableMethod_##Method : public nsRunnable                            \
+{                                                                              \
+public:                                                                        \
+                                                                               \
+  nsRunnableMethod_##Method(ClassType *aObj,                                   \
+                            Arg1Type aArg1, Arg2Type aArg2) :                  \
+    mObj(aObj), mArg1(aArg1), mArg2(aArg2)                                     \
+  {                                                                            \
+    NS_IF_ADDREF(mObj);                                                        \
+  }                                                                            \
+                                                                               \
+  NS_IMETHODIMP Run()                                                          \
+  {                                                                            \
+    if (!mObj)                                                                 \
+      return NS_OK;                                                            \
+    (mObj-> Method)(mArg1, mArg2);                                             \
+    return NS_OK;                                                              \
+  }                                                                            \
+                                                                               \
+  NS_DECL_RUNNABLEMETHOD_HELPER(ClassType, Method)                             \
+  Arg1Type mArg1;                                                              \
+  Arg2Type mArg2;                                                              \
+};
+
+#define NS_DISPATCH_RUNNABLEMETHOD(Method, Obj)                                \
+{                                                                              \
+  nsCOMPtr<nsIRunnable> runnable =                                             \
+    new nsRunnableMethod_##Method(Obj);                                        \
+  if (runnable)                                                                \
+    NS_DispatchToMainThread(runnable);                                         \
+}
+
+#define NS_DISPATCH_RUNNABLEMETHOD_ARG1(Method, Obj, Arg1)                     \
+{                                                                              \
+  nsCOMPtr<nsIRunnable> runnable =                                             \
+    new nsRunnableMethod_##Method(Obj, Arg1);                                  \
+  if (runnable)                                                                \
+    NS_DispatchToMainThread(runnable);                                         \
+}
+
+#define NS_DISPATCH_RUNNABLEMETHOD_ARG2(Method, Obj, Arg1, Arg2)               \
+{                                                                              \
+  nsCOMPtr<nsIRunnable> runnable =                                             \
+    new nsRunnableMethod_##Method(Obj, Arg1, Arg2);                            \
+  if (runnable)                                                                \
+    NS_DispatchToMainThread(runnable);                                         \
+}
+
 #endif
 
--- a/accessible/src/base/nsFormControlAccessible.cpp
+++ b/accessible/src/base/nsFormControlAccessible.cpp
@@ -69,23 +69,24 @@ NS_IMETHODIMP nsRadioButtonAccessible::G
 {
   if (aIndex == eAction_Click) {
     aName.AssignLiteral("select"); 
     return NS_OK;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
-/** Our only action is to click */
-NS_IMETHODIMP nsRadioButtonAccessible::DoAction(PRUint8 aIndex)
+NS_IMETHODIMP
+nsRadioButtonAccessible::DoAction(PRUint8 aIndex)
 {
-  if (aIndex == eAction_Click) {
-    return DoCommand();
-  }
-  return NS_ERROR_INVALID_ARG;
+  if (aIndex != eAction_Click)
+    return NS_ERROR_INVALID_ARG;
+
+  DoCommand();
+  return NS_OK;
 }
 
 nsresult
 nsRadioButtonAccessible::GetRoleInternal(PRUint32 *aRole)
 {
   *aRole = nsIAccessibleRole::ROLE_RADIOBUTTON;
   return NS_OK;
 }
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -537,18 +537,22 @@ nsRootAccessible::FireAccessibleFocusEve
 
   FireDelayedAccessibleEvent(nsIAccessibleEvent::EVENT_FOCUS,
                              finalFocusNode, nsAccEvent::eRemoveDupes,
                              aIsAsynch, aIsFromUserInput);
 
   return PR_TRUE;
 }
 
-void nsRootAccessible::FireCurrentFocusEvent()
+void
+nsRootAccessible::FireCurrentFocusEvent()
 {
+  if (IsDefunct())
+    return;
+
   nsCOMPtr<nsIDOMNode> focusedNode = GetCurrentFocus();
   if (!focusedNode) {
     return; // No current focus
   }
 
   // Simulate a focus event so that we can reuse code that fires focus for container children like treeitems
   nsCOMPtr<nsIDOMDocumentEvent> docEvent = do_QueryInterface(mDocument);
   if (docEvent) {
@@ -767,23 +771,17 @@ nsresult nsRootAccessible::HandleEventWi
   }
   else
 #endif
   if (eventType.EqualsLiteral("focus")) {
     if (aTargetNode == mDOMNode && mDOMNode != gLastFocusedNode) {
       // Got focus event for the window, we will make sure that an accessible
       // focus event for initial focus is fired. We do this on a short timer
       // because the initial focus may not have been set yet.
-      if (!mFireFocusTimer) {
-        mFireFocusTimer = do_CreateInstance("@mozilla.org/timer;1");
-      }
-      if (mFireFocusTimer) {
-        mFireFocusTimer->InitWithFuncCallback(FireFocusCallback, this,
-                                              0, nsITimer::TYPE_ONE_SHOT);
-      }
+      NS_DISPATCH_RUNNABLEMETHOD(FireCurrentFocusEvent, this)
     }
 
     // Keep a reference to the target node. We might want to change
     // it to the individual radio button or selected item, and send
     // the focus event to that.
     nsCOMPtr<nsIDOMNode> focusedItem(aTargetNode);
 
     if (!treeItemAccessible) {
@@ -929,23 +927,16 @@ void nsRootAccessible::GetTargetNode(nsI
                                                         aTargetNode);
     if (NS_SUCCEEDED(rv) && *aTargetNode)
       return;
   }
 
   NS_ADDREF(*aTargetNode = eventTarget);
 }
 
-void nsRootAccessible::FireFocusCallback(nsITimer *aTimer, void *aClosure)
-{
-  nsRootAccessible *rootAccessible = static_cast<nsRootAccessible*>(aClosure);
-  NS_ASSERTION(rootAccessible, "How did we get here without a root accessible?");
-  rootAccessible->FireCurrentFocusEvent();
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode
 
 nsresult
 nsRootAccessible::Init()
 {
   nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
   NS_ENSURE_STATE(root);
@@ -965,21 +956,16 @@ nsRootAccessible::Shutdown()
 
   nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
   NS_ENSURE_STATE(root);
 
   root->RemoveRootAccessible(this);
 
   mCurrentARIAMenubar = nsnull;
 
-  if (mFireFocusTimer) {
-    mFireFocusTimer->Cancel();
-    mFireFocusTimer = nsnull;
-  }
-
   return nsDocAccessibleWrap::Shutdown();
 }
 
 // nsRootAccessible protected member
 already_AddRefed<nsIDocShellTreeItem>
 nsRootAccessible::GetContentDocShell(nsIDocShellTreeItem *aStart)
 {
   if (!aStart) {
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -46,17 +46,16 @@
 #include "nsXULTreeAccessible.h"
 #endif
 
 #include "nsHashtable.h"
 #include "nsCaretAccessible.h"
 #include "nsIDocument.h"
 #include "nsIDOMFocusListener.h"
 #include "nsIDOMFormListener.h"
-#include "nsITimer.h"
 
 #define NS_ROOTACCESSIBLE_IMPL_CID                      \
 {  /* eaba2cf0-21b1-4e2b-b711-d3a89dcd5e1a */           \
   0xeaba2cf0,                                           \
   0x21b1,                                               \
   0x4e2b,                                               \
   { 0xb7, 0x11, 0xd3, 0xa8, 0x9d, 0xcd, 0x5e, 0x1a }    \
 }
@@ -117,21 +116,19 @@ public:
     /**
       * Fire an accessible focus event for the current focused node,
       * if there is a focus.
       */
     void FireCurrentFocusEvent();
 
     nsCaretAccessible *GetCaretAccessible();
 
-  private:
-    nsCOMPtr<nsITimer> mFireFocusTimer;
-    static void FireFocusCallback(nsITimer *aTimer, void *aClosure);
-    
-  protected:
+protected:
+  NS_DECL_RUNNABLEMETHOD(nsRootAccessible, FireCurrentFocusEvent)
+
     nsresult AddEventListeners();
     nsresult RemoveEventListeners();
     nsresult HandleEventWithTarget(nsIDOMEvent* aEvent,
                                    nsIDOMNode* aTargetNode);
     static void GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNode);
     void TryFireEarlyLoadEvent(nsIDOMNode *aDocNode);
     void GetChromeEventHandler(nsIDOMEventTarget **aChromeTarget);
 
--- a/accessible/src/html/nsHTMLFormControlAccessible.cpp
+++ b/accessible/src/html/nsHTMLFormControlAccessible.cpp
@@ -93,22 +93,24 @@ NS_IMETHODIMP nsHTMLCheckboxAccessible::
     else
       aName.AssignLiteral("check"); 
 
     return NS_OK;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
-NS_IMETHODIMP nsHTMLCheckboxAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+nsHTMLCheckboxAccessible::DoAction(PRUint8 aIndex)
 {
-  if (index == 0) {   // 0 is the magic value for default action
-    return DoCommand();
-  }
-  return NS_ERROR_INVALID_ARG;
+  if (aIndex != 0)
+    return NS_ERROR_INVALID_ARG;
+
+  DoCommand();
+  return NS_OK;
 }
 
 nsresult
 nsHTMLCheckboxAccessible::GetStateInternal(PRUint32 *aState,
                                            PRUint32 *aExtraState)
 {
   nsresult rv = nsFormControlAccessible::GetStateInternal(aState, aExtraState);
   NS_ENSURE_A11Y_SUCCESS(rv, rv);
@@ -251,22 +253,24 @@ NS_IMETHODIMP nsHTMLButtonAccessible::Ge
 {
   if (aIndex == eAction_Click) {
     aName.AssignLiteral("press"); 
     return NS_OK;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
-NS_IMETHODIMP nsHTMLButtonAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+nsHTMLButtonAccessible::DoAction(PRUint8 aIndex)
 {
-  if (index == eAction_Click) {
-    return DoCommand();
-  }
-  return NS_ERROR_INVALID_ARG;
+  if (aIndex != eAction_Click)
+    return NS_ERROR_INVALID_ARG;
+
+  DoCommand();
+  return NS_OK;
 }
 
 nsresult
 nsHTMLButtonAccessible::GetStateInternal(PRUint32 *aState,
                                          PRUint32 *aExtraState)
 {
   nsresult rv = nsHyperTextAccessibleWrap::GetStateInternal(aState,
                                                             aExtraState);
@@ -344,22 +348,24 @@ NS_IMETHODIMP nsHTML4ButtonAccessible::G
 {
   if (aIndex == eAction_Click) {
     aName.AssignLiteral("press"); 
     return NS_OK;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
-NS_IMETHODIMP nsHTML4ButtonAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+nsHTML4ButtonAccessible::DoAction(PRUint8 aIndex)
 {
-  if (index == 0) {
-    return DoCommand();
-  }
-  return NS_ERROR_INVALID_ARG;
+  if (aIndex != 0)
+    return NS_ERROR_INVALID_ARG;
+
+  DoCommand();
+  return NS_OK;
 }
 
 nsresult
 nsHTML4ButtonAccessible::GetRoleInternal(PRUint32 *aRole)
 {
   *aRole = nsIAccessibleRole::ROLE_PUSHBUTTON;
   return NS_OK;
 }
--- a/accessible/src/html/nsHTMLLinkAccessible.cpp
+++ b/accessible/src/html/nsHTMLLinkAccessible.cpp
@@ -155,18 +155,18 @@ nsHTMLLinkAccessible::DoAction(PRUint8 a
 
   // Action 0 (default action): Jump to link
   if (aIndex != eAction_Jump)
     return NS_ERROR_INVALID_ARG;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
-  return DoCommand(content);
+  DoCommand();
+  return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibleHyperLink
 
 NS_IMETHODIMP
 nsHTMLLinkAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
 {
--- a/accessible/src/xforms/nsXFormsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsAccessible.cpp
@@ -621,17 +621,18 @@ nsXFormsSelectableItemAccessible::GetNum
 }
 
 NS_IMETHODIMP
 nsXFormsSelectableItemAccessible::DoAction(PRUint8 aIndex)
 {
   if (aIndex != eAction_Click)
     return NS_ERROR_INVALID_ARG;
 
-  return DoCommand();
+  DoCommand();
+  return NS_OK;
 }
 
 PRBool
 nsXFormsSelectableItemAccessible::IsItemSelected()
 {
   nsresult rv;
 
   nsCOMPtr<nsINode> parent = do_QueryInterface(mDOMNode);
--- a/accessible/src/xforms/nsXFormsFormControlsAccessible.cpp
+++ b/accessible/src/xforms/nsXFormsFormControlsAccessible.cpp
@@ -125,20 +125,21 @@ nsXFormsTriggerAccessible::GetActionName
     return NS_OK;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
 NS_IMETHODIMP
 nsXFormsTriggerAccessible::DoAction(PRUint8 aIndex)
 {
-  if (aIndex == eAction_Click)
-    return DoCommand();
+  if (aIndex != eAction_Click)
+    return NS_ERROR_INVALID_ARG;
 
-  return NS_ERROR_INVALID_ARG;
+  DoCommand();
+  return NS_OK;
 }
 
 // nsXFormsInputAccessible
 
 nsXFormsInputAccessible::
   nsXFormsInputAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell):
   nsXFormsEditableAccessible(aNode, aShell)
 {
@@ -241,17 +242,18 @@ nsXFormsInputBooleanAccessible::GetActio
 }
 
 NS_IMETHODIMP
 nsXFormsInputBooleanAccessible::DoAction(PRUint8 aIndex)
 {
   if (aIndex != eAction_Click)
     return NS_ERROR_INVALID_ARG;
 
-  return DoCommand();
+  DoCommand();
+  return NS_OK;
 }
 
 // nsXFormsInputDateAccessible
 
 nsXFormsInputDateAccessible::
   nsXFormsInputDateAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell):
   nsXFormsContainerAccessible(aNode, aShell)
 {
--- a/accessible/src/xul/nsXULFormControlAccessible.cpp
+++ b/accessible/src/xul/nsXULFormControlAccessible.cpp
@@ -91,20 +91,21 @@ nsXULButtonAccessible::GetActionName(PRU
     return NS_OK;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
 NS_IMETHODIMP
 nsXULButtonAccessible::DoAction(PRUint8 aIndex)
 {
-  if (aIndex == 0)
-    return DoCommand();
+  if (aIndex != 0)
+    return NS_ERROR_INVALID_ARG;
 
-  return NS_ERROR_INVALID_ARG;
+  DoCommand();
+  return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULButtonAccessible: nsAccessNode
 
 nsresult
 nsXULButtonAccessible::Init()
 {
@@ -414,22 +415,24 @@ NS_IMETHODIMP nsXULCheckboxAccessible::G
     return NS_OK;
   }
   return NS_ERROR_INVALID_ARG;
 }
 
 /**
   * Tell the checkbox to do its only action -- check( or uncheck) itself
   */
-NS_IMETHODIMP nsXULCheckboxAccessible::DoAction(PRUint8 index)
+NS_IMETHODIMP
+nsXULCheckboxAccessible::DoAction(PRUint8 aIndex)
 {
-  if (index == eAction_Click) {
-   return DoCommand();
-  }
-  return NS_ERROR_INVALID_ARG;
+  if (aIndex != eAction_Click)
+    return NS_ERROR_INVALID_ARG;
+
+  DoCommand();
+  return NS_OK;
 }
 
 /**
   * Possible states: focused, focusable, unavailable(disabled), checked
   */
 nsresult
 nsXULCheckboxAccessible::GetStateInternal(PRUint32 *aState,
                                           PRUint32 *aExtraState)
--- a/accessible/src/xul/nsXULListboxAccessible.cpp
+++ b/accessible/src/xul/nsXULListboxAccessible.cpp
@@ -142,17 +142,18 @@ nsXULColumnItemAccessible::GetActionName
 }
 
 NS_IMETHODIMP
 nsXULColumnItemAccessible::DoAction(PRUint8 aIndex)
 {
   if (aIndex != eAction_Click)
     return NS_ERROR_INVALID_ARG;
 
-  return DoCommand();
+  DoCommand();
+  return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULListboxAccessible
 ////////////////////////////////////////////////////////////////////////////////
 
 nsXULListboxAccessible::
   nsXULListboxAccessible(nsIDOMNode* aDOMNode, nsIWeakReference* aShell) :
--- a/accessible/src/xul/nsXULSliderAccessible.cpp
+++ b/accessible/src/xul/nsXULSliderAccessible.cpp
@@ -115,17 +115,18 @@ nsXULSliderAccessible::GetActionName(PRU
 NS_IMETHODIMP
 nsXULSliderAccessible::DoAction(PRUint8 aIndex)
 {
   NS_ENSURE_ARG(aIndex == 0);
 
   nsCOMPtr<nsIContent> sliderContent(GetSliderNode());
   NS_ENSURE_STATE(sliderContent);
 
-  return DoCommand(sliderContent);
+  DoCommand(sliderContent);
+  return NS_OK;
 }
 
 // nsIAccessibleValue
 
 NS_IMETHODIMP
 nsXULSliderAccessible::GetMaximumValue(double *aValue)
 {
   nsresult rv = nsAccessibleWrap::GetMaximumValue(aValue);
--- a/accessible/src/xul/nsXULTextAccessible.cpp
+++ b/accessible/src/xul/nsXULTextAccessible.cpp
@@ -228,18 +228,18 @@ NS_IMETHODIMP
 nsXULLinkAccessible::DoAction(PRUint8 aIndex)
 {
   if (aIndex != eAction_Jump)
     return NS_ERROR_INVALID_ARG;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
-  return DoCommand(content);
+  DoCommand();
+  return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULLinkAccessible. nsIAccessibleHyperLink
 
 NS_IMETHODIMP
 nsXULLinkAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
 {
--- a/accessible/src/xul/nsXULTreeAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeAccessible.cpp
@@ -930,17 +930,18 @@ nsXULTreeItemAccessibleBase::DoAction(PR
 {
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   if (aIndex != eAction_Click &&
       (aIndex != eAction_Expand || !IsExpandable()))
     return NS_ERROR_INVALID_ARG;
 
-  return DoCommand(nsnull, aIndex);
+  DoCommand(nsnull, aIndex);
+  return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeItemAccessibleBase: nsAccessNode implementation
 
 PRBool
 nsXULTreeItemAccessibleBase::IsDefunct()
 {
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -968,23 +968,27 @@ nsXULTreeGridCellAccessible::DoAction(PR
   if (aIndex != eAction_Click)
     return NS_ERROR_INVALID_ARG;
 
   if (IsDefunct())
     return NS_ERROR_FAILURE;
 
   PRBool isCycler = PR_FALSE;
   mColumn->GetCycler(&isCycler);
-  if (isCycler)
-    return DoCommand();
+  if (isCycler) {
+    DoCommand();
+    return NS_OK;
+  }
 
   PRInt16 type;
   mColumn->GetType(&type);
-  if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable())
-    return DoCommand();
+  if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable()) {
+    DoCommand();
+    return NS_OK;
+  }
 
   return NS_ERROR_INVALID_ARG;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsXULTreeGridCellAccessible: nsIAccessibleTableCell implementation
 
 NS_IMETHODIMP
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -72,16 +72,20 @@
       <menuitem id="context-copyemail"
                 label="&copyEmailCmd.label;"
                 accesskey="&copyEmailCmd.accesskey;"
                 oncommand="gContextMenu.copyEmail();"/>
       <menuitem id="context-copylink"
                 label="&copyLinkCmd.label;"
                 accesskey="&copyLinkCmd.accesskey;"
                 oncommand="goDoCommand('cmd_copyLink');"/>
+      <menuitem id="context-copylinktext"
+                label="&copyLinkText2Cmd.label;"
+                accesskey="&copyLinkText2Cmd.accesskey;"
+                oncommand="gContextMenu.copyLinkText();"/>
       <menuseparator id="context-sep-copylink"/>
       <menuitem id="context-media-play"
                 label="&mediaPlay.label;"
                 accesskey="&mediaPlay.accesskey;"
                 oncommand="gContextMenu.mediaCommand('play');"/>
       <menuitem id="context-media-pause"
                 label="&mediaPause.label;"
                 accesskey="&mediaPause.accesskey;"
--- a/browser/base/content/browser-tabPreviews.js
+++ b/browser/base/content/browser-tabPreviews.js
@@ -727,18 +727,20 @@ var allTabs = {
         break;
       case "TabMove":
         let siblingPreview = tab.nextSibling &&
                              this._getPreview(tab.nextSibling);
         if (siblingPreview)
           siblingPreview.parentNode.insertBefore(preview, siblingPreview);
         else
           this.container.lastChild.appendChild(preview);
-        if (this.isOpen && !preview.hidden)
+        if (this.isOpen && !preview.hidden) {
           this._reflow();
+          preview.focus();
+        }
         break;
       case "TabClose":
         this._removePreview(preview);
         break;
       case "keypress":
         this._onKeyPress(event);
         break;
       case "command":
--- a/browser/base/content/browser-tabPreviews.xml
+++ b/browser/base/content/browser-tabPreviews.xml
@@ -79,11 +79,29 @@
         <xul:hbox class="allTabs-favicon-container">
           <xul:image class="allTabs-favicon" xbl:inherits="src=image"/>
         </xul:hbox>
       </xul:stack>
     </content>
     <handlers>
       <handler event="command" action="allTabs.pick(this);"/>
       <handler event="click" button="1" action="gBrowser.removeTab(this._tab);"/>
+
+      <handler event="dragstart"><![CDATA[
+        event.dataTransfer.mozSetDataAt("application/x-moz-node", this._tab, 0);
+      ]]></handler>
+
+      <handler event="dragover"><![CDATA[
+        let tab = event.dataTransfer.mozGetDataAt("application/x-moz-node", 0);
+        if (tab && tab.parentNode == gBrowser.tabContainer)
+          event.preventDefault();
+      ]]></handler>
+
+      <handler event="drop"><![CDATA[
+        let tab = event.dataTransfer.mozGetDataAt("application/x-moz-node", 0);
+        if (tab && tab.parentNode == gBrowser.tabContainer) {
+          let newIndex = Array.indexOf(gBrowser.tabContainer.childNodes, this._tab);
+          gBrowser.moveTabTo(tab, newIndex);
+        }
+      ]]></handler>
     </handlers>
   </binding>
 </bindings>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3334,22 +3334,18 @@ function BrowserCustomizeToolbar()
     // The document might not have been loaded yet, if this is the first time.
     // If it is already loaded, reload it so that the onload initialization code
     // re-runs.
     if (sheetFrame.getAttribute("src") == customizeURL)
       sheetFrame.contentWindow.location.reload()
     else
       sheetFrame.setAttribute("src", customizeURL);
 
-    // XXXmano: there's apparently no better way to get this when the iframe is
-    // hidden
-    var sheetWidth = sheetFrame.style.width.match(/([0-9]+)px/)[1];
     document.getElementById("customizeToolbarSheetPopup")
-            .openPopup(gNavToolbox, "after_start",
-                       (window.innerWidth - sheetWidth) / 2, 0);
+            .openPopup(gNavToolbox, "after_start", 0, 0);
 
     return sheetFrame.contentWindow;
   } else {
     return window.openDialog(customizeURL,
                              "CustomizeToolbar",
                              "chrome,titlebar,toolbar,location,resizable,dependent",
                              gNavToolbox);
   }
@@ -4519,16 +4515,23 @@ nsBrowserAccess.prototype = {
           needToFocusWin = true;
         }
 
         if (!win) {
           // we couldn't find a suitable window, a new one needs to be opened.
           return null;
         }
 
+        if (isExternal && (!aURI || aURI.spec == "about:blank")) {
+          win.BrowserOpenTab(); // this also focuses the location bar
+          win.focus();
+          newWindow = win.content;
+          break;
+        }
+
         let loadInBackground = gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground");
         let referrer = aOpener ? makeURI(aOpener.location.href) : null;
 
         // If this is an external load, we need to load a blank tab first,
         // because loadflags can't be passed to loadOneTab.
         let loadBlankFirst = !aURI || isExternal;
         let tab = win.gBrowser.loadOneTab(loadBlankFirst ? "about:blank" : aURI.spec, {
                                           referrerURI: referrer,
@@ -5271,18 +5274,20 @@ function stylesheetFillPopup(menuPopup) 
 
   for (let i = 0; i < styleSheets.length; ++i) {
     let currentStyleSheet = styleSheets[i];
 
     if (!currentStyleSheet.title)
       continue;
 
     // Skip any stylesheets that don't match the screen media type.
-    let (media = currentStyleSheet.media.mediaText.toLowerCase()) {
-      if (media && (media.indexOf("screen") == -1) && (media.indexOf("all") == -1))
+    if (currentStyleSheet.media.length > 0) {
+      let media = currentStyleSheet.media.mediaText.split(", ");
+      if (media.indexOf("screen") == -1 &&
+          media.indexOf("all") == -1)
         continue;
     }
 
     if (!currentStyleSheet.disabled)
       altStyleSelected = true;
 
     haveAltSheets = true;
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -295,17 +295,19 @@
                        tooltiptext="&closeCmd.label;"
                        style="visibility:hidden"/>
       </stack>
     </panel>
 
     <!-- Bookmarks and history tooltip -->
     <tooltip id="bhTooltip"/>
 
-    <panel id="customizeToolbarSheetPopup" noautohide="true">
+    <panel id="customizeToolbarSheetPopup"
+           noautohide="true"
+           onpopupshown="this.moveTo(this.boxObject.screenX + (window.innerWidth - this.boxObject.width) / 2, this.boxObject.screenY);">
       <iframe id="customizeToolbarSheetIFrame"
               style="&dialog.style;"
               hidden="true"/>
     </panel>
   </popupset>
 
   <toolbox id="navigator-toolbox" class="toolbox-top" mode="icons"
 #ifdef WINCE
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -433,16 +433,18 @@ nsContextMenu.prototype = {
     // nsDocumentViewer.cpp has code to determine whether we're
     // on a link or an image. we really ought to be using that...
 
     // Copy email link depends on whether we're on an email link.
     this.showItem("context-copyemail", this.onMailtoLink);
 
     // Copy link location depends on whether we're on a non-mailto link.
     this.showItem("context-copylink", this.onLink && !this.onMailtoLink);
+    this.showItem("context-copylinktext",
+                  this.onLink && !this.onImage && !this.isTextSelected);
     this.showItem("context-sep-copylink", this.onLink &&
                   (this.onImage || this.onVideo || this.onAudio));
 
 #ifdef CONTEXT_COPY_IMAGE_CONTENTS
     // Copy image contents depends on whether we're on an image.
     this.showItem("context-copyimage-contents", this.onImage);
 #endif
     // Copy image location depends on whether we're on an image.
@@ -1173,16 +1175,24 @@ nsContextMenu.prototype = {
       // Do nothing.
     }
 
     var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
                     getService(Ci.nsIClipboardHelper);
     clipboard.copyString(addresses);
   },
 
+  copyLinkText: function() {
+    let text = this.linkText();
+
+    let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"].
+                    getService(Ci.nsIClipboardHelper);
+    clipboard.copyString(text);
+  },
+
   ///////////////
   // Utilities //
   ///////////////
 
   // Show/hide one item (specified via name or the item element itself).
   showItem: function(aItemOrId, aShow) {
     var item = aItemOrId.constructor == String ?
       document.getElementById(aItemOrId) : aItemOrId;
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1339,17 +1339,18 @@
                                     "notificationbox");
             notificationbox.setAttribute("flex", "1");
             notificationbox.appendChild(b);
             b.setAttribute("flex", "1");
             this.mPanelContainer.appendChild(notificationbox);
 
             b.addEventListener("DOMTitleChanged", this.onTitleChanged, true);
 
-            if (this.mStrip.collapsed)
+            if (this.mStrip.collapsed &&
+                this.mTabs.length - this._removingTabs.length > 1)
               this.setStripVisibilityTo(true);
 
             // wire up a progress listener for the new browser object.
             var position = this.mTabContainer.childNodes.length-1;
             var tabListener = this.mTabProgressListener(t, b, blank);
             const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
                                      .createInstance(Components.interfaces.nsIWebProgress);
             filter.addProgressListener(tabListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -96,16 +96,17 @@ include $(topsrcdir)/config/rules.mk
                  browser_bug441778.js \
                  browser_bug455852.js \
                  browser_bug462673.js \
                  browser_bug481560.js \
                  browser_bug484315.js \
                  browser_bug477014.js \
                  browser_bug495058.js \
                  browser_bug517902.js \
+                 browser_bug520538.js \
                  browser_bug521216.js \
                  browser_bug537474.js \
                  browser_discovery.js \
                  browser_tabfocus.js \
                  discovery.html \
                  moz.png \
                  test_bug435035.html \
                  test_bug462673.html \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/browser_bug520538.js
@@ -0,0 +1,15 @@
+function test() {
+  var tabs = gBrowser.tabContainer.childElementCount;
+  content.focus();
+  browserDOMWindow.openURI(makeURI("about:blank"),
+                           null,
+                           Ci.nsIBrowserDOMWindow.OPEN_NEWTAB,
+                           Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
+  is(gBrowser.tabContainer.childElementCount, tabs + 1,
+     "'-new-tab about:blank' opens a new tab");
+  is(gBrowser.selectedTab, gBrowser.tabContainer.childNodes[tabs],
+     "'-new-tab about:blank' selects the new tab");
+  is(document.activeElement, gURLBar.inputField,
+     "'-new-tab about:blank' focuses the location bar");
+  gBrowser.removeCurrentTab();
+}
--- a/browser/base/content/test/page_style_sample.html
+++ b/browser/base/content/test/page_style_sample.html
@@ -18,14 +18,19 @@
     <link data-state="0" href="404.css" title="8" rel="alternate">
     <link data-state="1" href="404.css" title="9" rel="alternate STYLEsheet">
     <link data-state="1" href="404.css" title="10" rel="alternate stylesheet" media="">
     <link data-state="1" href="404.css" title="11" rel="alternate stylesheet" media="all">
     <link data-state="1" href="404.css" title="12" rel="alternate stylesheet" media="ALL ">
     <link data-state="1" href="404.css" title="13" rel="alternate stylesheet" media="screen">
     <link data-state="1" href="404.css" title="14" rel="alternate stylesheet" media=" Screen">
     <link data-state="1" href="404.css" title="15" rel="alternate stylesheet" media="screen foo">
-    <link data-state="1" href="404.css" title="16" rel="alternate stylesheet" media="all  screen">
-    <link data-state="0-todo" href="404.css" title="17" rel="alternate stylesheet" media="allscreen">
-    <link data-state="0-todo" href="404.css" title="18" rel="alternate stylesheet" media="_all">
+    <link data-state="1" href="404.css" title="16" rel="alternate stylesheet" media="all screen">
+    <link data-state="1" href="404.css" title="17" rel="alternate stylesheet" media="foo bar">
+    <link data-state="1" href="404.css" title="18" rel="alternate stylesheet" media="all,screen">
+    <link data-state="1" href="404.css" title="19" rel="alternate stylesheet" media="all, screen">
+    <link data-state="1" href="404.css" title="20" rel="alternate stylesheet" media="all  screen">
+    <link data-state="0" href="404.css" title="21" rel="alternate stylesheet" media="foo">
+    <link data-state="0" href="404.css" title="22" rel="alternate stylesheet" media="allscreen">
+    <link data-state="0" href="404.css" title="23" rel="alternate stylesheet" media="_all">
   </head>
   <body></body>
 </html>
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -168,24 +168,26 @@ function runTest(testNum) {
     case 3:
         // Context menu for text link
         checkContextMenu(["context-openlink",      true,
                           "context-openlinkintab", true,
                           "---",                   null,
                           "context-bookmarklink",  true,
                           "context-savelink",      true,
                           "context-sendlink",      true,
-                          "context-copylink",      true]);
+                          "context-copylink",      true,
+                          "context-copylinktext",  true]);
         closeContextMenu();
         openContextMenuFor(mailto); // Invoke context menu for next test.
         break;
 
     case 4:
         // Context menu for text mailto-link
-        checkContextMenu(["context-copyemail", true]);
+        checkContextMenu(["context-copyemail",    true,
+                          "context-copylinktext", true]);
         closeContextMenu();
         openContextMenuFor(input); // Invoke context menu for next test.
         break;
 
     case 5:
         // Context menu for text input field
         checkContextMenu(["context-undo",        false,
                           "---",                 null,
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -55,25 +55,29 @@
         this.timeout = this._prefs.getIntPref("delay");
 
         this._urlTooltip = document.getElementById("urlTooltip");
 
         this.inputField.controllers.insertControllerAt(0, this._copyCutController);
         this.inputField.addEventListener("mousedown", this, false);
         this.inputField.addEventListener("mousemove", this, false);
         this.inputField.addEventListener("mouseout", this, false);
+        this.inputField.addEventListener("overflow", this, false);
+        this.inputField.addEventListener("underflow", this, false);
       ]]></constructor>
 
       <destructor><![CDATA[
         this._prefs.removeObserver("", this);
         this._prefs = null;
         this.inputField.controllers.removeController(this._copyCutController);
         this.inputField.removeEventListener("mousedown", this, false);
         this.inputField.removeEventListener("mousemove", this, false);
         this.inputField.removeEventListener("mouseout", this, false);
+        this.inputField.removeEventListener("overflow", this, false);
+        this.inputField.removeEventListener("underflow", this, false);
       ]]></destructor>
 
       <method name="handleRevert">
         <body><![CDATA[
           var isScrolling = this.popupOpen;
 
           gBrowser.userTypedValue = null;
 
@@ -206,20 +210,22 @@
           }
 
           var postData = {};
           url = getShortcutOrURI(url, postData);
 
           return [url, postData.value];
         ]]></body>
       </method>
+
+      <field name="_contentIsCropped">false</field>
 
       <method name="_initURLTooltip">
         <body><![CDATA[
-          if (this.focused || this.value == "")
+          if (this.focused || !this._contentIsCropped)
             return;
           if (this._tooltipTimer)
             clearTimeout(this._tooltipTimer);
           this._tooltipTimer = setTimeout(function (self) {
             self._tooltipTimer = 0;
             var label = self._urlTooltip.firstChild;
             label.value = self.value;
             var bO = self.boxObject;
@@ -373,16 +379,23 @@
               }
               break;
             case "mousemove":
               this._initURLTooltip();
               break;
             case "mouseout":
               this._hideURLTooltip();
               break;
+            case "overflow":
+              this._contentIsCropped = true;
+              break;
+            case "underflow":
+              this._contentIsCropped = false;
+              this._hideURLTooltip();
+              break;
           }
         ]]></body>
       </method>
 
       <property name="textValue"
                 onget="return this.value;">
         <setter>
           <![CDATA[
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -65,24 +65,27 @@ struct RedirEntry {
   URI_SAFE_FOR_UNTRUSTED_CONTENT.  Also note, however, that adding
   URI_SAFE_FOR_UNTRUSTED_CONTENT will allow random web sites to link to that
   URI.  Perhaps we should separate the two concepts out...
  */
 static RedirEntry kRedirMap[] = {
 #ifdef MOZ_SAFE_BROWSING
   { "blocked", "chrome://browser/content/safebrowsing/blockedSite.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
-    nsIAboutModule::ALLOW_SCRIPT },
+    nsIAboutModule::ALLOW_SCRIPT |
+    nsIAboutModule::HIDE_FROM_ABOUTABOUT },
 #endif
   { "certerror", "chrome://browser/content/certerror/aboutCertError.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
-    nsIAboutModule::ALLOW_SCRIPT },
+    nsIAboutModule::ALLOW_SCRIPT |
+    nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "feeds", "chrome://browser/content/feeds/subscribe.xhtml",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
-    nsIAboutModule::ALLOW_SCRIPT },
+    nsIAboutModule::ALLOW_SCRIPT |
+    nsIAboutModule::HIDE_FROM_ABOUTABOUT },
   { "privatebrowsing", "chrome://browser/content/aboutPrivateBrowsing.xhtml",
     nsIAboutModule::ALLOW_SCRIPT },
   { "rights",
 #ifdef MOZ_OFFICIAL_BRANDING
     "chrome://global/content/aboutRights.xhtml",
 #else
     "chrome://global/content/aboutRights-unbranded.xhtml",
 #endif
--- a/browser/components/dirprovider/DirectoryProvider.cpp
+++ b/browser/components/dirprovider/DirectoryProvider.cpp
@@ -94,25 +94,16 @@ DirectoryProvider::GetFile(const char *a
     rv = NS_GetSpecialDirectory(NS_APP_DEFAULTS_50_DIR,
                                 getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
 
     file->AppendNative(NS_LITERAL_CSTRING("existing-profile-defaults.js"));
     file.swap(*aResult);
     return NS_OK;
   }
-  else if (!strcmp(aKey, NS_APP_MICROSUMMARY_DIR)) {
-    rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
-                                getter_AddRefs(file));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    file->AppendNative(NS_LITERAL_CSTRING("microsummary-generators"));
-    file.swap(*aResult);
-    return NS_OK;
-  }
   else if (!strcmp(aKey, NS_APP_USER_MICROSUMMARY_DIR)) {
     rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
                                 getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
 
     file->AppendNative(NS_LITERAL_CSTRING("microsummary-generators"));
     file.swap(*aResult);
     return NS_OK;
--- a/browser/components/dirprovider/nsBrowserDirectoryServiceDefs.h
+++ b/browser/components/dirprovider/nsBrowserDirectoryServiceDefs.h
@@ -47,17 +47,16 @@
 // General application properties are defined in nsAppDirectoryServiceDefs.h.
 //
 //=============================================================================
 
 // ----------------------------------------------------------------------------
 // Files and directories that exist on a per-browser basis.
 // ----------------------------------------------------------------------------
 
-#define NS_APP_MICROSUMMARY_DIR                 "MicsumGens"
 #define NS_APP_EXISTING_PREF_OVERRIDE           "ExistingPrefOverride"
 
 // ----------------------------------------------------------------------------
 // Files and directories that exist on a per-profile basis.
 // ----------------------------------------------------------------------------
 
 #define NS_APP_USER_MICROSUMMARY_DIR            "UsrMicsumGens"
          
--- a/browser/components/dirprovider/tests/unit/test_keys.js
+++ b/browser/components/dirprovider/tests/unit/test_keys.js
@@ -48,24 +48,16 @@ function test_usr_micsum() {
 
   let tfile = writeTestFile(tmdir, "usrmicsum");
   do_check_true(tfile.exists());
 
   mdir.append(tfile.leafName);
   do_check_true(mdir.exists());
 }
 
-function test_app_micsum() {
-  let mdir = gDirSvc.get("XCurProcD", Ci.nsIFile);
-  mdir.append("microsummary-generators");
-
-  let tmdir = gDirSvc.get("MicsumGens", Ci.nsIFile);
-  do_check_true(tmdir.equals(mdir));
-}
-
 function test_bookmarkhtml() {
   let bmarks = gProfD.clone();
   bmarks.append("bookmarks.html");
 
   let tbmarks = gDirSvc.get("BMarks", Ci.nsIFile);
   do_check_true(bmarks.equals(tbmarks));
 }
 
@@ -74,17 +66,16 @@ function test_prefoverride() {
   dir.append("existing-profile-defaults.js");
 
   let tdir = gDirSvc.get("ExistingPrefOverride", Ci.nsIFile);
   do_check_true(dir.equals(tdir));
 }
 
 function run_test() {
   [test_usr_micsum,
-   test_app_micsum,
    test_bookmarkhtml,
    test_prefoverride
   ].forEach(function(f) {
     do_test_pending();
     print("Running test: " + f.name);
     f();
     do_test_finished();
   });
--- a/browser/components/feeds/src/WebContentConverter.js
+++ b/browser/components/feeds/src/WebContentConverter.js
@@ -396,16 +396,28 @@ WebContentConverterRegistrar.prototype =
   },
 
   /**
    * See nsIWebContentHandlerRegistrar
    */
   registerProtocolHandler: 
   function WCCR_registerProtocolHandler(aProtocol, aURIString, aTitle, aContentWindow) {
     LOG("registerProtocolHandler(" + aProtocol + "," + aURIString + "," + aTitle + ")");
+
+    if (Cc["@mozilla.org/privatebrowsing;1"].
+        getService(Ci.nsIPrivateBrowsingService).
+        privateBrowsingEnabled) {
+      // Inside the private browsing mode, we don't want to alert the user to save
+      // a protocol handler.  We log it to the error console so that web developers
+      // would have some way to tell what's going wrong.
+      Cc["@mozilla.org/consoleservice;1"].
+      getService(Ci.nsIConsoleService).
+      logStringMessage("Web page denied access to register a protocol handler inside private browsing mode");
+      return;
+    }
     
     // First, check to make sure this isn't already handled internally (we don't
     // want to let them take over, say "chrome").
     var ios = Cc["@mozilla.org/network/io-service;1"].
               getService(Ci.nsIIOService);
     var handler = ios.getProtocolHandler(aProtocol);
     if (!(handler instanceof Ci.nsIExternalProtocolHandler)) {
       // This is handled internally, so we don't want them to register
--- a/browser/components/microsummaries/src/nsMicrosummaryService.js
+++ b/browser/components/microsummaries/src/nsMicrosummaryService.js
@@ -261,25 +261,20 @@ MicrosummaryService.prototype = {
                   Date.now() + (microsummary.updateInterval || this._updateInterval));
   },
 
   /**
    * Load local generators into the cache.
    * 
    */
   _cacheLocalGenerators: function MSS__cacheLocalGenerators() {
-    // Load generators from the application directory.
-    var appDir = this._dirs.get("MicsumGens", Ci.nsIFile);
-    if (appDir.exists())
-      this._cacheLocalGeneratorDir(appDir);
-
     // Load generators from the user's profile.
-    var profileDir = this._dirs.get("UsrMicsumGens", Ci.nsIFile);
-    if (profileDir.exists())
-      this._cacheLocalGeneratorDir(profileDir);
+    var msDir = this._dirs.get("UsrMicsumGens", Ci.nsIFile);
+    if (msDir.exists())
+      this._cacheLocalGeneratorDir(msDir);
   },
 
   /**
    * Load local generators from a directory into the cache.
    *
    * @param   dir
    *          nsIFile object pointing to directory containing generator files
    * 
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -44,17 +44,16 @@
 const Ci = Components.interfaces;
 const Cc = Components.classes;
 const Cr = Components.results;
 const Cu = Components.utils;
 
 const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource:///modules/distribution.js");
 
 const PREF_EM_NEW_ADDONS_LIST = "extensions.newAddons";
 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.
 const BOOKMARKS_BACKUP_IDLE_TIME = 15 * 60;
@@ -85,16 +84,17 @@ function BrowserGlue() {
                                      "@mozilla.org/intl/stringbundle;1",
                                      "nsIStringBundleService");
 
   XPCOMUtils.defineLazyServiceGetter(this, "_idleService",
                                      "@mozilla.org/widget/idleservice;1",
                                      "nsIIdleService");
 
   XPCOMUtils.defineLazyGetter(this, "_distributionCustomizer", function() {
+                                Cu.import("resource:///modules/distribution.js");
                                 return new DistributionCustomizer();
                               });
 
   XPCOMUtils.defineLazyGetter(this, "_sanitizer",
     function() {
       let sanitizerScope = {};
       Cc["@mozilla.org/moz/jssubscript-loader;1"].
       getService(Ci.mozIJSSubScriptLoader).
@@ -1069,47 +1069,47 @@ BrowserGlue.prototype = {
 
 #ifndef XP_WIN
 #define BROKEN_WM_Z_ORDER
 #endif
 
   // this returns the most recent non-popup browser window
   getMostRecentBrowserWindow: function BG_getMostRecentBrowserWindow() {
     var wm = Cc["@mozilla.org/appshell/window-mediator;1"].
-             getService(Components.interfaces.nsIWindowMediator);
+             getService(Ci.nsIWindowMediator);
+
+    function isFullBrowserWindow(win) {
+      return !win.closed &&
+             !win.document.documentElement.getAttribute("chromehidden");
+    }
 
 #ifdef BROKEN_WM_Z_ORDER
-    var win = wm.getMostRecentWindow("navigator:browser", true);
+    var win = wm.getMostRecentWindow("navigator:browser");
 
     // if we're lucky, this isn't a popup, and we can just return this
-    if (win && win.document.documentElement.getAttribute("chromehidden")) {
+    if (win && !isFullBrowserWindow(win)) {
       win = null;
-      var windowList = wm.getEnumerator("navigator:browser", true);
+      let windowList = wm.getEnumerator("navigator:browser");
       // this is oldest to newest, so this gets a bit ugly
       while (windowList.hasMoreElements()) {
-        var nextWin = windowList.getNext();
-        if (!nextWin.document.documentElement.getAttribute("chromehidden"))
+        let nextWin = windowList.getNext();
+        if (isFullBrowserWindow(nextWin))
           win = nextWin;
       }
     }
+    return win;
 #else
     var windowList = wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
-    if (!windowList.hasMoreElements())
-      return null;
-
-    var win = windowList.getNext();
-    while (win.document.documentElement.getAttribute("chromehidden")) {
-      if (!windowList.hasMoreElements())
-        return null;
-
-      win = windowList.getNext();
+    while (windowList.hasMoreElements()) {
+      let win = windowList.getNext();
+      if (isFullBrowserWindow(win))
+        return win;
     }
+    return null;
 #endif
-
-    return win;
   },
 
 
   // for XPCOM
   classDescription: "Firefox Browser Glue Service",
   classID:          Components.ID("{eab9012e-5f74-4cbc-b2b5-a590235513cc}"),
   contractID:       "@mozilla.org/browser/browserglue;1",
 
--- a/browser/components/preferences/cookies.js
+++ b/browser/components/preferences/cookies.js
@@ -577,21 +577,23 @@ var gCookiesWindow = {
         else if (!item.container)
           ++selectedCookieCount;
       }
     }
     var item = this._view._getItemAtIndex(seln.currentIndex);
     if (item && seln.count == 1 && item.container && item.open)
       selectedCookieCount += 2;
 
-    var stringKey = selectedCookieCount == 1 ? "removeCookie" : "removeCookies";
-    document.getElementById("removeCookie").label = this._bundle.getString(stringKey);
+    var removeCookie = document.getElementById("removeCookie");
+    var removeCookies = document.getElementById("removeCookies");
+    removeCookie.parentNode.selectedPanel =
+      selectedCookieCount == 1 ? removeCookie : removeCookies;
 
     document.getElementById("removeAllCookies").disabled = this._view._filtered;
-    document.getElementById("removeCookie").disabled = !(seln.count > 0);
+    removeCookie.disabled = removeCookies.disabled = !(seln.count > 0);
   },
 
   deleteCookie: function () {
 #   // Selection Notes
 #   // - Selection always moves to *NEXT* adjacent item unless item
 #   //   is last child at a given level in which case it moves to *PREVIOUS*
 #   //   item
 #   //
--- a/browser/components/preferences/cookies.xul
+++ b/browser/components/preferences/cookies.xul
@@ -119,19 +119,24 @@
             <textbox id="expires" readonly="true" class="plain"/>
           </row>
         </rows>
       </grid>
     </hbox>
   </vbox>
   <hbox align="end">
     <hbox class="actionButtons" flex="1">
-      <button id="removeCookie" disabled="true" icon="remove" 
-              label="&button.removecookie.label;" accesskey="&button.removecookie.accesskey;"
-              oncommand="gCookiesWindow.deleteCookie();"/>
+      <deck oncommand="gCookiesWindow.deleteCookie();">
+        <button id="removeCookie" disabled="true" icon="remove"
+                label="&button.removecookie.label;"
+                accesskey="&button.removecookie.accesskey;"/>
+        <button id="removeCookies" disabled="true" icon="remove"
+                label="&button.removecookies.label;"
+                accesskey="&button.removecookie.accesskey;"/>
+      </deck>
       <button id="removeAllCookies" disabled="true" icon="clear"
               label="&button.removeallcookies.label;" accesskey="&button.removeallcookies.accesskey;"
               oncommand="gCookiesWindow.deleteAllCookies();"/>
       <spacer flex="1"/>
 #ifndef XP_MACOSX
       <button oncommand="close();" icon="close"
               label="&button.close.label;" accesskey="&button.close.accesskey;"/>
 #endif
--- a/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
+++ b/browser/components/privatebrowsing/src/nsPrivateBrowsingService.js
@@ -82,40 +82,32 @@ const STATE_IDLE = 0;
 const STATE_TRANSITION_STARTED = 1;
 const STATE_WAITING_FOR_RESTORE = 2;
 const STATE_RESTORE_FINISHED = 3;
 
 ////////////////////////////////////////////////////////////////////////////////
 //// PrivateBrowsingService
 
 function PrivateBrowsingService() {
+  this._obs = Cc["@mozilla.org/observer-service;1"].
+              getService(Ci.nsIObserverService);
   this._obs.addObserver(this, "profile-after-change", true);
   this._obs.addObserver(this, "quit-application-granted", true);
   this._obs.addObserver(this, "private-browsing", true);
   this._obs.addObserver(this, "command-line-startup", true);
   this._obs.addObserver(this, "sessionstore-browser-state-restored", true);
 }
 
 PrivateBrowsingService.prototype = {
-  // Observer Service
-  __obs: null,
-  get _obs() {
-    if (!this.__obs)
-      this.__obs = Cc["@mozilla.org/observer-service;1"].
-                   getService(Ci.nsIObserverService);
-    return this.__obs;
-  },
-
   // Preferences Service
-  __prefs: null,
   get _prefs() {
-    if (!this.__prefs)
-      this.__prefs = Cc["@mozilla.org/preferences-service;1"].
-                     getService(Ci.nsIPrefBranch);
-    return this.__prefs;
+    let prefs = Cc["@mozilla.org/preferences-service;1"].
+                getService(Ci.nsIPrefBranch);
+    this.__defineGetter__("_prefs", function() prefs);
+    return this._prefs;
   },
 
   // Whether the private browsing mode is currently active or not.
   _inPrivateBrowsing: false,
 
   // Saved browser state before entering the private mode.
   _savedBrowserState: null,
 
--- a/browser/components/privatebrowsing/test/browser/Makefile.in
+++ b/browser/components/privatebrowsing/test/browser/Makefile.in
@@ -59,16 +59,18 @@ include $(topsrcdir)/config/rules.mk
 		browser_privatebrowsing_import.js \
 		browser_privatebrowsing_newwindow_stopcmd.js \
 		browser_privatebrowsing_opendir.js \
 		browser_privatebrowsing_openlocation.js \
 		browser_privatebrowsing_pageinfo.js \
 		browser_privatebrowsing_placestitle.js \
 		browser_privatebrowsing_popupblocker.js \
 		browser_privatebrowsing_popupmode.js \
+		browser_privatebrowsing_protocolhandler.js \
+		browser_privatebrowsing_protocolhandler_page.html \
 		browser_privatebrowsing_searchbar.js \
 		browser_privatebrowsing_sslsite_transition.js \
 		browser_privatebrowsing_theming.js \
 		browser_privatebrowsing_transition.js \
 		browser_privatebrowsing_ui.js \
 		browser_privatebrowsing_urlbarfocus.js \
 		browser_privatebrowsing_viewsource.js \
 		browser_privatebrowsing_windowtitle.js \
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler.js
@@ -0,0 +1,86 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Private Browsing Tests.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ehsan Akhgari <ehsan.akhgari@gmail.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+// This test makes sure that the web pages can't register protocol handlers
+// inside the private browsing mode.
+
+function test() {
+  // initialization
+  let pb = Cc["@mozilla.org/privatebrowsing;1"].
+           getService(Ci.nsIPrivateBrowsingService);
+
+  const testPageURL = "http://example.com/browser/" +
+    "browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html";
+  waitForExplicitFinish();
+
+  const notificationValue = "Protocol Registration: testprotocol";
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function () {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+    setTimeout(function() {
+      // Make sure the notification is correctly displayed with a remember control
+      let notificationBox = gBrowser.getNotificationBox();
+      let notification = notificationBox.getNotificationWithValue(notificationValue);
+      ok(notification, "Notification box should be displaying outside of private browsing mode");
+      gBrowser.removeCurrentTab();
+
+      // enter the private browsing mode
+      pb.privateBrowsingEnabled = true;
+
+      gBrowser.selectedTab = gBrowser.addTab();
+      gBrowser.selectedBrowser.addEventListener("load", function () {
+        gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+        setTimeout(function () {
+          // Make sure the notification is correctly displayed without a remember control
+          let notificationBox = gBrowser.getNotificationBox();
+          let notification = notificationBox.getNotificationWithValue(notificationValue);
+          ok(!notification, "Notification box should not be displayed inside of private browsing mode");
+
+          gBrowser.removeCurrentTab();
+
+          // cleanup
+          pb.privateBrowsingEnabled = false;
+          finish();
+        }, 100); // remember control is added in a setTimeout(0) call
+      }, true);
+      content.location = testPageURL;
+    }, 100); // remember control is added in a setTimeout(0) call
+  }, true);
+  content.location = testPageURL;
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_protocolhandler_page.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
+<html>
+  <head>
+    <title>Protocol registrar page</title>
+  </head>
+  <body>
+    <script type="text/javascript">
+      navigator.registerProtocolHandler("testprotocol",
+          "https://example.com/foobar?uri=%s",
+          "Test Protocol");
+    </script>
+  </body>
+</html>
--- a/browser/components/sessionstore/src/nsSessionStartup.js
+++ b/browser/components/sessionstore/src/nsSessionStartup.js
@@ -64,17 +64,18 @@
 # * browser.startup.page is set to 3.
 */
 
 /* :::::::: Constants and Helpers ::::::::::::::: */
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+const Cu = Components.utils;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 const STATE_RUNNING_STR = "running";
 const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 megabytes
 
 XPCOMUtils.defineLazyServiceGetter(this, "ConsoleSvc",
   "@mozilla.org/consoleservice;1", "nsIConsoleService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "ObserverSvc",
@@ -127,18 +128,18 @@ SessionStartup.prototype = {
     
     // get string containing session state
     this._iniString = this._readStateFile(sessionFile);
     if (!this._iniString)
       return;
     
     try {
       // parse the session state into JS objects
-      var s = new Components.utils.Sandbox("about:blank");
-      var initialState = Components.utils.evalInSandbox("(" + this._iniString + ")", s);
+      var s = new Cu.Sandbox("about:blank");
+      var initialState = Cu.evalInSandbox("(" + this._iniString + ")", s);
     }
     catch (ex) { debug("The session file is invalid: " + ex); } 
     
     let lastSessionCrashed =
       initialState && initialState.session && initialState.session.state &&
       initialState.session.state == STATE_RUNNING_STR;
     
     // set the startup type
@@ -289,17 +290,17 @@ SessionStartup.prototype = {
       cvstream.init(stream, "UTF-8", fileSize, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
       var data = {};
       cvstream.readString(fileSize, data);
       var content = data.value;
       cvstream.close();
 
       return content.replace(/\r\n?/g, "\n");
     }
-    catch (ex) { Components.utils.reportError(ex); }
+    catch (ex) { Cu.reportError(ex); }
 
     return null;
   },
 
   /* ........ QueryInterface .............. */
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIObserver,
                                           Ci.nsISupportsWeakReference,
                                           Ci.nsISessionStartup]),
--- a/browser/fuel/test/browser_ApplicationPrefs.js
+++ b/browser/fuel/test/browser_ApplicationPrefs.js
@@ -135,43 +135,43 @@ function test() {
   ok(!pref.locked, "A single preference should not be locked.");
 
   pref.locked = true;
   ok(pref.locked, "A single preference should be locked.");
 
   try {
     prev.value = "test value";
 
-    ok(false, "A locked preference should not be able to be modified.");
+    ok(false, "A locked preference could be modified.");
   } catch(e){
     ok(true, "A locked preference should not be able to be modified.");
   }
 
   pref.locked = false;
-  ok(!pref.locked, "A single preference should not be locked.");
+  ok(!pref.locked, "A single preference is unlocked.");
 
   // check for change event when setting a value
   waitForExplicitFinish();
   Application.prefs.events.addListener("change", onPrefChange);
   Application.prefs.setValue("fuel.fuel-test", "change event");
 }
 
 function onPrefChange(evt) {
-  is(evt.data, testdata.dummy, "Check 'Application.prefs.set' fired a change event");
+  is(evt.data, testdata.dummy, "Check 'Application.prefs.setValue' fired a change event");
   Application.prefs.events.removeListener("change", onPrefChange);
 
   // We are removing the old listener after adding the new listener so we can test that
   // removing a listener does not remove all listeners
   Application.prefs.get("fuel.fuel-test").events.addListener("change", onPrefChangeDummy);
   Application.prefs.get("fuel.fuel-test").events.addListener("change", onPrefChange2);
   Application.prefs.get("fuel.fuel-test").events.removeListener("change", onPrefChangeDummy);
 
   Application.prefs.setValue("fuel.fuel-test", "change event2");
 }
 
 function onPrefChange2(evt) {
-  is(evt.data, testdata.dummy, "Check 'Application.prefs.set' fired a change event for a single preference");
+  is(evt.data, testdata.dummy, "Check 'Application.prefs.setValue' fired a change event for a single preference");
   Application.prefs.events.removeListener("change", onPrefChange2);
 
   finish();
 }
 
 function onPrefChangeDummy(evt) { }
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -303,16 +303,18 @@
 <!ENTITY sendImageCmd.label           "Send Image…">
 <!ENTITY sendImageCmd.accesskey       "n">
 <!ENTITY sendVideoCmd.label           "Send Video…">
 <!ENTITY sendVideoCmd.accesskey       "n">
 <!ENTITY sendAudioCmd.label           "Send Audio…">
 <!ENTITY sendAudioCmd.accesskey       "n">
 <!ENTITY copyLinkCmd.label            "Copy Link Location">
 <!ENTITY copyLinkCmd.accesskey        "a">
+<!ENTITY copyLinkText2Cmd.label       "Copy Link Text">
+<!ENTITY copyLinkText2Cmd.accesskey   "x">
 <!ENTITY copyImageCmd.label           "Copy Image Location">
 <!ENTITY copyImageCmd.accesskey       "o">
 <!ENTITY copyImageContentsCmd.label   "Copy Image">
 <!ENTITY copyImageContentsCmd.accesskey  "y"> 
 <!ENTITY copyVideoURLCmd.label        "Copy Video Location">
 <!ENTITY copyVideoURLCmd.accesskey    "o">
 <!ENTITY copyAudioURLCmd.label        "Copy Audio Location">
 <!ENTITY copyAudioURLCmd.accesskey    "o">
--- a/browser/locales/en-US/chrome/browser/preferences/cookies.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/cookies.dtd
@@ -1,13 +1,14 @@
 <!ENTITY window.width                       "36em">
 
 <!ENTITY     cookiesonsystem.label          "The following cookies are stored on your computer:">
 <!ENTITY     cookiename.label               "Cookie Name">
 <!ENTITY     cookiedomain.label             "Site"> 
+<!ENTITY     button.removecookies.label     "Remove Cookies">
 <!ENTITY     button.removecookie.label      "Remove Cookie">
 <!ENTITY     button.removecookie.accesskey  "R">
 <!ENTITY     button.removeallcookies.label  "Remove All Cookies">
 <!ENTITY     button.removeallcookies.accesskey "A">
 
 <!ENTITY     props.name.label               "Name:">
 <!ENTITY     props.value.label              "Content:">
 <!ENTITY     props.domain.label             "Host:">
--- a/browser/locales/en-US/chrome/browser/preferences/preferences.properties
+++ b/browser/locales/en-US/chrome/browser/preferences/preferences.properties
@@ -83,18 +83,16 @@ forSecureOnly=Encrypted connections only
 forAnyConnection=Any type of connection
 expireAtEndOfSession=At end of session
 can=Allow
 canSession=Allow for Session
 cannot=Block
 noCookieSelected=<no cookie selected>
 cookiesAll=The following cookies are stored on your computer:
 cookiesFiltered=The following cookies match your search:
-removeCookies=Remove Cookies
-removeCookie=Remove Cookie
 
 #### Offline apps
 offlineAppRemoveTitle=Remove offline website data
 offlineAppRemovePrompt=After removing this data, %S will not be available offline.  Are you sure you want to remove this offline website?
 offlineAppRemoveConfirm=Remove offline data
 
 # LOCALIZATION NOTE: The next string is for the disk usage of the
 # offline application
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -42,21 +42,22 @@
 #include "nsISerializable.idl"
 
 %{C++
 struct JSContext;
 struct JSPrincipals;
 %}
 
 interface nsIURI;
+interface nsIContentSecurityPolicy;
 
 [ptr] native JSContext(JSContext);
 [ptr] native JSPrincipals(JSPrincipals);
 
-[scriptable, uuid(b8268b9a-2403-44ed-81e3-614075c92034)]
+[scriptable, uuid(799ab95c-0038-4e0f-b705-74c21f185bb5)]
 interface nsIPrincipal : nsISerializable
 {
     /**
      * Values of capabilities for each principal. Order is
      * significant: if an operation is performed on a set
      * of capabilities, the minimum is computed.
      */
     const short ENABLE_DENIED                = 1;
@@ -236,9 +237,14 @@ interface nsIPrincipal : nsISerializable
      */
     readonly attribute AUTF8String subjectName;
 
     /**
      * The certificate associated with this principal, if any.  If there isn't
      * one, this will return null.  Getting this attribute never throws.
      */
     readonly attribute nsISupports certificate;
+
+    /**
+     * A Content Security Policy associated with this principal.
+     */
+    [noscript] attribute nsIContentSecurityPolicy csp;
 };
--- a/caps/include/nsPrincipal.h
+++ b/caps/include/nsPrincipal.h
@@ -133,16 +133,17 @@ protected:
 
   // Keep this is a pointer, even though it may slightly increase the
   // cost of keeping a certificate, this is a good tradeoff though since
   // it is very rare that we actually have a certificate.
   nsAutoPtr<Certificate> mCert;
 
   DomainPolicy* mSecurityPolicy;
 
+  nsCOMPtr<nsIContentSecurityPolicy> mCSP;
   nsCOMPtr<nsIURI> mCodebase;
   nsCOMPtr<nsIURI> mDomain;
   PRPackedBool mTrusted;
   PRPackedBool mInitialized;
   // If mCodebaseImmutable is true, mCodebase is non-null and immutable
   PRPackedBool mCodebaseImmutable;
   PRPackedBool mDomainImmutable;
 };
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -247,16 +247,31 @@ nsNullPrincipal::DisableCapability(const
 
 NS_IMETHODIMP 
 nsNullPrincipal::GetURI(nsIURI** aURI)
 {
   return NS_EnsureSafeToReturn(mURI, aURI);
 }
 
 NS_IMETHODIMP
+nsNullPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
+{
+  // CSP on a null principal makes no sense
+  *aCsp = nsnull;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsNullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
+{
+  // CSP on a null principal makes no sense
+  return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
 nsNullPrincipal::GetDomain(nsIURI** aDomain)
 {
   return NS_EnsureSafeToReturn(mURI, aDomain);
 }
 
 NS_IMETHODIMP
 nsNullPrincipal::SetDomain(nsIURI* aDomain)
 {
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -52,16 +52,17 @@
 #include "nsVoidArray.h"
 #include "nsHashtable.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIPrefBranch2.h"
 #include "nsIPrefService.h"
 #include "nsIClassInfoImpl.h"
 #include "nsDOMError.h"
+#include "nsIContentSecurityPolicy.h"
 
 #include "nsPrincipal.h"
 
 class nsCodeBasePrefObserver : nsIObserver
 {
 public:
   nsCodeBasePrefObserver()
   {
@@ -770,16 +771,35 @@ nsPrincipal::GetCertificate(nsISupports*
   }
   else {
     *aCertificate = nsnull;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
+{
+  NS_IF_ADDREF(*aCsp = mCSP);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
+{
+  // If CSP was already set, it should not be destroyed!  Instead, it should
+  // get set anew when a new principal is created.
+  if (mCSP)
+    return NS_ERROR_ALREADY_INITIALIZED;
+
+  mCSP = aCsp;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsPrincipal::GetHashValue(PRUint32* aValue)
 {
   NS_PRECONDITION(mCert || mCodebase, "Need a cert or codebase");
 
   // If there is a certificate, it takes precendence over the codebase.
   if (mCert) {
     *aValue = nsCRT::HashCode(mCert->fingerprint.get());
   }
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -219,16 +219,30 @@ nsSystemPrincipal::GetCertificate(nsISup
 NS_IMETHODIMP 
 nsSystemPrincipal::GetHasCertificate(PRBool* aResult)
 {
     *aResult = PR_FALSE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsSystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
+{
+  *aCsp = nsnull;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsSystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
+{
+  // CSP on a null principal makes no sense
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsSystemPrincipal::GetDomain(nsIURI** aDomain)
 {
     *aDomain = nsnull;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSystemPrincipal::SetDomain(nsIURI* aDomain)
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -509,16 +509,18 @@ MOZ_TOOLKIT_REGISTRY_CFLAGS = \
 CAIRO_FT_CFLAGS		= @CAIRO_FT_CFLAGS@
 
 MOZ_TREE_FREETYPE		= @MOZ_TREE_FREETYPE@
 MOZ_ENABLE_CAIRO_FT	= @MOZ_ENABLE_CAIRO_FT@
 MOZ_ENABLE_GTK2		= @MOZ_ENABLE_GTK2@
 MOZ_ENABLE_QT		= @MOZ_ENABLE_QT@
 MOZ_ENABLE_PHOTON	= @MOZ_ENABLE_PHOTON@
 MOZ_ENABLE_XREMOTE	= @MOZ_ENABLE_XREMOTE@
+MOZ_ENABLE_DWRITE_FONT	= @MOZ_ENABLE_DWRITE_FONT@
+MOZ_ENABLE_D2D_SURFACE	= @MOZ_ENABLE_D2D_SURFACE@
 
 MOZ_GTK2_CFLAGS		= @MOZ_GTK2_CFLAGS@
 MOZ_GTK2_LIBS		= @MOZ_GTK2_LIBS@
 
 MOZ_QT_CFLAGS		= @MOZ_QT_CFLAGS@
 MOZ_QT_LIBS		= @MOZ_QT_LIBS@
 
 MOZ_DBUS_GLIB_CFLAGS    = @MOZ_DBUS_GLIB_CFLAGS@
--- a/configure.in
+++ b/configure.in
@@ -1043,17 +1043,16 @@ OBJ_SUFFIX=o
 LIB_SUFFIX=a
 ASM_SUFFIX=s
 IMPORT_LIB_SUFFIX=
 TARGET_MD_ARCH=unix
 DIRENT_INO=d_ino
 CYGWIN_WRAPPER=
 WIN_TOP_SRC=
 MOZ_USER_DIR=".mozilla"
-HOST_AR='$(AR)'
 HOST_AR_FLAGS='$(AR_FLAGS)'
 
 MOZ_JPEG_CFLAGS=
 MOZ_JPEG_LIBS='$(call EXPAND_LIBNAME_PATH,mozjpeg,$(DEPTH)/jpeg)'
 MOZ_ZLIB_CFLAGS=
 MOZ_ZLIB_LIBS='$(call EXPAND_LIBNAME_PATH,mozz,$(DEPTH)/modules/zlib/src)'
 MOZ_BZ2_CFLAGS=
 MOZ_BZ2_LIBS='$(call EXPAND_LIBNAME_PATH,bz2,$(DEPTH)/modules/libbz2/src)'
@@ -2613,17 +2612,16 @@ alpha*-*-osf*)
     AC_DEFINE(NSCAP_DISABLE_TEST_DONTQUERY_CASES)
     AC_DEFINE(NSCAP_DISABLE_DEBUG_PTR_TYPES)
     CXXFLAGS="$CXXFLAGS -I/usr/include/CC"
     if test ! "$GNU_CC"; then
        DSO_LDOPTS='-G'
     fi
     ;;
 
-dnl the qsort routine under solaris is faulty
 *-solaris*) 
     AC_DEFINE(SOLARIS)
     TARGET_NSPR_MDCPUCFG='\"md/_solaris.cfg\"'
     SYSTEM_MAKEDEPEND=
     # $ORIGIN/.. is for shared libraries under components/ to locate shared
     # libraries one level up (e.g. libnspr4.so)
     LDFLAGS="$LDFLAGS -z ignore -R '\$\$ORIGIN:\$\$ORIGIN/..'"
     MOZ_MEMORY=1
@@ -7680,18 +7678,29 @@ if test "$MOZ_TREE_CAIRO"; then
         QUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_SURFACE 1"
         QUARTZ_IMAGE_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_IMAGE_SURFACE 1"
         QUARTZ_FONT_FEATURE="#define CAIRO_HAS_QUARTZ_FONT 1"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "windows"; then
         WIN32_SURFACE_FEATURE="#define CAIRO_HAS_WIN32_SURFACE 1"
         if test -z "$WINCE"; then
             WIN32_FONT_FEATURE="#define CAIRO_HAS_WIN32_FONT 1"
+            if test "$MOZ_WINSDK_TARGETVER" -ge "06010000"; then
+                WIN32_DWRITE_FONT_FEATURE="#define CAIRO_HAS_DWRITE_FONT 1"
+                WIN32_D2D_SURFACE_FEATURE="#define CAIRO_HAS_D2D_SURFACE 1"
+                MOZ_ENABLE_D2D_SURFACE=1
+                MOZ_ENABLE_DWRITE_FONT=1
+            else
+                WIN32_DWRITE_FONT_FEATURE=
+                WIN32_D2D_SURFACE_FEATURE=
+            fi
         else
             WIN32_FONT_FEATURE=
+            WIN32_DWRITE_FONT_FEATURE=
+            WIN32_D2D_SURFACE_FEATURE=
         fi
 
         AC_TRY_COMPILE([#include <ddraw.h>], [int foo = DDLOCK_WAITNOTBUSY;], HAS_DDRAW=1, HAS_DDRAW=)
         if test -z "$HAS_DDRAW"; then
             AC_MSG_WARN([DirectDraw ddraw.h header not found or it's missing DDLOCK_WAITNOTBUSY, disabling DirectDraw surface.  If you have an older SDK (such as the CE5 SDK), try copying in ddraw.lib and ddraw.h from the WM6 SDK.])
             DDRAW_SURFACE_FEATURE=
         else
             DDRAW_SURFACE_FEATURE="#define CAIRO_HAS_DDRAW_SURFACE 1"
@@ -7729,16 +7738,18 @@ if test "$MOZ_TREE_CAIRO"; then
         BEOS_SURFACE_FEATURE="#define CAIRO_HAS_BEOS_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
         MOZ_ENABLE_CAIRO_FT=1
     fi
     if test "$USE_FC_FREETYPE"; then
         FC_FONT_FEATURE="#define CAIRO_HAS_FC_FONT 1"
     fi
     AC_SUBST(MOZ_ENABLE_CAIRO_FT)
+    AC_SUBST(MOZ_ENABLE_DWRITE_FONT)
+    AC_SUBST(MOZ_ENABLE_D2D_SURFACE)
     AC_SUBST(CAIRO_FT_CFLAGS)
     AC_SUBST(HAS_OGLES)
 
     if test "$MOZ_DEBUG"; then
       SANITY_CHECKING_FEATURE="#define CAIRO_DO_SANITY_CHECKING 1"
     else
       SANITY_CHECKING_FEATURE="#undef CAIRO_DO_SANITY_CHECKING"
     fi
@@ -7757,16 +7768,18 @@ if test "$MOZ_TREE_CAIRO"; then
     AC_SUBST(DDRAW_SURFACE_FEATURE)
     AC_SUBST(OGLES_SURFACE_FEATURE)    
     AC_SUBST(OS2_SURFACE_FEATURE)
     AC_SUBST(BEOS_SURFACE_FEATURE)
     AC_SUBST(DIRECTFB_SURFACE_FEATURE)
     AC_SUBST(FT_FONT_FEATURE)
     AC_SUBST(FC_FONT_FEATURE)
     AC_SUBST(WIN32_FONT_FEATURE)
+    AC_SUBST(WIN32_DWRITE_FONT_FEATURE)
+    AC_SUBST(WIN32_D2D_SURFACE_FEATURE)
     AC_SUBST(QUARTZ_FONT_FEATURE)
     AC_SUBST(PNG_FUNCTIONS_FEATURE)
     AC_SUBST(QT_SURFACE_FEATURE)
 
     if test "$_WIN32_MSVC"; then
         MOZ_CAIRO_LIBS='$(DEPTH)/gfx/cairo/cairo/src/mozcairo.lib $(DEPTH)/gfx/cairo/libpixman/src/mozlibpixman.lib'
     else
         MOZ_CAIRO_LIBS='$(DEPTH)/gfx/cairo/cairo/src/$(LIB_PREFIX)mozcairo.$(LIB_SUFFIX) $(DEPTH)/gfx/cairo/libpixman/src/$(LIB_PREFIX)mozlibpixman.$(LIB_SUFFIX)'" $CAIRO_FT_LIBS"
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -32,31 +32,31 @@ load 369216-1.html
 load 371466-1.xhtml
 load 377360-1.xhtml
 load 384663-1.html
 load 386000-1.html
 load 386794-1.html
 load 387460-1.html
 load 395469-1.xhtml
 load 395469-2.xhtml
-load 399712-1.html
+skip load 399712-1.html # sporadically times out (bug 473680)
 load 398088-1.xul
 load 400763-1.html
 load 401993-1.html
 load 407818.html
 load 410860-1.xml
 load 416734-1.html
 load 418928-1.html
 load 420620-1.html
 load 424276-1.html
 load 426987-1.html
 load 443538-1.svg
 load 450383-1.html
 load 450385-1.html
-skip load 458637-1.html # sporadically fails -- see bug 473680
+skip load 458637-1.html # sporadically times out (bug 473680)
 load 472593-1.html
 load 474041-1.svg
 load 483818-1.html
 load 493281-1.html
 load 493281-2.html
 load 490760-1.xhtml
 load 494810-1.html
 load 529670.html
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -97,17 +97,17 @@ interface nsIXMLHttpRequestUpload : nsIX
  *   The 'onload', 'onerror', and 'onreadystatechange' attributes moved to
  *   nsIJSXMLHttpRequest, but if you're coding in C++ you should avoid using
  *   those.
  *
  * Conclusion: Do not use event listeners on XMLHttpRequest from C++, unless
  * you're aware of all the security implications.  And then think twice about
  * it.
  */
-[scriptable, uuid(ad78bf21-2227-447e-8ed5-824a017c265f)]
+[scriptable, uuid(6bb91106-85f0-4d93-8cb4-e57b3d0624f2)]
 interface nsIXMLHttpRequest : nsISupports
 {
   /**
    * The request uses a channel in order to perform the
    * request.  This attribute represents the channel used
    * for the request.  NULL if the channel has not yet been
    * created.
    *
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -74,16 +74,17 @@ CPPSRCS		= \
 		nsContentAreaDragDrop.cpp \
 		nsContentIterator.cpp \
 		nsContentList.cpp \
 		nsContentPolicy.cpp \
 		nsContentSink.cpp \
 		nsContentUtils.cpp \
 		nsCopySupport.cpp \
 		nsCrossSiteListenerProxy.cpp \
+		nsCSPService.cpp \
 		nsDataDocumentContentPolicy.cpp \
 		nsDOMAttribute.cpp \
 		nsDOMAttributeMap.cpp \
 		nsDOMDocumentType.cpp \
 		nsDOMFile.cpp \
 		nsDOMFileReader.cpp \
 		nsDOMLists.cpp \
 		nsDOMParser.cpp \
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsCSPService.cpp
@@ -0,0 +1,198 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brandon Sterne <bsterne@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "prlog.h"
+#include "nsString.h"
+#include "nsCOMPtr.h"
+#include "nsIURI.h"
+#include "nsIPrincipal.h"
+#include "nsIObserver.h"
+#include "nsIDocument.h"
+#include "nsIContent.h"
+#include "nsContentUtils.h"
+#include "nsCSPService.h"
+#include "nsIContentSecurityPolicy.h"
+
+/* Keeps track of whether or not CSP is enabled */
+static PRBool gCSPEnabled = PR_TRUE;
+
+#ifdef PR_LOGGING
+static PRLogModuleInfo* gCspPRLog;
+#endif
+
+CSPService::CSPService()
+{
+  nsContentUtils::AddBoolPrefVarCache("security.csp.enable", &gCSPEnabled);
+
+#ifdef PR_LOGGING
+  if (!gCspPRLog)
+    gCspPRLog = PR_NewLogModule("CSP");
+#endif
+}
+
+CSPService::~CSPService()
+{
+}
+
+NS_IMPL_ISUPPORTS1(CSPService, nsIContentPolicy)
+
+/* nsIContentPolicy implementation */
+NS_IMETHODIMP
+CSPService::ShouldLoad(PRUint32 aContentType,
+                       nsIURI *aContentLocation,
+                       nsIURI *aRequestOrigin,
+                       nsISupports *aRequestContext,
+                       const nsACString &aMimeTypeGuess,
+                       nsISupports *aExtra,
+                       PRInt16 *aDecision)
+{
+    if (!aContentLocation)
+        return NS_ERROR_FAILURE;
+
+#ifdef PR_LOGGING 
+    {
+        nsCAutoString location;
+        aContentLocation->GetSpec(location);
+        PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+            ("CSPService::ShouldLoad called for %s", location.get()));
+    }
+#endif
+    // default decision, CSP can revise it if there's a policy to enforce
+    *aDecision = nsIContentPolicy::ACCEPT;
+
+    // No need to continue processing if CSP is disabled
+    if (!gCSPEnabled)
+        return NS_OK;
+
+    // find the nsDocument that initiated this request and see if it has a
+    // CSP policy object
+    nsresult rv;
+    nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
+    nsCOMPtr<nsIPrincipal> principal;
+    nsCOMPtr<nsIContentSecurityPolicy> csp;
+    if (node) {
+        principal = node->NodePrincipal();
+        principal->GetCsp(getter_AddRefs(csp));
+
+        if (csp) {
+#ifdef PR_LOGGING 
+            nsAutoString policy;
+            csp->GetPolicy(policy);
+            PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+                    ("Document has CSP: %s", 
+                     NS_ConvertUTF16toUTF8(policy).get()));
+#endif
+            // obtain the enforcement decision
+            csp->ShouldLoad(aContentType,
+                            aContentLocation,
+                            aRequestOrigin,
+                            aRequestContext,
+                            aMimeTypeGuess,
+                            aExtra,
+                            aDecision);
+        }
+    }
+#ifdef PR_LOGGING
+    else {
+        nsCAutoString uriSpec;
+        aContentLocation->GetSpec(uriSpec);
+        PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+            ("COULD NOT get nsINode for location: %s", uriSpec.get()));
+    }
+#endif
+	
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+CSPService::ShouldProcess(PRUint32         aContentType,
+                          nsIURI           *aContentLocation,
+                          nsIURI           *aRequestOrigin,
+                          nsISupports      *aRequestContext,
+                          const nsACString &aMimeTypeGuess,
+                          nsISupports      *aExtra,
+                          PRInt16          *aDecision)
+{
+    if (!aContentLocation)
+        return NS_ERROR_FAILURE;
+
+    // default decision is to accept the item
+    *aDecision = nsIContentPolicy::ACCEPT;
+
+    // No need to continue processing if CSP is disabled
+    if (!gCSPEnabled)
+        return NS_OK;
+
+    // find the nsDocument that initiated this request and see if it has a
+    // CSP policy object
+    nsresult rv;
+    nsCOMPtr<nsINode> node(do_QueryInterface(aRequestContext));
+    nsCOMPtr<nsIPrincipal> principal;
+    nsCOMPtr<nsIContentSecurityPolicy> csp;
+    if (node) {
+        principal = node->NodePrincipal();
+        principal->GetCsp(getter_AddRefs(csp));
+
+        if (csp) {
+#ifdef PR_LOGGING
+            nsAutoString policy;
+            csp->GetPolicy(policy);
+            PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+                  ("shouldProcess - document has policy: %s",
+                    NS_ConvertUTF16toUTF8(policy).get()));
+#endif
+            // obtain the enforcement decision
+            csp->ShouldProcess(aContentType,
+                               aContentLocation,
+                               aRequestOrigin,
+                               aRequestContext,
+                               aMimeTypeGuess,
+                               aExtra,
+                               aDecision);
+        }
+    }
+#ifdef PR_LOGGING
+    else {
+        nsCAutoString uriSpec;
+        aContentLocation->GetSpec(uriSpec);
+        PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+            ("COULD NOT get nsINode for location: %s", uriSpec.get()));
+    }
+#endif
+    return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsCSPService.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brandon Sterne <bsterne@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsXPCOM.h"
+#include "nsIContentPolicy.h"
+
+#define CSPSERVICE_CONTRACTID "@mozilla.org/cspservice;1"
+#define CSPSERVICE_CID \
+  { 0x8d2f40b2, 0x4875, 0x4c95, \
+    { 0x97, 0xd9, 0x3f, 0x7d, 0xca, 0x2c, 0xb4, 0x60 } }
+class CSPService : public nsIContentPolicy
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICONTENTPOLICY
+  
+  CSPService();
+  virtual ~CSPService();
+
+private:
+  PRBool mEnabled;
+};
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -176,25 +176,32 @@ static NS_DEFINE_CID(kDOMEventGroupCID, 
 #include "mozAutoDocUpdate.h"
 
 #ifdef MOZ_SMIL
 #include "nsSMILAnimationController.h"
 #include "imgIContainer.h"
 #include "nsSVGUtils.h"
 #endif // MOZ_SMIL
 
+// FOR CSP (autogenerated by xpidl)
+#include "nsIContentSecurityPolicy.h"
+
 
 #ifdef MOZ_LOGGING
 // so we can get logging even in release builds
 #define FORCE_PR_LOG 1
 #endif
 #include "prlog.h"
 
+/* Keeps track of whether or not CSP is enabled */
+static PRBool gCSPEnabled = PR_TRUE;
+
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDocumentLeakPRLog;
+static PRLogModuleInfo* gCspPRLog;
 #endif
 
 void
 nsUint32ToContentHashEntry::Destroy()
 {
   HashSet* set = GetHashSet();
   if (set) {
     delete set;
@@ -893,17 +900,17 @@ nsExternalResourceMap::AddExternalResour
   nsRefPtr<PendingLoad> load;
   mPendingLoads.Get(aURI, getter_AddRefs(load));
   mPendingLoads.Remove(aURI);
 
   nsresult rv = NS_OK;
   
   nsCOMPtr<nsIDocument> doc;
   if (aViewer) {
-    aViewer->GetDocument(getter_AddRefs(doc));
+    doc = aViewer->GetDocument();
     NS_ASSERTION(doc, "Must have a document");
 
     nsCOMPtr<nsIXULDocument> xulDoc = do_QueryInterface(doc);
     if (xulDoc) {
       // We don't handle XUL stuff here yet.
       rv = NS_ERROR_NOT_AVAILABLE;
     } else {
       doc->SetDisplayDocument(aDisplayDocument);
@@ -1490,18 +1497,23 @@ nsDocument::nsDocument(const char* aCont
   
 #ifdef PR_LOGGING
   if (!gDocumentLeakPRLog)
     gDocumentLeakPRLog = PR_NewLogModule("DocumentLeak");
 
   if (gDocumentLeakPRLog)
     PR_LOG(gDocumentLeakPRLog, PR_LOG_DEBUG,
            ("DOCUMENT %p created", this));
+
+  if (!gCspPRLog)
+    gCspPRLog = PR_NewLogModule("CSP");
 #endif
 
+  nsContentUtils::AddBoolPrefVarCache("security.csp.enable", &gCSPEnabled);
+
   // Start out mLastStyleSheetSet as null, per spec
   SetDOMStringToNull(mLastStyleSheetSet);
 }
 
 static PLDHashOperator
 ClearAllBoxObjects(const void* aKey, nsPIBoxObject* aBoxObject, void* aUserArg)
 {
   if (aBoxObject) {
@@ -2246,17 +2258,121 @@ nsDocument::StartDocumentLoad(const char
     semicolon = start;
     FindCharInReadable(';', semicolon, end);
     mContentType = Substring(start, semicolon);
   }
 
   RetrieveRelevantHeaders(aChannel);
 
   mChannel = aChannel;
-
+  
+  nsresult rv = InitCSP();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+
+nsresult
+nsDocument::InitCSP()
+{
+  if (gCSPEnabled) {
+    nsAutoString cspHeaderValue;
+    nsAutoString cspROHeaderValue;
+
+    this->GetHeaderData(nsGkAtoms::headerCSP, cspHeaderValue);
+    this->GetHeaderData(nsGkAtoms::headerCSPReportOnly, cspROHeaderValue);
+
+    PRBool system = PR_FALSE;
+    nsIScriptSecurityManager *ssm = nsContentUtils::GetSecurityManager();
+
+    if (NS_SUCCEEDED(ssm->IsSystemPrincipal(NodePrincipal(), &system)) && system) {
+      // only makes sense to register new CSP if this document is not priviliged
+      return NS_OK;
+    }
+
+    if (cspHeaderValue.IsEmpty() && cspROHeaderValue.IsEmpty()) {
+      // no CSP header present, stop processing
+      return NS_OK;
+    }
+
+#ifdef PR_LOGGING 
+    PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP header specified for document %p", this));
+#endif
+
+    nsresult rv;
+    nsCOMPtr<nsIContentSecurityPolicy> mCSP;
+    mCSP = do_CreateInstance("@mozilla.org/contentsecuritypolicy;1", &rv);
+
+    if (NS_FAILED(rv)) {
+#ifdef PR_LOGGING 
+      PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("Failed to create CSP object: %x", rv));
+#endif
+      return rv;
+    }
+
+    // Store the request context for violation reports
+    nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mChannel);
+    mCSP->ScanRequestData(httpChannel);
+
+    // Start parsing the policy
+    nsCOMPtr<nsIURI> chanURI;
+    mChannel->GetURI(getter_AddRefs(chanURI));
+
+#ifdef PR_LOGGING 
+    PR_LOG(gCspPRLog, PR_LOG_DEBUG, ("CSP Loaded"));
+#endif
+
+    // ReportOnly mode is enabled *only* if there are no regular-strength CSP
+    // headers present.  If there are, then we ignore the ReportOnly mode and
+    // toss a warning into the error console, proceeding with enforcing the
+    // regular-strength CSP.
+    if (cspHeaderValue.IsEmpty()) {
+      mCSP->SetReportOnlyMode(true);
+      mCSP->RefinePolicy(cspROHeaderValue, chanURI);
+#ifdef PR_LOGGING 
+      {
+        PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+                ("CSP (report only) refined, policy: \"%s\"", 
+                  NS_ConvertUTF16toUTF8(cspROHeaderValue).get()));
+      }
+#endif
+    } else {
+      //XXX(sstamm): maybe we should post a warning when both read only and regular 
+      // CSP headers are present.
+      mCSP->RefinePolicy(cspHeaderValue, chanURI);
+#ifdef PR_LOGGING 
+      {
+        PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+               ("CSP refined, policy: \"%s\"",
+                NS_ConvertUTF16toUTF8(cspHeaderValue).get()));
+      }
+#endif
+    }
+
+    //Copy into principal
+    nsIPrincipal* principal = GetPrincipal();
+
+    if (principal) {
+        principal->SetCsp(mCSP);
+#ifdef PR_LOGGING
+        PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+                ("Inserted CSP into principal %p", principal));
+    }
+    else {
+      PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+              ("Couldn't copy CSP into absent principal %p", principal));
+#endif
+    }
+  }
+#ifdef PR_LOGGING
+  else { //CSP was not enabled!
+    PR_LOG(gCspPRLog, PR_LOG_DEBUG, 
+           ("CSP is disabled, skipping CSP init for document %p", this));
+  }
+#endif
   return NS_OK;
 }
 
 void
 nsDocument::StopDocumentLoad()
 {
   if (mParser) {
     mParser->Terminate();
@@ -6643,16 +6759,18 @@ nsDocument::RetrieveRelevantHeaders(nsIC
 
     static const char *const headers[] = {
       "default-style",
       "content-style-type",
       "content-language",
       "content-disposition",
       "refresh",
       "x-dns-prefetch-control",
+      "x-content-security-policy",
+      "x-content-security-policy-read-only",
       // add more http headers if you need
       // XXXbz don't add content-location support without reading bug
       // 238654 and its dependencies/dups first.
       0
     };
     
     nsCAutoString headerVal;
     const char *const *name = headers;
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -1208,16 +1208,18 @@ protected:
   nsCOMPtr<nsIContent> mFirstBaseNodeWithHref;
 
 private:
   friend class nsUnblockOnloadEvent;
 
   void PostUnblockOnloadEvent();
   void DoUnblockOnload();
 
+  nsresult InitCSP();
+
   /**
    * See if aDocument is a child of this.  If so, return the frame element in
    * this document that holds currentDoc (or an ancestor).
    */
   already_AddRefed<nsIDOMElement>
     CheckAncestryAndGetFrame(nsIDocument* aDocument) const;
 
   // Just like EnableStyleSheetsForSet, but doesn't check whether
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1002,16 +1002,18 @@ GK_ATOM(where, "where")
 GK_ATOM(widget, "widget")
 GK_ATOM(width, "width")
 GK_ATOM(window, "window")
 GK_ATOM(headerWindowTarget, "window-target")
 GK_ATOM(withParam, "with-param")
 GK_ATOM(wizard, "wizard")
 GK_ATOM(wrap, "wrap")
 GK_ATOM(headerDNSPrefetchControl,"x-dns-prefetch-control")
+GK_ATOM(headerCSP, "x-content-security-policy")
+GK_ATOM(headerCSPReportOnly, "x-content-security-policy-report-only")
 GK_ATOM(xml, "xml")
 GK_ATOM(xmlns, "xmlns")
 GK_ATOM(xmp, "xmp")
 GK_ATOM(xulcontentsgenerated, "xulcontentsgenerated")
 GK_ATOM(yes, "yes")
 GK_ATOM(z_index, "z-index")
 GK_ATOM(zeroDigit, "zero-digit")
 
--- a/content/base/src/nsHTMLContentSerializer.cpp
+++ b/content/base/src/nsHTMLContentSerializer.cpp
@@ -63,18 +63,16 @@
 #include "nsEscape.h"
 #include "nsITextToSubURI.h"
 #include "nsCRT.h"
 #include "nsIParserService.h"
 #include "nsContentUtils.h"
 #include "nsLWBrkCIID.h"
 #include "nsIScriptElement.h"
 #include "nsAttrName.h"
-#include "nsHtml5Module.h"
-#include "nsIHTMLDocument.h"
 
 static const char kMozStr[] = "moz";
 
 static const PRInt32 kLongLineLen = 128;
 
 nsresult NS_NewHTMLContentSerializer(nsIContentSerializer** aSerializer)
 {
   nsHTMLContentSerializer* it = new nsHTMLContentSerializer();
@@ -113,41 +111,18 @@ nsHTMLContentSerializer::SerializeHTMLAt
   PRInt32 count = aContent->GetAttrCount();
   if (!count)
     return;
 
   nsresult rv;
   nsAutoString nameStr, valueStr;
   NS_NAMED_LITERAL_STRING(_mozStr, "_moz");
 
-  // HTML5 parser stored them in the order they were parsed so we want to
-  // loop forward in that case.
-  nsIDocument* doc = aContent->GetOwnerDocument();
-  PRBool loopForward = PR_FALSE;
-  if (!doc || doc->IsHTML()) {
-    nsCOMPtr<nsIHTMLDocument> htmlDoc(do_QueryInterface(doc));
-    if (htmlDoc) {
-      loopForward = nsHtml5Module::sEnabled;
-    }
-  }
-  PRInt32 index, limit, step;
-  if (loopForward) {
-    index = 0;
-    limit = count;
-    step = 1;
-  }
-  else {
-    // Loop backward over the attributes, since the order they are stored in is
-    // the opposite of the order they were parsed in (see bug 213347 for reason).
-    index = count - 1;
-    limit = -1;
-    step = -1;
-  }
-  
-  for (; index != limit; index += step) {
+  for (PRInt32 index = count; index > 0;) {
+    --index;
     const nsAttrName* name = aContent->GetAttrNameAt(index);
     PRInt32 namespaceID = name->NamespaceID();
     nsIAtom* attrName = name->LocalName();
 
     // Filter out any attribute starting with [-|_]moz
     const char* sharedName;
     attrName->GetUTF8String(&sharedName);
     if ((('_' == *sharedName) || ('-' == *sharedName)) &&
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -328,16 +328,20 @@ include $(topsrcdir)/config/rules.mk
 		test_bug475156.html \
 		bug475156.sjs \
 		test_copypaste.html \
 		test_bug503481.html \
 		file_bug503481.sjs \
 		test_bug503481b.html \
 		file_bug503481b_inner.html \
 		test_viewport_scroll.html \
+		test_CSP.html \
+		file_CSP.sjs \
+		file_CSP_main.html \
+		file_CSP_main.js \
 		$(NULL)
 
 # Disabled; see bug 492181
 #		test_plugin_freezing.html
 
 # Disabled for now. Mochitest isn't reliable enough for these.
 # test_bug444546.html \
 # bug444546.sjs \
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP.sjs
@@ -0,0 +1,44 @@
+// SJS file for CSP mochitests
+
+function handleRequest(request, response)
+{
+  var query = {};
+  request.queryString.split('&').forEach(function (val) {
+    var [name, value] = val.split('=');
+    query[name] = unescape(value);
+  });
+
+  var isPreflight = request.method == "OPTIONS";
+
+
+  //avoid confusing cache behaviors
+  response.setHeader("Cache-Control", "no-cache", false);
+
+  if ("main" in query) {
+    var xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]  
+                   .createInstance(Components.interfaces.nsIXMLHttpRequest);
+    //serve the main page with a CSP header!
+    // -- anything served from 'self' (localhost:8888) will be allowed,
+    // -- anything served from other hosts (example.com:80) will be blocked.
+    // -- XHR tests are set up in the file_CSP_main.js file which is sourced.
+    response.setHeader("X-Content-Security-Policy", 
+                       "allow 'self'",
+                       false);
+    xhr.open("GET", "http://localhost:8888/tests/content/base/test/file_CSP_main.html", false);
+    xhr.send(null);
+    if(xhr.status == 200) {
+      response.write(xhr.responseText);
+    }
+  } else {
+    if ("type" in query) {
+      response.setHeader("Content-Type", unescape(query['type']), false);
+    } else {
+      response.setHeader("Content-Type", "text/html", false);
+    }
+
+    if ("content" in query) {
+      response.setHeader("Content-Type", "text/html", false);
+      response.write(unescape(query['content']));
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP_main.html
@@ -0,0 +1,55 @@
+<html>
+  <head>
+    <link rel='stylesheet' type='text/css'
+          href='http://example.org/tests/content/base/test/file_CSP.sjs?testid=style_bad&type=text/css' />
+    <link rel='stylesheet' type='text/css'
+          href='file_CSP.sjs?testid=style_good&type=text/css' />
+
+
+    <style>
+      /* CSS font embedding tests */
+      @font-face {
+        font-family: "arbitrary_good";
+        src: url('file_CSP.sjs?testid=font_good&type=application/octet-stream');
+      }
+      @font-face {
+        font-family: "arbitrary_bad";
+        src: url('http://example.org/tests/content/base/test/file_CSP.sjs?testid=font_bad&type=application/octet-stream');
+      }
+
+      .div_arbitrary_good { font-family: "arbitrary_good"; }
+      .div_arbitrary_bad { font-family: "arbitrary_bad"; }
+    </style>
+  </head>
+  <body>
+    <!-- these should be stopped by CSP.  :) -->
+    <img src="http://example.org/tests/content/base/test/file_CSP.sjs?testid=img_bad&type=img/png"> </img>
+    <audio src="http://example.org/tests/content/base/test/file_CSP.sjs?testid=media_bad&type=audio/vorbis"></audio>
+    <script src='http://example.org/tests/content/base/test/file_CSP.sjs?testid=script_bad&type=text/javascript'></script>
+    <iframe src='http://example.org/tests/content/base/test/file_CSP.sjs?testid=frame_bad&content=FAIL'></iframe>
+    <object width="10" height="10">
+      <param name="movie" value="http://example.org/tests/content/base/test/file_CSP.sjs?testid=object_bad&type=application/x-shockwave-flash">
+      <embed src="http://example.org/tests/content/base/test/file_CSP.sjs?testid=object_bad&type=application/x-shockwave-flash"></embed>
+    </object>
+
+    <!-- these should load ok.  :) -->
+    <img src="file_CSP.sjs?testid=img_good&type=img/png" />
+    <audio src="file_CSP.sjs?testid=media_good&type=audio/vorbis"></audio>
+    <script src='file_CSP.sjs?testid=script_good&type=text/javascript'></script>
+    <iframe src='file_CSP.sjs?testid=frame_good&content=PASS'></iframe>
+
+    <object width="10" height="10">
+      <param name="movie" value="file_CSP.sjs?testid=object_good&type=application/x-shockwave-flash">
+      <embed src="file_CSP.sjs?testid=object_good&type=application/x-shockwave-flash"></embed>
+    </object>
+
+    <!-- XHR tests... they're taken care of in this script, 
+         and since the URI doesn't have any 'testid' values, 
+         it will just be ignored by the test framework.  -->
+    <script src='file_CSP_main.js'></script>
+
+    <!-- Support elements for the @font-face test -->
+    <div class="div_arbitrary_good">arbitrary good</div>
+    <div class="div_arbitrary_bad">arbitrary_bad</div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_CSP_main.js
@@ -0,0 +1,16 @@
+// some javascript for the CSP XHR tests
+//
+
+try {
+  var xhr_good = new XMLHttpRequest();
+  var xhr_good_uri ="http://localhost:8888/tests/content/base/test/file_CSP.sjs?testid=xhr_good";
+  xhr_good.open("GET", xhr_good_uri, true);
+  xhr_good.send(null);
+} catch(e) {}
+
+try {
+  var xhr_bad = new XMLHttpRequest();
+  var xhr_bad_uri ="http://example.com/tests/content/base/test/file_CSP.sjs?testid=xhr_bad";
+  xhr_bad.open("GET", xhr_bad_uri, true);
+  xhr_bad.send(null);
+} catch(e) {}
--- a/content/base/test/file_htmlserializer_1.html
+++ b/content/base/test/file_htmlserializer_1.html
@@ -1,16 +1,12 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!DOCTYPE html><html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8">
   <title>Test for html serializer</title>
 
-</head>
-<body>
+</head><body>
 <p>Hello world</p> <p>
 
        Lorem ipsum dolor sit amet, <strong>consectetuer</strong> adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
      litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
 nostra, per inceptos hymenaeos. </p>
 
 
 <ul><li>Nam tellus massa,éàèçù</li><li>
@@ -40,11 +36,9 @@ comments -->
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
-<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-</body>
-</html>
\ No newline at end of file
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_bodyonly.html
+++ b/content/base/test/file_htmlserializer_1_bodyonly.html
@@ -39,10 +39,9 @@ comments -->
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
 <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
-aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-</body>
\ No newline at end of file
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p></body>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_format.html
+++ b/content/base/test/file_htmlserializer_1_format.html
@@ -1,9 +1,9 @@
-<!DOCTYPE HTML>
+<!DOCTYPE html>
 <html>
   <head>
     <meta http-equiv="content-type" content="text/html; charset=UTF-8">
     <title>Test for html serializer</title>
   </head>
   <body>
     <p>Hello world</p>
     <p> Lorem ipsum dolor sit amet, <strong>consectetuer</strong>
--- a/content/base/test/file_htmlserializer_1_linebreak.html
+++ b/content/base/test/file_htmlserializer_1_linebreak.html
@@ -1,13 +1,11 @@
-<!DOCTYPE HTML>
-<html><head>
-
-
-   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!DOCTYPE html>
+<html><head><meta http-equiv="content-type" content="text/html; 
+charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
        Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
 adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
 Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
@@ -46,10 +44,9 @@ comments -->
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
 <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
-aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-</body></html>
\ No newline at end of file
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_links.html
+++ b/content/base/test/file_htmlserializer_1_links.html
@@ -1,13 +1,11 @@
-<!DOCTYPE HTML>
-<html><head>
-
-
-   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!DOCTYPE html>
+<html><head><meta http-equiv="content-type" content="text/html; 
+charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
        Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
 adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
 Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
@@ -47,10 +45,9 @@ comments -->
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
 <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
-aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-</body></html>
\ No newline at end of file
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_nested_body.html
+++ b/content/base/test/file_htmlserializer_1_nested_body.html
@@ -1,13 +1,11 @@
-<!DOCTYPE HTML>
-<html><head>
-
-
-   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!DOCTYPE html>
+<html><head><meta http-equiv="content-type" content="text/html; 
+charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
        Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
 adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
 Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
@@ -46,10 +44,10 @@ comments -->
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
 <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
-aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-<body><p>this is an other body element</p></body></body></html>
\ No newline at end of file
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p><body><p>this is
+ an other body element</p></body></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_no_body.html
+++ b/content/base/test/file_htmlserializer_1_no_body.html
@@ -1,8 +1,6 @@
-<!DOCTYPE HTML>
-<html><head>
-
-
-   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!DOCTYPE html>
+<html><head><meta http-equiv="content-type" content="text/html; 
+charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_noflag.html
+++ b/content/base/test/file_htmlserializer_1_noflag.html
@@ -1,13 +1,11 @@
-<!DOCTYPE HTML>
-<html><head>
-
-
-   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!DOCTYPE html>
+<html><head><meta http-equiv="content-type" content="text/html; 
+charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
        Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
 adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
 Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
@@ -46,10 +44,9 @@ comments -->
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
 <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
-aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-</body></html>
\ No newline at end of file
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_noformatpre.html
+++ b/content/base/test/file_htmlserializer_1_noformatpre.html
@@ -1,13 +1,11 @@
-<!DOCTYPE HTML>
-<html><head>
-
-
-   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!DOCTYPE html>
+<html><head><meta http-equiv="content-type" content="text/html; 
+charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
        Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
 adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
 Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
@@ -50,10 +48,9 @@ comments -->
 
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
 <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
-aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-</body></html>
\ No newline at end of file
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_raw.html
+++ b/content/base/test/file_htmlserializer_1_raw.html
@@ -1,13 +1,10 @@
-<!DOCTYPE HTML>
-<html><head>
-
-
-   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!DOCTYPE html>
+<html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body>
 <p>Hello world</p> <p>
 
        Lorem ipsum dolor sit amet, <strong>consectetuer</strong> adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu ad 
      litora</span> torquent <a href="file_htmlserializer_1_result1.html">per conubia</a> 
 nostra, per inceptos hymenaeos. </p>
@@ -40,10 +37,9 @@ comments -->
  nisi at odio<br>
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
-<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-</body></html>
\ No newline at end of file
+<p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_sibling_body.html
+++ b/content/base/test/file_htmlserializer_1_sibling_body.html
@@ -1,13 +1,11 @@
-<!DOCTYPE HTML>
-<html><head>
-
-
-   <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<!DOCTYPE html>
+<html><head><meta http-equiv="content-type" content="text/html; 
+charset=UTF-8">
   <title>Test for html serializer</title>
 
 </head><body><p>this is an other body element</p></body><body>
 <p>Hello world</p> <p>
 
        Lorem ipsum dolor sit amet, <strong>consectetuer</strong> 
 adipiscing elit. Nam eu sapien. Sed viverra lacus. Donec quis ipsum. 
 Nunc cursus aliquet lectus. Nunc vitae eros. Class aptent taciti <span>sociosqu
@@ -46,10 +44,9 @@ comments -->
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
 <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
-aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-</body></html>
\ No newline at end of file
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_1_sibling_body_only_body.html
+++ b/content/base/test/file_htmlserializer_1_sibling_body_only_body.html
@@ -39,10 +39,9 @@ comments -->
  consectetuer molestie. Curabitur consectetuer urna a sem. Nunc non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Sed sollicitudin, nulla at pharetra rutrum, <br>
 lacus risus pulvinar ante.
 </pre>
 ut gravida eros leo ut libero
 <p></p>
 <noscript>
 <p>Curabitur consectetuer urna a sem. Nunc & non urna. Cras in massa. Vestibulum ante ipsum primis in faucibus orci luctus</p></noscript>
 <p>Nam eu sapien. Sed viverra lacus. Donec quis ipsum. Nunc cursus 
-aliquet lectus. Nunc vitae eros. Class aptent taciti</p>
-</body>
\ No newline at end of file
+aliquet lectus. Nunc vitae eros. Class aptent taciti</p></body>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_2.html
+++ b/content/base/test/file_htmlserializer_2.html
@@ -1,29 +1,22 @@
-<!DOCTYPE HTML>
-<html>
-<head>
-  <title>Test for html serializer with entities</title>
-</head>
-<body>
+<!DOCTYPE html><html><head><title>Test for html serializer with entities</title>
+</head><body>
 
 <p>The basic set is just &nbsp; &amp; &lt; &gt; &quot; for interoperability with older products that don't support &alpha; and friends.</p>
 
 <p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; &copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; &sup3; &acute; 
 &micro; &para; &middot; &cedil; &sup1; &ordm; &raquo; &frac14; &frac12; &frac34; &iquest; &Agrave; &Aacute; &Acirc; &Atilde; &Auml; &Aring; &AElig;
 &Ccedil; &Egrave; &Eacute; &Ecirc; &Euml; &Igrave; &Iacute; &Icirc; &Iuml; &ETH; &Ntilde; &Ograve; &Oacute; &Ocirc; &Otilde; &Ouml; &times; &Oslash;
 &Ugrave; &Uacute; &Ucirc; &Uuml; &Yacute; &THORN; &szlig; &agrave; &aacute; &acirc; &atilde; &auml; &aring; &aelig; &ccedil; &egrave; &eacute; &ecirc; 
 &euml; &igrave; &iacute; &icirc; &iuml; &eth; &ntilde; &ograve; &oacute; &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; &uuml; &yacute; 
 &thorn; &yuml; </p>
 <p>symbols, math.. &fnof; &Alpha; &Beta; &Gamma; &Delta; &Epsilon; &Zeta; &Eta; &Theta; &Iota; &Kappa; &Lambda; &Mu; &Nu; &Xi; &Omicron; &Pi; &Rho; &Sigma; &Tau; &Upsilon;
 &Phi; &Chi; &Psi; &Omega; &alpha; &beta; &gamma; &delta; &epsilon; &zeta; &eta; &theta; &iota; &kappa; &lambda; &mu; &nu; &xi; &omicron; &pi; &rho; &sigmaf;
 &sigma; &tau; &upsilon; &phi; &chi; &psi; &omega; &thetasym; &upsih; &piv; &bull; &hellip; &prime; &Prime; &oline; &frasl; &weierp; &image; &real;
 &trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr; &uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla; &isin; &notin;
 &ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and; &or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le; &ge;
-&sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil; &rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts; &diams;
+&sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil; &rceil; &lfloor; &rfloor; &loz; &spades; &clubs; &hearts; &diams;
 </p>
 <p> others
 &OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp; &thinsp; &zwnj; &zwj; &lrm; &rlm;&ndash;&mdash; &lsquo; &rsquo;
 &sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo; &rsaquo; &euro;
-</p>
-
-</body>
-</html>
\ No newline at end of file
+</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_2_basic.html
+++ b/content/base/test/file_htmlserializer_2_basic.html
@@ -1,30 +1,26 @@
-<!DOCTYPE HTML>
+<!DOCTYPE html>
 <html><head>
-<meta http-equiv="content-type" content="text/html; charset=">
-
-
-  <title>Test for html serializer with entities</title>
+<meta http-equiv="content-type" content="text/html; charset="><title>Test
+ for html serializer with entities</title>
 </head><body>
 
 <p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
 with older products that don't support α and friends.</p>
 
 <p>latin1 ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ 
 µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ
 Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø
 Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê 
 ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý 
 þ ÿ </p>
 <p>symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ
 Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς
 σ τ υ φ χ ψ ω ϑ ϒ ϖ • … ′ ″ ‾ ⁄ ℘ ℑ ℜ
 ™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉
 ∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥
-⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ 〈 〉 ◊ ♠ ♣ ♥ ♦
+⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ ◊ ♠ ♣ ♥ ♦
 </p>
 <p> others
 Œ œ Š š Ÿ ˆ ˜       ‌ ‍ ‎ ‏–— ‘ ’
 ‚“ ” „ † ‡ ‰ ‹ › €
-</p>
-
-</body></html>
\ No newline at end of file
+</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_2_enthtml.html
+++ b/content/base/test/file_htmlserializer_2_enthtml.html
@@ -1,14 +1,12 @@
-<!DOCTYPE HTML>
+<!DOCTYPE html>
 <html><head>
-<meta http-equiv="content-type" content="text/html; charset=">
-
-
-  <title>Test for html serializer with entities</title>
+<meta http-equiv="content-type" content="text/html; charset="><title>Test
+ for html serializer with entities</title>
 </head><body>
 
 <p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
 with older products that don't support &alpha; and friends.</p>
 
 <p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; 
 &copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; 
 &sup3; &acute; 
@@ -36,19 +34,16 @@ with older products that don't support &
 &real;
 &trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr; 
 &uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla; 
 &isin; &notin;
 &ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and; 
 &or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le; 
 &ge;
 &sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil; 
-&rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts; 
-&diams;
+&rceil; &lfloor; &rfloor; &loz; &spades; &clubs; &hearts; &diams;
 </p>
 <p> others
 &OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp; 
 &thinsp; &zwnj; &zwj; &lrm; &rlm;&ndash;&mdash; &lsquo; &rsquo;
 &sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo; 
 &rsaquo; &euro;
-</p>
-
-</body></html>
\ No newline at end of file
+</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_2_entw3c.html
+++ b/content/base/test/file_htmlserializer_2_entw3c.html
@@ -1,14 +1,12 @@
-<!DOCTYPE HTML>
+<!DOCTYPE html>
 <html><head>
-<meta http-equiv="content-type" content="text/html; charset=">
-
-
-  <title>Test for html serializer with entities</title>
+<meta http-equiv="content-type" content="text/html; charset="><title>Test
+ for html serializer with entities</title>
 </head><body>
 
 <p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
 with older products that don't support &alpha; and friends.</p>
 
 <p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; 
 &copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; 
 &sup3; &acute; 
@@ -36,19 +34,16 @@ with older products that don't support &
 &real;
 &trade; &alefsym; &larr; &uarr; &rarr; &darr; &harr; &crarr; &lArr; 
 &uArr; &rArr; &dArr; &hArr; &forall; &part; &exist; &empty; &nabla; 
 &isin; &notin;
 &ni; &prod; &sum; &minus; &lowast; &radic; &prop; &infin; &ang; &and; 
 &or; &cap; &cup; &int; &there4; &sim; &cong; &asymp; &ne; &equiv; &le; 
 &ge;
 &sub; &sup; &nsub; &sube; &supe; &oplus; &otimes; &perp; &sdot; &lceil; 
-&rceil; &lfloor; &rfloor; &lang; &rang; &loz; &spades; &clubs; &hearts; 
-&diams;
+&rceil; &lfloor; &rfloor; &loz; &spades; &clubs; &hearts; &diams;
 </p>
 <p> others
 &OElig; &oelig; &Scaron; &scaron; &Yuml; &circ; &tilde; &ensp; &emsp; 
 &thinsp; &zwnj; &zwj; &lrm; &rlm;&ndash;&mdash; &lsquo; &rsquo;
 &sbquo;&ldquo; &rdquo; &bdquo; &dagger; &Dagger; &permil; &lsaquo; 
 &rsaquo; &euro;
-</p>
-
-</body></html>
\ No newline at end of file
+</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_2_latin1.html
+++ b/content/base/test/file_htmlserializer_2_latin1.html
@@ -1,14 +1,12 @@
-<!DOCTYPE HTML>
+<!DOCTYPE html>
 <html><head>
-<meta http-equiv="content-type" content="text/html; charset=">
-
-
-  <title>Test for html serializer with entities</title>
+<meta http-equiv="content-type" content="text/html; charset="><title>Test
+ for html serializer with entities</title>
 </head><body>
 
 <p>The basic set is just &nbsp; &amp; &lt; &gt; " for interoperability 
 with older products that don't support α and friends.</p>
 
 <p>latin1 &iexcl; &cent; &pound; &curren; &yen; &brvbar; &sect; &uml; 
 &copy; &ordf; &laquo; &not; &shy; &reg; &macr; &deg; &plusmn; &sup2; 
 &sup3; &acute; 
@@ -25,16 +23,14 @@ with older products that don't support α and friends.</p>
  &ocirc; &otilde; &ouml; &divide; &oslash; &ugrave; &uacute; &ucirc; 
 &uuml; &yacute; 
 &thorn; &yuml; </p>
 <p>symbols, math.. ƒ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ
 Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς
 σ τ υ φ χ ψ ω ϑ ϒ ϖ • … ′ ″ ‾ ⁄ ℘ ℑ ℜ
 ™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉
 ∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥
-⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ 〈 〉 ◊ ♠ ♣ ♥ ♦
+⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ ◊ ♠ ♣ ♥ ♦
 </p>
 <p> others
 Œ œ Š š Ÿ ˆ ˜       ‌ ‍ ‎ ‏–— ‘ ’
 ‚“ ” „ † ‡ ‰ ‹ › €
-</p>
-
-</body></html>
\ No newline at end of file
+</p></body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_ipv6.html
+++ b/content/base/test/file_htmlserializer_ipv6.html
@@ -1,8 +1,5 @@
-<!DOCTYPE html>
-<html>
-  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<!DOCTYPE html><html><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <title>Testcase for IPv6 addresses</title>
   <body>
     <a href="http://[2001:4860:a003::68]/">Test</a>
-  </body>
-</html>
+  </body></html>
\ No newline at end of file
--- a/content/base/test/file_htmlserializer_ipv6_out.html
+++ b/content/base/test/file_htmlserializer_ipv6_out.html
@@ -1,8 +1,7 @@
-<!DOCTYPE HTML>
-<html><head>
-
-  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<!DOCTYPE html>
+<html><head><meta http-equiv="Content-Type" content="text/html; 
+charset=UTF-8">
   <title>Testcase for IPv6 addresses</title>
   </head><body>
     <a href="http://[2001:4860:a003::68]/">Test</a>
   </body></html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_CSP.html
@@ -0,0 +1,127 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test for Content Security Policy Connections</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+  
+</div>
+
+<iframe style="width:200px;height:200px;" id='cspframe'></iframe>
+<script class="testbody" type="text/javascript">
+
+var path = "/tests/content/base/test/";
+
+// These are test results: -1 means it hasn't run, 
+// true/false is the pass/fail result.
+window.tests = {
+  img_good: -1,
+  img_bad: -1,
+  style_good: -1,
+  style_bad: -1,
+  frame_good: -1,
+  frame_bad: -1,
+  script_good: -1,
+  script_bad: -1,
+  xhr_good: -1,
+  xhr_bad: -1,
+  media_good: -1,
+  media_bad: -1,
+  font_good: -1,
+  font_bad: -1,
+  object_good: -1,
+  object_bad: -1,
+};
+
+
+// This is used to watch the blocked data bounce off CSP and allowed data 
+// get sent out to the wire.
+function examiner() {
+  netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+  var obsvc = Components.classes['@mozilla.org/observer-service;1']
+                        .getService(Components.interfaces.nsIObserverService);
+  obsvc.addObserver(this, "csp-on-violate-policy", false);
+  obsvc.addObserver(this, "http-on-modify-request", false);
+}
+examiner.prototype  = {
+  observe: function(subject, topic, data) {
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+    // subject should be an nsURI, and should be either allowed or blocked.
+    if(!subject.QueryInterface)
+      return;
+      
+    var testpat = new RegExp("testid=([a-z0-9_]+)");
+
+    //_good things better be allowed!
+    //_bad things better be stopped!
+
+    if (topic === "http-on-modify-request") {
+      //these things were allowed by CSP
+      var uri = subject.QueryInterface(Components.interfaces.nsIHttpChannel).URI;
+      if (!testpat.test(uri.asciiSpec)) return;
+      var testid = testpat.exec(uri.asciiSpec)[1];
+      window.testResult(testid,
+                        /_good/.test(testid),
+                        uri.asciiSpec + " allowed by csp");
+
+    }
+
+    if(topic === "csp-on-violate-policy") {
+      //these were blocked... record that they were blocked
+      var uri = subject.QueryInterface(Components.interfaces.nsIURI);
+      if (!testpat.test(uri.asciiSpec)) return;
+      var testid = testpat.exec(uri.asciiSpec)[1];
+      window.testResult(testid,
+                        /_bad/.test(testid),
+                        uri.asciiSpec + " blocked by \"" + data + "\"");
+    }
+  },
+
+  // must eventually call this to remove the listener, 
+  // or mochitests might get borked.
+  remove: function() {
+    netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
+    var obsvc = Components.classes['@mozilla.org/observer-service;1']
+                          .getService(Components.interfaces.nsIObserverService);
+    obsvc.removeObserver(this, "csp-on-violate-policy");
+    obsvc.removeObserver(this, "http-on-modify-request");
+  }
+}
+
+window.examiner = new examiner();
+
+window.testResult = function(testname, result, msg) {
+
+  //test already complete.... forget it... remember the first result.
+  if (window.tests[testname] != -1)
+    return;
+
+  window.tests[testname] = result;
+  is(result, true, testname + ' test: ' + msg);
+
+  // if any test is incomplete, keep waiting
+  for (var v in window.tests)
+    if(tests[v] == -1)
+      return;
+
+  // ... otherwise, finish
+  window.examiner.remove();
+  SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+// save this for last so that our listeners are registered.
+// ... this loads the testbed of good and bad requests.
+document.getElementById('cspframe').src = 'file_CSP.sjs?main=1';
+
+</script>
+</pre>
+</body>
+</html>
--- a/content/base/test/test_bug424359-1.html
+++ b/content/base/test/test_bug424359-1.html
@@ -39,16 +39,21 @@ function loadFileContent(aFile, aCharset
     inputStream.init(chann.open(), aCharset, 1024, cis.DEFAULT_REPLACEMENT_CHARACTER);
     var str = {}, content = '';
     while (inputStream.readString(4096, str) != 0) {
         content += str.value;
     }
     return content;
 }
 
+function isRoughly(actual, expected, message) {
+  return is(actual.replace("<!DOCTYPE HTML", "<!DOCTYPE html"), 
+            expected, 
+            message);
+}
 
 function testHtmlSerializer_1 () {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   const de = Components.interfaces.nsIDocumentEncoder
   var encoder = Components.classes["@mozilla.org/layout/documentEncoder;1?type=text/html"]
                    .createInstance(Components.interfaces.nsIDocumentEncoder);
 
   var doc = $("testframe").contentDocument;
@@ -58,136 +63,136 @@ function testHtmlSerializer_1 () {
   // to have the default line break of the platform in the result, so the test
   // can pass on all platform
 
   //------------ no flags
   encoder.init(doc, "text/html", de.OutputLFLineBreak);
   encoder.setCharset("UTF-8");
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_noflag.html");
-  is(out, expected, "test no flags");
+  isRoughly(out, expected, "test no flags");
 
   //------------- unsupported flags
   // since the following flags are not supported, we should
   // have a result like the one without flag
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputPreformatted);
   out = encoder.encodeToString();
-  is(out, expected, "test OutputPreformatted");
+  isRoughly(out, expected, "test OutputPreformatted");
 
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputFormatFlowed);
   out = encoder.encodeToString();
-  is(out, expected, "test OutputFormatFlowed");
+  isRoughly(out, expected, "test OutputFormatFlowed");
 
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputNoScriptContent);
   out = encoder.encodeToString();
-  is(out, expected, "test OutputNoScriptContent");
+  isRoughly(out, expected, "test OutputNoScriptContent");
 
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputNoFramesContent);
   out = encoder.encodeToString();
-  is(out, expected, "test OutputNoFramesContent");
+  isRoughly(out, expected, "test OutputNoFramesContent");
 
 
   //------------ OutputWrap
   // by default, this flag is set, so we should have the same result as
   // when there are no flags.
   encoder.init(doc, "text/html", de.OutputLFLineBreak |de.OutputWrap);
   out = encoder.encodeToString();
-  is(out, expected, "test OutputWrap");
+  isRoughly(out, expected, "test OutputWrap");
 
   //------------ OutputFormatted
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputFormatted);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_format.html");
-  is(out, expected, "test OutputFormatted");
+  isRoughly(out, expected, "test OutputFormatted");
 
   //------------ OutputRaw
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputRaw);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_raw.html");
-  is(out, expected, "test OutputRaw");
+  isRoughly(out, expected, "test OutputRaw");
 
   //------------ OutputBodyOnly
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputBodyOnly);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_bodyonly.html");
-  is(out, expected, "test OutputBodyOnly");
+  isRoughly(out, expected, "test OutputBodyOnly");
 
 
 
   //------------ OutputAbsoluteLinks
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputAbsoluteLinks);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_links.html");
-  is(out, expected, "test OutputAbsoluteLinks");
+  isRoughly(out, expected, "test OutputAbsoluteLinks");
 
   //------------ OutputLFLineBreak
   encoder.init(doc, "text/html",de.OutputLFLineBreak);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_linebreak.html");
-  is(out, expected, "test OutputLFLineBreak");
+  isRoughly(out, expected, "test OutputLFLineBreak");
 
   //------------ OutputCRLineBreak
   encoder.init(doc, "text/html",de.OutputCRLineBreak);
   out = encoder.encodeToString();
   expected = expected.replace(/\n/mg, "\r");
-  is(out, expected, "test OutputCRLineBreak");
+  isRoughly(out, expected, "test OutputCRLineBreak");
 
   //------------ OutputLFLineBreak + OutputCRLineBreak
   encoder.init(doc, "text/html",de.OutputLFLineBreak | de.OutputCRLineBreak);
   out = encoder.encodeToString();
   expected = expected.replace(/\r/mg, "\r\n");
-  is(out, expected, "test OutputLFLineBreak + OutputCRLineBreak");
+  isRoughly(out, expected, "test OutputLFLineBreak + OutputCRLineBreak");
 
   //------------ OutputNoFormattingInPre
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputNoFormattingInPre);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_noformatpre.html");
-  is(out, expected, "test OutputNoFormattingInPre");
+  isRoughly(out, expected, "test OutputNoFormattingInPre");
 
   // ------------- nested body elements
   var body2 = doc.createElement('body');
   var p = doc.createElement('p');
   p.appendChild(doc.createTextNode("this is an other body element"));
   body2.appendChild(p);
   var body = doc.getElementsByTagName('body')[0];
   body.appendChild(body2);
 
   is(doc.getElementsByTagName('body').length, 2); // to be sure we have two body elements
 
   encoder.init(doc, "text/html", de.OutputLFLineBreak);
   encoder.setCharset("UTF-8");
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_nested_body.html");
-  is(out, expected, "test with two nested body elements");
+  isRoughly(out, expected, "test with two nested body elements");
 
   // ------------- two body elements
   body.parentNode.insertBefore(body2, body);
 
   is(doc.getElementsByTagName('body').length, 2); // to be sure we have two body elements
   encoder.init(doc, "text/html", de.OutputLFLineBreak);
   encoder.setCharset("UTF-8");
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_sibling_body.html");
-  is(out, expected, "test with two body elements");
+  isRoughly(out, expected, "test with two body elements");
 
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputBodyOnly);
   encoder.setCharset("UTF-8");
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_sibling_body_only_body.html");
-  is(out, expected, "test with two body elements, and output body only");
+  isRoughly(out, expected, "test with two body elements, and output body only");
 
   // --------------- no body element
   doc.documentElement.removeChild(body);
   doc.documentElement.removeChild(body2);
 
   encoder.init(doc, "text/html", de.OutputLFLineBreak);
   encoder.setCharset("UTF-8");
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_1_no_body.html");
-  is(out, expected, "test with no body element");
+  isRoughly(out, expected, "test with no body element");
 
   SimpleTest.finish();
 }
 
 
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(testHtmlSerializer_1);
--- a/content/base/test/test_bug424359-2.html
+++ b/content/base/test/test_bug424359-2.html
@@ -39,16 +39,21 @@ function loadFileContent(aFile, aCharset
     inputStream.init(chann.open(), aCharset, 1024, cis.DEFAULT_REPLACEMENT_CHARACTER);
     var str = {}, content = '';
     while (inputStream.readString(4096, str) != 0) {
         content += str.value;
     }
     return content;
 }
 
+function isRoughly(actual, expected, message) {
+  return is(actual.replace("<!DOCTYPE HTML", "<!DOCTYPE html"), 
+            expected, 
+            message);
+}
 
 function testHtmlSerializer_1 () {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   const de = Components.interfaces.nsIDocumentEncoder
   var encoder = Components.classes["@mozilla.org/layout/documentEncoder;1?type=text/html"]
                    .createInstance(Components.interfaces.nsIDocumentEncoder);
 
   var doc = $("testframe").contentDocument;
@@ -57,35 +62,35 @@ function testHtmlSerializer_1 () {
   // in the following tests, we must use the OutputLFLineBreak flag, to avoid
   // to have the default line break of the platform in the result, so the test
   // can pass on all platform
 
   //------------ OutputEncodeW3CEntities
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputEncodeW3CEntities);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_2_entw3c.html");
-  is(out, expected, "test OutputEncodeW3CEntities");
+  isRoughly(out, expected, "test OutputEncodeW3CEntities");
 
   //------------ OutputEncodeBasicEntities
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputEncodeBasicEntities);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_2_basic.html");
-  is(out, expected, "test OutputEncodeBasicEntities");
+  isRoughly(out, expected, "test OutputEncodeBasicEntities");
 
   //------------ OutputEncodeLatin1Entities
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputEncodeLatin1Entities);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_2_latin1.html");
-  is(out, expected, "test OutputEncodeLatin1Entities");
+  isRoughly(out, expected, "test OutputEncodeLatin1Entities");
 
   //------------ OutputEncodeHTMLEntities
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputEncodeHTMLEntities);
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_2_enthtml.html");
-  is(out, expected, "test OutputEncodeHTMLEntities");
+  isRoughly(out, expected, "test OutputEncodeHTMLEntities");
 
 
   // tests on the serialization of selections
 
   var node = document.getElementById('draggable');
 
   var select = window.getSelection();
   select.selectAllChildren(node);  
--- a/content/base/test/test_bug498433.html
+++ b/content/base/test/test_bug498433.html
@@ -38,16 +38,21 @@ function loadFileContent(aFile, aCharset
     inputStream.init(chann.open(), aCharset, 1024, cis.DEFAULT_REPLACEMENT_CHARACTER);
     var str = {}, content = '';
     while (inputStream.readString(4096, str) != 0) {
         content += str.value;
     }
     return content;
 }
 
+function isRoughly(actual, expected, message) {
+  return is(actual.replace("<!DOCTYPE HTML", "<!DOCTYPE html"), 
+            expected, 
+            message);
+}
 
 function testHtmlSerializer_1 () {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   const de = Components.interfaces.nsIDocumentEncoder
   var encoder = Components.classes["@mozilla.org/layout/documentEncoder;1?type=text/html"]
                    .createInstance(Components.interfaces.nsIDocumentEncoder);
 
   var doc = $("testframe").contentDocument;
@@ -57,29 +62,29 @@ function testHtmlSerializer_1 () {
   // to have the default line break of the platform in the result, so the test
   // can pass on all platform
 
   //------------ no flags
   encoder.init(doc, "text/html", de.OutputLFLineBreak);
   encoder.setCharset("UTF-8");
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_ipv6_out.html");
-  is(out, expected, "test no flags");
+  isRoughly(out, expected, "test no flags");
   //------------ OutputAbsoluteLinks
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputAbsoluteLinks);
   encoder.setCharset("UTF-8");
   out = encoder.encodeToString();
   expected = loadFileContent("file_htmlserializer_ipv6_out.html");
-  is(out, expected, "test OutputAbsoluteLinks");
+  isRoughly(out, expected, "test OutputAbsoluteLinks");
   //------------ serializing a selection
   encoder.init(doc, "text/html", de.OutputLFLineBreak | de.OutputAbsoluteLinks);
   encoder.setNode(doc.links[0]);
   out = encoder.encodeToString();
   expected = "<a href=\"http://[2001:4860:a003::68]/\">Test</a>";
-  is(out, expected, "test selection");
+  isRoughly(out, expected, "test selection");
 
 
   SimpleTest.finish();
 }
 
 
 SimpleTest.waitForExplicitFinish();
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/src/CustomQS_WebGL.h
@@ -0,0 +1,1031 @@
+/* -*- Mode: c++; c-basic-offset: 4; tab-width: 40; indent-tabs-mode: nil; -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Intended to be #included in dom_quickstubs.cpp via qsconf!
+ */
+
+#include "jstypedarray.h"
+
+static inline bool
+helper_isInt32Array(JSObject *obj) {
+    return obj->getClass() == &js::TypedArray::fastClasses[js::TypedArray::TYPE_INT32];
+}
+
+static inline bool
+helper_isFloat32Array(JSObject *obj) {
+    return obj->getClass() == &js::TypedArray::fastClasses[js::TypedArray::TYPE_FLOAT32];
+}
+
+/*
+ * BufferData takes:
+ *    BufferData (int, int, int)
+ *    BufferData_buf (int, js::ArrayBuffer *, int)
+ *    BufferData_array (int, js::TypedArray *, int)
+ */
+static JSBool
+nsICanvasRenderingContextWebGL_BufferData(JSContext *cx, uintN argc, jsval *vp)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    JSAutoTempValueRooter tvr(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
+        return JS_FALSE;
+
+    if (argc < 3)
+        return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+
+    jsval *argv = JS_ARGV(cx, vp);
+
+    int32 target;
+    js::TypedArray *wa = 0;
+    js::ArrayBuffer *wb = 0;
+    int32 size;
+    int32 usage;
+
+    if (!JS_ValueToECMAInt32(cx, argv[0], &target))
+        return JS_FALSE;
+    if (!JS_ValueToECMAInt32(cx, argv[2], &usage))
+        return JS_FALSE;
+
+    if (JSVAL_IS_OBJECT(argv[1])) {
+        JSObject *arg2 = JSVAL_TO_OBJECT(argv[1]);
+        if (js_IsArrayBuffer(arg2)) {
+            wb = js::ArrayBuffer::fromJSObject(arg2);
+        } else if (js_IsTypedArray(arg2)) {
+            wa = js::TypedArray::fromJSObject(arg2);
+        }
+    }
+
+    if (!wa && !wb &&
+        !JS_ValueToECMAInt32(cx, argv[1], &size))
+    {
+        return JS_FALSE;
+    }
+      
+    nsresult rv;
+
+    if (wa)
+        rv = self->BufferData_array(target, wa, usage);
+    else if (wb)
+        rv = self->BufferData_buf(target, wb, usage);
+    else
+        rv = self->BufferData_size(target, size, usage);
+
+    if (NS_FAILED(rv))
+        return xpc_qsThrowMethodFailed(cx, rv, vp);
+
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+/*
+ * BufferSubData takes:
+ *    BufferSubData (int, int, js::ArrayBuffer *)
+ *    BufferSubData_array (int, int, js::TypedArray *)
+ */
+static JSBool
+nsICanvasRenderingContextWebGL_BufferSubData(JSContext *cx, uintN argc, jsval *vp)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    JSAutoTempValueRooter tvr(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
+        return JS_FALSE;
+
+    if (argc < 3)
+        return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+
+    jsval *argv = JS_ARGV(cx, vp);
+
+    int32 target;
+    int32 offset;
+    js::TypedArray *wa = 0;
+    js::ArrayBuffer *wb = 0;
+
+    if (!JS_ValueToECMAInt32(cx, argv[0], &target))
+        return JS_FALSE;
+    if (!JS_ValueToECMAInt32(cx, argv[1], &offset))
+        return JS_FALSE;
+
+    if (!JSVAL_IS_OBJECT(argv[2])) {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2);
+        return JS_FALSE;
+    }
+
+    JSObject *arg3 = JSVAL_TO_OBJECT(argv[2]);
+    if (js_IsArrayBuffer(arg3)) {
+        wb = js::ArrayBuffer::fromJSObject(arg3);
+    } else if (js_IsTypedArray(arg3)) {
+        wa = js::TypedArray::fromJSObject(arg3);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2);
+        return JS_FALSE;
+    }
+
+    nsresult rv;
+
+    if (wa) {
+        rv = self->BufferSubData_array(target, offset, wa);
+    } else if (wb) {
+        rv = self->BufferSubData_buf(target, offset, wb);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2);
+        return JS_FALSE;
+    }
+
+    if (NS_FAILED(rv))
+        return xpc_qsThrowMethodFailed(cx, rv, vp);
+
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+/*
+ * TexImage2D takes:
+ *    TexImage2D(int, int, int, int, int, int, int, int, WebGLArray)
+ *    TexImage2D(int, int, int, int, int, int, int, int, WebGLArrayBuffer)
+ *    TexImage2D(int, int, nsIDOMElement, [bool[, bool]])
+ */
+static JSBool
+nsICanvasRenderingContextWebGL_TexImage2D(JSContext *cx, uintN argc, jsval *vp)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    nsresult rv;
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    JSAutoTempValueRooter tvr(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
+        return JS_FALSE;
+
+    if (argc < 3 || (argc > 3 && argc < 9))
+        return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+
+    jsval *argv = JS_ARGV(cx, vp);
+
+    int32 intargs[8];
+
+    // convert the first two args, they must be ints
+    for (jsuint i = 0; i < 2; ++i) {
+        if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
+            return JS_FALSE;
+    }
+
+    if (JSVAL_IS_OBJECT(argv[2])) {
+        // try to make this a nsIDOMElement
+        nsIDOMElement *elt;
+        xpc_qsSelfRef eltRef;
+        rv = xpc_qsUnwrapArg<nsIDOMElement>(cx, argv[2], &elt, &eltRef.ptr, &argv[2]);
+        if (NS_SUCCEEDED(rv)) {
+            intargs[3] = 0;
+            intargs[4] = 0;
+
+            // convert args 4 and 5 if present, default to 0
+            for (jsuint i = 3; i < 5 && i < argc; ++i) {
+                if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
+                    return JS_FALSE;
+            }
+
+            rv = self->TexImage2D_dom(intargs[0], intargs[1], elt, (GLboolean) intargs[3], (GLboolean) intargs[4]);
+            if (NS_FAILED(rv))
+                return xpc_qsThrowMethodFailed(cx, rv, vp);
+            return JS_TRUE;
+        }
+    }
+
+    // didn't succeed? convert the rest of the int args
+    for (jsuint i = 2; i < 8; ++i) {
+        if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
+            return JS_FALSE;
+    }
+
+    if (!JSVAL_IS_OBJECT(argv[8])) {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
+        return JS_FALSE;
+    }
+
+    // then try to grab either a js::ArrayBuffer or js::TypedArray
+    js::TypedArray *wa = 0;
+    js::ArrayBuffer *wb = 0;
+
+    JSObject *arg9 = JSVAL_TO_OBJECT(argv[8]);
+    if (js_IsArrayBuffer(arg9)) {
+        wb = js::ArrayBuffer::fromJSObject(arg9);
+    } else if (js_IsTypedArray(arg9)) {
+        wa = js::TypedArray::fromJSObject(arg9);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
+        return JS_FALSE;
+    }
+
+    if (wa) {
+        rv = self->TexImage2D_array(intargs[0], intargs[1], intargs[2], intargs[3],
+                                    intargs[4], intargs[5], intargs[6], intargs[7],
+                                    wa);
+    } else if (wb) {
+        rv = self->TexImage2D_buf(intargs[0], intargs[1], intargs[2], intargs[3],
+                                  intargs[4], intargs[5], intargs[6], intargs[7],
+                                  wb);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
+        return JS_FALSE;
+    }
+
+    if (NS_FAILED(rv))
+        return xpc_qsThrowMethodFailed(cx, rv, vp);
+
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+/*
+ * TexSubImage2D takes:
+ *    TexSubImage2D(int, int, int, int, int, int, int, int, WebGLArray)
+ *    TexSubImage2D(int, int, int, int, int, int, int, int, WebGLArrayBuffer)
+ *    TexSubImage2D(int, int, int, int, int, int, nsIDOMElement, [bool[, bool]])
+ */
+static JSBool
+nsICanvasRenderingContextWebGL_TexSubImage2D(JSContext *cx, uintN argc, jsval *vp)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    nsresult rv;
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    JSAutoTempValueRooter tvr(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
+        return JS_FALSE;
+
+    if (argc < 7 || (argc > 7 && argc < 9))
+        return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+
+    jsval *argv = JS_ARGV(cx, vp);
+
+    int32 intargs[8];
+
+    // convert the first six args, they must be ints
+    for (jsuint i = 0; i < 6; ++i) {
+        if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
+            return JS_FALSE;
+    }
+
+    if (JSVAL_IS_OBJECT(argv[6])) {
+        // try to make this a nsIDOMElement
+        nsIDOMElement *elt;
+        xpc_qsSelfRef eltRef;
+
+        // these are two optinal args, default to 0
+        intargs[7] = 0;
+        intargs[8] = 0;
+
+        // convert args 7 and 8 if present
+        for (jsuint i = 7; i < 9 && i < argc; ++i) {
+            if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
+                return JS_FALSE;
+        }
+
+        rv = xpc_qsUnwrapArg<nsIDOMElement>(cx, argv[2], &elt, &eltRef.ptr, &argv[2]);
+        if (NS_SUCCEEDED(rv)) {
+            rv = self->TexSubImage2D_dom(intargs[0], intargs[1], intargs[2],
+                                         intargs[2], intargs[4], intargs[5],
+                                         elt, (GLboolean) intargs[7], (GLboolean) intargs[8]);
+            if (NS_FAILED(rv))
+                return xpc_qsThrowMethodFailed(cx, rv, vp);
+            return JS_TRUE;
+        }
+    }
+
+    // didn't succeed? convert the rest of the int args
+    for (jsuint i = 6; i < 8; ++i) {
+        if (!JS_ValueToECMAInt32(cx, argv[i], &intargs[i]))
+            return JS_FALSE;
+    }
+
+    if (!JSVAL_IS_OBJECT(argv[8])) {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
+        return JS_FALSE;
+    }
+
+    // then try to grab either a js::ArrayBuffer or js::TypedArray
+    js::TypedArray *wa = 0;
+    js::ArrayBuffer *wb = 0;
+
+    JSObject *arg9 = JSVAL_TO_OBJECT(argv[8]);
+    if (js_IsArrayBuffer(arg9)) {
+        wb = js::ArrayBuffer::fromJSObject(arg9);
+    } else if (js_IsTypedArray(arg9)) {
+        wa = js::TypedArray::fromJSObject(arg9);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
+        return JS_FALSE;
+    }
+
+    if (wa) {
+        rv = self->TexSubImage2D_array(intargs[0], intargs[1], intargs[2], intargs[3],
+                                       intargs[4], intargs[5], intargs[6], intargs[7],
+                                       wa);
+    } else if (wb) {
+        rv = self->TexSubImage2D_buf(intargs[0], intargs[1], intargs[2], intargs[3],
+                                     intargs[4], intargs[5], intargs[6], intargs[7],
+                                     wb);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
+        return JS_FALSE;
+    }
+
+    if (NS_FAILED(rv))
+        return xpc_qsThrowMethodFailed(cx, rv, vp);
+
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+/* NOTE: There is a TN version of this below, update it as well */
+static inline JSBool
+helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(JSContext *cx, uintN argc, jsval *vp, int nElements)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    nsresult rv;
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    JSAutoTempValueRooter tvr(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
+        return JS_FALSE;
+
+    if (argc < 2)
+        return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+
+    jsval *argv = JS_ARGV(cx, vp);
+
+    uint32 location;
+    if (!JS_ValueToECMAUint32(cx, argv[0], &location))
+        return JS_FALSE;
+
+    if (!JSVAL_IS_OBJECT(argv[1])) {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1);
+        return JS_FALSE;
+    }
+
+    JSObject *arg1 = JSVAL_TO_OBJECT(argv[1]);
+
+    JSAutoTempValueRooter obj_tvr(cx);
+
+    js::TypedArray *wa = 0;
+
+    if (helper_isInt32Array(arg1)) {
+        wa = js::TypedArray::fromJSObject(arg1);
+    }  else if (JS_IsArrayObject(cx, arg1)) {
+        JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_INT32, arg1);
+        if (!nobj) {
+            // XXX this will likely return a strange error message if it goes wrong
+            return JS_FALSE;
+        }
+
+        *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj);
+        wa = js::TypedArray::fromJSObject(nobj);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1);
+        return JS_FALSE;
+    }
+
+    if (nElements == 1) {
+        rv = self->Uniform1iv_array(location, wa);
+    } else if (nElements == 2) {
+        rv = self->Uniform2iv_array(location, wa);
+    } else if (nElements == 3) {
+        rv = self->Uniform3iv_array(location, wa);
+    } else if (nElements == 4) {
+        rv = self->Uniform4iv_array(location, wa);
+    }
+
+    if (NS_FAILED(rv))
+        return xpc_qsThrowMethodFailed(cx, rv, vp);
+
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+/* NOTE: There is a TN version of this below, update it as well */
+static inline JSBool
+helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    nsresult rv;
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    JSAutoTempValueRooter tvr(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
+        return JS_FALSE;
+
+    if (argc < 2)
+        return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+
+    jsval *argv = JS_ARGV(cx, vp);
+
+    uint32 location;
+    if (!JS_ValueToECMAUint32(cx, argv[0], &location))
+        return JS_FALSE;
+
+    if (!JSVAL_IS_OBJECT(argv[1])) {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1);
+        return JS_FALSE;
+    }
+
+    JSObject *arg1 = JSVAL_TO_OBJECT(argv[1]);
+
+    JSAutoTempValueRooter obj_tvr(cx);
+
+    js::TypedArray *wa = 0;
+
+    if (helper_isFloat32Array(arg1)) {
+        wa = js::TypedArray::fromJSObject(arg1);
+    }  else if (JS_IsArrayObject(cx, arg1)) {
+        JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg1);
+        if (!nobj) {
+            // XXX this will likely return a strange error message if it goes wrong
+            return JS_FALSE;
+        }
+
+        *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj);
+        wa = js::TypedArray::fromJSObject(nobj);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1);
+        return JS_FALSE;
+    }
+
+    if (nElements == 1) {
+        rv = self->Uniform1fv_array(location, wa);
+    } else if (nElements == 2) {
+        rv = self->Uniform2fv_array(location, wa);
+    } else if (nElements == 3) {
+        rv = self->Uniform3fv_array(location, wa);
+    } else if (nElements == 4) {
+        rv = self->Uniform4fv_array(location, wa);
+    }
+
+    if (NS_FAILED(rv))
+        return xpc_qsThrowMethodFailed(cx, rv, vp);
+
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+/* NOTE: There is a TN version of this below, update it as well */
+static inline JSBool
+helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    nsresult rv;
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    JSAutoTempValueRooter tvr(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
+        return JS_FALSE;
+
+    if (argc < 3)
+        return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+
+    jsval *argv = JS_ARGV(cx, vp);
+
+    uint32 location;
+    int32 transpose;
+    if (!JS_ValueToECMAUint32(cx, argv[0], &location))
+        return JS_FALSE;
+
+    if (!JS_ValueToECMAInt32(cx, argv[1], &transpose))
+        return JS_FALSE;
+
+    if (!JSVAL_IS_OBJECT(argv[2])) {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2);
+        return JS_FALSE;
+    }
+
+    JSObject *arg2 = JSVAL_TO_OBJECT(argv[2]);
+
+    JSAutoTempValueRooter obj_tvr(cx);
+
+    js::TypedArray *wa = 0;
+
+    if (helper_isFloat32Array(arg2)) {
+        wa = js::TypedArray::fromJSObject(arg2);
+    }  else if (JS_IsArrayObject(cx, arg2)) {
+        JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg2);
+        if (!nobj) {
+            // XXX this will likely return a strange error message if it goes wrong
+            return JS_FALSE;
+        }
+
+        *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj);
+        wa = js::TypedArray::fromJSObject(nobj);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 2);
+        return JS_FALSE;
+    }
+
+    if (nElements == 2) {
+        rv = self->UniformMatrix2fv_array(location, transpose ? 1 : 0, wa);
+    } else if (nElements == 3) {
+        rv = self->UniformMatrix3fv_array(location, transpose ? 1 : 0, wa);
+    } else if (nElements == 4) {
+        rv = self->UniformMatrix4fv_array(location, transpose ? 1 : 0, wa);
+    }
+
+    if (NS_FAILED(rv))
+        return xpc_qsThrowMethodFailed(cx, rv, vp);
+
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+static inline JSBool
+helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(JSContext *cx, uintN argc, jsval *vp, int nElements)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+    JSObject *obj = JS_THIS_OBJECT(cx, vp);
+    if (!obj)
+        return JS_FALSE;
+
+    nsresult rv;
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    JSAutoTempValueRooter tvr(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, tvr.addr(), nsnull))
+        return JS_FALSE;
+
+    if (argc < 2)
+        return xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
+
+    jsval *argv = JS_ARGV(cx, vp);
+
+    uint32 location;
+    if (!JS_ValueToECMAUint32(cx, argv[0], &location))
+        return JS_FALSE;
+
+    if (!JSVAL_IS_OBJECT(argv[1])) {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1);
+        return JS_FALSE;
+    }
+
+    JSObject *arg1 = JSVAL_TO_OBJECT(argv[1]);
+
+    JSAutoTempValueRooter obj_tvr(cx);
+
+    js::TypedArray *wa = 0;
+
+    if (helper_isFloat32Array(arg1)) {
+        wa = js::TypedArray::fromJSObject(arg1);
+    }  else if (JS_IsArrayObject(cx, arg1)) {
+        JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg1);
+        if (!nobj) {
+            // XXX this will likely return a strange error message if it goes wrong
+            return JS_FALSE;
+        }
+
+        *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj);
+        wa = js::TypedArray::fromJSObject(nobj);
+    } else {
+        xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 1);
+        return JS_FALSE;
+    }
+
+    if (nElements == 1) {
+        rv = self->VertexAttrib1fv_array(location, wa);
+    } else if (nElements == 2) {
+        rv = self->VertexAttrib2fv_array(location, wa);
+    } else if (nElements == 3) {
+        rv = self->VertexAttrib3fv_array(location, wa);
+    } else if (nElements == 4) {
+        rv = self->VertexAttrib4fv_array(location, wa);
+    }
+
+    if (NS_FAILED(rv))
+        return xpc_qsThrowMethodFailed(cx, rv, vp);
+
+    *vp = JSVAL_VOID;
+    return JS_TRUE;
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_Uniform1iv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 1);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_Uniform2iv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 2);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_Uniform3iv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 3);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_Uniform4iv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv(cx, argc, vp, 4);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_Uniform1fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 1);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_Uniform2fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 2);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_Uniform3fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 3);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_Uniform4fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv(cx, argc, vp, 4);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_UniformMatrix2fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(cx, argc, vp, 2);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_UniformMatrix3fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(cx, argc, vp, 3);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_UniformMatrix4fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv(cx, argc, vp, 4);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_VertexAttrib1fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 1);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_VertexAttrib2fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 2);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_VertexAttrib3fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 3);
+}
+
+static JSBool
+nsICanvasRenderingContextWebGL_VertexAttrib4fv(JSContext *cx, uintN argc, jsval *vp)
+{
+    return helper_nsICanvasRenderingContextWebGL_VertexAttrib_x_fv(cx, argc, vp, 4);
+}
+
+#ifdef JS_TRACER
+
+static inline jsval FASTCALL
+helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg, int nElements)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    xpc_qsArgValArray<3> vp(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) {
+        js_SetTraceableNativeFailed(cx);
+        return JSVAL_VOID;
+    }
+
+    JSAutoTempValueRooter obj_tvr(cx);
+
+    js::TypedArray *wa = 0;
+
+    if (helper_isInt32Array(arg)) {
+        wa = js::TypedArray::fromJSObject(arg);
+    }  else if (JS_IsArrayObject(cx, arg)) {
+        JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_INT32, arg);
+        if (!nobj) {
+            // XXX this will likely return a strange error message if it goes wrong
+            js_SetTraceableNativeFailed(cx);
+            return JSVAL_VOID;
+        }
+
+        *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj);
+        wa = js::TypedArray::fromJSObject(nobj);
+    } else {
+        xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNiv");
+        js_SetTraceableNativeFailed(cx);
+        return JSVAL_VOID;
+    }
+
+    nsresult rv;
+
+    if (nElements == 1) {
+        rv = self->Uniform1iv_array(location, wa);
+    } else if (nElements == 2) {
+        rv = self->Uniform2iv_array(location, wa);
+    } else if (nElements == 3) {
+        rv = self->Uniform3iv_array(location, wa);
+    } else if (nElements == 4) {
+        rv = self->Uniform4iv_array(location, wa);
+    }
+
+    if (NS_FAILED(rv)) {
+        xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNiv");
+        js_SetTraceableNativeFailed(cx);
+    }
+
+    return JSVAL_VOID;
+}
+
+static inline jsval FASTCALL
+helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg, int nElements)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    xpc_qsArgValArray<3> vp(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) {
+        js_SetTraceableNativeFailed(cx);
+        return JSVAL_VOID;
+    }
+
+    JSAutoTempValueRooter obj_tvr(cx);
+
+    js::TypedArray *wa = 0;
+
+    if (helper_isFloat32Array(arg)) {
+        wa = js::TypedArray::fromJSObject(arg);
+    }  else if (JS_IsArrayObject(cx, arg)) {
+        JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg);
+        if (!nobj) {
+            // XXX this will likely return a strange error message if it goes wrong
+            js_SetTraceableNativeFailed(cx);
+            return JSVAL_VOID;
+        }
+
+        *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj);
+        wa = js::TypedArray::fromJSObject(nobj);
+    } else {
+        xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformNfv");
+        js_SetTraceableNativeFailed(cx);
+        return JSVAL_VOID;
+    }
+
+    nsresult rv;
+
+    if (nElements == 1) {
+        rv = self->Uniform1fv_array(location, wa);
+    } else if (nElements == 2) {
+        rv = self->Uniform2fv_array(location, wa);
+    } else if (nElements == 3) {
+        rv = self->Uniform3fv_array(location, wa);
+    } else if (nElements == 4) {
+        rv = self->Uniform4fv_array(location, wa);
+    }
+
+    if (NS_FAILED(rv)) {
+        xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformNfv");
+        js_SetTraceableNativeFailed(cx);
+    }
+
+    return JSVAL_VOID;
+}
+
+static inline jsval FASTCALL
+helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSBool transpose, JSObject *arg, int nElements)
+{
+    XPC_QS_ASSERT_CONTEXT_OK(cx);
+
+    nsICanvasRenderingContextWebGL *self;
+    xpc_qsSelfRef selfref;
+    xpc_qsArgValArray<4> vp(cx);
+    if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, &vp.array[0], nsnull)) {
+        js_SetTraceableNativeFailed(cx);
+        return JSVAL_VOID;
+    }
+
+    JSAutoTempValueRooter obj_tvr(cx);
+
+    js::TypedArray *wa = 0;
+
+    if (helper_isFloat32Array(arg)) {
+        wa = js::TypedArray::fromJSObject(arg);
+    }  else if (JS_IsArrayObject(cx, arg)) {
+        JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_FLOAT32, arg);
+        if (!nobj) {
+            // XXX this will likely return a strange error message if it goes wrong
+            js_SetTraceableNativeFailed(cx);
+            return JSVAL_VOID;
+        }
+
+        *obj_tvr.addr() = OBJECT_TO_JSVAL(nobj);
+        wa = js::TypedArray::fromJSObject(nobj);
+    } else {
+        xpc_qsThrowMethodFailedWithDetails(cx, NS_ERROR_FAILURE, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv");
+        js_SetTraceableNativeFailed(cx);
+        return JSVAL_VOID;
+    }
+
+    nsresult rv;
+    if (nElements == 2) {
+        rv = self->UniformMatrix2fv_array(location, transpose, wa);
+    } else if (nElements == 3) {
+        rv = self->UniformMatrix3fv_array(location, transpose, wa);
+    } else if (nElements == 4) {
+        rv = self->UniformMatrix4fv_array(location, transpose, wa);
+    }
+
+    if (NS_FAILED(rv)) {
+        xpc_qsThrowMethodFailedWithDetails(cx, rv, "nsICanvasRenderingContextWebGL", "uniformMatrixNfv");
+        js_SetTraceableNativeFailed(cx);
+    }
+
+    return JSVAL_VOID;
+}
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_Uniform1iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 1);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1iv,
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_Uniform2iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 2);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2iv,
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_Uniform3iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 3);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3iv,
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_Uniform4iv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_iv_tn(cx, obj, location, arg, 4);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4iv,
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4iv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_Uniform1fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 1);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform1fv,
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform1fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_Uniform2fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 2);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform2fv,
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform2fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_Uniform3fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 3);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform3fv,
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform3fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_Uniform4fv_tn(JSContext *cx, JSObject *obj, uint32 location, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_Uniform_x_fv_tn(cx, obj, location, arg, 4);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_Uniform4fv,
+    (4, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_Uniform4fv_tn, CONTEXT, THIS, UINT32, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 2);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix2fv,
+    (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix2fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 3);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix3fv,
+    (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix3fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, 0)))
+
+static jsval FASTCALL
+nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn(JSContext *cx, JSObject *obj, uint32 loc, JSBool transpose, JSObject *arg)
+{
+    return helper_nsICanvasRenderingContextWebGL_UniformMatrix_x_fv_tn(cx, obj, loc, transpose, arg, 4);
+}
+
+JS_DEFINE_TRCINFO_1(nsICanvasRenderingContextWebGL_UniformMatrix4fv,
+    (5, (static, JSVAL_FAIL, nsICanvasRenderingContextWebGL_UniformMatrix4fv_tn, CONTEXT, THIS, UINT32, BOOL, OBJECT, 0, 0)))
+
+#endif /* JS_TRACER */
--- a/content/canvas/src/Makefile.in
+++ b/content/canvas/src/Makefile.in
@@ -41,17 +41,19 @@ srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= content
 LIBRARY_NAME	= gkconcvs_s
 LIBXUL_LIBRARY  = 1
 
-
+EXPORTS = \
+	CustomQS_WebGL.h \
+	$(NULL)
 
 CPPSRCS	= \
 	CanvasUtils.cpp \
 	nsCanvasRenderingContext2D.cpp \
 	$(NULL)
 
 ifdef MOZ_IPC
 CPPSRCS += \
@@ -84,17 +86,16 @@ WEBGL_PLATFORM = WGL
 endif
 endif
 
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 WEBGL_PLATFORM = CGL
 endif
 
 CPPSRCS += \
-	WebGLArrays.cpp \
 	WebGLContext.cpp \
 	WebGLContextGL.cpp \
 	WebGLContextUtils.cpp \
 	WebGLContextValidate.cpp \
 	NativeJSContext.cpp \
 	glwrap.cpp \
 	nsGLPbuffer.cpp \
 	nsGLPbufferOSMesa.cpp \
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -10,18 +10,16 @@
 #include "nsDOMError.h"
 
 #include "gfxContext.h"
 #include "gfxPattern.h"
 
 #include "CanvasUtils.h"
 #include "NativeJSContext.h"
 
-#include "WebGLArray.h"
-
 using namespace mozilla;
 
 nsresult NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult);
 
 nsresult
 NS_NewCanvasRenderingContextWebGL(nsICanvasRenderingContextWebGL** aResult)
 {
     nsICanvasRenderingContextWebGL* ctx = new WebGLContext();
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -53,23 +53,20 @@
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsWeakReference.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIJSNativeInitializer.h"
 
 #include "SimpleBuffer.h"
 #include "nsGLPbuffer.h"
 
-#include "WebGLArrays.h"
-
 class nsIDocShell;
 
 namespace mozilla {
 
-class WebGLArray;
 class WebGLTexture;
 class WebGLBuffer;
 class WebGLProgram;
 class WebGLShader;
 class WebGLFramebuffer;
 class WebGLRenderbuffer;
 
 class WebGLZeroingObject;
@@ -260,19 +257,30 @@ protected:
     PRBool SafeToCreateCanvas3DContext(nsICanvasElement *canvasElement);
     PRBool ValidateGL();
     PRBool ValidateBuffers(PRUint32 count);
 
     void Invalidate();
 
     void MakeContextCurrent() { mGLPbuffer->MakeContextCurrent(); }
 
-    nsresult TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas,
-                                 gfxImageSurface **imageOut,
-                                 PRBool flipY, PRBool premultiplyAlpha);
+    // helpers
+    nsresult TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
+                             GLsizei width, GLsizei height, GLint border,
+                             GLenum format, GLenum type,
+                             void *data, PRUint32 byteLength);
+    nsresult TexSubImage2D_base(GLenum target, GLint level,
+                                GLint xoffset, GLint yoffset,
+                                GLsizei width, GLsizei height,
+                                GLenum format, GLenum type,
+                                void *pixels, PRUint32 byteLength);
+
+    nsresult DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
+                                      gfxImageSurface **imageOut,
+                                      PRBool flipY, PRBool premultiplyAlpha);
 
     GLuint mActiveTexture;
 
     // the buffers bound to the current program's attribs
     nsTArray<WebGLVertexAttribData> mAttribBuffers;
 
     // the textures bound to any sampler uniforms
     nsTArray<WebGLObjectRefPtr<WebGLTexture> > mUniformTextures;
@@ -339,52 +347,42 @@ protected:
 };
 
 class WebGLBuffer :
     public nsIWebGLBuffer,
     public WebGLZeroingObject
 {
 public:
     WebGLBuffer(GLuint name)
-        : mName(name), mDeleted(PR_FALSE), mGLType(0)
+        : mName(name), mDeleted(PR_FALSE), mByteLength(0)
     { }
 
     void Delete() {
         if (mDeleted)
             return;
         ZeroOwners();
+
         mDeleted = PR_TRUE;
+        mByteLength = 0;
     }
+
     PRBool Deleted() { return mDeleted; }
     GLuint GLName() { return mName; }
-
-    void Set(nsIWebGLArray *na) {
-        mGLType = na->NativeType();
-        mElementSize = na->NativeElementSize();
-        mCount = na->NativeCount();
-    }
+    PRUint32 ByteLength() { return mByteLength; }
 
-    void SetCount(GLuint count) {
-        mCount = count;
+    void SetByteLength(GLuint len) {
+        mByteLength = len;
     }
 
-    GLenum GLType() { return mGLType; }
-    PRUint32 ByteCount() { return mElementSize * mCount; }
-    PRUint32 Count() { return mCount; }
-    PRUint32 ElementSize() { return mElementSize; }
-
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLBUFFER
 protected:
     GLuint mName;
     PRBool mDeleted;
-
-    GLenum mGLType;
-    PRUint32 mElementSize;
-    PRUint32 mCount;
+    PRUint32 mByteLength;
 };
 
 class WebGLTexture :
     public nsIWebGLTexture,
     public WebGLZeroingObject
 {
 public:
     WebGLTexture(GLuint name) :
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -49,16 +49,18 @@
 #include "nsContentUtils.h"
 #include "nsDOMError.h"
 #include "nsLayoutUtils.h"
 
 #include "CanvasUtils.h"
 #include "NativeJSContext.h"
 #include "SimpleBuffer.h"
 
+#include "jstypedarray.h"
+
 using namespace mozilla;
 
 // XXX why is this broken?
 #ifndef GL_BLEND_EQUATION
 #define GL_BLEND_EQUATION 0x8009
 #endif
 
 static PRBool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize);
@@ -102,200 +104,16 @@ NS_IMETHODIMP WebGLContext::name(t1 a1, 
 NS_IMETHODIMP WebGLContext::name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5, t6 a6) { \
     MakeContextCurrent(); gl->f##glname(a1,a2,a3,a4,a5,a6); return NS_OK; \
 }
 
 //
 //  WebGL API
 //
 
-/* nsIWebGLFloatArray createFloatArray (); */
-NS_IMETHODIMP
-WebGLContext::CreateFloatArray(nsIWebGLFloatArray **retval)
-{
-    NativeJSContext js;
-
-    if (js.argc != 1)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
-    JSObject *arrayObj;
-    jsuint arrayLen;
-
-    if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) ||
-        arrayObj == NULL ||
-        !::JS_IsArrayObject(js.ctx, arrayObj) ||
-        !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen))
-    {
-            return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    WebGLFloatArray *wgfa = new WebGLFloatArray(js.ctx, arrayObj, arrayLen);
-    if (wgfa)
-        NS_ADDREF(*retval = wgfa);
-
-    return NS_OK;
-}
-
-/* nsIWebGLByteArray createByteArray (); */
-NS_IMETHODIMP
-WebGLContext::CreateByteArray(nsIWebGLByteArray **retval)
-{
-    NativeJSContext js;
-
-    if (js.argc != 1)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
-    JSObject *arrayObj;
-    jsuint arrayLen;
-
-    if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) ||
-        arrayObj == NULL ||
-        !::JS_IsArrayObject(js.ctx, arrayObj) ||
-        !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen))
-    {
-            return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    WebGLByteArray *wgba = new WebGLByteArray(js.ctx, arrayObj, arrayLen);
-    if (wgba)
-        NS_ADDREF(*retval = wgba);
-    return NS_OK;
-}
-
-/* nsIWebGLUnsignedByteArray createUnsignedByteArray (); */
-NS_IMETHODIMP
-WebGLContext::CreateUnsignedByteArray(nsIWebGLUnsignedByteArray **retval)
-{
-    NativeJSContext js;
-
-    if (js.argc != 1)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
-    JSObject *arrayObj;
-    jsuint arrayLen;
-
-    if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) ||
-        arrayObj == NULL ||
-        !::JS_IsArrayObject(js.ctx, arrayObj) ||
-        !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen))
-    {
-            return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    WebGLUnsignedByteArray *wguba = new WebGLUnsignedByteArray(js.ctx, arrayObj, arrayLen);
-    if (wguba)
-        NS_ADDREF(*retval = wguba);
-    return NS_OK;
-}
-
-/* nsIWebGLShortArray createShortArray (); */
-NS_IMETHODIMP
-WebGLContext::CreateShortArray(nsIWebGLShortArray **retval)
-{
-    NativeJSContext js;
-
-    if (js.argc != 1)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
-    JSObject *arrayObj;
-    jsuint arrayLen;
-
-    if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) ||
-        arrayObj == NULL ||
-        !::JS_IsArrayObject(js.ctx, arrayObj) ||
-        !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen))
-    {
-            return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    WebGLShortArray *wgsa = new WebGLShortArray(js.ctx, arrayObj, arrayLen);
-    if (wgsa)
-        NS_ADDREF(*retval = wgsa);
-    return NS_OK;
-}
-
-/* nsIWebGLUnsignedShortArray createUnsignedShortArray (); */
-NS_IMETHODIMP
-WebGLContext::CreateUnsignedShortArray(nsIWebGLUnsignedShortArray **retval)
-{
-    NativeJSContext js;
-
-    if (js.argc != 1)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
-    JSObject *arrayObj;
-    jsuint arrayLen;
-
-    if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) ||
-        arrayObj == NULL ||
-        !::JS_IsArrayObject(js.ctx, arrayObj) ||
-        !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen))
-    {
-            return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    WebGLUnsignedShortArray *wgusa = new WebGLUnsignedShortArray(js.ctx, arrayObj, arrayLen);
-    if (wgusa)
-        NS_ADDREF(*retval = wgusa);
-    return NS_OK;
-}
-
-
-/* nsIWebGLUnsignedIntArray createUnsignedIntArray (); */
-NS_IMETHODIMP
-WebGLContext::CreateIntArray(nsIWebGLIntArray **retval)
-{
-    NativeJSContext js;
-
-    if (js.argc != 1)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
-    JSObject *arrayObj;
-    jsuint arrayLen;
-
-    if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) ||
-        arrayObj == NULL ||
-        !::JS_IsArrayObject(js.ctx, arrayObj) ||
-        !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen))
-    {
-            return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    WebGLIntArray *wgia = new WebGLIntArray(js.ctx, arrayObj, arrayLen);
-    if (wgia)
-        NS_ADDREF(*retval = wgia);
-    return NS_OK;
-}
-
-/* nsIWebGLUnsignedIntArray createUnsignedIntArray (); */
-NS_IMETHODIMP
-WebGLContext::CreateUnsignedIntArray(nsIWebGLUnsignedIntArray **retval)
-{
-    NativeJSContext js;
-
-    if (js.argc != 1)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
-    JSObject *arrayObj;
-    jsuint arrayLen;
-
-    if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "o", &arrayObj) ||
-        arrayObj == NULL ||
-        !::JS_IsArrayObject(js.ctx, arrayObj) ||
-        !::JS_GetArrayLength(js.ctx, arrayObj, &arrayLen))
-    {
-            return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    WebGLUnsignedIntArray *wguia = new WebGLUnsignedIntArray(js.ctx, arrayObj, arrayLen);
-    if (wguia)
-        NS_ADDREF(*retval = wguia);
-    return NS_OK;
-}
-
 /* readonly attribute nsIDOMHTMLCanvasElement canvas; */
 NS_IMETHODIMP
 WebGLContext::GetCanvas(nsIDOMHTMLCanvasElement **aCanvas)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 
@@ -465,175 +283,154 @@ GL_SAME_METHOD_1(BlendEquation, BlendEqu
 
 GL_SAME_METHOD_2(BlendEquationSeparate, BlendEquationSeparate, PRUint32, PRUint32)
 
 GL_SAME_METHOD_2(BlendFunc, BlendFunc, PRUint32, PRUint32)
 
 GL_SAME_METHOD_4(BlendFuncSeparate, BlendFuncSeparate, PRUint32, PRUint32, PRUint32, PRUint32)
 
 NS_IMETHODIMP
-WebGLContext::BufferData(GLenum target)
+WebGLContext::BufferData(PRInt32 dummy)
 {
-    // overloaded:
-    // void bufferData (in GLenum target, in GLsizei size, in GLenum usage);
-    // void bufferData (in GLenum target, in nsIWebGLArray data, in GLenum usage);
-    // void bufferData (in GLenum target, in nsIWebGLArrayBuffer data, in GLenum usage)
-
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    if (js.argc != 3)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
+    // this should never be called
+    LogMessage("BufferData");
+    return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+WebGLContext::BufferData_size(GLenum target, GLsizei size, GLenum usage)
+{
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
-        // XXX fix type check
-        //if (na->NativeType() != LOCAL_GL_UNSIGNED_SHORT)
-        //    return ErrorMessage("glBufferData: %x - GL_ELEMENT_ARRAY_BUFFER target must be used with UnsignedShortBuffer", na->NativeType());
-
         boundBuffer = mBoundElementArrayBuffer;
     } else {
-        return ErrorMessage("glBufferData: invalid target");
+        return ErrorMessage("BufferData: invalid target");
     }
 
-    if (boundBuffer == NULL) {
-        return ErrorMessage("glBufferData: no buffer bound!");
-    }
-
+    if (boundBuffer == nsnull)
+        return ErrorMessage("BufferData: no buffer bound!");
 
     MakeContextCurrent();
 
-    uint32 usage;
-
-    if (!::JS_ValueToECMAUint32(js.ctx, js.argv[2], &usage)) {
-        return ErrorMessage("bufferData: invalid usage parameter");
-    }
-
-    if (JSVAL_IS_NUMBER(js.argv[1])) {
-        int32 size;
-        if (!::JS_ValueToECMAInt32(js.ctx, js.argv[1], &size)) {
-            return ErrorMessage("bufferData: invalid size parameter");
-        }
-        boundBuffer->SetCount(size);
-        gl->fBufferData(target, size, 0, usage);
-    } else if (JSVAL_IS_OBJECT(js.argv[1])) {
-        nsCOMPtr<nsIWebGLArray> canvasArrayObj;
-        nsresult rv;
-
-        rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[1]),
-                                                 NS_GET_IID(nsIWebGLArray), getter_AddRefs(canvasArrayObj));
-        if (NS_FAILED(rv) || !canvasArrayObj) {
-            nsCOMPtr<nsIWebGLArrayBuffer> arrayBuf;
-            rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[1]),
-                                                     NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(arrayBuf));
-            if (NS_FAILED(rv) || !arrayBuf)
-                return ErrorMessage("bufferData: need CanvasArray or CanvasArrayBuffer");
-
-            boundBuffer->SetCount(arrayBuf->NativeSize());
-            gl->fBufferData(target, arrayBuf->NativeSize(), arrayBuf->NativePointer(), usage);
-        } else {
-            boundBuffer->Set(canvasArrayObj);
-            gl->fBufferData(target, canvasArrayObj->NativeSize(), canvasArrayObj->NativePointer(), usage);
-        }
-    } else {
-        return ErrorMessage("bufferData: invalid data");
-    }
+    // XXX what happens if BufferData fails? We probably shouldn't
+    // update our size here then, right?
+    boundBuffer->SetByteLength(size);
+    gl->fBufferData(target, size, 0, usage);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::BufferSubData(GLenum target, GLsizeiptr offset)
+WebGLContext::BufferData_buf(GLenum target, js::ArrayBuffer *wb, GLenum usage)
 {
-    // overloaded:
-    // void bufferSubData(in GLenum target, in GLsizeiptr offset, in CanvasArray data) 
-    // void bufferSubData(in GLenum target, in GLsizeiptr offset, in CanvasArrayBuffer data) 
-
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    if (js.argc != 3)
-        return NS_ERROR_DOM_SYNTAX_ERR;
-
+    WebGLBuffer *boundBuffer = NULL;
+
+    if (target == LOCAL_GL_ARRAY_BUFFER) {
+        boundBuffer = mBoundArrayBuffer;
+    } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
+        boundBuffer = mBoundElementArrayBuffer;
+    } else {
+        return ErrorMessage("BufferData: invalid target");
+    }
+
+    if (boundBuffer == nsnull)
+        return ErrorMessage("BufferData: no buffer bound!");
+
+    MakeContextCurrent();
+
+    boundBuffer->SetByteLength(wb->byteLength);
+    gl->fBufferData(target, wb->byteLength, wb->data, usage);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLContext::BufferData_array(GLenum target, js::TypedArray *wa, GLenum usage)
+{
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
-        return ErrorMessage("glBufferSubData: invalid target");
-    }
-
-    if (boundBuffer == NULL) {
-        return ErrorMessage("glBufferSubData: no buffer bound!");
+        return ErrorMessage("BufferData: invalid target");
     }
 
-    /* XXX FIXME 
-    // check type
-    if (na->NativeType() != boundBuffer->GLType()) {
-        return ErrorMessage("glBufferSubData: existing buffer has different base type (0x%04x) the sub data (0x%04x)!", boundBuffer->GLType(), na->NativeType());
-        return NS_ERROR_FAILURE;
+    if (boundBuffer == nsnull)
+        return ErrorMessage("BufferData: no buffer bound!");
+
+    MakeContextCurrent();
+
+    boundBuffer->SetByteLength(wa->byteLength);
+    gl->fBufferData(target, wa->byteLength, wa->data, usage);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLContext::BufferSubData(PRInt32 dummy)
+{
+    return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+WebGLContext::BufferSubData_buf(GLenum target, GLsizei offset, js::ArrayBuffer *wb)
+{
+    WebGLBuffer *boundBuffer = NULL;
+
+    if (target == LOCAL_GL_ARRAY_BUFFER) {
+        boundBuffer = mBoundArrayBuffer;
+    } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
+        boundBuffer = mBoundElementArrayBuffer;
+    } else {
+        return ErrorMessage("BufferSubData: invalid target");
     }
-    */
-
-    if (JSVAL_IS_OBJECT(js.argv[2])) {
-        nsCOMPtr<nsIWebGLArray> canvasArrayObj;
-        nsresult rv;
-
-        rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[2]),
-                                                 NS_GET_IID(nsIWebGLArray), getter_AddRefs(canvasArrayObj));
-        if (NS_FAILED(rv) || !canvasArrayObj) {
-            nsCOMPtr<nsIWebGLArrayBuffer> arrayBuf;
-            rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, JSVAL_TO_OBJECT(js.argv[2]),
-                                                     NS_GET_IID(nsIWebGLArrayBuffer), getter_AddRefs(arrayBuf));
-            if (NS_FAILED(rv) || !arrayBuf)
-                return ErrorMessage("bufferData: need CanvasArray or CanvasArrayBuffer");
-
-            // check size
-            // XXX should be bytes
-            if ((offset + arrayBuf->NativeSize()) > boundBuffer->Count()) {
-                return ErrorMessage("glBufferSubData: existing buffer is too small (%d) for data at offset (%d+%d)",
-                                    boundBuffer->Count(), offset, arrayBuf->NativeSize());
-                return NS_ERROR_FAILURE;
-            }
-#ifdef DEBUG_mwsteele
-            LogMessage("bufferSubData: buffer (%d) for data at offset (%d+%d)", boundBuffer->Count(), offset, arrayBuf->NativeSize());
-#endif
-            // all good
-
-            MakeContextCurrent();
-
-            gl->fBufferSubData(target, offset, arrayBuf->NativeSize(), arrayBuf->NativePointer());
-        } else {
-            // check size
-            // XXX should be bytes
-            if ((offset + canvasArrayObj->NativeCount()) > boundBuffer->Count()) {
-                return ErrorMessage("glBufferSubData: existing buffer is too small (%d) for data at offset (%d+%d)",
-                                    boundBuffer->Count(), offset, canvasArrayObj->NativeCount());
-                return NS_ERROR_FAILURE;
-            }
-#ifdef DEBUG_mwsteele
-            LogMessage("bufferSubData: buffer (%d) for data at offset (%d+%d)", boundBuffer->Count(), offset, canvasArrayObj->NativeSize());
-#endif
-            // all good
-
-            MakeContextCurrent();
-
-            gl->fBufferSubData(target, offset, canvasArrayObj->NativeSize(), canvasArrayObj->NativePointer());
-        }
+
+    if (boundBuffer == nsnull)
+        return ErrorMessage("BufferSubData: no buffer bound!");
+
+    // XXX check for overflow
+    if (offset + wb->byteLength > boundBuffer->ByteLength())
+        return ErrorMessage("BufferSubData: data too big! Operation requires %d bytes, but buffer only has %d bytes.", offset, wb->byteLength, boundBuffer->ByteLength());
+
+    MakeContextCurrent();
+
+    gl->fBufferSubData(target, offset, wb->byteLength, wb->data);
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLContext::BufferSubData_array(GLenum target, GLsizei offset, js::TypedArray *wa)
+{
+    WebGLBuffer *boundBuffer = NULL;
+
+    if (target == LOCAL_GL_ARRAY_BUFFER) {
+        boundBuffer = mBoundArrayBuffer;
+    } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
+        boundBuffer = mBoundElementArrayBuffer;
     } else {
-        return ErrorMessage("bufferData: invalid data");
+        return ErrorMessage("BufferSubData: invalid target");
     }
 
+    if (boundBuffer == nsnull)
+        return ErrorMessage("BufferSubData: no buffer bound!");
+
+    // XXX check for overflow
+    if (offset + wa->byteLength > boundBuffer->ByteLength())
+        return ErrorMessage("BufferSubData: data too big! Operation requires %d bytes, but buffer only has %d bytes.", offset, wa->byteLength, boundBuffer->ByteLength());
+
+    MakeContextCurrent();
+
+    gl->fBufferSubData(target, offset, wa->byteLength, wa->data);
+
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::CheckFramebufferStatus(GLenum target, GLenum *retval)
 {
     MakeContextCurrent();
     // XXX check target
@@ -1021,17 +818,17 @@ WebGLContext::DrawElements(GLenum mode, 
     }
 
     if (!mBoundElementArrayBuffer)
         return ErrorMessage("glDrawElements: must have element array buffer binding!");
 
     if (offset+count < offset || offset+count < count)
         return ErrorMessage("glDrawElements: overflow in offset+count");
 
-    if (count*elementSize + offset > mBoundElementArrayBuffer->ByteCount())
+    if (count*elementSize + offset > mBoundElementArrayBuffer->ByteLength())
         return ErrorMessage("glDrawElements: bound element array buffer is too small for given count and offset");
 
     MakeContextCurrent();
 
     // XXXmark fix validation
     // XXX either GLushort or GLubyte; just put this calculation as a method on the array object
 #if 0
     GLuint maxindex = 0;
@@ -1259,18 +1056,18 @@ WebGLContext::GetAttachedShaders(nsIWebG
     js.ReleaseGCRoot(obj);
 
     return NS_OK;
 }
 #endif
 
 NS_IMETHODIMP
 WebGLContext::GetAttribLocation(nsIWebGLProgram *prog,
-                                  const nsAString& name,
-                                  PRInt32 *retval)
+                                const nsAString& name,
+                                PRInt32 *retval)
 {
     if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
         return ErrorMessage("%s: program is null or deleted!", __FUNCTION__);
 
     GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
 
     MakeContextCurrent();
     *retval = gl->fGetAttribLocation(program, NS_LossyConvertUTF16toASCII(name).get());
@@ -1441,44 +1238,16 @@ WebGLContext::GetParameter(PRUint32 pnam
         default:
             return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::GetBufferParameteri(GLenum target, GLenum pname, GLint *retval)
-{
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    MakeContextCurrent();
-
-    switch (pname) {
-        case LOCAL_GL_BUFFER_SIZE:
-        case LOCAL_GL_BUFFER_USAGE:
-        case LOCAL_GL_BUFFER_ACCESS:
-        case LOCAL_GL_BUFFER_MAPPED:
-        {
-            PRInt32 iv = 0;
-            gl->fGetBufferParameteriv(target, pname, (GLint*) &iv);
-            js.SetRetVal(iv);
-        }
-            break;
-
-        default:
-            return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 WebGLContext::GetBufferParameter(GLenum target, GLenum pname)
 {
     NativeJSContext js;
     if (NS_FAILED(js.error))
         return js.error;
 
     MakeContextCurrent();
 
@@ -1497,53 +1266,16 @@ WebGLContext::GetBufferParameter(GLenum 
         default:
             return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::GetFramebufferAttachmentParameteri(GLenum target, GLenum attachment, GLenum pname, GLint *retval)
-{
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    MakeContextCurrent();
-
-    switch (attachment) {
-        case LOCAL_GL_COLOR_ATTACHMENT0:
-        case LOCAL_GL_DEPTH_ATTACHMENT:
-        case LOCAL_GL_STENCIL_ATTACHMENT:
-            break;
-        default:
-            return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
-    switch (pname) {
-        case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
-        case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
-        case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
-        case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
-        {
-            PRInt32 iv = 0;
-            gl->fGetFramebufferAttachmentParameteriv(target, attachment, pname, (GLint*) &iv);
-            js.SetRetVal(iv);
-        }
-            break;
-
-        default:
-            return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 WebGLContext::GetFramebufferAttachmentParameter(GLenum target, GLenum attachment, GLenum pname)
 {
     NativeJSContext js;
     if (NS_FAILED(js.error))
         return js.error;
 
     MakeContextCurrent();
 
@@ -1571,49 +1303,16 @@ WebGLContext::GetFramebufferAttachmentPa
         default:
             return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::GetRenderbufferParameteri(GLenum target, GLenum pname, GLint *retval)
-{
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    MakeContextCurrent();
-
-    switch (pname) {
-        case LOCAL_GL_RENDERBUFFER_WIDTH:
-        case LOCAL_GL_RENDERBUFFER_HEIGHT:
-        case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
-        case LOCAL_GL_RENDERBUFFER_RED_SIZE:
-        case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
-        case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
-        case LOCAL_GL_RENDERBUFFER_ALPHA_SIZE:
-        case LOCAL_GL_RENDERBUFFER_DEPTH_SIZE:
-        case LOCAL_GL_RENDERBUFFER_STENCIL_SIZE:
-        {
-            PRInt32 iv = 0;
-            gl->fGetRenderbufferParameteriv(target, pname, (GLint*) &iv);
-            js.SetRetVal(iv);
-        }
-            break;
-
-        default:
-            return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 WebGLContext::GetRenderbufferParameter(GLenum target, GLenum pname)
 {
     NativeJSContext js;
     if (NS_FAILED(js.error))
         return js.error;
 
     MakeContextCurrent();
 
@@ -1683,55 +1382,16 @@ NS_IMETHODIMP
 WebGLContext::GetError(GLenum *_retval)
 {
     MakeContextCurrent();
     *_retval = gl->fGetError();
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::GetProgrami(nsIWebGLProgram *prog, PRUint32 pname, GLint *retval)
-{
-    if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
-        return ErrorMessage("%s: program is null or deleted!", __FUNCTION__);
-
-    GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
-
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    MakeContextCurrent();
-
-    switch (pname) {
-        case LOCAL_GL_CURRENT_PROGRAM:
-        case LOCAL_GL_DELETE_STATUS:
-        case LOCAL_GL_LINK_STATUS:
-        case LOCAL_GL_VALIDATE_STATUS:
-        case LOCAL_GL_ATTACHED_SHADERS:
-        case LOCAL_GL_INFO_LOG_LENGTH:
-        case LOCAL_GL_ACTIVE_UNIFORMS:
-        case LOCAL_GL_ACTIVE_UNIFORM_MAX_LENGTH:
-        case LOCAL_GL_ACTIVE_ATTRIBUTES:
-        case LOCAL_GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
-        {
-            PRInt32 iv = 0;
-            gl->fGetProgramiv(program, pname, (GLint*) &iv);
-            js.SetRetVal(iv);
-        }
-            break;
-
-        default:
-            return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 WebGLContext::GetProgramParameter(nsIWebGLProgram *prog, PRUint32 pname)
 {
     if (!prog || static_cast<WebGLProgram*>(prog)->Deleted())
         return ErrorMessage("%s: program is null or deleted!", __FUNCTION__);
 
     GLuint program = static_cast<WebGLProgram*>(prog)->GLName();
 
     NativeJSContext js;
@@ -1927,76 +1587,16 @@ WebGLContext::TexParameter()
         default:
             return NS_ERROR_DOM_SYNTAX_ERR;
     }
 
     return NS_OK;
 }
 #endif
 
-/* XXX fix */
-/* void getTexParameter (); */
-
-/* GLfloat getTexParameterf (in GLenum target, in GLenum pname); */
-NS_IMETHODIMP
-WebGLContext::GetTexParameterf(GLenum target, GLenum pname, GLfloat *retval)
-{
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    MakeContextCurrent();
-
-    switch (pname) {
-        case LOCAL_GL_TEXTURE_MIN_FILTER:
-        case LOCAL_GL_TEXTURE_MAG_FILTER:
-        case LOCAL_GL_TEXTURE_WRAP_S:
-        case LOCAL_GL_TEXTURE_WRAP_T:
-        {
-            float fv = 0;
-            gl->fGetTexParameterfv(target, pname, (GLfloat*) &fv);
-            js.SetRetVal(fv);
-        }
-            break;
-
-        default:
-            return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
-WebGLContext::GetTexParameteri(GLenum target, GLenum pname, GLint *retval)
-{
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    MakeContextCurrent();
-
-    switch (pname) {
-        case LOCAL_GL_TEXTURE_MIN_FILTER:
-        case LOCAL_GL_TEXTURE_MAG_FILTER:
-        case LOCAL_GL_TEXTURE_WRAP_S:
-        case LOCAL_GL_TEXTURE_WRAP_T:
-        {
-            PRInt32 iv = 0;
-            gl->fGetTexParameteriv(target, pname, (GLint*) &iv);
-            js.SetRetVal(iv);
-        }
-            break;
-
-        default:
-            return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
-    return NS_OK;
-}
-
 NS_IMETHODIMP
 WebGLContext::GetTexParameter(GLenum target, GLenum pname)
 {
     NativeJSContext js;
     if (NS_FAILED(js.error))
         return js.error;
 
     MakeContextCurrent();
@@ -2326,19 +1926,19 @@ GL_SAME_METHOD_1(StencilMask, StencilMas
 GL_SAME_METHOD_2(StencilMaskSeparate, StencilMaskSeparate, GLenum, GLuint)
 
 GL_SAME_METHOD_3(StencilOp, StencilOp, GLenum, GLenum, GLenum)
 
 GL_SAME_METHOD_4(StencilOpSeparate, StencilOpSeparate, GLenum, GLenum, GLenum, GLenum)
 
 
 nsresult
-WebGLContext::TexImageElementBase(nsIDOMHTMLElement *imageOrCanvas,
-                                  gfxImageSurface **imageOut,
-                                  PRBool flipY, PRBool premultiplyAlpha)
+WebGLContext::DOMElementToImageSurface(nsIDOMElement *imageOrCanvas,
+                                       gfxImageSurface **imageOut,
+                                       PRBool flipY, PRBool premultiplyAlpha)
 {
     gfxImageSurface *surf = nsnull;
 
     nsLayoutUtils::SurfaceFromElementResult res =
         nsLayoutUtils::SurfaceFromElement(imageOrCanvas,
                                           nsLayoutUtils::SFE_WANT_NEW_SURFACE | nsLayoutUtils::SFE_WANT_IMAGE_SURFACE);
     if (!res.mSurface)
         return NS_ERROR_FAILURE;
@@ -2451,169 +2051,100 @@ WebGLContext::TexImageElementBase(nsIDOM
     }
 
     res.mSurface.forget();
     *imageOut = surf;
 
     return NS_OK;
 }
 
+#define GL_SIMPLE_ARRAY_METHOD(name, cnt, arrayType, ptrType)           \
+NS_IMETHODIMP                                                           \
+WebGLContext::name(PRInt32 dummy) {                                     \
+     return NS_ERROR_NOT_IMPLEMENTED;                                   \
+}                                                                       \
+NS_IMETHODIMP                                                           \
+WebGLContext::name##_array(GLint idx, js::TypedArray *wa)               \
+{                                                                       \
+    if (!wa || wa->type != js::TypedArray::arrayType)                   \
+        return ErrorMessage("array must be " #arrayType);               \
+    if (wa->length == 0 || wa->length % cnt != 0)                       \
+        return ErrorMessage("array must be > 0 elements and have a length multiple of %d", cnt); \
+    MakeContextCurrent();                                               \
+    gl->f##name(idx, wa->length / cnt, (ptrType *)wa->data);            \
+    return NS_OK;                                                       \
+}
+
+#define GL_SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, arrayType, ptrType)  \
+NS_IMETHODIMP                                                           \
+WebGLContext::name(PRInt32 dummy) {                                     \
+     return NS_ERROR_NOT_IMPLEMENTED;                                   \
+}                                                                       \
+NS_IMETHODIMP                                                           \
+WebGLContext::name##_array(GLuint idx, js::TypedArray *wa)              \
+{                                                                       \
+    if (!wa || wa->type != js::TypedArray::arrayType)                   \
+        return ErrorMessage("array must be " #arrayType);               \
+    if (wa->length < cnt)                                               \
+        return ErrorMessage("array must be >= %d elements", cnt);       \
+    MakeContextCurrent();                                               \
+    gl->f##name(idx, (ptrType *)wa->data);                              \
+    return NS_OK;                                                       \
+}
+
+#define GL_SIMPLE_MATRIX_METHOD(name, dim, arrayType, ptrType)          \
+NS_IMETHODIMP                                                           \
+WebGLContext::name(PRInt32 dummy) {                                     \
+     return NS_ERROR_NOT_IMPLEMENTED;                                   \
+}                                                                       \
+NS_IMETHODIMP                                                           \
+WebGLContext::name##_array(GLint idx, GLboolean transpose, js::TypedArray *wa)  \
+{                                                                       \
+    if (!wa || wa->type != js::TypedArray::arrayType)                   \
+        return ErrorMessage("array must be " #arrayType);               \
+    if (wa->length == 0 || wa->length % (dim*dim) != 0)                 \
+        return ErrorMessage("array must be > 0 elements and have a length multiple of %d", dim*dim); \
+    MakeContextCurrent();                                               \
+    gl->f##name(idx, wa->length / (dim*dim), transpose, (ptrType *)wa->data); \
+    return NS_OK;                                                       \
+}
+
 GL_SAME_METHOD_2(Uniform1i, Uniform1i, GLint, GLint)
 GL_SAME_METHOD_3(Uniform2i, Uniform2i, GLint, GLint, GLint)
 GL_SAME_METHOD_4(Uniform3i, Uniform3i, GLint, GLint, GLint, GLint)
 GL_SAME_METHOD_5(Uniform4i, Uniform4i, GLint, GLint, GLint, GLint, GLint)
 
 GL_SAME_METHOD_2(Uniform1f, Uniform1f, GLint, GLfloat)
 GL_SAME_METHOD_3(Uniform2f, Uniform2f, GLint, GLfloat, GLfloat)
 GL_SAME_METHOD_4(Uniform3f, Uniform3f, GLint, GLfloat, GLfloat, GLfloat)
 GL_SAME_METHOD_5(Uniform4f, Uniform4f, GLint, GLfloat, GLfloat, GLfloat, GLfloat)
 
-// one uint arg followed by an array of c elements of glTypeConst.
-#define GL_SIMPLE_ARRAY_METHOD(glname, name, c, glTypeConst, ptrType)             \
-NS_IMETHODIMP                                                                     \
-WebGLContext::name(GLint idx, nsIWebGLArray *v)                                  \
-{                                                                                 \
-    NativeJSContext js;                                                           \
-    if (NS_FAILED(js.error))                                                      \
-        return js.error;                                                          \
-    JSObject *arrayObj;                                                           \
-    jsuint arrayLen;                                                              \
-    if (js.argc != 2)                                                             \
-        return NS_ERROR_INVALID_ARG;                                              \
-    if (NativeJSContext::JSValToJSArrayAndLength(js.ctx, js.argv[1], &arrayObj, &arrayLen)) { \
-        if (arrayLen % c != 0) {                                                  \
-            return ErrorMessage(#name ": array length not divisible by " #c);     \
-        }                                                                         \
-        SimpleBuffer sbuffer(glTypeConst, c, js.ctx, arrayObj, arrayLen);         \
-        if (!sbuffer.Valid())                                                     \
-            return NS_ERROR_FAILURE;                                              \
-        MakeContextCurrent();                                                     \
-        gl->f##glname(idx, arrayLen / c, ( ptrType *)sbuffer.data);               \
-    } else {                                                                      \
-        if (glTypeConst == LOCAL_GL_INT) {                                        \
-            if (v->NativeType() != LOCAL_GL_INT) {                                \
-                return ErrorMessage(#name ": arg not an array");                  \
-            }                                                                     \
-            if (v->NativeCount() % c != 0) {                                      \
-                return ErrorMessage(#name ": array length not divisible by " #c); \
-            }                                                                     \
-            MakeContextCurrent();                                                 \
-            gl->f##glname(idx, v->NativeCount() / c, ( ptrType *)v->NativePointer()); \
-        } else if (glTypeConst == LOCAL_GL_FLOAT) {                               \
-            if (v->NativeType() != LOCAL_GL_FLOAT) {                              \
-                return ErrorMessage(#name ": arg not an array");                  \
-            }                                                                     \
-            if (v->NativeCount() % c != 0) {                                      \
-                return ErrorMessage(#name ": array length not divisible by " #c); \
-            }                                                                     \
-            MakeContextCurrent();                                                 \
-            gl->f##glname(idx, v->NativeCount() / c, ( ptrType *)v->NativePointer()); \
-        } else {                                                                  \
-            return ErrorMessage("Unhandled glTypeConst"); /* need compiler fail */\
-        }                                                                         \
-    }                                                                             \
-    return NS_OK;                                                                 \
-}
-
-#define GL_SIMPLE_ARRAY_METHOD_NO_COUNT(glname, name, c, glTypeConst, ptrType)    \
-NS_IMETHODIMP                                                                     \
-WebGLContext::name(GLuint idx, nsIWebGLArray *v)                                 \
-{                                                                                 \
-    NativeJSContext js;                                                           \
-    if (NS_FAILED(js.error))                                                      \
-        return js.error;                                                          \
-    JSObject *arrayObj;                                                           \
-    jsuint arrayLen;                                                              \
-    if (js.argc != 2)                                                             \
-        return NS_ERROR_INVALID_ARG;                                              \
-    if (NativeJSContext::JSValToJSArrayAndLength(js.ctx, js.argv[1], &arrayObj, &arrayLen)) { \
-        if (arrayLen % c != 0) {                                                  \
-            return ErrorMessage(#name ": array wrong size, expected " #c);        \
-        }                                                                         \
-        SimpleBuffer sbuffer(glTypeConst, c, js.ctx, arrayObj, arrayLen);         \
-        if (!sbuffer.Valid())                                                     \
-            return NS_ERROR_FAILURE;                                              \
-        MakeContextCurrent();                                                     \
-        gl->f##glname(idx, ( ptrType *)sbuffer.data);                             \
-    } else {                                                                      \
-        if (glTypeConst == LOCAL_GL_INT) {                                        \
-            if (v->NativeType() != LOCAL_GL_INT) {                                \
-                return ErrorMessage(#name ": arg not an array");                  \
-            }                                                                     \
-            if (v->NativeCount() % c != 0) {                                      \
-                return ErrorMessage(#name ": array wrong size %d, expected " #c, v->NativeCount()); \
-            }                                                                     \
-            MakeContextCurrent();                                                 \
-            gl->f##glname(idx, ( ptrType *)v->NativePointer());                   \
-        } else if (glTypeConst == LOCAL_GL_FLOAT) {                               \
-            if (v->NativeType() != LOCAL_GL_FLOAT) {                              \
-                return ErrorMessage(#name ": arg not an array");                  \
-            }                                                                     \
-            if (v->NativeCount() % c != 0) {                                      \
-                return ErrorMessage(#name ": array wrong size %d, expected " #c, v->NativeCount()); \
-            }                                                                     \
-            MakeContextCurrent();                                                 \
-            gl->f##glname(idx, ( ptrType *)v->NativePointer());                   \
-        } else {                                                                  \
-            return ErrorMessage("Unhandled glTypeConst"); /* need compiler fail */\
-        }                                                                         \
-    }                                                                             \
-    return NS_OK;                                                                 \
-}
-
-#define GL_SIMPLE_MATRIX_METHOD(glname, name, c, glTypeConst, ptrType)            \
-NS_IMETHODIMP                                                                     \
-WebGLContext::name(GLint location, GLboolean transpose, nsIWebGLArray *value)    \
-{                                                                                 \
-    NativeJSContext js;                                                           \
-    if (NS_FAILED(js.error))                                                      \
-        return js.error;                                                          \
-    JSObject *arrayObj;                                                           \
-    jsuint arrayLen;                                                              \
-    if (js.argc != 3)                                                             \
-        return NS_ERROR_INVALID_ARG;                                              \
-    if (NativeJSContext::JSValToJSArrayAndLength(js.ctx, js.argv[2], &arrayObj, &arrayLen)) { \
-        if (arrayLen % c != 0) {                                                  \
-            return ErrorMessage(#name ": array wrong size, expected " #c);        \
-        }                                                                         \
-        SimpleBuffer sbuffer(glTypeConst, c, js.ctx, arrayObj, arrayLen);         \
-        if (!sbuffer.Valid())                                                     \
-            return NS_ERROR_FAILURE;                                              \
-        MakeContextCurrent();                                                     \
-        gl->f##glname(location, arrayLen / c, transpose, ( ptrType *)sbuffer.data); \
-    } else {                                                                      \
-        if (glTypeConst == LOCAL_GL_FLOAT) {                                      \
-            if (value->NativeType() != LOCAL_GL_FLOAT) {                          \
-                return ErrorMessage(#name ": arg not an array");                  \
-            }                                                                     \
-            if (value->NativeCount() % c != 0) {                                  \
-                return ErrorMessage(#name ": array wrong size %d, expected " #c, value->NativeCount());     \
-            }                                                                     \
-            MakeContextCurrent();                                                 \
-            gl->f##glname(location, value->NativeCount() / c, transpose, ( ptrType *)value->NativePointer()); \
-        } else {                                                                  \
-            return ErrorMessage("Unhandled glTypeConst"); /* need compiler fail */\
-        }                                                                         \
-    }                                                                             \
-    return NS_OK;                                                                 \
-}
-
-GL_SIMPLE_ARRAY_METHOD(Uniform1iv, Uniform1iv, 1, LOCAL_GL_INT, GLint)
-GL_SIMPLE_ARRAY_METHOD(Uniform2iv, Uniform2iv, 2, LOCAL_GL_INT, GLint)
-GL_SIMPLE_ARRAY_METHOD(Uniform3iv, Uniform3iv, 3, LOCAL_GL_INT, GLint)
-GL_SIMPLE_ARRAY_METHOD(Uniform4iv, Uniform4iv, 4, LOCAL_GL_INT, GLint)
-
-GL_SIMPLE_ARRAY_METHOD(Uniform1fv, Uniform1fv, 1, LOCAL_GL_FLOAT, GLfloat)
-GL_SIMPLE_ARRAY_METHOD(Uniform2fv, Uniform2fv, 2, LOCAL_GL_FLOAT, GLfloat)
-GL_SIMPLE_ARRAY_METHOD(Uniform3fv, Uniform3fv, 3, LOCAL_GL_FLOAT, GLfloat)
-GL_SIMPLE_ARRAY_METHOD(Uniform4fv, Uniform4fv, 4, LOCAL_GL_FLOAT, GLfloat)
-
-GL_SIMPLE_MATRIX_METHOD(UniformMatrix2fv, UniformMatrix2fv, 4, LOCAL_GL_FLOAT, GLfloat)
-GL_SIMPLE_MATRIX_METHOD(UniformMatrix3fv, UniformMatrix3fv, 9, LOCAL_GL_FLOAT, GLfloat)
-GL_SIMPLE_MATRIX_METHOD(UniformMatrix4fv, UniformMatrix4fv, 16, LOCAL_GL_FLOAT, GLfloat)
+GL_SIMPLE_ARRAY_METHOD(Uniform1iv, 1, TYPE_INT32, GLint)
+GL_SIMPLE_ARRAY_METHOD(Uniform2iv, 2, TYPE_INT32, GLint)
+GL_SIMPLE_ARRAY_METHOD(Uniform3iv, 3, TYPE_INT32, GLint)
+GL_SIMPLE_ARRAY_METHOD(Uniform4iv, 4, TYPE_INT32, GLint)
+
+GL_SIMPLE_ARRAY_METHOD(Uniform1fv, 1, TYPE_FLOAT32, GLfloat)
+GL_SIMPLE_ARRAY_METHOD(Uniform2fv, 2, TYPE_FLOAT32, GLfloat)
+GL_SIMPLE_ARRAY_METHOD(Uniform3fv, 3, TYPE_FLOAT32, GLfloat)
+GL_SIMPLE_ARRAY_METHOD(Uniform4fv, 4, TYPE_FLOAT32, GLfloat)
+
+GL_SIMPLE_MATRIX_METHOD(UniformMatrix2fv, 2, TYPE_FLOAT32, GLfloat)
+GL_SIMPLE_MATRIX_METHOD(UniformMatrix3fv, 3, TYPE_FLOAT32, GLfloat)
+GL_SIMPLE_MATRIX_METHOD(UniformMatrix4fv, 4, TYPE_FLOAT32, GLfloat)
+
+GL_SAME_METHOD_2(VertexAttrib1f, VertexAttrib1f, PRUint32, GLfloat)
+GL_SAME_METHOD_3(VertexAttrib2f, VertexAttrib2f, PRUint32, GLfloat, GLfloat)
+GL_SAME_METHOD_4(VertexAttrib3f, VertexAttrib3f, PRUint32, GLfloat, GLfloat, GLfloat)
+GL_SAME_METHOD_5(VertexAttrib4f, VertexAttrib4f, PRUint32, GLfloat, GLfloat, GLfloat, GLfloat)
+
+GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, TYPE_FLOAT32, GLfloat)
+GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, TYPE_FLOAT32, GLfloat)
+GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, 3, TYPE_FLOAT32, GLfloat)
+GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, TYPE_FLOAT32, GLfloat)
 
 NS_IMETHODIMP
 WebGLContext::UseProgram(nsIWebGLProgram *prog)
 {
     if (prog && static_cast<WebGLProgram*>(prog)->Deleted())
         return ErrorMessage("glUseProgram: program has already been deleted!");
 
     GLuint program = prog ? static_cast<WebGLProgram*>(prog)->GLName() : 0;
@@ -2637,26 +2168,16 @@ WebGLContext::ValidateProgram(nsIWebGLPr
 
     MakeContextCurrent();
 
     gl->fValidateProgram(program);
 
     return NS_OK;
 }
 
-GL_SAME_METHOD_2(VertexAttrib1f, VertexAttrib1f, PRUint32, float)
-GL_SAME_METHOD_3(VertexAttrib2f, VertexAttrib2f, PRUint32, float, float)
-GL_SAME_METHOD_4(VertexAttrib3f, VertexAttrib3f, PRUint32, float, float, float)
-GL_SAME_METHOD_5(VertexAttrib4f, VertexAttrib4f, PRUint32, float, float, float, float)
-
-GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, VertexAttrib1fv, 1, LOCAL_GL_FLOAT, GLfloat)
-GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, VertexAttrib2fv, 2, LOCAL_GL_FLOAT, GLfloat)
-GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, VertexAttrib3fv, 3, LOCAL_GL_FLOAT, GLfloat)
-GL_SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, VertexAttrib4fv, 4, LOCAL_GL_FLOAT, GLfloat)
-
 NS_IMETHODIMP
 WebGLContext::CreateFramebuffer(nsIWebGLFramebuffer **retval)
 {
     MakeContextCurrent();
 
     GLuint name;
     gl->fGenFramebuffers(1, &name);
 
@@ -2704,50 +2225,16 @@ WebGLContext::CompileShader(nsIWebGLShad
 
     gl->fCompileShader(shader);
 
     return NS_OK;
 }
 
 
 NS_IMETHODIMP
-WebGLContext::GetShaderi(nsIWebGLShader *shobj, GLenum pname, GLint *_retval)
-{
-    if (!shobj || static_cast<WebGLShader*>(shobj)->Deleted())
-        return ErrorMessage("%s: shader is null or deleted!", __FUNCTION__);
-
-    GLuint shader = static_cast<WebGLShader*>(shobj)->GLName();
-    
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    MakeContextCurrent();
-
-    switch (pname) {
-        case LOCAL_GL_SHADER_TYPE:
-        case LOCAL_GL_DELETE_STATUS:
-        case LOCAL_GL_COMPILE_STATUS:
-        case LOCAL_GL_INFO_LOG_LENGTH:
-        case LOCAL_GL_SHADER_SOURCE_LENGTH:
-        {
-            PRInt32 iv = 0;
-            gl->fGetShaderiv(shader, pname, (GLint*) &iv);
-            js.SetRetVal(iv);
-        }
-            break;
-
-        default:
-            return NS_ERROR_NOT_IMPLEMENTED;
-    }
-
-    return NS_OK;
-}
-
-NS_IMETHODIMP
 WebGLContext::GetShaderParameter(nsIWebGLShader *shobj, GLenum pname)
 {
     if (!shobj || static_cast<WebGLShader*>(shobj)->Deleted())
         return ErrorMessage("%s: shader is null or deleted!", __FUNCTION__);
 
     GLuint shader = static_cast<WebGLShader*>(shobj)->GLName();
     
     NativeJSContext js;
@@ -2854,18 +2341,18 @@ WebGLContext::ShaderSource(nsIWebGLShade
     const char *p = asciisrc.get();
 
     gl->fShaderSource(shader, 1, &p, NULL);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::VertexAttribPointer(GLuint index, GLint size, GLenum type,
-                                    GLboolean normalized, GLuint stride,
-                                    GLuint offset)
+                                  GLboolean normalized, GLuint stride,
+                                  GLuint offset)
 {
     if (mBoundArrayBuffer == nsnull)
         return ErrorMessage("glvertexattribpointer: must have GL_ARRAY_BUFFER binding!");
 
     if (index >= mAttribBuffers.Length())
         return ErrorMessage("glVertexAttribPointer: index out of range - %d >= %d", index, mAttribBuffers.Length());
 
     if (size < 1 || size > 4)
@@ -2941,360 +2428,303 @@ WebGLContext::ValidateGL()
     // gl_PointSize is always available in ES2 GLSL
     gl->fEnable(LOCAL_GL_VERTEX_PROGRAM_POINT_SIZE);
 #endif
 
     return PR_TRUE;
 }
 
 NS_IMETHODIMP
-WebGLContext::TexSubImage2D()
+WebGLContext::TexImage2D(PRInt32 dummy)
 {
-    // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
-    //                    in GLsizei width, in GLsizei height,
-    //                    in GLenum format, in GLenum type, in CanvasArray pixels)
-    // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, 
-    //                    in ImageData pixels,
-    //                    [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
-    // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, 
-    //                    in HTMLImageElement image,
-    //                    [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
-    // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset, 
-    //                    in HTMLCanvasElement image,
-    //                    [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
-    // void texSubImage2D(in GLenum target, in GLint level, in GLint xoffset, in GLint yoffset,
-    //                    in HTMLVideoElement image,
-    //                    [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
-
-    // XXX TODO
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    if (js.argc < 5 || js.argc > 9) {
-        return ErrorMessage("texSubImage2D: expected 5 to 9 arguments");
-        return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    if (js.argc < 8) {
-        jsuint argTarget, argLevel, argX, argY;
-        JSObject *argPixelsObj;
-        JSBool flipY = JS_FALSE;
-        JSBool premultiplyAlpha = JS_TRUE;
-
-        if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuo/bb",
-                                   &argTarget, &argLevel, &argX, &argY,
-                                   &argPixelsObj, &flipY, &premultiplyAlpha) ||
-            !argPixelsObj)
-            {
-                return ErrorMessage("texSubImage2D: argument error");
-                return NS_ERROR_DOM_SYNTAX_ERR;
-            }
-        nsCOMPtr<nsIDOMHTMLElement> imgElt;
-        nsresult rv;
-        rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsIDOMHTMLElement), getter_AddRefs(imgElt));
-
-        nsRefPtr<gfxImageSurface> isurf;
-
-        rv = TexImageElementBase(imgElt, getter_AddRefs(isurf), flipY, premultiplyAlpha);
-
-        if (NS_FAILED(rv))
-            return ErrorMessage("texImage2D: failed to get image for element");
-
-        MakeContextCurrent();
-
-        gl->fTexSubImage2D (argTarget, argLevel, argX, argY, isurf->Width(), isurf->Height(), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, isurf->Data());
-    } else {
-        jsuint argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType;
-        JSObject *argPixelsObj;
-        if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo",
-                                   &argTarget, &argLevel, &argX, &argY,
-                                   &argWidth, &argHeight, &argFormat, &argType,
-                                   &argPixelsObj) ||
-            !argPixelsObj)
-            {
-                return ErrorMessage("texSubImage2D: argument error");
-                return NS_ERROR_DOM_SYNTAX_ERR;
-            }
-
-        switch (argTarget) {
-            case LOCAL_GL_TEXTURE_2D:
-            case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
-            case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
-            case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
-            case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
-            case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
-            case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
-                break;
-            default:
-                return ErrorMessage("texSubImage2D: unsupported target");
-                return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        PRUint32 bufferType, bufferSize;
-        switch (argFormat) {
-            case LOCAL_GL_RED:
-            case LOCAL_GL_GREEN:
-            case LOCAL_GL_BLUE:
-            case LOCAL_GL_ALPHA:
-            case LOCAL_GL_LUMINANCE:
-                bufferSize = 1;
-                break;
-            case LOCAL_GL_LUMINANCE_ALPHA:
-                bufferSize = 2;
-                break;
-            case LOCAL_GL_RGB:
-                bufferSize = 3;
-                break;
-            case LOCAL_GL_RGBA:
-                bufferSize = 4;
-                break;
-            default:
-                return ErrorMessage("texSubImage2D: pixel format not supported");
-                return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        switch (argType) {
-            case LOCAL_GL_SHORT:
-            case LOCAL_GL_UNSIGNED_SHORT:
-            case LOCAL_GL_BYTE:
-            case LOCAL_GL_UNSIGNED_BYTE:
-            case LOCAL_GL_INT:
-            case LOCAL_GL_UNSIGNED_INT:
-            case LOCAL_GL_FLOAT:
-                bufferType = argType;
-                break;
-            case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
-            case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
-            case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
-                bufferType = LOCAL_GL_UNSIGNED_SHORT;
-                break;
-            default:
-                return ErrorMessage("texSubImage2D: pixel packing not supported");
-                return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        // make sure the size is valid
-        PRInt32 tmp = argWidth * argHeight;
-        if (tmp && tmp / argHeight != argWidth) {
-            return ErrorMessage("texSubImage2D: too large width or height");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        tmp = tmp * bufferSize;
-        if (tmp && tmp / bufferSize != (argWidth * argHeight)) {
-            return ErrorMessage("texSubImage2D: too large width or height (after multiplying with pixel size)");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        nsCOMPtr<nsIWebGLArray> arrayObj;
-        nsresult rv;
-        rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsISupports), getter_AddRefs(arrayObj));
-        arrayObj = do_QueryInterface(arrayObj, &rv);
-
-        if (NS_FAILED(rv) || !arrayObj) {
-            return ErrorMessage("texSubImage2D: pixels arg is not a WebGL array");
-        }
-
-        if ((PRUint32) tmp > arrayObj->NativeSize()) {
-            return ErrorMessage("texSubImage2D: array dimensions too small for width, height and pixel format");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        MakeContextCurrent();
-        gl->fTexSubImage2D (argTarget, argLevel, argX, argY, argWidth, argHeight, argFormat, argType, arrayObj->NativePointer());
-    }
-    return NS_OK;
+    return NS_ERROR_FAILURE;
 }
 
-NS_IMETHODIMP
-WebGLContext::TexImage2D()
+nsresult
+WebGLContext::TexImage2D_base(GLenum target, GLint level, GLenum internalformat,
+                              GLsizei width, GLsizei height, GLint border,
+                              GLenum format, GLenum type,
+                              void *data, PRUint32 byteLength)
 {
-    // void texImage2D(in GLenum target, in GLint level, in GLenum internalformat,
-    //                 in GLsizei width, in GLsizei height, in GLint border, in GLenum format,
-    //                 in GLenum type, in CanvasArray pixels)
-    // void texImage2D(in GLenum target, in GLint level, in ImageData pixels,
-    //                 [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
-    // void texImage2D(in GLenum target, in GLint level, in HTMLImageElement image,
-    //                 [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
-    // void texImage2D(in GLenum target, in GLint level, in HTMLCanvasElement image,
-    //                 [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
-    // void texImage2D(in GLenum target, in GLint level, in HTMLVideoElement image,
-    //                 [Optional] GLboolean flipY, [Optional] in asPremultipliedAlpha)
-
-    // XXX TODO
-    NativeJSContext js;
-    if (NS_FAILED(js.error))
-        return js.error;
-
-    if (js.argc < 3 || js.argc > 9) {
-        return ErrorMessage("texImage2D: expected 3-5 or 9 arguments, got %d", js.argc);
-        return NS_ERROR_DOM_SYNTAX_ERR;
-    }
-
-    jsuint argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType;
-
-    if (js.argc > 2 && js.argc < 6) {
-        JSObject *argPixelsObj;
-        JSBool flipY = JS_FALSE;
-        JSBool premultiplyAlpha = JS_TRUE;
-
-        if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuo/bb",
-                                   &argTarget, &argLevel,
-                                   &argPixelsObj, &flipY, &premultiplyAlpha) ||
-            !argPixelsObj)
-            {
-                return ErrorMessage("texImage2D: argument error");
-                return NS_ERROR_DOM_SYNTAX_ERR;
-            }
-        nsCOMPtr<nsIDOMHTMLElement> imgElt;
-        nsresult rv;
-        rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsIDOMHTMLElement), getter_AddRefs(imgElt));
-
-        nsRefPtr<gfxImageSurface> isurf;
-
-        rv = TexImageElementBase(imgElt, getter_AddRefs(isurf), flipY, premultiplyAlpha);
-
-        if (NS_FAILED(rv))
-            return ErrorMessage("texImage2D: failed to get image for element");
-
-        MakeContextCurrent();
-
-        gl->fTexImage2D (argTarget, argLevel, LOCAL_GL_RGBA, isurf->Width(), isurf->Height(), 0, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE, isurf->Data());
-
-    } else if (js.argc == 9) {
-        JSObject *argPixelsObj;
-        if (!::JS_ConvertArguments(js.ctx, js.argc, js.argv, "uuuuuuuuo",
-                                   &argTarget, &argLevel, &argInternalFormat, &argWidth,
-                                   &argHeight, &argBorder, &argFormat, &argType,
-                                   &argPixelsObj) ||
-            !argPixelsObj)
-            {
-                return ErrorMessage("texImage2D: argument error");
-                return NS_ERROR_DOM_SYNTAX_ERR;
-            }
-        if (argWidth == 0 || argHeight == 0) {
-            return ErrorMessage("texImage2D: width or height is zero");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        switch (argTarget) {
+    switch (target) {
         case LOCAL_GL_TEXTURE_2D:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
         case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
         case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             break;
         default:
             return ErrorMessage("texImage2D: unsupported target");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        if (argBorder != 0) {
-            return ErrorMessage("texImage2D: non-zero border given");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        switch (argInternalFormat) {
+    }
+
+    if (level < 0)
+        return ErrorMessage("texImage2D: level must be >= 0");
+
+    switch (internalformat) {
         case LOCAL_GL_RGB:
         case LOCAL_GL_RGBA:
         case LOCAL_GL_ALPHA:
         case LOCAL_GL_LUMINANCE:
         case LOCAL_GL_LUMINANCE_ALPHA:
             break;
         default:
             return ErrorMessage("texImage2D: internal format not supported");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        PRUint32 bufferType, bufferSize;
-        switch (argFormat) {
+    }
+
+    if (width <= 0 || height <= 0)
+        return ErrorMessage("texImage2D: width and height must be > 0!");
+
+    if (border != 0)
+        return ErrorMessage("texImage2D: border must be 0");
+
+    // number of bytes per pixel
+    uint32 bufferPixelSize = 0;
+    switch (format) {
         case LOCAL_GL_RED:
         case LOCAL_GL_GREEN:
         case LOCAL_GL_BLUE:
         case LOCAL_GL_ALPHA:
         case LOCAL_GL_LUMINANCE:
-            bufferSize = 1;
+            bufferPixelSize = 1;
             break;
         case LOCAL_GL_LUMINANCE_ALPHA:
-            bufferSize = 2;
+            bufferPixelSize = 2;
             break;
         case LOCAL_GL_RGB:
-            bufferSize = 3;
+            bufferPixelSize = 3;
             break;
         case LOCAL_GL_RGBA:
-            bufferSize = 4;
+            bufferPixelSize = 4;
             break;
         default:
             return ErrorMessage("texImage2D: pixel format not supported");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        switch (argType) {
+    }
+
+    switch (type) {
+        case LOCAL_GL_BYTE:
+        case LOCAL_GL_UNSIGNED_BYTE:
+            break;
         case LOCAL_GL_SHORT:
         case LOCAL_GL_UNSIGNED_SHORT:
-        case LOCAL_GL_BYTE:
-        case LOCAL_GL_UNSIGNED_BYTE:
+            bufferPixelSize *= 2;
+            break;
         case LOCAL_GL_INT:
         case LOCAL_GL_UNSIGNED_INT:
         case LOCAL_GL_FLOAT:
-            bufferType = argType;
+            bufferPixelSize *= 4;
             break;
         case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
         case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
         case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
-            bufferType = LOCAL_GL_UNSIGNED_SHORT;
+            bufferPixelSize *= 2;
+            break;
+        default:
+            return ErrorMessage("texImage2D: invalid type argument");
+    }
+
+    // XXX overflow!
+    uint32 bytesNeeded = width * height * bufferPixelSize;
+
+    if (byteLength && byteLength < bytesNeeded)
+        return ErrorMessage("texImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
+
+    MakeContextCurrent();
+
+    if (byteLength) {
+        gl->fTexImage2D(target, level, internalformat, width, height, border, format, type, data);
+    } else {
+        gl->fTexImage2D(target, level, internalformat, width, height, border, format, type, NULL);
+    }
+
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+WebGLContext::TexImage2D_buf(GLenum target, GLint level, GLenum internalformat,
+                             GLsizei width, GLsizei height, GLint border,
+                             GLenum format, GLenum type,
+                             js::ArrayBuffer *pixels)
+{
+    return TexImage2D_base(target, level, internalformat, width, height, border, format, type,
+                           pixels ? pixels->data : 0,
+                           pixels ? pixels->byteLength : 0);
+}
+
+NS_IMETHODIMP
+WebGLContext::TexImage2D_array(GLenum target, GLint level, GLenum internalformat,
+                               GLsizei width, GLsizei height, GLint border,
+                               GLenum format, GLenum type,
+                               js::TypedArray *pixels)
+{
+    return TexImage2D_base(target, level, internalformat, width, height, border, format, type,
+                           pixels ? pixels->data : 0,
+                           pixels ? pixels->byteLength : 0);
+}
+
+NS_IMETHODIMP
+WebGLContext::TexImage2D_dom(GLenum target, GLint level,
+                             nsIDOMElement *elt,
+                             GLboolean flipY, GLboolean premultiplyAlpha)
+{
+    nsRefPtr<gfxImageSurface> isurf;
+
+    nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf),
+                                           flipY, premultiplyAlpha);
+    if (NS_FAILED(rv))
+        return rv;
+
+    return TexImage2D_base(target, level, LOCAL_GL_RGBA,
+                           isurf->Width(), isurf->Height(), 0,
+                           LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
+                           isurf->Data(), isurf->Stride() * isurf->Height());
+}
+
+NS_IMETHODIMP
+WebGLContext::TexSubImage2D(PRInt32 dummy)
+{
+    return NS_ERROR_FAILURE;
+}
+
+nsresult
+WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
+                                 GLint xoffset, GLint yoffset,
+                                 GLsizei width, GLsizei height,
+                                 GLenum format, GLenum type,
+                                 void *pixels, PRUint32 byteLength)
+{
+    switch (target) {
+        case LOCAL_GL_TEXTURE_2D:
+        case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+        case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+        case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+        case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+        case LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+        case LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
             break;
         default:
-            return ErrorMessage("texImage2D: pixel packing not supported");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        // make sure the size is valid
-        PRInt32 tmp = argWidth * argHeight;
-        if (tmp && tmp / argHeight != argWidth) {
-            return ErrorMessage("texImage2D: too large width or height");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        tmp = tmp * bufferSize;
-        if (tmp && tmp / bufferSize != (argWidth * argHeight)) {
-            return ErrorMessage("texImage2D: too large width or height (after multiplying with pixel size)");
-            return NS_ERROR_DOM_SYNTAX_ERR;
-        }
-
-        // XXX handle LOCAL_GL_UNPACK_ALIGNMENT !
-
-        if (argPixelsObj == NULL) {
-            MakeContextCurrent();
-            gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, NULL);
-        } else {
-            nsCOMPtr<nsIWebGLArray> arrayObj;
-            nsresult rv;
-            rv = nsContentUtils::XPConnect()->WrapJS(js.ctx, argPixelsObj, NS_GET_IID(nsISupports), getter_AddRefs(arrayObj));
-            arrayObj = do_QueryInterface(arrayObj, &rv);
-
-            if (NS_FAILED(rv) || !arrayObj) {
-                return ErrorMessage("texImage2D: pixels arg is not a WebGL array");
-            }
-
-            if ((PRUint32) tmp > arrayObj->NativeSize()) {
-                return ErrorMessage("texImage2D: array dimensions too small for width, height and pixel format");
-                return NS_ERROR_DOM_SYNTAX_ERR;
-            }
-
-            MakeContextCurrent();
-            gl->fTexImage2D (argTarget, argLevel, argInternalFormat, argWidth, argHeight, argBorder, argFormat, argType, arrayObj->NativePointer());
-        }
+            return ErrorMessage("texSubImage2D: unsupported target");
+    }
+
+    if (level < 0)
+        return ErrorMessage("texSubImage2D: level must be >= 0");
+
+    if (width <= 0 || height <= 0)
+        return ErrorMessage("texSubImage2D: width and height must be > 0!");
+
+    // number of bytes per pixel
+    uint32 bufferPixelSize = 0;
+    switch (format) {
+        case LOCAL_GL_RED:
+        case LOCAL_GL_GREEN:
+        case LOCAL_GL_BLUE:
+        case LOCAL_GL_ALPHA:
+        case LOCAL_GL_LUMINANCE:
+            bufferPixelSize = 1;
+            break;
+        case LOCAL_GL_LUMINANCE_ALPHA:
+            bufferPixelSize = 2;
+            break;
+        case LOCAL_GL_RGB:
+            bufferPixelSize = 3;
+            break;
+        case LOCAL_GL_RGBA:
+            bufferPixelSize = 4;
+            break;
+        default:
+            return ErrorMessage("texImage2D: pixel format not supported");
+    }
+
+    switch (type) {
+        case LOCAL_GL_BYTE:
+        case LOCAL_GL_UNSIGNED_BYTE:
+            break;
+        case LOCAL_GL_SHORT:
+        case LOCAL_GL_UNSIGNED_SHORT:
+            bufferPixelSize *= 2;
+            break;
+        case LOCAL_GL_INT:
+        case LOCAL_GL_UNSIGNED_INT:
+        case LOCAL_GL_FLOAT:
+            bufferPixelSize *= 4;
+            break;
+        case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
+        case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
+        case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
+            bufferPixelSize *= 2;
+            break;
+        default:
+            return ErrorMessage("texImage2D: invalid type argument");
     }
+
+    // XXX overflow!
+    uint32 bytesNeeded = width * height * bufferPixelSize;
+
+    if (byteLength < bytesNeeded)
+        return ErrorMessage("texSubImage2D: not enough data for operation (need %d, have %d)", bytesNeeded, byteLength);
+
+    MakeContextCurrent();
+
+    gl->fTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+
     return NS_OK;
 }
 
+NS_IMETHODIMP
+WebGLContext::TexSubImage2D_buf(GLenum target, GLint level,
+                                GLint xoffset, GLint yoffset,
+                                GLsizei width, GLsizei height,
+                                GLenum format, GLenum type,
+                                js::ArrayBuffer *pixels)
+{
+    if (!pixels)
+        return ErrorMessage("texSubImage2D: pixels must not be null!");
+
+    return TexSubImage2D_base(target, level, xoffset, yoffset,
+                              width, height, format, type,
+                              pixels->data, pixels->byteLength);
+}
+
+NS_IMETHODIMP
+WebGLContext::TexSubImage2D_array(GLenum target, GLint level,
+                                  GLint xoffset, GLint yoffset,
+                                  GLsizei width, GLsizei height,
+                                  GLenum format, GLenum type,
+                                  js::TypedArray *pixels)
+{
+    if (!pixels)
+        return ErrorMessage("texSubImage2D: pixels must not be null!");
+
+    return TexSubImage2D_base(target, level, xoffset, yoffset,
+                              width, height, format, type,
+                              pixels->data, pixels->byteLength);
+}
+
+NS_IMETHODIMP
+WebGLContext::TexSubImage2D_dom(GLenum target, GLint level,
+                                GLint xoffset, GLint yoffset,
+                                GLsizei width, GLsizei height,
+                                nsIDOMElement *elt,
+                                GLboolean flipY, GLboolean premultiplyAlpha)
+{
+    nsRefPtr<gfxImageSurface> isurf;
+
+    nsresult rv = DOMElementToImageSurface(elt, getter_AddRefs(isurf),
+                                           flipY, premultiplyAlpha);
+    if (NS_FAILED(rv))
+        return rv;
+
+    return TexSubImage2D_base(target, level,
+                              xoffset, yoffset,
+                              width, height,
+                              LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE,
+                              isurf->Data(), isurf->Stride() * isurf->Height());
+}
+
 #if 0
 // ImageData getImageData (in float x, in float y, in float width, in float height);
 NS_IMETHODIMP
 WebGLContext::GetImageData(PRUint32 x, PRUint32 y, PRUint32 w, PRUint32 h)
 {
     // disabled due to win32 linkage issues with thebes symbols and NS_RELEASE
     return NS_ERROR_FAILURE;
 
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -76,24 +76,24 @@ WebGLContext::ValidateBuffers(PRUint32 c
     }
     PRUint32 maxAttribs = numAttributes;
 
     for (PRUint32 i = 0; i < maxAttribs; ++i) {
       WebGLVertexAttribData& vd = mAttribBuffers[i];
 
       // is this a problem?
       if (!vd.enabled)
-	continue;
+          continue;
 
       if (vd.buf == nsnull) {
-	LogMessage("No VBO bound to index %d (or it's been deleted)!", i);
-	return PR_FALSE;
+          LogMessage("No VBO bound to index %d (or it's been deleted)!", i);
+          return PR_FALSE;
       }
 
       GLuint needed = vd.offset + (vd.stride ? vd.stride : vd.size) * count;
-      if (vd.buf->Count() < needed) {
-	LogMessage("VBO too small for bound attrib index %d: need at least %d elements, but have only %d", i, needed, vd.buf->Count());
-	return PR_FALSE;
+      if (vd.buf->ByteLength() < needed) {
+          LogMessage("VBO too small for bound attrib index %d: need at least %d bytes, but have only %d", i, needed, vd.buf->ByteLength());
+          return PR_FALSE;
       }
     }
 
     return PR_TRUE;
 }
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -964,36 +964,42 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOU
 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsEventStateManager, nsIEventStateManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEventStateManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCurrentTargetContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastMouseOverElement);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGestureDownContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGestureDownFrameOwner);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastLeftMouseDownContent);
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastLeftMouseDownContentParent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastMiddleMouseDownContent);
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastMiddleMouseDownContentParent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastRightMouseDownContent);
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLastRightMouseDownContentParent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mActiveContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mHoverContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDragOverContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mURLTargetContent);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstMouseOverEventElement);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFirstMouseOutEventElement);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mAccessKeys);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsEventStateManager)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCurrentTargetContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastMouseOverElement);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGestureDownContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGestureDownFrameOwner);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastLeftMouseDownContent);
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastLeftMouseDownContentParent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastMiddleMouseDownContent);
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastMiddleMouseDownContentParent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastRightMouseDownContent);
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLastRightMouseDownContentParent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mActiveContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mHoverContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDragOverContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mURLTargetContent);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstMouseOverEventElement);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFirstMouseOutEventElement);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument);
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mAccessKeys);
@@ -3716,64 +3722,82 @@ nsEventStateManager::UpdateDragDataTrans
       // retrieve the current moz cursor setting and save it.
       nsAutoString mozCursor;
       eventTransferNS->GetMozCursor(mozCursor);
       initialDataTransferNS->SetMozCursor(mozCursor);
     }
   }
 }
 
+nsIContent* GetParentContentForMouseTarget(nsIContent* aContent)
+{
+  return aContent && aContent->IsInNativeAnonymousSubtree() ?
+           aContent->GetParent() : nsnull;
+}
+
 nsresult
 nsEventStateManager::SetClickCount(nsPresContext* aPresContext,
                                    nsMouseEvent *aEvent,
                                    nsEventStatus* aStatus)
 {
   nsCOMPtr<nsIContent> mouseContent;
   mCurrentTarget->GetContentForEvent(aPresContext, aEvent, getter_AddRefs(mouseContent));
 
   switch (aEvent->button) {
   case nsMouseEvent::eLeftButton:
     if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
       mLastLeftMouseDownContent = mouseContent;
+      mLastLeftMouseDownContentParent =
+        GetParentContentForMouseTarget(mouseContent);
     } else if (aEvent->message == NS_MOUSE_BUTTON_UP) {
-      if (mLastLeftMouseDownContent == mouseContent) {
+      if (mLastLeftMouseDownContent == mouseContent ||
+          mLastLeftMouseDownContentParent == mouseContent) {
         aEvent->clickCount = mLClickCount;
         mLClickCount = 0;
       } else {
         aEvent->clickCount = 0;
       }
       mLastLeftMouseDownContent = nsnull;
+      mLastLeftMouseDownContentParent = nsnull;
     }
     break;
 
   case nsMouseEvent::eMiddleButton:
     if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
       mLastMiddleMouseDownContent = mouseContent;
+      mLastMiddleMouseDownContentParent =
+        GetParentContentForMouseTarget(mouseContent);
     } else if (aEvent->message == NS_MOUSE_BUTTON_UP) {
-      if (mLastMiddleMouseDownContent == mouseContent) {
+      if (mLastMiddleMouseDownContent == mouseContent ||
+          mLastMiddleMouseDownContentParent == mouseContent) {
         aEvent->clickCount = mMClickCount;
         mMClickCount = 0;
       } else {
         aEvent->clickCount = 0;
       }
-      // XXX Why we don't clear mLastMiddleMouseDownContent here?
+      mLastMiddleMouseDownContent = nsnull;
+      mLastMiddleMouseDownContentParent = nsnull;
     }
     break;
 
   case nsMouseEvent::eRightButton:
     if (aEvent->message == NS_MOUSE_BUTTON_DOWN) {
       mLastRightMouseDownContent = mouseContent;
+      mLastRightMouseDownContentParent =
+        GetParentContentForMouseTarget(mouseContent);
     } else if (aEvent->message == NS_MOUSE_BUTTON_UP) {
-      if (mLastRightMouseDownContent == mouseContent) {
+      if (mLastRightMouseDownContent == mouseContent ||
+          mLastRightMouseDownContentParent == mouseContent) {
         aEvent->clickCount = mRClickCount;
         mRClickCount = 0;
       } else {
         aEvent->clickCount = 0;
       }
-      // XXX Why we don't clear mLastRightMouseDownContent here?
+      mLastRightMouseDownContent = nsnull;
+      mLastRightMouseDownContentParent = nsnull;
     }
     break;
   }
 
   return NS_OK;
 }
 
 nsresult
--- a/content/events/src/nsEventStateManager.h
+++ b/content/events/src/nsEventStateManager.h
@@ -355,18 +355,21 @@ protected:
   nsCOMPtr<nsIContent> mGestureDownFrameOwner;
   // State of keys when the original gesture-down happened
   PRPackedBool mGestureDownShift;
   PRPackedBool mGestureDownControl;
   PRPackedBool mGestureDownAlt;
   PRPackedBool mGestureDownMeta;
 
   nsCOMPtr<nsIContent> mLastLeftMouseDownContent;
+  nsCOMPtr<nsIContent> mLastLeftMouseDownContentParent;
   nsCOMPtr<nsIContent> mLastMiddleMouseDownContent;
+  nsCOMPtr<nsIContent> mLastMiddleMouseDownContentParent;
   nsCOMPtr<nsIContent> mLastRightMouseDownContent;
+  nsCOMPtr<nsIContent> mLastRightMouseDownContentParent;
 
   nsCOMPtr<nsIContent> mActiveContent;
   nsCOMPtr<nsIContent> mHoverContent;
   nsCOMPtr<nsIContent> mDragOverContent;
   nsCOMPtr<nsIContent> mURLTargetContent;
 
   // The last element on which we fired a mouseover event, or null if
   // the last mouseover event we fired has finished processing.
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -77,16 +77,17 @@ include $(topsrcdir)/config/rules.mk
 		bug457672.html \
 		test_draggableprop.html \
 		test_dragstart.html \
 		test_bug489671.html \
 		test_bug493251.html \
 		test_bug502818.html \
 		test_bug508479.html \
 		test_bug517851.html \
+		test_bug534833.html \
 		$(NULL)
 
 _CHROME_FILES = \
 		test_bug415498.xul \
 		bug415498-doc1.html \
 		bug415498-doc2.html \
 		$(NULL)
 
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_bug534833.html
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=534833
+-->
+<head>
+  <title>Test for Bug 534833</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="runTests()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=534833">Mozilla Bug 534833</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 534833 **/
+SimpleTest.waitForExplicitFinish();
+
+var input1GotClick = 0;
+var input2GotClick = 0;
+var textarea1GotClick = 0;
+var textarea2GotClick = 0;
+var div1GotClick = 0;
+var div2GotClick = 0;
+
+var tests = [ { element: "text",  clickText: true  },
+              { element: "text2", clickText: false },
+              { element: "area",  clickText: true  },
+              { element: "area2", clickText: false  },
+              { element: "d",     clickText: true  },
+              { element: "d",     clickText: false },
+              { element: "d2",    clickText: true  },
+              { element: "d2",    clickText: false }
+             ];
+
+function nextTest_() {
+  if (!tests.length) {
+    finishTests();
+    return;
+  }
+
+  var test = tests.shift();
+  var el = document.getElementById(test.element);
+  el.scrollIntoView(true);
+  if (test.clickText) {
+    synthesizeMouse(el, 5, 5, {type : "mousedown" });
+    synthesizeMouse(el, 5, 5, {type : "mouseup" });
+  } else {
+    synthesizeMouse(el, el.getBoundingClientRect().width - 5, 5, {type : "mousedown" });
+    synthesizeMouse(el, el.getBoundingClientRect().width - 5, 5, {type : "mouseup" });
+  }
+  nextTest();
+}
+
+function nextTest() {
+  document.getElementById("initialfocus").focus();
+  setTimeout(nextTest_, 100);
+}
+
+function runTests() {
+  var t = document.getElementById("text");
+  var t2 = document.getElementById("text2");
+  var a = document.getElementById("area");
+  var a2 = document.getElementById("area2");
+  var d = document.getElementById("d");
+  var d2 = document.getElementById("d2");
+
+  // input 1
+  t.onfocus = function(e) {
+    t.value = "";
+  }
+  t.onclick = function(e) {
+    ++input1GotClick;
+  }
+
+  // input 2
+  t2.onfocus = function(e) {
+    t2.value = "";
+  }
+  t2.onclick = function(e) {
+    ++input2GotClick;
+  }
+
+  // textarea 1
+  a.onfocus = function(e) {
+    a.value = "";
+  }
+  a.onclick = function(e) {
+    ++textarea1GotClick;
+  }
+
+  // textarea 2
+  a2.onfocus = function(e) {
+    a2.value = "";
+  }
+  a2.onclick = function(e) {
+    ++textarea2GotClick;
+  }
+
+  // div 1
+  var c = 0;
+  d.onmousedown = function(e) {
+    d.textContent = (++c) + " / click before or after |";
+  }
+  d.onclick = function(e) {
+    ++div1GotClick;
+  }
+
+  // div 2
+  var c2 = 0;
+  d2.onmousedown = function(e) {
+    d2.firstChild.data = (++c2) + " / click before or after |";
+  }
+  d2.onclick = function(e) {
+    ++div2GotClick;
+  }
+  nextTest();
+}
+
+function finishTests() {
+  is(input1GotClick, 1, "input element should have got a click!");
+  is(input2GotClick, 1, "input element should have got a click! (2)");
+  is(textarea1GotClick, 1, "textarea element should have got a click!");
+  is(textarea2GotClick, 1, "textarea element should have got a click! (2)");
+  is(div1GotClick, 1, "div element's content text was replaced, it should have got 1 click!");
+  is(div2GotClick, 2, "div element's content text was modified, it should have got 2 clicks!");
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+<input type="text" id="initialfocus"><br>
+<input type="text" id="text" value="click before |" style="width: 95%;"><br>
+<input type="text" id="text2" value="click after |" style="width: 95%;">
+<br>
+<textarea id="area" rows="2" style="width: 95%;">
+ click before
+            |
+</textarea><br>
+<textarea id="area2" rows="2" style="width: 95%;">
+ click after |
+</textarea>
+<div id="d" style="border: 1px solid black;">click before or after |</div>
+<div id="d2" style="border: 1px solid black;">click before or after |</div>
+</body>
+</html>
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -592,16 +592,22 @@ nsHTMLDocument::TryDefaultCharset( nsIMa
   }
   return PR_FALSE;
 }
 
 void
 nsHTMLDocument::StartAutodetection(nsIDocShell *aDocShell, nsACString& aCharset,
                                    const char* aCommand)
 {
+  if (mIsRegularHTML && 
+      nsHtml5Module::sEnabled && 
+      aCommand && 
+      !nsCRT::strcmp(aCommand, "view")) {
+    return; // the HTML5 parser uses chardet directly
+  }
   nsCOMPtr <nsIParserFilter> cdetflt;
 
   nsresult rv_detect;
   if(!gInitDetector) {
     const nsAdoptingString& detector_name =
       nsContentUtils::GetLocalizedStringPref("intl.charset.detector");
 
     if(!detector_name.IsEmpty()) {
@@ -764,20 +770,18 @@ nsHTMLDocument::StartDocumentLoad(const 
   }
 
   nsCOMPtr<nsIDocShell> parent(do_QueryInterface(parentAsItem));
   nsCOMPtr<nsIDocument> parentDocument;
   nsCOMPtr<nsIContentViewer> parentContentViewer;
   if (parent) {
     rv = parent->GetContentViewer(getter_AddRefs(parentContentViewer));
     NS_ENSURE_SUCCESS(rv, rv);
-    nsCOMPtr<nsIDocumentViewer> docViewer =
-      do_QueryInterface(parentContentViewer);
-    if (docViewer) {
-      docViewer->GetDocument(getter_AddRefs(parentDocument));
+    if (parentContentViewer) {
+      parentDocument = parentContentViewer->GetDocument();
     }
   }
 
   //
   // The following logic is mirrored in nsWebShell::Embed!
   //
   nsCOMPtr<nsIMarkupDocumentViewer> muCV;
   PRBool muCVIsParent = PR_FALSE;
--- a/content/html/document/test/test_bug324378.html
+++ b/content/html/document/test/test_bug324378.html
@@ -62,16 +62,17 @@ https://bugzilla.mozilla.org/show_bug.cg
   is($("d"), null, "Unexpected node with id=d");
   is($("e"), body, "Unexpected node with id=e");
   is($("f"), null, "Unexpected node with id=f");
   is($("g"), null, "Unexpected node with id=g");
   is($("j"), null, "Unexpected node with id=j");
   is($("m"), null, "Unexpected node with id=m");
 
   is(html.getAttribute("foo"), "h", "Unexpected 'foo' value on <html>");
-  is(head.getAttribute("foo"), "k", "Unexpected 'foo' value on <head>");
+  // The line below can be uncommented once the HTML5 parser is on by default
+  // is(head.getAttribute("foo"), null, "Unexpected 'foo' value on <head>");
   is(body.getAttribute("foo"), "n", "Unexpected 'foo' value on <body>");
 
 </script>
 </pre>
 </body>
 </html>
 
--- a/content/html/document/test/test_bug478251.html
+++ b/content/html/document/test/test_bug478251.html
@@ -43,17 +43,17 @@ is(doc.documentElement.textContent, "und
 doc.open();
 doc.write(undefined, undefined);
 doc.close();
 is(doc.documentElement.textContent, "undefinedundefined", "Writing |undefined, undefined| failed");
 
 doc.open();
 doc.writeln();
 doc.close();
-is(doc.documentElement.textContent, "\n", "Writing |\\n| failed");
+ok(doc.documentElement.textContent == "\n" || doc.documentElement.textContent == "", "Writing |\\n| failed");
 
 doc.open();
 doc.writeln(null);
 doc.close();
 is(doc.documentElement.textContent, "null\n", "Writing |null\\n| failed");
 
 doc.open();
 doc.writeln(null, null);
--- a/content/smil/Makefile.in
+++ b/content/smil/Makefile.in
@@ -65,16 +65,18 @@ CPPSRCS		+= \
 	nsSMILParserUtils.cpp \
 	nsSMILRepeatCount.cpp \
 	nsSMILSetAnimationFunction.cpp \
 	nsSMILTimeContainer.cpp \
 	nsSMILTimedElement.cpp \
 	nsSMILTimeValue.cpp \
 	nsSMILTimeValueSpec.cpp \
 	nsSMILValue.cpp \
+	SMILBoolType.cpp \
+	SMILEnumType.cpp \
 		$(NULL)
 endif
 
 include $(topsrcdir)/config/config.mk
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
new file mode 100644
--- /dev/null
+++ b/content/smil/SMILBoolType.cpp
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "SMILBoolType.h"
+#include "nsSMILValue.h"
+#include "nsDebug.h"
+#include <math.h>
+
+namespace mozilla {
+
+/*static*/ SMILBoolType SMILBoolType::sSingleton;
+
+nsresult
+SMILBoolType::Init(nsSMILValue& aValue) const
+{
+  NS_PRECONDITION(aValue.mType == this || aValue.IsNull(),
+                  "Unexpected value type");
+  aValue.mU.mBool = PR_FALSE;
+  aValue.mType = this;
+  return NS_OK;
+}
+
+void
+SMILBoolType::Destroy(nsSMILValue& aValue) const
+{
+  NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value.");
+  aValue.mU.mBool = PR_FALSE;
+  aValue.mType = &nsSMILNullType::sSingleton;
+}
+
+nsresult
+SMILBoolType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
+{
+  NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types.");
+  NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value.");
+  aDest.mU.mBool = aSrc.mU.mBool;
+  return NS_OK;
+}
+
+nsresult
+SMILBoolType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
+                  PRUint32 aCount) const
+{
+  NS_PRECONDITION(aValueToAdd.mType == aDest.mType,
+                  "Trying to add invalid types");
+  NS_PRECONDITION(aValueToAdd.mType == this, "Unexpected source type");
+  return NS_ERROR_FAILURE; // bool values can't be added to each other
+}
+
+nsresult
+SMILBoolType::ComputeDistance(const nsSMILValue& aFrom,
+                              const nsSMILValue& aTo,
+                              double& aDistance) const
+{
+  NS_PRECONDITION(aFrom.mType == aTo.mType,"Trying to compare different types");
+  NS_PRECONDITION(aFrom.mType == this, "Unexpected source type");
+  return NS_ERROR_FAILURE; // there is no concept of distance between bool values
+}
+
+nsresult
+SMILBoolType::Interpolate(const nsSMILValue& aStartVal,
+                          const nsSMILValue& aEndVal,
+                          double aUnitDistance,
+                          nsSMILValue& aResult) const
+{
+  NS_PRECONDITION(aStartVal.mType == aEndVal.mType,
+      "Trying to interpolate different types");
+  NS_PRECONDITION(aStartVal.mType == this,
+      "Unexpected types for interpolation.");
+  NS_PRECONDITION(aResult.mType   == this, "Unexpected result type.");
+  return NS_ERROR_FAILURE; // bool values do not interpolate
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/smil/SMILBoolType.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_SMILBOOLTYPE_H_
+#define MOZILLA_SMILBOOLTYPE_H_
+
+#include "nsISMILType.h"
+
+namespace mozilla {
+
+class SMILBoolType : public nsISMILType
+{
+public:
+  virtual nsresult Init(nsSMILValue& aValue) const;
+  virtual void     Destroy(nsSMILValue&) const;
+  virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
+  virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
+                       PRUint32 aCount) const;
+  virtual nsresult ComputeDistance(const nsSMILValue& aFrom,
+                                   const nsSMILValue& aTo,
+                                   double& aDistance) const;
+  virtual nsresult Interpolate(const nsSMILValue& aStartVal,
+                               const nsSMILValue& aEndVal,
+                               double aUnitDistance,
+                               nsSMILValue& aResult) const;
+
+  static SMILBoolType sSingleton;
+
+private:
+  SMILBoolType() {}
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_SMILBOOLTYPE_H_
new file mode 100644
--- /dev/null
+++ b/content/smil/SMILEnumType.cpp
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "SMILEnumType.h"
+#include "nsSMILValue.h"
+#include "nsDebug.h"
+#include <math.h>
+
+namespace mozilla {
+
+/*static*/ SMILEnumType SMILEnumType::sSingleton;
+
+nsresult
+SMILEnumType::Init(nsSMILValue& aValue) const
+{
+  NS_PRECONDITION(aValue.mType == this || aValue.IsNull(),
+    "Unexpected value type");
+  aValue.mU.mUint = 0;
+  aValue.mType = this;
+  return NS_OK;
+}
+
+void
+SMILEnumType::Destroy(nsSMILValue& aValue) const
+{
+  NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value.");
+  aValue.mU.mUint = 0;
+  aValue.mType = &nsSMILNullType::sSingleton;
+}
+
+nsresult
+SMILEnumType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
+{
+  NS_PRECONDITION(aDest.mType == aSrc.mType, "Incompatible SMIL types.");
+  NS_PRECONDITION(aDest.mType == this, "Unexpected SMIL value.");
+  aDest.mU.mUint = aSrc.mU.mUint;
+  return NS_OK;
+}
+
+nsresult
+SMILEnumType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
+                  PRUint32 aCount) const
+{
+  NS_PRECONDITION(aValueToAdd.mType == aDest.mType,
+                  "Trying to add invalid types");
+  NS_PRECONDITION(aValueToAdd.mType == this, "Unexpected source type");
+  return NS_ERROR_FAILURE; // enum values can't be added to each other
+}
+
+nsresult
+SMILEnumType::ComputeDistance(const nsSMILValue& aFrom,
+                              const nsSMILValue& aTo,
+                              double& aDistance) const
+{
+  NS_PRECONDITION(aFrom.mType == aTo.mType,"Trying to compare different types");
+  NS_PRECONDITION(aFrom.mType == this, "Unexpected source type");
+  return NS_ERROR_FAILURE; // there is no concept of distance between enum values
+}
+
+nsresult
+SMILEnumType::Interpolate(const nsSMILValue& aStartVal,
+                          const nsSMILValue& aEndVal,
+                          double aUnitDistance,
+                          nsSMILValue& aResult) const
+{
+  NS_PRECONDITION(aStartVal.mType == aEndVal.mType,
+      "Trying to interpolate different types");
+  NS_PRECONDITION(aStartVal.mType == this,
+      "Unexpected types for interpolation.");
+  NS_PRECONDITION(aResult.mType   == this, "Unexpected result type.");
+  return NS_ERROR_FAILURE; // enum values do not interpolate
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/content/smil/SMILEnumType.h
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Mozilla SVG project.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef MOZILLA_SMILENUMTYPE_H_
+#define MOZILLA_SMILENUMTYPE_H_
+
+#include "nsISMILType.h"
+
+namespace mozilla {
+
+class SMILEnumType : public nsISMILType
+{
+public:
+  virtual nsresult Init(nsSMILValue& aValue) const;
+  virtual void     Destroy(nsSMILValue&) const;
+  virtual nsresult Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const;
+  virtual nsresult Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
+                       PRUint32 aCount) const;
+  virtual nsresult ComputeDistance(const nsSMILValue& aFrom,
+                                   const nsSMILValue& aTo,
+                                   double& aDistance) const;
+  virtual nsresult Interpolate(const nsSMILValue& aStartVal,
+                               const nsSMILValue& aEndVal,
+                               double aUnitDistance,
+                               nsSMILValue& aResult) const;
+
+  static SMILEnumType sSingleton;
+
+private:
+  SMILEnumType() {}
+};
+
+} // namespace mozilla
+
+#endif // MOZILLA_SMILENUMTYPE_H_
--- a/content/smil/nsSMILValue.h
+++ b/content/smil/nsSMILValue.h
@@ -64,16 +64,18 @@ public:
   nsresult Add(const nsSMILValue& aValueToAdd, PRUint32 aCount = 1);
   nsresult SandwichAdd(const nsSMILValue& aValueToAdd);
   nsresult ComputeDistance(const nsSMILValue& aTo, double& aDistance) const;
   nsresult Interpolate(const nsSMILValue& aEndVal,
                        double aUnitDistance,
                        nsSMILValue& aResult) const;
 
   union {
+    PRBool mBool;
+    PRUint64 mUint;
     PRInt64 mInt;
     double mDouble;
     void* mPtr;
   } mU;
   const nsISMILType* mType;
 };
 
 #endif  // NS_SMILVALUE_H_
--- a/content/svg/content/src/nsSVGBoolean.cpp
+++ b/content/svg/content/src/nsSVGBoolean.cpp
@@ -30,16 +30,22 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSVGBoolean.h"
+#ifdef MOZ_SMIL
+#include "nsSMILValue.h"
+#include "SMILBoolType.h"
+#endif // MOZ_SMIL
+
+using namespace mozilla;
 
 NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGBoolean::DOMAnimatedBoolean, mSVGElement)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGBoolean::DOMAnimatedBoolean)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGBoolean::DOMAnimatedBoolean)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGBoolean::DOMAnimatedBoolean)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedBoolean)
@@ -59,16 +65,21 @@ nsSVGBoolean::SetBaseValueString(const n
   if (aValueAsString.EqualsLiteral("true"))
     val = PR_TRUE;
   else if (aValueAsString.EqualsLiteral("false"))
     val = PR_FALSE;
   else
     return NS_ERROR_DOM_SYNTAX_ERR;
 
   mBaseVal = mAnimVal = val;
+#ifdef MOZ_SMIL
+  if (mIsAnimated) {
+    aSVGElement->AnimationNeedsResample();
+  }
+#endif
   return NS_OK;
 }
 
 void
 nsSVGBoolean::GetBaseValueString(nsAString & aValueAsString)
 {
   aValueAsString.Assign(mBaseVal
                         ? NS_LITERAL_STRING("true")
@@ -76,23 +87,92 @@ nsSVGBoolean::GetBaseValueString(nsAStri
 }
 
 void
 nsSVGBoolean::SetBaseValue(PRBool aValue,
                            nsSVGElement *aSVGElement)
 {
   NS_PRECONDITION(aValue == PR_TRUE || aValue == PR_FALSE, "Boolean out of range");
 
-  mAnimVal = mBaseVal = aValue;
-  aSVGElement->DidChangeBoolean(mAttrEnum, PR_TRUE);
+  if (aValue != mBaseVal) {
+    mAnimVal = mBaseVal = aValue;
+    aSVGElement->DidChangeBoolean(mAttrEnum, PR_TRUE);
+#ifdef MOZ_SMIL
+    if (mIsAnimated) {
+      aSVGElement->AnimationNeedsResample();
+    }
+#endif
+  }
+}
+
+void
+nsSVGBoolean::SetAnimValue(PRBool aValue, nsSVGElement *aSVGElement)
+{
+  mAnimVal = aValue;
+  mIsAnimated = PR_TRUE;
+  aSVGElement->DidAnimateBoolean(mAttrEnum);
 }
 
 nsresult
 nsSVGBoolean::ToDOMAnimatedBoolean(nsIDOMSVGAnimatedBoolean **aResult,
                                    nsSVGElement *aSVGElement)
 {
   *aResult = new DOMAnimatedBoolean(this, aSVGElement);
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult);
   return NS_OK;
 }
+
+#ifdef MOZ_SMIL
+nsISMILAttr*
+nsSVGBoolean::ToSMILAttr(nsSVGElement *aSVGElement)
+{
+  return new SMILBool(this, aSVGElement);
+}
+
+nsresult
+nsSVGBoolean::SMILBool::ValueFromString(const nsAString& aStr,
+                                        const nsISMILAnimationElement* /*aSrcElement*/,
+                                        nsSMILValue& aValue) const
+{
+  nsSMILValue val(&SMILBoolType::sSingleton);
+
+  if (aStr.EqualsLiteral("true"))
+    val.mU.mBool = PR_TRUE;
+  else if (aStr.EqualsLiteral("false"))
+    val.mU.mBool = PR_FALSE;
+  else
+    return NS_ERROR_FAILURE;
+
+  aValue = val;
+  return NS_OK;
+}
+
+nsSMILValue
+nsSVGBoolean::SMILBool::GetBaseValue() const
+{
+  nsSMILValue val(&SMILBoolType::sSingleton);
+  val.mU.mBool = mVal->mBaseVal;
+  return val;
+}
+
+void
+nsSVGBoolean::SMILBool::ClearAnimValue()
+{
+  if (mVal->mIsAnimated) {
+    mVal->SetAnimValue(mVal->mBaseVal, mSVGElement);
+    mVal->mIsAnimated = PR_FALSE;
+  }
+}
+
+nsresult
+nsSVGBoolean::SMILBool::SetAnimValue(const nsSMILValue& aValue)
+{
+  NS_ASSERTION(aValue.mType == &SMILBoolType::sSingleton,
+               "Unexpected type to assign animated value");
+  if (aValue.mType == &SMILBoolType::sSingleton) {
+    mVal->SetAnimValue(PRUint16(aValue.mU.mBool), mSVGElement);
+  }
+  return NS_OK;
+}
+#endif // MOZ_SMIL
--- a/content/svg/content/src/nsSVGBoolean.h
+++ b/content/svg/content/src/nsSVGBoolean.h
@@ -43,36 +43,49 @@
 
 class nsSVGBoolean
 {
 
 public:
   void Init(PRUint8 aAttrEnum = 0xff, PRBool aValue = PR_FALSE) {
     mAnimVal = mBaseVal = aValue;
     mAttrEnum = aAttrEnum;
+    mIsAnimated = PR_FALSE;
   }
 
   nsresult SetBaseValueString(const nsAString& aValue,
                               nsSVGElement *aSVGElement,
                               PRBool aDoSetAttr);
   void GetBaseValueString(nsAString& aValue);
 
   void SetBaseValue(PRBool aValue, nsSVGElement *aSVGElement);
   PRBool GetBaseValue() const
     { return mBaseVal; }
-  PRBool GetAnimValue() const
-    { return mAnimVal; }
+
+  void SetAnimValue(PRBool aValue, nsSVGElement *aSVGElement);
+  PRBool GetAnimValue(nsSVGElement *aSVGElement) const
+  {
+  #ifdef MOZ_SMIL
+    aSVGElement->FlushAnimations();
+  #endif
+    return mAnimVal;
+  }
 
   nsresult ToDOMAnimatedBoolean(nsIDOMSVGAnimatedBoolean **aResult,
                                 nsSVGElement* aSVGElement);
+#ifdef MOZ_SMIL
+  // Returns a new nsISMILAttr object that the caller must delete
+  nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement);
+#endif // MOZ_SMIL
 
 private:
 
   PRPackedBool mAnimVal;
   PRPackedBool mBaseVal;
+  PRPackedBool mIsAnimated;
   PRUint8 mAttrEnum; // element specified tracking for attribute
 
   struct DOMAnimatedBoolean : public nsIDOMSVGAnimatedBoolean
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedBoolean)
 
     DOMAnimatedBoolean(nsSVGBoolean* aVal, nsSVGElement *aSVGElement)
@@ -81,14 +94,36 @@ private:
     nsSVGBoolean* mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(PRBool* aResult)
       { *aResult = mVal->GetBaseValue(); return NS_OK; }
     NS_IMETHOD SetBaseVal(PRBool aValue)
       { mVal->SetBaseValue(aValue, mSVGElement); return NS_OK; }
     NS_IMETHOD GetAnimVal(PRBool* aResult)
-      { *aResult = mVal->GetAnimValue(); return NS_OK; }
+      { *aResult = mVal->GetAnimValue(mSVGElement); return NS_OK; }
 
   };
 
+#ifdef MOZ_SMIL
+  struct SMILBool : public nsISMILAttr
+  {
+  public:
+    SMILBool(nsSVGBoolean* aVal, nsSVGElement* aSVGElement)
+      : mVal(aVal), mSVGElement(aSVGElement) {}
+    
+    // These will stay alive because a nsISMILAttr only lives as long
+    // as the Compositing step, and DOM elements don't get a chance to
+    // die during that.
+    nsSVGBoolean* mVal;
+    nsSVGElement* mSVGElement;
+    
+    // nsISMILAttr methods
+    virtual nsresult ValueFromString(const nsAString& aStr,
+                                     const nsISMILAnimationElement* aSrcElement,
+                                     nsSMILValue& aValue) const;
+    virtual nsSMILValue GetBaseValue() const;
+    virtual void ClearAnimValue();
+    virtual nsresult SetAnimValue(const nsSMILValue& aValue);
+  };
+#endif // MOZ_SMIL
 };
 #endif //__NS_SVGBOOLEAN_H__
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -1417,16 +1417,29 @@ nsSVGElement::DidChangeBoolean(PRUint8 a
 
   nsAutoString newStr;
   info.mBooleans[aAttrEnum].GetBaseValueString(newStr);
 
   SetAttr(kNameSpaceID_None, *info.mBooleanInfo[aAttrEnum].mName,
           newStr, PR_TRUE);
 }
 
+void
+nsSVGElement::DidAnimateBoolean(PRUint8 aAttrEnum)
+{
+  nsIFrame* frame = GetPrimaryFrame();
+  
+  if (frame) {
+    BooleanAttributesInfo info = GetBooleanInfo();
+    frame->AttributeChanged(kNameSpaceID_None,
+                            *info.mBooleanInfo[aAttrEnum].mName,
+                            nsIDOMMutationEvent::MODIFICATION);
+  }
+}
+
 nsSVGElement::EnumAttributesInfo
 nsSVGElement::GetEnumInfo()
 {
   return EnumAttributesInfo(nsnull, nsnull, 0);
 }
 
 void nsSVGElement::EnumAttributesInfo::Reset(PRUint8 aAttrEnum)
 {
@@ -1449,16 +1462,29 @@ nsSVGElement::DidChangeEnum(PRUint8 aAtt
 
   nsAutoString newStr;
   info.mEnums[aAttrEnum].GetBaseValueString(newStr, this);
 
   SetAttr(kNameSpaceID_None, *info.mEnumInfo[aAttrEnum].mName,
           newStr, PR_TRUE);
 }
 
+void
+nsSVGElement::DidAnimateEnum(PRUint8 aAttrEnum)
+{
+  nsIFrame* frame = GetPrimaryFrame();
+
+  if (frame) {
+    EnumAttributesInfo info = GetEnumInfo();
+    frame->AttributeChanged(kNameSpaceID_None,
+                            *info.mEnumInfo[aAttrEnum].mName,
+                            nsIDOMMutationEvent::MODIFICATION);
+  }
+}
+
 nsSVGViewBox *
 nsSVGElement::GetViewBox()
 {
   return nsnull;
 }
 
 void
 nsSVGElement::DidChangeViewBox(PRBool aDoSetAttr)
@@ -1698,16 +1724,36 @@ nsSVGElement::GetAnimatedAttr(const nsIA
       // *above* this one at that time to catch those properties before we get
       // here. The separate properties should then point into the list.
       if (aName == *info.mNumberInfo[i].mName) {
         return info.mNumbers[i].ToSMILAttr(this);
       }
     }
   }
 
+  // Enumerations:
+  {
+    EnumAttributesInfo info = GetEnumInfo();
+    for (PRUint32 i = 0; i < info.mEnumCount; i++) {
+      if (aName == *info.mEnumInfo[i].mName) {
+        return info.mEnums[i].ToSMILAttr(this);
+      }
+    }
+  }
+
+  // Booleans:
+  {
+    BooleanAttributesInfo info = GetBooleanInfo();
+    for (PRUint32 i = 0; i < info.mBooleanCount; i++) {
+      if (aName == *info.mBooleanInfo[i].mName) {
+        return info.mBooleans[i].ToSMILAttr(this);
+      }
+    }
+  }
+
   return nsnull;
 }
 
 void
 nsSVGElement::AnimationNeedsResample()
 {
   nsIDocument* doc = GetCurrentDoc();
   if (doc) {
--- a/content/svg/content/src/nsSVGElement.h
+++ b/content/svg/content/src/nsSVGElement.h
@@ -152,16 +152,18 @@ public:
   virtual void DidChangeBoolean(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeEnum(PRUint8 aAttrEnum, PRBool aDoSetAttr);
   virtual void DidChangeViewBox(PRBool aDoSetAttr);
   virtual void DidChangePreserveAspectRatio(PRBool aDoSetAttr);
   virtual void DidChangeString(PRUint8 aAttrEnum) {}
 
   virtual void DidAnimateLength(PRUint8 aAttrEnum);
   virtual void DidAnimateNumber(PRUint8 aAttrEnum);
+  virtual void DidAnimateBoolean(PRUint8 aAttrEnum);
+  virtual void DidAnimateEnum(PRUint8 aAttrEnum);
 
   void GetAnimatedLengthValues(float *aFirst, ...);
   void GetAnimatedNumberValues(float *aFirst, ...);
   void GetAnimatedIntegerValues(PRInt32 *aFirst, ...);
 
 #ifdef MOZ_SMIL
   virtual nsISMILAttr* GetAnimatedAttr(const nsIAtom* aName);
   void AnimationNeedsResample();
--- a/content/svg/content/src/nsSVGEnum.cpp
+++ b/content/svg/content/src/nsSVGEnum.cpp
@@ -32,16 +32,22 @@
  * 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 "nsSVGEnum.h"
 #include "nsIAtom.h"
 #include "nsSVGElement.h"
+#ifdef MOZ_SMIL
+#include "nsSMILValue.h"
+#include "SMILEnumType.h"
+#endif // MOZ_SMIL
+
+using namespace mozilla;
 
 NS_SVG_VAL_IMPL_CYCLE_COLLECTION(nsSVGEnum::DOMAnimatedEnum, mSVGElement)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsSVGEnum::DOMAnimatedEnum)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsSVGEnum::DOMAnimatedEnum)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsSVGEnum::DOMAnimatedEnum)
   NS_INTERFACE_MAP_ENTRY(nsIDOMSVGAnimatedEnumeration)
@@ -62,67 +68,150 @@ nsSVGEnum::GetMapping(nsSVGElement *aSVG
 
 nsresult
 nsSVGEnum::SetBaseValueString(const nsAString& aValue,
                               nsSVGElement *aSVGElement,
                               PRBool aDoSetAttr)
 {
   nsCOMPtr<nsIAtom> valAtom = do_GetAtom(aValue);
 
-  nsSVGEnumMapping *tmp = GetMapping(aSVGElement);
+  nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
 
-  while (tmp && tmp->mKey) {
-    if (valAtom == *(tmp->mKey)) {
-      mBaseVal = mAnimVal = tmp->mVal;
+  while (mapping && mapping->mKey) {
+    if (valAtom == *(mapping->mKey)) {
+      if (mBaseVal != mapping->mVal) {
+        mBaseVal = mAnimVal = mapping->mVal;
+#ifdef MOZ_SMIL
+        if (mIsAnimated) {
+          aSVGElement->AnimationNeedsResample();
+        }
+#endif
+      }
       return NS_OK;
     }
-    tmp++;
+    mapping++;
   }
 
   // only a warning since authors may mistype attribute values
   NS_WARNING("unknown enumeration key");
   return NS_ERROR_DOM_SYNTAX_ERR;
 }
 
 void
 nsSVGEnum::GetBaseValueString(nsAString& aValue, nsSVGElement *aSVGElement)
 {
-  nsSVGEnumMapping *tmp = GetMapping(aSVGElement);
+  nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
 
-  while (tmp && tmp->mKey) {
-    if (mBaseVal == tmp->mVal) {
-      (*tmp->mKey)->ToString(aValue);
+  while (mapping && mapping->mKey) {
+    if (mBaseVal == mapping->mVal) {
+      (*mapping->mKey)->ToString(aValue);
       return;
     }
-    tmp++;
+    mapping++;
   }
   NS_ERROR("unknown enumeration value");
 }
 
 nsresult
 nsSVGEnum::SetBaseValue(PRUint16 aValue,
                         nsSVGElement *aSVGElement,
                         PRBool aDoSetAttr)
 {
-  nsSVGEnumMapping *tmp = GetMapping(aSVGElement);
+  nsSVGEnumMapping *mapping = GetMapping(aSVGElement);
 
-  while (tmp && tmp->mKey) {
-    if (tmp->mVal == aValue) {
-      mAnimVal = mBaseVal = PRUint8(aValue);
-      aSVGElement->DidChangeEnum(mAttrEnum, aDoSetAttr);
+  while (mapping && mapping->mKey) {
+    if (mapping->mVal == aValue) {
+      if (mBaseVal != PRUint8(aValue)) {
+        mBaseVal = mAnimVal = PRUint8(aValue);
+        aSVGElement->DidChangeEnum(mAttrEnum, aDoSetAttr);
+#ifdef MOZ_SMIL
+        if (mIsAnimated) {
+          aSVGElement->AnimationNeedsResample();
+        }
+#endif
+      }
       return NS_OK;
     }
-    tmp++;
+    mapping++;
   }
   return NS_ERROR_DOM_SYNTAX_ERR;
 }
 
+void
+nsSVGEnum::SetAnimValue(PRUint16 aValue, nsSVGElement *aSVGElement)
+{
+  mAnimVal = aValue;
+  mIsAnimated = PR_TRUE;
+  aSVGElement->DidAnimateEnum(mAttrEnum);
+}
+
 nsresult
 nsSVGEnum::ToDOMAnimatedEnum(nsIDOMSVGAnimatedEnumeration **aResult,
                              nsSVGElement *aSVGElement)
 {
   *aResult = new DOMAnimatedEnum(this, aSVGElement);
   if (!*aResult)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ADDREF(*aResult);
   return NS_OK;
 }
+
+#ifdef MOZ_SMIL
+nsISMILAttr*
+nsSVGEnum::ToSMILAttr(nsSVGElement *aSVGElement)
+{
+  return new SMILEnum(this, aSVGElement);
+}
+
+nsresult
+nsSVGEnum::SMILEnum::ValueFromString(const nsAString& aStr,
+                                     const nsISMILAnimationElement* /*aSrcElement*/,
+                                     nsSMILValue& aValue) const
+{
+  nsCOMPtr<nsIAtom> valAtom = do_GetAtom(aStr);
+  nsSVGEnumMapping *mapping = mVal->GetMapping(mSVGElement);
+
+  while (mapping && mapping->mKey) {
+    if (valAtom == *(mapping->mKey)) {
+      nsSMILValue val(&SMILEnumType::sSingleton);
+      val.mU.mUint = mapping->mVal;
+      aValue = val;
+      return NS_OK;
+    }
+    mapping++;
+  }
+  
+  // only a warning since authors may mistype attribute values
+  NS_WARNING("unknown enumeration key");
+  return NS_ERROR_FAILURE;
+}
+
+nsSMILValue
+nsSVGEnum::SMILEnum::GetBaseValue() const
+{
+  nsSMILValue val(&SMILEnumType::sSingleton);
+  val.mU.mUint = mVal->mBaseVal;
+  return val;
+}
+
+void
+nsSVGEnum::SMILEnum::ClearAnimValue()
+{
+  if (mVal->mIsAnimated) {
+    mVal->SetAnimValue(mVal->mBaseVal, mSVGElement);
+    mVal->mIsAnimated = PR_FALSE;
+  }
+}
+
+nsresult
+nsSVGEnum::SMILEnum::SetAnimValue(const nsSMILValue& aValue)
+{
+  NS_ASSERTION(aValue.mType == &SMILEnumType::sSingleton,
+               "Unexpected type to assign animated value");
+  if (aValue.mType == &SMILEnumType::sSingleton) {
+    NS_ABORT_IF_FALSE(aValue.mU.mUint <= USHRT_MAX,
+                      "Very large enumerated value - too big for PRUint16");
+    mVal->SetAnimValue(PRUint16(aValue.mU.mUint), mSVGElement);
+  }
+  return NS_OK;
+}
+#endif // MOZ_SMIL
--- a/content/svg/content/src/nsSVGEnum.h
+++ b/content/svg/content/src/nsSVGEnum.h
@@ -49,40 +49,52 @@ struct nsSVGEnumMapping {
 };
 
 class nsSVGEnum
 {
 public:
   void Init(PRUint8 aAttrEnum, PRUint16 aValue) {
     mAnimVal = mBaseVal = PRUint8(aValue);
     mAttrEnum = aAttrEnum;
+    mIsAnimated = PR_FALSE;
   }
 
   nsresult SetBaseValueString(const nsAString& aValue,
                               nsSVGElement *aSVGElement,
                               PRBool aDoSetAttr);
   void GetBaseValueString(nsAString& aValue,
                           nsSVGElement *aSVGElement);
 
   nsresult SetBaseValue(PRUint16 aValue,
                         nsSVGElement *aSVGElement,
                         PRBool aDoSetAttr);
-
   PRUint16 GetBaseValue() const
     { return mBaseVal; }
-  PRUint16 GetAnimValue() const
-    { return mAnimVal; }
+
+  void SetAnimValue(PRUint16 aValue, nsSVGElement *aSVGElement);
+  PRUint16 GetAnimValue(nsSVGElement *aSVGElement) const
+  {
+  #ifdef MOZ_SMIL
+    aSVGElement->FlushAnimations();
+  #endif
+    return mAnimVal;
+  }
 
   nsresult ToDOMAnimatedEnum(nsIDOMSVGAnimatedEnumeration **aResult,
                              nsSVGElement* aSVGElement);
+#ifdef MOZ_SMIL
+  // Returns a new nsISMILAttr object that the caller must delete
+  nsISMILAttr* ToSMILAttr(nsSVGElement* aSVGElement);
+#endif // MOZ_SMIL
 
 private:
   nsSVGEnumValue mAnimVal;
   nsSVGEnumValue mBaseVal;
   PRUint8 mAttrEnum; // element specified tracking for attribute
+  PRPackedBool mIsAnimated;
 
   nsSVGEnumMapping *GetMapping(nsSVGElement *aSVGElement);
 
   struct DOMAnimatedEnum : public nsIDOMSVGAnimatedEnumeration
   {
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_CYCLE_COLLECTION_CLASS(DOMAnimatedEnum)
 
@@ -92,13 +104,36 @@ private:
     nsSVGEnum *mVal; // kept alive because it belongs to content
     nsRefPtr<nsSVGElement> mSVGElement;
 
     NS_IMETHOD GetBaseVal(PRUint16* aResult)
       { *aResult = mVal->GetBaseValue(); return NS_OK; }
     NS_IMETHOD SetBaseVal(PRUint16 aValue)
       { return mVal->SetBaseValue(aValue, mSVGElement, PR_TRUE); }
     NS_IMETHOD GetAnimVal(PRUint16* aResult)
-      { *aResult = mVal->GetAnimValue(); return NS_OK; }
+      { *aResult = mVal->GetAnimValue(mSVGElement); return NS_OK; }
   };
+
+#ifdef MOZ_SMIL
+  struct SMILEnum : public nsISMILAttr
+  {
+  public:
+    SMILEnum(nsSVGEnum* aVal, nsSVGElement* aSVGElement)
+      : mVal(aVal), mSVGElement(aSVGElement) {}
+
+    // These will stay alive because a nsISMILAttr only lives as long
+    // as the Compositing step, and DOM elements don't get a chance to
+    // die during that.
+    nsSVGEnum* mVal;
+    nsSVGElement* mSVGElement;
+
+    // nsISMILAttr methods
+    virtual nsresult ValueFromString(const nsAString& aStr,
+                                     const nsISMILAnimationElement* aSrcElement,
+                                     nsSMILValue& aValue) const;
+    virtual nsSMILValue GetBaseValue() const;
+    virtual void ClearAnimValue();
+    virtual nsresult SetAnimValue(const nsSMILValue& aValue);
+  };
+#endif // MOZ_SMIL
 };
 
 #endif //__NS_SVGENUM_H__
--- a/content/svg/content/src/nsSVGFilterElement.cpp
+++ b/content/svg/content/src/nsSVGFilterElement.cpp
@@ -242,8 +242,18 @@ void
 nsSVGFilterElement::DidAnimateLength(PRUint8 aAttrEnum)
 {
   // nsSVGFilterFrame does not implement a useful AttributeChanged
   nsIFrame* frame = GetPrimaryFrame();
   if (frame) {
     nsSVGEffects::InvalidateRenderingObservers(frame);
   }
 }
+
+void
+nsSVGFilterElement::DidAnimateEnum(PRUint8 aAttrEnum)
+{
+  // nsSVGFilterFrame does not implement a useful AttributeChanged
+  nsIFrame* frame = GetPrimaryFrame();
+  if (frame) {
+    nsSVGEffects::InvalidateRenderingObservers(frame);
+  }
+}
--- a/content/svg/content/src/nsSVGFilterElement.h
+++ b/content/svg/content/src/nsSVGFilterElement.h
@@ -83,16 +83,17 @@ public:
 protected:
 
   virtual LengthAttributesInfo GetLengthInfo();
   virtual IntegerAttributesInfo GetIntegerInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   virtual StringAttributesInfo GetStringInfo();
 
   virtual void DidAnimateLength(PRUint8 aAttrEnum);
+  virtual void DidAnimateEnum(PRUint8 aAttrEnum);
 
   enum { X, Y, WIDTH, HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
 
   enum { FILTERRES_X, FILTERRES_Y };
   nsSVGInteger mIntegerAttributes[2];
   static IntegerInfo sIntegerInfo[2];
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -297,34 +297,47 @@ NS_IMETHODIMP nsSVGFE::GetResult(nsIDOMS
 
 nsSVGElement::LengthAttributesInfo
 nsSVGFE::GetLengthInfo()
 {
   return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
                               NS_ARRAY_LENGTH(sLengthInfo));
 }
 
-void
-nsSVGFE::DidAnimateLength(PRUint8 aAttrEnum)
+inline static void DidAnimateAttr(nsSVGFE *aFilterPrimitive)
 {
   // nsSVGLeafFrame doesn't implement AttributeChanged.
-  nsIFrame* frame = GetPrimaryFrame();
+  nsIFrame* frame = aFilterPrimitive->GetPrimaryFrame();
   if (frame) {
     nsSVGEffects::InvalidateRenderingObservers(frame);
   }
 }
 
 void
+nsSVGFE::DidAnimateLength(PRUint8 aAttrEnum)
+{
+  DidAnimateAttr(this);
+}
+
+void
 nsSVGFE::DidAnimateNumber(PRUint8 aAttrEnum)
 {
-  // nsSVGLeafFrame doesn't implement AttributeChanged.
-  nsIFrame* frame = GetPrimaryFrame();
-  if (frame) {
-    nsSVGEffects::InvalidateRenderingObservers(frame);
-  }
+  DidAnimateAttr(this);
+}
+
+void
+nsSVGFE::DidAnimateEnum(PRUint8 aAttrEnum)
+{
+  DidAnimateAttr(this);
+}
+
+void
+nsSVGFE::DidAnimateBoolean(PRUint8 aAttrEnum)
+{
+  DidAnimateAttr(this);
 }
 
 //---------------------Gaussian Blur------------------------
 
 typedef nsSVGFE nsSVGFEGaussianBlurElementBase;
 
 class nsSVGFEGaussianBlurElement : public nsSVGFEGaussianBlurElementBase,
                                    public nsIDOMSVGFEGaussianBlurElement
@@ -922,17 +935,17 @@ nsSVGFEBlendElement::Filter(nsSVGFilterI
                             const nsIntRect& rect)
 {
   CopyRect(aTarget, aSources[0], rect);
 
   PRUint8* sourceData = aSources[1]->mImage->Data();
   PRUint8* targetData = aTarget->mImage->Data();
   PRUint32 stride = aTarget->mImage->Stride();
 
-  PRUint16 mode = mEnumAttributes[MODE].GetAnimValue();
+  PRUint16 mode = mEnumAttributes[MODE].GetAnimValue(this);
 
   for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
     for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
       PRUint32 targIndex = y * stride + 4 * x;
       PRUint32 qa = targetData[targIndex + GFX_ARGB32_OFFSET_A];
       PRUint32 qb = sourceData[targIndex + GFX_ARGB32_OFFSET_A];
       for (PRInt32 i = NS_MIN(GFX_ARGB32_OFFSET_B, GFX_ARGB32_OFFSET_R);
            i <= NS_MAX(GFX_ARGB32_OFFSET_B, GFX_ARGB32_OFFSET_R); i++) {
@@ -1155,17 +1168,17 @@ nsSVGFEColorMatrixElement::Filter(nsSVGF
                                   const nsTArray<const Image*>& aSources,
                                   const Image* aTarget,
                                   const nsIntRect& rect)
 {
   PRUint8* sourceData = aSources[0]->mImage->Data();
   PRUint8* targetData = aTarget->mImage->Data();
   PRUint32 stride = aTarget->mImage->Stride();
 
-  PRUint16 type = mEnumAttributes[TYPE].GetAnimValue();
+  PRUint16 type = mEnumAttributes[TYPE].GetAnimValue(this);
 
   nsCOMPtr<nsIDOMSVGNumberList> list;
   mValues->GetAnimVal(getter_AddRefs(list));
   PRUint32 num = 0;
   if (list) {
     list->GetNumberOfItems(&num);
   }
 
@@ -1490,17 +1503,17 @@ nsSVGFECompositeElement::SetK(float k1, 
 }
 
 nsresult
 nsSVGFECompositeElement::Filter(nsSVGFilterInstance *instance,
                                 const nsTArray<const Image*>& aSources,
                                 const Image* aTarget,
                                 const nsIntRect& rect)
 {
-  PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue();
+  PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue(this);
 
   // Cairo does not support arithmetic operator
   if (op == nsSVGFECompositeElement::SVG_OPERATOR_ARITHMETIC) {
     float k1, k2, k3, k4;
     GetAnimatedNumberValues(&k1, &k2, &k3, &k4, nsnull);
 
 #ifdef DEBUG_tor
     fprintf(stderr, "FILTER COMPOSITE rect: %d,%d  %dx%d\n",
@@ -1563,17 +1576,17 @@ nsSVGFECompositeElement::GetSourceImageN
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN1], this));
   aSources.AppendElement(nsSVGStringInfo(&mStringAttributes[IN2], this));
 }
 
 nsIntRect
 nsSVGFECompositeElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
         const nsSVGFilterInstance& aInstance)
 {
-  PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue();
+  PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue(this);
 
   if (op == nsSVGFECompositeElement::SVG_OPERATOR_ARITHMETIC) {
     // "arithmetic" operator can produce non-zero alpha values even where
     // all input alphas are zero, so we can actually render outside the
     // union of the source bboxes.
     // XXX we could also check that k4 is nonzero and check for other
     // cases like k1/k2 or k1/k3 zero.
     return GetMaxRect();
@@ -1923,17 +1936,17 @@ NS_IMETHODIMP nsSVGComponentTransferFunc
 NS_IMETHODIMP nsSVGComponentTransferFunctionElement::GetOffset(nsIDOMSVGAnimatedNumber * *aOffset)
 {
   return mNumberAttributes[OFFSET].ToDOMAnimatedNumber(aOffset, this);
 }
 
 void
 nsSVGComponentTransferFunctionElement::GenerateLookupTable(PRUint8 *aTable)
 {
-  PRUint16 type = mEnumAttributes[TYPE].GetAnimValue();
+  PRUint16 type = mEnumAttributes[TYPE].GetAnimValue(this);
 
   float slope, intercept, amplitude, exponent, offset;
   GetAnimatedNumberValues(&slope, &intercept, &amplitude, 
                           &exponent, &offset, nsnull);
 
   PRUint32 i;
 
   switch (type) {
@@ -3180,18 +3193,18 @@ nsSVGFETurbulenceElement::Filter(nsSVGFi
 
 #ifdef DEBUG_tor
   fprintf(stderr, "FILTER TURBULENCE rect: %d,%d  %dx%d\n",
           rect.x, rect.y, rect.width, rect.height);
 #endif
 
   float fX, fY, seed;
   PRInt32 octaves = mIntegerAttributes[OCTAVES].GetAnimValue();
-  PRUint16 type = mEnumAttributes[TYPE].GetAnimValue();
-  PRUint16 stitch = mEnumAttributes[STITCHTILES].GetAnimValue();
+  PRUint16 type = mEnumAttributes[TYPE].GetAnimValue(this);
+  PRUint16 stitch = mEnumAttributes[STITCHTILES].GetAnimValue(this);
 
   GetAnimatedNumberValues(&fX, &fY, &seed, nsnull);
 
   InitSeed((PRInt32)seed);
 
   // XXXroc this makes absolutely no sense to me.
   float filterX = instance->GetFilterRect().X();
   float filterY = instance->GetFilterRect().Y();
@@ -3678,17 +3691,17 @@ nsSVGFEMorphologyElement::Filter(nsSVGFi
     return NS_OK;
   }
 
   PRUint8* sourceData = aSources[0]->mImage->Data();
   PRUint8* targetData = aTarget->mImage->Data();
   PRUint32 stride = aTarget->mImage->Stride();
   PRUint32 xExt[4], yExt[4];  // X, Y indices of RGBA extrema
   PRUint8 extrema[4];         // RGBA magnitude of extrema
-  PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue();
+  PRUint16 op = mEnumAttributes[OPERATOR].GetAnimValue(this);
 
   /* Scan the kernel for each pixel to determine max/min RGBA values.  Note that
    * as we advance in the x direction, each kernel overlaps the previous kernel.
    * Thus, we can avoid iterating over the entire kernel by comparing the
    * leading edge of the new kernel against the extrema found in the previous
    * kernel.   We must still scan the entire kernel if the previous extrema do
    * not fall within the current kernel or if we are starting a new row.
    */
@@ -3814,17 +3827,17 @@ public:
 
   NS_FORWARD_NSIDOMNODE(nsSVGFEConvolveMatrixElementBase::)
   NS_FORWARD_NSIDOMELEMENT(nsSVGFEConvolveMatrixElementBase::)
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
 protected:
   virtual PRBool OperatesOnPremultipledAlpha() {
-    return !mBooleanAttributes[PRESERVEALPHA].GetAnimValue();
+    return !mBooleanAttributes[PRESERVEALPHA].GetAnimValue(this);
   }
 
   virtual NumberAttributesInfo GetNumberInfo();
   virtual IntegerAttributesInfo GetIntegerInfo();
   virtual BooleanAttributesInfo GetBooleanInfo();
   virtual EnumAttributesInfo GetEnumInfo();
   virtual StringAttributesInfo GetStringInfo();
 
@@ -4177,18 +4190,18 @@ nsSVGFEConvolveMatrixElement::Filter(nsS
 
   ScaleInfo info = SetupScalingFilter(instance, aSources[0], aTarget, rect,
                                       &mNumberAttributes[KERNEL_UNIT_LENGTH_X],
                                       &mNumberAttributes[KERNEL_UNIT_LENGTH_Y],
                                       this);
   if (!info.mTarget)
     return NS_ERROR_FAILURE;
 
-  PRUint16 edgeMode = mEnumAttributes[EDGEMODE].GetAnimValue();
-  PRBool preserveAlpha = mBooleanAttributes[PRESERVEALPHA].GetAnimValue();
+  PRUint16 edgeMode = mEnumAttributes[EDGEMODE].GetAnimValue(this);
+  PRBool preserveAlpha = mBooleanAttributes[PRESERVEALPHA].GetAnimValue(this);
 
   float bias = 0;
   if (HasAttr(kNameSpaceID_None, nsGkAtoms::bias)) {
     bias = mNumberAttributes[BIAS].GetAnimValue(this);
   }
 
   const nsIntRect& dataRect = info.mDataRect;
   PRInt32 stride = info.mSource->Stride();
@@ -5726,18 +5739,18 @@ nsSVGFEDisplacementMapElement::Filter(ns
   scale = instance->GetPrimitiveLength(&val);
 
   static const PRUint16 channelMap[5] = {
                              0,
                              GFX_ARGB32_OFFSET_R,
                              GFX_ARGB32_OFFSET_G,
                              GFX_ARGB32_OFFSET_B,
                              GFX_ARGB32_OFFSET_A };
-  PRUint16 xChannel = channelMap[mEnumAttributes[CHANNEL_X].GetAnimValue()];
-  PRUint16 yChannel = channelMap[mEnumAttributes[CHANNEL_Y].GetAnimValue()];
+  PRUint16 xChannel = channelMap[mEnumAttributes[CHANNEL_X].GetAnimValue(this)];
+  PRUint16 yChannel = channelMap[mEnumAttributes[CHANNEL_Y].GetAnimValue(this)];
 
   double scaleOver255 = scale / 255.0;
   double scaleAdjustment = 0.5 - 0.5 * scale;
 
   for (PRInt32 y = rect.y; y < rect.YMost(); y++) {
     for (PRInt32 x = rect.x; x < rect.XMost(); x++) {
       PRUint32 targIndex = y * stride + 4 * x;
       // At some point we might want to replace this with a bilinear sample.
--- a/content/svg/content/src/nsSVGFilters.h
+++ b/content/svg/content/src/nsSVGFilters.h
@@ -214,16 +214,18 @@ protected:
     return style->GetStyleSVG()->mColorInterpolationFilters ==
              NS_STYLE_COLOR_INTERPOLATION_SRGB;
   }
 
   // nsSVGElement specializations:
   virtual LengthAttributesInfo GetLengthInfo();
   virtual void DidAnimateLength(PRUint8 aAttrEnum);
   virtual void DidAnimateNumber(PRUint8 aAttrEnum);
+  virtual void DidAnimateEnum(PRUint8 aAttrEnum);
+  virtual void DidAnimateBoolean(PRUint8 aAttrEnum);
 
   // nsIDOMSVGFitlerPrimitiveStandardAttributes values
   enum { X, Y, WIDTH, HEIGHT };
   nsSVGLength2 mLengthAttributes[4];
   static LengthInfo sLengthInfo[4];
 };
 
 #endif
--- a/content/svg/content/src/nsSVGMarkerElement.cpp
+++ b/content/svg/content/src/nsSVGMarkerElement.cpp
@@ -377,17 +377,17 @@ nsSVGMarkerElement::GetPreserveAspectRat
 //----------------------------------------------------------------------
 // public helpers
 
 gfxMatrix
 nsSVGMarkerElement::GetMarkerTransform(float aStrokeWidth,
                                        float aX, float aY, float aAngle)
 {
   float scale = 1.0;
-  if (mEnumAttributes[MARKERUNITS].GetAnimValue() ==
+  if (mEnumAttributes[MARKERUNITS].GetAnimValue(this) ==
       SVG_MARKERUNITS_STROKEWIDTH)
     scale = aStrokeWidth;
 
   if (mOrientType.GetAnimValue() != SVG_MARKER_ORIENT_AUTO) {
     aAngle = mAngleAttributes[ORIENT].GetAnimValue();
   }
 
   return gfxMatrix(cos(aAngle) * scale,   sin(aAngle) * scale,
--- a/content/svg/content/src/nsSVGMatrix.cpp
+++ b/content/svg/content/src/nsSVGMatrix.cpp
@@ -310,29 +310,33 @@ NS_IMETHODIMP nsSVGMatrix::FlipY(nsIDOMS
 
 /* nsIDOMSVGMatrix skewX (in float angle); */
 NS_IMETHODIMP nsSVGMatrix::SkewX(float angle, nsIDOMSVGMatrix **_retval)
 {
   NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
 
   double ta = tan( angle*radPerDegree );
 
+  NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
+
   return NS_NewSVGMatrix(_retval,
                          mA,                    mB,
                          (float) ( mC + mA*ta), (float) ( mD + mB*ta),
                          mE,                    mF);
 }
 
 /* nsIDOMSVGMatrix skewY (in float angle); */
 NS_IMETHODIMP nsSVGMatrix::SkewY(float angle, nsIDOMSVGMatrix **_retval)
 {
   NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
 
   double ta = tan( angle*radPerDegree );
 
+  NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
+
   return NS_NewSVGMatrix(_retval,
                          (float) (mA + mC*ta), (float) (mB + mD*ta),
                          mC,                    mD,
                          mE,                    mF);
 }
 
 
 //----------------------------------------------------------------------
--- a/content/svg/content/src/nsSVGSVGElement.cpp
+++ b/content/svg/content/src/nsSVGSVGElement.cpp
@@ -814,17 +814,17 @@ nsSVGSVGElement::GetTransformToElement(n
 
 //----------------------------------------------------------------------
 // nsIDOMSVGZoomAndPan methods
 
 /* attribute unsigned short zoomAndPan; */
 NS_IMETHODIMP
 nsSVGSVGElement::GetZoomAndPan(PRUint16 *aZoomAndPan)
 {
-  *aZoomAndPan = mEnumAttributes[ZOOMANDPAN].GetAnimValue();
+  *aZoomAndPan = mEnumAttributes[ZOOMANDPAN].GetAnimValue(this);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSVGSVGElement::SetZoomAndPan(PRUint16 aZoomAndPan)
 {
   if (aZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_DISABLE ||
       aZoomAndPan == nsIDOMSVGZoomAndPan::SVG_ZOOMANDPAN_MAGNIFY) {
--- a/content/svg/content/src/nsSVGTransform.cpp
+++ b/content/svg/content/src/nsSVGTransform.cpp
@@ -41,16 +41,18 @@
 #include "nsSVGMatrix.h"
 #include "nsISVGValueUtils.h"
 #include "nsWeakReference.h"
 #include "nsSVGMatrix.h"
 #include "nsTextFormatter.h"
 #include "nsContentUtils.h"
 #include "nsDOMError.h"
 
+const double radPerDegree = 2.0*3.1415926535 / 360.0;
+
 //----------------------------------------------------------------------
 // Implementation
 
 nsresult
 nsSVGTransform::Create(nsIDOMSVGTransform** aResult)
 {
   nsSVGTransform *pl = new nsSVGTransform();
   NS_ENSURE_TRUE(pl, NS_ERROR_OUT_OF_MEMORY);
@@ -198,16 +200,19 @@ NS_IMETHODIMP nsSVGTransform::WillModify
 {
   WillModify();
   return NS_OK;
 }
 
 NS_IMETHODIMP nsSVGTransform::DidModifySVGObservable (nsISVGValue* observable,
                                                       modificationType aModType)
 {
+  // we become a general matrix transform if mMatrix changes
+  mType = SVG_TRANSFORM_MATRIX;
+  mAngle = 0.0f;
   DidModify();
   return NS_OK;
 }
 
 
 //----------------------------------------------------------------------
 // nsIDOMSVGTransform methods:
 
@@ -240,76 +245,76 @@ NS_IMETHODIMP nsSVGTransform::SetMatrix(
 
   if (!matrix)
     return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR;
 
   WillModify();
 
   mType = SVG_TRANSFORM_MATRIX;
   mAngle = 0.0f;
-  mOriginX = 0.0f;
-  mOriginY = 0.0f;
   
   matrix->GetA(&a);
   matrix->GetB(&b);
   matrix->GetC(&c);
   matrix->GetD(&d);
   matrix->GetE(&e);
   matrix->GetF(&f);
 
+  NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
   mMatrix->SetA(a);
   mMatrix->SetB(b);
   mMatrix->SetC(c);
   mMatrix->SetD(d);
   mMatrix->SetE(e);
   mMatrix->SetF(f);
+  NS_ADD_SVGVALUE_OBSERVER(mMatrix);
 
   DidModify();
   return NS_OK;
 }
 
 /* void setTranslate (in float tx, in float ty); */
 NS_IMETHODIMP nsSVGTransform::SetTranslate(float tx, float ty)
 {
   NS_ENSURE_FINITE2(tx, ty, NS_ERROR_ILLEGAL_VALUE);
 
   WillModify();
   
   mType = SVG_TRANSFORM_TRANSLATE;
   mAngle = 0.0f;
-  mOriginX = 0.0f;
-  mOriginY = 0.0f;
+  NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
   mMatrix->SetA(1.0f);
   mMatrix->SetB(0.0f);
   mMatrix->SetC(0.0f);
   mMatrix->SetD(1.0f);
   mMatrix->SetE(tx);
   mMatrix->SetF(ty);
+  NS_ADD_SVGVALUE_OBSERVER(mMatrix);
 
   DidModify();
   return NS_OK;
 }
 
 /* void setScale (in float sx, in float sy); */
 NS_IMETHODIMP nsSVGTransform::SetScale(float sx, float sy)
 {
   NS_ENSURE_FINITE2(sx, sy, NS_ERROR_ILLEGAL_VALUE);
 
   WillModify();
   
   mType = SVG_TRANSFORM_SCALE;
   mAngle = 0.0f;
-  mOriginX = 0.0f;
-  mOriginY = 0.0f;
+  NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
   mMatrix->SetA(sx);
   mMatrix->SetB(0.0f);
   mMatrix->SetC(0.0f);
   mMatrix->SetD(sy);
   mMatrix->SetE(0.0f);
   mMatrix->SetF(0.0f);
+  NS_ADD_SVGVALUE_OBSERVER(mMatrix);
 
   DidModify();
   return NS_OK;
 }
 
 /* void setRotate (in float angle, in float cx, in float cy); */
 NS_IMETHODIMP nsSVGTransform::SetRotate(float angle, float cx, float cy)
 {
@@ -317,67 +322,81 @@ NS_IMETHODIMP nsSVGTransform::SetRotate(
 
   WillModify();
   
   mType = SVG_TRANSFORM_ROTATE;
   mAngle = angle;
   mOriginX = cx;
   mOriginY = cy;
 
+  gfxMatrix matrix(1, 0, 0, 1, cx, cy);
+  matrix.Rotate(angle * radPerDegree);
+  matrix.Translate(gfxPoint(-cx, -cy));
+
   NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
-  NS_NewSVGMatrix(getter_AddRefs(mMatrix));
-  nsCOMPtr<nsIDOMSVGMatrix> temp;
-  mMatrix->Translate(cx, cy, getter_AddRefs(temp));
-  mMatrix = temp;
-  mMatrix->Rotate(angle, getter_AddRefs(temp));
-  mMatrix = temp;
-  mMatrix->Translate(-cx,-cy, getter_AddRefs(temp));
-  mMatrix = temp;
+  mMatrix->SetA(static_cast<float>(matrix.xx));
+  mMatrix->SetB(static_cast<float>(matrix.yx));
+  mMatrix->SetC(static_cast<float>(matrix.xy));
+  mMatrix->SetD(static_cast<float>(matrix.yy));
+  mMatrix->SetE(static_cast<float>(matrix.x0));
+  mMatrix->SetF(static_cast<float>(matrix.y0));
   NS_ADD_SVGVALUE_OBSERVER(mMatrix);
 
   DidModify();
   return NS_OK;
 }
 
 /* void setSkewX (in float angle); */
 NS_IMETHODIMP nsSVGTransform::SetSkewX(float angle)
 {
   NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
 
+  float ta = static_cast<float>(tan(angle * radPerDegree));
+
+  NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
+
   WillModify();
   
   mType = SVG_TRANSFORM_SKEWX;
   mAngle = angle;
 
   NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
-  NS_NewSVGMatrix(getter_AddRefs(mMatrix));
-  nsCOMPtr<nsIDOMSVGMatrix> temp;
-  mMatrix->SkewX(angle, getter_AddRefs(temp));
-  mMatrix = temp;
+  mMatrix->SetA(1.0f);
+  mMatrix->SetB(0.0f);
+  mMatrix->SetC(ta);
+  mMatrix->SetD(1.0f);
+  mMatrix->SetE(0.0f);
+  mMatrix->SetF(0.0f);
   NS_ADD_SVGVALUE_OBSERVER(mMatrix);
 
   DidModify();
   return NS_OK;
 }
 
 /* void setSkewY (in float angle); */
 NS_IMETHODIMP nsSVGTransform::SetSkewY(float angle)
 {
   NS_ENSURE_FINITE(angle, NS_ERROR_ILLEGAL_VALUE);
 
+  float ta = static_cast<float>(tan(angle * radPerDegree));
+
+  NS_ENSURE_FINITE(ta, NS_ERROR_DOM_SVG_INVALID_VALUE_ERR);
+
   WillModify();
   
   mType = SVG_TRANSFORM_SKEWY;
   mAngle = angle;
 
   NS_REMOVE_SVGVALUE_OBSERVER(mMatrix);
-  NS_NewSVGMatrix(getter_AddRefs(mMatrix));
-  nsCOMPtr<nsIDOMSVGMatrix> temp;
-  mMatrix->SkewY(angle, getter_AddRefs(temp));
-  mMatrix = temp;
+  mMatrix->SetA(1.0f);
+  mMatrix->SetB(ta);
+  mMatrix->SetC(0.0f);
+  mMatrix->SetD(1.0f);
+  mMatrix->SetE(0.0f);
+  mMatrix->SetF(0.0f);
   NS_ADD_SVGVALUE_OBSERVER(mMatrix);
 
   DidModify();
   return NS_OK;
 }
 
 
 
--- a/content/svg/content/test/test_transform.xhtml
+++ b/content/svg/content/test/test_transform.xhtml
@@ -19,16 +19,23 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 <![CDATA[
 
 SimpleTest.waitForExplicitFinish();
 
+var tolerance = 1 / 65535;
+      
+function isequal( value, expected, tolerance )
+{
+  ok(Math.abs(value - expected) < tolerance, 'matrix value expected:' +expected + ' actual:' + value);
+}
+
 function run()
 {
   var g, svg, t, m, m2;
 
   svg = $('svg');
   g = $('g');
 
   t = g.transform.baseVal.getItem(0);
@@ -75,16 +82,59 @@ function run()
   is(m.a, 1, 'm.a for matrix');
   is(m.b, 2, 'm.b for matrix');
   is(m.c, 3, 'm.c for matrix');
   is(m.d, 4, 'm.d for matrix');
   is(m.e, 5, 'm.e for matrix');
   is(m.f, 6, 'm.f for matrix');
   is(t.angle, 0, 't.angle for matrix');
 
+  // set the SVGTransform to be a translate() then convert to a matrix
+  t.setTranslate(0, 0);
+  m.a = 2;
+
+  // test that the SVGTransform now reflects the matrix value
+  is(t.type, SVGTransform.SVG_TRANSFORM_MATRIX, 't.type for matrix');
+
+  // set the SVGTransform to be a rotate()
+  t.setRotate(90, 0, 0);
+
+  // test that the SVGTransform now reflects the matrix value
+  is(t.type, SVGTransform.SVG_TRANSFORM_ROTATE, 't.type for rotate');
+  isequal(m.a, Math.cos(Math.PI/2), tolerance);
+  isequal(m.b, Math.sin(Math.PI/2), tolerance);
+  isequal(m.c, -Math.sin(Math.PI/2), tolerance);
+  isequal(m.d, Math.cos(Math.PI/2), tolerance);
+  isequal(m.e, 0, tolerance);
+  isequal(m.f, 0, tolerance);
+
+  // set the SVGTransform to be a skewX()
+  t.setSkewX(45);
+
+  // test that the SVGTransform now reflects the matrix value
+  is(t.type, SVGTransform.SVG_TRANSFORM_SKEWX, 't.type for skewx');
+  isequal(m.a, 1, tolerance);
+  isequal(m.b, 0, tolerance);
+  isequal(m.c, Math.tan(Math.PI/4), tolerance);
+  isequal(m.d, Math.tan(Math.PI/4), tolerance);
+  isequal(m.e, 0, tolerance);
+  isequal(m.f, 0, tolerance);
+
+  // set the SVGTransform to be a skewY()
+  t.setSkewY(45);
+
+  // test that the SVGTransform now reflects the matrix value
+  is(t.type, SVGTransform.SVG_TRANSFORM_SKEWY, 't.type for skewy');
+  isequal(m.a, Math.tan(Math.PI/4), tolerance);
+  isequal(m.b, Math.tan(Math.PI/4), tolerance);
+  isequal(m.c, 0, tolerance);
+  isequal(m.d, 1, tolerance);
+  isequal(m.e, 0, tolerance);
+  isequal(m.f, 0, tolerance);
+
   SimpleTest.finish();
 }
 
 window.addEventListener("load", run, false);
 
 ]]>
 </script>
 </pre>
--- a/docshell/base/nsAboutRedirector.cpp
+++ b/docshell/base/nsAboutRedirector.cpp
@@ -79,17 +79,18 @@ static RedirEntry kRedirMap[] = {
     { "buildconfig", "chrome://global/content/buildconfig.html",
       nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT },
     { "license", "chrome://global/content/license.html",
       nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT },
     { "licence", "chrome://global/content/license.html",
       nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT },
     { "neterror", "chrome://global/content/netError.xhtml",
       nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
-      nsIAboutModule::ALLOW_SCRIPT },
+      nsIAboutModule::ALLOW_SCRIPT |
+      nsIAboutModule::HIDE_FROM_ABOUTABOUT },
     { "memory", "chrome://global/content/aboutMemory.xhtml",
       nsIAboutModule::ALLOW_SCRIPT }
 };
 static const int kRedirTotal = NS_ARRAY_LENGTH(kRedirMap);
 
 NS_IMETHODIMP
 nsAboutRedirector::NewChannel(nsIURI *aURI, nsIChannel **result)
 {
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1787,18 +1787,17 @@ nsDocShell::SetDocumentCharsetInfo(nsIDo
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetChannelIsUnsafe(PRBool *aUnsafe)
 {
     *aUnsafe = PR_FALSE;
 
-    nsCOMPtr<nsIChannel> channel;
-    GetCurrentDocumentChannel(getter_AddRefs(channel));
+    nsIChannel* channel = GetCurrentDocChannel();
     if (!channel) {
         return NS_OK;
     }
 
     nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(channel);
     if (!jarChannel) {
         return NS_OK;
     }
@@ -2282,32 +2281,30 @@ nsDocShell::AddSessionStorage(nsIPrincip
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetCurrentDocumentChannel(nsIChannel** aResult)
 {
-    *aResult = nsnull;
-    if (!mContentViewer)
-        return NS_OK;
-
-    nsCOMPtr<nsIDOMDocument> domDoc;
-    nsresult rv = mContentViewer->GetDOMDocument(getter_AddRefs(domDoc));
-    if (NS_FAILED(rv))
-        return rv;
-
-    nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
-    if (doc) {
-      *aResult = doc->GetChannel();
-      NS_IF_ADDREF(*aResult);
-    }
-  
-    return NS_OK;
+    NS_IF_ADDREF(*aResult = GetCurrentDocChannel()); 
+    return NS_OK;
+}
+
+nsIChannel*
+nsDocShell::GetCurrentDocChannel()
+{
+    if (mContentViewer) {
+        nsIDocument* doc = mContentViewer->GetDocument();
+        if (doc) {
+            return doc->GetChannel();
+        }
+    }
+    return nsnull;
 }
 
 //*****************************************************************************
 // nsDocShell::nsIDocShellTreeItem
 //*****************************************************************************   
 
 NS_IMETHODIMP
 nsDocShell::GetName(PRUnichar ** aName)
@@ -2983,22 +2980,20 @@ nsDocShell::AddChild(nsIDocShellTreeItem
 
     // get the child's docCSInfo object
     nsCOMPtr<nsIDocumentCharsetInfo> dcInfo = NULL;
     res = childAsDocShell->GetDocumentCharsetInfo(getter_AddRefs(dcInfo));
     if (NS_FAILED(res) || (!dcInfo))
         return NS_OK;
 
     // get the parent's current charset
-    nsCOMPtr<nsIDocumentViewer> docv(do_QueryInterface(mContentViewer));
-    if (!docv)
+    if (!mContentViewer)
         return NS_OK;
-    nsCOMPtr<nsIDocument> doc;
-    res = docv->GetDocument(getter_AddRefs(doc));
-    if (NS_FAILED(res) || (!doc))
+    nsIDocument* doc = mContentViewer->GetDocument();
+    if (!doc)
         return NS_OK;
     const nsACString &parentCS = doc->GetDocumentCharacterSet();
 
     PRBool isWyciwyg = PR_FALSE;
 
     if (mCurrentURI) {
         // Check if the url is wyciwyg
         mCurrentURI->SchemeIs("wyciwyg", &isWyciwyg);      
@@ -8045,21 +8040,17 @@ nsDocShell::InternalLoad(nsIURI * aURI,
 }
 
 nsIPrincipal*
 nsDocShell::GetInheritedPrincipal(PRBool aConsiderCurrentDocument)
 {
     nsCOMPtr<nsIDocument> document;
 
     if (aConsiderCurrentDocument && mContentViewer) {
-        nsCOMPtr<nsIDocumentViewer>
-            docViewer(do_QueryInterface(mContentViewer));
-        if (!docViewer)
-            return nsnull;
-        docViewer->GetDocument(getter_AddRefs(document));
+        document = mContentViewer->GetDocument();
     }
 
     if (!document) {
         nsCOMPtr<nsIDocShellTreeItem> parentItem;
         GetSameTypeParent(getter_AddRefs(parentItem));
         if (parentItem) {
             nsCOMPtr<nsIDOMDocument> parentDomDoc(do_GetInterface(parentItem));
             document = do_QueryInterface(parentDomDoc);
@@ -8071,21 +8062,19 @@ nsDocShell::GetInheritedPrincipal(PRBool
             return nsnull;
         }
 
         // Make sure we end up with _something_ as the principal no matter
         // what.
         EnsureContentViewer();  // If this fails, we'll just get a null
                                 // docViewer and bail.
 
-        nsCOMPtr<nsIDocumentViewer>
-            docViewer(do_QueryInterface(mContentViewer));
-        if (!docViewer)
+        if (!mContentViewer)
             return nsnull;
-        docViewer->GetDocument(getter_AddRefs(document));
+        document = mContentViewer->GetDocument();
     }
 
     //-- Get the document's principal
     if (document) {
         return document->NodePrincipal();
     }
 
     return nsnull;
@@ -8695,22 +8684,18 @@ nsDocShell::ScrollIfAnchor(nsIURI * aURI
         nsMemory::Free(str);
 
         // Above will fail if the anchor name is not UTF-8.  Need to
         // convert from document charset to unicode.
         if (NS_FAILED(rv)) {
                 
             // Get a document charset
             NS_ENSURE_TRUE(mContentViewer, NS_ERROR_FAILURE);
-            nsCOMPtr<nsIDocumentViewer>
-                docv(do_QueryInterface(mContentViewer));
-            NS_ENSURE_TRUE(docv, NS_ERROR_FAILURE);
-            nsCOMPtr<nsIDocument> doc;
-            rv = docv->GetDocument(getter_AddRefs(doc));
-            NS_ENSURE_SUCCESS(rv, rv);
+            nsIDocument* doc = mContentViewer->GetDocument();
+            NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
             const nsACString &aCharset = doc->GetDocumentCharacterSet();
 
             nsCOMPtr<nsITextToSubURI> textToSubURI =
                 do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
             NS_ENSURE_SUCCESS(rv, rv);
 
             // Unescape and convert to unicode
             nsXPIDLString uStr;
@@ -10083,30 +10068,27 @@ nsDocShell::InterfaceRequestorProxy::Get
 
 nsresult
 nsDocShell::SetBaseUrlForWyciwyg(nsIContentViewer * aContentViewer)
 {
     if (!aContentViewer)
         return NS_ERROR_FAILURE;
 
     nsCOMPtr<nsIURI> baseURI;
-    nsCOMPtr<nsIDocument> document;
     nsresult rv = NS_ERROR_NOT_AVAILABLE;
 
     if (sURIFixup)
         rv = sURIFixup->CreateExposableURI(mCurrentURI,
                                            getter_AddRefs(baseURI));
 
     // Get the current document and set the base uri
     if (baseURI) {
-        nsCOMPtr<nsIDocumentViewer> docViewer(do_QueryInterface(aContentViewer));
-        if (docViewer) {
-            rv = docViewer->GetDocument(getter_AddRefs(document));
-            if (document)
-                rv = document->SetBaseURI(baseURI);
+        nsIDocument* document = aContentViewer->GetDocument();
+        if (document) {
+            rv = document->SetBaseURI(baseURI);
         }
     }
     return rv;
 }
 
 //*****************************************************************************
 // nsDocShell::nsIAuthPromptProvider
 //*****************************************************************************
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -609,17 +609,18 @@ protected:
                                      nsIDOMStorage** aStorage);
 
     // helpers for executing commands
     nsresult GetControllerForCommand(const char *inCommand,
                                      nsIController** outController);
     nsresult IsCommandEnabled(const char * inCommand, PRBool* outEnabled);
     nsresult DoCommand(const char * inCommand);
     nsresult EnsureCommandHandler();
-    
+
+    nsIChannel* GetCurrentDocChannel();
 protected:
     // Override the parent setter from nsDocLoader
     virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader);
 
     // Event type dispatched by RestorePresentation
     class RestorePresentationEvent : public nsRunnable {
     public:
         NS_DECL_NSIRUNNABLE
--- a/docshell/base/nsIContentViewer.idl
+++ b/docshell/base/nsIContentViewer.idl
@@ -2,23 +2,25 @@
 
 interface nsIDOMDocument;
 interface nsISHEntry;
 interface nsIPrintSettings;
 
 
 %{ C++
 class nsIWidget;
+class nsIDocument;
 struct nsIntRect;
 %}
 
 [ptr] native nsIWidgetPtr(nsIWidget);
+[ptr] native nsIDocumentPtr(nsIDocument);
 [ref] native nsIntRectRef(nsIntRect);
 
-[scriptable, uuid(08665a60-b398-11de-8a39-0800200c9a66)]
+[scriptable, uuid(c824ac5e-3d86-4ae5-9ccc-9433bdc43004)]
 interface nsIContentViewer : nsISupports
 {
 
   [noscript] void init(in nsIWidgetPtr aParentWidget,
                        [const] in nsIntRectRef aBounds);
 
   attribute nsISupports container;
 
@@ -70,16 +72,21 @@ interface nsIContentViewer : nsISupports
    */
   void close(in nsISHEntry historyEntry);
   void destroy();
 
   void stop();
 
   attribute nsIDOMDocument DOMDocument;
 
+  /**
+   * Returns DOMDocument as nsIDocument and without addrefing.
+   */
+  [noscript,notxpcom] nsIDocumentPtr getDocument();
+
   [noscript] void getBounds(in nsIntRectRef aBounds);
   [noscript] void setBounds([const] in nsIntRectRef aBounds);
 
   /**
    * The previous content viewer, which has been |close|d but not
    * |destroy|ed.
    */
   [noscript] attribute nsIContentViewer previousViewer;
--- a/docshell/test/Makefile.in
+++ b/docshell/test/Makefile.in
@@ -76,16 +76,18 @@ include $(topsrcdir)/config/rules.mk
 		file_bug385434_1.html \
 		file_bug385434_2.html \
 		file_bug385434_3.html \
 		test_bug509055.html \
 		file_bug509055.html \
 		test_bug529119-1.html \
 		test_bug529119-2.html \
 		bug529119-window.html \
+		test_bug540462.html \
+		file_bug540462.html \
 		$(NULL)
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 _TEST_FILES += \
 		test_bug511449.html \
 		file_bug511449.html \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/docshell/test/file_bug540462.html
@@ -0,0 +1,16 @@
+<html>
+  <head>
+    <script>
+    //<!--
+    function test() {
+      document.open();
+      document.write("<html><body onload='opener.documentWriteLoad(); rel();'><a href='foo.html'>foo</a><script>function rel() { setTimeout('location.reload()', 0); }</script></body></html>");
+      document.close();
+    }
+    //-->
+    </script>
+  </head>
+  <body onload="setTimeout('test()', 0)">
+    Test for bug 540462
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/docshell/test/test_bug540462.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=540462
+-->
+<head>
+  <title>Test for Bug 540462</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="runTest()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=540462">Mozilla Bug 540462</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 540462 **/
+
+var win;
+function runTest() {
+  win = window.open("file_bug540462.html", "", "width=100,height=100");
+}
+
+var dwlCount = 0;
+var originalURL;
+function documentWriteLoad() {
+  if (++dwlCount == 1) {
+    originalURL = win.document.body.firstChild.href;
+  } else if (dwlCount == 2) {
+    is(win.document.body.firstChild.href, originalURL, "Wrong href!");
+    win.close();
+    SimpleTest.finish();
+  }
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -430,17 +430,16 @@
 #include "nsIDOMSVGUseElement.h"
 #include "nsIDOMSVGUnitTypes.h"
 #include "nsIDOMSVGZoomAndPan.h"
 #include "nsIDOMSVGZoomEvent.h"
 #endif // MOZ_SVG
 
 #include "nsIDOMCanvasRenderingContext2D.h"
 #include "nsICanvasRenderingContextWebGL.h"
-#include "WebGLArray.h"
 
 #include "nsIImageDocument.h"
 
 // Storage includes
 #include "nsDOMStorage.h"
 
 // Drag and drop
 #include "nsIDOMDataTransfer.h"
@@ -1316,39 +1315,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(WebGLProgram, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLShader, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLFramebuffer, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLRenderbuffer, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(WebGLArrayBuffer, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(WebGLFloatArray, nsDOMGenericSH,
-                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
-                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
-  NS_DEFINE_CLASSINFO_DATA(WebGLByteArray, nsDOMGenericSH,
-                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
-                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
-  NS_DEFINE_CLASSINFO_DATA(WebGLUnsignedByteArray, nsDOMGenericSH,
-                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
-                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
-  NS_DEFINE_CLASSINFO_DATA(WebGLShortArray, nsDOMGenericSH,
-                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
-                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
-  NS_DEFINE_CLASSINFO_DATA(WebGLUnsignedShortArray, nsDOMGenericSH,
-                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
-                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
-  NS_DEFINE_CLASSINFO_DATA(WebGLIntArray, nsDOMGenericSH,
-                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
-                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
-  NS_DEFINE_CLASSINFO_DATA(WebGLUnsignedIntArray, nsDOMGenericSH,
-                           nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE |
-                           nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY)
 
   NS_DEFINE_CLASSINFO_DATA(PaintRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(PaintRequestList, nsPaintRequestListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(ScrollAreaEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -1386,26 +1362,16 @@ struct nsConstructorFuncMapData
 };
 
 #define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func)                        \
   { eDOMClassInfo_##_class##_id, _func },
 
 static const nsConstructorFuncMapData kConstructorFuncMap[] =
 {
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker)
-
-  // WebGL Array Types
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLArrayBuffer, NS_NewWebGLArrayBuffer)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLFloatArray, NS_NewWebGLFloatArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLByteArray, NS_NewWebGLByteArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLUnsignedByteArray, NS_NewWebGLUnsignedByteArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLShortArray, NS_NewWebGLShortArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLUnsignedShortArray, NS_NewWebGLUnsignedShortArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLIntArray, NS_NewWebGLIntArray)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(WebGLUnsignedIntArray, NS_NewWebGLUnsignedIntArray)
 };
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nsnull;
 PRBool nsDOMClassInfo::sIsInitialized = PR_FALSE;
 PRBool nsDOMClassInfo::sDisableDocumentAllSupport = PR_FALSE;
 PRBool nsDOMClassInfo::sDisableGlobalScopePollutionSupport = PR_FALSE;
 
@@ -3736,48 +3702,16 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(WebGLFramebuffer, nsIWebGLFramebuffer)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLFramebuffer)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLRenderbuffer, nsIWebGLRenderbuffer)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLRenderbuffer)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(WebGLArrayBuffer, nsIWebGLArrayBuffer)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLArrayBuffer)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(WebGLFloatArray, nsIWebGLFloatArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLFloatArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(WebGLByteArray, nsIWebGLByteArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLByteArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(WebGLUnsignedByteArray, nsIWebGLUnsignedByteArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUnsignedByteArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(WebGLShortArray, nsIWebGLShortArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLShortArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(WebGLUnsignedShortArray, nsIWebGLUnsignedShortArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUnsignedShortArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(WebGLIntArray, nsIWebGLIntArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLIntArray)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(WebGLUnsignedIntArray, nsIWebGLUnsignedIntArray)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebGLUnsignedIntArray)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(PaintRequest, nsIDOMPaintRequest)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMPaintRequest)
    DOM_CLASSINFO_MAP_END
  
   DOM_CLASSINFO_MAP_BEGIN(PaintRequestList, nsIDOMPaintRequestList)