Merge TM -> JM
authorBrian Hackett <bhackett1024@gmail.com>
Tue, 22 Mar 2011 18:07:31 -0700
changeset 74841 ea1997ab6c32b50c133ac07af880315fd3642668
parent 74840 13323fd7e400633e813160f830f9fb34a6203fab (current diff)
parent 64348 41ed083faf4a75bcb09e38f58311013cf3495768 (diff)
child 74842 af6d3ea1e6e77e21d7f045eacb3edefb16dcf498
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
milestone2.0b13pre
Merge TM -> JM
accessible/tests/mochitest/test_nsIAccessible_focus.html
content/canvas/test/webgl/conformance/resources/testrunner.js
content/canvas/test/webgl/more/00_testFIXME_list.txt
content/canvas/test/webgl/more/00_test_list.txt
content/canvas/test/webgl/more/README.md
content/canvas/test/webgl/more/all_tests.html
content/canvas/test/webgl/more/all_tests_linkonly.html
content/canvas/test/webgl/more/all_tests_sequential.html
content/canvas/test/webgl/more/conformance/badArgsArityLessThanArgc.html
content/canvas/test/webgl/more/conformance/constants.html
content/canvas/test/webgl/more/conformance/fuzzTheAPI.html
content/canvas/test/webgl/more/conformance/getContext.html
content/canvas/test/webgl/more/conformance/methods.html
content/canvas/test/webgl/more/conformance/quickCheckAPI.html
content/canvas/test/webgl/more/conformance/quickCheckAPI.js
content/canvas/test/webgl/more/conformance/quickCheckAPIBadArgs.html
content/canvas/test/webgl/more/conformance/webGLArrays.html
content/canvas/test/webgl/more/demos/opengl_web.html
content/canvas/test/webgl/more/demos/video.html
content/canvas/test/webgl/more/functions/bindBuffer.html
content/canvas/test/webgl/more/functions/bindBufferBadArgs.html
content/canvas/test/webgl/more/functions/bindFramebufferLeaveNonZero.html
content/canvas/test/webgl/more/functions/bufferData.html
content/canvas/test/webgl/more/functions/bufferDataBadArgs.html
content/canvas/test/webgl/more/functions/bufferSubData.html
content/canvas/test/webgl/more/functions/bufferSubDataBadArgs.html
content/canvas/test/webgl/more/functions/copyTexImage2D.html
content/canvas/test/webgl/more/functions/copyTexImage2DBadArgs.html
content/canvas/test/webgl/more/functions/copyTexSubImage2D.html
content/canvas/test/webgl/more/functions/copyTexSubImage2DBadArgs.html
content/canvas/test/webgl/more/functions/deleteBufferBadArgs.html
content/canvas/test/webgl/more/functions/drawArrays.html
content/canvas/test/webgl/more/functions/drawArraysOutOfBounds.html
content/canvas/test/webgl/more/functions/drawElements.html
content/canvas/test/webgl/more/functions/drawElementsBadArgs.html
content/canvas/test/webgl/more/functions/getImageData.html
content/canvas/test/webgl/more/functions/getImageDataBadArgs.html
content/canvas/test/webgl/more/functions/isTests.html
content/canvas/test/webgl/more/functions/linkProgramBadArgs.html
content/canvas/test/webgl/more/functions/readPixels.html
content/canvas/test/webgl/more/functions/readPixelsBadArgs.html
content/canvas/test/webgl/more/functions/texImage2D.html
content/canvas/test/webgl/more/functions/texImage2DBadArgs.html
content/canvas/test/webgl/more/functions/texImage2DHTML.html
content/canvas/test/webgl/more/functions/texImage2DHTMLBadArgs.html
content/canvas/test/webgl/more/functions/texSubImage2D.html
content/canvas/test/webgl/more/functions/texSubImage2DBadArgs.html
content/canvas/test/webgl/more/functions/texSubImage2DHTML.html
content/canvas/test/webgl/more/functions/texSubImage2DHTMLBadArgs.html
content/canvas/test/webgl/more/functions/uniformMatrix.html
content/canvas/test/webgl/more/functions/uniformMatrixBadArgs.html
content/canvas/test/webgl/more/functions/uniformf.html
content/canvas/test/webgl/more/functions/uniformfBadArgs.html
content/canvas/test/webgl/more/functions/uniformi.html
content/canvas/test/webgl/more/functions/uniformiBadArgs.html
content/canvas/test/webgl/more/functions/vertexAttrib.html
content/canvas/test/webgl/more/functions/vertexAttribBadArgs.html
content/canvas/test/webgl/more/functions/vertexAttribPointer.html
content/canvas/test/webgl/more/functions/vertexAttribPointerBadArgs.html
content/canvas/test/webgl/more/glsl/arrayOutOfBounds.html
content/canvas/test/webgl/more/glsl/longLoops.html
content/canvas/test/webgl/more/glsl/uniformOutOfBounds.html
content/canvas/test/webgl/more/glsl/unusedAttribsUniforms.html
content/canvas/test/webgl/more/index.html
content/canvas/test/webgl/more/performance/CPUvsGPU.html
content/canvas/test/webgl/more/performance/bandwidth.html
content/canvas/test/webgl/more/performance/jsGCPause.html
content/canvas/test/webgl/more/performance/jsMatrixMult.html
content/canvas/test/webgl/more/performance/jsToGLOverhead.html
content/canvas/test/webgl/more/unit.css
content/canvas/test/webgl/more/unit.js
content/canvas/test/webgl/more/util.js
js/src/Makefile.in
js/src/configure.in
js/src/jit-test/tests/basic/bug633890.js
js/src/jsapi-tests/Makefile.in
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsarray.cpp
js/src/jsarray.h
js/src/jsatom.cpp
js/src/jsbool.cpp
js/src/jsbuiltins.cpp
js/src/jsbuiltins.h
js/src/jsclone.cpp
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsdbgapi.cpp
js/src/jsemit.cpp
js/src/jsemit.h
js/src/jsexn.cpp
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsgc.cpp
js/src/jsgc.h
js/src/jsgcinlines.h
js/src/jshashtable.h
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsinterp.h
js/src/jsinterpinlines.h
js/src/jsiter.cpp
js/src/jsmath.cpp
js/src/jsnum.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/jsobjinlines.h
js/src/json.cpp
js/src/jsopcode.tbl
js/src/jsparse.cpp
js/src/jsparse.h
js/src/jsprobes.cpp
js/src/jsreflect.cpp
js/src/jsregexp.cpp
js/src/jsregexpinlines.h
js/src/jsscope.h
js/src/jsscopeinlines.h
js/src/jsscript.cpp
js/src/jsscript.h
js/src/jsscriptinlines.h
js/src/jsstr.cpp
js/src/jstracer.cpp
js/src/jstracer.h
js/src/jstypedarray.cpp
js/src/jsval.h
js/src/jswrapper.cpp
js/src/jsxdrapi.h
js/src/jsxml.cpp
js/src/methodjit/Compiler.cpp
js/src/methodjit/FastBuiltins.cpp
js/src/methodjit/FastOps.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/PolyIC.cpp
js/src/methodjit/StubCalls.cpp
js/src/shell/Makefile.in
js/src/shell/js.cpp
js/src/tests/js1_8_5/regress/jstests.list
js/src/tracejit/Writer.cpp
modules/libpref/src/init/all.js
netwerk/base/public/nsISSLStatus.idl
netwerk/base/public/nsISSLStatusProvider.idl
netwerk/base/public/nsIX509Cert.idl
services/sync/tests/unit/test_utils_anno.js
--- a/.hgtags
+++ b/.hgtags
@@ -49,8 +49,9 @@ dba2abb7db57078c5a4810884834d3056a5d56c2
 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R9
 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R10
 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R11
 0327e126ea245112c0aa7283fee154e084866fb5 bsmedberg-static-xpcom-registration-base
 0327e126ea245112c0aa7283fee154e084866fb5 bsmedberg-static-xpcom-registration-base
 2f83edbbeef0de7dd901411d270da61106c8afae bsmedberg-static-xpcom-registration-base
 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R12
 138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R13
+138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R11_1_MU
--- a/accessible/src/atk/nsARIAGridAccessibleWrap.h
+++ b/accessible/src/atk/nsARIAGridAccessibleWrap.h
@@ -12,17 +12,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/atk/nsAccessibleWrap.cpp
+++ b/accessible/src/atk/nsAccessibleWrap.cpp
@@ -1076,17 +1076,17 @@ nsAccessibleWrap::FirePlatformEvent(AccE
 
     case nsIAccessibleEvent::EVENT_TEXT_REMOVED:
     case nsIAccessibleEvent::EVENT_TEXT_INSERTED:
         return FireAtkTextChangedEvent(aEvent, atkObj);
 
     case nsIAccessibleEvent::EVENT_FOCUS:
       {
         MAI_LOG_DEBUG(("\n\nReceived: EVENT_FOCUS\n"));
-        nsRefPtr<nsRootAccessible> rootAccWrap = accWrap->GetRootAccessible();
+        nsRootAccessible* rootAccWrap = accWrap->RootAccessible();
         if (rootAccWrap && rootAccWrap->mActivated) {
             atk_focus_tracker_notify(atkObj);
             // Fire state change event for focus
             nsRefPtr<AccEvent> stateChangeEvent =
               new AccStateChangeEvent(accessible,
                                       nsIAccessibleStates::STATE_FOCUSED,
                                       PR_FALSE, PR_TRUE);
             return FireAtkStateChangeEvent(stateChangeEvent, atkObj);
--- a/accessible/src/atk/nsXULListboxAccessibleWrap.h
+++ b/accessible/src/atk/nsXULListboxAccessibleWrap.h
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -214,17 +214,17 @@ NotificationController::WillRefresh(mozi
       return;
 
 #ifdef DEBUG_NOTIFICATIONS
     printf("\ninitial tree created, document: %p, document node: %p\n",
            mDocument.get(), mDocument->GetDocumentNode());
 #endif
 
     mTreeConstructedState = eTreeConstructed;
-    mDocument->CacheChildrenInSubtree(mDocument);
+    mDocument->NotifyOfInitialUpdate();
 
     NS_ASSERTION(mContentInsertions.Length() == 0,
                  "Pending content insertions while initial accessible tree isn't created!");
   }
 
   // Process content inserted notifications to update the tree. Process other
   // notifications like DOM events and then flush event queue. If any new
   // notifications are queued during this processing then they will be processed
--- a/accessible/src/base/a11yGeneric.h
+++ b/accessible/src/base/a11yGeneric.h
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@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"),
--- a/accessible/src/base/nsARIAGridAccessible.cpp
+++ b/accessible/src/base/nsARIAGridAccessible.cpp
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@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"),
--- a/accessible/src/base/nsARIAGridAccessible.h
+++ b/accessible/src/base/nsARIAGridAccessible.h
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@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"),
--- a/accessible/src/base/nsAccCache.h
+++ b/accessible/src/base/nsAccCache.h
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@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"),
--- a/accessible/src/base/nsAccessNode.cpp
+++ b/accessible/src/base/nsAccessNode.cpp
@@ -280,34 +280,34 @@ nsPresContext* nsAccessNode::GetPresCont
 
 nsDocAccessible *
 nsAccessNode::GetDocAccessible() const
 {
   return mContent ?
     GetAccService()->GetDocAccessible(mContent->GetOwnerDoc()) : nsnull;
 }
 
-already_AddRefed<nsRootAccessible> nsAccessNode::GetRootAccessible()
+nsRootAccessible*
+nsAccessNode::RootAccessible() const
 {
   nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
     nsCoreUtils::GetDocShellTreeItemFor(mContent);
   NS_ASSERTION(docShellTreeItem, "No docshell tree item for mContent");
   if (!docShellTreeItem) {
     return nsnull;
   }
   nsCOMPtr<nsIDocShellTreeItem> root;
   docShellTreeItem->GetRootTreeItem(getter_AddRefs(root));
   NS_ASSERTION(root, "No root content tree item");
   if (!root) {
     return nsnull;
   }
 
-  nsDocAccessible *docAcc = nsAccUtils::GetDocAccessibleFor(root);
-  nsRefPtr<nsRootAccessible> rootAcc = do_QueryObject(docAcc);
-  return rootAcc.forget();
+  nsDocAccessible* docAcc = nsAccUtils::GetDocAccessibleFor(root);
+  return docAcc ? docAcc->AsRoot() : nsnull;
 }
 
 nsIFrame*
 nsAccessNode::GetFrame() const
 {
   return mContent ? mContent->GetPrimaryFrame() : nsnull;
 }
 
@@ -342,18 +342,18 @@ nsAccessNode::GetDocument(nsIAccessibleD
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessNode::GetRootDocument(nsIAccessibleDocument **aRootDocument)
 {
   NS_ENSURE_ARG_POINTER(aRootDocument);
 
-  nsRefPtr<nsRootAccessible> rootDocument = GetRootAccessible();
-  NS_IF_ADDREF(*aRootDocument = rootDocument.get());
+  nsRootAccessible* rootDocument = RootAccessible();
+  NS_IF_ADDREF(*aRootDocument = rootDocument);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAccessNode::GetInnerHTML(nsAString& aInnerHTML)
 {
   aInnerHTML.Truncate();
 
--- a/accessible/src/base/nsAccessNode.h
+++ b/accessible/src/base/nsAccessNode.h
@@ -100,17 +100,17 @@ public:
   /**
    * Return the document accessible for this access node.
    */
   nsDocAccessible *GetDocAccessible() const;
 
   /**
    * Return the root document accessible for this accessnode.
    */
-  already_AddRefed<nsRootAccessible> GetRootAccessible();
+  nsRootAccessible* RootAccessible() const;
 
   /**
    * Reference to a node of focused accessible.
    */
   static nsINode *gLastFocusedNode;
 
   /**
    * Return focused node within accessible window.
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -555,16 +555,31 @@ nsAccessibilityService::PresShellDestroy
   NS_LOG_ACCDOCDESTROY("presshell destroyed", doc)
 
   nsDocAccessible* docAccessible = GetDocAccessibleFromCache(doc);
   if (docAccessible)
     docAccessible->Shutdown();
 }
 
 void
+nsAccessibilityService::PresShellActivated(nsIPresShell* aPresShell)
+{
+  nsIDocument* DOMDoc = aPresShell->GetDocument();
+  if (DOMDoc) {
+    nsDocAccessible* document = GetDocAccessibleFromCache(DOMDoc);
+    if (document) {
+      nsRootAccessible* rootDocument = document->RootAccessible();
+      NS_ASSERTION(rootDocument, "Entirely broken tree: no root document!");
+      if (rootDocument)
+        rootDocument->DocumentActivated(document);
+    }
+  }
+}
+
+void
 nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
                                            nsIContent* aContent)
 {
   nsDocAccessible* document = GetDocAccessible(aPresShell->GetDocument());
   if (document) {
     document->HandleNotification<nsDocAccessible, nsIContent>
       (document, &nsDocAccessible::RecreateAccessible, aContent);
   }
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -119,16 +119,21 @@ public:
                               nsIContent* aChild);
 
   virtual void UpdateText(nsIPresShell* aPresShell, nsIContent* aContent);
 
   virtual void NotifyOfAnchorJumpTo(nsIContent *aTarget);
 
   virtual void PresShellDestroyed(nsIPresShell* aPresShell);
 
+  /**
+   * Notify that presshell is activated.
+   */
+  virtual void PresShellActivated(nsIPresShell* aPresShell);
+
   virtual void RecreateAccessible(nsIPresShell* aPresShell,
                                   nsIContent* aContent);
 
   virtual void FireAccessibleEvent(PRUint32 aEvent, nsAccessible* aTarget);
 
   // nsAccessibiltiyService
 
   /**
--- a/accessible/src/base/nsAccessible.h
+++ b/accessible/src/base/nsAccessible.h
@@ -359,16 +359,19 @@ public:
   //////////////////////////////////////////////////////////////////////////////
   // Downcasting
 
   inline bool IsApplication() const { return mFlags & eApplicationAccessible; }
 
   inline bool IsHyperText() const { return mFlags & eHyperTextAccessible; }
   nsHyperTextAccessible* AsHyperText();
 
+  inline bool IsRoot() const { return mFlags & eRootAccessible; }
+  nsRootAccessible* AsRoot();
+
   inline bool IsTextLeaf() const { return mFlags & eTextLeafAccessible; }
   nsTextAccessible* AsTextLeaf();
 
   //////////////////////////////////////////////////////////////////////////////
   // HyperLinkAccessible
 
   /**
    * Return true if the accessible is hyper link accessible.
@@ -504,17 +507,18 @@ protected:
 
   /**
    * Flags describing the accessible itself.
    * @note keep these flags in sync with ChildrenFlags
    */
   enum AccessibleTypes {
     eApplicationAccessible = 1 << 2,
     eHyperTextAccessible = 1 << 3,
-    eTextLeafAccessible = 1 << 4
+    eRootAccessible = 1 << 4,
+    eTextLeafAccessible = 1 << 5
   };
 
   //////////////////////////////////////////////////////////////////////////////
   // Miscellaneous helpers
 
   /**
    * Return ARIA role (helper method).
    */
--- a/accessible/src/base/nsDocAccessible.cpp
+++ b/accessible/src/base/nsDocAccessible.cpp
@@ -765,17 +765,17 @@ nsresult nsDocAccessible::AddEventListen
     if (commandManager) {
       commandManager->AddCommandObserver(this, "obs_documentCreated");
     }
   }
 
   nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
   docShellTreeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
   if (rootTreeItem) {
-    nsRefPtr<nsRootAccessible> rootAccessible = GetRootAccessible();
+    nsRootAccessible* rootAccessible = RootAccessible();
     NS_ENSURE_TRUE(rootAccessible, NS_ERROR_FAILURE);
     nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
     if (caretAccessible) {
       caretAccessible->AddDocSelectionListener(presShell);
     }
   }
 
   // add document observer
@@ -812,17 +812,17 @@ nsresult nsDocAccessible::RemoveEventLis
   }
 
   if (mScrollWatchTimer) {
     mScrollWatchTimer->Cancel();
     mScrollWatchTimer = nsnull;
     NS_RELEASE_THIS(); // Kung fu death grip
   }
 
-  nsRefPtr<nsRootAccessible> rootAccessible(GetRootAccessible());
+  nsRootAccessible* rootAccessible = RootAccessible();
   if (rootAccessible) {
     nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
     if (caretAccessible) {
       // Don't use GetPresShell() which can call Shutdown() if it sees dead pres shell
       nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
       caretAccessible->RemoveDocSelectionListener(presShell);
     }
   }
@@ -1130,17 +1130,17 @@ nsDocAccessible::ARIAAttributeChanged(ns
   }
 
   if (aAttribute == nsAccessibilityAtoms::aria_activedescendant) {
     // The activedescendant universal property redirects accessible focus events
     // to the element with the id that activedescendant points to
     nsCOMPtr<nsINode> focusedNode = GetCurrentFocus();
     if (nsCoreUtils::GetRoleContent(focusedNode) == aContent) {
       nsAccessible* focusedAcc = GetAccService()->GetAccessible(focusedNode);
-      nsRefPtr<nsRootAccessible> rootAcc = GetRootAccessible();
+      nsRootAccessible* rootAcc = RootAccessible();
       if (rootAcc && focusedAcc) {
         rootAcc->FireAccessibleFocusEvent(focusedAcc, nsnull, PR_TRUE);
       }
     }
     return;
   }
 
   // For aria drag and drop changes we fire a generic attribute change event;
@@ -1496,16 +1496,30 @@ nsDocAccessible::CacheChildren()
   nsRefPtr<nsAccessible> child;
   while ((child = walker.GetNextChild()) && AppendChild(child));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Protected members
 
 void
+nsDocAccessible::NotifyOfInitialUpdate()
+{
+  // The content element may be changed before the initial update and then we
+  // miss the notification (since content tree change notifications are ignored
+  // prior to initial update). Make sure the content element is valid.
+  nsIContent* contentElm = nsCoreUtils::GetRoleContent(mDocument);
+  if (contentElm && mContent != contentElm)
+    mContent = contentElm;
+
+  // Build initial tree.
+  CacheChildrenInSubtree(this);
+}
+
+void
 nsDocAccessible::AddDependentIDsFor(nsAccessible* aRelProvider,
                                     nsIAtom* aRelAttr)
 {
   for (PRUint32 idx = 0; idx < kRelationAttrsLen; idx++) {
     nsIAtom* relAttr = *kRelationAttrs[idx];
     if (aRelAttr && aRelAttr != relAttr)
       continue;
 
--- a/accessible/src/base/nsDocAccessible.h
+++ b/accessible/src/base/nsDocAccessible.h
@@ -340,16 +340,23 @@ protected:
 
   // nsAccessible
   virtual void CacheChildren();
 
   // nsDocAccessible
     virtual void GetBoundsRect(nsRect& aRect, nsIFrame** aRelativeFrame);
     virtual nsresult AddEventListeners();
     virtual nsresult RemoveEventListeners();
+
+  /**
+   * Notify this document that was bound to the accessible document tree.
+   * Can be overridden by wrappers to prepare initialization work.
+   */
+  virtual void NotifyOfInitialUpdate();
+
     void AddScrollListener();
     void RemoveScrollListener();
 
   /**
    * Append the given document accessible to this document's child document
    * accessibles.
    */
   bool AppendChildDocument(nsDocAccessible* aChildDocument)
--- a/accessible/src/base/nsEventShell.cpp
+++ b/accessible/src/base/nsEventShell.cpp
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@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"),
--- a/accessible/src/base/nsEventShell.h
+++ b/accessible/src/base/nsEventShell.h
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@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"),
--- a/accessible/src/base/nsRootAccessible.cpp
+++ b/accessible/src/base/nsRootAccessible.cpp
@@ -107,16 +107,17 @@ NS_IMPL_RELEASE_INHERITED(nsRootAccessib
 ////////////////////////////////////////////////////////////////////////////////
 // Constructor/desctructor
 
 nsRootAccessible::
   nsRootAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
                    nsIWeakReference *aShell) :
   nsDocAccessibleWrap(aDocument, aRootContent, aShell)
 {
+  mFlags |= eRootAccessible;
 }
 
 nsRootAccessible::~nsRootAccessible()
 {
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessible
@@ -303,16 +304,19 @@ nsresult nsRootAccessible::RemoveEventLi
   if (mCaretAccessible) {
     mCaretAccessible->Shutdown();
     mCaretAccessible = nsnull;
   }
 
   return NS_OK;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// public
+
 nsCaretAccessible*
 nsRootAccessible::GetCaretAccessible()
 {
   return mCaretAccessible;
 }
 
 void
 nsRootAccessible::FireAccessibleFocusEvent(nsAccessible* aFocusAccessible,
@@ -430,16 +434,21 @@ nsRootAccessible::FireCurrentFocusEvent(
       nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
       nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(focusedNode));
       privateEvent->SetTarget(target);
       HandleEvent(event);
     }
   }
 }
 
+void
+nsRootAccessible::DocumentActivated(nsDocAccessible* aDocument)
+{
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // nsIDOMEventListener
 
 NS_IMETHODIMP
 nsRootAccessible::HandleEvent(nsIDOMEvent* aDOMEvent)
 {
   nsCOMPtr<nsIDOMNSEvent> DOMNSEvent(do_QueryInterface(aDOMEvent));
   nsCOMPtr<nsIDOMEventTarget> DOMEventTarget;
--- a/accessible/src/base/nsRootAccessible.h
+++ b/accessible/src/base/nsRootAccessible.h
@@ -119,16 +119,21 @@ public:
     /**
       * Fire an accessible focus event for the current focused node,
       * if there is a focus.
       */
     void FireCurrentFocusEvent();
 
     nsCaretAccessible *GetCaretAccessible();
 
+  /**
+   * Notify that the sub document presshell was activated.
+   */
+  virtual void DocumentActivated(nsDocAccessible* aDocument);
+
 protected:
   NS_DECL_RUNNABLEMETHOD(nsRootAccessible, FireCurrentFocusEvent)
 
   /**
    * Add/remove DOM event listeners.
    */
   virtual nsresult AddEventListeners();
   virtual nsresult RemoveEventListeners();
@@ -159,9 +164,16 @@ protected:
     already_AddRefed<nsIDocShellTreeItem>
            GetContentDocShell(nsIDocShellTreeItem *aStart);
     nsRefPtr<nsCaretAccessible> mCaretAccessible;
   nsCOMPtr<nsINode> mCurrentARIAMenubar;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsRootAccessible, NS_ROOTACCESSIBLE_IMPL_CID)
 
+inline nsRootAccessible*
+nsAccessible::AsRoot()
+{
+  return mFlags & eRootAccessible ?
+    static_cast<nsRootAccessible*>(this) : nsnull;
+}
+
 #endif
--- a/accessible/src/mac/mozAccessible.mm
+++ b/accessible/src/mac/mozAccessible.mm
@@ -360,17 +360,17 @@ GetNativeFromGeckoAccessible(nsIAccessib
       return GetClosestInterestingAccessible(nativeParent);
   }
   
   // GetUnignoredParent() returns null when there is no unignored accessible all the way up to
   // the root accessible. so we'll have to return whatever native accessible is above our root accessible 
   // (which might be the owning NSWindow in the application, for example).
   //
   // get the native root accessible, and tell it to return its first parent unignored accessible.
-  nsRefPtr<nsRootAccessible> root(mGeckoAccessible->GetRootAccessible());
+  nsRootAccessible* root = mGeckoAccessible->RootAccessible();
   id nativeParent = GetNativeFromGeckoAccessible(static_cast<nsIAccessible*>(root));
   NSAssert1 (nativeParent, @"!!! we can't find a parent for %@", self);
   
   return GetClosestInterestingAccessible(nativeParent);
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
--- a/accessible/src/mac/nsARIAGridAccessibleWrap.h
+++ b/accessible/src/mac/nsARIAGridAccessibleWrap.h
@@ -12,17 +12,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/mac/nsXULListboxAccessibleWrap.h
+++ b/accessible/src/mac/nsXULListboxAccessibleWrap.h
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/msaa/CAccessibleTableCell.cpp
+++ b/accessible/src/msaa/CAccessibleTableCell.cpp
@@ -12,17 +12,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/msaa/CAccessibleTableCell.h
+++ b/accessible/src/msaa/CAccessibleTableCell.h
@@ -12,17 +12,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/msaa/Makefile.in
+++ b/accessible/src/msaa/Makefile.in
@@ -48,16 +48,17 @@ LIBXUL_LIBRARY = 1
 
 CPPSRCS = \
   nsAccessNodeWrap.cpp \
   nsAccessibleWrap.cpp \
   nsTextAccessibleWrap.cpp \
   nsDocAccessibleWrap.cpp \
   nsHTMLWin32ObjectAccessible.cpp \
   nsARIAGridAccessibleWrap.cpp \
+  nsRootAccessibleWrap.cpp \
   nsXULMenuAccessibleWrap.cpp \
   nsXULListboxAccessibleWrap.cpp \
   nsXULTreeGridAccessibleWrap.cpp \
   nsHyperTextAccessibleWrap.cpp \
   nsHTMLImageAccessibleWrap.cpp \
   nsHTMLTableAccessibleWrap.cpp \
   nsAccessibleRelationWrap.cpp \
   nsApplicationAccessibleWrap.cpp \
--- a/accessible/src/msaa/nsARIAGridAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsARIAGridAccessibleWrap.cpp
@@ -12,17 +12,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/msaa/nsARIAGridAccessibleWrap.h
+++ b/accessible/src/msaa/nsARIAGridAccessibleWrap.h
@@ -12,17 +12,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -771,16 +771,23 @@ nsAccessNodeWrap::WindowProc(HWND hWnd, 
                                                msaaAccessible); // does an addref
             msaaAccessible->Release(); // release extra addref
             return result;
           }
         }
       }
       return 0;
     }
+    case WM_NCHITTEST:
+    {
+      LRESULT lRet = ::DefWindowProc(hWnd, msg, wParam, lParam);
+      if (HTCLIENT == lRet)
+        lRet = HTTRANSPARENT;
+      return lRet;
+    }
   }
 
   return ::DefWindowProcW(hWnd, msg, wParam, lParam);
 }
 
 STDMETHODIMP_(LRESULT)
 nsAccessNodeWrap::LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc)
 {
--- a/accessible/src/msaa/nsAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsAccessibleWrap.cpp
@@ -1767,17 +1767,17 @@ nsAccessibleWrap::GetXPAccessibleFor(con
 }
 
 void nsAccessibleWrap::UpdateSystemCaret()
 {
   // Move the system caret so that Windows Tablet Edition and tradional ATs with 
   // off-screen model can follow the caret
   ::DestroyCaret();
 
-  nsRefPtr<nsRootAccessible> rootAccessible = GetRootAccessible();
+  nsRootAccessible* rootAccessible = RootAccessible();
   if (!rootAccessible) {
     return;
   }
 
   nsRefPtr<nsCaretAccessible> caretAccessible = rootAccessible->GetCaretAccessible();
   if (!caretAccessible) {
     return;
   }
--- a/accessible/src/msaa/nsDocAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp
@@ -247,38 +247,16 @@ STDMETHODIMP nsDocAccessibleWrap::get_ac
     return hr;
 
   return get_URL(pszValue);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsAccessNode
 
-PRBool
-nsDocAccessibleWrap::Init()
-{
-  if (nsWinUtils::IsWindowEmulationEnabled()) {
-    // Create window for tab document.
-    if (nsWinUtils::IsTabDocument(mDocument)) {
-      nsRefPtr<nsRootAccessible> root = GetRootAccessible();
-      mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent,
-                                             static_cast<HWND>(root->GetNativeWindow()));
-
-      nsAccessibleWrap::sHWNDCache.Put(mHWND, this);
-
-    } else {
-      nsDocAccessible* parentDocument = ParentDocument();
-      if (parentDocument)
-        mHWND = parentDocument->GetNativeWindow();
-    }
-  }
-
-  return nsDocAccessible::Init();
-}
-
 void
 nsDocAccessibleWrap::Shutdown()
 {
   if (nsWinUtils::IsWindowEmulationEnabled()) {
     // Destroy window created for root document.
     if (nsWinUtils::IsTabDocument(mDocument)) {
       nsAccessibleWrap::sHWNDCache.Remove(mHWND);
       ::DestroyWindow(static_cast<HWND>(mHWND));
@@ -286,15 +264,56 @@ nsDocAccessibleWrap::Shutdown()
 
     mHWND = nsnull;
   }
 
   nsDocAccessible::Shutdown();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-// nsDocAccessible
+// nsDocAccessible public
 
 void*
 nsDocAccessibleWrap::GetNativeWindow() const
 {
   return mHWND ? mHWND : nsDocAccessible::GetNativeWindow();
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// nsDocAccessible protected
+
+void
+nsDocAccessibleWrap::NotifyOfInitialUpdate()
+{
+  nsDocAccessible::NotifyOfInitialUpdate();
+
+  if (nsWinUtils::IsWindowEmulationEnabled()) {
+    // Create window for tab document.
+    if (nsWinUtils::IsTabDocument(mDocument)) {
+      nsRootAccessible* rootDocument = RootAccessible();
+
+      PRBool isActive = PR_TRUE;
+      PRInt32 x = CW_USEDEFAULT, y = CW_USEDEFAULT, width = 0, height = 0;
+      if (nsWinUtils::IsWindowEmulationEnabled(kDolphinModuleHandle)) {
+        GetBounds(&x, &y, &width, &height);
+        PRInt32 rootX = 0, rootY = 0, rootWidth = 0, rootHeight = 0;
+        rootDocument->GetBounds(&rootX, &rootY, &rootWidth, &rootHeight);
+        x = rootX - x;
+        y -= rootY;
+
+        nsCOMPtr<nsISupports> container = mDocument->GetContainer();
+        nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
+        docShell->GetIsActive(&isActive);
+      }
+
+      HWND parentWnd = static_cast<HWND>(rootDocument->GetNativeWindow());
+      mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent, parentWnd,
+                                             x, y, width, height, isActive);
+
+      nsAccessibleWrap::sHWNDCache.Put(mHWND, this);
+
+    } else {
+      nsDocAccessible* parentDocument = ParentDocument();
+      if (parentDocument)
+        mHWND = parentDocument->GetNativeWindow();
+    }
+  }
+}
--- a/accessible/src/msaa/nsDocAccessibleWrap.h
+++ b/accessible/src/msaa/nsDocAccessibleWrap.h
@@ -85,22 +85,25 @@ public:
     // IAccessible
 
     // Override get_accValue to provide URL when no other value is available
     virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accValue( 
         /* [optional][in] */ VARIANT varChild,
         /* [retval][out] */ BSTR __RPC_FAR *pszValue);
 
   // nsAccessNode
-  virtual PRBool Init();
   virtual void Shutdown();
 
   // nsAccessibleWrap
   virtual nsAccessible *GetXPAccessibleFor(const VARIANT& varChild);
 
   // nsDocAccessible
   virtual void* GetNativeWindow() const;
 
 protected:
+  // nsDocAccessible
+  virtual void NotifyOfInitialUpdate();
+
+protected:
   void* mHWND;
 };
 
 #endif
new file mode 100644
--- /dev/null
+++ b/accessible/src/msaa/nsRootAccessibleWrap.cpp
@@ -0,0 +1,78 @@
+/* -*- 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 Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Alexander Surkov <surkov.alexander@gmail.com> (origianl 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 ***** */
+
+#include "nsRootAccessibleWrap.h"
+
+#include "nsWinUtils.h"
+
+#include "nsIDOMEventTarget.h"
+#include "nsIEventListenerManager.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// Constructor/desctructor
+
+nsRootAccessibleWrap::
+  nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
+                       nsIWeakReference* aShell) :
+  nsRootAccessible(aDocument, aRootContent, aShell)
+{
+}
+
+nsRootAccessibleWrap::~nsRootAccessibleWrap()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsRootAccessible
+
+void
+nsRootAccessibleWrap::DocumentActivated(nsDocAccessible* aDocument)
+{
+  if (nsWinUtils::IsWindowEmulationEnabled(kDolphinModuleHandle) &&
+      nsWinUtils::IsTabDocument(aDocument->GetDocumentNode())) {
+    PRUint32 count = mChildDocuments.Length();
+    for (PRUint32 idx = 0; idx < count; idx++) {
+      nsDocAccessible* childDoc = mChildDocuments[idx];
+      HWND childDocHWND = static_cast<HWND>(childDoc->GetNativeWindow());
+      if (childDoc != aDocument)
+        nsWinUtils::HideNativeWindow(childDocHWND);
+      else
+        nsWinUtils::ShowNativeWindow(childDocHWND);
+    }
+  }
+}
--- a/accessible/src/msaa/nsRootAccessibleWrap.h
+++ b/accessible/src/msaa/nsRootAccessibleWrap.h
@@ -15,36 +15,42 @@
  * The Original Code is mozilla.org code.
  *
  * The Initial Developer of the Original Code is
  * Netscape Communications Corporation.
  * Portions created by the Initial Developer are Copyright (C) 2003
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
- *   Original Author: Aaron Leventhal (aaronl@netscape.com)
+ *   Aaron Leventhal <aaronl@netscape.com> (original author)
+ *   Alexander Surkov <surkov.alexander@gmail.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 ***** */
 
-/* For documentation of the accessibility architecture, 
- * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
- */
-
 #ifndef _nsRootAccessibleWrap_H_
 #define _nsRootAccessibleWrap_H_
 
 #include "nsRootAccessible.h"
 
-typedef class nsRootAccessible nsRootAccessibleWrap;
+class nsRootAccessibleWrap : public nsRootAccessible
+{
+public:
+  nsRootAccessibleWrap(nsIDocument* aDocument, nsIContent* aRootContent,
+                       nsIWeakReference* aShell);
+  virtual ~nsRootAccessibleWrap();
+
+  // nsRootAccessible
+  virtual void DocumentActivated(nsDocAccessible* aDocument);
+};
 
 #endif
--- a/accessible/src/msaa/nsWinUtils.cpp
+++ b/accessible/src/msaa/nsWinUtils.cpp
@@ -12,17 +12,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -35,18 +35,19 @@
  * 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 "nsWinUtils.h"
 
-#include "nsAccessibleWrap.h"
 #include "nsIWinAccessNode.h"
+#include "nsRootAccessible.h"
+
 #include "nsArrayUtils.h"
 #include "nsIDocShellTreeItem.h"
 
 HRESULT
 nsWinUtils::ConvertToIA2Array(nsIArray *aGeckoArray, IUnknown ***aIA2Array,
                               long *aIA2ArrayLen)
 {
   *aIA2Array = NULL;
@@ -111,35 +112,51 @@ nsWinUtils::RegisterNativeWindow(LPCWSTR
   wc.hCursor = NULL;
   wc.hbrBackground = NULL;
   wc.lpszMenuName = NULL;
   wc.lpszClassName = aWindowClass;
   ::RegisterClassW(&wc);
 }
 
 HWND
-nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd)
+nsWinUtils::CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd,
+                               int aX, int aY, int aWidth, int aHeight,
+                               bool aIsActive)
 {
-  return ::CreateWindowW(aWindowClass,
-                         L"NetscapeDispatchWnd",
-                         WS_CHILD | WS_VISIBLE,
-                         CW_USEDEFAULT, CW_USEDEFAULT,
-                         0, 0,
-                         aParentWnd,
-                         NULL,
-                         GetModuleHandle(NULL),
-                         NULL);
+  return ::CreateWindowExW(WS_EX_TRANSPARENT, aWindowClass,
+                           L"NetscapeDispatchWnd",
+                           WS_CHILD | (aIsActive ? WS_VISIBLE : 0),
+                           aX, aY, aWidth, aHeight,
+                           aParentWnd,
+                           NULL,
+                           GetModuleHandle(NULL),
+                           NULL);
+}
+
+void
+nsWinUtils::ShowNativeWindow(HWND aWnd)
+{
+  ::ShowWindow(aWnd, SW_SHOW);
+}
+
+void
+nsWinUtils::HideNativeWindow(HWND aWnd)
+{
+  ::SetWindowPos(aWnd, NULL, 0, 0, 0, 0,
+                 SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
+                 SWP_NOZORDER | SWP_NOACTIVATE);
 }
 
 bool
-nsWinUtils::IsWindowEmulationEnabled()
+nsWinUtils::IsWindowEmulationEnabled(LPCWSTR kModuleHandle)
 {
-  return ::GetModuleHandleW(kJAWSModuleHandle) ||
+  return kModuleHandle ? ::GetModuleHandleW(kModuleHandle) :
+    ::GetModuleHandleW(kJAWSModuleHandle) ||
     ::GetModuleHandleW(kWEModuleHandle)  ||
-    ::GetModuleHandleW(kDolphnModuleHandle);
+    ::GetModuleHandleW(kDolphinModuleHandle);
 }
 
 bool
 nsWinUtils::IsTabDocument(nsIDocument* aDocumentNode)
 {
   nsCOMPtr<nsISupports> container = aDocumentNode->GetContainer();
   nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
 
--- a/accessible/src/msaa/nsWinUtils.h
+++ b/accessible/src/msaa/nsWinUtils.h
@@ -12,17 +12,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -46,17 +46,17 @@
 #include "nsIArray.h"
 #include "nsIDocument.h"
 
 const LPCWSTR kClassNameRoot = L"MozillaUIWindowClass";
 const LPCWSTR kClassNameTabContent = L"MozillaContentWindowClass";
 
 const LPCWSTR kJAWSModuleHandle = L"jhook";
 const LPCWSTR kWEModuleHandle = L"gwm32inc";
-const LPCWSTR kDolphnModuleHandle = L"dolwinhk";
+const LPCWSTR kDolphinModuleHandle = L"dolwinhk";
 
 class nsWinUtils
 {
 public:
   /**
    * Convert nsIArray array of accessible objects to an array of IUnknown*
    * objects used in IA2 methods.
    */
@@ -66,22 +66,34 @@ public:
   /**
    * Helper to register window class.
    */
   static void RegisterNativeWindow(LPCWSTR aWindowClass);
 
   /**
    * Helper to create a window.
    */
-  static HWND CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd);
+  static HWND CreateNativeWindow(LPCWSTR aWindowClass, HWND aParentWnd,
+                                 int aX, int aY, int aWidth, int aHeight,
+                                 bool aIsActive);
+
+  /**
+   * Helper to show window.
+   */
+  static void ShowNativeWindow(HWND aWnd);
+
+  /**
+   * Helper to hide window.
+   */
+  static void HideNativeWindow(HWND aWnd);
 
   /**
    * Return true if window emulation is enabled.
    */
-  static bool IsWindowEmulationEnabled();
+  static bool IsWindowEmulationEnabled(LPCWSTR kModuleHandle = 0);
 
   /**
    * Return true if the given document node is for tab document accessible.
    */
   static bool IsTabDocument(nsIDocument* aDocumentNode);
 };
 
 #endif
--- a/accessible/src/msaa/nsXULListboxAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsXULListboxAccessibleWrap.cpp
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/msaa/nsXULListboxAccessibleWrap.h
+++ b/accessible/src/msaa/nsXULListboxAccessibleWrap.h
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/other/nsARIAGridAccessibleWrap.h
+++ b/accessible/src/other/nsARIAGridAccessibleWrap.h
@@ -12,17 +12,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/other/nsXULListboxAccessibleWrap.h
+++ b/accessible/src/other/nsXULListboxAccessibleWrap.h
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@gmail.com> (original author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
--- a/accessible/src/xul/nsXULTreeGridAccessible.cpp
+++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@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"),
--- a/accessible/src/xul/nsXULTreeGridAccessible.h
+++ b/accessible/src/xul/nsXULTreeGridAccessible.h
@@ -10,17 +10,17 @@
  * 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.
+ * Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2009
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Alexander Surkov <surkov.alexander@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"),
--- a/accessible/tests/mochitest/Makefile.in
+++ b/accessible/tests/mochitest/Makefile.in
@@ -95,22 +95,22 @@ include $(topsrcdir)/config/rules.mk
 		test_elm_landmarks.html \
 		test_elm_listbox.xul \
 	$(warning   test_elm_media.html temporarily disabled) \
 		test_elm_nsApplicationAcc.html \
 		test_elm_plugin.html \
 		test_keys.html \
 	$(warning test_nsIAccessible_comboboxes.xul temporarily disabled) \
  		test_nsIAccessible_selects.html \
-		test_nsIAccessible_focus.html \
 		test_nsIAccessibleDocument.html \
 		test_nsIAccessibleImage.html \
 		test_nsIAccessNode_utils.html \
 		test_nsOuterDocAccessible.html \
 		test_role_nsHyperTextAcc.html \
+		test_takeFocus.html \
 		test_text_caret.html \
 		test_textboxes.html \
 		test_textboxes.xul \
 		test_value.html \
 		test_value.xul \
 		testTextboxes.js \
 		text.js \
 		treeview.css \
--- a/accessible/tests/mochitest/states.js
+++ b/accessible/tests/mochitest/states.js
@@ -54,23 +54,24 @@ const EXT_STATE_VERTICAL = nsIAccessible
  * In addition, the function performs a few plausibility checks derived from the
  * sstates and extra states passed in.
  *
  * @param aAccOrElmOrID      The accessible, DOM element or ID to be tested.
  * @param aState             The state bits that are wanted.
  * @param aExtraState        The extra state bits that are wanted.
  * @param aAbsentState       State bits that are not wanted.
  * @param aAbsentExtraState  Extra state bits that are not wanted.
+ * @param aTestName          The test name.
  */
 function testStates(aAccOrElmOrID, aState, aExtraState, aAbsentState,
-                    aAbsentExtraState)
+                    aAbsentExtraState, aTestName)
 {
   var [state, extraState] = getStates(aAccOrElmOrID);
 
-  var id = prettyName(aAccOrElmOrID);
+  var id = prettyName(aAccOrElmOrID) + (aTestName ? " [" + aTestName + "]": "");
 
   // Primary test.
   isState(state & aState, aState, false,
           "wrong state bits for " + id + "!");
 
   if (aExtraState)
     isState(extraState & aExtraState, aExtraState, true,
             "wrong extra state bits for " + id + "!");
--- a/accessible/tests/mochitest/states/Makefile.in
+++ b/accessible/tests/mochitest/states/Makefile.in
@@ -40,30 +40,29 @@ DEPTH		= ../../../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = accessible/states
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
-# temporarily disabled test (bug 562328)
-#  test_frames.html \
-
 _TEST_FILES =\
 		test_aria.html \
 		test_aria_imgmap.html \
 		test_doc.html \
 		test_docarticle.html \
 		test_editablebody.html \
+		test_frames.html \
 		test_inputs.html \
 		test_inputs.xul \
 		test_link.html \
 		test_popup.xul \
 		test_tree.xul \
 		z_frames.html \
 		z_frames_article.html \
 		z_frames_checkbox.html \
 		z_frames_textbox.html \
+		z_frames_update.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
--- a/accessible/tests/mochitest/states/test_doc.html
+++ b/accessible/tests/mochitest/states/test_doc.html
@@ -79,10 +79,11 @@
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
 
   <p id="p">hello</p>
 
   <div id="document" role="document">document</div>
   <div id="editable_document" role="document" contentEditable="true">editable document</doc>
+
 </body>
 </html>
--- a/accessible/tests/mochitest/states/test_frames.html
+++ b/accessible/tests/mochitest/states/test_frames.html
@@ -18,52 +18,65 @@
 
   <script type="application/javascript">
     function doTest()
     {
       frameDoc = document.getElementById("frame_doc").contentDocument;
       frameDocArticle = document.getElementById("frame_doc_article").contentDocument;
       frameDocCheckbox = document.getElementById("frame_doc_checkbox").contentDocument;
       frameDocTextbox = document.getElementById("frame_doc_textbox").contentDocument;
-      
-      testStates(frameDoc, STATE_READONLY);
-      testStates(frameDocArticle, STATE_READONLY);
-      testStates(frameDocCheckbox, 0, 0, STATE_READONLY);
-      testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE);
+
+      testStates(frameDoc, STATE_READONLY, 0, 0, 0, "test1: frameDoc");
+      testStates(frameDocArticle, STATE_READONLY, 0, 0, 0, "test1: frameDocArticle");
+      testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0, "test1: frameDocCheckbox");
+      testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, 0, 0, "test1: frameDocTextbox");
 
       frameDoc.designMode = "on";
-      testStates(frameDoc,  0, EXT_STATE_EDITABLE);
-      testStates(frameDocArticle, STATE_READONLY);
-      testStates(frameDocCheckbox, 0, 0, STATE_READONLY);
-      testStates(frameDocTextbox,  0, EXT_STATE_EDITABLE);
+      testStates(frameDoc,  0, EXT_STATE_EDITABLE, 0, 0, "test2: frameDoc");
+      testStates(frameDocArticle, STATE_READONLY, 0, 0, 0, "test2: frameDocArticle");
+      testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0, "test2: frameDocCheckbox");
+      testStates(frameDocTextbox, 0, EXT_STATE_EDITABLE, 0, 0, "test2: frameDocTextbox");
 
       frameDocArticle.designMode = "on";
-      testStates(frameDocArticle, 0, EXT_STATE_EDITABLE);
+      testStates(frameDocArticle, 0, EXT_STATE_EDITABLE, 0, 0, "test3: frameDocArticle");
 
       frameDocCheckbox.designMode = "on";
-      testStates(frameDocCheckbox, 0, 0, STATE_READONLY);
-      
+      testStates(frameDocCheckbox, 0, 0, STATE_READONLY, 0, "test4: frameDocCheckbox");
+
+      // Replace iframe document body before the document accessible tree is
+      // created. Check the states are updated for new body.
+      var frameUpdateDoc =
+        document.getElementById("frame_updatedoc").contentDocument;
+      testStates(frameUpdateDoc, 0, EXT_STATE_EDITABLE,
+                 STATE_READONLY, EXT_STATE_STALE, "test5: frameUpdateDoc");
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   </script>
 </head>
 
 <body>
 
   <a target="_blank"
-    href="https://bugzilla.mozilla.org/show_bug.cgi?id=467387"
-    title="Expose non-editable documents as readonly, regardless of role">
-     Mozilla Bug 467387
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=467387"
+     title="Expose non-editable documents as readonly, regardless of role">
+    Mozilla Bug 467387
+  </a>
+  <a target="_blank"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=638106"
+     title="CKEditor document should be editable">
+    Mozilla Bug 638106
   </a>
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
-  
+
   <iframe id="frame_doc" src="z_frames.html"></iframe>
   <iframe id="frame_doc_article" src="z_frames_article.html"></iframe>
   <iframe id="frame_doc_checkbox" src="z_frames_checkbox.html"></iframe>
   <iframe id="frame_doc_textbox" src="z_frames_textbox.html"></iframe>
+  <iframe id="frame_updatedoc" src="z_frames_update.html"></iframe>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/states/z_frames_update.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+<script>
+function replaceBody()
+{
+  var accRetrieval = Components.classes["@mozilla.org/accessibleRetrieval;1"].
+    getService(Components.interfaces.nsIAccessibleRetrieval);
+  accRetrieval.getAccessibleFor(document);
+
+  var newBody = document.createElement("body");
+  newBody.setAttribute("contentEditable", "true");
+  newBody.textContent = "New Hello";
+  document.documentElement.replaceChild(newBody, document.body);
+  getComputedStyle(newBody, "").color;
+}
+</script>
+</head>
+<body onload="replaceBody();">
+OLD hello
+</body>
+</html>
+
rename from accessible/tests/mochitest/test_nsIAccessible_focus.html
rename to accessible/tests/mochitest/test_takeFocus.html
--- a/accessible/tests/mochitest/test_nsIAccessible_focus.html
+++ b/accessible/tests/mochitest/test_takeFocus.html
@@ -8,123 +8,61 @@
 
   <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js"></script>
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <script type="application/javascript"
           src="common.js"></script>
   <script type="application/javascript"
+          src="states.js"></script>
+  <script type="application/javascript"
           src="events.js"></script>
 
   <script type="application/javascript">
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
-    function doTest()
+    var gQueue = null;
+
+    function takeFocusInvoker(aID)
     {
-      // focus ARIA link
-      var ID = "aria-link";
-      var linkAcc = getAccessible(ID);
+      this.accessible = getAccessible(aID);
+
+      this.eventSeq = [ new invokerChecker(EVENT_FOCUS, this.accessible) ];
+
+      this.invoke = function takeFocusInvoker_invoke()
+      {
+        this.accessible.takeFocus();
+      }
 
-      gFocusManager.listenElement(linkAcc, ID, doTest2);
-      linkAcc.takeFocus();
+      this.finalCheck = function takeFocusInvoker()
+      {
+        testStates(this.accessible, STATE_FOCUSED);
+      }
+
+      this.getID = function takeFocusInvoker_getID()
+      {
+        return "takeFocus for " + prettyName(aID);
+      }
     }
 
-    function doTest2()
-    {
-      // focus first child of ARIA link
-      var ID = "aria-link2";
-      var linkAcc = getAccessible(ID);
-
-      gFocusManager.listenElement(linkAcc, ID, doTest3);
-      linkAcc.firstChild.takeFocus();
-    }
-
-    function doTest3()
+    function doTest()
     {
-      // focus html:a
-      var ID = "link";
-      var linkAcc = getAccessible(ID);
+      gQueue = new eventQueue();
 
-      gFocusManager.listenElement(linkAcc, ID, finishTest);
-      linkAcc.takeFocus();
-    }
+      gQueue.push(new takeFocusInvoker("aria-link"));
+      gQueue.push(new takeFocusInvoker("aria-link2"));
+      gQueue.push(new takeFocusInvoker("link"));
 
-    function finishTest()
-    {
-      SimpleTest.finish();
+      gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
-
-    ////////////////////////////////////////////////////////////////////////////
-    // Helpers
-
-    var gFocusManager =
-    {
-      // Public
-      listenElement: function listenElement(aAccOrID, aPrettyName, aCallback)
-      {
-        registerA11yEventListener(nsIAccessibleEvent.EVENT_FOCUS, this);
-
-        var elmObj = {};
-        this.mAcc = getAccessible(aAccOrID, null, elmObj);
-        this.mElm = elmObj.value;
-        this.mName = aPrettyName ? aPrettyName : aAccOrID;
-        this.mCallback = aCallback;
-
-        window.setTimeout(
-          function(aFocusMgr)
-          {
-            aFocusMgr.checkWasFocusHandled();
-            // Try to work around bug 573085 by using a timeout that's a lot
-            // bigger than our refresh driver period.
-          }, 100, this);
-      },
-
-      // Private
-      handleEvent: function handleEvent(aAccEvent)
-      {
-        var node = aAccEvent.DOMNode;
-        if (node == this.mElm)
-            this.mIsFocusHandled = true;
-      },
-
-      checkWasFocusHandled: function checkWasFocusHandled()
-      {
-        window.setTimeout(
-          function(aFocusMgr)
-          {
-            unregisterA11yEventListener(nsIAccessibleEvent.EVENT_FOCUS, this);
-
-            ok(aFocusMgr.mIsFocusHandled,
-               "Focus wasn't received for element with ID " + aFocusMgr.mName + ".");
-
-            var states = {}, extraStates = {};
-            aFocusMgr.mAcc.getState(states, extraStates);
-// XXX see bug 455840. Only fails on aria-link, the other two are OK.
-// When fixing this bug, remove the if statement and else block and "todo" statement.
-            if (states.value & nsIAccessibleStates.STATE_FOCUSED)
-              ok(states.value & nsIAccessibleStates.STATE_FOCUSED,
-                 "No focused state for element with ID " + aFocusMgr.mName + ".");
-            else
-              todo(states.value & nsIAccessibleStates.STATE_FOCUSED,
-                   "No focused state for element with ID " + aFocusMgr.mName + ".");
-
-            aFocusMgr.mCallback();
-          }, 0, this);
-      },
-
-      mAcc: null,
-      mElm: null,
-      mName: "",
-      mIsFocusHandled: false
-    };
   </script>
 </head>
 
 <body>
 
   <a target="_blank"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=452710"
      title="nsIAccessible::takeFocus testing">
--- a/accessible/tests/mochitest/text.js
+++ b/accessible/tests/mochitest/text.js
@@ -21,16 +21,24 @@ function testCharacterCount(aIDs, aCount
 {
   for (var i = 0; i < aIDs.length; i++) {
     var textacc = getAccessible(aIDs[i], [nsIAccessibleText]);
     is(textacc.characterCount, aCount,
        "Wrong character count for " + prettyName(aIDs[i]));
   }
 }
 
+/**
+ * Test text between two given offsets
+ *
+ * @param aIDs          [in] an array of accessible IDs to test
+ * @param aStartOffset  [in] the start offset within the text to test
+ * @param aEndOffset    [in] the end offset up to which the text is tested
+ * @param aText         [in] the expected result from the test
+ */
 function testText(aIDs, aStartOffset, aEndOffset, aText)
 {
   for (var i = 0; i < aIDs.length; i++)
   {
     var acc = getAccessible(aIDs[i], nsIAccessibleText);
     try {
       is(acc.getText(aStartOffset, aEndOffset), aText,
          "getText: wrong text between start and end offsets '" + aStartOffset +
@@ -39,16 +47,44 @@ function testText(aIDs, aStartOffset, aE
       ok(false,
          "getText fails between start and end offsets '" + aStartOffset +
          "', '" + aEndOffset + " for '" + prettyName(aIDs[i]) + "'");
     }
   }
 }
 
 /**
+ * Test password text between two given offsets
+ *
+ * @param aIDs          [in] an array of accessible IDs to test
+ * @param aStartOffset  [in] the start offset within the text to test
+ * @param aEndOffset    [in] the end offset up to which the text is tested
+ * @param aText         [in] the expected result from the test
+ *
+ * @note  All this function does is test that getText doe snot expose the
+ *        password text itself, but something else.
+ */
+function testPasswordText(aIDs, aStartOffset, aEndOffset, aText)
+{
+  for (var i = 0; i < aIDs.length; i++)
+  {
+    var acc = getAccessible(aIDs[i], nsIAccessibleText);
+    try {
+      isnot(acc.getText(aStartOffset, aEndOffset), aText,
+         "getText: plain text between start and end offsets '" + aStartOffset +
+         "', '" + aEndOffset + " for '" + prettyName(aIDs[i]) + "'");
+    } catch (e) {
+      ok(false,
+         "getText fails between start and end offsets '" + aStartOffset +
+         "', '" + aEndOffset + " for '" + prettyName(aIDs[i]) + "'");
+    }
+  }
+}
+
+/**
  * Test getTextAtOffset for BOUNDARY_CHAR over different elements.
  *
  * @param aIDs          [in] the accessible identifier or array of accessible
  *                        identifiers
  * @param aOffset       [in] the offset to get a character at it
  * @param aChar         [in] the expected character
  * @param aStartOffset  [in] expected start offset of the character
  * @param aEndOffset    [in] expected end offset of the character
--- a/accessible/tests/mochitest/text/Makefile.in
+++ b/accessible/tests/mochitest/text/Makefile.in
@@ -44,15 +44,16 @@ relativesrcdir  = accessible/text
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES = \
 		doc.html \
 		test_doc.html \
 		test_hypertext.html \
+		test_passwords.html \
 		test_singleline.html \
 		test_whitespaces.html \
 		test_words.html \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/accessible/tests/mochitest/text/test_passwords.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>nsIAccessibleText getText related function tests for text and password inputs</title>
+  <link rel="stylesheet" type="text/css"
+        href="chrome://mochikit/content/tests/SimpleTest/test.css" />
+
+  <script type="application/javascript"
+          src="chrome://mochikit/content/MochiKit/packed.js"></script>
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript"
+          src="../common.js"></script>
+  <script type="application/javascript"
+          src="../text.js"></script>
+
+  <script type="application/javascript">
+    function doTest()
+    {
+      //////////////////////////////////////////////////////////////////////////
+      // regular text and password inputs
+      //////////////////////////////////////////////////////////////////////////
+
+      ////////////////////////////////////////////////////////////////////////
+      // characterCount and getText for regular text field
+
+      var IDs = [ "username" ];
+      testCharacterCount(IDs, 4);
+      testText(IDs, 0, 4, "test");
+
+      ////////////////////////////////////////////////////////////////////////
+      // characterCount and getText for password field
+
+      IDs = [ "password" ];
+      testCharacterCount(IDs, 4);
+      testPasswordText(IDs, 0, 4, "test");
+
+      SimpleTest.finish();
+    }
+
+    SimpleTest.waitForExplicitFinish();
+    addA11yLoadEvent(doTest);
+  </script>
+</head>
+<body>
+
+  <a target="_blank"
+     title="mochitest for getText for password fields"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=415943">Mozilla Bug 415943</a>
+  <p id="display"></p>
+  <div id="content" style="display: none"></div>
+  <pre id="test">
+  </pre>
+
+  <form action="post.php" method="post">
+    <label for="username">User name:</label>
+    <input id="username" value="test"><br />
+    <label for="password">Password:</label>
+    <input type="password" id="password" value="test"/>
+  </form>
+</body>
+</html>
--- a/accessible/tests/mochitest/tree/test_combobox.xul
+++ b/accessible/tests/mochitest/tree/test_combobox.xul
@@ -1,17 +1,17 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
                  type="text/css"?>
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         title="Accessible XUL menulist and textbox @autocomplete hierarchy tests">
 
-  <script type="application/javascript" 
+  <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
           src="../role.js" />
@@ -28,110 +28,207 @@
 
       var accTree = {
         role: ROLE_COMBOBOX,
         children: [
           {
             role: ROLE_COMBOBOX_LIST,
             children: [
               {
-                role: ROLE_COMBOBOX_OPTION
+                role: ROLE_COMBOBOX_OPTION,
+                children: []
               },
               {
-                role: ROLE_COMBOBOX_OPTION
+                role: ROLE_COMBOBOX_OPTION,
+                children: []
               }
             ]
           }
         ]
       };
+
       testAccessibleTree("menulist", accTree);
 
       //////////////////////////////////////////////////////////////////////////
       // editable menulist
 
       accTree = {
         role: ROLE_COMBOBOX,
         children: [
           {
             role: ROLE_ENTRY,
-            children: [ ] // no text leaf accessible for text node
+            children: [
+              // no text leaf accessible for text node
+            ]
           },
           {
             role: ROLE_COMBOBOX_LIST, // context menu
             children: []
           },
           {
             role: ROLE_PUSHBUTTON, // dropmarker
+            children: []
           },
           {
             role: ROLE_COMBOBOX_LIST, // option list
             children: [
               {
-                role: ROLE_COMBOBOX_OPTION
+                role: ROLE_COMBOBOX_OPTION,
+                children: []
               },
               {
-                role: ROLE_COMBOBOX_OPTION
+                role: ROLE_COMBOBOX_OPTION,
+                children: []
               }
             ]
           }
         ]
       };
 
       // XXX Bug 551957
       if (!MAC) {
         testAccessibleTree("menulist2", accTree);
       }
 
       //////////////////////////////////////////////////////////////////////////
       // textbox@type=autocomplete #1 (history)
 
       accTree = {
+        // textbox
         role: ROLE_AUTOCOMPLETE,
         children: [
           {
+            // html:input
             role: ROLE_ENTRY,
             children: [
               {
+                // #text
                 role: ROLE_TEXT_LEAF,
-                name: "http://mochi.test:8888/redirect-a11y.html"
+                name: "http://mochi.test:8888/redirect-a11y.html",
+                children: []
               }
             ]
           },
           {
+            // xul:menupopup
             role: ROLE_COMBOBOX_LIST, // context menu popup
-            children: [ ]
+            children: []
           }
         ]
       };
+
+      // XPFE and Toolkit autocomplete widgets differ.
+      var ac1h = document.getElementById("autocomplete");
+      if ("clearResults" in ac1h) {
+        SimpleTest.ok(true, "Testing (Old) XPFE autocomplete widget. (ac1h)");
+
+        // Popup is always created.
+        accTree.children.push(
+          {
+            // xul:panel
+            role: ROLE_COMBOBOX_LIST,
+            children: [
+              {
+                // xul:tree
+                role: ROLE_TABLE,
+                children: [
+                  {
+                    // xul:treecols
+                    role: ROLE_LIST,
+                    children: [
+                      {
+                        // xul:treecol
+                        role: ROLE_COLUMNHEADER,
+                        children: []
+                      }
+                    ]
+                  }
+                ]
+              }
+            ]
+          }
+          );
+      } else {
+        SimpleTest.ok(true, "Testing (New) Toolkit autocomplete widget. (ac1h)");
+
+        // Popup is lazily created, so not present in this case.
+      }
+
       testAccessibleTree("autocomplete", accTree);
 
       //////////////////////////////////////////////////////////////////////////
       // textbox@type=autocomplete #2 (child menupoup)
 
       accTree = {
+        // textbox
         role: ROLE_AUTOCOMPLETE,
         children: [
           {
+            // menupopup
             role: ROLE_COMBOBOX_LIST, // autocomplete menu popup
             children: [
               {
-                role: ROLE_COMBOBOX_OPTION
+                // menuitem
+                role: ROLE_COMBOBOX_OPTION,
+                children: []
               }
             ]
           },
           {
+            // html:input
             role: ROLE_ENTRY,
-            children: [ ] // no text leaf accessible for text node
+            children: [
+              // no text leaf accessible for text node
+            ]
           },
           {
+            // xul:menupopup
             role: ROLE_COMBOBOX_LIST, // context menu popup
-            children: [ ]
+            children: []
           }
         ]
       };
+
+      // XPFE and Toolkit autocomplete widgets differ.
+      var ac2cmp = document.getElementById("autocomplete2");
+      if ("clearResults" in ac2cmp) {
+        SimpleTest.ok(true, "Testing (Old) XPFE autocomplete widget. (ac2mp)");
+
+        // Popup is always created.
+        accTree.children.push(
+          {
+            // xul:panel
+            role: ROLE_COMBOBOX_LIST,
+            children: [
+              {
+                // xul:tree
+                role: ROLE_TABLE,
+                children: [
+                  {
+                    // xul:treecols
+                    role: ROLE_LIST,
+                    children: [
+                      {
+                        // xul:treecol
+                        role: ROLE_COLUMNHEADER,
+                        children: []
+                      }
+                    ]
+                  }
+                ]
+              }
+            ]
+          }
+          );
+      } else {
+        SimpleTest.ok(true, "Testing (New) Toolkit autocomplete widget. (ac2mp)");
+
+        // Popup is lazily created, so not present in this case.
+      }
+
       testAccessibleTree("autocomplete2", accTree);
 
       SimpleTest.finish()
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
@@ -179,9 +276,8 @@
         <menupopup>
           <menuitem label="item1"/>
         </menupopup>
       </textbox>
     </vbox>
   </hbox>
 
 </window>
-
--- a/accessible/tests/mochitest/tree/test_tabbrowser.xul
+++ b/accessible/tests/mochitest/tree/test_tabbrowser.xul
@@ -9,17 +9,17 @@
                  type="text/css"?>
 
 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
                  type="text/css"?>
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         title="Accessible XUL tabbrowser hierarchy tests">
 
-  <script type="application/javascript" 
+  <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
           src="../role.js" />
@@ -31,87 +31,185 @@
 
     const Ci = Components.interfaces;
 
     // Hack to make xul:tabbrowser work.
     Components.utils.import("resource://gre/modules/Services.jsm");
     var handleDroppedLink = null;
     var XULBrowserWindow = {
       isBusy: false,
-      setOverLink: function (link, b) {
-      }
+      setOverLink: function (link, b) {}
     };
     var gFindBar = {
       hidden: true
     };
 
     function doTest()
     {
       var tabBrowser = document.getElementById("tabbrowser");
 
       var progressListener =
       {
         onStateChange: function onStateChange(aWebProgress,
                                               aRequest,
                                               aStateFlags,
                                               aStatus)
-       {
-        if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
-          testAccTree();
-       }
+        {
+          if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) {
+            tabBrowser.removeProgressListener(progressListener);
+
+            SimpleTest.executeSoon(testAccTree);
+          }
+        }
       };
-
       tabBrowser.addProgressListener(progressListener,
                                      Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
 
+      // Test XUL and HTML documents.
       tabBrowser.loadTabs(["about:", "about:mozilla"], false, true);
     }
 
     function testAccTree()
     {
+      var tabBrowser = document.getElementById("tabbrowser");
+
+      ////////////////////
+      // Tab bar
+      ////////////////////
       var tabsAccTree = {
+        // xul:tabs
         role: ROLE_PAGETABLIST,
         children: [
+          // Children depend on application (UI): see below.
+        ]
+      };
+
+      // SeaMonkey and Firefox tabbrowser UIs differ.
+      if ("restoreTab" in tabBrowser) {
+        SimpleTest.ok(true, "Testing SeaMonkey tabbrowser UI.");
+
+        tabsAccTree.children.splice(0, 0,
           {
+            // xul:toolbarbutton ("Open a new tab")
+            role: ROLE_PUSHBUTTON,
+            children: []
+          },
+          {
+            // xul:tab ("about:")
             role: ROLE_PAGETAB,
+            children: []
+          },
+          {
+            // tab ("about:mozilla")
+            role: ROLE_PAGETAB,
+            children: []
+          },
+          {
+            // xul:toolbarbutton ("List all tabs")
+            role: ROLE_PUSHBUTTON,
             children: [
               {
-                role: ROLE_PUSHBUTTON
+                // xul:menupopup
+                role: ROLE_MENUPOPUP,
+                children: []
               }
             ]
           },
           {
+            // xul:toolbarbutton ("Close current tab")
+            role: ROLE_PUSHBUTTON,
+            children: []
+          }
+          );
+      } else {
+        SimpleTest.ok(true, "Testing Firefox tabbrowser UI.");
+
+        // NB: The (3) buttons are not visible, unless manually hovered,
+        //     probably due to size reduction in this test.
+        tabsAccTree.children.splice(0, 0,
+          {
+            // xul:tab ("about:")
             role: ROLE_PAGETAB,
             children: [
               {
-                role: ROLE_PUSHBUTTON
+                // xul:toolbarbutton ("Close Tab")
+                role: ROLE_PUSHBUTTON,
+                children: []
               }
             ]
           },
           {
-            role: ROLE_PUSHBUTTON
+            // tab ("about:mozilla")
+            role: ROLE_PAGETAB,
+            children: [
+              {
+                // xul:toolbarbutton ("Close Tab")
+                role: ROLE_PUSHBUTTON,
+                children: []
+              }
+            ]
+          },
+          {
+            // xul:toolbarbutton ("Open a new tab")
+            role: ROLE_PUSHBUTTON,
+            children: []
           }
-        ]
-      };
-      testAccessibleTree(getNode("tabbrowser").tabContainer, tabsAccTree);
+          // "List all tabs" dropdown
+          // XXX: This child(?) is not present in this test.
+          //      I'm not sure why (though probably expected).
+          );
+      }
 
+      testAccessibleTree(tabBrowser.tabContainer, tabsAccTree);
+
+      ////////////////////
+      // Tab contents
+      ////////////////////
       var tabboxAccTree = {
+        // xul:tabpanels
         role: ROLE_PANE,
         children: [
           {
-            role: ROLE_PROPERTYPAGE
+            // xul:notificationbox
+            role: ROLE_PROPERTYPAGE,
+            children: [
+              {
+                // xul:browser
+                role: ROLE_INTERNAL_FRAME,
+                children: [
+                  {
+                    // #document ("about:")
+                    role: ROLE_DOCUMENT
+                    // children: [ ... ] // Ignore document content.
+                  }
+                ]
+              }
+            ]
           },
           {
-            role: ROLE_PROPERTYPAGE
+            // notificationbox
+            role: ROLE_PROPERTYPAGE,
+            children: [
+              {
+                // browser
+                role: ROLE_INTERNAL_FRAME,
+                children: [
+                  {
+                    // #document ("about:mozilla")
+                    role: ROLE_DOCUMENT
+                    // children: [ ... ] // Ignore document content.
+                  }
+                ]
+              }
+            ]
           }
         ]
       };
 
-      testAccessibleTree(getNode("tabbrowser").mTabBox.tabpanels,
-                         tabboxAccTree);
+      testAccessibleTree(tabBrowser.mTabBox.tabpanels, tabboxAccTree);
 
       SimpleTest.finish()
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
@@ -153,9 +251,8 @@
     <tabbrowser id="tabbrowser"
                 type="content-primary"
                 tabcontainer="tabbrowser-tabs"
                 flex="1"/>
     <toolbar id="addon-bar"/>
   </vbox>
 
 </window>
-
--- a/accessible/tests/mochitest/tree/test_txtctrl.xul
+++ b/accessible/tests/mochitest/tree/test_txtctrl.xul
@@ -1,107 +1,182 @@
 <?xml version="1.0"?>
 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
                  type="text/css"?>
 
 <window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         title="Accessible XUL textbox and textarea hierarchy tests">
 
-  <script type="application/javascript" 
+  <script type="application/javascript"
           src="chrome://mochikit/content/MochiKit/packed.js" />
   <script type="application/javascript"
           src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
 
   <script type="application/javascript"
           src="../common.js" />
   <script type="application/javascript"
           src="../role.js" />
 
   <script type="application/javascript">
   <![CDATA[
     ////////////////////////////////////////////////////////////////////////////
     // Test
 
     function doTest()
     {
+      ////////////////////
       // textbox
+      ////////////////////
       var accTree = {
         role: ROLE_ENTRY,
         children: [
           {
             role: ROLE_TEXT_LEAF,
             children: []
           }
         ]
       };
+
+      // default textbox
       testAccessibleTree("txc1", accTree);
 
       // number textbox
       testAccessibleTree("txc2", accTree);
 
       // search textbox
       testAccessibleTree("txc3", accTree);
 
       // timed textbox
-      testAccessibleTree("txc4", accTree);
+      testAccessibleTree("txc4_deprecated", accTree);
 
+      ////////////////////
       // password textbox
+      ////////////////////
       accTree = {
         role: ROLE_PASSWORD_TEXT,
         children: [
           {
             role: ROLE_TEXT_LEAF,
             children: []
           }
         ]
       };
 
       testAccessibleTree("txc5", accTree);
 
+      ////////////////////
       // multiline textbox
+      ////////////////////
       accTree = {
         role: ROLE_ENTRY,
         children: [
           {
             role: ROLE_TEXT_LEAF,
             children: []
           },
           {
             role: ROLE_WHITESPACE,
             children: []
           }
         ]
       };
 
       testAccessibleTree("txc6", accTree);
 
+      ////////////////////
       // autocomplete textbox
+      ////////////////////
       accTree = {
+        // textbox
         role: ROLE_AUTOCOMPLETE,
         children: [
           {
+            // html:input
             role: ROLE_ENTRY,
             children: [
               {
+                // #text
                 role: ROLE_TEXT_LEAF,
                 children: []
               }
             ]
           },
           {
+            // xul:menupopup
             role: ROLE_COMBOBOX_LIST,
             children: []
           }
         ]
       };
 
-      testAccessibleTree("txc7", accTree);
+      // XPFE and Toolkit autocomplete widgets differ.
+      var txc7 = document.getElementById("txc7");
+      if ("clearResults" in txc7) {
+        SimpleTest.ok(true, "Testing (Old) XPFE autocomplete widget.");
+
+        // Popup is always created. (See code below.)
 
-      SimpleTest.finish();
+        accTree.children.push(
+          {
+            // xul:panel
+            role: ROLE_COMBOBOX_LIST,
+            children: [
+              {
+                // xul:tree
+                role: ROLE_TABLE,
+                children: [
+                  {
+                    // xul:treecols
+                    role: ROLE_LIST,
+                    children: [
+                      {
+                        // xul:treecol
+                        role: ROLE_COLUMNHEADER,
+                        children: []
+                      }
+                    ]
+                  }
+                ]
+              }
+            ]
+          }
+          );
+      } else {
+        SimpleTest.ok(true, "Testing (New) Toolkit autocomplete widget.");
+
+        // Dumb access to trigger popup lazy creation. (See code below.)
+        txc7.popup;
+
+        accTree.children.push(
+          {
+            role: ROLE_LIST,
+            children: [
+              {
+                role: ROLE_LIST,
+                children: [
+                  {
+                    role: ROLE_COLUMNHEADER,
+                    children: []
+                  }
+                ]
+              }
+            ]
+          }
+          );
+      }
+
+      // Delay txc7 test a bit, to let Toolkit popup lazy creation complete.
+      function test_txc7() {
+        testAccessibleTree("txc7", accTree);
+  
+        SimpleTest.finish();
+      }
+      // SimpleTest.executeSoon() doesn't help here: use setTimeout() with a little delay.
+      setTimeout(test_txc7, 25);
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
 
   <hbox flex="1" style="overflow: auto;">
@@ -117,17 +192,18 @@
       <pre id="test">
       </pre>
     </body>
 
     <vbox flex="1">
       <textbox id="txc1" value="hello"/>
       <textbox id="txc2" type="number" value="44"/>
       <textbox id="txc3" type="search" value="hello"/>
-      <textbox id="txc4" type="timed" value="hello"/>
+      <!-- This textbox triggers "Warning: Timed textboxes are deprecated. Consider using type="search" instead.".
+           Yet let's test it too as long as it's (still) supported. -->
+      <textbox id="txc4_deprecated" type="timed" value="hello"/>
       <textbox id="txc5" type="password" value="hello"/>
       <textbox id="txc6" multiline="true" value="hello"/>
       <textbox id="txc7" type="autocomplete" value="hello"/>
     </vbox>
   </hbox>
 
 </window>
-
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -3648,23 +3648,20 @@ function retrieveToolbarIconsizesFromThe
     if (aToolbar.localName != "toolbar")
       return;
 
     // The theme indicates that it wants to override the "iconsize" attribute
     // by specifying a special value for the "counter-reset" property on the
     // toolbar. A custom property cannot be used because getComputedStyle can
     // only return the values of standard CSS properties.
     let counterReset = getComputedStyle(aToolbar).counterReset;
-    if (counterReset == "smallicons 0") {
+    if (counterReset == "smallicons 0")
       aToolbar.setAttribute("iconsize", "small");
-      document.persist(aToolbar.id, "iconsize");
-    } else if (counterReset == "largeicons 0") {
+    else if (counterReset == "largeicons 0")
       aToolbar.setAttribute("iconsize", "large");
-      document.persist(aToolbar.id, "iconsize");
-    }
   }
 
   Array.forEach(gNavToolbox.childNodes, retrieveToolbarIconsize);
   gNavToolbox.externalToolbars.forEach(retrieveToolbarIconsize);
 }
 
 /**
  * Update the global flag that tracks whether or not any edit UI (the Edit menu,
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -3745,34 +3745,55 @@
         <xul:label class="statuspanel-label"
                    role="status"
                    xbl:inherits="value=label,crop,mirror"
                    flex="1"
                    crop="end"/>
       </xul:hbox>
     </content>
 
-    <implementation>
+    <implementation implements="nsIDOMEventListener">
+      <constructor><![CDATA[
+        window.addEventListener("findbaropen", this, false);
+      ]]></constructor>
+
+      <destructor><![CDATA[
+        window.removeEventListener("findbaropen", this, false);
+      ]]></destructor>
+
       <property name="label">
         <setter><![CDATA[
-          if (!this.label)
-            this.removeAttribute("mirror");
+          if (!this.label) {
+            if (window.gFindBarInitialized && !window.gFindBar.hidden)
+              this.setAttribute("mirror", "true");
+            else
+              this.removeAttribute("mirror");
+          }
 
           this.style.minWidth = this.getAttribute("type") == "status" &&
                                 this.getAttribute("previoustype") == "status"
                                   ? getComputedStyle(this).width : "";
 
           this.setAttribute("label", val);
           return val;
         ]]></setter>
         <getter>
           return this.getAttribute("label");
         </getter>
       </property>
 
+      <method name="handleEvent">
+        <parameter name="event"/>
+        <body><![CDATA[
+          if (event.type == "findbaropen" &&
+              this.label)
+            this.setAttribute("mirror", "true");
+        ]]></body>
+      </method>
+
       <method name="_mirror">
         <body>
           if (this.hasAttribute("mirror"))
             this.removeAttribute("mirror");
           else
             this.setAttribute("mirror", "true");
         </body>
       </method>
--- a/browser/base/content/test/browser_bug553455.js
+++ b/browser/base/content/test/browser_bug553455.js
@@ -700,16 +700,98 @@ function test_renotify_installed() {
   var triggers = encodeURIComponent(JSON.stringify({
     "XPI": "unsigned.xpi"
   }));
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
 },
 
 function test_cancel_restart() {
+  // If the XPI is already cached then the HTTP observer won't see the request
+  var cacheService = Cc["@mozilla.org/network/cache-service;1"].
+                     getService(Ci.nsICacheService);
+  try {
+    cacheService.evictEntries(Components.interfaces.nsICache.STORE_ANYWHERE);
+  } catch(ex) {}
+
+  // Must be registered before any request starts
+  var observerService = Cc["@mozilla.org/network/http-activity-distributor;1"].
+                        getService(Ci.nsIHttpActivityDistributor);
+  observerService.addObserver({
+    observeActivity: function(aChannel, aType, aSubtype, aTimestamp, aSizeData,
+                              aStringData) {
+      aChannel.QueryInterface(Ci.nsIChannel);
+
+      // Wait for the first event for the download
+      if (aChannel.URI.spec != TESTROOT + "unsigned.xpi" ||
+        aType != Ci.nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION ||
+        aSubtype != Ci.nsIHttpActivityObserver.ACTIVITY_SUBTYPE_REQUEST_HEADER)
+        return;
+
+      observerService.removeObserver(this);
+
+      info("Replacing channel");
+      aChannel.QueryInterface(Ci.nsITraceableChannel);
+      var listener = aChannel.setNewListener({
+        onStartRequest: function(aRequest, aContext) {
+          listener.onStartRequest(aRequest, aContext);
+        },
+
+        onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
+          listener.onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount);
+        },
+
+        onStopRequest: function(aRequest, aContext, aStatusCode) {
+          listener.onStopRequest(aRequest, aContext, aStatusCode);
+
+          // Request should have been cancelled
+          is(aStatusCode, Components.results.NS_BINDING_ABORTED, "Should have seen a cancelled request");
+
+          // Notification should have changed to cancelled
+          let notification = PopupNotifications.panel.childNodes[0];
+          is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
+
+          // Wait for the install confirmation dialog
+          wait_for_install_dialog(function(aWindow) {
+            // Wait for the complete notification
+            wait_for_notification(function(aPanel) {
+              let notification = aPanel.childNodes[0];
+              is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
+              is(notification.button.label, "Restart Now", "Should have seen the right button");
+              is(notification.getAttribute("label"),
+                 "XPI Test will be installed after you restart " + gApp + ".",
+                 "Should have seen the right message");
+
+              AddonManager.getAllInstalls(function(aInstalls) {
+                is(aInstalls.length, 1, "Should be one pending install");
+                aInstalls[0].cancel();
+
+                Services.perms.remove("example.com", "install");
+                wait_for_notification_close(runNextTest);
+                gBrowser.removeTab(gBrowser.selectedTab);
+              });
+            });
+
+            aWindow.document.documentElement.acceptDialog();
+          });
+
+          // Restart the download
+          info("Restarting download");
+          EventUtils.synthesizeMouse(notification.button, 20, 10, {});
+
+          // Should be back to a progress notification
+          ok(PopupNotifications.isPanelOpen, "Notification should still be open");
+          is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
+          notification = PopupNotifications.panel.childNodes[0];
+          is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
+        }
+      });
+    }
+  });
+
   // Wait for the progress notification
   wait_for_notification(function(aPanel) {
     let notification = aPanel.childNodes[0];
     is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
 
     // Close the notification
     let anchor = document.getElementById("addons-notification-icon");
     EventUtils.synthesizeMouseAtCenter(anchor, {});
@@ -719,58 +801,18 @@ function test_cancel_restart() {
     ok(PopupNotifications.isPanelOpen, "Notification should still be open");
     is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
     isnot(notification, aPanel.childNodes[0], "Should have reconstructed the notification UI");
     notification = aPanel.childNodes[0];
     is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
     let button = document.getAnonymousElementByAttribute(notification, "anonid", "cancel");
 
     // Cancel the download
+    info("Cancelling download");
     EventUtils.synthesizeMouse(button, 2, 2, {});
-
-    // Downloads cannot be restarted synchronously, bug 611755
-    executeSoon(function() {
-      // Notification should have changed to cancelled
-      notification = aPanel.childNodes[0];
-      is(notification.id, "addon-install-cancelled-notification", "Should have seen the cancelled notification");
-
-      // Wait for the install confirmation dialog
-      wait_for_install_dialog(function(aWindow) {
-        // Wait for the complete notification
-        wait_for_notification(function(aPanel) {
-          let notification = aPanel.childNodes[0];
-          is(notification.id, "addon-install-complete-notification", "Should have seen the install complete");
-          is(notification.button.label, "Restart Now", "Should have seen the right button");
-          is(notification.getAttribute("label"),
-             "XPI Test will be installed after you restart " + gApp + ".",
-             "Should have seen the right message");
-
-          AddonManager.getAllInstalls(function(aInstalls) {
-            is(aInstalls.length, 1, "Should be one pending install");
-            aInstalls[0].cancel();
-
-            Services.perms.remove("example.com", "install");
-            wait_for_notification_close(runNextTest);
-            gBrowser.removeTab(gBrowser.selectedTab);
-          });
-        });
-
-        aWindow.document.documentElement.acceptDialog();
-      });
-
-      // Restart the download
-      EventUtils.synthesizeMouse(notification.button, 20, 10, {});
-
-      // Should be back to a progress notification
-      ok(PopupNotifications.isPanelOpen, "Notification should still be open");
-      is(PopupNotifications.panel.childNodes.length, 1, "Should be only one notification");
-      notification = aPanel.childNodes[0];
-      is(notification.id, "addon-progress-notification", "Should have seen the progress notification");
-
-    });
   });
 
   var pm = Services.perms;
   pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
 
   var triggers = encodeURIComponent(JSON.stringify({
     "XPI": "unsigned.xpi"
   }));
--- a/browser/base/content/test/browser_contentAreaClick.js
+++ b/browser/base/content/test/browser_contentAreaClick.js
@@ -179,26 +179,33 @@ let gInvokedMethods = [];
 
 // The test currently running.
 let gCurrentTest = null;
 
 function test() {
   waitForExplicitFinish();
 
   gTestWin = openDialog(location, "", "chrome,all,dialog=no", "about:blank");
-  gTestWin.addEventListener("load", function (event) {
-    info("Window loaded.");
-    gTestWin.removeEventListener("load", arguments.callee, false);
+  Services.obs.addObserver(function(aSubject, aTopic, aData) {
+    if (aSubject != gTestWin)
+      return;
+
+    Services.obs.removeObserver(arguments.callee, "browser-delayed-startup-finished");
+
+    info("Browser window opened");
     waitForFocus(function() {
-      info("Setting up browser...");
-      setupTestBrowserWindow();
-      info("Running tests...");
-      executeSoon(runNextTest);
-    }, gTestWin.content, true);
-  }, false);
+      info("Browser window focused");
+      waitForFocus(function() {
+        info("Setting up browser...");
+        setupTestBrowserWindow();
+        info("Running tests...");
+        executeSoon(runNextTest);
+      }, gTestWin.content, true);
+    }, gTestWin);
+  }, "browser-delayed-startup-finished", false);
 }
 
 // Click handler used to steal click events.
 let gClickHandler = {
   handleEvent: function (event) {
     let linkId = event.target.id;
     is(event.type, "click",
        gCurrentTest.desc + ":Handler received a click event on " + linkId);
--- a/browser/base/content/test/browser_sanitize-timespans.js
+++ b/browser/base/content/test/browser_sanitize-timespans.js
@@ -278,17 +278,17 @@ function setupHistory() {
   bhist.addPageWithDetails(makeURI("http://2hour.com/"), "Less than 2 hours ago", now_uSec - 90*60*1000000);
   bhist.addPageWithDetails(makeURI("http://2hour10minutes.com/"), "2 hours 10 minutes ago", now_uSec - 130*60*1000000);
   bhist.addPageWithDetails(makeURI("http://4hour.com/"), "Less than 4 hours ago", now_uSec - 180*60*1000000);
   bhist.addPageWithDetails(makeURI("http://4hour10minutes.com/"), "4 hours 10 minutesago", now_uSec - 250*60*1000000);
   
   let today = new Date();
   today.setHours(0);
   today.setMinutes(0);
-  today.setSeconds(30);
+  today.setSeconds(1);
   bhist.addPageWithDetails(makeURI("http://today.com/"), "Today", today.valueOf() * 1000);
   
   let lastYear = new Date();
   lastYear.setFullYear(lastYear.getFullYear() - 1);
   bhist.addPageWithDetails(makeURI("http://before-today.com/"), "Before Today", lastYear.valueOf() * 1000);
   
   // Confirm everything worked
   ok(bhist.isVisited(makeURI("http://10minutes.com/")), "Pretend visit to 10minutes.com should exist");
@@ -521,17 +521,17 @@ function setupDownloads() {
   finally {
     stmt.reset();
   }
 
   // Add "today" download
   let today = new Date();
   today.setHours(0);
   today.setMinutes(0);
-  today.setSeconds(30);
+  today.setSeconds(1);
   
   data = {
     id:   "5555554",
     name: "fakefile-today",
     source: "https://bugzilla.mozilla.org/show_bug.cgi?id=453440",
     target: "fakefile-today",
     startTime: today.valueOf() * 1000,  // 12:00:30am this morning, in uSec
     endTime: (today.valueOf() + 1000) * 1000, // 1 second later
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1080,76 +1080,103 @@
                 xbl:inherits="iconic,label,disabled,onclick=oncommand,_moz-menuactive=active"/>
       <xul:menu anonid="menu" class="splitmenu-menu"
                 xbl:inherits="disabled,_moz-menuactive=active"
                 oncommand="event.stopPropagation();">
         <children includes="menupopup"/>
       </xul:menu>
     </content>
 
-    <implementation>
+    <implementation implements="nsIDOMEventListener">
+      <constructor><![CDATA[
+        this._parentMenupopup.addEventListener("DOMMenuItemActive", this, false);
+        this._parentMenupopup.addEventListener("popuphidden", this, false);
+      ]]></constructor>
+
+      <destructor><![CDATA[
+        this._parentMenupopup.removeEventListener("DOMMenuItemActive", this, false);
+        this._parentMenupopup.removeEventListener("popuphidden", this, false);
+      ]]></destructor>
+
       <field name="menuitem" readonly="true">
         document.getAnonymousElementByAttribute(this, "anonid", "menuitem");
       </field>
       <field name="menu" readonly="true">
         document.getAnonymousElementByAttribute(this, "anonid", "menu");
       </field>
 
       <field name="_menuDelay">600</field>
 
       <field name="_parentMenupopup"><![CDATA[
-        let node = this.parentNode;
-        while (node) {
-          if (node.localName == "menupopup")
-            break;
-          node = node.parentNode;
-        }
-        node;
+        this._getParentMenupopup(this);
       ]]></field>
+
+      <method name="_getParentMenupopup">
+        <parameter name="aNode"/>
+        <body><![CDATA[
+          let node = aNode.parentNode;
+          while (node) {
+            if (node.localName == "menupopup")
+              break;
+            node = node.parentNode;
+          }
+          return node;
+        ]]></body>
+      </method>
+
+      <method name="handleEvent">
+        <parameter name="event"/>
+        <body><![CDATA[
+          switch (event.type) {
+            case "DOMMenuItemActive":
+              if (this.getAttribute("active") == "true" &&
+                  event.target != this &&
+                  this._getParentMenupopup(event.target) == this._parentMenupopup)
+                this.removeAttribute("active");
+              break;
+            case "popuphidden":
+              if (event.target == this._parentMenupopup)
+                this.removeAttribute("active");
+              break;
+          }
+        ]]></body>
+      </method>
     </implementation>
 
     <handlers>
       <handler event="mouseover"><![CDATA[
         if (this.getAttribute("active") != "true" &&
             this.getAttribute("disabled") != "true") {
           this.setAttribute("active", "true");
 
+          let event = document.createEvent("Events");
+          event.initEvent("DOMMenuItemActive", true, false);
+          this.dispatchEvent(event);
+
           let self = this;
           setTimeout(function () {
             if (self.getAttribute("active") == "true")
               self.menu.open = true;
           }, this._menuDelay);
         }
       ]]></handler>
 
-      <handler event="mouseout"><![CDATA[
-        if (this.menu.open)
-          return;
-
-        let node = event.relatedTarget;
-        while (node) {
-          if (node == this)
-            return;
-          node = node.parentNode;
-        }
-        this.removeAttribute("active");
-      ]]></handler>
-
-      <handler event="popuphidden"><![CDATA[
-        if (event.target == this.firstChild)
-          this.removeAttribute("active");
-      ]]></handler>
-
       <handler event="popupshowing"><![CDATA[
         if (event.target == this.firstChild &&
             this._parentMenupopup._currentPopup)
           this._parentMenupopup._currentPopup.hidePopup();
       ]]></handler>
 
       <handler event="click" phase="capturing"><![CDATA[
+        if (this.getAttribute("disabled") == "true") {
+          // Prevent the command from being carried out
+          event.stopPropagation();
+          return;
+        }
+
         let node = event.originalTarget;
         while (true) {
           if (node == this.menuitem)
             break;
           if (node == this)
             return;
           node = node.parentNode;
         }
--- a/browser/components/places/tests/browser/browser_bookmarksProperties.js
+++ b/browser/components/places/tests/browser/browser_bookmarksProperties.js
@@ -195,16 +195,17 @@ gTests.push({
 
 gTests.push({
   desc: "Bug 462662 - Pressing Enter to select tag from autocomplete closes bookmarks properties dialog",
   sidebar: SIDEBAR_BOOKMARKS_ID,
   action: ACTION_EDIT,
   itemType: null,
   window: null,
   _itemId: null,
+  _cleanShutdown: false,
 
   setup: function() {
     // Add a bookmark in unsorted bookmarks folder.
     this._itemId = add_bookmark(PlacesUtils._uri(TEST_URL));
     ok(this._itemId > 0, "Correctly added a bookmark");
     // Add a tag to this bookmark.
     PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL),
                                ["testTag"]);
@@ -217,41 +218,37 @@ gTests.push({
     is(tree.selectedNode.itemId, this._itemId, "Bookmark has been selected");
   },
 
   run: function() {
     // open tags autocomplete and press enter
     var tagsField = this.window.document.getElementById("editBMPanel_tagsField");
     var self = this;
 
-    function windowObserver(aSubject, aTopic, aData) {
-      if (aTopic == "domwindowclosed" &&
-          aSubject.QueryInterface(Ci.nsIDOMWindow).location == DIALOG_URL) {
-        ww.unregisterNotification(windowObserver);
-        tagsField.popup.removeEventListener("popuphidden", popupListener, true);
-        ok(false, "Dialog window should not be closed by pressing Enter on the autocomplete popup");
+    this.window.addEventListener("unload", function(event) {
+      self.window.removeEventListener("unload", arguments.callee, true);
+      tagsField.popup.removeEventListener("popuphidden", popupListener, true);
+      ok(self._cleanShutdown, "Dialog window should not be closed by pressing Enter on the autocomplete popup");
+      executeSoon(function () {
         self.finish();
-      }
-    }
+      });
+    }, true);
 
     var popupListener = {
       handleEvent: function(aEvent) {
         switch (aEvent.type) {
           case "popuphidden":
             // Everything worked fine, we can stop observing the window.
-            ww.unregisterNotification(windowObserver);
-            tagsField.popup.removeEventListener("popuphidden", this, true);
+            self._cleanShutdown = true;
             self.window.document.documentElement.cancelDialog();
-            self.finish();
             break;
           case "popupshown":
             tagsField.popup.removeEventListener("popupshown", this, true);
-            // In case this test fails the window will close, we should mark the
-            // failure and continue, to avoid timing out.
-            ww.registerNotification(windowObserver);
+            // In case this test fails the window will close, the test will fail
+            // since we didn't set _cleanShutdown.
             var tree = tagsField.popup.tree;
             // Focus and select first result.
             isnot(tree, null, "Autocomplete results tree exists");
             is(tree.view.rowCount, 1, "We have 1 autocomplete result");
             tagsField.popup.selectedIndex = 0;
             is(tree.view.selection.count, 1,
                "We have selected a tag from the autocomplete popup");
             info("About to focus the autocomplete results tree");
@@ -313,22 +310,24 @@ gTests.push({
   },
 
   run: function() {
     this._itemId = this.window.gEditItemOverlay._itemId;
     // Change folder name
     var namePicker = this.window.document.getElementById("editBMPanel_namePicker");
     var userEnteredName = this.window.document.getElementById("editBMPanel_userEnteredName");
     var self = this;
+
     this.window.addEventListener("unload", function(event) {
-        this.window.removeEventListener("unload", arguments.callee, false);
-        executeSoon(function() {
-          self.finish();
-        });
-      }, false);
+      self.window.removeEventListener("unload", arguments.callee, false);
+      executeSoon(function () {
+        self.finish();
+      });
+    }, false);
+
     namePicker.value = "n";
     userEnteredName.label = "n";
     info("About to focus the namePicker field");
     namePicker.focus();
     EventUtils.synthesizeKey("VK_RETURN", {}, this.window);
   },
 
   finish: function() {
@@ -352,16 +351,17 @@ gTests.push({
 
 gTests.push({
   desc: "Bug 476020 - Pressing Esc while having the tag autocomplete open closes the bookmarks panel",
   sidebar: SIDEBAR_BOOKMARKS_ID,
   action: ACTION_EDIT,
   itemType: null,
   window: null,
   _itemId: null,
+  _cleanShutdown: false,
 
   setup: function() {
     // Add a bookmark in unsorted bookmarks folder.
     this._itemId = add_bookmark(PlacesUtils._uri(TEST_URL));
     ok(this._itemId > 0, "Correctly added a bookmark");
     // Add a tag to this bookmark.
     PlacesUtils.tagging.tagURI(PlacesUtils._uri(TEST_URL),
                                ["testTag"]);
@@ -374,41 +374,37 @@ gTests.push({
     is(tree.selectedNode.itemId, this._itemId, "Bookmark has been selected");
   },
 
   run: function() {
     // open tags autocomplete and press enter
     var tagsField = this.window.document.getElementById("editBMPanel_tagsField");
     var self = this;
 
-    function windowObserver(aSubject, aTopic, aData) {
-      if (aTopic == "domwindowclosed" &&
-          aSubject.QueryInterface(Ci.nsIDOMWindow).location == DIALOG_URL) {
-        ww.unregisterNotification(windowObserver);
-        tagsField.popup.removeEventListener("popuphidden", popupListener, true);
-        ok(false, "Dialog window should not be closed by pressing Escape on the autocomplete popup");
+    this.window.addEventListener("unload", function(event) {
+      self.window.removeEventListener("unload", arguments.callee, true);
+      tagsField.popup.removeEventListener("popuphidden", popupListener, true);
+      ok(self._cleanShutdown, "Dialog window should not be closed by pressing Escape on the autocomplete popup");
+      executeSoon(function () {
         self.finish();
-      }
-    }
+      });
+    }, true);
 
     var popupListener = {
       handleEvent: function(aEvent) {
         switch (aEvent.type) {
           case "popuphidden":
-            // Everything worked fine, we can stop observing the window.
-            ww.unregisterNotification(windowObserver);
-            tagsField.popup.removeEventListener("popuphidden", this, true);
+            // Everything worked fine.
+            self._cleanShutdown = true;
             self.window.document.documentElement.cancelDialog();
-            self.finish();
             break;
           case "popupshown":
             tagsField.popup.removeEventListener("popupshown", this, true);
-            // In case this test fails the window will close, we should mark the
-            // failure and continue, to avoid timing out.
-            ww.registerNotification(windowObserver);
+            // In case this test fails the window will close, the test will fail
+            // since we didn't set _cleanShutdown.
             var tree = tagsField.popup.tree;
             // Focus and select first result.
             isnot(tree, null, "Autocomplete results tree exists");
             is(tree.view.rowCount, 1, "We have 1 autocomplete result");
             tagsField.popup.selectedIndex = 0;
             is(tree.view.selection.count, 1,
                "We have selected a tag from the autocomplete popup");
             info("About to focus the autocomplete results tree");
@@ -474,26 +470,23 @@ gTests.push({
   },
 
   run: function() {
     // Open folder selector.
     var foldersExpander = this.window.document.getElementById("editBMPanel_foldersExpander");
     var folderTree = this.window.document.getElementById("editBMPanel_folderTree");
     var self = this;
 
-    function windowObserver(aSubject, aTopic, aData) {
-      if (aTopic == "domwindowclosed" &&
-          aSubject.QueryInterface(Ci.nsIDOMWindow).location == DIALOG_URL_MINIMAL_UI) {
-        ww.unregisterNotification(windowObserver);
-        ok(self._cleanShutdown,
-           "Dialog window should not be closed by pressing ESC in folder name textbox");
+    this.window.addEventListener("unload", function(event) {
+      self.window.removeEventListener("unload", arguments.callee, true);
+      ok(self._cleanShutdown, "Dialog window should not be closed by pressing ESC in folder name textbox");
+      executeSoon(function () {
         self.finish();
-      }
-    }
-    ww.registerNotification(windowObserver);
+      });
+    }, true);
 
     folderTree.addEventListener("DOMAttrModified", function onDOMAttrModified(event) {
       if (event.attrName != "place")
         return;
       folderTree.removeEventListener("DOMAttrModified", arguments.callee, false);
       executeSoon(function () {
         // Create a new folder.
         var newFolderButton = self.window.document.getElementById("editBMPanel_newFolderButton");
--- a/browser/components/places/tests/browser/browser_sidebarpanels_click.js
+++ b/browser/components/places/tests/browser/browser_sidebarpanels_click.js
@@ -34,182 +34,183 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 // This test makes sure that the items in the bookmarks and history sidebar
 // panels are clickable in both LTR and RTL modes.
 
 function test() {
+  waitForExplicitFinish();
+
   const BOOKMARKS_SIDEBAR_ID = "viewBookmarksSidebar";
   const BOOKMARKS_SIDEBAR_TREE_ID = "bookmarks-view";
   const HISTORY_SIDEBAR_ID = "viewHistorySidebar";
   const HISTORY_SIDEBAR_TREE_ID = "historyTree";
-
-  // Initialization.
-  let os = Cc["@mozilla.org/observer-service;1"].
-           getService(Ci.nsIObserverService);
-  let bs = PlacesUtils.bookmarks;
-  let hs = PlacesUtils.history;
-  let sidebarBox = document.getElementById("sidebar-box");
-  let sidebar = document.getElementById("sidebar");
-  waitForExplicitFinish();
+  const TEST_URL = "http://mochi.test:8888/browser/browser/components/places/tests/browser/sidebarpanels_click_test_page.html";
 
   // If a sidebar is already open, close it.
-  if (!sidebarBox.hidden) {
+  if (!document.getElementById("sidebar-box").hidden) {
     info("Unexpected sidebar found - a previous test failed to cleanup correctly");
     toggleSidebar();
   }
 
-  const TEST_URL = "http://mochi.test:8888/browser/browser/components/places/tests/browser/sidebarpanels_click_test_page.html";
+  let sidebar = document.getElementById("sidebar");
+  let tests = [];
+  let currentTest;
 
-  let tests = [];
   tests.push({
     _itemID: null,
     init: function() {
       // Add a bookmark to the Unfiled Bookmarks folder.
-      this._itemID = bs.insertBookmark(bs.unfiledBookmarksFolder,
-                                       PlacesUtils._uri(TEST_URL),
-                                       bs.DEFAULT_INDEX, "test");
+      this._itemID = PlacesUtils.bookmarks.insertBookmark(
+        PlacesUtils.unfiledBookmarksFolderId, PlacesUtils._uri(TEST_URL),
+        PlacesUtils.bookmarks.DEFAULT_INDEX, "test"
+      );
     },
     prepare: function() {
     },
     selectNode: function(tree) {
       tree.selectItems([this._itemID]);
     },
-    cleanup: function() {
-      bs.removeFolderChildren(bs.unfiledBookmarksFolder);
+    cleanup: function(aCallback) {
+      PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
+      executeSoon(aCallback);
     },
     sidebarName: BOOKMARKS_SIDEBAR_ID,
     treeName: BOOKMARKS_SIDEBAR_TREE_ID,
     desc: "Bookmarks sidebar test"
   });
 
   tests.push({
     init: function() {
       // Add a history entry.
-      this.cleanup();
       let uri = PlacesUtils._uri(TEST_URL);
-      hs.addVisit(uri, Date.now() * 1000, null, hs.TRANSITION_TYPED, false, 0);
-      let gh = hs.QueryInterface(Ci.nsIGlobalHistory2);
-      ok(gh.isVisited(uri), "Item is visited");
+      PlacesUtils.history.addVisit(uri, Date.now() * 1000, null,
+                                   PlacesUtils.history.TRANSITION_TYPED,
+                                   false, 0);
+      ok(PlacesUtils.ghistory2.isVisited(uri), "Item is visited");
     },
     prepare: function() {
       sidebar.contentDocument.getElementById("byvisited").doCommand();
     },
     selectNode: function(tree) {
       tree.selectNode(tree.view.nodeForTreeIndex(0));
       is(tree.selectedNode.uri, TEST_URL, "The correct visit has been selected");
       is(tree.selectedNode.itemId, -1, "The selected node is not bookmarked");
     },
-    cleanup: function() {
-      hs.QueryInterface(Ci.nsIBrowserHistory)
-        .removeAllPages();
+    cleanup: function(aCallback) {
+      waitForClearHistory(aCallback);
     },
     sidebarName: HISTORY_SIDEBAR_ID,
     treeName: HISTORY_SIDEBAR_TREE_ID,
     desc: "History sidebar test"
   });
 
-  let currentTest;
-
   function testPlacesPanel(preFunc, postFunc) {
     currentTest.init();
 
     sidebar.addEventListener("load", function() {
       sidebar.removeEventListener("load", arguments.callee, true);
-
-      let doc = sidebar.contentDocument;
-      let tree = doc.getElementById(currentTest.treeName);
-      let tbo = tree.treeBoxObject;
-
       executeSoon(function() {
         currentTest.prepare();
+
         if (preFunc)
           preFunc();
 
         function observer(aSubject, aTopic, aData) {
           info("alert dialog observed as expected");
-          os.removeObserver(observer, "common-dialog-loaded");
-          os.removeObserver(observer, "tabmodal-dialog-loaded");
+          Services.obs.removeObserver(observer, "common-dialog-loaded");
+          Services.obs.removeObserver(observer, "tabmodal-dialog-loaded");
 
           aSubject.Dialog.ui.button0.click();
 
           executeSoon(function () {
               toggleSidebar(currentTest.sidebarName);
-              currentTest.cleanup();
-              postFunc();
+              currentTest.cleanup(postFunc);
             });
         }
-        os.addObserver(observer, "common-dialog-loaded", false);
-        os.addObserver(observer, "tabmodal-dialog-loaded", false);
+        Services.obs.addObserver(observer, "common-dialog-loaded", false);
+        Services.obs.addObserver(observer, "tabmodal-dialog-loaded", false);
+
+        let tree = sidebar.contentDocument.getElementById(currentTest.treeName);
 
         // Select the inserted places item.
         currentTest.selectNode(tree);
-        is(tbo.view.selection.count, 1,
-           "The test node should be successfully selected");
-        // Get its row ID.
-        let min = {}, max = {};
-        tbo.view.selection.getRangeAt(0, min, max);
-        let rowID = min.value;
-        tbo.ensureRowIsVisible(rowID);
 
-        // Calculate the click coordinates.
-        let x = {}, y = {}, width = {}, height = {};
-        tbo.getCoordsForCellItem(rowID, tree.columns[0], "text",
-                                 x, y, width, height);
-        x = x.value + width.value / 2;
-        y = y.value + height.value / 2;
-        // Simulate the click.
-        EventUtils.synthesizeMouse(tree.body, x, y, {}, doc.defaultView);
+        synthesizeClickOnSelectedTreeCell(tree);
         // Now, wait for the observer to catch the alert dialog.
         // If something goes wrong, the test will time out at this stage.
         // Note that for the history sidebar, the URL itself is not opened,
         // and Places will show the load-js-data-url-error prompt as an alert
         // box, which means that the click actually worked, so it's good enough
         // for the purpose of this test.
       });
     }, true);
     toggleSidebar(currentTest.sidebarName);
   }
 
+  function synthesizeClickOnSelectedTreeCell(aTree) {
+    let tbo = aTree.treeBoxObject;
+    is(tbo.view.selection.count, 1,
+       "The test node should be successfully selected");
+    // Get selection rowID.
+    let min = {}, max = {};
+    tbo.view.selection.getRangeAt(0, min, max);
+    let rowID = min.value;
+    tbo.ensureRowIsVisible(rowID);
+
+    // Calculate the click coordinates.
+    let x = {}, y = {}, width = {}, height = {};
+    tbo.getCoordsForCellItem(rowID, aTree.columns[0], "text",
+                             x, y, width, height);
+    x = x.value + width.value / 2;
+    y = y.value + height.value / 2;
+    // Simulate the click.
+    EventUtils.synthesizeMouse(aTree.body, x, y, {},
+                               aTree.ownerDocument.defaultView);
+  }
+
   function changeSidebarDirection(aDirection) {
-    document.getElementById("sidebar")
-            .contentDocument
-            .documentElement
-            .style.direction = aDirection;
+    sidebar.contentDocument.documentElement.style.direction = aDirection;
+  }
+
+  function waitForClearHistory(aCallback) {
+    Services.obs.addObserver(function(aSubject, aTopic, aData) {
+      Services.obs.removeObserver(arguments.callee, PlacesUtils.TOPIC_EXPIRATION_FINISHED);
+      aCallback(aSubject, aTopic, aData);
+    }, PlacesUtils.TOPIC_EXPIRATION_FINISHED, false);
+    PlacesUtils.bhistory.removeAllPages();
   }
 
   function runNextTest() {
-    // Remove any extraneous tabs.
-    for (let tabCount = gBrowser.tabContainer.childNodes.length;
-         tabCount > 1; tabCount--) {
-      gBrowser.selectedTab = gBrowser.tabContainer.childNodes[tabCount - 1];
-      gBrowser.removeCurrentTab();
+    // Remove eventual tabs created by previous sub-tests.
+    while (gBrowser.tabs.length > 1) {
+      gBrowser.removeTab(gBrowser.tabContainer.lastChild);
     }
 
-    if (tests.length == 0)
+    if (tests.length == 0) {
       finish();
+    }
     else {
-      // Create a new tab for our test to use.
+      // Create a new tab and run the test.
       gBrowser.selectedTab = gBrowser.addTab();
-
-      // Now we can run our test.
       currentTest = tests.shift();
       testPlacesPanel(function() {
-        changeSidebarDirection("ltr");
-        info("Running " + currentTest.desc + " in LTR mode");
-      }, function() {
-        executeSoon(function() {
-          testPlacesPanel(function() {
-            // Run the test in RTL mode.
-            changeSidebarDirection("rtl");
-            info("Running " + currentTest.desc + " in RTL mode");
-          }, function() {
-            executeSoon(runNextTest);
-          });
-        });
-      });
+                        changeSidebarDirection("ltr");
+                        info("Running " + currentTest.desc + " in LTR mode");
+                      },
+                      function() {
+                        testPlacesPanel(function() {
+                          // Run the test in RTL mode.
+                          changeSidebarDirection("rtl");
+                          info("Running " + currentTest.desc + " in RTL mode");
+                        },
+                        function() {
+                          runNextTest();
+                        });
+                      });
     }
   }
 
-  runNextTest();
+  // Ensure history is clean before starting the test.
+  waitForClearHistory(runNextTest);
 }
--- a/browser/components/sessionstore/src/nsSessionStore.js
+++ b/browser/components/sessionstore/src/nsSessionStore.js
@@ -4021,17 +4021,17 @@ SessionStoreService.prototype = {
    *        nsIFile
    * @param aData
    *        String data
    */
   _writeFile: function sss_writeFile(aFile, aData) {
     // Initialize the file output stream.
     var ostream = Cc["@mozilla.org/network/safe-file-output-stream;1"].
                   createInstance(Ci.nsIFileOutputStream);
-    ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, 0);
+    ostream.init(aFile, 0x02 | 0x08 | 0x20, 0600, ostream.DEFER_OPEN);
 
     // Obtain a converter to convert our data to a UTF-8 encoded input stream.
     var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
                     createInstance(Ci.nsIScriptableUnicodeConverter);
     converter.charset = "UTF-8";
 
     // Asynchronously copy the data to the file.
     var istream = converter.convertToInputStream(aData);
--- a/browser/components/sessionstore/test/browser/browser_500328.js
+++ b/browser/components/sessionstore/test/browser/browser_500328.js
@@ -72,18 +72,18 @@ function checkState(tab) {
       // previous entry, which is bad.
       let doc = contentWindow.document;
       let newElem = doc.getElementById("new-elem");
       ok(newElem, "doc should contain new-elem.");
       newElem.parentNode.removeChild(newElem);
       ok(!doc.getElementById("new-elem"), "new-elem should be removed.");
 
       // Clean up after ourselves and finish the test.
-      tab.linkedBrowser.removeEventListener("popstate", arguments.callee, false);
-      tab.linkedBrowser.removeEventListener("load", arguments.callee, false);
+      tab.linkedBrowser.removeEventListener("popstate", arguments.callee, true);
+      tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
       gBrowser.removeTab(tab);
       finish();
     }
   };
 
   tab.linkedBrowser.addEventListener("load", handler, true);
   tab.linkedBrowser.addEventListener("popstate", handler, true);
 
--- a/browser/locales/shipped-locales
+++ b/browser/locales/shipped-locales
@@ -19,16 +19,17 @@ en-US
 en-ZA
 eo
 es-AR
 es-CL
 es-ES
 es-MX
 et
 eu
+fa
 fi
 fr
 fy-NL
 ga-IE
 gd
 gl
 gu-IN
 he
index 24a14b825da0c9c0325fae2c773f1397bd4b145d..0c7a196de516f54cbd1ab19b06d46236c43ad206
GIT binary patch
literal 394
zc$@)>0d@X~P)<h;3K|Lk000e1NJLTq000{R000^Y1^@s6Mu;cy0003|Nkl<ZNQtG6
zF;Bx#41_OLN~j=6K&NahbP5YuqAu+~Vd(#@Sm37}ixXL{{qhnbeX`%(*$zm48IB~+
zQnhAt1LuUN=T9Jcl846AjwJViKFoOjxC;}*QwKZ_!Q37qY7T<cJ-Uf(r{DIN9qj1;
zL}wQz<~n_>b9j^5J6>-xp6_`*%z<cu=X*b5b)A0)$(=*%XfH-@6P^p4P%FbZKd=k3
zt_PBhh?dttk7!K2+BY0)NN!c%B=jhkVoS1tG)t&Wodgp0s4}%2zam*fno0#LlFt)M
zbGX_80OP@^pP<gkLB2v*35BW}I9dw3zkoV2hhnB)N=3Plwdz-aZoyhnn)h71d9Ara
zHw%tLGo{*z>L1(+k!Lk*0)|DAzX5P3q%wL3>VOBS_ojN8T=3-ZI8)CBr<r^tywBte
o$sfZ-)eFgAlHY-EXT3cme>5FoW_=%r=Kufz07*qoM6N<$f^37SIRF3v
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -181,21 +181,26 @@
   #navigator-toolbox[tabsontop=false] > #PersonalToolbar {
     margin-top: 2px;
     border-top: 1px solid @toolbarShadowColor@;
   }
   #navigator-toolbox[tabsontop=false] > #PersonalToolbar:not(:-moz-lwtheme) {
     background-image: -moz-linear-gradient(@toolbarHighlight@, rgba(255,255,255,0));
   }
 
-  #main-window[sizemode="normal"] #TabsToolbar[tabsontop="true"]:not([inFullscreen="true"]):not(:-moz-lwtheme) {
+  #main-window[sizemode=normal] #TabsToolbar[tabsontop=true]:not([inFullscreen]) {
     padding-left: 4px;
     padding-right: 4px;
   }
 
+  #main-window[sizemode=normal] #TabsToolbar[tabsontop=false]:not([inFullscreen]) {
+    padding-left: 2px;
+    padding-right: 2px;
+  }
+
   /* Make the window draggable by glassed toolbars (bug 555081) */
   #toolbar-menubar:not([autohide="true"]),
   #TabsToolbar[tabsontop="true"],
   #navigator-toolbox[tabsontop="false"] > #nav-bar,
   #nav-bar + #customToolbars + #PersonalToolbar[collapsed="true"] + #TabsToolbar[tabsontop="false"]:last-child,
   #navigator-toolbox > toolbar:not(#toolbar-menubar):-moz-lwtheme {
     -moz-binding: url("chrome://global/content/bindings/toolbar.xml#toolbar-drag");
   }
@@ -316,8 +321,77 @@
   -moz-image-region: rect(0, 49px, 16px, 32px);
 }
 #close-button:hover {
   -moz-image-region: rect(16px, 49px, 32px, 32px);
 }
 #close-button:hover:active {
   -moz-image-region: rect(32px, 49px, 48px, 32px);
 }
+
+/* ::::: splitmenu highlight style that imitates Windows 7 start menu ::::: */
+@media all and (-moz-windows-default-theme) {
+  .splitmenu-menuitem,
+  .splitmenu-menu {
+    -moz-appearance: none;
+    padding-top: 2px;
+    padding-bottom: 2px;
+    border: 1px solid transparent;
+  }
+  .splitmenu-menuitem {
+    -moz-margin-end: 0;
+  }
+  .splitmenu-menu {
+    -moz-margin-start: -1px;
+  }
+  .splitmenu-menuitem:-moz-locale-dir(ltr),
+  .splitmenu-menu:-moz-locale-dir(rtl) {
+    border-top-left-radius: 3px;
+    border-bottom-left-radius: 3px;
+  }
+  .splitmenu-menu:-moz-locale-dir(ltr),
+  .splitmenu-menuitem:-moz-locale-dir(rtl) {
+    border-top-right-radius: 3px;
+    border-bottom-right-radius: 3px;
+  }
+
+  .splitmenu-menuitem > .menu-text {
+    -moz-margin-start: 1px !important;
+    -moz-margin-end: 3px !important;
+  }
+  .splitmenu-menu > .menu-right {
+    -moz-margin-end: -3px;
+  }
+
+  .splitmenu-menuitem[iconic],
+  .splitmenu-menu[iconic] {
+    padding-bottom: 1px;
+  }
+  .splitmenu-menuitem[iconic] > .menu-iconic-left {
+    margin-top: -3px;
+    margin-bottom: -2px;
+    -moz-margin-start: -1px;
+  }
+  .splitmenu-menuitem[iconic] > .menu-iconic-text {
+    -moz-margin-start: 2px !important;
+    -moz-margin-end: 3px !important;
+  }
+  .splitmenu-menu[iconic] > .menu-right {
+    margin-top: -1px;
+  }
+
+  .splitmenu-menuitem[_moz-menuactive],
+  .splitmenu-menu[_moz-menuactive] {
+    background-color: transparent;
+    background-image: -moz-linear-gradient(#fafbfd, #ebf3fd);
+    border-color: #aeccf1;
+  }
+
+  .splitmenu-menuitem[disabled][_moz-menuactive],
+  .splitmenu-menu[disabled][_moz-menuactive] {
+    background-image: -moz-linear-gradient(#f8f9f9, #eaeaea);
+    border-color: #d8d7d7;
+  }
+
+  .splitmenu-menu[_moz-menuactive]:not(:hover):not([open]) {
+    background-image: none;
+  }
+}
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -1528,29 +1528,38 @@ richlistitem[type~="action"][actiontype=
 }
 
 #TabsToolbar:not(:-moz-lwtheme),
 #TabsToolbar[tabsontop=false] {
   background-image:
     -moz-linear-gradient(bottom, @toolbarShadowColor@ 1px, rgba(0,0,0,.05) 1px, transparent 50%);
 }
 
+%ifndef WINSTRIPE_AERO
+@media all and (-moz-windows-default-theme) {
+  #main-window[sizemode=normal] #TabsToolbar:not([inFullscreen]) {
+    padding-left: 2px;
+    padding-right: 2px;
+  }
+}
+%endif
+
 .tabbrowser-tab,
 .tabs-newtab-button {
   -moz-appearance: none;
   background: @toolbarShadowOnTab@, @bgTabTexture@,
               -moz-linear-gradient(-moz-dialog, -moz-dialog);
   background-origin: border-box;
   background-position: 1px 2px;
-  background-size: 100% -moz-calc(100% - 2px);
+  background-size: -moz-calc(100% - 2px) -moz-calc(100% - 2px);
   background-repeat: no-repeat;
   margin: 0;
   padding: 0;
-  -moz-border-image: url(tabbrowser/tab.png) 4 5 3 6 / 4px 5px 3px 6px repeat stretch;
-  border-radius: 10px 8px 0 0;
+  -moz-border-image: url(tabbrowser/tab.png) 6 3 4 / 6px 3px 4px repeat stretch;
+  border-radius: 7px 7px 0 0;
 }
 
 .tabbrowser-tab:hover,
 .tabs-newtab-button:hover {
   background-image: @toolbarShadowOnTab@, @bgTabTextureHover@,
                     -moz-linear-gradient(-moz-dialog, -moz-dialog);
 }
 
@@ -1618,16 +1627,17 @@ richlistitem[type~="action"][actiontype=
 }
 
 .tab-throbber,
 .tab-icon-image {
   width: 16px;
   height: 16px;
   list-style-image: url("chrome://global/skin/icons/folder-item.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
+  -moz-margin-start: 2px;
   -moz-margin-end: 3px;
 }
 
 .tab-throbber {
   list-style-image: url("chrome://browser/skin/tabbrowser/connecting.png");
 }
 
 .tab-throbber[progress] {
@@ -1635,18 +1645,18 @@ richlistitem[type~="action"][actiontype=
 }
 
 #tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
   min-height: 16px; /* corresponds to the max. height of non-textual tab contents, i.e. the favicon */
 }
 
 .tab-throbber[pinned],
 .tab-icon-image[pinned] {
-  -moz-margin-start: 2px;
-  -moz-margin-end: 2px;
+  -moz-margin-start: 5px;
+  -moz-margin-end: 5px;
 }
 
 /* tabbrowser-tab focus ring */
 .tabbrowser-tab:focus > .tab-stack {
   outline: 1px dotted;
 }
 
 /* Tab DnD indicator */
@@ -1751,17 +1761,17 @@ richlistitem[type~="action"][actiontype=
 .tabs-newtab-button,
 #TabsToolbar > #new-tab-button,
 #TabsToolbar > toolbarpaletteitem > #new-tab-button {
   list-style-image: url(chrome://browser/skin/tabbrowser/newtab.png);
   -moz-image-region: rect(0, 16px, 18px, 0);
 }
 
 .tabs-newtab-button {
-  width: 31px;
+  width: 30px;
 }
 
 .tabs-newtab-button:hover:active,
 #TabsToolbar > #new-tab-button:hover:active {
   -moz-image-region: rect(0, 32px, 18px, 16px);
 }
 
 #alltabs-button {
index deeeb0add3074b1bf453f08dc96cbf84c43bb74f..fb0fc676f11c54d4b5af1e284e72a8e8b5b3f684
GIT binary patch
literal 238
zc%17D@N?(olHy`uVBq!ia0vp^Ahrw#8<33Ht7i?QBuiW)N`mv#O3D+9QW+dm@{>{(
zJaZG%Q-e|yQz{EjrrH1%P4IMa45_%4BqBIHDJda=Au&zEjjev+4|(nh39Lz?3SkUM
zb|$U!8-6ef+-ID*Bs)2G>Hgf$Zs)G+&$DwsreHWh#)Fsn!mA0(&(Ev;`~QEuM90jA
z8H`<yIf)>d6E0<%o}LpvzIVuT+$46Sj(uu!dK1?_#z+5oW<0PD;d>M9#&)QoFy!Hi
hLxHU(K^y`J3|Ft%GfduRr3G{wgQu&X%Q~loCIBBuRU!ZY
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -553,16 +553,17 @@ MOZ_ENABLE_D3D9_LAYER	= @MOZ_ENABLE_D3D9
 MOZ_ENABLE_D3D10_LAYER  = @MOZ_ENABLE_D3D10_LAYER@
 
 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_ENABLE_QTNETWORK    = @MOZ_ENABLE_QTNETWORK@
+MOZ_ENABLE_QTMOBILITY   = @MOZ_ENABLE_QTMOBILITY@
 MOZ_ENABLE_CONTENTACTION   = @MOZ_ENABLE_CONTENTACTION@
 MOZ_ENABLE_MEEGOTOUCHSHARE = @MOZ_ENABLE_MEEGOTOUCHSHARE@
 
 MOZ_DBUS_CFLAGS         = @MOZ_DBUS_CFLAGS@
 MOZ_DBUS_LIBS           = @MOZ_DBUS_LIBS@
 MOZ_DBUS_GLIB_CFLAGS    = @MOZ_DBUS_GLIB_CFLAGS@
 MOZ_DBUS_GLIB_LIBS      = @MOZ_DBUS_GLIB_LIBS@
 MOZ_ENABLE_DBUS         = @MOZ_ENABLE_DBUS@
new file mode 100755
--- /dev/null
+++ b/config/find_OOM_errors.py
@@ -0,0 +1,335 @@
+#!/usr/bin/env python
+
+usage = """%prog: A test for OOM conditions in the shell.
+
+%prog finds segfaults and other errors caused by incorrect handling of
+allocation during OOM (out-of-memory) conditions.
+"""
+
+help = """Check for regressions only. This runs a set of files with a known
+number of OOM errors (specified by REGRESSION_COUNT), and exits with a non-zero
+result if more or less errors are found. See js/src/Makefile.in for invocation.
+"""
+
+
+import hashlib
+import re
+import shlex
+import subprocess
+import sys
+import threading
+import time
+
+from optparse import OptionParser
+
+#####################################################################
+# Utility functions
+#####################################################################
+def run(args, stdin=None):
+  class ThreadWorker(threading.Thread):
+    def __init__(self, pipe):
+      super(ThreadWorker, self).__init__()
+      self.all = ""
+      self.pipe = pipe
+      self.setDaemon(True)
+
+    def run(self):
+      while True:
+        line = self.pipe.readline()
+        if line == '': break
+        else:
+          self.all += line
+
+  try:
+    if type(args) == str:
+      args = shlex.split(args)
+
+    args = [str(a) for a in args] # convert to strs
+
+    stdin_pipe = subprocess.PIPE if stdin else None
+    proc = subprocess.Popen(args, stdin=stdin_pipe, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    if stdin_pipe:
+      proc.stdin.write(stdin)
+      proc.stdin.close()
+
+    stdout_worker = ThreadWorker(proc.stdout)
+    stderr_worker = ThreadWorker(proc.stderr)
+    stdout_worker.start()
+    stderr_worker.start()
+
+    proc.wait()
+    stdout_worker.join()
+    stderr_worker.join()
+
+  except KeyboardInterrupt, e:
+    sys.exit(-1)
+
+  stdout, stderr = stdout_worker.all, stderr_worker.all
+  result = (stdout, stderr, proc.returncode)
+  return result
+
+def get_js_files():
+  (out, err, exit) = run('find ../jit-test/tests -name "*.js"')
+  if (err, exit) == ("", 0):
+    sys.exit("Wrong directory, run from an objdir")
+  return out.split()
+
+
+
+#####################################################################
+# Blacklisting
+#####################################################################
+def in_blacklist(sig):
+  return sig in blacklist
+
+def add_to_blacklist(sig):
+  blacklist[sig] = blacklist.get(sig, 0)
+  blacklist[sig] += 1
+
+# How often is a particular lines important for this.
+def count_lines():
+  """Keep track of the amount of times individual lines occur, in order to
+     prioritize the errors which occur most frequently."""
+  counts = {}
+  for string,count in blacklist.items():
+    for line in string.split("\n"):
+      counts[line] = counts.get(line, 0) + count
+
+  lines = []
+  for k,v in counts.items():
+    lines.append("%6d: %s" % (v,k))
+
+  lines.sort()
+
+  countlog = file("../OOM_count_log", "w")
+  countlog.write("\n".join(lines))
+  countlog.flush()
+  countlog.close()
+
+
+#####################################################################
+# Output cleaning
+#####################################################################
+def clean_voutput(err):
+  # Skip what we can't reproduce
+  err = re.sub(r"^--\d+-- run: /usr/bin/dsymutil \"shell/js\"$", "", err, flags=re.MULTILINE)
+  err = re.sub(r"^==\d+==", "", err, flags=re.MULTILINE)
+  err = re.sub(r"^\*\*\d+\*\*", "", err, flags=re.MULTILINE)
+  err = re.sub(r"^\s+by 0x[0-9A-Fa-f]+: ", "by: ", err, flags=re.MULTILINE)
+  err = re.sub(r"^\s+at 0x[0-9A-Fa-f]+: ", "at: ", err, flags=re.MULTILINE)
+  err = re.sub(r"(^\s+Address 0x)[0-9A-Fa-f]+( is not stack'd)", r"\1\2", err, flags=re.MULTILINE)
+  err = re.sub(r"(^\s+Invalid write of size )\d+", r"\1x", err, flags=re.MULTILINE)
+  err = re.sub(r"(^\s+Invalid read of size )\d+", r"\1x", err, flags=re.MULTILINE)
+  err = re.sub(r"(^\s+Address 0x)[0-9A-Fa-f]+( is )\d+( bytes inside a block of size )[0-9,]+( free'd)", r"\1\2\3\4", err, flags=re.MULTILINE)
+
+  # Skip the repeating bit due to the segfault
+  lines = []
+  for l in err.split('\n'):
+    if l == " Process terminating with default action of signal 11 (SIGSEGV)":
+      break
+    lines.append(l)
+  err = '\n'.join(lines)
+
+  return err
+
+def remove_failed_allocation_backtraces(err):
+  lines = []
+
+  add = True
+  for l in err.split('\n'):
+
+    # Set start and end conditions for including text
+    if l == " The site of the failed allocation is:":
+      add = False
+    elif l[:2] not in ['by: ', 'at:']:
+      add = True
+
+    if add:
+      lines.append(l)
+
+
+  err = '\n'.join(lines)
+
+  return err
+
+
+def clean_output(err):
+  err = re.sub(r"^js\(\d+,0x[0-9a-f]+\) malloc: \*\*\* error for object 0x[0-9a-f]+: pointer being freed was not allocated\n\*\*\* set a breakppoint in malloc_error_break to debug\n$", "pointer being freed was not allocated", err, flags=re.MULTILINE)
+
+  return err
+
+
+#####################################################################
+# Consts, etc
+#####################################################################
+
+command_template = 'shell/js' \
+                 + ' -m -j -p' \
+                 + ' -e "const platform=\'darwin\'; const libdir=\'../jit-test/lib/\';"' \
+                 + ' -f ../jit-test/lib/prolog.js' \
+                 + ' -f %s'
+
+
+# Blacklists are things we don't want to see in our logs again (though we do
+# want to count them when they happen). Whitelists we do want to see in our
+# logs again, principally because the information we have isn't enough.
+
+blacklist = {}
+add_to_blacklist(r"('', '', 1)") # 1 means OOM if the shell hasn't launched yet.
+add_to_blacklist(r"('', 'out of memory\n', 1)")
+
+whitelist = set()
+whitelist.add(r"('', 'out of memory\n', -11)") # -11 means OOM
+whitelist.add(r"('', 'out of memory\nout of memory\n', -11)")
+
+
+
+#####################################################################
+# Program
+#####################################################################
+
+# Options
+parser = OptionParser(usage=usage)
+parser.add_option("-r", "--regression", action="store", metavar="REGRESSION_COUNT", help=help,
+                  type="int", dest="regression", default=0) # TODO: support a value of zero, eventually
+                  
+(OPTIONS, args) = parser.parse_args()
+
+
+if OPTIONS.regression:
+  # TODO: This should be expanded as we get a better hang of the OOM problems.
+  # For now, we'll just check that the number of OOMs in one short file does not
+  # increase.
+  files = ["../jit-test/tests/arguments/args-createontrace.js"]
+else:
+  files = get_js_files()
+
+  # Use a command-line arg to reduce the set of files
+  if len (args):
+    files = [f for f in files if f.find(args[0]) != -1]
+
+
+if OPTIONS.regression:
+  # Don't use a logfile, this is automated for tinderbox.
+  log = file("../OOM_log", "w")
+
+
+num_failures = 0
+for f in files:
+
+  # Run it once to establish boundaries
+  command = (command_template + ' -O') % (f)
+  out, err, exit = run(command)
+  max = re.match(".*OOM max count: (\d+).*", out, flags=re.DOTALL).groups()[0]
+  max = int(max)
+  
+  # OOMs don't recover well for the first 20 allocations or so.
+  # TODO: revisit this.
+  for i in range(20, max): 
+
+    if OPTIONS.regression == None:
+      print "Testing allocation %d/%d in %s" % (i,max,f)
+
+    command = (command_template + ' -A %d') % (f, i)
+    out, err, exit = run(command)
+
+    # Success (5 is SM's exit code for controlled errors)
+    if exit == 5 and err.find("out of memory") != -1:
+      continue
+
+    # Failure
+    else:
+
+      if OPTIONS.regression:
+        # Just count them
+        num_failures += 1
+        continue
+
+      #########################################################################
+      # The regression tests ends above. The rest of this is for running  the
+      # script manually.
+      #########################################################################
+
+      problem = str((out, err, exit))
+      if in_blacklist(problem) and problem not in whitelist:
+        add_to_blacklist(problem)
+        continue
+
+      add_to_blacklist(problem)
+
+
+      # Get valgrind output for a good stack trace
+      vcommand = "valgrind --dsymutil=yes -q --log-file=OOM_valgrind_log_file " + command
+      run(vcommand)
+      vout = file("OOM_valgrind_log_file").read()
+      vout = clean_voutput(vout)
+      sans_alloc_sites = remove_failed_allocation_backtraces(vout)
+
+      # Don't print duplicate information
+      if in_blacklist(sans_alloc_sites):
+        add_to_blacklist(sans_alloc_sites)
+        continue
+
+      add_to_blacklist(sans_alloc_sites)
+
+      log.write ("\n")
+      log.write ("\n")
+      log.write ("=========================================================================")
+      log.write ("\n")
+      log.write ("An allocation failure at\n\tallocation %d/%d in %s\n\tcauses problems (detected using bug 624094)" % (i, max, f))
+      log.write ("\n")
+      log.write ("\n")
+
+      log.write ("Command (from obj directory, using patch from bug 624094):\n  " + command)
+      log.write ("\n")
+      log.write ("\n")
+      log.write ("stdout, stderr, exitcode:\n  " + problem)
+      log.write ("\n")
+      log.write ("\n")
+
+      double_free = err.find("pointer being freed was not allocated") != -1
+      oom_detected = err.find("out of memory") != -1
+      multiple_oom_detected = err.find("out of memory\nout of memory") != -1
+      segfault_detected = exit == -11
+
+      log.write ("Diagnosis: ")
+      log.write ("\n")
+      if multiple_oom_detected:
+        log.write ("  - Multiple OOMs reported")
+        log.write ("\n")
+      if segfault_detected:
+        log.write ("  - segfault")
+        log.write ("\n")
+      if not oom_detected:
+        log.write ("  - No OOM checking")
+        log.write ("\n")
+      if double_free:
+        log.write ("  - Double free")
+        log.write ("\n")
+
+      log.write ("\n")
+
+      log.write ("Valgrind info:\n" + vout)
+      log.write ("\n")
+      log.write ("\n")
+      log.flush()
+
+  if not OPTIONS.regression == None:
+    count_lines()
+
+
+# Do the actual regression check
+if OPTIONS.regression:
+  expected_num_failures = OPTIONS.regression
+
+  if num_failures != expected_num_failures:
+
+    print "TEST-UNEXPECTED-FAIL |",
+    if num_failures > expected_num_failures:
+      print "More out-of-memory errors were found (%s) than expected (%d). This probably means an allocation site has been added without a NULL-check. If this is unavoidable, you can account for it by updating Makefile.in." % (num_failures, expected_num_failures),
+    else:
+      print "Congratulations, you have removed %d out-of-memory error(s) (%d remain)! Please account for it by updating Makefile.in." % (expected_num_failures - num_failures, num_failures),
+    sys.exit(-1)
+  else:
+    print 'TEST-PASS | find_OOM_errors | Found the expected number of OOM errors (%d)' % (expected_num_failures)
+
--- a/configure.in
+++ b/configure.in
@@ -5483,26 +5483,47 @@ incorrect])
     PKG_CHECK_MODULES(_QTNETWORK, QtNetwork >= 4.7,
                       MOZ_ENABLE_QTNETWORK=1,
                       MOZ_ENABLE_QTNETWORK=)
 
     if test "$MOZ_ENABLE_QTNETWORK"; then
       MOZ_ENABLE_QTNETWORK=1
       AC_DEFINE(MOZ_ENABLE_QTNETWORK)
     fi
+
+    MOZ_ENABLE_QTMOBILITY=
+    PKG_CHECK_MODULES(_QTMOBILITY, QtSensors,
+                      MOZ_ENABLE_QTMOBILITY=1,
+                      MOZ_ENABLE_QTMOBILITY=)
+    if test "$MOZ_ENABLE_QTMOBILITY"; then
+       MOZ_ENABLE_QTMOBILITY=1
+       MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS $_QTMOBILITY_CFLAGS"
+       MOZ_QT_LIBS="$MOZ_QT_LIBS $_QTMOBILITY_LIBS"
+    else
+       AC_CHECK_LIB(QtSensors, main, [
+          MOZ_ENABLE_QTMOBILITY=1
+          MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtMobility"
+          MOZ_QT_CFLAGS="$MOZ_QT_CFLAGS -I/usr/include/qt4/QtSensors"
+          MOZ_QT_LIBS="$MOZ_QT_LIBS -lQtSensors"
+       ])
+    fi
+    if test "$MOZ_ENABLE_QTMOBILITY"; then
+       AC_DEFINE(MOZ_ENABLE_QTMOBILITY)
+    fi
 fi
 
 AC_SUBST(GTK_CONFIG)
 AC_SUBST(TK_CFLAGS)
 AC_SUBST(TK_LIBS)
 
 AC_SUBST(MOZ_ENABLE_GTK2)
 AC_SUBST(MOZ_ENABLE_PHOTON)
 AC_SUBST(MOZ_ENABLE_QT)
 AC_SUBST(MOZ_ENABLE_QTNETWORK)
+AC_SUBST(MOZ_ENABLE_QTMOBILITY)
 AC_SUBST(MOZ_ENABLE_XREMOTE)
 AC_SUBST(MOZ_GTK2_CFLAGS)
 AC_SUBST(MOZ_GTK2_LIBS)
 AC_SUBST(MOZ_QT_CFLAGS)
 AC_SUBST(MOZ_QT_LIBS)
 
 AC_SUBST(MOC)
 
@@ -9661,16 +9682,17 @@ ac_configure_args="$ac_configure_args --
 ac_configure_args="$ac_configure_args --prefix=$dist"
 ac_configure_args="$ac_configure_args --with-sync-build-files=$_topsrcdir"
 if test "$MOZ_MEMORY"; then
    ac_configure_args="$ac_configure_args --enable-jemalloc"
    if test -n "$MOZ_MEMORY_LDFLAGS"; then
      export MOZ_MEMORY_LDFLAGS
    fi
 fi
+export MOZ_APP_NAME
 AC_OUTPUT_SUBDIRS(js/src)
 ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 
 fi # COMPILE_ENVIRONMENT && !LIBXUL_SDK_DIR
 
 dnl Prevent the regeneration of autoconf.mk forcing rebuilds of the world
 dnl Needs to be at the end to respect possible changes from NSPR configure
 if cmp -s config/autoconf.mk config/autoconf.mk.orig; then
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/637214-1.svg
@@ -0,0 +1,26 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="reftest-wait">
+
+<script>
+<![CDATA[
+
+window.addEventListener("load", function () {
+    document.documentElement.appendChild(document.getElementById("a"));
+    setTimeout(function () {
+        document.getElementById("x").setAttribute("id", "m1");
+        document.documentElement.removeAttribute("class");
+    }, 0);
+}, false);
+
+]]>
+</script>
+
+<g id="a">
+  <path id="x"/>
+  <text>
+    <textPath xlink:href="#m1">Text</textPath>
+    <textPath xlink:href="#m1">Text</textPath>
+
+  </text>
+</g>
+
+</svg>
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/637214-2.svg
@@ -0,0 +1,26 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="reftest-wait">
+
+<script>
+<![CDATA[
+
+window.addEventListener("load", function () {
+    document.documentElement.appendChild(document.getElementById("a"));
+    setTimeout(function () {
+        document.getElementById("x").removeAttribute("id");
+        document.documentElement.removeAttribute("class");
+    }, 0);
+}, false);
+
+]]>
+</script>
+
+<g id="a">
+  <path id="x"/>
+  <text>
+    <textPath xlink:href="#m1">Text</textPath>
+    <textPath xlink:href="#m1">Text</textPath>
+
+  </text>
+</g>
+
+</svg>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -81,8 +81,10 @@ load 590395-1.html
 load 595606-1.html
 load 595606-2.html
 load 606729-1.html
 load 593302-1.html
 load 593302-2.html
 load 610571-1.html
 load 604262-1.html
 load 628599-1.html
+load 637214-1.svg
+load 637214-2.svg
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1694,39 +1694,39 @@ public:
                                          nsIDOMNodeList** aReturn);
 
   /**
    * Returns a layer manager to use for the given document. Basically we
    * look up the document hierarchy for the first document which has
    * a presentation with an associated widget, and use that widget's
    * layer manager.
    *
-   * If one can't be found, a BasicLayerManager is created and returned.
-   *
    * @param aDoc the document for which to return a layer manager.
+   * @param aAllowRetaining an outparam that states whether the returned
+   * layer manager should be used for retained layers
    */
   static already_AddRefed<mozilla::layers::LayerManager>
-  LayerManagerForDocument(nsIDocument *aDoc);
+  LayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining = nsnull);
 
   /**
    * Returns a layer manager to use for the given document. Basically we
    * look up the document hierarchy for the first document which has
    * a presentation with an associated widget, and use that widget's
    * layer manager. In addition to the normal layer manager lookup this will
    * specifically request a persistent layer manager. This means that the layer
    * manager is expected to remain the layer manager for the document in the
    * forseeable future. This function should be used carefully as it may change
    * the document's layer manager.
    *
-   * If one can't be found, a BasicLayerManager is created and returned.
-   *
    * @param aDoc the document for which to return a layer manager.
+   * @param aAllowRetaining an outparam that states whether the returned
+   * layer manager should be used for retained layers
    */
   static already_AddRefed<mozilla::layers::LayerManager>
-  PersistentLayerManagerForDocument(nsIDocument *aDoc);
+  PersistentLayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining = nsnull);
 
   /**
    * Determine whether a content node is focused or not,
    *
    * @param aContent the content node to check
    * @return true if the content node is focused, false otherwise.
    */
   static PRBool IsFocusedContent(const nsIContent *aContent);
@@ -1893,16 +1893,29 @@ public:
   }
   ~nsAutoScriptBlocker() {
     nsContentUtils::RemoveScriptBlocker();
   }
 private:
   MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
+class NS_STACK_CLASS nsAutoRemovableScriptBlocker {
+public:
+  nsAutoRemovableScriptBlocker(MOZILLA_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
+    MOZILLA_GUARD_OBJECT_NOTIFIER_INIT;
+    nsContentUtils::AddRemovableScriptBlocker();
+  }
+  ~nsAutoRemovableScriptBlocker() {
+    nsContentUtils::RemoveRemovableScriptBlocker();
+  }
+private:
+  MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
+};
+
 class NS_STACK_CLASS mozAutoRemovableBlockerRemover
 {
 public:
   mozAutoRemovableBlockerRemover(nsIDocument* aDocument
                                  MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM);
   ~mozAutoRemovableBlockerRemover();
 
 private:
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -1621,19 +1621,16 @@ protected:
 
   // True if we're currently bfcached. This is only here for binary compat.
   // Remove once the gecko 2.0 has branched and just use mSHEntry instead.
   PRPackedBool mShellIsHidden;
 
   PRPackedBool mIsRegularHTML;
   PRPackedBool mIsXUL;
 
-  // Sync document.close behavior with document.open() (bug 627729)
-  PRPackedBool mForceOldParserForHotmail;
-
   enum {
     eTriUnset = 0,
     eTriFalse,
     eTriTrue
   } mAllowXULXBL;
 
   // True if we're loaded as data and therefor has any dangerous stuff, such
   // as scripts and plugins, disabled.
--- a/content/base/src/CSPUtils.jsm
+++ b/content/base/src/CSPUtils.jsm
@@ -157,17 +157,17 @@ CSPPolicyURIListener.prototype = {
   function(request, context, status) {
     if (Components.isSuccessCode(status)) {
       // send the policy we received back to the parent document's CSP
       // for parsing
       this._csp.refinePolicy(this._policy, this._docURI, this._docRequest);
     }
     else {
       // problem fetching policy so fail closed
-      this._csp.refinePolicy("allow 'none'", null, this._docURI, this._docRequest);
+      this._csp.refinePolicy("allow 'none'", this._docURI, this._docRequest);
     }
     // resume the parent document request
     this._docRequest.resume();
   }
 };
 
 //:::::::::::::::::::::::: CLASSES ::::::::::::::::::::::::::// 
 
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6349,17 +6349,18 @@ static nsIView* GetDisplayRootFor(nsIVie
     if (displayRoot->GetFloating() && !displayParent->GetFloating())
       return displayRoot;
     displayRoot = displayParent;
   }
   return nsnull;
 }
 
 static already_AddRefed<LayerManager>
-LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent)
+LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
+                                bool* aAllowRetaining)
 {
   nsIDocument* doc = aDoc;
   nsIDocument* displayDoc = doc->GetDisplayDocument();
   if (displayDoc) {
     doc = displayDoc;
   }
 
   nsIPresShell* shell = doc->GetShell();
@@ -6389,37 +6390,38 @@ LayerManagerForDocumentInternal(nsIDocum
       if (NS_SUCCEEDED(VM->GetRootView(rootView)) && rootView) {
         nsIView* displayRoot = GetDisplayRootFor(rootView);
         if (displayRoot) {
           nsIWidget* widget = displayRoot->GetNearestWidget(nsnull);
           if (widget) {
             nsRefPtr<LayerManager> manager =
               static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget)->
                 GetLayerManager(aRequirePersistent ? nsIWidget_MOZILLA_2_0_BRANCH::LAYER_MANAGER_PERSISTENT : 
-                                                     nsIWidget_MOZILLA_2_0_BRANCH::LAYER_MANAGER_CURRENT);
+                                                     nsIWidget_MOZILLA_2_0_BRANCH::LAYER_MANAGER_CURRENT,
+                                aAllowRetaining);
             return manager.forget();
           }
         }
       }
     }
   }
 
   return nsnull;
 }
 
 already_AddRefed<LayerManager>
-nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc)
-{
-  return LayerManagerForDocumentInternal(aDoc, false);
+nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
+{
+  return LayerManagerForDocumentInternal(aDoc, false, aAllowRetaining);
 }
 
 already_AddRefed<LayerManager>
-nsContentUtils::PersistentLayerManagerForDocument(nsIDocument *aDoc)
-{
-  return LayerManagerForDocumentInternal(aDoc, true);
+nsContentUtils::PersistentLayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
+{
+  return LayerManagerForDocumentInternal(aDoc, true, aAllowRetaining);
 }
 
 bool
 nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal)
 {
   if (IsSystemPrincipal(aPrincipal)) {
     return true;
   }
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -246,18 +246,17 @@ nsCrossSiteListenerProxy::CheckRequestAp
     NS_LITERAL_CSTRING("Access-Control-Allow-Origin"), allowedOriginHeader);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mWithCredentials || !allowedOriginHeader.EqualsLiteral("*")) {
     nsCAutoString origin;
     rv = nsContentUtils::GetASCIIOrigin(mRequestingPrincipal, origin);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    if (!allowedOriginHeader.Equals(origin) ||
-        origin.EqualsLiteral("null")) {
+    if (!allowedOriginHeader.Equals(origin)) {
       return NS_ERROR_DOM_BAD_URI;
     }
   }
 
   // Check Access-Control-Allow-Credentials header
   if (mWithCredentials) {
     nsCAutoString allowCredentialsHeader;
     rv = http->GetResponseHeader(
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -47,16 +47,17 @@
 #include "nsICharsetDetector.h"
 #include "nsICharsetConverterManager.h"
 #include "nsIConverterInputStream.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsIFile.h"
 #include "nsIFileStreams.h"
 #include "nsIInputStream.h"
+#include "nsIIPCSerializable.h"
 #include "nsIMIMEService.h"
 #include "nsIPlatformCharset.h"
 #include "nsISeekableStream.h"
 #include "nsIUnicharInputStream.h"
 #include "nsIUnicodeDecoder.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsIUUIDGenerator.h"
@@ -70,17 +71,18 @@
 using namespace mozilla;
 
 // XXXkhuey the input stream that we pass out of a DOMFile
 // can outlive the actual DOMFile object.  Thus, we must
 // ensure that the buffer underlying the stream we get
 // from NS_NewByteInputStream is held alive as long as the
 // stream is.  We do that by passing back this class instead.
 class DataOwnerAdapter : public nsIInputStream,
-                         public nsISeekableStream {
+                         public nsISeekableStream
+{
   typedef nsDOMMemoryFile::DataOwner DataOwner;
 public:
   static nsresult Create(DataOwner* aDataOwner,
                          PRUint32 aStart,
                          PRUint32 aLength,
                          nsIInputStream** _retval);
 
   NS_DECL_ISUPPORTS
@@ -98,17 +100,19 @@ private:
     NS_ASSERTION(mSeekableStream, "Somebody gave us the wrong stream!");
   }
 
   nsRefPtr<DataOwner> mDataOwner;
   nsCOMPtr<nsIInputStream> mStream;
   nsCOMPtr<nsISeekableStream> mSeekableStream;
 };
 
-NS_IMPL_THREADSAFE_ISUPPORTS2(DataOwnerAdapter, nsIInputStream, nsISeekableStream)
+NS_IMPL_THREADSAFE_ISUPPORTS2(DataOwnerAdapter,
+                              nsIInputStream,
+                              nsISeekableStream)
 
 nsresult DataOwnerAdapter::Create(DataOwner* aDataOwner,
                                   PRUint32 aStart,
                                   PRUint32 aLength,
                                   nsIInputStream** _retval)
 {
   nsresult rv;
   NS_ASSERTION(aDataOwner, "Uh ...");
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -884,16 +884,17 @@ TransferZoomLevels(nsIDocument* aFromDoc
   if (!toShell)
     return;
 
   nsPresContext* toCtxt = toShell->GetPresContext();
   if (!toCtxt)
     return;
 
   toCtxt->SetFullZoom(fromCtxt->GetFullZoom());
+  toCtxt->SetMinFontSize(fromCtxt->MinFontSize());
   toCtxt->SetTextZoom(fromCtxt->TextZoom());
 }
 
 void
 TransferShowingState(nsIDocument* aFromDoc, nsIDocument* aToDoc)
 {
   NS_ABORT_IF_FALSE(aFromDoc && aToDoc,
                     "transferring showing state from/to null doc");
@@ -4098,16 +4099,20 @@ nsDocument::RemoveIDTargetObserver(nsIAt
 
 NS_IMETHODIMP
 nsDocument::MozSetImageElement(const nsAString& aImageElementId,
                                nsIDOMElement* aImageElement)
 {
   if (aImageElementId.IsEmpty())
     return NS_OK;
 
+  // Hold a script blocker while calling SetImageElement since that can call
+  // out to id-observers
+  nsAutoScriptBlocker scriptBlocker;
+
   nsCOMPtr<nsIContent> content = do_QueryInterface(aImageElement);
   nsIdentifierMapEntry *entry = mIdentifierMap.PutEntry(aImageElementId);
   if (entry) {
     entry->SetImageElement(content ? content->AsElement() : nsnull);
     if (entry->IsEmpty()) {
       mIdentifierMap.RemoveEntry(aImageElementId);
     }
   }
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2231,16 +2231,18 @@ nsGenericElement::SetPrefix(const nsAStr
     NS_ENSURE_TRUE(prefix, NS_ERROR_OUT_OF_MEMORY);
   }
 
   if (!nsContentUtils::IsValidNodeName(mNodeInfo->NameAtom(), prefix,
                                        mNodeInfo->NamespaceID())) {
     return NS_ERROR_DOM_NAMESPACE_ERR;
   }
 
+  nsAutoScriptBlocker scriptBlocker;
+
   nsCOMPtr<nsINodeInfo> newNodeInfo;
   nsresult rv = nsContentUtils::PrefixChanged(mNodeInfo, prefix,
                                               getter_AddRefs(newNodeInfo));
   NS_ENSURE_SUCCESS(rv, rv);
 
   mNodeInfo.swap(newNodeInfo);
   NodeInfoChanged(newNodeInfo);
 
@@ -4652,16 +4654,20 @@ nsGenericElement::SetAttr(PRInt32 aNames
 
   nsresult rv = BeforeSetAttr(aNamespaceID, aName, &aValue, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aNotify) {
     nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType);
   }
 
+  // Hold a script blocker while calling ParseAttribute since that can call
+  // out to id-observers
+  nsAutoRemovableScriptBlocker scriptBlocker;
+
   nsAttrValue attrValue;
   if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
     attrValue.SetTo(aValue);
   }
 
   return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
                           attrValue, modType, hasListeners, aNotify,
                           &aValue);
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -1744,16 +1744,17 @@ GK_ATOM(Unicode, "x-unicode")
 // Names for editor transactions
 GK_ATOM(TypingTxnName, "Typing")
 GK_ATOM(IMETxnName, "IME")
 GK_ATOM(DeleteTxnName, "Deleting")
 
 // IPC stuff
 GK_ATOM(Remote, "remote")
 GK_ATOM(RemoteId, "_remote_id")
+GK_ATOM(DisplayPort, "_displayport")
 
 // Names for system metrics
 GK_ATOM(scrollbar_start_backward, "scrollbar-start-backward")
 GK_ATOM(scrollbar_start_forward, "scrollbar-start-forward")
 GK_ATOM(scrollbar_end_backward, "scrollbar-end-backward")
 GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward")
 GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional")
 GK_ATOM(images_in_menus, "images-in-menus")
--- a/content/base/src/nsStyledElement.cpp
+++ b/content/base/src/nsStyledElement.cpp
@@ -126,16 +126,17 @@ nsStyledElement::ParseAttribute(PRInt32 
   return nsStyledElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
                                              aResult);
 }
 
 nsresult
 nsStyledElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                            PRBool aNotify)
 {
+  nsAutoRemovableScriptBlocker scriptBlocker;
   if (aAttribute == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) {
     // Have to do this before clearing flag. See RemoveFromIdTable
     RemoveFromIdTable();
   }
 
   return nsGenericElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
 }
 
--- a/content/base/test/file_x-frame-options_page.sjs
+++ b/content/base/test/file_x-frame-options_page.sjs
@@ -7,17 +7,16 @@ function handleRequest(request, response
     query[name] = unescape(value);
   });
 
   response.setHeader("Cache-Control", "no-cache", false);
   response.setHeader("Content-Type", "text/html", false);
 
   // X-Frame-Options header value
   if (query['xfo'] == "deny") {
-    for (var i = 0 ; i < 0x7fffff ; i++) { }
     response.setHeader("X-Frame-Options", "DENY", false);
   }
   else if (query['xfo'] == "sameorigin") {
     response.setHeader("X-Frame-Options", "SAMEORIGIN", false);
   }
 
   // from the test harness we'll be checking for the presence of this element
   // to test if the page loaded
--- a/content/base/test/script-1_bug597345.sjs
+++ b/content/base/test/script-1_bug597345.sjs
@@ -1,13 +1,16 @@
+// timer has to be alive so it can't be eaten by the GC.
+var timer;
+
 function handleRequest(request, response)
 {
   response.setHeader("Cache-Control", "no-cache", false);
   response.setHeader("Content-Type", "text/javascript", false);
   // The "stray" open comment at the end of the write is important!
   response.write("document.write(\"<script charset='utf-8' src='script-2_bug597345.js'></script><!--\")");
   response.processAsync();
-  var timer = Components.classes["@mozilla.org/timer;1"]
+  timer = Components.classes["@mozilla.org/timer;1"]
     .createInstance(Components.interfaces.nsITimer);
   timer.initWithCallback(function() {
       response.finish();
     }, 200, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
 }
--- a/content/base/test/script_bug602838.sjs
+++ b/content/base/test/script_bug602838.sjs
@@ -1,12 +1,15 @@
+// timer needs to be global so it can't be eaten by GC.
+var timer;
+
 function handleRequest(request, response)
 {
   response.setHeader("Cache-Control", "no-cache", false);
   response.setHeader("Content-Type", "text/javascript", false);
   response.write("ok(asyncRan, 'Async script should have run first.'); firstRan = true;");
   response.processAsync();
-  var timer = Components.classes["@mozilla.org/timer;1"]
-    .createInstance(Components.interfaces.nsITimer);
+  timer = Components.classes["@mozilla.org/timer;1"]
+                    .createInstance(Components.interfaces.nsITimer);
   timer.initWithCallback(function() {
       response.finish();
     }, 200, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
 }
--- a/content/base/test/test_CrossSiteXHR_origin.html
+++ b/content/base/test/test_CrossSiteXHR_origin.html
@@ -105,19 +105,18 @@ function runTest() {
       origin.substr(0, 5) == "https" ? origin.replace("https", "http")
                                      : origin.replace("http", "https"),
       origin.replace("://", "://www."),
       origin.replace("://", ":// "),
       origin.replace(/\/[^.]+\./, "/"),
     ];
 
     if (isNullOrigin) {
-      passTests = ["*", "\t \t* \t "];
+      passTests = ["*", "\t \t* \t ", "null"];
       failTests = failTests.filter(function(v) { return v != origin });
-      failTests.push("null");
     }
     
     for each(allowOrigin in passTests) {
       req = {
         url: baseURL +
              "allowOrigin=" + escape(allowOrigin) +
              "&origin=" + escape(origin),
         method: "GET",
--- a/content/base/test/test_bug421602.html
+++ b/content/base/test/test_bug421602.html
@@ -17,52 +17,45 @@ https://bugzilla.mozilla.org/show_bug.cg
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 /** Test for Bug 421602 **/
 SimpleTest.waitForExplicitFinish();
 
 var img1loaded = false;
-var img2loaded = false;
 var img1errored = false;
-var img2errored = false;
 
 function gc() {
   netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
   window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
         .getInterface(Components.interfaces.nsIDOMWindowUtils)
         .garbageCollect();
 }
 
 // Our test image
 function loadTestImage() {
   var img1 = new Image();
-  img1.onload = function() { img1loaded = true; }
+  img1.onload = function() {
+    img1loaded = true;
+    finishTest();
+  }
   img1.onerror = function() {
-    is(img2errored, false, "Image 2 should not error before image 1");
     img1errored = true;
+    finishTest();
   }
   img1.src = window.location.href + "?image1=true";
 }
 loadTestImage();
 
 // Probably overkill to gc() more than once, but let's be safe
 gc(); gc(); gc();
 
-// And now our "wrap the test up" image.
-var img2 = new Image();
-img2.onload = function() { img2loaded = true; }
-img2.onerror = function() { img2errored = true; finishTest(); }
-img2.src = window.location.href + "?image2=true";
-
 function finishTest() {
   is(img1errored, true, "Image 1 should error");
-  is(img2errored, true, "Image 2 should error");
   is(img1loaded, false, "Image 1 should not load");
-  is(img2loaded, false, "Image 2 should not load");
   SimpleTest.finish();
 }
 </script>
 </pre>
 </body>
 </html>
 
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -56,16 +56,18 @@
 #include "gfxContext.h"
 #include "gfxPattern.h"
 #include "gfxUtils.h"
 
 #include "CanvasUtils.h"
 
 #include "GLContextProvider.h"
 
+#include "gfxCrashReporterUtils.h"
+
 #ifdef MOZ_SVG
 #include "nsSVGEffects.h"
 #endif
 
 #include "prenv.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
@@ -344,16 +346,18 @@ WebGLContext::SetContextOptions(nsIPrope
 
     mOptions = newOpts;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::SetDimensions(PRInt32 width, PRInt32 height)
 {
+    ScopedGfxFeatureReporter reporter("WebGL");
+
     if (mWidth == width && mHeight == height)
         return NS_OK;
 
     // If we already have a gl context, then we just need to resize
     // FB0.
     if (gl &&
         gl->ResizeOffscreen(gfxIntSize(width, height)))
     {
@@ -522,16 +526,17 @@ WebGLContext::SetDimensions(PRInt32 widt
     // we'll end up displaying random memory
     gl->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, gl->GetOffscreenFBO());
     gl->fViewport(0, 0, mWidth, mHeight);
     gl->fClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     gl->fClearDepth(1.0f);
     gl->fClearStencil(0);
     gl->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT | LOCAL_GL_STENCIL_BUFFER_BIT);
 
+    reporter.SetSuccessful();
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::Render(gfxContext *ctx, gfxPattern::GraphicsFilter f)
 {
     if (!gl)
         return NS_OK;
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -373,19 +373,19 @@ PRBool WebGLContext::ValidateTexFormatAn
                 ErrorInvalidEnum("%s: invalid type 0x%x", info, type);
                 return PR_FALSE;
         }
     }
 }
 
 PRBool WebGLContext::ValidateAttribIndex(WebGLuint index, const char *info)
 {
-    if (index > mAttribBuffers.Length()) {
+    if (index >= mAttribBuffers.Length()) {
         if (index == WebGLuint(-1)) {
-             ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLication() call, "
+             ErrorInvalidValue("%s: index -1 is invalid. That probably comes from a getAttribLocation() call, "
                                "where this return value -1 means that the passed name didn't correspond to an active attribute in "
                                "the specified program.", info);
         } else {
              ErrorInvalidValue("%s: index %d is out of range", info, index);
         }
         return PR_FALSE;
     } else {
         return PR_TRUE;
--- a/content/canvas/test/webgl/00_test_list.txt
+++ b/content/canvas/test/webgl/00_test_list.txt
@@ -1,5 +1,5 @@
-// files that end in .txt list other tests
-// other lines are assumed to be .html files
-
-conformance/00_test_list.txt
-
+// files that end in .txt list other tests
+// other lines are assumed to be .html files
+
+conformance/00_test_list.txt
+
--- a/content/canvas/test/webgl/README.mozilla
+++ b/content/canvas/test/webgl/README.mozilla
@@ -1,24 +1,13 @@
-This is a local copy of the WebGL conformance suite.
-
-  SVN revision: 13113
+This is a local copy of the WebGL conformance suite, version 1.0.0.
 
 The canonical location for this testsuite is:
 
-  https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/tests/
+  https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/conformance-suites/1.0.0/webgl-conformance-tests.html
 
 All files and directories in this directory, with the exceptions listed below, come from
 upstream and should not be modified without corresponding upstream fixes and/or a
-patch file in the "patches" directory. The exceptions (the Mozilla-specific files) are:
+patch file in this directory. The exceptions (the Mozilla-specific files) are:
  * README.mozilla (this file)
- * failing_tests.txt
+ * failing_tests_*.txt
  * Makefile.in
- * the "mozilla" directory, if any
- * the "patches" directory, if any
-
-Moreover, the files named 00_test_list.txt are temporarily renamed to 00_testFIXME_list.txt to work around bug 584611, quote:
-> In mochitest, we tell people that mochitests should start with test_.  The
-> actual truth is that we match anything with a test_ in it.
-
-The "mozilla" directory contains integration of this test suite into Mozilla's
-testing system.
-
+ * *.patch files, if any
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/README.txt
@@ -0,0 +1,28 @@
+Welcome to the WebGL Conformance Test Suite
+===========================================
+
+This is the initial release of the WebGL conformance test suite.
+
+NOTE TO USERS: Unless you are a WebGL implementor, there is no need to submit
+a conformance result using this process.  Should you discover bugs in your
+browser's WebGL implementation, either via this test suite or otherwise,
+please report them to your browser vendor's bug tracking system.
+
+FOR WEBGL IMPLEMENTORS: Please follow the isntructions below to create
+a formal conformance submission.'
+
+1) Open webgl-conformance-tests.html in your target browser
+
+2) Press the "run tests" button
+
+3) At the end of the run, press "display text summary"
+
+4) Verify that the User Agent and WebGL renderer strings identify your browser and target correctly.
+
+5) Copy the contents of the text summary (starting with "WebGL Conformance Test Results") and send via email to
+   --- NEED ADDRESS HERE --- @khronos.org
+
+
+- Version 1.0.0
+- February 24, 2011
+
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/00_test_list.txt
+++ b/content/canvas/test/webgl/conformance/00_test_list.txt
@@ -1,17 +1,20 @@
 array-buffer-crash.html
 array-buffer-view-crash.html
 array-unit-tests.html
 bad-arguments-test.html
 buffer-bind-test.html
 buffer-data-array-buffer.html
+buffer-preserve-test.html
 canvas-test.html
 constants.html
 context-attributes-alpha-depth-stencil-antialias.html
+context-lost-restored.html
+context-lost.html
 context-type-test.html
 copy-tex-image-and-sub-image-2d.html
 draw-arrays-out-of-bounds.html
 draw-elements-out-of-bounds.html
 error-reporting.html
 framebuffer-object-attachment.html
 framebuffer-test.html
 get-active-test.html
@@ -19,66 +22,78 @@ gl-bind-attrib-location-test.html
 gl-clear.html
 gl-drawelements.html
 gl-enable-enum-test.html
 gl-enable-vertex-attrib.html
 gl-enum-tests.html
 gl-get-active-attribute.html
 gl-get-active-uniform.html
 gl-get-calls.html
+gl-getshadersource.html
 gl-getstring.html
+gl-min-attribs.html
+# gl-min-textures.html
+gl-min-uniforms.html
 gl-object-get-calls.html
 gl-pixelstorei.html
 gl-scissor-test.html
 gl-shader-test.html
 gl-teximage.html
 gl-uniform-arrays.html
 gl-uniform-bool.html
 gl-uniformmatrix4fv.html
 gl-unknown-uniform.html
 gl-vertex-attrib.html
+gl-vertex-attrib-zero-issues.html
 gl-vertexattribpointer.html
-glsl-2types-of-textures-on-same-unit.html
+#glsl-2types-of-textures-on-same-unit.html
 glsl-conformance.html
 incorrect-context-object-behaviour.html
 index-validation-copies-indices.html
 index-validation-crash-with-buffer-sub-data.html
 index-validation-verifies-too-many-indices.html
 index-validation-with-resized-buffer.html
 index-validation.html
+instanceof-test.html
 invalid-UTF-16.html
 invalid-passed-params.html
 is-object.html
 methods.html
 more-than-65536-points.html
 null-object-behaviour.html
 null-uniform-location.html
 object-deletion-behaviour.html
+oes-standard-derivatives.html
+oes-texture-float.html
+oes-vertex-array-object.html
 origin-clean-conformance.html
 point-size.html
 program-test.html
 read-pixels-pack-alignment.html
 read-pixels-test.html
 renderbuffer-initialization.html
 resource-sharing-test.html
 tex-image-and-sub-image-2d-with-array-buffer-view.html
 tex-image-and-sub-image-2d-with-image-data.html
 tex-image-and-sub-image-2d-with-image.html
 tex-image-and-sub-image-2d-with-video.html
 tex-image-and-uniform-binding-bugs.html
 tex-image-with-format-and-type.html
 tex-image-with-invalid-data.html
 tex-input-validation.html
+tex-sub-image-2d-bad-args.html
 tex-sub-image-2d.html
 texparameter-test.html
 texture-active-bind-2.html
 texture-active-bind.html
 texture-complete.html
 texture-formats-test.html
 texture-npot.html
 texture-transparent-pixels-initialized.html
 triangle.html
 type-conversion-test.html
 uniform-location.html
 uniform-samplers-test.html
 uninitialized-test.html
 viewport-unchanged-upon-resize.html
 webgl-specific.html
+more/00_test_list.txt
+
--- a/content/canvas/test/webgl/conformance/array-unit-tests.html
+++ b/content/canvas/test/webgl/conformance/array-unit-tests.html
@@ -182,16 +182,105 @@ function testConstructWithTypedArrayOfSi
     }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
 //
+// Test cases for integral types.
+// Some JavaScript engines need separate copies of this code in order
+// to exercise all of their optimized code paths.
+//
+
+function testIntegralArrayTruncationBehavior(type, name, unsigned) {
+  running('test integral array truncation behavior for ' + name);
+
+  var sourceData;
+  var expectedResults;
+
+  if (unsigned) {
+    sourceData = [0.6, 10.6];
+    expectedResults = [0, 10];
+  } else {
+    sourceData = [0.6, 10.6, -0.6, -10.6];
+    expectedResults = [0, 10, 0, -10];
+  }
+
+  var numIterations = 10;
+  var array = new type(numIterations);
+
+  // The code block in each of the case statements below is identical, but some
+  // JavaScript engines need separate copies in order to exercise all of
+  // their optimized code paths.
+
+  try {
+    switch (type) {
+    case Int8Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Int16Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Int32Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Uint8Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Uint16Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    case Uint32Array:
+      for (var ii = 0; ii < sourceData.length; ++ii) {
+        for (var jj = 0; jj < numIterations; ++jj) {
+          array[jj] = sourceData[ii];
+          assertEq('Storing ' + sourceData[ii], expectedResults[ii], array[jj]);
+        }
+      }
+      break;
+    default:
+      fail("Unhandled type");
+      break;
+    }
+
+    pass();
+  } catch (e) {
+    fail(e);
+  }
+}
+
+
+//
 // Test cases for both signed and unsigned types
 //
 
 function testGetWithOutOfRangeIndices(type, name) {
     debug('Testing ' + name + ' GetWithOutOfRangeIndices');
     // See below for declaration of this global variable
     array = new type([2, 3]);
     shouldBeUndefined("array[2]");
@@ -309,18 +398,18 @@ function negativeTestSetFromArray(type, 
     } catch (e) {
     }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
-function testSlice(type, name) {
-  running('test ' + name + ' Slice');
+function testSubarray(type, name) {
+  running('test ' + name + ' Subarray');
   try {
     var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
     var subarray = array.subarray(0, 5);
     assertEq('subarray.length', 5, subarray.length);
     for (var i = 0; i < 5; i++) {
       assertEq('Element ' + i, i, subarray[i]);
     }
     subarray = array.subarray(4, 10);
@@ -329,18 +418,18 @@ function testSlice(type, name) {
       assertEq('Element ' + i, 4 + i, subarray[i]);
     }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
-function negativeTestSlice(type, name) {
-  running('negativeTest ' + name + ' Slice');
+function negativeTestSubarray(type, name) {
+  running('negativeTest ' + name + ' Subarray');
   try {
     var array = new type([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
     subarray = array.subarray(5, 11);
     if (subarray.length != 5) {
       fail();
       return;
     }
     subarray = array.subarray(10, 10);
@@ -349,27 +438,41 @@ function negativeTestSlice(type, name) {
       return;
     }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
-function testBoundaryConditions(type, name, lowValue, expectedLowValue, highValue, expectedHighValue) {
-  running('test ' + name + ' BoundaryConditions(' +
-          lowValue + ', ' + expectedLowValue + ', ' +
-          highValue + ', ' + expectedHighValue + ')');
+function testSetBoundaryConditions(type, name, testValues, expectedValues) {
+  running('test ' + name + ' SetBoundaryConditions');
   try {
     var array = new type(1);
     assertEq('Array length', 1, array.length);
-    array[0] = lowValue;
-    assertEq('Element 0', expectedLowValue, array[0]);
-    array[0] = highValue;
-    assertEq('Element 0', expectedHighValue, array[0]);
+    for (var ii = 0; ii < testValues.length; ++ii) {
+      for (var jj = 0; jj < 10; ++jj) {
+        array[0] = testValues[ii];
+        assertEq('Element 0', expectedValues[ii], array[0]);
+      }
+    }
+    pass();
+  } catch (e) {
+    fail(e);
+  }
+}
+
+function testConstructionBoundaryConditions(type, name, testValues, expectedValues) {
+  running('test ' + name + ' ConstructionBoundaryConditions');
+  try {
+    var array = new type(testValues);
+    assertEq('Array length', testValues.length, array.length);
+    for (var ii = 0; ii < testValues.length; ++ii) {
+      assertEq('Element ' + ii, expectedValues[ii], array[ii]);
+    }
     pass();
   } catch (e) {
     fail(e);
   }
 }
 
 function testConstructionWithNullBuffer(type, name) {
     var array;
@@ -471,18 +574,18 @@ function testConstructionWithBothArrayBu
         testFailed("Array lengths DID NOT MATCH with explicit and implicit creation of ArrayBuffer");
     }
 }
 
 // These need to be global for shouldBe to see them
 var array;
 var typeSize;
 
-function testSlicingWithOutOfRangeValues(type, name, sz) {
-    debug("Testing slicing of " + name);
+function testSubarrayWithOutOfRangeValues(type, name, sz) {
+    debug("Testing subarray of " + name);
     try {
         var buffer = new ArrayBuffer(32);
         array = new type(buffer);
         typeSize = sz;
         shouldBe("array.length", "32 / typeSize");
         try {
             shouldBe("array.subarray(4, 0x3FFFFFFF).length", "(32 / typeSize) - 4");
             shouldBe("array.subarray(4, -2147483648).length", "0");
@@ -492,37 +595,37 @@ function testSlicingWithOutOfRangeValues
                 // Full byte offset is +1 larger than the maximum unsigned long int.
                 // Make sure subarray() still handles it correctly.  Otherwise overflow would happen and
                 // offset would be 0, and array.length array.length would incorrectly be 1.
                 var start = 4294967296 / sz - 2;
                 array = array.subarray(start, start + 1);
                 shouldBe("array.length", "0");
             }
         } catch (e) {
-            testFailed("Slicing of " + name + " threw exception");
+            testFailed("Subarray of " + name + " threw exception");
         }
     } catch (e) {
         testFailed("Exception: " + e);
     }
 }
 
-function testSlicingWithDefaultValues(type, name, sz) {
-    debug("Testing slicing with default inputs of " + name);
+function testSubarrayWithDefaultValues(type, name, sz) {
+    debug("Testing subarray with default inputs of " + name);
     try {
         var buffer = new ArrayBuffer(32);
         array = new type(buffer);
         typeSize = sz;
         shouldBe("array.length", "32 / typeSize");
         try {
             shouldBe("array.subarray(0).length", "(32 / typeSize)");
             shouldBe("array.subarray(2).length", "(32 / typeSize) - 2");
             shouldBe("array.subarray(-2).length", "2");
             shouldBe("array.subarray(-2147483648).length", "(32 / typeSize)");
         } catch (e) {
-            testFailed("Slicing of " + name + " threw exception");
+            testFailed("Subarray of " + name + " threw exception");
         }
     } catch (e) {
         testFailed("Exception: " + e);
     }
 }
 
 function testSettingFromArrayWithOutOfRangeOffset(type, name) {
     var webglArray = new type(32);
@@ -579,76 +682,151 @@ function negativeTestGetAndSetMethods(ty
     var output = "array.set(0, 1) ";
     if (exceptionThrown) {
         testPassed(output + "threw exception.");
     } else {
         testFailed(output + "did not throw exception.");
     }
 }
 
+function testNaNConversion(type, name) {
+  running('test storing NaN in ' + name);
+
+  var array = new type([1, 1]);
+  var results = [];
+
+  // The code block in each of the case statements below is identical, but some
+  // JavaScript engines need separate copies in order to exercise all of
+  // their optimized code paths.
+  try {
+    switch (type) {
+    case Float32Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Int8Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Int16Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Int32Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Uint8Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Uint16Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    case Uint32Array:
+      for (var i = 0; i < array.length; ++i) {
+        array[i] = NaN;
+        results[i] = array[i];
+      }
+      break;
+    default:
+      fail("Unhandled type");
+      break;
+    }
+
+    // Some types preserve NaN values; all other types convert NaN to zero.
+    if (type === Float32Array) {
+      assert('initial NaN preserved', isNaN(new type([NaN])[0]));
+      for (var i = 0; i < array.length; ++i)
+        assert('NaN preserved via setter', isNaN(results[i]));
+    } else {
+      assertEq('initial NaN converted to zero', 0, new type([NaN])[0]);
+      for (var i = 0; i < array.length; ++i)
+        assertEq('NaN converted to zero by setter', 0, results[i]);
+    }
+
+    pass();
+  } catch (e) {
+      fail(e);
+  }
+}
+
 //
 // Test driver
 //
 
 function runTests() {
   allPassed = true;
 
   // The "name" attribute is a concession to browsers which don't
   // implement the "name" property on function objects
   var testCases =
     [ {name: "Float32Array",
        unsigned: false,
+       integral: false,
        elementSizeInBytes: 4,
-       low: -500.5,
-       expectedLow: -500.5,
-       high: 500.5,
-       expectedHigh: 500.5},
+       testValues:     [ -500.5, 500.5 ],
+       expectedValues: [ -500.5, 500.5 ]
+      },
       {name: "Int8Array",
        unsigned: false,
+       integral: true,
        elementSizeInBytes: 1,
-       low: -128,
-       expectedLow: -128,
-       high: 127,
-       expectedHigh: 127},
+       testValues:     [ -128, 127, -129,  128 ],
+       expectedValues: [ -128, 127,  127, -128 ]
+      },
       {name: "Int16Array",
        unsigned: false,
+       integral: true,
        elementSizeInBytes: 2,
-       low: -32768,
-       expectedLow: -32768,
-       high: 32767,
-       expectedHigh: 32767},
+       testValues:     [ -32768, 32767, -32769,  32768 ],
+       expectedValues: [ -32768, 32767,  32767, -32768 ]
+      },
       {name: "Int32Array",
        unsigned: false,
+       integral: true,
        elementSizeInBytes: 4,
-       low: -2147483648,
-       expectedLow: -2147483648,
-       high: 2147483647,
-       expectedHigh: 2147483647},
+       testValues:     [ -2147483648, 2147483647, -2147483649,  2147483648 ],
+       expectedValues: [ -2147483648, 2147483647,  2147483647, -2147483648 ]
+      },
       {name: "Uint8Array",
        unsigned: true,
+       integral: true,
        elementSizeInBytes: 1,
-       low: 0,
-       expectedLow: 0,
-       high: 255,
-       expectedHigh: 255},
+       testValues:     [ 0, 255,  -1, 256 ],
+       expectedValues: [ 0, 255, 255,   0 ]
+      },
       {name: "Uint16Array",
        unsigned: true,
+       integral: true,
        elementSizeInBytes: 2,
-       low: 0,
-       expectedLow: 0,
-       high: 65535,
-       expectedHigh: 65535},
+       testValues:     [ 0, 65535,    -1, 65536 ],
+       expectedValues: [ 0, 65535, 65535,     0 ]
+      },
       {name: "Uint32Array",
        unsigned: true,
+       integral: true,
        elementSizeInBytes: 4,
-       low: 0,
-       expectedLow: 0,
-       high: 4294967295,
-       expectedHigh: 4294967295} ];
-
+       testValues:     [ 0, 4294967295,         -1, 4294967296 ],
+       expectedValues: [ 0, 4294967295, 4294967295,          0 ]
+      }
+    ];
   for (var i = 0; i < testCases.length; i++) {
     var testCase = testCases[i];
     running(testCase.name);
     if (!(testCase.name in window)) {
         fail("does not exist");
         continue;
     }
     var type = window[testCase.name];
@@ -657,43 +835,49 @@ function runTests() {
       testSetAndGet10To1(type, name);
       testConstructWithArrayOfUnsignedValues(type, name);
       testConstructWithTypedArrayOfUnsignedValues(type, name);
     } else {
       testSetAndGetPos10ToNeg10(type, name);
       testConstructWithArrayOfSignedValues(type, name);
       testConstructWithTypedArrayOfSignedValues(type, name);
     }
+    if (testCase.integral) {
+      testIntegralArrayTruncationBehavior(type, name, testCase.unsigned);
+    }
     testGetWithOutOfRangeIndices(type, name);
     testOffsetsAndSizes(type, name, testCase.elementSizeInBytes);
     testSetFromTypedArray(type, name);
     negativeTestSetFromTypedArray(type, name);
     testSetFromArray(type, name);
     negativeTestSetFromArray(type, name);
-    testSlice(type, name);
-    negativeTestSlice(type, name);
-    testBoundaryConditions(type,
-                           name,
-                           testCase.low,
-                           testCase.expectedLow,
-                           testCase.high,
-                           testCase.expectedHigh);
+    testSubarray(type, name);
+    negativeTestSubarray(type, name);
+    testSetBoundaryConditions(type,
+                              name,
+                              testCase.testValues,
+                              testCase.expectedValues);
+    testConstructionBoundaryConditions(type,
+                                       name,
+                                       testCase.testValues,
+                                       testCase.expectedValues);
     testConstructionWithNullBuffer(type, name);
     testConstructionWithOutOfRangeValues(type, name);
     testConstructionWithNegativeOutOfRangeValues(type, name);
     testConstructionWithUnalignedOffset(type, name, testCase.elementSizeInBytes);
     testConstructionWithUnalignedLength(type, name, testCase.elementSizeInBytes);
     testConstructionOfHugeArray(type, name, testCase.elementSizeInBytes);
     testConstructionWithBothArrayBufferAndLength(type, name, testCase.elementSizeInBytes);
-    testSlicingWithOutOfRangeValues(type, name, testCase.elementSizeInBytes);
-    testSlicingWithDefaultValues(type, name, testCase.elementSizeInBytes);
+    testSubarrayWithOutOfRangeValues(type, name, testCase.elementSizeInBytes);
+    testSubarrayWithDefaultValues(type, name, testCase.elementSizeInBytes);
     testSettingFromArrayWithOutOfRangeOffset(type, name);
     testSettingFromFakeArrayWithOutOfRangeLength(type, name);
     testSettingFromTypedArrayWithOutOfRangeOffset(type, name);
     negativeTestGetAndSetMethods(type, name);
+    testNaNConversion(type, name);
   }
 
   printSummary();
 }
 
 runTests();
 successfullyParsed = true;
 
--- a/content/canvas/test/webgl/conformance/buffer-data-array-buffer.html
+++ b/content/canvas/test/webgl/conformance/buffer-data-array-buffer.html
@@ -28,25 +28,34 @@ var buf = gl.createBuffer();
 shouldBeNonNull(buf);
 
 gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
 glErrorShouldBe(gl, gl.INVALID_OPERATION);
 
 gl.bindBuffer(gl.ARRAY_BUFFER, buf);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
+gl.bufferData(gl.ARRAY_BUFFER, -10, gl.STATIC_DRAW);
+glErrorShouldBe(gl, gl.INVALID_VALUE);
+
 // This should not crash, but the selection of the overload is ambiguous per Web IDL.
 gl.bufferData(gl.ARRAY_BUFFER, null, gl.STATIC_DRAW);
 gl.getError();
 
 gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 array = new ArrayBuffer(64);
 
+gl.bufferSubData(gl.ARRAY_BUFFER, -10, array);
+glErrorShouldBe(gl, gl.INVALID_VALUE);
+
+gl.bufferSubData(gl.ARRAY_BUFFER, -10, new Float32Array(8));
+glErrorShouldBe(gl, gl.INVALID_VALUE);
+
 gl.bufferSubData(gl.ARRAY_BUFFER, 10, array);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 gl.bufferSubData(gl.ARRAY_BUFFER, 10, null);
 glErrorShouldBe(gl, gl.NO_ERROR);
 
 successfullyParsed = true;
 </script>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/buffer-preserve-test.html
@@ -0,0 +1,85 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<title>WebGL required buffer clear behaviour test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+<style type="text/css">
+body {
+    height: 3000px;
+}
+</style>
+<script type="text/javascript">
+
+var iter = 0;
+var gl;
+
+var wtu = WebGLTestUtils;
+
+function checkPixel(gl, x, y, c) {
+    var buf = new Uint8Array(4);
+    gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+
+    return buf[0] == c[0] &&
+	buf[1] == c[1] &&
+	buf[2] == c[2] &&
+	buf[3] == c[3];
+}
+
+function timer() {
+    if (iter == 0) {
+	// some random hacky stuff to make sure that we get a compositing step
+	window.scrollBy(0, 10);
+	window.scrollBy(0, -10);
+	iter++;
+
+	setTimeout(timer, 500);
+    } else if (iter == 1) {
+	// scissor was set earlier
+	gl.clearColor(0, 0, 1, 1);
+	gl.clear(gl.COLOR_BUFFER_BIT);
+
+	wtu.checkCanvasRect(gl, 0, 10, 10, 10, [0, 0, 255, 255], "cleared corner should be blue, stencil should be preserved");
+	wtu.checkCanvasRect(gl, 0, 0, 10, 10, [0, 0, 0, 0], "remainder of buffer should be cleared");
+
+	finishTest();
+    }
+}
+
+function go() {
+    description("This test ensures WebGL implementations correctly clear the drawing buffer on composite if preserveDrawingBuffer is false.");
+
+    debug("");
+
+    gl = create3DContext(document.getElementById("c"));
+    if (!gl) {
+	finishTest();
+	return;
+    }
+
+    shouldBeTrue('gl.getContextAttributes().preserveDrawingBuffer == false');
+
+    gl.clearColor(1, 0, 0, 1);
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
+
+    // enable scissor here, before compositing, to make sure it's correctly
+    // ignored and restored
+    gl.scissor(0, 10, 10, 10);
+    gl.enable(gl.SCISSOR_TEST);
+
+    setTimeout(timer, 500);
+}
+
+window.addEventListener("load", go, false);
+
+successfullyParsed = true;
+</script>
+</head>
+<body>
+<div id="description"></div>
+<canvas width="20" height="20" style="border: 1px solid blue;" id="c"></canvas>
+<div id="console"></div>
+</body>
+</html>
\ No newline at end of file
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/canvas-test.html
+++ b/content/canvas/test/webgl/conformance/canvas-test.html
@@ -24,16 +24,17 @@ if (window.initNonKhronosFramework) {
   window.initNonKhronosFramework(true);
 }
 
 description("This test ensures WebGL implementations interact correctly with the canvas tag.");
 
 debug("");
 debug("Canvas.getContext");
 
+var err;
 var canvas = document.getElementById("canvas");
 var canvas2d = document.getElementById("canvas2d");
 var ctx2d = canvas2d.getContext("2d");
 var gl = create3DContext(canvas);
 if (!gl) {
   testFailed("context does not exist");
 } else {
   testPassed("context exists");
@@ -153,48 +154,42 @@ if (!gl) {
       // Check that the clear color does not change.
       // Check that the color mask does not change.
       debug("");
       debug("change the actual size of the canvas and see that the viewport does not change");
       gl.clearColor(0.25, 0.5, 0.75, 1);
       gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
       checkCanvasContentIs(64, 128, 192, 255);
       gl.colorMask(0,0,0,0);
+      glErrorShouldBe(gl, gl.NO_ERROR, "No GL errors before resizing the canvas");
       canvas.width = 400;
       canvas.height = 10;
-
-      var v = gl.getParameter(gl.COLOR_CLEAR_VALUE);
-      assertMsg(isAboutEqual(v[0], 0.25) &&
-                isAboutEqual(v[1], 0.5) &&
-                isAboutEqual(v[2], 0.75) &&
-                isAboutEqual(v[3], 1),
-                "gl.clearColor should not change after canvas resize");
-      v = gl.getParameter(gl.COLOR_WRITEMASK);
-      assertMsg(isAboutEqual(v[0], 0) &&
-                isAboutEqual(v[1], 0) &&
-                isAboutEqual(v[2], 0) &&
-                isAboutEqual(v[3], 0),
-                "gl.colorMask should not change after canvas resize");
-      shouldBe('getViewport()', '"0,0,300,150"');
-      checkCanvasContentIs(0, 0, 0, 0);
+      err = gl.getError();
+      // Some implementations might lost the context when resizing
+      if (err != gl.CONTEXT_LOST_WEBGL) {
+        shouldBe("err", "gl.NO_ERROR");
+        var v = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+        assertMsg(isAboutEqual(v[0], 0.25) &&
+                  isAboutEqual(v[1], 0.5) &&
+                  isAboutEqual(v[2], 0.75) &&
+                  isAboutEqual(v[3], 1),
+                  "gl.clearColor should not change after canvas resize");
+        v = gl.getParameter(gl.COLOR_WRITEMASK);
+        assertMsg(isAboutEqual(v[0], 0) &&
+                  isAboutEqual(v[1], 0) &&
+                  isAboutEqual(v[2], 0) &&
+                  isAboutEqual(v[3], 0),
+                  "gl.colorMask should not change after canvas resize");
+        shouldBe('getViewport()', '"0,0,300,150"');
+        checkCanvasContentIs(0, 0, 0, 0);
+      }
 
       debug("");
-      successfullyParsed = true;
-      var epilogue = document.createElement("script");
-      epilogue.onload = finish;
-      epilogue.src = "../resources/js-test-post.js";
-      document.body.appendChild(epilogue);
+      finishTest();
     }
    }, 1000/30);
 }
-
-function finish() {
-  if (window.nonKhronosFrameworkNotifyDone) {
-    window.nonKhronosFrameworkNotifyDone();
-  }
-}
-
 </script>
 <script>
 </script>
 
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/constants.html
+++ b/content/canvas/test/webgl/conformance/constants.html
@@ -240,19 +240,17 @@ MAX_VERTEX_TEXTURE_IMAGE_UNITS   : 0x8B4
 MAX_TEXTURE_IMAGE_UNITS          : 0x8872,
 MAX_FRAGMENT_UNIFORM_VECTORS     : 0x8DFD,
 SHADER_TYPE                      : 0x8B4F,
 DELETE_STATUS                    : 0x8B80,
 LINK_STATUS                      : 0x8B82,
 VALIDATE_STATUS                  : 0x8B83,
 ATTACHED_SHADERS                 : 0x8B85,
 ACTIVE_UNIFORMS                  : 0x8B86,
-ACTIVE_UNIFORM_MAX_LENGTH        : 0x8B87,
 ACTIVE_ATTRIBUTES                : 0x8B89,
-ACTIVE_ATTRIBUTE_MAX_LENGTH      : 0x8B8A,
 SHADING_LANGUAGE_VERSION         : 0x8B8C,
 CURRENT_PROGRAM                  : 0x8B8D,
     
     /* StencilFunction */
 NEVER                          : 0x0200,
 LESS                           : 0x0201,
 EQUAL                          : 0x0202,
 LEQUAL                         : 0x0203,
@@ -270,17 +268,16 @@ DECR                           : 0x1E03,
 INVERT                         : 0x150A,
 INCR_WRAP                      : 0x8507,
 DECR_WRAP                      : 0x8508,
     
     /* StringName */
 VENDOR                         : 0x1F00,
 RENDERER                       : 0x1F01,
 VERSION                        : 0x1F02,
-EXTENSIONS                     : 0x1F03,
     
     /* TextureMagFilter */
 NEAREST                        : 0x2600,
 LINEAR                         : 0x2601,
     
     /* TextureMinFilter */
     /*      NEAREST */
     /*      LINEAR */
@@ -372,18 +369,16 @@ VERTEX_ATTRIB_ARRAY_SIZE           : 0x8
 VERTEX_ATTRIB_ARRAY_STRIDE         : 0x8624,
 VERTEX_ATTRIB_ARRAY_TYPE           : 0x8625,
 VERTEX_ATTRIB_ARRAY_NORMALIZED     : 0x886A,
 VERTEX_ATTRIB_ARRAY_POINTER        : 0x8645,
 VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : 0x889F,
     
     /* Shader Source */
 COMPILE_STATUS                 : 0x8B81,
-INFO_LOG_LENGTH                : 0x8B84,
-SHADER_SOURCE_LENGTH           : 0x8B88,
 SHADER_COMPILER                : 0x8DFA,
     
     /* Shader Precision-Specified Types */
 LOW_FLOAT                      : 0x8DF0,
 MEDIUM_FLOAT                   : 0x8DF1,
 HIGH_FLOAT                     : 0x8DF2,
 LOW_INT                        : 0x8DF3,
 MEDIUM_INT                     : 0x8DF4,
--- a/content/canvas/test/webgl/conformance/context-attributes-alpha-depth-stencil-antialias.html
+++ b/content/canvas/test/webgl/conformance/context-attributes-alpha-depth-stencil-antialias.html
@@ -207,28 +207,19 @@ function runTest()
     testAlpha(false);
     testDepth(true);
     testDepth(false);
     testStencil(true);
     testStencil(false);
     testAntialias(true);
     testAntialias(false);
 
-    successfullyParsed = true;
-    var epilogue = document.createElement("script");
-    epilogue.onload = finish;
-    epilogue.src = "../resources/js-test-post.js";
-    document.body.appendChild(epilogue);
+    finishTest()
 }
 
-function finish() {
-    if (window.nonKhronosFrameworkNotifyDone) {
-        window.nonKhronosFrameworkNotifyDone();
-    }
-}
 </script>
 </head>
 <body onload="init()">
 <canvas id="alphaOn" width="1px" height="1px"></canvas>
 <canvas id="alphaOff" width="1px" height="1px"></canvas>
 <canvas id="depthOn" width="1px" height="1px"></canvas>
 <canvas id="depthOff" width="1px" height="1px"></canvas>
 <canvas id="stencilOn" width="1px" height="1px"></canvas>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/context-lost-restored.html
@@ -0,0 +1,130 @@
+<html>
+<head>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"></script>
+<script src="resources/webgl-test-utils.js"></script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas;
+var gl;
+var shouldGenerateGLError;
+var extension_name = "WEBKIT_lose_context";
+var extension;
+var bufferObjects;
+var program;
+var texture;
+var texColor = [255, 10, 20, 255];
+
+function init()
+{
+    if (window.initNonKhronosFramework) {
+        window.initNonKhronosFramework(true);
+    }
+
+    description("Tests behavior under a restored context");
+
+    canvas = document.getElementById("canvas");
+    canvas.addEventListener("webglcontextlost", testLostContext, false);
+    canvas.addEventListener("webglcontextrestored", testRestoredContext, false);
+
+    gl = wtu.create3DContext(canvas);
+    shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+    extension = gl.getExtension(extension_name);
+    if (!extension) {
+        debug(extension_name + " extension not found.");
+        finish();
+        return;
+    }
+
+    testOriginalContext();
+    extension.loseContext();
+}
+
+function testRendering()
+{
+    gl.clearColor(0, 0, 0, 255);
+    gl.colorMask(1, 1, 1, 0);
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+    program = wtu.setupSimpleTextureProgram(gl);
+    bufferObjects = wtu.setupUnitQuad(gl);
+    texture = wtu.createColoredTexture(gl, canvas.width, canvas.height, texColor);
+
+    gl.uniform1i(gl.getUniformLocation(program, "tex"), 0);
+    wtu.drawQuad(gl, [0, 0, 0, 255]);
+
+    var compare = texColor.slice(0, 3);
+    wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, compare, "shouldBe " + compare);
+
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+}
+
+function testOriginalContext()
+{
+    debug("Test valid context");
+    shouldBeFalse("gl.isContextLost()");
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+    testRendering();
+    debug("");
+}
+
+function testLostContext()
+{
+    debug("Test lost context");
+    shouldBeTrue("gl.isContextLost()");
+    shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+    debug("");
+}
+
+function testResources(expected)
+{
+    var tests = [
+        "gl.bindTexture(gl.TEXTURE_2D, texture)",
+        "gl.useProgram(program)",
+        "gl.bindBuffer(gl.ARRAY_BUFFER, bufferObjects[0])",
+    ];
+
+    for (var i = 0; i < tests.length; ++i)
+        shouldGenerateGLError(gl, expected, tests[i]);
+}
+
+function testRestoredContext()
+{
+    debug("Test restored context");
+    shouldBeFalse("gl.isContextLost()");
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+
+    // Validate that using old resources fails.
+    testResources(gl.INVALID_OPERATION);
+
+    testRendering();
+
+    // Validate new resources created in testRendering().
+    testResources(gl.NO_ERROR);
+    debug("");
+
+    finish();
+}
+
+function finish() {
+    successfullyParsed = true;
+    var epilogue = document.createElement("script");
+    epilogue.onload = function() {
+        if (window.nonKhronosFrameworkNotifyDone)
+            window.nonKhronosFrameworkNotifyDone();
+    };
+    epilogue.src = "../resources/js-test-post.js";
+    document.body.appendChild(epilogue);
+}
+
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" width="1px" height="1px"></canvas>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/context-lost.html
@@ -0,0 +1,318 @@
+<html>
+<head>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"></script>
+<script src="resources/webgl-test-utils.js"></script>
+<script>
+var wtu;
+var canvas;
+var gl;
+var shouldGenerateGLError;
+var extension_name = "WEBKIT_lose_context";
+var extension;
+
+var buffer;
+var framebuffer;
+var program;
+var renderbuffer;
+var shader;
+var texture;
+var uniformLocation;
+var arrayBuffer;
+var arrayBufferView
+var image;
+var video;
+var canvas2d;
+var ctx2d;
+var imageData;
+var float32array;
+var int32array;
+
+function init()
+{
+    wtu = WebGLTestUtils;
+    canvas = document.getElementById("canvas");
+    gl = wtu.create3DContext(canvas);
+    shouldGenerateGLError = wtu.shouldGenerateGLError;
+
+    description("Tests behavior under a lost context");
+
+    if (window.initNonKhronosFramework) {
+        window.initNonKhronosFramework(true);
+    }
+
+    // call testValidContext() before checking for the extension, because this is where we check
+    // for the isContextLost() method, which we want to do regardless of the extension's presence.
+    testValidContext();
+
+    extension = gl.getExtension(extension_name);
+    if (!extension) {
+        debug(extension_name + " extension not found.");
+        finish();
+        return;
+    }
+
+    canvas.addEventListener("webglcontextlost", testLostContext, false);
+
+    loseContext();
+}
+
+function loseContext()
+{
+    debug("");
+    debug("Lose context");
+    shouldGenerateGLError(gl, gl.NO_ERROR, "extension.loseContext()");
+    debug("");
+}
+
+function testValidContext()
+{
+    debug("Test valid context");
+
+    shouldBeFalse("gl.isContextLost()");
+
+    arrayBuffer = new ArrayBuffer(4);
+    arrayBufferView = new Int8Array(arrayBuffer);
+
+    // Generate resources for testing.
+    buffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+    framebuffer = gl.createFramebuffer();
+    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+    program = wtu.setupSimpleTextureProgram(gl);
+    renderbuffer = gl.createRenderbuffer();
+    gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
+    shader = gl.createShader(gl.VERTEX_SHADER);
+    texture = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+
+    // Test is queries that will later be false
+    shouldGenerateGLError(gl, gl.NO_ERROR, "gl.enable(gl.BLEND)");
+    shouldBeTrue("gl.isBuffer(buffer)");
+    shouldBeTrue("gl.isEnabled(gl.BLEND)");
+    shouldBeTrue("gl.isFramebuffer(framebuffer)");
+    shouldBeTrue("gl.isProgram(program)");
+    shouldBeTrue("gl.isRenderbuffer(renderbuffer)");
+    shouldBeTrue("gl.isShader(shader)");
+    shouldBeTrue("gl.isTexture(texture)");
+}
+
+function testLostContext()
+{
+    debug("Test lost context");
+
+    // Functions with special return values.
+    shouldBeTrue("gl.isContextLost()");
+    shouldBe("gl.getError()", "gl.CONTEXT_LOST_WEBGL");
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+    shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
+    shouldBe("gl.getAttribLocation(program, 'u_modelViewProjMatrix')", "-1");
+    shouldBe("gl.getVertexAttribOffset(0, gl.VERTEX_ATTRIB_ARRAY_POINTER)", "0");
+
+    // Test the extension itself.
+    shouldGenerateGLError(gl, gl.INVALID_OPERATION, "extension.loseContext()");
+
+    image = document.createElement("image");
+    video = document.createElement("video");
+    canvas2d = document.createElement("canvas");
+    ctx2d = canvas2d.getContext("2d");
+    imageData = ctx2d.createImageData(1, 1);
+    float32array = new Float32Array(1);
+    int32array = new Int32Array(1);
+
+    // Functions returning void should return immediately.
+    // This is untestable, but we can at least be sure they cause no errors
+    // and the codepaths are exercised.
+    var voidTests = [
+        "gl.activeTexture(gl.TEXTURE0)",
+        "gl.attachShader(program, shader)",
+        "gl.bindBuffer(gl.ARRAY_BUFFER, buffer)",
+        "gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer)",
+        "gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer)",
+        "gl.bindTexture(gl.TEXTURE_2D, texture)",
+        "gl.blendColor(1.0, 1.0, 1.0, 1.0)",
+        "gl.blendEquation(gl.FUNC_ADD)",
+        "gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD)",
+        "gl.blendFunc(gl.ONE)",
+        "gl.blendFuncSeparate(gl.ONE, gl.ONE)",
+        "gl.bufferData(gl.ARRAY_BUFFER, 0, gl.STATIC_DRAW)",
+        "gl.bufferData(gl.ARRAY_BUFFER, arrayBufferView, gl.STATIC_DRAW)",
+        "gl.bufferData(gl.ARRAY_BUFFER, arrayBuffer, gl.STATIC_DRAW)",
+        "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBufferView)",
+        "gl.bufferSubData(gl.ARRAY_BUFFRE, 0, arrayBuffer)",
+        "gl.clear(gl.COLOR_BUFFER_BIT)",
+        "gl.clearColor(1, 1, 1, 1)",
+        "gl.clearDepth(1)",
+        "gl.clearStencil(0)",
+        "gl.colorMask(1, 1, 1, 1)",
+        "gl.compileShader(shader)",
+        "gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, 0, 0)",
+        "gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 0, 0)",
+        "gl.cullFace(gl.FRONT)",
+        "gl.deleteBuffer(buffer)",
+        "gl.deleteFramebuffer(framebuffer)",
+        "gl.deleteProgram(program)",
+        "gl.deleteRenderbuffer(renderbuffer)",
+        "gl.deleteShader(shader)",
+        "gl.deleteTexture(texture)",
+        "gl.depthFunc(gl.NEVER)",
+        "gl.depthMask(0)",
+        "gl.depthRange(0, 1)",
+        "gl.detachShader(program, shader)",
+        "gl.disable(gl.BLEND)",
+        "gl.disableVertexAttribArray(0)",
+        "gl.drawArrays(gl.POINTS, 0, 0)",
+        "gl.drawElements(gl.POINTS, 0, gl.UNSIGNED_SHORT, 0)",
+        "gl.enable(gl.BLEND)",
+        "gl.enableVertexAttribArray(0)",
+        "gl.finish()",
+        "gl.flush()",
+        "gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, renderbuffer)",
+        "gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0)",
+        "gl.frontFace(gl.CW)",
+        "gl.generateMipmap(gl.TEXTURE_2D)",
+        "gl.hint(gl.GENERATE_MIPMAP_HINT, gl.FASTEST)",
+        "gl.lineWidth(0)",
+        "gl.linkProgram(program)",
+        "gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0)",
+        "gl.polygonOffset(0, 0)",
+        "gl.readPixels(0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
+        "gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0)",
+        "gl.sampleCoverage(0, 0)",
+        "gl.scissor(0, 0, 0, 0)",
+        "gl.shaderSource(shader, '')",
+        "gl.stencilFunc(gl.NEVER, 0, 0)",
+        "gl.stencilFuncSeparate(gl.FRONT, gl.NEVER, 0, 0)",
+        "gl.stencilMask(0)",
+        "gl.stencilMaskSeparate(gl.FRONT, 0)",
+        "gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP)",
+        "gl.stencilOpSeparate(gl.FRONT, gl.KEEP, gl.KEEP, gl.KEEP)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageData)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas)",
+        "gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, video)",
+        "gl.texParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)",
+        "gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, arrayBufferView)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, imageData)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, canvas)",
+        "gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, video)",
+        "gl.uniform1f(uniformLocation, 0)",
+        "gl.uniform1fv(uniformLocation, float32array)",
+        "gl.uniform1fv(uniformLocation, [0])",
+        "gl.uniform1i(uniformLocation, 0)",
+        "gl.uniform1iv(uniformLocation, int32array)",
+        "gl.uniform1iv(uniformLocation, [0])",
+        "gl.uniform2f(uniformLocation, 0, 0)",
+        "gl.uniform2fv(uniformLocation, float32array)",
+        "gl.uniform2fv(uniformLocation, [0, 0])",
+        "gl.uniform2i(uniformLocation, 0, 0)",
+        "gl.uniform2iv(uniformLocation, int32array)",
+        "gl.uniform2iv(uniformLocation, [0, 0])",
+        "gl.uniform3f(uniformLocation, 0, 0, 0)",
+        "gl.uniform3fv(uniformLocation, float32array)",
+        "gl.uniform3fv(uniformLocation, [0, 0, 0])",
+        "gl.uniform3i(uniformLocation, 0, 0, 0)",
+        "gl.uniform3iv(uniformLocation, int32array)",
+        "gl.uniform3iv(uniformLocation, [0, 0, 0])",
+        "gl.uniform4f(uniformLocation, 0, 0, 0, 0)",
+        "gl.uniform4fv(uniformLocation, float32array)",
+        "gl.uniform4fv(uniformLocation, [0, 0, 0, 0])",
+        "gl.uniform4i(uniformLocation, 0, 0, 0, 0)",
+        "gl.uniform4iv(uniformLocation, int32array)",
+        "gl.uniform4iv(uniformLocation, [0, 0, 0, 0])",
+        "gl.uniformMatrix2fv(uniformLocation, false, float32array)",
+        "gl.uniformMatrix2fv(uniformLocation, false, [0, 0, 0, 0])",
+        "gl.uniformMatrix3fv(uniformLocation, false, float32array)",
+        "gl.uniformMatrix3fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0])",
+        "gl.uniformMatrix4fv(uniformLocation, false, float32array)",
+        "gl.uniformMatrix4fv(uniformLocation, false, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])",
+        "gl.useProgram(program)",
+        "gl.validateProgram(program)",
+        "gl.vertexAttrib1f(0, 0)",
+        "gl.vertexAttrib1fv(0, float32array)",
+        "gl.vertexAttrib1fv(0, [0])",
+        "gl.vertexAttrib2f(0, 0, 0)",
+        "gl.vertexAttrib2fv(0, float32array)",
+        "gl.vertexAttrib2fv(0, [0, 0])",
+        "gl.vertexAttrib3f(0, 0, 0, 0)",
+        "gl.vertexAttrib3fv(0, float32array)",
+        "gl.vertexAttrib3fv(0, [0, 0, 0])",
+        "gl.vertexAttrib4f(0, 0, 0, 0, 0)",
+        "gl.vertexAttrib4fv(0, float32array)",
+        "gl.vertexAttrib4fv(0, [0, 0, 0, 0])",
+        "gl.vertexAttribPointer(0, 0, gl.FLOAT, false, 0, 0)",
+        "gl.viewport(0, 0, 0, 0)",
+    ];
+    for (var i = 0; i < voidTests.length; ++i) {
+        shouldGenerateGLError(gl, gl.NO_ERROR, voidTests[i]);
+    }
+
+    // Functions return nullable values should all return null.
+    var nullTests = [
+        "gl.createBuffer()",
+        "gl.createFramebuffer()",
+        "gl.createProgram()",
+        "gl.createRenderbuffer()",
+        "gl.createShader(gl.GL_VERTEX_SHADER)",
+        "gl.createTexture()",
+        "gl.getActiveAttrib(program, 0)",
+        "gl.getActiveUniform(program, 0)",
+        "gl.getAttachedShaders(program)",
+        "gl.getBufferParameter(gl.ARRAY_BUFFER, gl.BUFFER_SIZE)",
+        "gl.getContextAttributes()",
+        "gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)",
+        "gl.getParameter(gl.CURRENT_PROGRAM)",
+        "gl.getProgramInfoLog(program)",
+        "gl.getProgramParameter(program, gl.LINK_STATUS)",
+        "gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)",
+        "gl.getShaderInfoLog(shader)",
+        "gl.getShaderParameter(shader, gl.SHADER_TYPE)",
+        "gl.getShaderSource(shader)",
+        "gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S)",
+        "gl.getUniform(program, uniformLocation)",
+        "gl.getUniformLocation(program, 'vPosition')",
+        "gl.getVertexAttrib(0, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)",
+        "gl.getSupportedExtensions()",
+        "gl.getExtension('" + extension_name + "')",
+    ];
+    for (var i = 0; i < nullTests.length; ++i) {
+        shouldBeNull(nullTests[i]);
+    }
+
+    // "Is" queries should all return false.
+    shouldBeFalse("gl.isBuffer(buffer)");
+    shouldBeFalse("gl.isEnabled(gl.BLEND)");
+    shouldBeFalse("gl.isFramebuffer(framebuffer)");
+    shouldBeFalse("gl.isProgram(program)");
+    shouldBeFalse("gl.isRenderbuffer(renderbuffer)");
+    shouldBeFalse("gl.isShader(shader)");
+    shouldBeFalse("gl.isTexture(texture)");
+
+    shouldBe("gl.getError()", "gl.NO_ERROR");
+
+    finish();
+}
+
+function finish() {
+    successfullyParsed = true;
+    var epilogue = document.createElement("script");
+    epilogue.onload = function() {
+        if (window.nonKhronosFrameworkNotifyDone)
+            window.nonKhronosFrameworkNotifyDone();
+    };
+    epilogue.src = "../resources/js-test-post.js";
+    document.body.appendChild(epilogue);
+}
+</script>
+</head>
+<body onload="init()">
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas">
+</body>
+</html>
--- a/content/canvas/test/webgl/conformance/copy-tex-image-and-sub-image-2d.html
+++ b/content/canvas/test/webgl/conformance/copy-tex-image-and-sub-image-2d.html
@@ -3,191 +3,130 @@ Copyright (c) 2010 The Chromium Authors.
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
  -->
 <html>
 <head>
 <link rel="stylesheet" href="../resources/js-test-style.css"/>
 <script src="../resources/js-test-pre.js"></script>
 <script src="resources/webgl-test.js"></script>
-<script id="vshader" type="x-shader/x-vertex">
-attribute vec3 g_Position;
-attribute vec2 g_TexCoord0;
-
-varying vec2 texCoord;
-
-void main()
-{
-    gl_Position = vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);
-    texCoord = g_TexCoord0;
-}
-</script>
-
-<script id="fshader" type="x-shader/x-fragment">
-#ifdef GL_ES
-precision mediump float;
-#endif
-uniform sampler2D tex;
-varying vec2 texCoord;
-void main()
-{
-    gl_FragColor = texture2D(tex, texCoord);
-}
-</script>
+<script src="resources/webgl-test-utils.js"></script>
 
 <script>
 var successfullyParsed = false;
 
 function init()
 {
     if (window.initNonKhronosFramework) {
         window.initNonKhronosFramework(true);
     }
 
     description('Verify copyTexImage2D and copyTexSubImage2D');
 
     runTest();
 }
 
-// These two declarations need to be global for "shouldBe" to see them
-var pixel = [0, 0, 0];
-var correctColor = null;
 var gl = null;
+var wtu = WebGLTestUtils;
 
 function runTestIteration(antialias)
 {
-    if (antialias)
-        gl = initWebGL("antialiasOn", "vshader", "fshader", [ "g_Position", "g_TexCoord0" ], [ 0, 0, 0, 1 ], 1);
-    else
-        gl = initWebGL("antialiasOff", "vshader", "fshader", [ "g_Position", "g_TexCoord0" ], [ 0, 0, 0, 1 ], 1, { antialias: false });
-
-    var textureLoc = gl.getUniformLocation(gl.program, "tex");
+    var canvas = document.getElementById(
+        antialias ? "antialiasOn" : "antialiasOff");
+    var attribs = antialias ? { antialias: false } : undefined;
+    gl = wtu.create3DContext(canvas, attribs);
+    var program = wtu.setupTexturedQuad(gl);
+    var textureLoc = gl.getUniformLocation(program, "tex");
+    glErrorShouldBe(gl, gl.NO_ERROR, "During Initialization");
 
-    var vertices = new Float32Array([
-         1.0,  1.0, 0.0,
-        -1.0,  1.0, 0.0,
-        -1.0, -1.0, 0.0,
-         1.0,  1.0, 0.0,
-        -1.0, -1.0, 0.0,
-         1.0, -1.0, 0.0]);
-    var texCoords = new Float32Array([
-        1.0, 1.0,
-        0.0, 1.0,
-        0.0, 0.0,
-        1.0, 1.0,
-        0.0, 0.0,
-        1.0, 0.0]);
-    var texCoordOffset = vertices.byteLength;
-
-    var vbo = gl.createBuffer();
-    gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
-    gl.bufferData(gl.ARRAY_BUFFER,
-                  texCoordOffset + texCoords.byteLength,
-                  gl.STATIC_DRAW);
-    gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices);
-    gl.bufferSubData(gl.ARRAY_BUFFER, texCoordOffset, texCoords);
-
-    gl.enableVertexAttribArray(0);
-    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
-    gl.enableVertexAttribArray(1);
-    gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, texCoordOffset);
-
-    gl.colorMask(1, 1, 1, 0);
+    gl.colorMask(1, 1, 1, 1);
     gl.disable(gl.BLEND);
     debug('Testing copyTexImage2D');
 
     // Red canvas
     gl.clearColor(1, 0, 0, 1);
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
     var texture = gl.createTexture();
     // Bind the texture to texture unit 0
     gl.bindTexture(gl.TEXTURE_2D, texture);
     // Set up texture
     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
     gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
-
-    glErrorShouldBe(gl, gl.NO_ERROR);
-    gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 2, 2, 0);
-    glErrorShouldBe(gl, gl.NO_ERROR);
+    gl.uniform1i(textureLoc, 0);
 
-    // Green canvas
-    gl.clearColor(0, 1, 0, 1);
-    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-    // Point the uniform sampler to texture unit 0
-    gl.uniform1i(textureLoc, 0);
-    // Draw the triangles
-    gl.drawArrays(gl.TRIANGLES, 0, 6);
+    var colors = [
+      [1, 0, 0, 1],
+      [0, 1, 0, 1],
+      [0, 0, 1, 1],
+      [0.5, 0.5, 0.5, 0.5],
+    ];
+    var count = 0;
+    for (var yy = -2; yy <= 2; ++yy) {
+      for (var xx = -2; xx <= 2; ++xx) {
+         for (var ii = 0; ii < 2; ++ii) {
+          var texColor = colors[count];
+          var clearColor = colors[(count + 1) % colors.length];
+          // clear to some color
+          gl.clearColor(texColor[0], texColor[1], texColor[2], texColor[3]);
+          gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
 
-    // Read back the rendering results, should be red
-    var buf = new Uint8Array(2 * 2 * 4);
-    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, buf);
-    var idx = 0;
-    correctColor = [255, 0, 0];
-    for (var y = 0; y < 2; y++) {
-        for (var x = 0; x < 2; x++) {
-            idx = (y * 2 + x) * 4;
-            pixel[0] = buf[idx];
-            pixel[1] = buf[idx + 1];
-            pixel[2] = buf[idx + 2];
-            shouldBe("pixel", "correctColor");
+          // copy that color to the texture.
+          switch (ii) {
+          case 0:
+            gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, xx, yy, 2, 2, 0);
+            glErrorShouldBe(gl, gl.NO_ERROR,
+                "using copyTexImage2D: x =" + xx + ", y = " + yy);
+            break;
+          case 1:
+            gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, xx, yy, 2, 2);
+            glErrorShouldBe(gl, gl.NO_ERROR,
+                "using copyTexSubImage2D: x =" + xx + ", y = " + yy);
+            break;
+          }
+
+          // clear to some other color.
+          gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+          gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+
+          // Draw the triangles
+          wtu.drawQuad(gl);
+
+          // check the rendering results
+          for (var iy = 0; iy < 2; ++iy) {
+            for (var ix = 0; ix < 2; ++ix) {
+              var x = xx + ix;
+              var y = yy + iy;
+              var expectedColor = (x < 0 || y < 0 || x >= 2 || y >= 2) ?
+                  [0,0,0,0] :
+                  [Math.floor(255 * texColor[0]),
+                   Math.floor(255 * texColor[1]),
+                   Math.floor(255 * texColor[2]),
+                   Math.floor(255 * texColor[3])];
+              wtu.checkCanvasRect(gl, ix, iy, 1, 1, expectedColor,
+                  "" + ix + ", " + iy + " should render " + expectedColor + " (+/-1)", 1);
+            }
+          }
+          count = (count + 1) % colors.length;
         }
+      }
     }
 
-    debug('Testing copyTexSubImage2D');
-
-    // Green canvas
-    gl.clearColor(0, 1, 0, 1);
-    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-    glErrorShouldBe(gl, gl.NO_ERROR);
-    gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2);
-    glErrorShouldBe(gl, gl.NO_ERROR);
-
-    // Blue canvas
-    gl.clearColor(0, 0, 1, 1);
-    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-    // Draw the triangles
-    gl.drawArrays(gl.TRIANGLES, 0, 6);
-
-    // Read back the rendering results, should be green
-    gl.readPixels(0, 0, 2, 2, gl.RGBA, gl.UNSIGNED_BYTE, buf);
-    correctColor = [0, 255, 0];
-    for (var y = 0; y < 2; y++) {
-        for (var x = 0; x < 2; x++) {
-            idx = (y * 2 + x) * 4;
-            pixel[0] = buf[idx];
-            pixel[1] = buf[idx + 1];
-            pixel[2] = buf[idx + 2];
-            shouldBe("pixel", "correctColor");
-        }
-    }
+    debug("");
 }
 
 function runTest(antialias)
 {
     debug("Testing with antialias on");
     runTestIteration(true);
     debug("Testing with antialias off");
     runTestIteration(false);
 
-    successfullyParsed = true;
-    var epilogue = document.createElement("script");
-    epilogue.onload = finish;
-    epilogue.src = "../resources/js-test-post.js";
-    document.body.appendChild(epilogue);
-}
-
-function finish() {
-    if (window.nonKhronosFrameworkNotifyDone) {
-        window.nonKhronosFrameworkNotifyDone();
-    }
+    finishTest();
 }
 </script>
 </head>
 <body onload="init()">
 <canvas id="antialiasOn" width="2px" height="2px"></canvas>
 <canvas id="antialiasOff" width="2px" height="2px"></canvas>
 <div id="description"></div>
 <div id="console"></div>
--- a/content/canvas/test/webgl/conformance/draw-elements-out-of-bounds.html
+++ b/content/canvas/test/webgl/conformance/draw-elements-out-of-bounds.html
@@ -112,23 +112,24 @@ context.vertexAttribPointer(0, 3, contex
 // bind 2 elements, starting after the first 3; same stride of 5 float elements
 context.vertexAttribPointer(1, 2, context.FLOAT, false, 5*4, 3*4);
 
 context.enableVertexAttribArray(0);
 context.enableVertexAttribArray(1);
 
 var ebo = context.createBuffer();
 context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, ebo);
-context.bufferData(context.ELEMENT_ARRAY_BUFFER, new Uint16Array([ 0, 1, 2,
-                                                                   1, 2, 0,
-                                                                   2, 0, 1,
-                                                                   200, 200, 200,
-                                                                   0x7fff, 0x7fff, 0x7fff,
-                                                                   0xffff, 0xffff, 0xffff ]),
-                   context.STATIC_DRAW);
+context.bufferData(context.ELEMENT_ARRAY_BUFFER, new Uint16Array(
+    [ 0, 1, 2,
+      1, 2, 0,
+      2, 0, 1,
+      200, 200, 200,
+      0x7fff, 0x7fff, 0x7fff,
+      0xffff, 0xffff, 0xffff ]),
+    context.STATIC_DRAW);
 
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 9, context.UNSIGNED_SHORT, 0)");
 
 // invalid type arguments
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.drawElements(context.TRIANGLES, 9, context.FLOAT, 0)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.drawElements(context.TRIANGLES, 9, context.SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.drawElements(context.TRIANGLES, 9, context.UNSIGNED_INT, 0)");
 
@@ -139,15 +140,36 @@ shouldGenerateGLError(context, context.I
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 18, context.UNSIGNED_SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 3, context.UNSIGNED_SHORT, 2*15)");
 
 shouldGenerateGLError(context, context.INVALID_VALUE, "context.drawElements(context.TRIANGLES, 0xffffffff, context.UNSIGNED_SHORT, 0)");
 shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 0x7fffffff, context.UNSIGNED_SHORT, 0)");
 
 shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 0, context.UNSIGNED_SHORT, 0)");
 
+// invalid operation with offset that's not a multiple of the type size
+shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 0)");
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 1)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
+
+// invalid operation if no buffer is bound to ELEMENT_ARRAY_BUFFER
+context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, null);
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 0)");
+context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, ebo);
+
+debug("")
+debug("Test buffer setting attrib 0 to a buffer too small and disable it.");
+var smallVBO = context.createBuffer();
+shouldBeNonNull('smallVBO');
+context.bindBuffer(context.ARRAY_BUFFER, smallVBO);
+context.bufferData(context.ARRAY_BUFFER, 1, context.STATIC_DRAW);
+context.vertexAttribPointer(0, 3, context.FLOAT, false, 0, 0x10);
+context.disableVertexAttribArray(0);
+shouldGenerateGLError(context, context.NO_ERROR, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
+context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, null);
+shouldGenerateGLError(context, context.INVALID_OPERATION, "context.drawElements(context.TRIANGLES, 6, context.UNSIGNED_SHORT, 2)");
 debug("")
 successfullyParsed = true;
 </script>
 
 <script src="../resources/js-test-post.js"></script>
 </body>
 </html>
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-bind-attrib-location-test.html
+++ b/content/canvas/test/webgl/conformance/gl-bind-attrib-location-test.html
@@ -120,17 +120,17 @@ function setBindLocations(colorLocation,
   gl.linkProgram(program);
   gl.useProgram(program);
   var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
   assertMsg(linked, "program linked successfully");
 
   debug("vPosition:" + gl.getAttribLocation(program, "vPosition"))
   debug("vColor   :" + gl.getAttribLocation(program, "vColor"))
   assertMsg(gl.getAttribLocation(program, "vPosition") == positionLocation,
-            "location of vPositon should be " + positionLocation);
+            "location of vPosition should be " + positionLocation);
   assertMsg(gl.getAttribLocation(program, "vColor") == colorLocation,
             "location of vColor should be " + colorLocation);
 
   var ploc = gl.getAttribLocation(program, "vPosition");
   var cloc = gl.getAttribLocation(program, "vColor");
   gl.bindBuffer(gl.ARRAY_BUFFER, positions);
   gl.enableVertexAttribArray(positionLocation);
   gl.vertexAttribPointer(positionLocation, 3, gl.FLOAT, false, 0, 0);
old mode 100755
new mode 100644
old mode 100755
new mode 100644
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-enum-tests.html
+++ b/content/canvas/test/webgl/conformance/gl-enum-tests.html
@@ -50,17 +50,16 @@ if (!gl) {
     "gl.bufferData(gl.ARRAY_BUFFER, 3, desktopGL['STATIC_READ'])",
     "gl.disable(desktopGL['CLIP_PLANE0'])",
     "gl.disable(desktopGL['POINT_SPRITE'])",
     "gl.getBufferParameter(gl.ARRAY_BUFFER, desktopGL['PIXEL_PACK_BUFFER'])",
     "gl.hint(desktopGL['PERSPECTIVE_CORRECTION_HINT'], gl.FASTEST)",
     "gl.isEnabled(desktopGL['CLIP_PLANE0'])",
     "gl.isEnabled(desktopGL['POINT_SPRITE'])",
     "gl.pixelStorei(desktopGL['PACK_SWAP_BYTES'], 1)",
-    "gl.readPixels(0, 0, 1, 1, gl.ALPHA, gl.SHORT, buf)",
   ];
   for (var ii = 0; ii < tests.length; ++ii) {
     eval(tests[ii]);
     glErrorShouldBe(gl, gl.INVALID_ENUM,
               tests[ii] + " should return INVALID_ENUM.");
   }
 
   gl.bindTexture(gl.TEXTURE_2D, tex);
--- a/content/canvas/test/webgl/conformance/gl-get-calls.html
+++ b/content/canvas/test/webgl/conformance/gl-get-calls.html
@@ -117,20 +117,33 @@ else {
     shouldBe('context.getParameter(context.STENCIL_WRITEMASK)', '0xFFFFFFFF');
 
     shouldBe('context.getParameter(context.TEXTURE_BINDING_2D)', 'null');
     shouldBe('context.getParameter(context.TEXTURE_BINDING_CUBE_MAP)', 'null');
     shouldBe('context.getParameter(context.UNPACK_ALIGNMENT)', '4');
     shouldBe('context.getParameter(context.UNPACK_FLIP_Y_WEBGL)', 'false');
     shouldBe('context.getParameter(context.UNPACK_PREMULTIPLY_ALPHA_WEBGL)', 'false');
     shouldBe('context.getParameter(context.VIEWPORT)', '[0, 0, 2, 2]');
+    shouldBe('context.getParameter(context.NUM_COMPRESSED_TEXTURE_FORMATS)', '0');
+
+    shouldBeTrue('context.getParameter(context.MAX_COMBINED_TEXTURE_IMAGE_UNITS) >= 8');
+    shouldBeTrue('context.getParameter(context.MAX_CUBE_MAP_TEXTURE_SIZE) >= 16');
     shouldBeTrue('context.getParameter(context.MAX_FRAGMENT_UNIFORM_VECTORS) >= 16');
+    shouldBeTrue('context.getParameter(context.MAX_RENDERBUFFER_SIZE) >= 1');
+    shouldBeTrue('context.getParameter(context.MAX_TEXTURE_IMAGE_UNITS) >= 8');
+    shouldBeTrue('context.getParameter(context.MAX_TEXTURE_SIZE) >= 64');
+    shouldBeTrue('context.getParameter(context.MAX_VARYING_VECTORS) >= 8');
+    shouldBeTrue('context.getParameter(context.MAX_VERTEX_ATTRIBS) >= 8');
+    shouldBeTrue('context.getParameter(context.MAX_VERTEX_TEXTURE_IMAGE_UNITS) >= 0');
     shouldBeTrue('context.getParameter(context.MAX_VERTEX_UNIFORM_VECTORS) >= 128');
-    shouldBeTrue('context.getParameter(context.MAX_VARYING_VECTORS) >= 8');
-    shouldBe('context.getParameter(context.NUM_COMPRESSED_TEXTURE_FORMATS)', '0');
+    // Note: This requirement should be removed from the spec IMO. Many impelementations
+    // will be based on FBOs and FBOs might have a restriction smaller than the current screen size.
+    // especially if there are multiple screens.
+    shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[0] >= window.screen.width');
+    shouldBeTrue('context.getParameter(context.MAX_VIEWPORT_DIMS)[1] >= window.screen.height');
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
 <script src="../resources/js-test-post.js"></script>
 
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-getshadersource.html
@@ -0,0 +1,45 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'/>
+   <title>WebGL getShaderSource conformance test.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">abc//defNOTASCII</script>
+<script>
+description("Tests that the source that goes into a shader is what comes out.");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var original = document.getElementById("vshader").text;
+var shader = gl.createShader(gl.VERTEX_SHADER);
+gl.shaderSource(shader, original);
+var source = gl.getShaderSource(shader);
+shouldBe("source", "original");
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors.");
+successfullyParsed = true;
+</script>
+</body>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-min-attribs.html
@@ -0,0 +1,91 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL the minimum number of attributes are supported.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec4 v0;
+attribute vec4 v1;
+attribute vec4 v2;
+attribute vec4 v3;
+attribute vec4 v4;
+attribute vec4 v5;
+attribute vec4 v6;
+varying vec4 color;
+void main()
+{
+    gl_Position = vPosition;
+    color = v0 + v1 + v2 + v3 + v4 + v5 + v6;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main()
+{
+    gl_FragColor = color;
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5', 'v6'],
+    [0, 1, 2, 3, 4, 5, 6, 7]);
+
+for (var ii = 0; ii < 7; ++ii) {
+  var v = (ii + 1) / 28;
+  var vertexObject = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8,
+      v, v/2, v/4, v/8]), gl.STATIC_DRAW);
+  gl.enableVertexAttribArray(ii + 1);
+  gl.vertexAttribPointer(ii + 1, 4, gl.FLOAT, false, 0, 0);
+}
+
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 127, 64, 32], "Should render 255,127,64,32 (+/-1)", 1);
+
+successfullyParsed = true;
+
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-min-textures-unroll.html
@@ -0,0 +1,86 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL the minimum number of uniforms are supported.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#define NUM_TEXTURES 8 // See spec
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D uni[8];
+void main()
+{
+    vec4 c = vec4(0,0,0,0);
+    c += texture2D(uni[0], vec2(0.5, 0.5));
+    c += texture2D(uni[1], vec2(0.5, 0.5));
+    c += texture2D(uni[2], vec2(0.5, 0.5));
+    c += texture2D(uni[3], vec2(0.5, 0.5));
+    c += texture2D(uni[4], vec2(0.5, 0.5));
+    c += texture2D(uni[5], vec2(0.5, 0.5));
+    c += texture2D(uni[6], vec2(0.5, 0.5));
+    c += texture2D(uni[7], vec2(0.5, 0.5));
+    gl_FragColor = c;
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+for (var ii = 0; ii < 8; ++ii) {
+  var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+  gl.activeTexture(gl.TEXTURE0 + ii);
+  var tex = gl.createTexture();
+  wtu.fillTexture(gl, tex, 1, 1, [32, 16, 8, ii * 9], 0);
+  gl.uniform1i(loc, ii);
+}
+
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvas(gl, [255, 128, 64, 252],
+                "Should render using all texture units");
+
+successfullyParsed = true;
+
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-min-textures.html
@@ -0,0 +1,81 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL the minimum number of uniforms are supported.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#define NUM_TEXTURES 8 // See spec
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D uni[8];
+void main()
+{
+    vec4 c = vec4(0,0,0,0);
+    for (int ii = 0; ii < NUM_TEXTURES; ++ii) {
+      c += texture2D(uni[ii], vec2(0.5, 0.5));
+    }
+    gl_FragColor = c;
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+for (var ii = 0; ii < 8; ++ii) {
+  var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+  gl.activeTexture(gl.TEXTURE0 + ii);
+  var tex = gl.createTexture();
+  wtu.fillTexture(gl, tex, 1, 1, [32, 16, 8, ii * 9], 0);
+  gl.uniform1i(loc, ii);
+}
+
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvas(gl, [255, 128, 64, 252],
+                "Should render using all texture units");
+
+successfullyParsed = true;
+
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-min-uniforms.html
@@ -0,0 +1,120 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL the minimum number of uniforms are supported.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="4" height="4" style="width: 40px; height: 30px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+#define NUM_UNIFORMS 128 // See spec
+attribute vec4 vPosition;
+uniform vec4 uni[NUM_UNIFORMS];
+varying vec4 color;
+void main()
+{
+    gl_Position = vPosition;
+    vec4 c = vec4(0,0,0,0);
+    for (int ii = 0; ii < NUM_UNIFORMS; ++ii) {
+      c += uni[ii];
+    }
+    color = c;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision mediump float;
+#endif
+varying vec4 color;
+void main()
+{
+    gl_FragColor = color;
+}
+</script>
+<script id="vshader2" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader2" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision mediump float;
+#endif
+#define NUM_UNIFORMS 16 // See spec
+uniform vec4 uni[NUM_UNIFORMS];
+void main()
+{
+    vec4 c = vec4(0,0,0,0);
+    for (int ii = 0; ii < NUM_UNIFORMS; ++ii) {
+       c += uni[ii];
+    }
+    gl_FragColor = vec4(c.r, c.g, c.b, c.a / 120.0);
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+var program = wtu.setupTexturedQuad(gl);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+for (var ii = 0; ii < 128; ++ii) {
+  var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+  gl.uniform4f(loc, 2/256, 2/512, 2/1024, ii/8128);
+}
+
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [255, 127, 64, 255], "Should render 255,127,64,32 (+/-1)", 1);
+
+//------------------------------------------------------------------------------
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader2', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader2', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+for (var ii = 0; ii < 16; ++ii) {
+  var loc = gl.getUniformLocation(program, "uni[" + ii + "]");
+  gl.uniform4f(loc, 16/2048, 16/1024, 16/512, ii);
+}
+
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.drawQuad(gl);
+glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [32, 64, 127, 255], "Should render 32,64,127,255 (+/-1)", 1);
+
+successfullyParsed = true;
+
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
--- a/content/canvas/test/webgl/conformance/gl-object-get-calls.html
+++ b/content/canvas/test/webgl/conformance/gl-object-get-calls.html
@@ -5,17 +5,17 @@ Redistribution and use in source and bin
 modification, are permitted provided that the following conditions
 are met:
 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions and the following disclaimer.
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution.
 
-THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. AS IS AND ANY
 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
@@ -111,22 +111,19 @@ shouldBe('gl.getFramebufferAttachmentPar
 
 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE)', 'gl.RENDERBUFFER');
 shouldBe('gl.getFramebufferAttachmentParameter(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)', 'renderbuffer');
 
 // Test getProgramParameter
 shouldBe('gl.getProgramParameter(standardProgram, gl.DELETE_STATUS)', 'false');
 shouldBe('gl.getProgramParameter(standardProgram, gl.LINK_STATUS)', 'true');
 shouldBe('typeof gl.getProgramParameter(standardProgram, gl.VALIDATE_STATUS)', '"boolean"');
-shouldBe('typeof gl.getProgramParameter(standardProgram, gl.INFO_LOG_LENGTH)', '"number"');
 shouldBe('gl.getProgramParameter(standardProgram, gl.ATTACHED_SHADERS)', '2');
 shouldBe('gl.getProgramParameter(standardProgram, gl.ACTIVE_ATTRIBUTES)', '2');
-shouldBeNonZero('gl.getProgramParameter(standardProgram, gl.ACTIVE_ATTRIBUTE_MAX_LENGTH)');
 shouldBe('gl.getProgramParameter(standardProgram, gl.ACTIVE_UNIFORMS)', '1');
-shouldBeNonZero('gl.getProgramParameter(standardProgram, gl.ACTIVE_UNIFORM_MAX_LENGTH)');
 
 // Test getRenderbufferParameter
 shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_WIDTH)', '2');
 shouldBe('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_HEIGHT)', '2');
 // Note: we can't test the actual value of the internal format since
 // the implementation is allowed to change it.
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_INTERNAL_FORMAT)');
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_DEPTH_SIZE)');
@@ -139,18 +136,16 @@ shouldBeNonZero('gl.getRenderbufferParam
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_GREEN_SIZE)');
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_BLUE_SIZE)');
 shouldBeNonZero('gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_ALPHA_SIZE)');
 
 // Test getShaderParameter
 shouldBe('gl.getShaderParameter(standardVert, gl.SHADER_TYPE)', 'gl.VERTEX_SHADER');
 shouldBe('gl.getShaderParameter(standardVert, gl.DELETE_STATUS)', 'false');
 shouldBe('gl.getShaderParameter(standardVert, gl.COMPILE_STATUS)', 'true');
-shouldBe('typeof gl.getShaderParameter(standardVert, gl.INFO_LOG_LENGTH)', '"number"');
-shouldBeNonZero('gl.getShaderParameter(standardVert, gl.SHADER_SOURCE_LENGTH)');
 
 // Test getTexParameter
 gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
 gl.bindTexture(gl.TEXTURE_2D, texture);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
@@ -206,16 +201,27 @@ gl.uniform1f(fvalLoc, 11);
 gl.uniform2f(fval2Loc, 12, 13);
 gl.uniform3f(fval3Loc, 14, 15, 16);
 gl.uniform4f(fval4Loc, 17, 18, 19, 20);
 glErrorShouldBe(gl, gl.NO_ERROR);
 shouldBe('gl.getUniform(floatProgram, fvalLoc)', '11');
 shouldBe('gl.getUniform(floatProgram, fval2Loc)', '[12, 13]');
 shouldBe('gl.getUniform(floatProgram, fval3Loc)', '[14, 15, 16]');
 shouldBe('gl.getUniform(floatProgram, fval4Loc)', '[17, 18, 19, 20]');
+// Sampler uniform variables
+var samplerProgram = loadProgram(gl, "resources/noopUniformShader.vert", "resources/samplerUniformShader.frag");
+shouldBe('gl.getProgramParameter(samplerProgram, gl.LINK_STATUS)', 'true');
+var s2DValLoc = gl.getUniformLocation(samplerProgram, "s2D");
+var sCubeValLoc = gl.getUniformLocation(samplerProgram, "sCube");
+gl.useProgram(samplerProgram);
+gl.uniform1i(s2DValLoc, 0);
+gl.uniform1i(sCubeValLoc, 1);
+glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBe('gl.getUniform(samplerProgram, s2DValLoc)', '0');
+shouldBe('gl.getUniform(samplerProgram, sCubeValLoc)', '1');
 // Matrix uniform variables
 var matProgram = loadProgram(gl, "resources/matUniformShader.vert", "resources/noopUniformShader.frag");
 shouldBe('gl.getProgramParameter(matProgram, gl.LINK_STATUS)', 'true');
 var mval2Loc = gl.getUniformLocation(matProgram, "mval2");
 var mval3Loc = gl.getUniformLocation(matProgram, "mval3");
 var mval4Loc = gl.getUniformLocation(matProgram, "mval4");
 gl.useProgram(matProgram);
 gl.uniformMatrix2fv(mval2Loc, false, [1, 2, 3, 4]);
old mode 100755
new mode 100644
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-teximage.html
+++ b/content/canvas/test/webgl/conformance/gl-teximage.html
@@ -34,16 +34,17 @@ var imgURLs = [
   'resources/gray-ramp-gamma1.0.png',
   'resources/gray-ramp-gamma2.0.png',
   'resources/gray-ramp-gamma4.0.png',
   'resources/gray-ramp-gamma9.0.png',
   'resources/gray-ramp.png',
   'resources/zero-alpha.png',
   'resources/3x3.png',
   'resources/blue-1x1.jpg',
+  'resources/red-indexed.png',
   'resources/green-2x2-16bit.png',
   'resources/small-square-with-colorspin-profile.jpg',
   'resources/small-square-with-colorspin-profile.png',
   'resources/small-square-with-cie-rgb-profile.png',
   'resources/small-square-with-colormatch-profile.png',
   'resources/small-square-with-e-srgb-profile.png',
   'resources/small-square-with-smpte-c-profile.png',
   'resources/small-square-with-srgb-iec61966-2.1-profile.png'];
@@ -84,29 +85,33 @@ function runTests(imgs) {
 
   function checkPixelRange(buf, x, y, color, allowedRange) {
     var off = (y * width + x) * 4;
     var msg = "pixel " + x + ", " + y + " should be within " +
               allowedRange + " units of " +
               color[0] + ", " +
               color[1] + ", " +
               color[2] + ", " +
-              color[3] + " was " +
+              color[3];
+    var subMsg = " was " +
               buf[off + 0] + ", " +
               buf[off + 1] + ", " +
               buf[off + 2] + ", " +
               buf[off + 3];
-
+    // When running in WebKit's test harness, we don't want to print the
+    // pixel value when the test passes, because different machines might
+    // have different results and we record the text output.
+    var inDumpRenderTree = window.layoutTestController;
     for (var ii = 0; ii < 4; ++ii) {
       if (Math.abs(buf[off + ii] - color[ii]) > allowedRange) {
-        testFailed(msg);
+        testFailed(msg + subMsg);
         return;
       }
     }
-    testPassed(msg);
+    testPassed(msg + (inDumpRenderTree ? "" : subMsg));
   }
 
   var tex = gl.createTexture();
   gl.bindTexture(gl.TEXTURE_2D, tex);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
   gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
@@ -202,54 +207,82 @@ function runTests(imgs) {
         break;
       }
     }
     assertMsg(same, "pixels should be same regardless of gamma settings.");
   }
 
   debug("");
   debug("check pixels are UN pre-multiplied");
-  var canvas2d = document.createElement("canvas");
-  canvas2d.width = 256;
-  canvas2d.height = 1;
-  //canvas2d.style.height = "40px";
-  //var description = document.getElementById("description");
-  //description.appendChild(canvas2d);
-  var ctx = canvas2d.getContext("2d");
-  ctx.fillRect(0, 0, 256, 1);
-  ctx.drawImage(imgs['resources/gray-ramp-256-with-128-alpha.png'], 0, 0);
-  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas2d);
-  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
-  wtu.drawQuad(gl);
-  var ref = new Uint8Array(width * height * 4);
-  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, ref);
-  var lt128Count = [0, 0, 0];
-  var ge128Count = [0, 0, 0];
-  for (var jj = 0; jj < width; ++jj) {
-    var off = jj * 4;
-    for (var cc = 0; cc < 3; ++cc) {
-      if (buf[off + cc] < 128) {
-        ++lt128Count[cc];
-      } else {
-        ++ge128Count[cc];
+  for (var ii = 0; ii < 2; ++ii) {
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+    if (ii == 0) {
+      var canvas2d = document.createElement("canvas");
+      canvas2d.width = 256;
+      canvas2d.height = 1;
+      var ctx = canvas2d.getContext("2d");
+      ctx.drawImage(imgs['resources/gray-ramp-256-with-128-alpha.png'], 0, 0);
+      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, canvas2d);
+    } else {
+      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+                    imgs['resources/gray-ramp-256-with-128-alpha.png']);
+    }
+    glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+    wtu.drawQuad(gl);
+    var buf = new Uint8Array(width * height * 4);
+    gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+    var lt128Count = [0, 0, 0];
+    var ge128Count = [0, 0, 0];
+    for (var jj = 0; jj < width; ++jj) {
+      var off = jj * 4;
+      for (var cc = 0; cc < 3; ++cc) {
+        if (buf[off + cc] < 128) {
+          ++lt128Count[cc];
+        } else {
+          ++ge128Count[cc];
+        }
       }
     }
+    // Not sure the exact count here because gamma does effect drawing into the
+    // canvas but it should be close to 50% so I'll pass 45%
+    for (var jj = 0; jj < 3; ++jj) {
+      assertMsg(ge128Count[jj] > 256 * 0.45,
+                "Half the pixels in channel " + jj +
+                " should be >= 128,128,128. found " +
+                ((ge128Count[jj] / 256) * 100).toFixed() + "%");
+      assertMsg(lt128Count[jj] > 256 * 0.45,
+                "Half the pixels in channel " + jj +
+                " should be < 128,128,128. found " +
+                ((lt128Count[jj] / 256) * 100).toFixed() + "%");
+    }
   }
-  // Not sure the exact count here because gamma does effect drawing into the
-  // canvas but it should be close to 50% so I'll pass 45%
-  for (var jj = 0; jj < 3; ++jj) {
-    assertMsg(ge128Count[jj] > 256 * 0.45,
-              "Half the pixels in channel " + jj +
-              " should be >= 128,128,128. found " +
-              ((ge128Count[jj] / 256) * 100).toFixed() + "%");
-    assertMsg(lt128Count[jj] > 256 * 0.45,
-              "Half the pixels in channel " + jj +
-              " should be < 128,128,128. found " +
-              ((lt128Count[jj] / 256) * 100).toFixed() + "%");
-  }
+
+  debug("");
+  debug("check canvas pixels are UN pre-multiplied");
+  var canvas2d = document.createElement("canvas");
+  canvas2d.width = 1;
+  canvas2d.height = 1;
+  var ctx = canvas2d.getContext("2d");
+  ctx.fillStyle ="rgba(255,255,255,0.5)";
+  ctx.fillRect(0, 0, 256, 1);
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+  wtu.drawQuad(gl);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+  checkPixelRange(buf, 0, 0, [255, 255, 255, 127], 4);
+
+  debug("");
+  debug("check canvas pixels are pre-multiplied");
+  gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+  wtu.drawQuad(gl);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup.");
+  checkPixelRange(buf, 0, 0, [127, 127, 127, 127], 4);
+
 
   debug("");
   debug("check pixels are pre-multiplied");
   gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
   // TODO(gman): use different texture that won't pass on failure
   gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE,
                 imgs['resources/zero-alpha.png']);
   glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
@@ -351,16 +384,26 @@ function runTests(imgs) {
         same = false;
         break;
       }
     }
     assertMsg(same, "uploading PNGs with same data but various ICC profiles should generate the same results");
   }
 
   debug("");
+  debug("check uploading of indexed PNG images");
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE,
+                imgs['resources/red-indexed.png']);
+  glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors from setup");
+  wtu.drawQuad(gl);
+  gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+  // The image should be red.
+  checkPixelRange(buf, middle, center, [ 255, 0, 0, 255 ], 10);
+
+  debug("");
   successfullyParsed = true;
   shouldBeTrue("successfullyParsed");
   debug('<br /><span class="pass">TEST COMPLETE</span>');
   notifyFinishedToHarness();
 }
 </script>
 </body>
 </html>
--- a/content/canvas/test/webgl/conformance/gl-uniform-arrays.html
+++ b/content/canvas/test/webgl/conformance/gl-uniform-arrays.html
@@ -103,23 +103,24 @@ var typeInfos = [
     },
     srcValueAsString: function(index, srcValues) {
       return srcValues[index].toString();
     },
     returnValueAsString: function(value) {
       return value === null ? 'null' : value.toString();
     },
     checkType: function(value) {
-      return typeof values === 'number';
+      return typeof value === 'number';
     },
     checkValue: function(typeInfo, index, value) {
       return typeInfo.srcValues[index] == value;
     },
     srcValues: [16, 15, 14],
-    srcValuesBad: [],
+    srcValuesLess: [],
+    srcValuesNonMultiple: null,
   },
   { type: 'vec2',
     jsTypeOf: 'Float32Array',
     setter: 'uniform2fv',
     elem: '[1]',
     numSrcValues: 3,
     invalidSet: function(loc) {
       gl.uniform1fv(loc, [2]);
@@ -130,26 +131,28 @@ var typeInfos = [
     srcValueAsString: function(index, srcValues) {
       return "[" + srcValues[index * 2 + 0].toString() + ", " +
                    srcValues[index * 2 + 1].toString() + "]";
     },
     returnValueAsString: function(value) {
       return value === null ? 'null' : ("[" + value[0] + ", " + value[1] + "]");
     },
     checkType: function(value) {
-      return typeof values.length === 'number' &&
-             values.length == 2;
+      return value &&
+             typeof value.length === 'number' &&
+             value.length == 2;
     },
     checkValue: function(typeInfo, index, value) {
       return value !== null &&
              typeInfo.srcValues[index * 2 + 0] == value[0] &&
              typeInfo.srcValues[index * 2 + 1] == value[1];
     },
     srcValues: [16, 15, 14, 13, 12, 11],
-    srcValuesBad: [16],
+    srcValuesLess: [16],
+    srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10],
   },
   { type: 'vec3',
     jsTypeOf: 'Float32Array',
     setter: 'uniform3fv',
     elem: '[2]',
     numSrcValues: 3,
     invalidSet: function(loc) {
       gl.uniform1fv(loc, [2]);
@@ -162,27 +165,29 @@ var typeInfos = [
                    srcValues[index * 3 + 1].toString() + ", " +
                    srcValues[index * 3 + 2].toString() + "]";
     },
     returnValueAsString: function(value) {
       return value === null ? 'null' :
           ("[" + value[0] + ", " + value[1] + ", " + value[2] + "]");
     },
     checkType: function(value) {
-      return typeof values.length === 'number' &&
-             values.length == 3;
+      return value &&
+             typeof value.length === 'number' &&
+             value.length == 3;
     },
     checkValue: function(typeInfo, index, value) {
       return value !== null &&
              typeInfo.srcValues[index * 3 + 0] == value[0] &&
              typeInfo.srcValues[index * 3 + 1] == value[1] &&
              typeInfo.srcValues[index * 3 + 2] == value[2];
     },
     srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8],
-    srcValuesBad: [16, 15],
+    srcValuesLess: [16, 15],
+    srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7],
   },
   { type: 'vec4',
     jsTypeOf: 'Float32Array',
     setter: 'uniform4fv',
     elem: '[3]',
     numSrcValues: 3,
     invalidSet: function(loc) {
       gl.uniform1fv(loc, [2]);
@@ -197,28 +202,30 @@ var typeInfos = [
                    srcValues[index * 4 + 3].toString() + "]";
     },
     returnValueAsString: function(value) {
       return value === null ? 'null' :
           ("[" + value[0] + ", " + value[1] +
            ", " + value[2] + ", " + value[3] + "]");
     },
     checkType: function(value) {
-      return typeof values.length === 'number' &&
-             values.length == 4;
+      return value &&
+             typeof value.length === 'number' &&
+             value.length == 4;
     },
     checkValue: function(typeInfo, index, value) {
       return value !== null &&
              typeInfo.srcValues[index * 4 + 0] == value[0] &&
              typeInfo.srcValues[index * 4 + 1] == value[1] &&
              typeInfo.srcValues[index * 4 + 2] == value[2] &&
              typeInfo.srcValues[index * 4 + 3] == value[3];
     },
     srcValues: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5],
-    srcValuesBad: [16, 15, 14],
+    srcValuesLess: [16, 15, 14],
+    srcValuesNonMultiple: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4],
   }
 ];
 
 for (var tt = 0; tt < typeInfos.length; ++tt) {
   var typeInfo = typeInfos[tt];
   debug("");
   debug("check " + typeInfo.type);
   var fSrc = fTemplate.replace(/\$type/g, typeInfo.type).
@@ -228,64 +235,70 @@ for (var tt = 0; tt < typeInfos.length; 
 
   var numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
   assertMsg(numUniforms == 1, "1 uniform found");
   var info = gl.getActiveUniform(program, 0);
   assertMsg(info.name == "color[0]",
             "uniform name is 'color[0]' not 'color' as per OpenGL ES 2.0.24 section 2.10");
   var loc = gl.getUniformLocation(program, "color[0]");
   var srcValues = typeInfo.srcValues;
-  var srcValuesBad = typeInfo.srcValuesBad;
+  var srcValuesLess = typeInfo.srcValuesLess;
+  var srcValuesNonMultiple = typeInfo.srcValuesNonMultiple;
 
   // Try setting the value before using the program
   gl[typeInfo.setter](loc, srcValues);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
-            "should fail if there is no current program");
+                  "should fail if there is no current program");
 
   gl.useProgram(program);
-  gl[typeInfo.setter](loc, srcValuesBad);
+  gl[typeInfo.setter](loc, srcValuesLess);
   glErrorShouldBe(gl, gl.INVALID_VALUE,
-            "should fail with insufficient array size with gl." + typeInfo.setter);
+                  "should fail with insufficient array size with gl." + typeInfo.setter);
+  if (srcValuesNonMultiple) {
+    gl[typeInfo.setter](loc, srcValuesNonMultiple);
+    glErrorShouldBe(gl, gl.INVALID_VALUE,
+                    "should fail with non-multiple array size with gl." + typeInfo.setter);
+  }
   gl[typeInfo.setter](loc, srcValues);
   glErrorShouldBe(gl, gl.NO_ERROR,
-            "can set an array of uniforms with gl." + typeInfo.setter);
+                  "can set an array of uniforms with gl." + typeInfo.setter);
   var values = gl.getUniform(program, loc);
   glErrorShouldBe(gl, gl.NO_ERROR,
-            "can call gl.getUniform");
+                  "can call gl.getUniform");
   assertMsg(typeInfo.checkType(values),
             "gl.getUniform returns the correct type.");
   for (var ii = 0; ii < typeInfo.numSrcValues; ++ii) {
     var elemLoc = gl.getUniformLocation(program, "color[" + ii + "]");
     glErrorShouldBe(gl, gl.NO_ERROR,
-              "can get location of element " + ii +
-              " of array from gl.getUniformLocation");
+                    "can get location of element " + ii +
+                    " of array from gl.getUniformLocation");
     var value = gl.getUniform(program, elemLoc);
     glErrorShouldBe(gl, gl.NO_ERROR,
-              "can get value of element " + ii + " of array from gl.getUniform");
+                    "can get value of element " + ii + " of array from gl.getUniform");
     assertMsg(typeInfo.checkValue(typeInfo, ii, value),
               "value put in (" + typeInfo.srcValueAsString(ii, srcValues) +
               ") matches value pulled out (" +
               typeInfo.returnValueAsString(value) + ")");
   }
   typeInfo.invalidSet(loc);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
-            "using the wrong size of gl.Uniform fails");
+                  "using the wrong size of gl.Uniform fails");
   var exceptionCaught = false;
   if (typeInfo.illegalSet) {
     try {
       typeInfo.illegalSet(loc);
     } catch (e) {
       exceptionCaught = true;
     }
     assertMsg(exceptionCaught, "passing non-array to glUniform*fv should throw TypeError");
   }
 
   gl.useProgram(null);
   glErrorShouldBe(gl, gl.NO_ERROR,
-            "can call gl.useProgram(null)");
+                  "can call gl.useProgram(null)");
 }
 debug("");
 successfullyParsed = true;
 
 </script>
 <script src="../resources/js-test-post.js"></script>
 
 <script>
--- a/content/canvas/test/webgl/conformance/gl-uniform-bool.html
+++ b/content/canvas/test/webgl/conformance/gl-uniform-bool.html
@@ -40,17 +40,17 @@ debug("");
 debug("NOTE: Some OpenGL drivers do not handle this correctly");
 debug("");
 debug("Checking gl.uniform1f with bool.");
 
 gl = initWebGL("example", "vshader", "fshader", [ "vPosition"], [ 0, 0, 0, 1 ], 1);
 var loc = gl.getUniformLocation(gl.program, "color");
 gl.uniform1f(loc, 1);
 glErrorShouldBe(gl, gl.NO_ERROR,
-          "should be able to set bool with gl.uniform1f");
+                "should be able to set bool with gl.uniform1f");
 
 debug("");
 successfullyParsed = true;
 
 </script>
 <script src="../resources/js-test-post.js"></script>
 
 <script>
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-uniformmatrix4fv.html
+++ b/content/canvas/test/webgl/conformance/gl-uniformmatrix4fv.html
@@ -40,27 +40,34 @@ void main()
 description("This test ensures WebGL implementations handle uniformMatrix in a OpenGL ES 2.0 spec compliant way");
 
 debug("");
 debug("Checking gl.uniformMatrix.");
 
 gl = initWebGL("example", "vshader", "fshader", [ "vPosition"], [ 0, 0, 0, 1 ], 1);
 for (var ii = 2; ii <= 4; ++ii) {
   var loc = gl.getUniformLocation(gl.program, "world" + ii);
-  var mat = [];
+  var matLess = [];
   for (var jj = 0; jj < ii; ++jj) {
     for (var ll = 0; ll < ii; ++ll) {
       if (jj == ii - 1 && ll == ii - 1)
         continue;
-      mat[jj * ii + ll] = (jj == ll) ? 1 : 0;
+      matLess[jj * ii + ll] = (jj == ll) ? 1 : 0;
     }
   }
+  var mat = matLess.concat([1]);
+  var matMore = mat.concat([1]);
   name = "uniformMatrix" + ii + "fv";
+  gl[name](loc, false, matLess);
+  glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with insufficient array size for " + name);
   gl[name](loc, false, mat);
-  glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with insufficient array size for " + name);
+  glErrorShouldBe(gl, gl.NO_ERROR, "should succeed with correct array size for " + name);
+  gl[name](loc, false, matMore);
+  glErrorShouldBe(gl, gl.INVALID_VALUE, "should fail with more than 1 array size for " + name);
+
   mat[ii * ii - 1] = 1;
   gl[name](loc, false, mat);
   glErrorShouldBe(gl, gl.NO_ERROR, "can call " + name + "with transpose = false");
   gl[name](loc, true, mat);
   glErrorShouldBe(gl, gl.INVALID_VALUE, name + " should return INVALID_VALUE with transpose = true");
 }
 
 debug("");
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/gl-vertex-attrib-zero-issues.html
@@ -0,0 +1,97 @@
+<!--
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+-->
+<!DOCTYPE html>
+<html>
+<head>
+<title>WebGL Enable Vertex Attrib Zero Test</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="example" width="50" height="50">
+</canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+    attribute vec4 vPosition;
+    void main()
+    {
+        gl_Position = vPosition;
+    }
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+    void main()
+    {
+        gl_FragColor = vec4(0.0,0.0,0.0,0.0);
+    }
+</script>
+
+<script>
+description("Test some of the issues of the difference between attrib 0 on OpenGL vs WebGL");
+debug("");
+var wtu = WebGLTestUtils;
+var canvas = document.getElementById("example");
+var gl = wtu.create3DContext(canvas);
+
+function setup(numVerts, attribIndex) {
+  var program = wtu.setupProgram(
+      gl,
+      [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+       wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+      ['vPosition'], [attribIndex]);
+  // draw with something on attrib zero with a small number of vertices
+  var vertexObject = gl.createBuffer();
+  g_program = program;
+  g_attribLocation = attribIndex;
+  shouldBe("g_attribLocation", "gl.getAttribLocation(g_program, 'vPosition')");
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+  gl.bufferData(
+      gl.ARRAY_BUFFER, new Float32Array(numVerts * 3), gl.STATIC_DRAW);
+  gl.vertexAttribPointer(attribIndex, 3, gl.FLOAT, false, 0, 0);
+  var indices = new Uint16Array(numVerts);
+  for (var ii = 0; ii < numVerts; ++ii) {
+    indices[ii] = ii;
+  }
+  var indexBuffer = gl.createBuffer();
+  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
+  gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
+  return program;
+}
+
+var p1 = setup(3, 0);
+var p2 = setup(60000, 3);
+
+for (var ii = 0; ii < 5; ++ii) {
+  gl.useProgram(p1);
+  gl.enableVertexAttribArray(0);
+  gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0);
+  glErrorShouldBe(
+      gl, gl.NO_ERROR,
+      "drawing using attrib 0 with 3 verts");
+
+  gl.useProgram(p2);
+  gl.enableVertexAttribArray(3);
+  gl.drawArrays(gl.LINES, 0, 60000);
+  glErrorShouldBe(
+      gl, gl.NO_ERROR,
+      "drawing using attrib 3 with 60000 verts");
+}
+
+wtu.checkCanvas(gl, [0, 0, 0, 0], "canvas should be 0, 0, 0, 0");
+
+successfullyParsed = true;
+</script>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/gl-vertexattribpointer.html
+++ b/content/canvas/test/webgl/conformance/gl-vertexattribpointer.html
@@ -8,49 +8,125 @@ found in the LICENSE file.
 <html>
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <title>WebGL vertexAttribPointer Conformance Tests</title>
 <link rel="stylesheet" href="../resources/js-test-style.css"/>
 <script src="../resources/desktop-gl-constants.js" type="text/javascript"></script>
 <script src="../resources/js-test-pre.js"></script>
 <script src="resources/webgl-test.js"></script>
+<script src="resources/webgl-test-utils.js"></script>
 </head>
 <body>
 <div id="description"></div>
 <div id="console"></div>
 <canvas id="canvas" width="2" height="2"> </canvas>
 <script>
 description("This test checks vertexAttribPointer behaviors in WebGL.");
 
 debug("");
 debug("Canvas.getContext");
 
+var wtu = WebGLTestUtils;
 var gl = create3DContext(document.getElementById("canvas"));
 if (!gl) {
   testFailed("context does not exist");
 } else {
   testPassed("context exists");
 
   debug("");
   debug("Checking gl.vertexAttribPointer.");
 
+  if (!gl.FIXED) {
+    gl.FIXED = 0x140C;
+  }
+
   gl.vertexAttribPointer(0, 3, gl.FLOAT, 0, 0, 12);
   glErrorShouldBe(gl, gl.INVALID_OPERATION,
       "vertexAttribPointer should fail if no buffer is bound");
 
   var vertexObject = gl.createBuffer();
   gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
-  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(512), gl.STATIC_DRAW);
-  gl.vertexAttribPointer(0, 1, gl.FLOAT, 0, 256, 0);
-  glErrorShouldBe(gl, gl.INVALID_VALUE,
-      "WebGL API supports vertex attribute data strides up to 255 bytes");
-  gl.vertexAttribPointer(0, 1, gl.FLOAT, 0, 255, 0);
-  glErrorShouldBe(gl, gl.NO_ERROR,
-      "vertexAttribPointer with stride <= 255 should succeed");
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(0), gl.STATIC_DRAW);
+
+  gl.vertexAttribPointer(0, 1, gl.INT, 0, 0, 0);
+  glErrorShouldBe(gl, gl.INVALID_ENUM,
+      "vertexAttribPointer should not support INT");
+  gl.vertexAttribPointer(0, 1, gl.UNSIGNED_INT, 0, 0, 0);
+  glErrorShouldBe(gl, gl.INVALID_ENUM,
+      "vertexAttribPointer should not support UNSIGNED_INT");
+  gl.vertexAttribPointer(0, 1, gl.FIXED, 0, 0, 0);
+  glErrorShouldBe(gl, gl.INVALID_ENUM,
+      "vertexAttribPointer should not support FIXED");
+
+  function checkVertexAttribPointer(
+      gl, err, reason, size, type, normalize, stride, offset) {
+    gl.vertexAttribPointer(0, size, type, normalize, stride, offset);
+    glErrorShouldBe(gl, err,
+        "gl.vertexAttribPointer(0, " + size +
+        ", gl." + wtu.glEnumToString(gl, type) +
+        ", " + normalize +
+        ", " + stride +
+        ", " + offset +
+        ") should " + (err == gl.NO_ERROR ? "succeed " : "fail ") + reason);
+  }
+
+  var types = [
+    { type:gl.BYTE,           bytesPerComponent: 1 },
+    { type:gl.UNSIGNED_BYTE,  bytesPerComponent: 1 },
+    { type:gl.SHORT,          bytesPerComponent: 2 },
+    { type:gl.UNSIGNED_SHORT, bytesPerComponent: 2 },
+    { type:gl.FLOAT,          bytesPerComponent: 4 },
+  ];
+
+  for (var ii = 0; ii < types.length; ++ii) {
+    var info = types[ii];
+    debug("");
+    for (var size = 1; size <= 4; ++size) {
+      debug("");
+      debug("checking: " + wtu.glEnumToString(gl, info.type) + " with size " + size);
+      var bytesPerElement = size * info.bytesPerComponent;
+      var offsetSet = [
+          0,
+          1,
+          info.bytesPerComponent - 1,
+          info.bytesPerComponent,
+          info.bytesPerComponent + 1,
+          info.bytesPerComponent * 2];
+      for (var jj = 0; jj < offsetSet.length; ++jj) {
+        var offset = offsetSet[jj];
+        for (var kk = 0; kk < offsetSet.length; ++kk) {
+          var stride = offsetSet[kk];
+          var err = gl.NO_ERROR;
+          var reason = ""
+          if (offset % info.bytesPerComponent != 0) {
+            reason = "because offset is bad";
+            err = gl.INVALID_OPERATION;
+          }
+          if (stride % info.bytesPerComponent != 0) {
+            reason = "because stride is bad";
+            err = gl.INVALID_OPERATION;
+          }
+          checkVertexAttribPointer(
+              gl, err, reason, size, info.type, false, stride, offset);
+        }
+        var stride = Math.floor(255 / info.bytesPerComponent) * info.bytesPerComponent;
+
+        if (offset == 0) {
+          checkVertexAttribPointer(
+              gl, gl.NO_ERROR, "at stride limit",
+              size, info.type, false, stride, offset);
+          checkVertexAttribPointer(
+              gl, gl.INVALID_VALUE, "over stride limit",
+              size, info.type, false,
+              stride + info.bytesPerComponent, offset);
+        }
+      }
+    }
+  }
 }
 
 debug("");
 successfullyParsed = true;
 
 </script>
 <script src="../resources/js-test-post.js"></script>
 
old mode 100755
new mode 100644
--- a/content/canvas/test/webgl/conformance/glsl-conformance.html
+++ b/content/canvas/test/webgl/conformance/glsl-conformance.html
@@ -95,16 +95,27 @@ void main()
   void main()
   {
       gl_FragColor = vec4(0.0,0.0,0.0,1.0);
   }
 #else
   foo
 #endif
 </script>
+<script id="fshaderWithUndefinedPreprocessorSymbol" type="text/something-not-javascript">
+#if UNDEFINED_FOO
+  // according to ES GLSL spec 3.4 undefined symbols should fail.
+#else
+  precision mediump float;
+  void main()
+  {
+      gl_FragColor = vec4(0.0,0.0,0.0,1.0);
+  }
+#endif
+</script>
 <script id="fshaderWithFragDepth" type="text/something-not-javascript">
 precision mediump float;
 void main()
 {
     gl_FragColor = vec4(0.0,0.0,0.0,1.0);
     gl_FragDepth = 1.0;
 }
 </script>
@@ -218,16 +229,26 @@ void main()
 </script>
 <script id="vshaderWithLineDirective" type="text/something-not-javascript">
 #line 123
 foo
 </script>
 <script id="vshaderWith__FILE__" type="text/something-not-javascript">
 __FILE__
 </script>
+<script id="vshaderWithIncludeDirective" type="text/something-not-javascript">
+// Sadly I can not force the current path so this could fail beacuse include.vs
+// does not exist, not because #include is disallowed.
+#include "include.vs"
+attribute vec4 vPosition;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
 <script id="fshaderWithdFdx" type="text/something-not-javascript">
 #extension GL_OES_standard_derivatives:enable
 precision mediump float;
 void main()
 {
     gl_FragColor = vec4(dFdx(0.5),0.0,0.0,1.0);
 }
 </script>
@@ -235,30 +256,62 @@ void main()
 precision mediump float;
 void main()
 {
     gl_FragColor = vec4(dFdx(0.5),0.0,0.0,1.0);
 }
 </script>
 <script id="fshaderWith256CharacterIdentifier" type="text/something-not-javascript">
 precision mediump float;
-uniform float a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345 = 2.0;
+uniform float a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345;
 void main()
 {
   gl_FragColor = vec4(a123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345,0.0,0.0,1.0);
 }
 </script>
 <script id="fshaderWith257CharacterIdentifier" type="text/something-not-javascript">
 precision mediump float;
-uniform float a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456 = 2.0;
+uniform float a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456;
 void main()
 {
   gl_FragColor = vec4(a1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456,0.0,0.0,1.0);
 }
 </script>
+<script id="fshaderWithLongLine" type="text/something-not-javascript">
+precision mediump float;
+uniform float fooo;
+#if defined(someSymbolNotDefined)
+#error long
+#endif
+void main()
+{
+    gl_FragColor = vec4(fooo+fooo+fooo+fooo, fooo+fooo+fooo+fooo, fooo+fooo+fooo+fooo, 1.0);
+}
+</script>
+<script id="fshaderWithErrorDirective" type="text/something-not-javascript">
+#error testing123 testing123
+void main()
+{
+    gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script id="fshaderWithQuotedErrorDirective" type="text/something-not-javascript">
+#error "testing123 testing123" // will return INVALID_VALUE. See WebGL 6.18
+void main()
+{
+    gl_FragColor = vec4(0,0,0,0);
+}
+</script>
+<script id="fshaderWithNonASCIIErrorDirective" type="text/something-not-javascript">
+#error ͂`rbhhł͂Ȃ // will return INVALID_VALUE. See WebGL 6.18
+void main()
+{
+    gl_FragColor = vec4(0,0,0,0);
+}
+</script>
 <canvas id="canvas" width="2" height="2"> </canvas>
 <script>
 description("This test ensures WebGL implementations allow proper GLES2 shaders compile and improper ones fail.");
 
 debug("");
 debug("Canvas.getContext");
 
 var wtu = WebGLTestUtils;
@@ -331,16 +384,23 @@ if (!gl) {
       vShaderSuccess: true,
       fShaderId: 'fshaderWithVERSION100PreprocessorSymbol',
       fShaderSuccess: true,
       linkSuccess: true,
       passMsg: 'fragment shader that uses __VERSION__==100 should succeed',
     },
     { vShaderId: 'vshader',
       vShaderSuccess: true,
+      fShaderId: 'fshaderWithUndefinedPreprocessorSymbol',
+      fShaderSuccess: false,
+      linkSuccess: false,
+      passMsg: 'fragment shader undefined preprocessor symbol should fail (3.4)',
+    },
+    { vShaderId: 'vshader',
+      vShaderSuccess: true,
       fShaderId: 'fshaderWithFragDepth',
       fShaderSuccess: false,
       linkSuccess: false,
       passMsg: 'fragment shader that uses gl_FragDepth should fail',
     },
     { vShaderId: 'vshader',
       vShaderSuccess: true,
       fShaderId: 'fshaderWithdFdx',
@@ -456,33 +516,82 @@ if (!gl) {
     { vShaderId: 'vshaderWithLineDirective',
       vShaderSuccess: false,
       vShaderTest: (function() { return wtu.getLastError().indexOf("124") >= 0; }),
       fShaderId: 'fshader',
       fShaderSuccess: true,
       linkSuccess: false,
       passMsg: 'vertex shader uses #line directive should report correct line',
     },
-// TODO(zmo): adding these tests back once the limit is added to WebGL spec.
-/*
+    { vShaderId: 'vshaderWithIncludeDirective',
+      vShaderSuccess: false,
+      fShaderId: 'fshader',
+      fShaderSuccess: true,
+      linkSuccess: false,
+      passMsg: 'vertex shader uses #include should fail',
+    },
+    //{ vShaderId: 'vshader',
+    //  vShaderSuccess: true,
+    //  fShaderId: 'fshaderWith257CharacterIdentifier',
+    //  fShaderSuccess: false,
+    //  linkSuccess: false,
+    //  passMsg: 'shader that uses 257 character identifier should fail',
+    //},
     { vShaderId: 'vshader',
       vShaderSuccess: true,
       fShaderId: 'fshaderWith256CharacterIdentifier',
       fShaderSuccess: true,
       linkSuccess: true,
-      passMsg: 'shared that uses 256 character identifier should succeed',
+      passMsg: 'shader that uses 256 character identifier should succeed',
     },
     { vShaderId: 'vshader',
       vShaderSuccess: true,
-      fShaderId: 'fshaderWith257CharacterIdentifier',
+      fShaderId: 'fshaderWithLongLine',
+      fShaderSuccess: true,
+      fShaderPrep: function(str) {
+        function expand(str, re, replacement, count) {
+          for (var ii = 0; ii < count; ++ii) {
+            str = str.replace(re, replacement);
+          }
+          return str;
+        }
+        str = expand(str, new RegExp(" ", 'g'), "  ", 12);
+        str = expand(str, new RegExp("0", 'g'), "00", 8);
+        str = expand(str, new RegExp("fooo", 'g'), "fooofooo", 6);
+        str = expand(str, new RegExp("long", 'g'), "longlong", 6);
+        //debug("len:" + str.length);
+        //debug(str);
+        return str;
+      },
+      linkSuccess: true,
+      passMsg: 'shader that uses long lines should succeed',
+    },
+    { vShaderId: 'vshader',
+      vShaderSuccess: true,
+      fShaderId: 'fshaderWithErrorDirective',
+      fShaderSuccess: false,
+      fShaderTest: (function() {
+        return wtu.getLastError().indexOf("testing123 testing123") >= 0; }),
+      linkSuccess: false,
+      passMsg: "error directive returns error user's error message",
+    },
+    { vShaderId: 'vshader',
+      vShaderSuccess: true,
+      fShaderId: 'fshaderWithQuotedErrorDirective',
       fShaderSuccess: false,
       linkSuccess: false,
-      passMsg: 'shared that uses 257 character identifier should fail',
+      passMsg: "error directive using quotes fails",
     },
-*/
+    { vShaderId: 'vshader',
+      vShaderSuccess: true,
+      fShaderId: 'fshaderWithNonASCIIErrorDirective',
+      fShaderSuccess: false,
+      linkSuccess: false,
+      passMsg: "error directive using characters outside of allowed set fails",
+    }
   ];
 
   // Read in all the shader source.
   for (var ii = 0; ii < shaderInfo.length; ++ii) {
     var si = shaderInfo[ii];
     si.vShaderSource = document.getElementById(si.vShaderId).text;
     si.fShaderSource = document.getElementById(si.fShaderId).text;
   }
@@ -543,42 +652,52 @@ if (!gl) {
   addExternalShaders('shaders/00_shaders.txt');
 
   for (var ii = 0; ii < shaderInfo.length; ++ii) {
     var info = shaderInfo[ii];
     var passMsg = '[' + info.vShaderId + '/' + info.fShaderId + ']: ' +
                   info.passMsg
     log(passMsg);
     //debug(info.fShaderId);
-    var vShader = wtu.loadShader(gl, info.vShaderSource, gl.VERTEX_SHADER);
+    var vSource = info.vShaderPrep ? info.vShaderPrep(info.vShaderSource) :
+      info.vShaderSource;
+    var vShader = wtu.loadShader(gl, vSource, gl.VERTEX_SHADER);
     if (info.vShaderTest) {
       if (!info.vShaderTest(vShader)) {
         testFailed(passMsg);
         continue;
       }
     }
     if ((vShader != null) != info.vShaderSuccess) {
       testFailed(passMsg);
       continue;
     }
-    var fShader = wtu.loadShader(gl, info.fShaderSource, gl.FRAGMENT_SHADER);
+    var fSource = info.fShaderPrep ? info.fShaderPrep(info.fShaderSource) :
+      info.fShaderSource;
+    var fShader = wtu.loadShader(gl, fSource, gl.FRAGMENT_SHADER);
+    if (info.fShaderTest) {
+      if (!info.fShaderTest(fShader)) {
+        testFailed(passMsg);
+        continue;
+      }
+    }
     //debug(fShader == null ? "fail" : "succeed");
     if ((fShader != null) != info.fShaderSuccess) {
       testFailed(passMsg);
       continue;
     }
 
     if (vShader && fShader) {
       var program = gl.createProgram();
       gl.attachShader(program, vShader);
       gl.attachShader(program, fShader);
       gl.linkProgram(program);
       var linked = (gl.getProgramParameter(program, gl.LINK_STATUS) != 0);
       if (!linked) {
-        var error = gl.getProgramInfoLog(shader);
+        var error = gl.getProgramInfoLog(program);
         log("*** Error linking program '"+program+"':"+error);
       }
       if (linked != info.linkSuccess) {
         testFailed(passMsg);
         continue;
       }
     } else {
       if (info.linkSuccess) {
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/include.vs
@@ -0,0 +1,4 @@
+// Do not delete!
+// Needed to help glsl-conformance tests.
+
+
--- a/content/canvas/test/webgl/conformance/index-validation.html
+++ b/content/canvas/test/webgl/conformance/index-validation.html
@@ -121,16 +121,18 @@ gl.enableVertexAttribArray(extraLoc);
 debug("Enable an extra attribute with null");
 glErrorShouldBe(gl, gl.NO_ERROR);
 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
 glErrorShouldBe(gl, gl.INVALID_OPERATION);
 debug("Enable an extra attribute with insufficient data buffer");
 gl.vertexAttribPointer(extraLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), 4 * sizeInBytes(gl.FLOAT));
 glErrorShouldBe(gl, gl.NO_ERROR);
 shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
+gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 7 * sizeInBytes(gl.FLOAT), -2000000000 * sizeInBytes(gl.FLOAT));
 glErrorShouldBe(gl, gl.NO_ERROR);
+shouldBeUndefined('gl.drawElements(gl.TRIANGLES, 3, gl.UNSIGNED_SHORT, 0)');
 
 successfullyParsed = true;
 </script>
 
 <script src="../resources/js-test-post.js"></script>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/instanceof-test.html
@@ -0,0 +1,97 @@
+<!--
+Copyright (c) 2009 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+ -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL instanceof test.</title>
+<link rel="stylesheet" href="../resources/js-test-style.css"/>
+<script src="../resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/webgl-test-utils.js"> </script>
+</head>
+<body>
+<canvas id="canvas" width="2" height="2" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+varying vec2 texCoord;
+void main()
+{
+    gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform vec4 color;
+void main()
+{
+    gl_FragColor = color;
+}
+</script>
+<script>
+var wtu = WebGLTestUtils;
+debug("Tests that instanceof works on WebGL objects.");
+debug("");
+var gl = create3DContext(document.getElementById("canvas"));
+shouldBeTrue('gl instanceof WebGLRenderingContext');
+shouldBeTrue('gl.createBuffer() instanceof WebGLBuffer');
+shouldBeTrue('gl.createFramebuffer() instanceof WebGLFramebuffer');
+shouldBeTrue('gl.createProgram() instanceof WebGLProgram');
+shouldBeTrue('gl.createRenderbuffer() instanceof WebGLRenderbuffer');
+shouldBeTrue('gl.createShader(gl.VERTEX_SHADER) instanceof WebGLShader');
+shouldBeTrue('gl.createTexture() instanceof WebGLTexture');
+
+var program = wtu.setupProgram(
+    gl,
+    [wtu.loadShaderFromScript(gl, 'vshader', gl.VERTEX_SHADER),
+     wtu.loadShaderFromScript(gl, 'fshader', gl.FRAGMENT_SHADER)],
+    ['vPosition'], [0]);
+
+shouldBeTrue('gl.getUniformLocation(program, "color") instanceof WebGLUniformLocation');
+shouldBeTrue('gl.getActiveAttrib(program, 0) instanceof WebGLActiveInfo');
+shouldBeTrue('gl.getActiveUniform(program, 0) instanceof WebGLActiveInfo');
+
+debug("");
+debug("Tests that those WebGL objects can not be constructed through new operator");
+debug("");
+
+function shouldThrowWithNew(objectType, objectName)
+{
+    try {
+        new objectType;
+        testFailed('new ' + objectName + ' did not throw');
+    } catch (e) {
+        testPassed('new ' + objectName + ' threw an error');
+    }
+}
+
+shouldThrowWithNew(WebGLRenderingContext, 'WebGLRenderingContext');
+shouldThrowWithNew(WebGLActiveInfo, 'WebGLActiveInfo');
+shouldThrowWithNew(WebGLBuffer, 'WebGLBuffer');
+shouldThrowWithNew(WebGLFramebuffer, 'WebGLFramebuffer');
+shouldThrowWithNew(WebGLProgram, 'WebGLProgram');
+shouldThrowWithNew(WebGLRenderbuffer, 'WebGLRenderbuffer');
+shouldThrowWithNew(WebGLShader, 'WebGLShader');
+shouldThrowWithNew(WebGLTexture, 'WebGLTexture');
+shouldThrowWithNew(WebGLUniformLocation, 'WebGLUniformLocation');
+
+successfullyParsed = true;
+</script>
+</body>
+<script src="../resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
+
+
--- a/content/canvas/test/webgl/conformance/invalid-passed-params.html
+++ b/content/canvas/test/webgl/conformance/invalid-passed-params.html
@@ -33,40 +33,156 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 <div id="description"></div>
 <div id="console"></div>
 
 <script>
 description("Test for invalid passed parameters");
 
 var context = create3DContext();
 
+debug("");
 debug("Test createShader()");
 shouldGenerateGLError(context, context.NO_ERROR, "context.createShader(context.FRAGMENT_SHADER)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.createShader(context.VERTEX_SHADER)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.createShader(0)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.createShader(context.TRIANGLES)");
 
+debug("");
 debug("Test clear()");
 shouldGenerateGLError(context, context.INVALID_VALUE, "context.clear(desktopGL['ACCUM_BUFFER_BIT'])");
 shouldGenerateGLError(context, context.INVALID_VALUE, "context.clear(desktopGL['ACCUM_BUFFER_BIT'] | context.COLOR_BUFFER_BIT)");
 shouldGenerateGLError(context, context.INVALID_VALUE, "context.clear(desktopGL['ACCUM_BUFFER_BIT'] | context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT | context.STENCIL_BUFFER_BIT)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT | context.STENCIL_BUFFER_BIT)");
 
+debug("");
 debug("Test bufferData()");
 var buffer = context.createBuffer();
 shouldGenerateGLError(context, context.NO_ERROR, "context.bindBuffer(context.ARRAY_BUFFER, buffer)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.bufferData(context.ARRAY_BUFFER, 16, context.STREAM_DRAW)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.bufferData(context.ARRAY_BUFFER, 16, context.STATIC_DRAW)");
 shouldGenerateGLError(context, context.NO_ERROR, "context.bufferData(context.ARRAY_BUFFER, 16, context.DYNAMIC_DRAW)");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['STREAM_READ'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['STREAM_COPY'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['STATIC_READ'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['STATIC_COPY'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['DYNAMIC_READ'])");
 shouldGenerateGLError(context, context.INVALID_ENUM, "context.bufferData(context.ARRAY_BUFFER, 16, desktopGL['DYNAMIC_COPY'])");
 
+debug("");
+debug("Test {copy}Tex{Sub}Image2D with negative offset/width/height");
+var tex = context.createTexture();
+var pixels = new Uint8Array(2 * 2 * 4);
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindTexture(context.TEXTURE_2D, tex)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, -16, -16, 0, context.RGBA, context.UNSIGNED_BYTE, null)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.texImage2D(context.TEXTURE_2D, 0, context.RGBA, 16, 16, 0, context.RGBA, context.UNSIGNED_BYTE, null)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.texSubImage2D(context.TEXTURE_2D, 0, -1, -1, 2, 2, context.RGBA, context.UNSIGNED_BYTE, pixels)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.texSubImage2D(context.TEXTURE_2D, 0, 0, 0, -1, -1, context.RGBA, context.UNSIGNED_BYTE, pixels)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.texSubImage2D(context.TEXTURE_2D, 0, 0, 0, 2, 2, context.RGBA, context.UNSIGNED_BYTE, pixels)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, -1, -1, 0)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.copyTexImage2D(context.TEXTURE_2D, 0, context.RGBA, 0, 0, 16, 16, 0)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.copyTexSubImage2D(context.TEXTURE_2D, 0, -1, -1, 0, 0, 2, 2)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, -1, -1)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.copyTexSubImage2D(context.TEXTURE_2D, 0, 0, 0, 0, 0, 2, 2)");
+
+debug("");
+debug("Test renderbufferStorage() with negative width/height");
+var renderbuffer = context.createRenderbuffer();
+shouldGenerateGLError(context, context.NO_ERROR, "context.bindRenderbuffer(context.RENDERBUFFER, renderbuffer)");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.renderbufferStorage(context.RENDERBUFFER, context.RGBA4, -2, -2)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.renderbufferStorage(context.RENDERBUFFER, context.RGBA4, 16, 16)");
+
+debug("");
+debug("Test scissor() with negative width/height");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.scissor(0, 0, -2, -2)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.scissor(0, 0, 16, 16)");
+
+debug("");
+debug("Test viewport() with negative width/height");
+shouldGenerateGLError(context, context.INVALID_VALUE, "context.viewport(0, 0, -2, -2)");
+shouldGenerateGLError(context, context.NO_ERROR, "context.viewport(0, 0, 16, 16)");
+
+debug("");
+debug("Set up a program to test invalid characters");
+var invalidSet = ['"', '$', '`', '@', '\\', "'"];
+var validUniformName = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_1234567890";
+var validAttribName = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+function generateShaderSource(opt_invalidIdentifierChar, opt_invalidCommentChar) {
+  var invalidIdentifierString = "";
+  var invalidCommentString = "";
+  if (opt_invalidIdentifierChar != undefined) {
+    invalidIdentifierString += opt_invalidIdentifierChar;
+  }
+  if (opt_invalidCommentChar != undefined) {
+    invalidCommentString += opt_invalidCommentChar;
+  }
+  return "uniform float " + validUniformName + invalidIdentifierString + ";\n"
+                          + "varying float " + validAttribName + ";\n"
+                          + "void main() {\n"
+                          + validAttribName  + " = " + validUniformName + ";\n"
+                          + "gl_Position = vec4(0.0, 0.0, 0.0, 1.0); }\n";
+                          + "//.+-/*%<>[](){}^|&~=!:;,?# " + invalidCommentString;
+}
+var vShader = context.createShader(context.VERTEX_SHADER);
+context.shaderSource(vShader, generateShaderSource());
+context.compileShader(vShader);
+shouldBe("context.getError()", "context.NO_ERROR");
+var fShader = context.createShader(context.FRAGMENT_SHADER);
+context.shaderSource(fShader, "precision highp float;\n"
+                              + "varying float " + validAttribName + ";\n"
+                              + "void main() {\n"
+                              + "gl_FragColor = vec4(" + validAttribName + ", 0.0, 0.0, 1.0); }");
+context.compileShader(fShader);
+shouldBe("context.getError()", "context.NO_ERROR");
+var program = context.createProgram();
+context.attachShader(program, vShader);
+context.attachShader(program, fShader);
+context.linkProgram(program);
+shouldBeTrue("context.getProgramParameter(program, context.LINK_STATUS)");
+shouldBe("context.getError()", "context.NO_ERROR");
+context.bindAttribLocation(program, 1, validAttribName);
+shouldBe("context.getError()", "context.NO_ERROR");
+context.getAttribLocation(program, validAttribName);
+shouldBe("context.getError()", "context.NO_ERROR");
+context.getUniformLocation(program, validUniformName);
+shouldBe("context.getError()", "context.NO_ERROR");
+
+debug("");
+debug("Test shaderSource() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+  var validShaderSource = generateShaderSource(undefined, invalidSet[i]);
+  context.shaderSource(vShader, validShaderSource);
+  shouldBe("context.getError()", "context.NO_ERROR");
+  var invalidShaderSource = generateShaderSource(invalidSet[i], undefined);
+  context.shaderSource(vShader, invalidShaderSource);
+  shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
+debug("");
+debug("Test bindAttribLocation() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+  var invalidName = validAttribName + invalidSet[i];
+  context.bindAttribLocation(program, 1, invalidName);
+  shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
+debug("");
+debug("Test getAttribLocation() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+  var invalidName = validAttribName + invalidSet[i];
+  context.getAttribLocation(program, invalidName);
+  shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
+debug("");
+debug("Test getUniformLocation() with invalid characters");
+for (var i = 0; i < invalidSet.length; ++i) {
+  var invalidName = validUniformName + invalidSet[i];
+  context.getUniformLocation(program, invalidName);
+  shouldBe("context.getError()", "context.INVALID_VALUE");
+}
+
 debug("")
 successfullyParsed = true;
 </script>
 
 <script src="../resources/js-test-post.js"></script>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/00_test_list.txt
@@ -0,0 +1,48 @@
+conformance/constants.html
+conformance/getContext.html
+conformance/methods.html
+#conformance/quickCheckAPI.html
+conformance/webGLArrays.html
+functions/bindBuffer.html
+functions/bindBufferBadArgs.html
+functions/bindFramebufferLeaveNonZero.html
+functions/bufferData.html
+functions/bufferDataBadArgs.html
+functions/bufferSubData.html
+functions/bufferSubDataBadArgs.html
+functions/copyTexImage2D.html
+functions/copyTexImage2DBadArgs.html
+functions/copyTexSubImage2D.html
+functions/copyTexSubImage2DBadArgs.html
+functions/deleteBufferBadArgs.html
+functions/drawArrays.html
+functions/drawArraysOutOfBounds.html
+functions/drawElements.html
+functions/drawElementsBadArgs.html
+functions/isTests.html
+functions/readPixels.html
+functions/readPixelsBadArgs.html
+functions/texImage2D.html
+functions/texImage2DBadArgs.html
+functions/texImage2DHTML.html
+functions/texImage2DHTMLBadArgs.html
+functions/texSubImage2D.html
+functions/texSubImage2DBadArgs.html
+functions/texSubImage2DHTML.html
+functions/texSubImage2DHTMLBadArgs.html
+functions/uniformf.html
+functions/uniformfBadArgs.html
+functions/uniformfArrayLen1.html
+functions/uniformi.html
+functions/uniformiBadArgs.html
+functions/uniformMatrix.html
+functions/uniformMatrixBadArgs.html
+functions/vertexAttrib.html
+functions/vertexAttribBadArgs.html
+functions/vertexAttribPointer.html
+functions/vertexAttribPointerBadArgs.html
+glsl/arrayOutOfBounds.html
+#glsl/longLoops.html // No interactive tests.
+glsl/uniformOutOfBounds.html
+#glsl/unusedAttribsUniforms.html // No interactive tests.
+
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/README.md
@@ -0,0 +1,53 @@
+Tests for the WebGL canvas context
+==================================
+
+These tests are intended to serve the following purposes:
+
+  * Assert spec conformance
+  * Check the safety of the GL binding (bounds checking, same origin policy)
+  * Provide performance numbers for developers
+
+
+Running the tests
+-----------------
+
+  1. <a href="http://learningwebgl.com/blog/?p=11">Install a browser with WebGL support</a>
+  2. Run <code>ruby gen_tests.rb</code> if you have modified the tests.
+  3. Run <code>ruby test_server.rb</code> if you want to get test run output to test_server's stdout (especially useful for finding out which test crashed your browser.)
+  4. Open all_tests.html in your browser.
+
+
+Want to contribute?
+-------------------
+
+  1. Fork this repo
+  2. Run <code>gen_tests.rb</code>
+  3. Look into templates/ to see which functions lack tests (also see <a href="../raw/master/methods.txt">methods.txt</a> and <a href="http://mxr.mozilla.org/mozilla-central/source/dom/interfaces/canvas/nsICanvasRenderingContextWebGL.idl">nsICanvasRenderingContextWebGL.idl</a>):
+    1. copy methodName.html to functions/methodName.html and write tests that test the results of valid inputs.
+    2. copy methodNameBadArgs.html to functions/methodNameBadArgs.html and write tests to assert that invalid inputs throw exceptions.
+    3. If your test causes a segfault, add the following to the top of the script tag: <code>Tests.autorun = false; Tests.message = "Caution: this may crash your browser";</code>
+  4. For each performance test:
+    1. Write a performance/myTestName.html and set <code>Tests.autorun = false;</code>
+  5. If you have a test that you would like to run over the whole API or want to generate tests programmatically, add them to gen_tests.rb or write your own script.
+  6. Create a commit for each file. (E.g. <code>for f in $(git status | grep -e "^#\\s*functions/\\S*$" | sed "s/^#\s*//"); do git add $f; git commit -m $f; done</code>)
+  7. Send me a pull request.
+  8. Congratulations, you're now a contributor!
+
+
+For more information on WebGL:
+
+  * <a href="http://planet-webgl.org">Planet WebGL</a>
+  * <a href="http://learningwebgl.com">Learning WebGL</a>
+  * <a href="http://www.khronos.org/message_boards/viewforum.php?f=34">WebGL on Khronos Message Boards</a>
+
+Developer links:
+
+  * <a href="https://bugzilla.mozilla.org/buglist.cgi?quicksearch=webgl">WebGL on Mozilla Bugzilla</a>
+  * <a href="https://bugzilla.webkit.org/buglist.cgi?quicksearch=webgl">WebGL on WebKit Bugzilla</a>
+  * <a href="http://code.google.com/p/chromium/issues/list?q=label:3D-WebGL">WebGL on Chromium Bugzilla</a>
+
+What's the stuff in apigen?
+
+  There are some Python scripts in the apigen/ directory that generate C++ based on the API definition files (gl2.h, api_modifications.txt, valid_args.txt.) The generated code is Mozilla XPCOM functions that check their args against the valid GLES 2.0 constants (as they were written on the man pages.) There's also some wackier stuff for checking copyTexImage2D and copyTexSubImage2D image dimensions against viewport dimensions.
+
+  If you can use it to generate code for your WebGL implementation, it might save you 1500 lines of typing and testing. The last time I used it was summer 2009 to generate a patch for Canvas 3D, so it's likely somewhat out of date.
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/all_tests.html
@@ -0,0 +1,399 @@
+<html>
+<head>
+<!--
+Tests for the OpenGL ES 2.0 HTML Canvas context
+
+Copyright (C) 2009  Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+-->
+  <title>OpenGL ES 2.0 &lt;canvas&gt; context tests</title>
+  <style type="text/css">
+    h2 { display: inline; font-size: 1em; margin-bottom: 0.2em; }
+    iframe { display: inline; border: 1px solid black; overflow: hidden;}
+  </style>
+  <script type="text/javascript">
+    function loadTest(id, url) {
+      document.getElementById(id).src = url;
+    }
+    function seqLoader() {
+      var iframes = document.getElementsByTagName('iframe');
+      for (var i=0; i<iframes.length; i++) {
+        iframes[i].addEventListener('load', (function(j) {
+          return function() {
+            var e = document.getElementById((j+1)+'_link');
+            if (e) loadTest(j+1, e.href);
+          }
+        })(i), false);
+      }
+      var e = document.getElementById('0_link');
+      if (e) loadTest(0, e.href);
+    }
+  </script>
+</head>
+<body onload="seqLoader()">
+
+    <div>
+      <iframe src="conformance/badArgsArityLessThanArgc.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/badArgsArityLessThanArgc.html">conformance/badArgsArityLessThanArgc.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/constants.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/constants.html">conformance/constants.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/fuzzTheAPI.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/fuzzTheAPI.html">conformance/fuzzTheAPI.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/getContext.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/getContext.html">conformance/getContext.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/methods.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/methods.html">conformance/methods.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/quickCheckAPI.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/quickCheckAPI.html">conformance/quickCheckAPI.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/quickCheckAPIBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/quickCheckAPIBadArgs.html">conformance/quickCheckAPIBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="conformance/webGLArrays.html" width="110" height="42"></iframe>
+      <h2><a href="conformance/webGLArrays.html">conformance/webGLArrays.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bindBuffer.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bindBuffer.html">functions/bindBuffer.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bindBufferBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bindBufferBadArgs.html">functions/bindBufferBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bindFramebufferLeaveNonZero.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bindFramebufferLeaveNonZero.html">functions/bindFramebufferLeaveNonZero.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bufferData.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bufferData.html">functions/bufferData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bufferDataBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bufferDataBadArgs.html">functions/bufferDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bufferSubData.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bufferSubData.html">functions/bufferSubData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/bufferSubDataBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/bufferSubDataBadArgs.html">functions/bufferSubDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/copyTexImage2D.html" width="110" height="42"></iframe>
+      <h2><a href="functions/copyTexImage2D.html">functions/copyTexImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/copyTexImage2DBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/copyTexImage2DBadArgs.html">functions/copyTexImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/copyTexSubImage2D.html" width="110" height="42"></iframe>
+      <h2><a href="functions/copyTexSubImage2D.html">functions/copyTexSubImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/copyTexSubImage2DBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/copyTexSubImage2DBadArgs.html">functions/copyTexSubImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/deleteBufferBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/deleteBufferBadArgs.html">functions/deleteBufferBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/drawArrays.html" width="110" height="42"></iframe>
+      <h2><a href="functions/drawArrays.html">functions/drawArrays.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/drawArraysOutOfBounds.html" width="110" height="42"></iframe>
+      <h2><a href="functions/drawArraysOutOfBounds.html">functions/drawArraysOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/drawElements.html" width="110" height="42"></iframe>
+      <h2><a href="functions/drawElements.html">functions/drawElements.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/drawElementsBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/drawElementsBadArgs.html">functions/drawElementsBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/getImageData.html" width="110" height="42"></iframe>
+      <h2><a href="functions/getImageData.html">functions/getImageData.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/getImageDataBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/getImageDataBadArgs.html">functions/getImageDataBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/isTests.html" width="110" height="42"></iframe>
+      <h2><a href="functions/isTests.html">functions/isTests.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/linkProgramBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/linkProgramBadArgs.html">functions/linkProgramBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/readPixels.html" width="110" height="42"></iframe>
+      <h2><a href="functions/readPixels.html">functions/readPixels.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/readPixelsBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/readPixelsBadArgs.html">functions/readPixelsBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texImage2D.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texImage2D.html">functions/texImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texImage2DBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texImage2DBadArgs.html">functions/texImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texImage2DHTML.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texImage2DHTML.html">functions/texImage2DHTML.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texImage2DHTMLBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texImage2DHTMLBadArgs.html">functions/texImage2DHTMLBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texSubImage2D.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texSubImage2D.html">functions/texSubImage2D.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texSubImage2DBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texSubImage2DBadArgs.html">functions/texSubImage2DBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texSubImage2DHTML.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texSubImage2DHTML.html">functions/texSubImage2DHTML.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/texSubImage2DHTMLBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/texSubImage2DHTMLBadArgs.html">functions/texSubImage2DHTMLBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformMatrix.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformMatrix.html">functions/uniformMatrix.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformMatrixBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformMatrixBadArgs.html">functions/uniformMatrixBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformf.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformf.html">functions/uniformf.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformfBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformfBadArgs.html">functions/uniformfBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformi.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformi.html">functions/uniformi.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/uniformiBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/uniformiBadArgs.html">functions/uniformiBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/vertexAttrib.html" width="110" height="42"></iframe>
+      <h2><a href="functions/vertexAttrib.html">functions/vertexAttrib.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/vertexAttribBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/vertexAttribBadArgs.html">functions/vertexAttribBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/vertexAttribPointer.html" width="110" height="42"></iframe>
+      <h2><a href="functions/vertexAttribPointer.html">functions/vertexAttribPointer.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="functions/vertexAttribPointerBadArgs.html" width="110" height="42"></iframe>
+      <h2><a href="functions/vertexAttribPointerBadArgs.html">functions/vertexAttribPointerBadArgs.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/CPUvsGPU.html" width="110" height="42"></iframe>
+      <h2><a href="performance/CPUvsGPU.html">performance/CPUvsGPU.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/bandwidth.html" width="110" height="42"></iframe>
+      <h2><a href="performance/bandwidth.html">performance/bandwidth.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/jsGCPause.html" width="110" height="42"></iframe>
+      <h2><a href="performance/jsGCPause.html">performance/jsGCPause.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/jsMatrixMult.html" width="110" height="42"></iframe>
+      <h2><a href="performance/jsMatrixMult.html">performance/jsMatrixMult.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="performance/jsToGLOverhead.html" width="110" height="42"></iframe>
+      <h2><a href="performance/jsToGLOverhead.html">performance/jsToGLOverhead.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="glsl/arrayOutOfBounds.html" width="110" height="42"></iframe>
+      <h2><a href="glsl/arrayOutOfBounds.html">glsl/arrayOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="glsl/longLoops.html" width="110" height="42"></iframe>
+      <h2><a href="glsl/longLoops.html">glsl/longLoops.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="glsl/uniformOutOfBounds.html" width="110" height="42"></iframe>
+      <h2><a href="glsl/uniformOutOfBounds.html">glsl/uniformOutOfBounds.html</a></h2>
+    </div>
+    
+
+    <div>
+      <iframe src="glsl/unusedAttribsUniforms.html" width="110" height="42"></iframe>
+      <h2><a href="glsl/unusedAttribsUniforms.html">glsl/unusedAttribsUniforms.html</a></h2>
+    </div>
+    
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/test/webgl/conformance/more/all_tests_linkonly.html
@@ -0,0 +1,399 @@
+<html>
+<head>
+<!--
+Tests for the OpenGL ES 2.0 HTML Canvas context
+
+Copyright (C) 2009  Ilmari Heikkinen <ilmari.heikkinen@gmail.com>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+-->
+  <title>OpenGL ES 2.0 &lt;canvas&gt; context tests</title>
+  <style type="text/css">
+    h2 { display: inline; font-size: 1em; margin-bottom: 0.2em; }
+    iframe { display: inline; border: 1px solid black; overflow: hidden;}
+  </style>
+  <script type="text/javascript">
+    function loadTest(id, url) {
+      document.getElementById(id).src = url;
+    }
+    function seqLoader() {
+      var iframes = document.getElementsByTagName('iframe');
+      for (var i=0; i<iframes.length; i++) {
+        iframes[i].addEventListener('load', (function(j) {
+          return function() {
+            var e = document.getElementById((j+1)+'_link');
+            if (e) loadTest(j+1, e.href);