Merge services-central with mozilla-central
authorPhilipp von Weitershausen <philipp@weitershausen.de>
Tue, 26 Apr 2011 21:33:22 -0700
changeset 68779 47694c46262268e008799d0a5f55ac9dfb4badac
parent 68778 7430b446a8663dc7567a130f732e18adab8c9515 (current diff)
parent 68753 e7cf36e1264391f87cfc0f641be6d7c41c0d8a10 (diff)
child 68780 83e8315c5f69d1a1119fb4351f73f2c2e1598309
push id99
push usereakhgari@mozilla.com
push dateTue, 24 May 2011 18:03:59 +0000
treeherdermozilla-aurora@26d6981b3d6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone6.0a1
Merge services-central with mozilla-central
js/landbranch.pl
js/src/Makefile.ref
js/src/config.mk
js/src/jit-test/tests/basic/bug630865-1.js
js/src/jit-test/tests/basic/bug630865-2.js
js/src/jit-test/tests/basic/bug630865-3.js
js/src/jit-test/tests/basic/bug630865-4.js
js/src/jsconfig.mk
js/src/methodjit/InlineFrameAssembler.h
js/src/ref-config/AIX4.1.mk
js/src/ref-config/AIX4.2.mk
js/src/ref-config/AIX4.3.mk
js/src/ref-config/Darwin.mk
js/src/ref-config/Darwin1.3.mk
js/src/ref-config/Darwin1.4.mk
js/src/ref-config/Darwin5.2.mk
js/src/ref-config/Darwin5.3.mk
js/src/ref-config/Darwin64.mk
js/src/ref-config/HP-UXB.10.10.mk
js/src/ref-config/HP-UXB.10.20.mk
js/src/ref-config/HP-UXB.11.00.mk
js/src/ref-config/HP-UXB.11.31.mk
js/src/ref-config/IRIX.mk
js/src/ref-config/IRIX5.3.mk
js/src/ref-config/IRIX6.1.mk
js/src/ref-config/IRIX6.2.mk
js/src/ref-config/IRIX6.3.mk
js/src/ref-config/IRIX6.5.mk
js/src/ref-config/Linux_All.mk
js/src/ref-config/Mac_OS10.0.mk
js/src/ref-config/OSF1V4.0.mk
js/src/ref-config/OSF1V5.0.mk
js/src/ref-config/SunOS4.1.4.mk
js/src/ref-config/SunOS5.10.mk
js/src/ref-config/SunOS5.3.mk
js/src/ref-config/SunOS5.4.mk
js/src/ref-config/SunOS5.5.1.mk
js/src/ref-config/SunOS5.5.mk
js/src/ref-config/SunOS5.6.mk
js/src/ref-config/SunOS5.7.mk
js/src/ref-config/SunOS5.8.mk
js/src/ref-config/SunOS5.9.mk
js/src/ref-config/WINNT4.0.mk
js/src/ref-config/WINNT5.0.mk
js/src/ref-config/WINNT5.1.mk
js/src/ref-config/WINNT5.2.mk
js/src/ref-config/WINNT6.0.mk
js/src/ref-config/dgux.mk
js/src/rules.mk
toolkit/components/url-classifier/nsUrlClassifierHashCompleter.cpp
toolkit/components/url-classifier/nsUrlClassifierHashCompleter.h
--- a/accessible/src/atk/nsMaiInterfaceComponent.cpp
+++ b/accessible/src/atk/nsMaiInterfaceComponent.cpp
@@ -40,16 +40,18 @@
 
 #include "nsMaiInterfaceComponent.h"
 
 #include "nsAccessibleWrap.h"
 #include "nsAccUtils.h"
 #include "nsCoreUtils.h"
 
 #include "nsIDOMDocument.h"
+#include "nsIDOMDocumentView.h"
+#include "nsIDOMAbstractView.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIInterfaceRequestorUtils.h"
 
 void
 componentInterfaceInitCB(AtkComponentIface *aIface)
 {
     NS_ASSERTION(aIface, "Invalid Interface");
--- a/accessible/src/base/nsCoreUtils.cpp
+++ b/accessible/src/base/nsCoreUtils.cpp
@@ -38,22 +38,25 @@
 
 #include "nsCoreUtils.h"
 
 #include "nsIAccessibleTypes.h"
 
 #include "nsAccessNode.h"
 
 #include "nsIDocument.h"
+#include "nsIDOMAbstractView.h"
 #include "nsIDOM3Node.h"
 #include "nsIDOMDocument.h"
+#include "nsIDOMDocumentView.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMRange.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDocShell.h"
 #include "nsIContentViewer.h"
 #include "nsIEventListenerManager.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIScrollableFrame.h"
@@ -417,22 +420,23 @@ nsCoreUtils::GetScreenCoordsForWindow(ns
   nsIntPoint coords(0, 0);
   nsCOMPtr<nsIDocShellTreeItem> treeItem(GetDocShellTreeItemFor(aNode));
   if (!treeItem)
     return coords;
 
   nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
   treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
   nsCOMPtr<nsIDOMDocument> domDoc = do_GetInterface(rootTreeItem);
-  if (!domDoc)
+  nsCOMPtr<nsIDOMDocumentView> docView(do_QueryInterface(domDoc));
+  if (!docView)
     return coords;
 
-  nsCOMPtr<nsIDOMWindow> window;
-  domDoc->GetDefaultView(getter_AddRefs(window));
-  nsCOMPtr<nsIDOMWindowInternal> windowInter(do_QueryInterface(window));
+  nsCOMPtr<nsIDOMAbstractView> abstractView;
+  docView->GetDefaultView(getter_AddRefs(abstractView));
+  nsCOMPtr<nsIDOMWindowInternal> windowInter(do_QueryInterface(abstractView));
   if (!windowInter)
     return coords;
 
   windowInter->GetScreenX(&coords.x);
   windowInter->GetScreenY(&coords.y);
   return coords;
 }
 
@@ -588,24 +592,24 @@ nsCoreUtils::GetComputedStyleDeclaration
   if (!content)
     return nsnull;
 
   // Returns number of items in style declaration
   nsIDocument* document = content->GetOwnerDoc();
   if (!document)
     return nsnull;
 
-  nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(document->GetWindow());
-  if (!window)
+  nsCOMPtr<nsIDOMViewCSS> viewCSS(do_QueryInterface(document->GetWindow()));
+  if (!viewCSS)
     return nsnull;
 
-  nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
+  nsIDOMCSSStyleDeclaration* cssDecl = nsnull;
   nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(content));
-  window->GetComputedStyle(domElement, aPseudoElt, getter_AddRefs(cssDecl));
-  return cssDecl.forget();
+  viewCSS->GetComputedStyle(domElement, aPseudoElt, &cssDecl);
+  return cssDecl;
 }
 
 already_AddRefed<nsIBoxObject>
 nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj)
 {
   nsCOMPtr<nsIDOMElement> tcElm;
   aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm));
   nsCOMPtr<nsIDOMXULElement> tcXULElm(do_QueryInterface(tcElm));
--- a/accessible/src/html/nsHyperTextAccessible.cpp
+++ b/accessible/src/html/nsHyperTextAccessible.cpp
@@ -42,19 +42,21 @@
 #include "States.h"
 #include "nsAccessibilityAtoms.h"
 #include "nsAccessibilityService.h"
 #include "nsAccUtils.h"
 #include "nsTextAttrs.h"
 
 #include "nsIClipboard.h"
 #include "nsContentCID.h"
+#include "nsIDOMAbstractView.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMDocument.h"
 #include "nsPIDOMWindow.h"        
+#include "nsIDOMDocumentView.h"
 #include "nsIDOMRange.h"
 #include "nsIDOMNSRange.h"
 #include "nsIDOMWindowInternal.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIEditingSession.h"
 #include "nsIEditor.h"
 #include "nsIFrame.h"
 #include "nsFrameSelection.h"
--- a/accessible/src/msaa/nsAccessNodeWrap.cpp
+++ b/accessible/src/msaa/nsAccessNodeWrap.cpp
@@ -47,16 +47,17 @@
 #include "nsCoreUtils.h"
 #include "nsRootAccessible.h"
 #include "nsWinUtils.h"
 
 #include "nsAttrName.h"
 #include "nsIDocument.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMNSHTMLElement.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIFrame.h"
 #include "nsINameSpaceManager.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsPIDOMWindow.h"
 #include "nsIServiceManager.h"
 
 /// the accessible library and cached methods
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -71,20 +71,19 @@ pref("extensions.blocklist.level", 2);
 pref("extensions.blocklist.url", "https://addons.mozilla.org/blocklist/3/%APP_ID%/%APP_VERSION%/%PRODUCT%/%BUILD_ID%/%BUILD_TARGET%/%LOCALE%/%CHANNEL%/%OS_VERSION%/%DISTRIBUTION%/%DISTRIBUTION_VERSION%/%PING_COUNT%/%TOTAL_PING_COUNT%/%DAYS_SINCE_LAST_PING%/");
 pref("extensions.blocklist.detailsURL", "https://www.mozilla.com/%LOCALE%/blocklist/");
 
 pref("extensions.update.autoUpdateDefault", true);
 
 // Dictionary download preference
 pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/%APP%/dictionaries/");
 
-// Update Timer Manager preferences
-// Interval: When all registered timers should be checked (in milliseconds)
-//           default=10 minutes
-pref("app.update.timer", 600000);
+// The minimum delay in seconds for the timer to fire.
+// default=2 minutes
+pref("app.update.timerMinimumDelay", 120);
 
 // App-specific update preferences
 
 // The interval to check for updates (app.update.interval) is defined in
 // firefox-branding.js
 
 // Alternative windowtype for an application update user interface window. When
 // a window with this windowtype is open the application update service won't
--- a/browser/base/content/aboutDialog.css
+++ b/browser/base/content/aboutDialog.css
@@ -1,69 +1,26 @@
 #aboutDialog {
   width: 620px;
 }
 
-/* Official branding has Firefox logo on the left side of the window. 
-   Nightly/aurora branding has background image applied to entire window. */
-%ifdef MOZ_OFFICIAL_BRANDING
-#clientBox {
-  background-color: #F7F7F7;
-  color: #222222;
-}
-%else
-#aboutDialogContainer {
-  background-image: url("chrome://branding/content/about-background.png");
-  background-repeat: no-repeat;
-  background-color: #000;
-  color: #fff;
-}
-
-.text-link {
-  color: #fff !important;
-}
-%endif
-
-%ifdef MOZ_OFFICIAL_BRANDING
-#leftBox {
-  background-image: url("chrome://branding/content/about-logo.png");
-  background-repeat: no-repeat;
-  /* min-width and min-height create room for the logo */
-  min-width: 210px;
-  min-height: 210px;
-  margin-top:20px;
-  -moz-margin-start: 30px;
-}
-%endif
-
 #rightBox {
   background-image: url("chrome://branding/content/about-wordmark.png");
   background-repeat: no-repeat;
   /* padding-top creates room for the wordmark */
   padding-top: 38px;
   margin-top:20px;
-%ifdef MOZ_OFFICIAL_BRANDING
-  margin-left: 30px;
-  margin-right: 30px;
-%else 
-  /* this margin prevents text from overlapping the planet image */
-  margin-left: 280px;
-  margin-right: 20px;
-%endif
 }
 
 #rightBox:-moz-locale-dir(rtl) {
   background-position: 100% 0;
 }
 
 #bottomBox {
   padding: 15px 10px 0;
-%ifndef MOZ_OFFICIAL_BRANDING
-  background-color: rgba(0,0,0,.7);
-%endif
 }
 
 #version {
   margin-top: 10px;
   -moz-margin-start: 0;
 }
 
 #distribution,
@@ -82,19 +39,16 @@
 
 #updateButton,
 #updateDeck > hbox > label {
   -moz-margin-start: 0;
   -moz-padding-start: 0;
 }
 
 #updateDeck > hbox > label:not([class="text-link"]) {
-%ifdef MOZ_OFFICIAL_BRANDING
-  color: #909090;
-%endif
   font-style:italic;
 }
 
 .update-throbber {
   width: 16px;
   min-height: 16px;
   -moz-margin-end: 3px;
   list-style-image: url("chrome://global/skin/icons/loading_16.png");
@@ -108,27 +62,16 @@
 }
 
 .bottom-link,
 .bottom-link:focus {
   text-align: center;
   margin: 0 40px;
 }
 
-/* we assume trademark text only appears in offical builds */
-%ifdef MOZ_OFFICIAL_BRANDING
-#trademark {
-  font-size: xx-small;
-  text-align: center;
-  color: #999999;
-  margin-top: 10px;
-  margin-bottom: 10px;
-}
-%endif
-
 #currentChannel {
   margin: 0;
   padding: 0;
   font-weight: bold;
 }
 
 #channelSelector {
   margin-top: 10px;
--- a/browser/base/content/aboutDialog.xul
+++ b/browser/base/content/aboutDialog.xul
@@ -36,16 +36,17 @@
 # and other provisions required by the LGPL or the GPL. 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 ***** -->
 
 <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/aboutDialog.css" type="text/css"?>
+<?xml-stylesheet href="chrome://branding/content/aboutDialog.css" type="text/css"?>
 
 <!DOCTYPE window [
 <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
 %brandDTD;
 <!ENTITY % aboutDialogDTD SYSTEM "chrome://browser/locale/aboutDialog.dtd" >
 %aboutDialogDTD;
 ]>
 
new file mode 100644
--- /dev/null
+++ b/browser/branding/aurora/content/aboutDialog.css
@@ -0,0 +1,20 @@
+#aboutDialogContainer {
+  background-image: url("chrome://branding/content/about-background.png");
+  background-repeat: no-repeat;
+  background-color: #000;
+  color: #fff;
+}
+
+.text-link {
+  color: #fff !important;
+}
+
+#rightBox {
+  /* this margin prevents text from overlapping the planet image */
+  margin-left: 280px;
+  margin-right: 20px;
+}
+
+#bottomBox {
+  background-color: rgba(0,0,0,.7);
+}
--- a/browser/branding/aurora/content/jar.mn
+++ b/browser/branding/aurora/content/jar.mn
@@ -3,8 +3,9 @@ browser.jar:
   content/branding/about.png                     (about.png)
   content/branding/about-background.png          (about-background.png)
   content/branding/about-logo.png                (about-logo.png)
   content/branding/about-wordmark.png            (about-wordmark.png)
   content/branding/icon48.png                    (icon48.png)
   content/branding/icon64.png                    (icon64.png)
   content/branding/icon128.png                   (../mozicon128.png)
   content/branding/icon16.png                    (../default16.png)
+  content/branding/aboutDialog.css               (aboutDialog.css)
new file mode 100644
--- /dev/null
+++ b/browser/branding/nightly/content/aboutDialog.css
@@ -0,0 +1,20 @@
+#aboutDialogContainer {
+  background-image: url("chrome://branding/content/about-background.png");
+  background-repeat: no-repeat;
+  background-color: #000;
+  color: #fff;
+}
+
+.text-link {
+  color: #fff !important;
+}
+
+#rightBox {
+  /* this margin prevents text from overlapping the planet image */
+  margin-left: 280px;
+  margin-right: 20px;
+}
+
+#bottomBox {
+  background-color: rgba(0,0,0,.7);
+}
--- a/browser/branding/nightly/content/jar.mn
+++ b/browser/branding/nightly/content/jar.mn
@@ -3,8 +3,9 @@ browser.jar:
   content/branding/about.png                     (about.png)
   content/branding/about-background.png          (about-background.png)
   content/branding/about-logo.png                (about-logo.png)
   content/branding/about-wordmark.png            (about-wordmark.png)
   content/branding/icon48.png                    (icon48.png)
   content/branding/icon64.png                    (icon64.png)
   content/branding/icon128.png                   (../mozicon128.png)
   content/branding/icon16.png                    (../default16.png)
+  content/branding/aboutDialog.css               (aboutDialog.css)
new file mode 100644
--- /dev/null
+++ b/browser/branding/official/content/aboutDialog.css
@@ -0,0 +1,31 @@
+#clientBox {
+  background-color: #F7F7F7;
+  color: #222222;
+}
+
+#leftBox {
+  background-image: url("chrome://branding/content/about-logo.png");
+  background-repeat: no-repeat;
+  /* min-width and min-height create room for the logo */
+  min-width: 210px;
+  min-height: 210px;
+  margin-top:20px;
+  -moz-margin-start: 30px;
+}
+
+#rightBox {
+  margin-left: 30px;
+  margin-right: 30px;
+}
+
+#updateDeck > hbox > label:not([class="text-link"]) {
+  color: #909090;
+}
+
+#trademark {
+  font-size: xx-small;
+  text-align: center;
+  color: #999999;
+  margin-top: 10px;
+  margin-bottom: 10px;
+}
--- a/browser/branding/official/content/jar.mn
+++ b/browser/branding/official/content/jar.mn
@@ -2,8 +2,9 @@ browser.jar:
 % content branding %content/branding/ contentaccessible=yes
   content/branding/about.png                     (about.png)
   content/branding/about-logo.png                (about-logo.png)
   content/branding/about-wordmark.png            (about-wordmark.png)
   content/branding/icon48.png                    (icon48.png)
   content/branding/icon64.png                    (icon64.png)
   content/branding/icon128.png                   (../mozicon128.png)
   content/branding/icon16.png                    (../default16.png)
+  content/branding/aboutDialog.css               (aboutDialog.css)
new file mode 100644
--- /dev/null
+++ b/browser/branding/unofficial/content/aboutDialog.css
@@ -0,0 +1,20 @@
+#aboutDialogContainer {
+  background-image: url("chrome://branding/content/about-background.png");
+  background-repeat: no-repeat;
+  background-color: #000;
+  color: #fff;
+}
+
+.text-link {
+  color: #fff !important;
+}
+
+#rightBox {
+  /* this margin prevents text from overlapping the planet image */
+  margin-left: 280px;
+  margin-right: 20px;
+}
+
+#bottomBox {
+  background-color: rgba(0,0,0,.7);
+}
--- a/browser/branding/unofficial/content/jar.mn
+++ b/browser/branding/unofficial/content/jar.mn
@@ -3,8 +3,9 @@ browser.jar:
   content/branding/about.png                     (about.png)
   content/branding/about-background.png          (about-background.png)
   content/branding/about-logo.png                (about-logo.png)
   content/branding/about-wordmark.png            (about-wordmark.png)
   content/branding/icon48.png                    (icon48.png)
   content/branding/icon64.png                    (icon64.png)
   content/branding/icon128.png                   (../mozicon128.png)
   content/branding/icon16.png                    (../default16.png)
+  content/branding/aboutDialog.css               (aboutDialog.css)
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -386,16 +386,17 @@
 
 ; Modules
 @BINPATH@/modules/*
 
 ; Safe Browsing
 @BINPATH@/components/nsSafebrowsingApplication.manifest
 @BINPATH@/components/nsSafebrowsingApplication.js
 @BINPATH@/components/nsURLClassifier.manifest
+@BINPATH@/components/nsUrlClassifierHashCompleter.js
 @BINPATH@/components/nsUrlClassifierListManager.js
 @BINPATH@/components/nsUrlClassifierLib.js
 @BINPATH@/components/url-classifier.xpt
 
 ; GNOME hooks
 #ifdef MOZ_ENABLE_GNOME_COMPONENT
 @BINPATH@/components/@DLL_PREFIX@mozgnome@DLL_SUFFIX@
 #endif
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -359,16 +359,17 @@ user_pref("gfx.color_management.force_sr
 user_pref("network.manage-offline-status", false);
 user_pref("test.mousescroll", true);
 user_pref("security.default_personal_cert", "Select Automatically"); // Need to client auth test be w/o any dialogs
 user_pref("network.http.prompt-temp-redirect", false);
 user_pref("media.cache_size", 100);
 user_pref("security.warn_viewing_mixed", false);
 user_pref("app.update.enabled", false);
 user_pref("browser.panorama.experienced_first_run", true); // Assume experienced
+user_pref("dom.w3c_touch_events.enabled", true);
 
 // Only load extensions from the application and user profile
 // AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
 user_pref("extensions.enabledScopes", 5);
 // Disable metadata caching for installed add-ons by default
 user_pref("extensions.getAddons.cache.enabled", false);
 // Disable intalling any distribution add-ons
 user_pref("extensions.installDistroAddons", false);
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -84,9 +84,9 @@ 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
 load 642022-1.html
-asserts(1) load 646184.html # Bug 651842
+load 646184.html
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1766,16 +1766,21 @@ public:
       TYPE_PLUGIN,
       TYPE_UNKNOWN
   };
 
   static already_AddRefed<nsIDocumentLoaderFactory>
   FindInternalContentViewer(const char* aType,
                             ContentViewerType* aLoaderType = nsnull);
 
+  /**
+   * Calling this adds support for
+   * ontouch* event handler DOM attributes.
+   */
+  static void InitializeTouchEventTable();
 private:
   static PRBool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
 
   static nsresult HoldScriptObject(PRUint32 aLangID, void* aObject);
--- a/content/base/src/nsContentAreaDragDrop.cpp
+++ b/content/base/src/nsContentAreaDragDrop.cpp
@@ -49,16 +49,17 @@
 #include "nsIDOMNSUIEvent.h"
 #include "nsIDOMUIEvent.h"
 #include "nsISelection.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMDragEvent.h"
+#include "nsIDOMAbstractView.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentRange.h"
 #include "nsIDOMRange.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLAreaElement.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsITransferable.h"
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -610,29 +610,19 @@ nsContentList::NamedItem(const nsAString
 }
 
 nsIContent*
 nsContentList::GetNodeAt(PRUint32 aIndex)
 {
   return Item(aIndex, PR_TRUE);
 }
 
-nsIContent*
-nsContentList::GetNodeAt(PRUint32 aIndex, nsresult* aResult)
+nsISupports*
+nsContentList::GetNamedItem(const nsAString& aName, nsWrapperCache **aCache)
 {
-  *aResult = NS_OK;
-  return Item(aIndex, PR_TRUE);
-}
-
-nsISupports*
-nsContentList::GetNamedItem(const nsAString& aName, nsWrapperCache **aCache,
-                            nsresult* aResult)
-{
-  *aResult = NS_OK;
-
   nsIContent *item;
   *aCache = item = NamedItem(aName, PR_TRUE);
   return item;
 }
 
 void
 nsContentList::AttributeChanged(nsIDocument *aDocument, Element* aElement,
                                 PRInt32 aNameSpaceID, nsIAtom* aAttribute,
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -255,20 +255,19 @@ public:
   NS_DECL_NSIDOMHTMLCOLLECTION
 
   // nsBaseContentList overrides
   virtual PRInt32 IndexOf(nsIContent *aContent, PRBool aDoFlush);
   virtual nsIContent* GetNodeAt(PRUint32 aIndex);
   virtual PRInt32 IndexOf(nsIContent* aContent);
 
   // nsIHTMLCollection
-  virtual nsIContent* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
+  // GetNodeAt already declared as part of nsINodeList
   virtual nsISupports* GetNamedItem(const nsAString& aName,
-                                    nsWrapperCache** aCache,
-                                    nsresult* aResult);
+                                    nsWrapperCache** aCache);
 
   // nsContentList public methods
   NS_HIDDEN_(nsINode*) GetParentObject() { return mRootNode; }
   NS_HIDDEN_(PRUint32) Length(PRBool aDoFlush);
   NS_HIDDEN_(nsIContent*) Item(PRUint32 aIndex, PRBool aDoFlush);
   NS_HIDDEN_(nsIContent*) NamedItem(const nsAString& aName, PRBool aDoFlush);
 
   // nsIMutationObserver
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -163,16 +163,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsIChannelEventSink.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIOfflineCacheUpdate.h"
 #include "nsCPrefetchService.h"
 #include "nsIChromeRegistry.h"
 #include "nsIMIMEHeaderParam.h"
 #include "nsIDOMXULCommandEvent.h"
+#include "nsIDOMAbstractView.h"
 #include "nsIDOMDragEvent.h"
 #include "nsDOMDataTransfer.h"
 #include "nsHtml5Module.h"
 #include "nsPresContext.h"
 #include "nsLayoutStatics.h"
 #include "nsLayoutUtils.h"
 #include "nsFrameManager.h"
 #include "BasicLayers.h"
@@ -204,16 +205,17 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_
 #include "nsScriptSecurityManager.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentDLF.h"
 #ifdef MOZ_MEDIA
 #include "nsHTMLMediaElement.h"
 #endif
+#include "nsDOMTouchEvent.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::layers;
 
 const char kLoadAsData[] = "loadAsData";
 
 static const char kJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
 static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
@@ -720,16 +722,45 @@ nsContentUtils::InitializeEventTable() {
       sStringEventTable = nsnull;
       return PR_FALSE;
     }
   }
 
   return PR_TRUE;
 }
 
+void
+nsContentUtils::InitializeTouchEventTable()
+{
+  static PRBool sEventTableInitialized = PR_FALSE;
+  if (!sEventTableInitialized && sAtomEventTable && sStringEventTable) {
+    sEventTableInitialized = PR_TRUE;
+    static const EventNameMapping touchEventArray[] = {
+      { nsGkAtoms::ontouchstart, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
+      { nsGkAtoms::ontouchend, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
+      { nsGkAtoms::ontouchmove, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
+      { nsGkAtoms::ontouchenter, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
+      { nsGkAtoms::ontouchleave, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT },
+      { nsGkAtoms::ontouchcancel, NS_USER_DEFINED_EVENT, EventNameType_All, NS_INPUT_EVENT }
+    };
+    for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(touchEventArray); ++i) {
+      if (!sAtomEventTable->Put(touchEventArray[i].mAtom, touchEventArray[i]) ||
+          !sStringEventTable->Put(Substring(nsDependentAtomString(touchEventArray[i].mAtom), 2),
+                                  touchEventArray[i])) {
+        delete sAtomEventTable;
+        sAtomEventTable = nsnull;
+        delete sStringEventTable;
+        sStringEventTable = nsnull;
+        return;
+      }
+    }
+  }
+}
+
+
 /**
  * Access a cached parser service. Don't addref. We need only one
  * reference to it and this class has that one.
  */
 /* static */
 nsIParserService*
 nsContentUtils::GetParserService()
 {
@@ -5495,18 +5526,19 @@ nsContentUtils::DispatchXULCommand(nsICo
   nsCOMPtr<nsIDOMDocumentEvent> docEvent = do_QueryInterface(doc);
   NS_ENSURE_STATE(docEvent);
   nsCOMPtr<nsIDOMEvent> event;
   docEvent->CreateEvent(NS_LITERAL_STRING("xulcommandevent"),
                         getter_AddRefs(event));
   nsCOMPtr<nsIDOMXULCommandEvent> xulCommand = do_QueryInterface(event);
   nsCOMPtr<nsIPrivateDOMEvent> pEvent = do_QueryInterface(xulCommand);
   NS_ENSURE_STATE(pEvent);
+  nsCOMPtr<nsIDOMAbstractView> view = do_QueryInterface(doc->GetWindow());
   nsresult rv = xulCommand->InitCommandEvent(NS_LITERAL_STRING("command"),
-                                             PR_TRUE, PR_TRUE, doc->GetWindow(),
+                                             PR_TRUE, PR_TRUE, view,
                                              0, aCtrl, aAlt, aShift, aMeta,
                                              aSourceEvent);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aShell) {
     nsEventStatus status = nsEventStatus_eIgnore;
     nsCOMPtr<nsIPresShell> kungFuDeathGrip = aShell;
     return aShell->HandleDOMEventWithTarget(aTarget, event, &status);
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -70,16 +70,18 @@
 
 #include "nsGUIEvent.h"
 #include "nsPLDOMEvent.h"
 
 #include "nsIDOMStyleSheet.h"
 #include "nsDOMAttribute.h"
 #include "nsIDOMDOMStringList.h"
 #include "nsIDOMDOMImplementation.h"
+#include "nsIDOMDocumentView.h"
+#include "nsIDOMAbstractView.h"
 #include "nsIDOMDocumentXBL.h"
 #include "mozilla/FunctionTimer.h"
 #include "nsGenericElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMEventGroup.h"
 #include "nsIDOMCDATASection.h"
 #include "nsIDOMProcessingInstruction.h"
 #include "nsDOMString.h"
@@ -196,16 +198,17 @@ static NS_DEFINE_CID(kDOMEventGroupCID, 
 #include "nsIContentSecurityPolicy.h"
 #include "nsCSPService.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsHTMLCSSStyleSheet.h"
 
 #include "mozilla/dom/Link.h"
 #include "nsIHTMLDocument.h"
 #include "nsXULAppAPI.h"
+#include "nsDOMTouchEvent.h"
 
 using namespace mozilla::dom;
 
 typedef nsTArray<Link*> LinkArray;
 
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDocumentLeakPRLog;
@@ -1694,16 +1697,17 @@ NS_INTERFACE_TABLE_HEAD(nsDocument)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOM3EventTarget)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMNSEventTarget)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsPIDOMEventTarget)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsISupportsWeakReference)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIRadioGroupContainer_MOZILLA_2_0_BRANCH)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIMutationObserver)
     NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIApplicationCacheContainer)
+    NS_INTERFACE_TABLE_ENTRY(nsDocument, nsIDOMDocumentTouch)
   NS_OFFSET_AND_INTERFACE_TABLE_END
   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDocument)
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOM3Node, new nsNode3Tearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
                                  new nsNode3Tearoff(this))
   NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMNodeSelector,
                                  new nsNodeSelectorTearoff(this))
@@ -5062,24 +5066,26 @@ nsDocument::CreateTreeWalker(nsIDOMNode 
 
   NS_ADDREF(*_retval = walker);
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
-nsDocument::GetDefaultView(nsIDOMWindow** aDefaultView)
-{
-  *aDefaultView = nsnull;
+nsDocument::GetDefaultView(nsIDOMAbstractView** aDefaultView)
+{
   nsPIDOMWindow* win = GetWindow();
-  if (!win) {
-    return NS_OK;
-  }
-  return CallQueryInterface(win, aDefaultView);
+  if (win) {
+    return CallQueryInterface(win, aDefaultView);
+  }
+
+  *aDefaultView = nsnull;
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocument::GetLocation(nsIDOMLocation **_retval)
 {
   NS_ENSURE_ARG_POINTER(_retval);
   *_retval = nsnull;
 
@@ -8312,8 +8318,81 @@ nsDocument::SetImagesNeedAnimating(PRBoo
   // Otherwise, iterate over our images and perform the appropriate action.
   mImageTracker.EnumerateRead(aAnimating ? IncrementAnimationEnumerator
                                          : DecrementAnimationEnumerator,
                               nsnull);
 
   // Update state.
   mAnimatingImages = aAnimating;
 }
+
+NS_IMETHODIMP
+nsDocument::CreateTouch(nsIDOMAbstractView* aView,
+                        nsIDOMEventTarget* aTarget,
+                        PRInt32 aIdentifier,
+                        PRInt32 aPageX,
+                        PRInt32 aPageY,
+                        PRInt32 aScreenX,
+                        PRInt32 aScreenY,
+                        PRInt32 aClientX,
+                        PRInt32 aClientY,
+                        PRInt32 aRadiusX,
+                        PRInt32 aRadiusY,
+                        float aRotationAngle,
+                        float aForce,
+                        nsIDOMTouchPoint** aRetVal)
+{
+  NS_ADDREF(*aRetVal = new nsDOMTouchPoint(aTarget,
+                                           aIdentifier,
+                                           aPageX,
+                                           aPageY,
+                                           aScreenX,
+                                           aScreenY,
+                                           aClientX,
+                                           aClientY,
+                                           aRadiusX,
+                                           aRadiusY,
+                                           aRotationAngle,
+                                           aForce));
+  return NS_OK;;
+}
+
+NS_IMETHODIMP
+nsDocument::CreateTouchList(nsIVariant* aPoints,
+                            nsIDOMTouchList** aRetVal)
+{
+  nsRefPtr<nsDOMTouchList> retval = new nsDOMTouchList();
+  if (aPoints) {
+    PRUint16 type;
+    aPoints->GetDataType(&type);
+    if (type == nsIDataType::VTYPE_INTERFACE ||
+        type == nsIDataType::VTYPE_INTERFACE_IS) {
+      nsCOMPtr<nsISupports> data;
+      aPoints->GetAsISupports(getter_AddRefs(data));
+      nsCOMPtr<nsIDOMTouchPoint> point = do_QueryInterface(data);
+      if (point) {
+        retval->Append(point);
+      }
+    } else if (type == nsIDataType::VTYPE_ARRAY) {
+      PRUint16 valueType;
+      nsIID iid;
+      PRUint32 valueCount;
+      void* rawArray;
+      aPoints->GetAsArray(&valueType, &iid, &valueCount, &rawArray);
+      if (valueType == nsIDataType::VTYPE_INTERFACE ||
+          valueType == nsIDataType::VTYPE_INTERFACE_IS) {
+        nsISupports** values = static_cast<nsISupports**>(rawArray);
+        for (PRUint32 i = 0; i < valueCount; ++i) {
+          nsCOMPtr<nsISupports> supports = dont_AddRef(values[i]);
+          nsCOMPtr<nsIDOMTouchPoint> point = do_QueryInterface(supports);
+          if (point) {
+            retval->Append(point);
+          }
+        }
+      }
+      nsMemory::Free(rawArray);
+    }
+  }
+
+  *aRetVal = retval.forget().get();
+  return NS_OK;
+}
+
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -47,16 +47,17 @@
 #include "nsCRT.h"
 #include "nsIDocument.h"
 #include "nsWeakReference.h"
 #include "nsWeakPtr.h"
 #include "nsVoidArray.h"
 #include "nsTArray.h"
 #include "nsHashSets.h"
 #include "nsIDOMXMLDocument.h"
+#include "nsIDOMDocumentView.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsIDOMNSDocument.h"
 #include "nsIDOMNSDocumentStyle.h"
 #include "nsIDOMDocumentRange.h"
 #include "nsIDOMDocumentTraversal.h"
 #include "nsStubDocumentObserver.h"
 #include "nsIDOM3EventTarget.h"
 #include "nsIDOMNSEventTarget.h"
@@ -103,16 +104,17 @@
 #include "nsIDOMXPathNSResolver.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsILoadContext.h"
 #include "nsIProgressEventSink.h"
 #include "nsISecurityEventSink.h"
 #include "nsIChannelEventSink.h"
 #include "imgIRequest.h"
 #include "nsIDOMDOMImplementation.h"
+#include "nsIDOMTouchEvent.h"
 
 #define XML_DECLARATION_BITS_DECLARATION_EXISTS   (1 << 0)
 #define XML_DECLARATION_BITS_ENCODING_EXISTS      (1 << 1)
 #define XML_DECLARATION_BITS_STANDALONE_EXISTS    (1 << 2)
 #define XML_DECLARATION_BITS_STANDALONE_YES       (1 << 3)
 
 
 class nsIEventListenerManager;
@@ -492,27 +494,29 @@ protected:
 // nsIDOMXMLDocument unless someone writes a real implementation of
 // the interface.
 class nsDocument : public nsIDocument,
                    public nsIDOMXMLDocument, // inherits nsIDOMDocument
                    public nsIDOMNSDocument,
                    public nsIDOMDocumentEvent,
                    public nsIDOM3DocumentEvent,
                    public nsIDOMNSDocumentStyle,
+                   public nsIDOMDocumentView,
                    public nsIDOMDocumentRange,
                    public nsIDOMDocumentTraversal,
                    public nsIDOMDocumentXBL,
                    public nsSupportsWeakReference,
                    public nsIDOMEventTarget,
                    public nsIDOM3EventTarget,
                    public nsIDOMNSEventTarget,
                    public nsIScriptObjectPrincipal,
                    public nsIRadioGroupContainer_MOZILLA_2_0_BRANCH,
                    public nsIApplicationCacheContainer,
-                   public nsStubMutationObserver
+                   public nsStubMutationObserver,
+                   public nsIDOMDocumentTouch
 {
 public:
   typedef mozilla::dom::Element Element;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   using nsINode::GetScriptTypeID;
 
@@ -807,16 +811,19 @@ public:
   NS_DECL_NSIDOM3DOCUMENTEVENT
 
   // nsIDOMDocumentStyle
   NS_DECL_NSIDOMDOCUMENTSTYLE
 
   // nsIDOMNSDocumentStyle
   NS_DECL_NSIDOMNSDOCUMENTSTYLE
 
+  // nsIDOMDocumentView
+  NS_DECL_NSIDOMDOCUMENTVIEW
+
   // nsIDOMDocumentRange
   NS_DECL_NSIDOMDOCUMENTRANGE
 
   // nsIDOMDocumentTraversal
   NS_DECL_NSIDOMDOCUMENTTRAVERSAL
 
   // nsIDOMDocumentXBL
   NS_DECL_NSIDOMDOCUMENTXBL
@@ -831,16 +838,19 @@ public:
   NS_DECL_NSIDOMNSEVENTTARGET
 
   // nsIScriptObjectPrincipal
   virtual nsIPrincipal* GetPrincipal();
 
   // nsIApplicationCacheContainer
   NS_DECL_NSIAPPLICATIONCACHECONTAINER
 
+  // nsIDOMDocumentTouch
+  NS_DECL_NSIDOMDOCUMENTTOUCH
+
   virtual nsresult Init();
   
   virtual nsresult AddXMLEventsContent(nsIContent * aXMLEventsElement);
 
   virtual nsresult CreateElem(const nsAString& aName, nsIAtom *aPrefix,
                               PRInt32 aNamespaceID,
                               PRBool aDocumentDefaultType,
                               nsIContent **aResult);
@@ -1253,14 +1263,15 @@ protected:
 #endif
 };
 
 #define NS_DOCUMENT_INTERFACE_TABLE_BEGIN(_class)                             \
   NS_NODE_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class)                            \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMDocument, nsDocument)      \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNSDocument, nsDocument)    \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMDocumentEvent, nsDocument) \
+  NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMDocumentView, nsDocument)  \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMDocumentTraversal,         \
                                      nsDocument)                              \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMEventTarget, nsDocument)   \
   NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(_class, nsIDOMNode, nsDocument)
 
 #endif /* nsDocument_h___ */
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -87,16 +87,17 @@
 #ifdef MOZ_XUL
 #include "nsXULElement.h"
 #endif /* MOZ_XUL */
 #include "nsFrameManager.h"
 #include "nsFrameSelection.h"
 
 #include "nsBindingManager.h"
 #include "nsXBLBinding.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIXBLService.h"
 #include "nsPIDOMWindow.h"
 #include "nsIBoxObject.h"
 #include "nsPIBoxObject.h"
 #include "nsIDOMNSDocument.h"
 #include "nsIDOMNSElement.h"
 #include "nsClientRect.h"
 #ifdef MOZ_SVG
--- a/content/base/src/nsGkAtomList.h
+++ b/content/base/src/nsGkAtomList.h
@@ -715,16 +715,22 @@ GK_ATOM(onRequest, "onRequest")
 GK_ATOM(onreset, "onreset")
 GK_ATOM(onMozBeforeResize, "onMozBeforeResize")
 GK_ATOM(onresize, "onresize")
 GK_ATOM(onscroll, "onscroll")
 GK_ATOM(onselect, "onselect")
 GK_ATOM(onset, "onset")
 GK_ATOM(onsubmit, "onsubmit")
 GK_ATOM(ontext, "ontext")
+GK_ATOM(ontouchstart, "ontouchstart")
+GK_ATOM(ontouchend, "ontouchend")
+GK_ATOM(ontouchmove, "ontouchmove")
+GK_ATOM(ontouchenter, "ontouchenter")
+GK_ATOM(ontouchleave, "ontouchleave")
+GK_ATOM(ontouchcancel, "ontouchcancel")
 GK_ATOM(ontransitionend, "ontransitionend")
 GK_ATOM(onunderflow, "onunderflow")
 GK_ATOM(onunload, "onunload")
 GK_ATOM(open, "open")
 GK_ATOM(optgroup, "optgroup")
 GK_ATOM(optimum, "optimum")
 GK_ATOM(option, "option")
 GK_ATOM(_or, "or")
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -553,16 +553,19 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
           if (elm->MayHavePaintEventListener()) {
             window->SetHasPaintEventListeners();
           }
 #ifdef MOZ_MEDIA
           if (elm->MayHaveAudioAvailableEventListener()) {
             window->SetHasAudioAvailableEventListeners();
           }
 #endif
+          if (elm->MayHaveTouchEventListener()) {
+            window->SetHasTouchEventListeners();
+          }
         }
       }
     }
 
 #ifdef MOZ_MEDIA
     if (wasRegistered && oldDoc != newDoc) {
       nsCOMPtr<nsIDOMHTMLMediaElement> domMediaElem(do_QueryInterface(aNode));
       if (domMediaElem) {
--- a/content/events/public/nsIEventListenerManager.h
+++ b/content/events/public/nsIEventListenerManager.h
@@ -51,29 +51,30 @@ class nsPIDOMEventTarget;
 class nsIEventListenerInfo;
 template<class E> class nsCOMArray;
 class nsCxPusher;
 
 /*
  * Event listener manager interface.
  */
 #define NS_IEVENTLISTENERMANAGER_IID \
-{ 0xe86a148b, 0x0563, 0x454f, \
-  { 0x8c, 0xf2, 0xbd, 0xc4, 0x7c, 0xe6, 0xbe, 0x91 } }
+{ 0x8e8667ed, 0x10d3, 0x41e8, \
+  { 0x93, 0xfa, 0xa4, 0xc4, 0xea, 0x16, 0x85, 0xd5 } }
 
 class nsIEventListenerManager : public nsISupports {
 
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IEVENTLISTENERMANAGER_IID)
 
   nsIEventListenerManager() : mMayHavePaintEventListener(PR_FALSE),
     mMayHaveMutationListeners(PR_FALSE),
     mMayHaveCapturingListeners(PR_FALSE),
     mMayHaveSystemGroupListeners(PR_FALSE),
     mMayHaveAudioAvailableEventListener(PR_FALSE),
+    mMayHaveTouchEventListener(PR_FALSE),
     mNoListenerForEvent(0)
   {}
 
   /**
   * Sets events listeners of all types.
   * @param an event listener
   */
   NS_IMETHOD AddEventListenerByIID(nsIDOMEventListener *aListener,
@@ -207,24 +208,29 @@ public:
   PRBool MayHavePaintEventListener() { return mMayHavePaintEventListener; }
 
   /**
    * Returns PR_TRUE if there may be a MozAudioAvailable event listener registered,
    * PR_FALSE if there definitely isn't.
    */
   PRBool MayHaveAudioAvailableEventListener() { return mMayHaveAudioAvailableEventListener; }
 
-
+  /**
+   * Returns PR_TRUE if there may be a touch event listener registered,
+   * PR_FALSE if there definitely isn't.
+   */
+  PRBool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; }
 protected:
   PRUint32 mMayHavePaintEventListener : 1;
   PRUint32 mMayHaveMutationListeners : 1;
   PRUint32 mMayHaveCapturingListeners : 1;
   PRUint32 mMayHaveSystemGroupListeners : 1;
   PRUint32 mMayHaveAudioAvailableEventListener : 1;
-  PRUint32 mNoListenerForEvent : 27;
+  PRUint32 mMayHaveTouchEventListener : 1;
+  PRUint32 mNoListenerForEvent : 26;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIEventListenerManager,
                               NS_IEVENTLISTENERMANAGER_IID)
 
 nsresult
 NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);
 
--- a/content/events/public/nsIPrivateDOMEvent.h
+++ b/content/events/public/nsIPrivateDOMEvent.h
@@ -137,9 +137,11 @@ NS_NewDOMTransitionEvent(nsIDOMEvent** a
 #ifdef MOZ_CSS_ANIMATIONS
 nsresult
 NS_NewDOMAnimationEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsAnimationEvent* aEvent);
 #endif
 nsresult
 NS_NewDOMCloseEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsEvent* aEvent);
 nsresult
 NS_NewDOMMozTouchEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsMozTouchEvent* aEvent);
+nsresult
+NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult, nsPresContext* aPresContext, class nsInputEvent *aEvent);
 #endif // nsIPrivateDOMEvent_h__
--- a/content/events/src/Makefile.in
+++ b/content/events/src/Makefile.in
@@ -86,16 +86,17 @@ CPPSRCS		= \
 		nsDOMSimpleGestureEvent.cpp \
 		nsDOMMozTouchEvent.cpp \
 		nsDOMEventTargetHelper.cpp \
 		nsDOMScrollAreaEvent.cpp \
 		nsDOMTransitionEvent.cpp \
 		nsDOMPopStateEvent.cpp \
 		nsDOMHashChangeEvent.cpp \
 		nsDOMCloseEvent.cpp \
+		nsDOMTouchEvent.cpp \
 		$(NULL)
 
 ifdef MOZ_CSS_ANIMATIONS
 CPPSRCS		+= nsDOMAnimationEvent.cpp 
 endif
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
--- a/content/events/src/nsDOMDragEvent.cpp
+++ b/content/events/src/nsDOMDragEvent.cpp
@@ -75,17 +75,17 @@ DOMCI_DATA(DragEvent, nsDOMDragEvent)
 NS_INTERFACE_MAP_BEGIN(nsDOMDragEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDragEvent)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(DragEvent)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMMouseEvent)
 
 NS_IMETHODIMP
 nsDOMDragEvent::InitDragEvent(const nsAString & aType,
                               PRBool aCanBubble, PRBool aCancelable,
-                              nsIDOMWindow* aView, PRInt32 aDetail,
+                              nsIDOMAbstractView* aView, PRInt32 aDetail,
                               PRInt32 aScreenX, PRInt32 aScreenY,
                               PRInt32 aClientX, PRInt32 aClientY, 
                               PRBool aCtrlKey, PRBool aAltKey, PRBool aShiftKey,
                               PRBool aMetaKey, PRUint16 aButton,
                               nsIDOMEventTarget *aRelatedTarget,
                               nsIDOMDataTransfer* aDataTransfer)
 {
   nsresult rv = nsDOMMouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
@@ -127,10 +127,12 @@ nsDOMDragEvent::GetDataTransfer(nsIDOMDa
   return NS_OK;
 }
 
 nsresult NS_NewDOMDragEvent(nsIDOMEvent** aInstancePtrResult,
                             nsPresContext* aPresContext,
                             nsDragEvent *aEvent) 
 {
   nsDOMDragEvent* event = new nsDOMDragEvent(aPresContext, aEvent);
+  NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
+
   return CallQueryInterface(event, aInstancePtrResult);
 }
--- a/content/events/src/nsDOMKeyboardEvent.cpp
+++ b/content/events/src/nsDOMKeyboardEvent.cpp
@@ -170,17 +170,17 @@ nsDOMKeyboardEvent::GetWhich(PRUint32* a
       break;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMKeyboardEvent::InitKeyEvent(const nsAString& aType, PRBool aCanBubble, PRBool aCancelable,
-                                 nsIDOMWindow* aView, PRBool aCtrlKey, PRBool aAltKey,
+                                 nsIDOMAbstractView* aView, PRBool aCtrlKey, PRBool aAltKey,
                                  PRBool aShiftKey, PRBool aMetaKey,
                                  PRUint32 aKeyCode, PRUint32 aCharCode)
 {
   nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, 0);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsKeyEvent* keyEvent = static_cast<nsKeyEvent*>(mEvent);
   keyEvent->isControl = aCtrlKey;
@@ -193,10 +193,14 @@ nsDOMKeyboardEvent::InitKeyEvent(const n
   return NS_OK;
 }
 
 nsresult NS_NewDOMKeyboardEvent(nsIDOMEvent** aInstancePtrResult,
                                 nsPresContext* aPresContext,
                                 nsKeyEvent *aEvent)
 {
   nsDOMKeyboardEvent* it = new nsDOMKeyboardEvent(aPresContext, aEvent);
+  if (nsnull == it) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   return CallQueryInterface(it, aInstancePtrResult);
 }
--- a/content/events/src/nsDOMMouseEvent.cpp
+++ b/content/events/src/nsDOMMouseEvent.cpp
@@ -99,17 +99,17 @@ DOMCI_DATA(MouseEvent, nsDOMMouseEvent)
 NS_INTERFACE_MAP_BEGIN(nsDOMMouseEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMouseEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNSMouseEvent)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MouseEvent)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMUIEvent)
 
 NS_IMETHODIMP
 nsDOMMouseEvent::InitMouseEvent(const nsAString & aType, PRBool aCanBubble, PRBool aCancelable,
-                                nsIDOMWindow* aView, PRInt32 aDetail, PRInt32 aScreenX, 
+                                nsIDOMAbstractView *aView, PRInt32 aDetail, PRInt32 aScreenX, 
                                 PRInt32 aScreenY, PRInt32 aClientX, PRInt32 aClientY, 
                                 PRBool aCtrlKey, PRBool aAltKey, PRBool aShiftKey, 
                                 PRBool aMetaKey, PRUint16 aButton, nsIDOMEventTarget *aRelatedTarget)
 {
   nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
   NS_ENSURE_SUCCESS(rv, rv);
 
   switch(mEvent->eventStructType)
@@ -142,17 +142,17 @@ nsDOMMouseEvent::InitMouseEvent(const ns
        break;
   }
 
   return NS_OK;
 }   
 
 NS_IMETHODIMP
 nsDOMMouseEvent::InitNSMouseEvent(const nsAString & aType, PRBool aCanBubble, PRBool aCancelable,
-                                  nsIDOMWindow *aView, PRInt32 aDetail, PRInt32 aScreenX,
+                                  nsIDOMAbstractView *aView, PRInt32 aDetail, PRInt32 aScreenX,
                                   PRInt32 aScreenY, PRInt32 aClientX, PRInt32 aClientY,
                                   PRBool aCtrlKey, PRBool aAltKey, PRBool aShiftKey,
                                   PRBool aMetaKey, PRUint16 aButton, nsIDOMEventTarget *aRelatedTarget,
                                   float aPressure, PRUint16 aInputSource)
 {
   nsresult rv = nsDOMMouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
                                                 aView, aDetail, aScreenX, aScreenY,
                                                 aClientX, aClientY, aCtrlKey, aAltKey, aShiftKey,
@@ -308,10 +308,14 @@ nsDOMMouseEvent::GetMozInputSource(PRUin
   return NS_OK;
 }
 
 nsresult NS_NewDOMMouseEvent(nsIDOMEvent** aInstancePtrResult,
                              nsPresContext* aPresContext,
                              nsInputEvent *aEvent) 
 {
   nsDOMMouseEvent* it = new nsDOMMouseEvent(aPresContext, aEvent);
+  if (nsnull == it) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   return CallQueryInterface(it, aInstancePtrResult);
 }
--- a/content/events/src/nsDOMMouseScrollEvent.cpp
+++ b/content/events/src/nsDOMMouseScrollEvent.cpp
@@ -83,17 +83,17 @@ DOMCI_DATA(MouseScrollEvent, nsDOMMouseS
 
 NS_INTERFACE_MAP_BEGIN(nsDOMMouseScrollEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMouseScrollEvent)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MouseScrollEvent)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMMouseEvent)
 
 NS_IMETHODIMP
 nsDOMMouseScrollEvent::InitMouseScrollEvent(const nsAString & aType, PRBool aCanBubble, PRBool aCancelable,
-                                nsIDOMWindow *aView, PRInt32 aDetail, PRInt32 aScreenX, 
+                                nsIDOMAbstractView *aView, PRInt32 aDetail, PRInt32 aScreenX, 
                                 PRInt32 aScreenY, PRInt32 aClientX, PRInt32 aClientY, 
                                 PRBool aCtrlKey, PRBool aAltKey, PRBool aShiftKey, 
                                 PRBool aMetaKey, PRUint16 aButton, nsIDOMEventTarget *aRelatedTarget,
                                 PRInt32 aAxis)
 {
   nsresult rv = nsDOMMouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable, aView, aDetail,
                                                 aScreenX, aScreenY, aClientX, aClientY, aCtrlKey,
                                                 aAltKey, aShiftKey, aMetaKey, aButton, aRelatedTarget);
@@ -124,10 +124,14 @@ nsDOMMouseScrollEvent::GetAxis(PRInt32* 
   return NS_OK;
 }
 
 nsresult NS_NewDOMMouseScrollEvent(nsIDOMEvent** aInstancePtrResult,
                                    nsPresContext* aPresContext,
                                    nsInputEvent *aEvent) 
 {
   nsDOMMouseScrollEvent* it = new nsDOMMouseScrollEvent(aPresContext, aEvent);
+  if (nsnull == it) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   return CallQueryInterface(it, aInstancePtrResult);
 }
--- a/content/events/src/nsDOMMozTouchEvent.cpp
+++ b/content/events/src/nsDOMMozTouchEvent.cpp
@@ -80,17 +80,17 @@ nsDOMMozTouchEvent::GetStreamId(PRUint32
   *aStreamId = static_cast<nsMozTouchEvent*>(mEvent)->streamId;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMMozTouchEvent::InitMozTouchEvent(const nsAString& aTypeArg,
                                       PRBool aCanBubbleArg,
                                       PRBool aCancelableArg,
-                                      nsIDOMWindow* aViewArg,
+                                      nsIDOMAbstractView* aViewArg,
                                       PRInt32 aDetailArg,
                                       PRInt32 aScreenX,
                                       PRInt32 aScreenY,
                                       PRInt32 aClientX,
                                       PRInt32 aClientY,
                                       PRBool aCtrlKeyArg,
                                       PRBool aAltKeyArg,
                                       PRBool aShiftKeyArg,
@@ -122,10 +122,13 @@ nsDOMMozTouchEvent::InitMozTouchEvent(co
   return NS_OK;
 }
 
 nsresult NS_NewDOMMozTouchEvent(nsIDOMEvent** aInstancePtrResult,
                                      nsPresContext* aPresContext,
                                      nsMozTouchEvent *aEvent)
 {
   nsDOMMozTouchEvent *it = new nsDOMMozTouchEvent(aPresContext, aEvent);
+  if (nsnull == it) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
   return CallQueryInterface(it, aInstancePtrResult);
 }
--- a/content/events/src/nsDOMScrollAreaEvent.cpp
+++ b/content/events/src/nsDOMScrollAreaEvent.cpp
@@ -96,17 +96,17 @@ nsDOMScrollAreaEvent::GetHeight(float *a
 {
   return mClientArea.GetHeight(aHeight);
 }
 
 NS_IMETHODIMP
 nsDOMScrollAreaEvent::InitScrollAreaEvent(const nsAString &aEventType,
                                           PRBool aCanBubble,
                                           PRBool aCancelable,
-                                          nsIDOMWindow *aView,
+                                          nsIDOMAbstractView *aView,
                                           PRInt32 aDetail,
                                           float aX, float aY,
                                           float aWidth, float aHeight)
 {
   nsresult rv = nsDOMUIEvent::InitUIEvent(aEventType, aCanBubble, aCancelable, aView, aDetail);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mClientArea.SetRect(aX, aY, aWidth, aHeight);
@@ -150,11 +150,16 @@ nsDOMScrollAreaEvent::Deserialize(const 
   return PR_TRUE;
 }
 
 nsresult
 NS_NewDOMScrollAreaEvent(nsIDOMEvent **aInstancePtrResult,
                          nsPresContext *aPresContext,
                          nsScrollAreaEvent *aEvent)
 {
-  nsDOMScrollAreaEvent* it = new nsDOMScrollAreaEvent(aPresContext, aEvent);
-  return CallQueryInterface(it, aInstancePtrResult);
+  nsDOMScrollAreaEvent *ev = new nsDOMScrollAreaEvent(aPresContext, aEvent);
+
+  if (!ev) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  return CallQueryInterface(ev, aInstancePtrResult);
 }
--- a/content/events/src/nsDOMSimpleGestureEvent.cpp
+++ b/content/events/src/nsDOMSimpleGestureEvent.cpp
@@ -90,17 +90,17 @@ nsDOMSimpleGestureEvent::GetDelta(PRFloa
   *aDelta = static_cast<nsSimpleGestureEvent*>(mEvent)->delta;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMSimpleGestureEvent::InitSimpleGestureEvent(const nsAString& aTypeArg,
                                                 PRBool aCanBubbleArg,
                                                 PRBool aCancelableArg,
-                                                nsIDOMWindow* aViewArg,
+                                                nsIDOMAbstractView* aViewArg,
                                                 PRInt32 aDetailArg,
                                                 PRInt32 aScreenX, 
                                                 PRInt32 aScreenY,
                                                 PRInt32 aClientX,
                                                 PRInt32 aClientY,
                                                 PRBool aCtrlKeyArg,
                                                 PRBool aAltKeyArg,
                                                 PRBool aShiftKeyArg,
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMTouchEvent.cpp
@@ -0,0 +1,341 @@
+                     /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* ***** 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 nsDOMTouchEvent.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Olli Pettay <Olli.Pettay@helsinki.fi> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsDOMTouchEvent.h"
+#include "nsGUIEvent.h"
+#include "nsDOMClassInfoID.h"
+#include "nsIClassInfo.h"
+#include "nsIXPCScriptable.h"
+#include "nsContentUtils.h"
+
+DOMCI_DATA(TouchPoint, nsDOMTouchPoint)
+
+NS_IMPL_CYCLE_COLLECTION_1(nsDOMTouchPoint, mTarget)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMTouchPoint)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMTouchPoint)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMTouchPoint)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchPoint)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTouchPoint)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTouchPoint)
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetIdentifier(PRInt32* aIdentifier)
+{
+  *aIdentifier = mIdentifier;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetTarget(nsIDOMEventTarget** aTarget)
+{
+  NS_IF_ADDREF(*aTarget = mTarget);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetScreenX(PRInt32* aScreenX)
+{
+  *aScreenX = mScreenX;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetScreenY(PRInt32* aScreenY)
+{
+  *aScreenY = mScreenY;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetClientX(PRInt32* aClientX)
+{
+  *aClientX = mClientX;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetClientY(PRInt32* aClientY)
+{
+  *aClientY = mClientY;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetPageX(PRInt32* aPageX)
+{
+  *aPageX = mPageX;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetPageY(PRInt32* aPageY)
+{
+  *aPageY = mPageY;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetRadiusX(PRInt32* aRadiusX)
+{
+  *aRadiusX = mRadiusX;
+  return NS_OK;
+}
+                                             
+NS_IMETHODIMP
+nsDOMTouchPoint::GetRadiusY(PRInt32* aRadiusY)
+{
+  *aRadiusY = mRadiusY;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetRotationAngle(float* aRotationAngle)
+{
+  *aRotationAngle = mRotationAngle;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchPoint::GetForce(float* aForce)
+{
+  *aForce = mForce;
+  return NS_OK;
+}
+
+// TouchList
+
+DOMCI_DATA(TouchList, nsDOMTouchList)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMTouchList)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMTouchList)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchList)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMTouchList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPoints)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMTouchList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPoints)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTouchList)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTouchList)
+
+NS_IMETHODIMP
+nsDOMTouchList::GetLength(PRUint32* aLength)
+{
+  *aLength = mPoints.Count();
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchList::Item(PRUint32 aIndex, nsIDOMTouchPoint** aRetVal)
+{
+  NS_IF_ADDREF(*aRetVal = mPoints.SafeObjectAt(aIndex));
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchList::IdentifiedPoint(PRInt32 aIdentifier, nsIDOMTouchPoint** aRetVal)
+{
+  for (PRInt32 i = 0; i < mPoints.Count(); ++i) {
+    nsCOMPtr<nsIDOMTouchPoint> point = mPoints[i];
+    PRInt32 identifier;
+    if (point && NS_SUCCEEDED(point->GetIdentifier(&identifier)) &&
+        aIdentifier == identifier) {
+      point.swap(*aRetVal);
+      break;
+    }
+  }
+  return NS_OK;
+}
+
+// TouchEvent
+
+nsDOMTouchEvent::nsDOMTouchEvent(nsPresContext* aPresContext,
+                                 nsInputEvent* aEvent)
+  : nsDOMUIEvent(aPresContext, aEvent ? aEvent :
+                                        new nsInputEvent(PR_FALSE, 0, nsnull))
+{
+  if (aEvent) {
+    mEventIsInternal = PR_FALSE;
+  } else {
+    mEventIsInternal = PR_TRUE;
+    mEvent->time = PR_Now();
+  }
+}
+
+nsDOMTouchEvent::~nsDOMTouchEvent()
+{
+  if (mEventIsInternal && mEvent) {
+    delete static_cast<nsInputEvent*>(mEvent);
+    mEvent = nsnull;
+  }
+}
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchEvent)
+
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTouches)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTargetTouches)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChangedTouches)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTouches)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTargetTouches)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChangedTouches)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
+DOMCI_DATA(TouchEvent, nsDOMTouchEvent)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMTouchEvent)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMTouchEvent)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchEvent)
+NS_INTERFACE_MAP_END_INHERITING(nsDOMUIEvent)
+
+NS_IMPL_ADDREF_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
+NS_IMPL_RELEASE_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
+
+
+NS_IMETHODIMP
+nsDOMTouchEvent::InitTouchEvent(const nsAString& aType,
+                                PRBool aCanBubble,
+                                PRBool aCancelable,
+                                nsIDOMAbstractView* aView,
+                                PRInt32 aDetail,
+                                PRBool aCtrlKey,
+                                PRBool aAltKey,
+                                PRBool aShiftKey,
+                                PRBool aMetaKey,
+                                nsIDOMTouchList* aTouches,
+                                nsIDOMTouchList* aTargetTouches,
+                                nsIDOMTouchList* aChangedTouches)
+{
+  nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  static_cast<nsInputEvent*>(mEvent)->isControl = aCtrlKey;
+  static_cast<nsInputEvent*>(mEvent)->isAlt = aAltKey;
+  static_cast<nsInputEvent*>(mEvent)->isShift = aShiftKey;
+  static_cast<nsInputEvent*>(mEvent)->isMeta = aMetaKey;
+  mTouches = aTouches;
+  mTargetTouches = aTargetTouches;
+  mChangedTouches = aChangedTouches;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchEvent::GetTouches(nsIDOMTouchList** aTouches)
+{
+  NS_IF_ADDREF(*aTouches = mTouches);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchEvent::GetTargetTouches(nsIDOMTouchList** aTargetTouches)
+{
+  NS_IF_ADDREF(*aTargetTouches = mTargetTouches);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchEvent::GetChangedTouches(nsIDOMTouchList** aChangedTouches)
+{
+  NS_IF_ADDREF(*aChangedTouches = mChangedTouches);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchEvent::GetAltKey(PRBool* aAltKey)
+{
+  *aAltKey = static_cast<nsInputEvent*>(mEvent)->isAlt;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchEvent::GetMetaKey(PRBool* aMetaKey)
+{
+  *aMetaKey = static_cast<nsInputEvent*>(mEvent)->isMeta;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchEvent::GetCtrlKey(PRBool* aCtrlKey)
+{
+  *aCtrlKey = static_cast<nsInputEvent*>(mEvent)->isControl;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDOMTouchEvent::GetShiftKey(PRBool* aShiftKey)
+{
+  *aShiftKey = static_cast<nsInputEvent*>(mEvent)->isShift;
+  return NS_OK;
+}
+
+PRBool
+nsDOMTouchEvent::PrefEnabled()
+{
+  static PRBool sDidCheckPref = PR_FALSE;
+  static PRBool sPrefValue = PR_FALSE;
+  if (!sDidCheckPref) {
+    sDidCheckPref = PR_TRUE;
+    sPrefValue = nsContentUtils::GetBoolPref("dom.w3c_touch_events.enabled", PR_FALSE);
+    if (sPrefValue) {
+      nsContentUtils::InitializeTouchEventTable();
+    }
+  }
+  return sPrefValue;
+}
+
+nsresult
+NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult,
+                    nsPresContext* aPresContext,
+                    nsInputEvent *aEvent)
+{
+  nsDOMTouchEvent* it = new nsDOMTouchEvent(aPresContext, aEvent);
+
+  return CallQueryInterface(it, aInstancePtrResult);
+}
new file mode 100644
--- /dev/null
+++ b/content/events/src/nsDOMTouchEvent.h
@@ -0,0 +1,131 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* ***** 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 nsDOMTouchEvent.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Olli Pettay <Olli.Pettay@helsinki.fi> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+#ifndef nsDOMTouchEvent_h_
+#define nsDOMTouchEvent_h_
+
+#include "nsDOMUIEvent.h"
+#include "nsIDOMTouchEvent.h"
+#include "nsString.h"
+#include "nsCOMArray.h"
+
+class nsDOMTouchPoint : public nsIDOMTouchPoint
+{
+public:
+  nsDOMTouchPoint(nsIDOMEventTarget* aTarget,
+                  PRInt32 aIdentifier,
+                  PRInt32 aPageX,
+                  PRInt32 aPageY,
+                  PRInt32 aScreenX,
+                  PRInt32 aScreenY,
+                  PRInt32 aClientX,
+                  PRInt32 aClientY,
+                  PRInt32 aRadiusX,
+                  PRInt32 aRadiusY,
+                  float aRotationAngle,
+                  float aForce)
+  : mTarget(aTarget),
+    mIdentifier(aIdentifier),
+    mPageX(aPageX),
+    mPageY(aPageY),
+    mScreenX(aScreenX),
+    mScreenY(aScreenY),
+    mClientX(aClientX),
+    mClientY(aClientY),
+    mRadiusX(aRadiusX),
+    mRadiusY(aRadiusY),
+    mRotationAngle(aRotationAngle),
+    mForce(aForce)
+    {}
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMTouchPoint)
+  NS_DECL_NSIDOMTOUCHPOINT
+protected:
+  nsCOMPtr<nsIDOMEventTarget> mTarget;
+  PRInt32 mIdentifier;
+  PRInt32 mPageX;
+  PRInt32 mPageY;
+  PRInt32 mScreenX;
+  PRInt32 mScreenY;
+  PRInt32 mClientX;
+  PRInt32 mClientY;
+  PRInt32 mRadiusX;
+  PRInt32 mRadiusY;
+  float mRotationAngle;
+  float mForce;
+};
+
+class nsDOMTouchList : public nsIDOMTouchList
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
+  NS_DECL_NSIDOMTOUCHLIST
+  
+  void Append(nsIDOMTouchPoint* aPoint)
+  {
+    mPoints.AppendObject(aPoint);
+  }
+
+  nsIDOMTouchPoint* GetItemAt(PRUint32 aIndex)
+  {
+    return mPoints.SafeObjectAt(aIndex);
+  }
+protected:
+  nsCOMArray<nsIDOMTouchPoint> mPoints;
+};
+
+class nsDOMTouchEvent : public nsDOMUIEvent,
+                        public nsIDOMTouchEvent
+{
+public:
+  nsDOMTouchEvent(nsPresContext* aPresContext, nsInputEvent* aEvent);
+  virtual ~nsDOMTouchEvent();
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
+  NS_DECL_NSIDOMTOUCHEVENT
+
+  NS_FORWARD_TO_NSDOMUIEVENT
+
+  static PRBool PrefEnabled();
+protected:
+  nsCOMPtr<nsIDOMTouchList> mTouches;
+  nsCOMPtr<nsIDOMTouchList> mTargetTouches;
+  nsCOMPtr<nsIDOMTouchList> mChangedTouches;
+};
+
+#endif /* !defined(nsDOMTouchEvent_h_) */
--- a/content/events/src/nsDOMUIEvent.cpp
+++ b/content/events/src/nsDOMUIEvent.cpp
@@ -171,36 +171,32 @@ nsDOMUIEvent::GetClientPoint()
   if (rootFrame)
     pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent, rootFrame);
 
   return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
                     nsPresContext::AppUnitsToIntCSSPixels(pt.y));
 }
 
 NS_IMETHODIMP
-nsDOMUIEvent::GetView(nsIDOMWindow** aView)
+nsDOMUIEvent::GetView(nsIDOMAbstractView** aView)
 {
   *aView = mView;
   NS_IF_ADDREF(*aView);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMUIEvent::GetDetail(PRInt32* aDetail)
 {
   *aDetail = mDetail;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMUIEvent::InitUIEvent(const nsAString& typeArg,
-                          PRBool canBubbleArg,
-                          PRBool cancelableArg,
-                          nsIDOMWindow* viewArg,
-                          PRInt32 detailArg)
+nsDOMUIEvent::InitUIEvent(const nsAString & typeArg, PRBool canBubbleArg, PRBool cancelableArg, nsIDOMAbstractView *viewArg, PRInt32 detailArg)
 {
   nsresult rv = nsDOMEvent::InitEvent(typeArg, canBubbleArg, cancelableArg);
   NS_ENSURE_SUCCESS(rv, rv);
   
   mDetail = detailArg;
   mView = viewArg;
 
   return NS_OK;
@@ -417,10 +413,14 @@ nsDOMUIEvent::Deserialize(const IPC::Mes
   return PR_TRUE;
 }
 
 nsresult NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult,
                           nsPresContext* aPresContext,
                           nsGUIEvent *aEvent) 
 {
   nsDOMUIEvent* it = new nsDOMUIEvent(aPresContext, aEvent);
+  if (nsnull == it) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   return CallQueryInterface(it, aInstancePtrResult);
 }
--- a/content/events/src/nsDOMUIEvent.h
+++ b/content/events/src/nsDOMUIEvent.h
@@ -31,21 +31,22 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#ifndef nsDOMUIEvent_h
-#define nsDOMUIEvent_h
+#ifndef nsDOMUIEvent_h__
+#define nsDOMUIEvent_h__
 
 #include "nsIDOMUIEvent.h"
 #include "nsIDOMNSUIEvent.h"
+#include "nsIDOMAbstractView.h"
 #include "nsDOMEvent.h"
 
 class nsDOMUIEvent : public nsDOMEvent,
                      public nsIDOMUIEvent,
                      public nsIDOMNSUIEvent
 {
 public:
   nsDOMUIEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent);
@@ -72,21 +73,21 @@ protected:
 
   // Internal helper functions
   nsIntPoint GetClientPoint();
   nsIntPoint GetScreenPoint();
   nsIntPoint GetLayerPoint();
   nsIntPoint GetPagePoint();
   
 protected:
-  nsCOMPtr<nsIDOMWindow> mView;
+  nsCOMPtr<nsIDOMAbstractView> mView;
   PRInt32 mDetail;
   nsIntPoint mClientPoint;
   // Screenpoint is mEvent->refPoint.
   nsIntPoint mLayerPoint;
   nsIntPoint mPagePoint;
 };
 
 #define NS_FORWARD_TO_NSDOMUIEVENT \
   NS_FORWARD_NSIDOMUIEVENT(nsDOMUIEvent::) \
   NS_FORWARD_TO_NSDOMEVENT
 
-#endif // nsDOMUIEvent_h
+#endif // nsDOMUIEvent_h__
--- a/content/events/src/nsDOMXULCommandEvent.cpp
+++ b/content/events/src/nsDOMXULCommandEvent.cpp
@@ -113,17 +113,17 @@ nsDOMXULCommandEvent::GetSourceEvent(nsI
   NS_ENSURE_ARG_POINTER(aSourceEvent);
   NS_IF_ADDREF(*aSourceEvent = mSourceEvent);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMXULCommandEvent::InitCommandEvent(const nsAString& aType,
                                        PRBool aCanBubble, PRBool aCancelable,
-                                       nsIDOMWindow* aView,
+                                       nsIDOMAbstractView *aView,
                                        PRInt32 aDetail,
                                        PRBool aCtrlKey, PRBool aAltKey,
                                        PRBool aShiftKey, PRBool aMetaKey,
                                        nsIDOMEvent* aSourceEvent)
 {
   nsresult rv = nsDOMUIEvent::InitUIEvent(aType, aCanBubble, aCancelable,
                                           aView, aDetail);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -139,10 +139,14 @@ nsDOMXULCommandEvent::InitCommandEvent(c
 }
 
 
 nsresult NS_NewDOMXULCommandEvent(nsIDOMEvent** aInstancePtrResult,
                                   nsPresContext* aPresContext,
                                   nsInputEvent *aEvent) 
 {
   nsDOMXULCommandEvent* it = new nsDOMXULCommandEvent(aPresContext, aEvent);
+  if (nsnull == it) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   return CallQueryInterface(it, aInstancePtrResult);
 }
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -47,16 +47,17 @@
 #include "nsMutationEvent.h"
 #include NEW_H
 #include "nsFixedSizeAllocator.h"
 #include "nsINode.h"
 #include "nsPIDOMWindow.h"
 #include "nsDOMPopStateEvent.h"
 #include "nsDOMHashChangeEvent.h"
 #include "nsFrameLoader.h"
+#include "nsDOMTouchEvent.h"
 
 #define NS_TARGET_CHAIN_FORCE_CONTENT_DISPATCH  (1 << 0)
 #define NS_TARGET_CHAIN_WANTS_WILL_HANDLE_EVENT (1 << 1)
 #define NS_TARGET_CHAIN_MAY_HAVE_MANAGER        (1 << 2)
 
 static nsEventTargetChainItem* gCachedETCI = nsnull;
 
 // nsEventTargetChainItem represents a single item in the event target chain.
@@ -867,13 +868,16 @@ nsEventDispatcher::CreateEvent(nsPresCon
     return NS_NewDOMAnimationEvent(aDOMEvent, aPresContext, nsnull);
 #endif
   if (aEventType.LowerCaseEqualsLiteral("popstateevent"))
     return NS_NewDOMPopStateEvent(aDOMEvent, aPresContext, nsnull);
   if (aEventType.LowerCaseEqualsLiteral("mozaudioavailableevent"))
     return NS_NewDOMAudioAvailableEvent(aDOMEvent, aPresContext, nsnull);
   if (aEventType.LowerCaseEqualsLiteral("closeevent"))
     return NS_NewDOMCloseEvent(aDOMEvent, aPresContext, nsnull);
+  if (aEventType.LowerCaseEqualsLiteral("touchevent") &&
+      nsDOMTouchEvent::PrefEnabled())
+    return NS_NewDOMTouchEvent(aDOMEvent, aPresContext, nsnull);
   if (aEventType.LowerCaseEqualsLiteral("hashchangeevent"))
     return NS_NewDOMHashChangeEvent(aDOMEvent, aPresContext, nsnull);
 
   return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
 }
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -502,17 +502,24 @@ nsEventListenerManager::AddEventListener
       window->SetMutationListeners((aType == NS_MUTATION_SUBTREEMODIFIED) ?
                                    kAllMutationBits :
                                    MutationBitForEventType(aType));
     }
   } else if (aTypeAtom == nsGkAtoms::onMozOrientation) {
     nsPIDOMWindow* window = GetInnerWindowForTarget();
     if (window)
       window->SetHasOrientationEventListener();
-  } else if (aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) {
+  } else if ((aType >= NS_MOZTOUCH_DOWN && aType <= NS_MOZTOUCH_UP) ||
+             (aTypeAtom == nsGkAtoms::ontouchstart ||
+              aTypeAtom == nsGkAtoms::ontouchend ||
+              aTypeAtom == nsGkAtoms::ontouchmove ||
+              aTypeAtom == nsGkAtoms::ontouchenter ||
+              aTypeAtom == nsGkAtoms::ontouchleave ||
+              aTypeAtom == nsGkAtoms::ontouchcancel)) {
+    mMayHaveTouchEventListener = PR_TRUE;
     nsPIDOMWindow* window = GetInnerWindowForTarget();
     if (window)
       window->SetHasTouchEventListeners();
   }
 
   return NS_OK;
 }
 
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -113,16 +113,17 @@
 #include "nsIObserverService.h"
 #include "nsIDocShell.h"
 #include "nsIMarkupDocumentViewer.h"
 #include "nsIDOMDocumentRange.h"
 #include "nsIDOMDocumentEvent.h"
 #include "nsIDOMMouseScrollEvent.h"
 #include "nsIDOMDragEvent.h"
 #include "nsIDOMEventTarget.h"
+#include "nsIDOMDocumentView.h"
 #include "nsIDOMNSUIEvent.h"
 #include "nsDOMDragEvent.h"
 #include "nsIDOMNSEditableElement.h"
 
 #include "nsIDOMRange.h"
 #include "nsCaret.h"
 #include "nsILookAndFeel.h"
 #include "nsWidgetsCID.h"
--- a/content/events/test/Makefile.in
+++ b/content/events/test/Makefile.in
@@ -95,16 +95,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug586961.xul \
 		test_clickevent_on_input.html \
 		test_bug593959.html \
 		test_bug591815.html \
 		test_bug605242.html \
 		test_bug607464.html \
 		test_bug624127.html \
 		test_bug641477.html \
+		test_bug648573.html \
 		$(NULL)
 
 #bug 585630
 ifneq (mobile,$(MOZ_BUILD_APP))
 _TEST_FILES += \
 		test_dragstart.html \
 		$(NULL)
 endif
new file mode 100644
--- /dev/null
+++ b/content/events/test/test_bug648573.html
@@ -0,0 +1,111 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=648573
+-->
+<head>
+  <title>Test for Bug 648573</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=648573">Mozilla Bug 648573</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 648573 **/
+
+ok(!SpecialPowers.DOMWindowUtils.mayHaveTouchEventListeners,
+  "There shouldn't be any touch event listeners yet.");
+
+ok("createTouch" in document, "Should have createTouch function");
+ok("createTouchList" in document, "Should have createTouchList function");
+ok(document.createEvent("touchevent"), "Should be able to create TouchEvent objects");
+
+var t1 = document.createTouch(window, document, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+is(t1.target, document, "Wrong target");
+is(t1.identifier, 1, "Wrong identifier");
+is(t1.pageX, 2, "Wrong pageX");
+is(t1.pageY, 3, "Wrong pageY");
+is(t1.screenX, 4, "Wrong screenX");
+is(t1.screenY, 5, "Wrong screenY");
+is(t1.clientX, 6, "Wrong clientX");
+is(t1.clientY, 7, "Wrong clientY");
+is(t1.radiusX, 8, "Wrong radiusX");
+is(t1.radiusY, 9, "Wrong radiusY");
+is(t1.rotationAngle, 10, "Wrong rotationAngle");
+is(t1.force, 11, "Wrong force");
+
+var t2 = document.createTouch();
+
+var l1 = document.createTouchList(t1);
+is(l1.length, 1, "Wrong length");
+is(l1.item(0), t1, "Wront item (1)");
+is(l1[0], t1, "Wront item (2)");
+
+var l2 = document.createTouchList([t1, t2]);
+is(l2.length, 2, "Wrong length");
+is(l2.item(0), t1, "Wront item (3)");
+is(l2.item(1), t2, "Wront item (4)");
+is(l2[0], t1, "Wront item (5)");
+is(l2[1], t2, "Wront item (6)");
+
+var l3 = document.createTouchList();
+
+var e = document.createEvent("touchevent");
+e.initTouchEvent("touchmove", true, true, window, 0, true, true, true, true,
+                 l1, l2, l3);
+is(e.touches, l1, "Wrong list (1)");
+is(e.targetTouches, l2, "Wrong list (2)");
+is(e.changedTouches, l3, "Wrong list (3)");
+ok(e.altKey, "Alt should be true");
+ok(e.metaKey, "Meta should be true");
+ok(e.ctrlKey, "Ctrl should be true");
+ok(e.shiftKey, "Shift should be true");
+
+
+var events =
+  ["touchstart",
+   "touchend",
+   "touchmove",
+   "touchenter",
+   "touchleave",
+   "touchcancel"];
+
+function runEventTest(type) {
+  var e = document.createEvent("touchevent");
+  e.initTouchEvent(type, true, true, window, 0, true, true, true, true,
+                   l1, l2, l3);
+  var t = document.createElement("div");
+  // Testing target.onFoo;
+  var didCall = false;
+  t["on" + type] = function (evt) {                       
+    is(evt, e, "Wrong event");
+    evt.target.didCall = true;
+  }
+  t.dispatchEvent(e);
+  ok(t.didCall, "Should have called the listener(1)");
+  
+  // Testing <element onFoo="">
+  t = document.createElement("div");
+  t.setAttribute("on" + type, "this.didCall = true;");
+  t.dispatchEvent(e);
+  ok(t.didCall, "Should have called the listener(2)");
+}
+
+for (var i = 0; i < events.length; ++i) {
+  runEventTest(events[i]);
+}
+
+ok(SpecialPowers.DOMWindowUtils.mayHaveTouchEventListeners,
+  "There should be touch event listeners.");
+</script>
+</pre>
+</body>
+</html>
+
--- a/content/html/content/public/nsIHTMLCollection.h
+++ b/content/html/content/public/nsIHTMLCollection.h
@@ -40,36 +40,35 @@
 
 #include "nsIDOMHTMLCollection.h"
 
 class nsIContent;
 class nsWrapperCache;
 
 // IID for the nsIHTMLCollection interface
 #define NS_IHTMLCOLLECTION_IID \
-{ 0xf38b43dc, 0x74d4, 0x4b11, \
- { 0xa6, 0xc9, 0xf8, 0xf4, 0xb5, 0xd3, 0x84, 0xe3 } }
+{ 0x84a68396, 0x518d, 0x4fa8, \
+ { 0x8f, 0x7f, 0xa0, 0x60, 0x55, 0xff, 0xef, 0xba } }
 
 /**
  * An internal interface that allows QI-less getting of nodes from HTML
  * collections
  */
 class nsIHTMLCollection : public nsIDOMHTMLCollection
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTMLCOLLECTION_IID)
 
   /**
    * Get the node at the index.  Returns null if the index is out of bounds.
    */
-  virtual nsIContent* GetNodeAt(PRUint32 aIndex, nsresult* aResult) = 0;
+  virtual nsIContent* GetNodeAt(PRUint32 aIndex) = 0;
 
   /**
    * Get the node for the name.  Returns null if no node exists for the name.
    */
   virtual nsISupports* GetNamedItem(const nsAString& aName,
-                                    nsWrapperCache** aCache,
-                                    nsresult* aResult) = 0;
+                                    nsWrapperCache** aCache) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLCollection, NS_IHTMLCOLLECTION_IID)
 
 #endif /* nsIHTMLCollection_h___ */
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -116,30 +116,25 @@ public:
 
   void DropFormReference();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMHTMLCollection interface
   NS_DECL_NSIDOMHTMLCOLLECTION
 
-  virtual nsIContent* GetNodeAt(PRUint32 aIndex, nsresult* aResult)
+  virtual nsIContent* GetNodeAt(PRUint32 aIndex)
   {
     FlushPendingNotifications();
 
-    *aResult = NS_OK;
-
     return mElements.SafeElementAt(aIndex, nsnull);
   }
   virtual nsISupports* GetNamedItem(const nsAString& aName,
-                                    nsWrapperCache **aCache,
-                                    nsresult* aResult)
+                                    nsWrapperCache **aCache)
   {
-    *aResult = NS_OK;
-
     nsISupports *item = NamedItemInternal(aName, PR_TRUE);
     *aCache = nsnull;
     return item;
   }
 
   nsresult AddElementToTable(nsGenericHTMLFormElement* aChild,
                              const nsAString& aName);
   nsresult RemoveElementFromTable(nsGenericHTMLFormElement* aChild,
@@ -2300,22 +2295,21 @@ nsFormControlList::GetLength(PRUint32* a
   FlushPendingNotifications();
   *aLength = mElements.Length();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormControlList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
 {
-  nsresult rv;
-  nsISupports* item = GetNodeAt(aIndex, &rv);
+  nsISupports* item = GetNodeAt(aIndex);
   if (!item) {
     *aReturn = nsnull;
 
-    return rv;
+    return NS_OK;
   }
 
   return CallQueryInterface(item, aReturn);
 }
 
 NS_IMETHODIMP 
 nsFormControlList::NamedItem(const nsAString& aName,
                              nsIDOMNode** aReturn)
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -2164,32 +2164,29 @@ nsHTMLOptionCollection::SetSelectedIndex
   NS_ENSURE_TRUE(mSelect, NS_ERROR_UNEXPECTED);
 
   return mSelect->SetSelectedIndex(aSelectedIndex);
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
 {
-  nsresult rv;
-  nsISupports* item = GetNodeAt(aIndex, &rv);
+  nsISupports* item = GetNodeAt(aIndex);
   if (!item) {
     *aReturn = nsnull;
 
-    return rv;
+    return NS_OK;
   }
 
   return CallQueryInterface(item, aReturn);
 }
 
 nsIContent*
-nsHTMLOptionCollection::GetNodeAt(PRUint32 aIndex, nsresult* aResult)
+nsHTMLOptionCollection::GetNodeAt(PRUint32 aIndex)
 {
-  *aResult = NS_OK;
-
   return static_cast<nsIContent*>(ItemAsOption(aIndex));
 }
 
 static nsHTMLOptionElement*
 GetNamedItemHelper(nsTArray<nsRefPtr<nsHTMLOptionElement> > &aElements,
                    const nsAString& aName)
 {
   PRUint32 count = aElements.Length();
@@ -2204,21 +2201,18 @@ GetNamedItemHelper(nsTArray<nsRefPtr<nsH
     }
   }
 
   return nsnull;
 }
 
 nsISupports*
 nsHTMLOptionCollection::GetNamedItem(const nsAString& aName,
-                                     nsWrapperCache **aCache,
-                                     nsresult* aResult)
+                                     nsWrapperCache **aCache)
 {
-  *aResult = NS_OK;
-
   nsINode *item = GetNamedItemHelper(mElements, aName);
   *aCache = item;
   return item;
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::NamedItem(const nsAString& aName,
                                   nsIDOMNode** aReturn)
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -82,20 +82,19 @@ public:
   NS_DECL_NSIDOMHTMLOPTIONSCOLLECTION
 
   // nsIDOMNSHTMLOptionCollection interface
   NS_DECL_NSIDOMNSHTMLOPTIONCOLLECTION
 
   // nsIDOMHTMLCollection interface, all its methods are defined in
   // nsIDOMHTMLOptionsCollection
 
-  virtual nsIContent* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
+  virtual nsIContent* GetNodeAt(PRUint32 aIndex);
   virtual nsISupports* GetNamedItem(const nsAString& aName,
-                                    nsWrapperCache** aCache,
-                                    nsresult* aResult);
+                                    nsWrapperCache** aCache);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHTMLOptionCollection,
                                            nsIHTMLCollection)
 
   // Helpers for nsHTMLSelectElement
   /**
    * Insert an option
    * @param aOption the option to insert
--- a/content/html/content/src/nsHTMLTableElement.cpp
+++ b/content/html/content/src/nsHTMLTableElement.cpp
@@ -90,16 +90,23 @@ public:
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLTableElement,
                                                      nsGenericHTMLElement)
 
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTHead() {
+    return GetSection(nsGkAtoms::thead);
+  }
+  already_AddRefed<nsIDOMHTMLTableSectionElement> GetTFoot() {
+    return GetSection(nsGkAtoms::tfoot);
+  }
+  nsContentList* TBodies();
 protected:
   already_AddRefed<nsIDOMHTMLTableSectionElement> GetSection(nsIAtom *aTag);
 
   nsRefPtr<nsContentList> mTBodies;
   nsRefPtr<TableRowsCollection> mRows;
 };
 
 
@@ -114,20 +121,19 @@ public:
   TableRowsCollection(nsHTMLTableElement *aParent);
   virtual ~TableRowsCollection();
 
   nsresult Init();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMHTMLCOLLECTION
 
-  virtual nsIContent* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
+  virtual nsIContent* GetNodeAt(PRUint32 aIndex);
   virtual nsISupports* GetNamedItem(const nsAString& aName,
-                                    nsWrapperCache **aCache,
-                                    nsresult* aResult);
+                                    nsWrapperCache **aCache);
 
   NS_IMETHOD    ParentDestroyed();
 
   NS_DECL_CYCLE_COLLECTION_CLASS(TableRowsCollection)
 
 protected:
   // Those rows that are not in table sections
   nsRefPtr<nsContentList> mOrphanRows;  
@@ -181,67 +187,46 @@ TableRowsCollection::Init()
 // rowgroup's rows will be in the nsIDOMHTMLCollection* named "rows".  Note
 // that this may be null at any time.  This macro assumes an nsresult named
 // |rv| is in scope.
 #define DO_FOR_EACH_ROWGROUP(_code)                                  \
   do {                                                               \
     if (mParent) {                                                   \
       /* THead */                                                    \
       nsCOMPtr<nsIDOMHTMLTableSectionElement> rowGroup;              \
-      rv = mParent->GetTHead(getter_AddRefs(rowGroup));              \
-      if (NS_FAILED(rv)) {                                           \
-        break;                                                       \
-      }                                                              \
+      rowGroup = mParent->GetTHead();                                \
       nsCOMPtr<nsIDOMHTMLCollection> rows;                           \
       if (rowGroup) {                                                \
         rowGroup->GetRows(getter_AddRefs(rows));                     \
         do { /* gives scoping */                                     \
           _code                                                      \
         } while (0);                                                 \
       }                                                              \
-      nsCOMPtr<nsIDOMHTMLCollection> _tbodies;                       \
       /* TBodies */                                                  \
-      rv = mParent->GetTBodies(getter_AddRefs(_tbodies));            \
-      if (NS_FAILED(rv)) {                                           \
-        break;                                                       \
-      }                                                              \
-      if (_tbodies) {                                                \
-        nsCOMPtr<nsIDOMNode> _node;                                  \
-        PRUint32 _tbodyIndex = 0;                                    \
-        rv = _tbodies->Item(_tbodyIndex, getter_AddRefs(_node));     \
-        if (NS_FAILED(rv)) {                                         \
-          break;                                                     \
+      nsContentList *_tbodies = mParent->TBodies();                  \
+      nsINode * _node;                                               \
+      PRUint32 _tbodyIndex = 0;                                      \
+      _node = _tbodies->GetNodeAt(_tbodyIndex);                      \
+      while (_node) {                                                \
+        rowGroup = do_QueryInterface(_node);                         \
+        if (rowGroup) {                                              \
+          rowGroup->GetRows(getter_AddRefs(rows));                   \
+          do { /* gives scoping */                                   \
+            _code                                                    \
+          } while (0);                                               \
         }                                                            \
-        while (_node) {                                              \
-          rowGroup = do_QueryInterface(_node);                       \
-          if (rowGroup) {                                            \
-            rowGroup->GetRows(getter_AddRefs(rows));                 \
-            do { /* gives scoping */                                 \
-              _code                                                  \
-            } while (0);                                             \
-          }                                                          \
-          rv = _tbodies->Item(++_tbodyIndex, getter_AddRefs(_node)); \
-          if (NS_FAILED(rv)) {                                       \
-            break;                                                   \
-          }                                                          \
-        }                                                            \
-        if (NS_FAILED(rv)) {                                         \
-          break;                                                     \
-        }                                                            \
+        _node = _tbodies->GetNodeAt(++_tbodyIndex);                  \
       }                                                              \
       /* orphan rows */                                              \
       rows = mOrphanRows;                                            \
       do { /* gives scoping */                                       \
         _code                                                        \
       } while (0);                                                   \
       /* TFoot */                                                    \
-      rv = mParent->GetTFoot(getter_AddRefs(rowGroup));              \
-      if (NS_FAILED(rv)) {                                           \
-        break;                                                       \
-      }                                                              \
+      rowGroup = mParent->GetTFoot();                                \
       rows = nsnull;                                                 \
       if (rowGroup) {                                                \
         rowGroup->GetRows(getter_AddRefs(rows));                     \
         do { /* gives scoping */                                     \
           _code                                                      \
         } while (0);                                                 \
       }                                                              \
     }                                                                \
@@ -261,23 +246,22 @@ CountRowsInRowGroup(nsIDOMHTMLCollection
 
 // we re-count every call.  A better implementation would be to set
 // ourselves up as an observer of contentAppended, contentInserted,
 // and contentDeleted
 NS_IMETHODIMP 
 TableRowsCollection::GetLength(PRUint32* aLength)
 {
   *aLength=0;
-  nsresult rv = NS_OK;
 
   DO_FOR_EACH_ROWGROUP(
     *aLength += CountRowsInRowGroup(rows);
   );
 
-  return rv;
+  return NS_OK;
 }
 
 // Returns the item at index aIndex if available. If null is returned,
 // then aCount will be set to the number of rows in this row collection.
 // Otherwise, the value of aCount is undefined.
 static nsIContent*
 GetItemOrCountInRowGroup(nsIDOMHTMLCollection* rows,
                          PRUint32 aIndex, PRUint32* aCount)
@@ -291,91 +275,81 @@ GetItemOrCountInRowGroup(nsIDOMHTMLColle
       return list->GetNodeAt(aIndex);
     }
   }
   
   return nsnull;
 }
 
 nsIContent*
-TableRowsCollection::GetNodeAt(PRUint32 aIndex, nsresult *aResult)
+TableRowsCollection::GetNodeAt(PRUint32 aIndex)
 {
-  nsresult rv = NS_OK;
   DO_FOR_EACH_ROWGROUP(
     PRUint32 count;
     nsIContent* node = GetItemOrCountInRowGroup(rows, aIndex, &count);
     if (node) {
       return node; 
     }
 
     NS_ASSERTION(count <= aIndex, "GetItemOrCountInRowGroup screwed up");
     aIndex -= count;
   );
 
-  *aResult = rv;
-
   return nsnull;
 }
 
 NS_IMETHODIMP 
 TableRowsCollection::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
 {
-  nsresult rv;
-
-  nsISupports* node = GetNodeAt(aIndex, &rv);
+  nsISupports* node = GetNodeAt(aIndex);
   if (!node) {
     *aReturn = nsnull;
 
-    return rv;
+    return NS_OK;
   }
 
   return CallQueryInterface(node, aReturn);
 }
 
 static nsISupports*
 GetNamedItemInRowGroup(nsIDOMHTMLCollection* aRows, const nsAString& aName,
-                       nsWrapperCache** aCache, nsresult* aResult)
+                       nsWrapperCache** aCache)
 {
   nsCOMPtr<nsIHTMLCollection> rows = do_QueryInterface(aRows);
   if (rows) {
-    return rows->GetNamedItem(aName, aCache, aResult);
+    return rows->GetNamedItem(aName, aCache);
   }
 
-  *aResult = NS_OK;
   return nsnull;
 }
 
 nsISupports* 
 TableRowsCollection::GetNamedItem(const nsAString& aName,
-                                  nsWrapperCache** aCache,
-                                  nsresult* aResult)
+                                  nsWrapperCache** aCache)
 {
-  nsresult rv = NS_OK;
   DO_FOR_EACH_ROWGROUP(
-    nsISupports* item = GetNamedItemInRowGroup(rows, aName, aCache, aResult);
-    if (NS_FAILED(*aResult) || item) {
+    nsISupports* item = GetNamedItemInRowGroup(rows, aName, aCache);
+    if (item) {
       return item;
     }
   );
   *aCache = nsnull;
-  *aResult = rv;
   return nsnull;
 }
 
 NS_IMETHODIMP 
 TableRowsCollection::NamedItem(const nsAString& aName,
                                nsIDOMNode** aReturn)
 {
-  nsresult rv;
   nsWrapperCache *cache;
-  nsISupports* item = GetNamedItem(aName, &cache, &rv);
+  nsISupports* item = GetNamedItem(aName, &cache);
   if (!item) {
     *aReturn = nsnull;
 
-    return rv;
+    return NS_OK;
   }
 
   return CallQueryInterface(item, aReturn);
 }
 
 NS_IMETHODIMP
 TableRowsCollection::ParentDestroyed()
 {
@@ -505,17 +479,17 @@ nsHTMLTableElement::GetSection(nsIAtom *
   }
 
   return nsnull;
 }
 
 NS_IMETHODIMP
 nsHTMLTableElement::GetTHead(nsIDOMHTMLTableSectionElement** aValue)
 {
-  *aValue = GetSection(nsGkAtoms::thead).get();
+  *aValue = GetTHead().get();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLTableElement::SetTHead(nsIDOMHTMLTableSectionElement* aValue)
 {
   nsCOMPtr<nsIContent> content(do_QueryInterface(aValue));
@@ -542,17 +516,17 @@ nsHTMLTableElement::SetTHead(nsIDOMHTMLT
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsHTMLTableElement::GetTFoot(nsIDOMHTMLTableSectionElement** aValue)
 {
-  *aValue = GetSection(nsGkAtoms::tfoot).get();
+  *aValue = GetTFoot().get();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLTableElement::SetTFoot(nsIDOMHTMLTableSectionElement* aValue)
 {
   nsCOMPtr<nsIContent> content(do_QueryInterface(aValue));
@@ -592,27 +566,33 @@ nsHTMLTableElement::GetRows(nsIDOMHTMLCo
   NS_ADDREF(*aValue);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLTableElement::GetTBodies(nsIDOMHTMLCollection** aValue)
 {
+  NS_ADDREF(*aValue = TBodies());
+  return NS_OK;
+}
+
+nsContentList*
+nsHTMLTableElement::TBodies()
+{
   if (!mTBodies) {
     // Not using NS_GetContentList because this should not be cached
     mTBodies = new nsContentList(this,
                                  mNodeInfo->NamespaceID(),
                                  nsGkAtoms::tbody,
                                  nsGkAtoms::tbody,
                                  PR_FALSE);
   }
 
-  NS_ADDREF(*aValue = mTBodies);
-  return NS_OK;
+  return mTBodies;
 }
 
 NS_IMETHODIMP
 nsHTMLTableElement::CreateTHead(nsIDOMHTMLElement** aValue)
 {
   *aValue = nsnull;
   nsresult rv = NS_OK;
   nsCOMPtr<nsIDOMHTMLTableSectionElement> head;
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -1383,22 +1383,16 @@ nsHTMLDocument::AdoptNode(nsIDOMNode* aS
 }
 
 NS_IMETHODIMP
 nsHTMLDocument::NormalizeDocument()
 {
   return nsDocument::NormalizeDocument();
 }
 
-NS_IMETHODIMP
-nsHTMLDocument::GetDefaultView(nsIDOMWindow** aWindow)
-{
-  return nsDocument::GetDefaultView(aWindow);
-}
-
 //
 // nsIDOMHTMLDocument interface implementation
 //
 NS_IMETHODIMP
 nsHTMLDocument::GetTitle(nsAString& aTitle)
 {
   return nsDocument::GetTitle(aTitle);
 }
--- a/content/media/ogg/nsOggReader.cpp
+++ b/content/media/ogg/nsOggReader.cpp
@@ -1056,17 +1056,17 @@ nsresult nsOggReader::GetSeekRanges(nsTA
 {
   NS_ASSERTION(mDecoder->OnStateMachineThread(),
                "Should be on state machine thread.");
   mMonitor.AssertCurrentThreadIn();
   nsTArray<nsByteRange> cached;
   nsresult res = mDecoder->GetCurrentStream()->GetCachedRanges(cached);
   NS_ENSURE_SUCCESS(res, res);
 
-  for (PRUint32 index = 0; index < aRanges.Length(); index++) {
+  for (PRUint32 index = 0; index < cached.Length(); index++) {
     nsByteRange& range = cached[index];
     PRInt64 startTime = -1;
     PRInt64 endTime = -1;
     if (NS_FAILED(ResetDecode())) {
       return NS_ERROR_FAILURE;
     }
     // Ensure the offsets are after the header pages.
     PRInt64 startOffset = NS_MAX(cached[index].mStart, mDataOffset);
--- a/content/smil/nsDOMTimeEvent.cpp
+++ b/content/smil/nsDOMTimeEvent.cpp
@@ -34,16 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsDOMTimeEvent.h"
 #include "nsGUIEvent.h"
 #include "nsPresContext.h"
 #include "nsIInterfaceRequestorUtils.h"
+#include "nsIDOMAbstractView.h"
 
 nsDOMTimeEvent::nsDOMTimeEvent(nsPresContext* aPresContext, nsEvent* aEvent)
   : nsDOMEvent(aPresContext, aEvent ? aEvent : new nsUIEvent(PR_FALSE, 0, 0)),
     mDetail(0)
 {
   if (aEvent) {
     mEventIsInternal = PR_FALSE;
   } else {
@@ -86,33 +87,33 @@ NS_IMPL_RELEASE_INHERITED(nsDOMTimeEvent
 DOMCI_DATA(TimeEvent, nsDOMTimeEvent)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMTimeEvent)
   NS_INTERFACE_MAP_ENTRY(nsIDOMTimeEvent)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TimeEvent)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
 
 NS_IMETHODIMP
-nsDOMTimeEvent::GetView(nsIDOMWindow** aView)
+nsDOMTimeEvent::GetView(nsIDOMAbstractView** aView)
 {
   *aView = mView;
   NS_IF_ADDREF(*aView);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMTimeEvent::GetDetail(PRInt32* aDetail)
 {
   *aDetail = mDetail;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMTimeEvent::InitTimeEvent(const nsAString& aTypeArg,
-                              nsIDOMWindow* aViewArg,
+                              nsIDOMAbstractView* aViewArg,
                               PRInt32 aDetailArg)
 {
   nsresult rv = nsDOMEvent::InitEvent(aTypeArg, PR_FALSE /*doesn't bubble*/,
                                                 PR_FALSE /*can't cancel*/);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mDetail = aDetailArg;
   mView = aViewArg;
--- a/content/smil/nsDOMTimeEvent.h
+++ b/content/smil/nsDOMTimeEvent.h
@@ -53,13 +53,13 @@ public:
 
   // nsIDOMTimeEvent interface:
   NS_DECL_NSIDOMTIMEEVENT
 
   // Forward to base class
   NS_FORWARD_TO_NSDOMEVENT
 
 private:
-  nsCOMPtr<nsIDOMWindow> mView;
-  PRInt32 mDetail;
+  nsCOMPtr<nsIDOMAbstractView> mView;
+  PRInt32                      mDetail;
 };
 
 #endif // NS_DOMTIMEEVENT_H_
--- a/content/svg/content/src/nsSVGElement.cpp
+++ b/content/svg/content/src/nsSVGElement.cpp
@@ -46,16 +46,18 @@
 #include "nsIDOMMutationEvent.h"
 #include "nsMutationEvent.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsBindingManager.h"
 #include "nsXBLBinding.h"
 #include "nsStyleConsts.h"
 #include "nsDOMError.h"
 #include "nsIPresShell.h"
+#include "nsIDOMViewCSS.h"
+#include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIServiceManager.h"
 #include "nsIXBLService.h"
 #include "nsGkAtoms.h"
 #include "mozilla/css/StyleRule.h"
 #include "nsRuleWalker.h"
 #include "mozilla/css/Declaration.h"
 #include "nsCSSProps.h"
 #include "nsCSSParser.h"
--- a/content/svg/content/test/Makefile.in
+++ b/content/svg/content/test/Makefile.in
@@ -55,16 +55,17 @@ include $(topsrcdir)/config/rules.mk
 		a_href_helper_01.svg \
 		a_href_helper_02_03.svg \
 		a_href_helper_04.svg \
 		test_animLengthObjectIdentity.xhtml \
 		test_animLengthReadonly.xhtml \
 		test_animLengthRelativeUnits.xhtml \
 		test_animLengthUnits.xhtml \
 		test_bbox.xhtml \
+		test_bbox-with-invalid-viewBox.xhtml \
 		bbox-helper.svg \
 		bounds-helper.svg \
 		test_dataTypes.html \
 		dataTypes-helper.svg \
 		getCTM-helper.svg \
 		test_getCTM.html \
 		test_getSubStringLength.xhtml \
 		getSubStringLength-helper.svg \
new file mode 100644
--- /dev/null
+++ b/content/svg/content/test/test_bbox-with-invalid-viewBox.xhtml
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=433063
+-->
+<head>
+  <title>Test for getBBox when the viewBox is invalid</title>
+  <script type="application/javascript" src="/MochiKit/packed.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+
+<svg id="svg" xmlns="http://www.w3.org/2000/svg"
+     style="width:200px; height:200px;" viewBox="0 0 200 0">
+  <rect width="120" height="120"/>
+</svg>
+
+<pre id="test">
+<script class="testbody" type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+function run()
+{
+  var bbox = $("svg").getBBox();
+  is(bbox.x, 0, "Check bbox.x");
+  is(bbox.y, 0, "Check bbox.y");
+  is(bbox.width, 120, "Check bbox.width");
+  is(bbox.height, 120, "Check bbox.height");
+  SimpleTest.finish();
+}
+
+window.addEventListener("load", run, false);
+</script>
+</pre>
+</body>
+</html>
--- a/content/xml/document/src/nsXMLPrettyPrinter.cpp
+++ b/content/xml/document/src/nsXMLPrettyPrinter.cpp
@@ -33,17 +33,20 @@
  * 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 "nsXMLPrettyPrinter.h"
 #include "nsContentUtils.h"
+#include "nsIDOMDocumentView.h"
+#include "nsIDOMAbstractView.h"
 #include "nsIDOMCSSStyleDeclaration.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsIObserver.h"
 #include "nsIXSLTProcessor.h"
 #include "nsSyncLoadService.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMDocument.h"
 #include "nsIServiceManager.h"
@@ -87,23 +90,26 @@ nsXMLPrettyPrinter::PrettyPrint(nsIDocum
     if (internalWin) {
         internalWin->GetFrameElement(getter_AddRefs(frameElem));
     }
 
     if (frameElem) {
         nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
         nsCOMPtr<nsIDOMDocument> frameOwnerDoc;
         frameElem->GetOwnerDocument(getter_AddRefs(frameOwnerDoc));
-        if (frameOwnerDoc) {
-            nsCOMPtr<nsIDOMWindow> window;
-            frameOwnerDoc->GetDefaultView(getter_AddRefs(window));
-            if (window) {
-                window->GetComputedStyle(frameElem,
-                                         EmptyString(),
-                                         getter_AddRefs(computedStyle));
+        nsCOMPtr<nsIDOMDocumentView> docView = do_QueryInterface(frameOwnerDoc);
+        if (docView) {
+            nsCOMPtr<nsIDOMAbstractView> defaultView;
+            docView->GetDefaultView(getter_AddRefs(defaultView));
+            nsCOMPtr<nsIDOMViewCSS> defaultCSSView =
+                do_QueryInterface(defaultView);
+            if (defaultCSSView) {
+                defaultCSSView->GetComputedStyle(frameElem,
+                                                 EmptyString(),
+                                                 getter_AddRefs(computedStyle));
             }
         }
 
         if (computedStyle) {
             nsAutoString visibility;
             computedStyle->GetPropertyValue(NS_LITERAL_STRING("visibility"),
                                             visibility);
             if (!visibility.EqualsLiteral("visible")) {
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -1,10 +1,11 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
  * Software distributed under the License is distributed on an "AS IS" basis,
@@ -113,16 +114,17 @@
 #include "nsStyleConsts.h"
 #include "nsXPIDLString.h"
 #include "nsXULControllers.h"
 #include "nsIBoxObject.h"
 #include "nsPIBoxObject.h"
 #include "nsXULDocument.h"
 #include "nsXULPopupListener.h"
 #include "nsRuleWalker.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsCSSParser.h"
 #include "nsIListBoxObject.h"
 #include "nsContentUtils.h"
 #include "nsContentList.h"
 #include "nsMutationEvent.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsPIDOMWindow.h"
--- a/content/xul/document/test/test_bug583948.xul
+++ b/content/xul/document/test/test_bug583948.xul
@@ -13,29 +13,27 @@
 </body>
 
 <script>
 SimpleTest.waitForExplicitFinish();
 
 var attempts = 0;
 
 function update() {
-  setTimeout(function() {
-    if (otherWindow.location)
-      otherWindow.location.reload()
-    }, 1);
-  otherWindow.document.commandDispatcher.updateCommands('');
   // without the crash fix, this usually crashes after 2 to 4 reloads
   if (++attempts == 6) {
     ok(true, "didn't crash after 6 attempts");
     otherWindow.close();
-    SimpleTest.finish();
-  }
-  else {
-    setTimeout(update, 100);
+    SimpleTest.waitForFocus(function() {
+      SimpleTest.finish();
+    });
+  } else {
+    otherWindow.document.commandDispatcher.updateCommands('');
+    setTimeout(function() {
+      otherWindow.location.reload()
+    }, 0);
   }
 }
 
 var otherWindow = window.open("window_bug583948.xul", "_new", "chrome");
-setTimeout(update, 100);
 </script>
 
 </window>
--- a/content/xul/document/test/window_bug583948.xul
+++ b/content/xul/document/test/window_bug583948.xul
@@ -1,8 +1,8 @@
 <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="opener.update()">
 
 <command oncommandupdate="document.removeChild(document.documentElement)" commandupdater="true"/>
 <box command="c"/>
 <iframe/>
 
 </window>
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -45,16 +45,17 @@ include $(DEPTH)/config/autoconf.mk
 MODULE		= dom
 DIRS = \
   interfaces/base \
   interfaces/canvas \
   interfaces/core \
   interfaces/html \
   interfaces/events \
   interfaces/stylesheets \
+  interfaces/views \
   interfaces/sidebar \
   interfaces/css \
   interfaces/traversal \
   interfaces/range \
   interfaces/xbl \
   interfaces/xpath \
   interfaces/load-save \
   interfaces/xul \
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -187,16 +187,17 @@
 #include "nsDOMCSSAttrDeclaration.h"
 
 // XBL related includes.
 #include "nsIXBLService.h"
 #include "nsXBLBinding.h"
 #include "nsBindingManager.h"
 #include "nsIFrame.h"
 #include "nsIPresShell.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsStyleSet.h"
 #include "nsStyleContext.h"
 #include "nsAutoPtr.h"
 #include "nsMemory.h"
 
 // Tranformiix
@@ -247,16 +248,17 @@
 #include "nsIDOMTransitionEvent.h"
 #ifdef MOZ_CSS_ANIMATIONS
 #include "nsIDOMAnimationEvent.h"
 #endif
 #include "nsIDOMNSDocumentStyle.h"
 #include "nsIDOMDocumentRange.h"
 #include "nsIDOMDocumentTraversal.h"
 #include "nsIDOMDocumentXBL.h"
+#include "nsIDOMDocumentView.h"
 #include "nsIDOMElementCSSInlineStyle.h"
 #include "nsIDOMLinkStyle.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMNSHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMNSHTMLElement.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLAppletElement.h"
@@ -505,16 +507,18 @@
 #include "mozilla/dom/indexedDB/IDBCursor.h"
 #include "mozilla/dom/indexedDB/IDBKeyRange.h"
 #include "mozilla/dom/indexedDB/IDBIndex.h"
 #include "nsIIDBDatabaseException.h"
 #include "nsIDOMEventException.h"
 
 #include "nsIDOMMediaQueryList.h"
 
+#include "nsDOMTouchEvent.h"
+
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
   "chrome://global/locale/dom/dom.properties";
 
 // NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS
@@ -604,31 +608,33 @@ DOMCI_DATA(Notation, void)
     { _helper::doCreate },                                                    \
     nsnull,                                                                   \
     nsnull,                                                                   \
     nsnull,                                                                   \
     _flags,                                                                   \
     PR_TRUE,                                                                  \
     0,                                                                        \
     PR_FALSE,                                                                 \
+    PR_FALSE,                                                                 \
     NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                    \
   },
 
 #define NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA_WITH_NAME(_class, _name,         \
                                                        _helper, _flags)       \
   { #_name,                                                                   \
     nsnull,                                                                   \
     { _helper::doCreate },                                                    \
     nsnull,                                                                   \
     nsnull,                                                                   \
     nsnull,                                                                   \
     _flags,                                                                   \
     PR_TRUE,                                                                  \
     0,                                                                        \
     PR_TRUE,                                                                  \
+    PR_FALSE,                                                                 \
     NS_DEFINE_CLASSINFO_DATA_DEBUG(_class)                                    \
   },
 
 #define NS_DEFINE_CLASSINFO_DATA(_class, _helper, _flags)                     \
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(_class, _class, _helper, _flags)
 
 #define NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(_class, _helper, _flags)          \
   NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA_WITH_NAME(_class, _class, _helper, \
@@ -1491,16 +1497,23 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(IDBVersionChangeRequest, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBDatabaseException, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(EventException, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
+  NS_DEFINE_CLASSINFO_DATA(TouchPoint, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(TouchList, nsDOMTouchListSH,
+                           ARRAY_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(TouchEvent, nsDOMGenericSH,
+                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
+
 #ifdef MOZ_CSS_ANIMATIONS
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframesRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 #endif
 
   NS_DEFINE_CLASSINFO_DATA(MediaQueryList, nsDOMGenericSH,
@@ -1663,16 +1676,23 @@ jsid nsDOMClassInfo::sOnmessage_id      
 jsid nsDOMClassInfo::sOnbeforescriptexecute_id = JSID_VOID;
 jsid nsDOMClassInfo::sOnafterscriptexecute_id = JSID_VOID;
 jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID;
 jsid nsDOMClassInfo::sURL_id             = JSID_VOID;
 jsid nsDOMClassInfo::sKeyPath_id         = JSID_VOID;
 jsid nsDOMClassInfo::sAutoIncrement_id   = JSID_VOID;
 jsid nsDOMClassInfo::sUnique_id          = JSID_VOID;
 
+jsid nsDOMClassInfo::sOntouchstart_id    = JSID_VOID;
+jsid nsDOMClassInfo::sOntouchend_id      = JSID_VOID;
+jsid nsDOMClassInfo::sOntouchmove_id     = JSID_VOID;
+jsid nsDOMClassInfo::sOntouchenter_id    = JSID_VOID;
+jsid nsDOMClassInfo::sOntouchleave_id    = JSID_VOID;
+jsid nsDOMClassInfo::sOntouchcancel_id   = JSID_VOID;
+
 static const JSClass *sObjectClass = nsnull;
 
 /**
  * Set our JSClass pointer for the Object class
  */
 static void
 FindObjectClass(JSObject* aGlobalObject)
 {
@@ -1993,16 +2013,23 @@ nsDOMClassInfo::DefineStaticJSVals(JSCon
   SET_JSID_TO_STRING(sOnafterscriptexecute_id, cx, "onafterscriptexecute");
 #endif // MOZ_MEDIA
   SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject");
   SET_JSID_TO_STRING(sURL_id,             cx, "URL");
   SET_JSID_TO_STRING(sKeyPath_id,         cx, "keyPath");
   SET_JSID_TO_STRING(sAutoIncrement_id,   cx, "autoIncrement");
   SET_JSID_TO_STRING(sUnique_id,          cx, "unique");
 
+  SET_JSID_TO_STRING(sOntouchstart_id,    cx, "ontouchstart");
+  SET_JSID_TO_STRING(sOntouchend_id,      cx, "ontouchend");
+  SET_JSID_TO_STRING(sOntouchmove_id,     cx, "ontouchmove");
+  SET_JSID_TO_STRING(sOntouchenter_id,    cx, "ontouchenter");
+  SET_JSID_TO_STRING(sOntouchleave_id,    cx, "ontouchleave");
+  SET_JSID_TO_STRING(sOntouchcancel_id,   cx, "ontouchcancel");
+  
   return NS_OK;
 }
 
 static nsresult
 CreateExceptionFromResult(JSContext *cx, nsresult aResult)
 {
   nsCOMPtr<nsIExceptionService> xs =
     do_GetService(NS_EXCEPTIONSERVICE_CONTRACTID);
@@ -2128,16 +2155,17 @@ nsresult
 nsDOMClassInfo::RegisterClassName(PRInt32 aClassInfoID)
 {
   nsScriptNameSpaceManager *nameSpaceManager = nsJSRuntime::GetNameSpaceManager();
   NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED);
 
   nameSpaceManager->RegisterClassName(sClassInfoData[aClassInfoID].mName,
                                       aClassInfoID,
                                       sClassInfoData[aClassInfoID].mChromeOnly,
+                                      sClassInfoData[aClassInfoID].mDisabled,
                                       &sClassInfoData[aClassInfoID].mNameUTF16);
 
   return NS_OK;
 }
 
 // static
 nsresult
 nsDOMClassInfo::RegisterClassProtos(PRInt32 aClassInfoID)
@@ -2237,45 +2265,50 @@ nsDOMClassInfo::RegisterExternalClasses(
     rv = nameSpaceManager->RegisterExternalClassName(categoryEntry.get(), *cid);
     nsMemory::Free(cid);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return nameSpaceManager->RegisterExternalInterfaces(PR_TRUE);
 }
 
-#define _DOM_CLASSINFO_MAP_BEGIN(_class, _ifptr, _has_class_if)               \
+#define _DOM_CLASSINFO_MAP_BEGIN(_class, _ifptr, _has_class_if, _disabled)    \
   {                                                                           \
     nsDOMClassInfoData &d = sClassInfoData[eDOMClassInfo_##_class##_id];      \
     d.mProtoChainInterface = _ifptr;                                          \
     d.mHasClassInterface = _has_class_if;                                     \
     d.mInterfacesBitmap = kDOMClassInfo_##_class##_interfaces;                \
+    d.mDisabled = _disabled;                                                  \
     static const nsIID *interface_list[] = {
 
 #define DOM_CLASSINFO_MAP_BEGIN(_class, _interface)                           \
-  _DOM_CLASSINFO_MAP_BEGIN(_class, &NS_GET_IID(_interface), PR_TRUE)
-
+  _DOM_CLASSINFO_MAP_BEGIN(_class, &NS_GET_IID(_interface), PR_TRUE, PR_FALSE)
+
+#define DOM_CLASSINFO_MAP_BEGIN_MAYBE_DISABLE(_class, _interface, _disable)   \
+  _DOM_CLASSINFO_MAP_BEGIN(_class, &NS_GET_IID(_interface), PR_TRUE, _disable)
+  
 #define DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(_class, _interface)               \
-  _DOM_CLASSINFO_MAP_BEGIN(_class, &NS_GET_IID(_interface), PR_FALSE)
+  _DOM_CLASSINFO_MAP_BEGIN(_class, &NS_GET_IID(_interface), PR_FALSE, PR_FALSE)
 
 #define DOM_CLASSINFO_MAP_ENTRY(_if)                                          \
       &NS_GET_IID(_if),
 
 #define DOM_CLASSINFO_MAP_END                                                 \
       nsnull                                                                  \
     };                                                                        \
                                                                               \
     d.mInterfaces = interface_list;                                           \
   }
 
 #define DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES                                    \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSDocument)                                 \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentEvent)                              \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentStyle)                              \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSDocumentStyle)                            \
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentView)                               \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentRange)                              \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTraversal)                          \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentXBL)                                \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)                              \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)                                \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)                                      \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathEvaluator)                             \
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
@@ -2342,27 +2375,31 @@ nsDOMClassInfo::Init()
 
   if (nsGlobalWindow::HasIndexedDBSupport()) {
     DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMViewCSS)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMAbstractView)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageIndexedDB)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow_2_0_BRANCH)
     DOM_CLASSINFO_MAP_END
   } else {
     DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMViewCSS)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMAbstractView)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
       DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow_2_0_BRANCH)
     DOM_CLASSINFO_MAP_END
   }
 
   DOM_CLASSINFO_MAP_BEGIN(WindowUtils, nsIDOMWindowUtils)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowUtils)
   DOM_CLASSINFO_MAP_END
@@ -2417,21 +2454,30 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DOMConstructor, nsIDOMDOMConstructor)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(XMLDocument, nsIDOMXMLDocument)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMXMLDocument)
-    DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
-  DOM_CLASSINFO_MAP_END
+  if (nsDOMTouchEvent::PrefEnabled()) {
+    DOM_CLASSINFO_MAP_BEGIN(XMLDocument, nsIDOMXMLDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMXMLDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTouch)
+      DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
+    DOM_CLASSINFO_MAP_END
+  } else {
+    DOM_CLASSINFO_MAP_BEGIN(XMLDocument, nsIDOMXMLDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMXMLDocument)
+      DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
+    DOM_CLASSINFO_MAP_END
+  }
 
   DOM_CLASSINFO_MAP_BEGIN(DocumentType, nsIDOMDocumentType)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentType)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
   DOM_CLASSINFO_MAP_END
 
@@ -2581,21 +2627,30 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(HashChangeEvent, nsIDOMHashChangeEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHashChangeEvent)
     DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(HTMLDocument, nsIDOMHTMLDocument)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLDocument)
-    DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
-  DOM_CLASSINFO_MAP_END
+  if (nsDOMTouchEvent::PrefEnabled()) {
+    DOM_CLASSINFO_MAP_BEGIN(HTMLDocument, nsIDOMHTMLDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTouch)
+      DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
+    DOM_CLASSINFO_MAP_END
+  } else {
+    DOM_CLASSINFO_MAP_BEGIN(HTMLDocument, nsIDOMHTMLDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLDocument)
+      DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
+    DOM_CLASSINFO_MAP_END
+  }
 
   DOM_CLASSINFO_MAP_BEGIN(HTMLOptionsCollection, nsIDOMHTMLOptionsCollection)
     // Order is significant.  nsIDOMHTMLOptionsCollection.length shadows
     // nsIDOMHTMLCollection.length, which is readonly.
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLOptionsCollection)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSHTMLOptionCollection)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMHTMLCollection)
   DOM_CLASSINFO_MAP_END
@@ -2994,21 +3049,30 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Selection, nsISelection)
     DOM_CLASSINFO_MAP_ENTRY(nsISelection)
     DOM_CLASSINFO_MAP_ENTRY(nsISelection3)
   DOM_CLASSINFO_MAP_END
 
 #ifdef MOZ_XUL
-  DOM_CLASSINFO_MAP_BEGIN(XULDocument, nsIDOMXULDocument)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULDocument)
-    DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
-  DOM_CLASSINFO_MAP_END
+  if (nsDOMTouchEvent::PrefEnabled()) {
+    DOM_CLASSINFO_MAP_BEGIN(XULDocument, nsIDOMXULDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTouch)
+      DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
+    DOM_CLASSINFO_MAP_END
+  } else {
+    DOM_CLASSINFO_MAP_BEGIN(XULDocument, nsIDOMXULDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULDocument)
+      DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
+    DOM_CLASSINFO_MAP_END  
+  }
 
   DOM_CLASSINFO_MAP_BEGIN(XULElement, nsIDOMXULElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOM3Node)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElementCSSInlineStyle)
@@ -3059,16 +3123,18 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMChromeWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageIndexedDB)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMViewCSS)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMAbstractView)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(RangeException, nsIDOMRangeException)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMRangeException)
     DOM_CLASSINFO_MAP_ENTRY(nsIException)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentList, nsIDOMHTMLCollection)
@@ -3137,23 +3203,34 @@ nsDOMClassInfo::Init()
 
   // XXX - the proto chain stuff is sort of hackish, because of the MI in
   // the SVG interfaces. I doubt that extending the proto on one interface
   // works properly on an element which inherits off multiple interfaces.
   // Tough luck. - bbaetz
 
   // The SVG document
 
-  DOM_CLASSINFO_MAP_BEGIN(SVGDocument, nsIDOMSVGDocument)
-    // Order is significant.  nsIDOMDocument.title shadows
-    // nsIDOMSVGDocument.title, which is readonly.
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGDocument)
-    DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
-  DOM_CLASSINFO_MAP_END
+  if (nsDOMTouchEvent::PrefEnabled()) {
+    DOM_CLASSINFO_MAP_BEGIN(SVGDocument, nsIDOMSVGDocument)
+      // Order is significant.  nsIDOMDocument.title shadows
+      // nsIDOMSVGDocument.title, which is readonly.
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocumentTouch)
+      DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
+    DOM_CLASSINFO_MAP_END
+  } else {
+    DOM_CLASSINFO_MAP_BEGIN(SVGDocument, nsIDOMSVGDocument)
+      // Order is significant.  nsIDOMDocument.title shadows
+      // nsIDOMSVGDocument.title, which is readonly.
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMDocument)
+      DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGDocument)
+      DOM_CLASSINFO_DOCUMENT_MAP_ENTRIES
+    DOM_CLASSINFO_MAP_END
+  }
 
   // SVG element classes
 
   DOM_CLASSINFO_MAP_BEGIN(SVGAElement, nsIDOMSVGAElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGAElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
@@ -3941,16 +4018,18 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowInternal)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMViewCSS)
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMAbstractView)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageWindow)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorageIndexedDB)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DataContainerEvent, nsIDOMDataContainerEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDataContainerEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
@@ -4237,16 +4316,32 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIException)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(EventException, nsIDOMEventException)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventException)
     DOM_CLASSINFO_MAP_ENTRY(nsIException)
   DOM_CLASSINFO_MAP_END
 
+  DOM_CLASSINFO_MAP_BEGIN_MAYBE_DISABLE(TouchPoint, nsIDOMTouchPoint,
+                                        !nsDOMTouchEvent::PrefEnabled())
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMTouchPoint)
+  DOM_CLASSINFO_MAP_END
+
+  DOM_CLASSINFO_MAP_BEGIN_MAYBE_DISABLE(TouchList, nsIDOMTouchList,
+                                        !nsDOMTouchEvent::PrefEnabled())
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMTouchList)
+  DOM_CLASSINFO_MAP_END
+  
+  DOM_CLASSINFO_MAP_BEGIN_MAYBE_DISABLE(TouchEvent, nsIDOMTouchEvent,
+                                        !nsDOMTouchEvent::PrefEnabled())
+    DOM_CLASSINFO_MAP_ENTRY(nsIDOMTouchEvent)
+    DOM_CLASSINFO_UI_EVENT_MAP_ENTRIES
+  DOM_CLASSINFO_MAP_END
+
 #ifdef MOZ_CSS_ANIMATIONS
   DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframeRule, nsIDOMMozCSSKeyframeRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframeRule)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframesRule, nsIDOMMozCSSKeyframesRule)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframesRule)
   DOM_CLASSINFO_MAP_END
@@ -5046,16 +5141,23 @@ nsDOMClassInfo::ShutDown()
   sOnmessage_id       = JSID_VOID;
   sOnbeforescriptexecute_id = JSID_VOID;
   sOnafterscriptexecute_id = JSID_VOID;
   sWrappedJSObject_id = JSID_VOID;
   sKeyPath_id         = JSID_VOID;
   sAutoIncrement_id   = JSID_VOID;
   sUnique_id          = JSID_VOID;
 
+  sOntouchstart_id    = JSID_VOID;
+  sOntouchend_id      = JSID_VOID;
+  sOntouchmove_id     = JSID_VOID;
+  sOntouchenter_id    = JSID_VOID;
+  sOntouchleave_id    = JSID_VOID;
+  sOntouchcancel_id   = JSID_VOID;
+
   NS_IF_RELEASE(sXPConnect);
   NS_IF_RELEASE(sSecMan);
   sIsInitialized = PR_FALSE;
 }
 
 // Window helper
 
 NS_IMETHODIMP
@@ -7586,23 +7688,31 @@ nsEventReceiverSH::ReallyIsEventName(jsi
   case 'r' :
     return (id == sOnreadystatechange_id ||
             id == sOnreset_id            ||
             id == sOnresize_id           ||
             id == sOnratechange_id);
   case 's' :
     return (id == sOnscroll_id       ||
             id == sOnselect_id       ||
-            id == sOnsubmit_id       ||
+            id == sOnsubmit_id       || 
             id == sOnseeked_id       ||
             id == sOnseeking_id      ||
             id == sOnstalled_id      ||
             id == sOnsuspend_id);
   case 't':
-    return id == sOntimeupdate_id;
+    return id == sOntimeupdate_id ||
+      (nsDOMTouchEvent::PrefEnabled() &&
+       (id == sOntouchstart_id ||
+        id == sOntouchend_id ||
+        id == sOntouchmove_id ||
+        id == sOntouchenter_id ||
+        id == sOntouchleave_id ||
+        id == sOntouchcancel_id));
+    
   case 'u' :
     return id == sOnunload_id;
   case 'v':
     return id == sOnvolumechange_id;
   case 'w':
     return id == sOnwaiting_id;
   }
 
@@ -8346,17 +8456,17 @@ nsHTMLCollectionSH::GetItemAt(nsISupport
     // If this assertion fires the QI implementation for the object in
     // question doesn't use the nsIHTMLCollection pointer as the nsISupports
     // pointer. That must be fixed, or we'll crash...
     NS_ABORT_IF_FALSE(collection_qi == collection, "Uh, fix QI!");
   }
 #endif
 
   nsINode *item;
-  *aCache = item = collection->GetNodeAt(aIndex, aResult);
+  *aCache = item = collection->GetNodeAt(aIndex);
   return item;
 }
 
 nsISupports*
 nsHTMLCollectionSH::GetNamedItem(nsISupports *aNative,
                                  const nsAString& aName,
                                  nsWrapperCache **aCache,
                                  nsresult *aResult)
@@ -8368,17 +8478,17 @@ nsHTMLCollectionSH::GetNamedItem(nsISupp
 
     // If this assertion fires the QI implementation for the object in
     // question doesn't use the nsIHTMLCollection pointer as the nsISupports
     // pointer. That must be fixed, or we'll crash...
     NS_ABORT_IF_FALSE(collection_qi == collection, "Uh, fix QI!");
   }
 #endif
 
-  return collection->GetNamedItem(aName, aCache, aResult);
+  return collection->GetNamedItem(aName, aCache);
 }
 
 
 // ContentList helper
 nsresult
 nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                            JSObject *globalObj, JSObject **parentObj)
 {
@@ -8408,27 +8518,27 @@ nsContentListSH::GetLength(nsIXPConnectW
 
 nsISupports*
 nsContentListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                            nsWrapperCache **aCache, nsresult *aResult)
 {
   nsContentList *list = nsContentList::FromSupports(aNative);
 
   nsIContent *item;
-  *aCache = item = list->GetNodeAt(aIndex, aResult);
+  *aCache = item = list->GetNodeAt(aIndex);
   return item;
 }
 
 nsISupports*
 nsContentListSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
                               nsWrapperCache **aCache, nsresult *aResult)
 {
   nsContentList *list = nsContentList::FromSupports(aNative);
 
-  return list->GetNamedItem(aName, aCache, aResult);
+  return list->GetNamedItem(aName, aCache);
 }
 
 NS_IMETHODIMP
 nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsid id, PRUint32 flags,
                          JSObject **objp, PRBool *_retval)
 {
   nsresult rv;
@@ -9486,18 +9596,17 @@ nsHTMLSelectElementSH::NewResolve(nsIXPC
 {
   PRInt32 n = GetArrayIndexFromId(cx, id);
   if (n >= 0) {
     nsHTMLSelectElement *s =
       nsHTMLSelectElement::FromSupports(GetNative(wrapper, obj));
 
     nsHTMLOptionCollection *options = s->GetOptions();
     if (options) {
-      nsresult rv;
-      nsISupports *node = options->GetNodeAt(n, &rv);
+      nsISupports *node = options->GetNodeAt(n);
       if (node) {
         *objp = obj;
         *_retval = JS_DefineElement(cx, obj, n, JSVAL_VOID, nsnull, nsnull,
                                     JSPROP_ENUMERATE | JSPROP_SHARED);
 
         return NS_OK;
       }
     }
@@ -9516,17 +9625,17 @@ nsHTMLSelectElementSH::GetProperty(nsIXP
   nsresult rv = NS_OK;
   if (n >= 0) {
     nsHTMLSelectElement *s =
       nsHTMLSelectElement::FromSupports(GetNative(wrapper, obj));
 
     nsHTMLOptionCollection *options = s->GetOptions();
 
     if (options) {
-      nsISupports *node = options->GetNodeAt(n, &rv);
+      nsISupports *node = options->GetNodeAt(n);
 
       rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx), node,
                       &NS_GET_IID(nsIDOMNode), PR_TRUE, vp);
       if (NS_SUCCEEDED(rv)) {
         rv = NS_SUCCESS_I_DID_SOMETHING;
       }
       return rv;
     }
@@ -10274,16 +10383,24 @@ nsISupports*
 nsPaintRequestListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                                 nsWrapperCache **aCache, nsresult *aResult)
 {
   nsPaintRequestList* list = nsPaintRequestList::FromSupports(aNative);
 
   return list->GetItemAt(aIndex);
 }
 
+nsISupports*
+nsDOMTouchListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                            nsWrapperCache **aCache, nsresult *aResult)
+{
+  nsDOMTouchList* list = static_cast<nsDOMTouchList*>(aNative);
+  return list->GetItemAt(aIndex);
+}
+
 #ifdef MOZ_XUL
 // TreeColumns helper
 
 nsISupports*
 nsTreeColumnsSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                            nsWrapperCache **aCache, nsresult *aResult)
 {
   nsTreeColumns* columns = nsTreeColumns::FromSupports(aNative);
--- a/dom/base/nsDOMClassInfo.h
+++ b/dom/base/nsDOMClassInfo.h
@@ -93,17 +93,18 @@ struct nsDOMClassInfoData
 
   nsIClassInfo *mCachedClassInfo; // low bit is set to 1 if external,
                                   // so be sure to mask if necessary!
   const nsIID *mProtoChainInterface;
   const nsIID **mInterfaces;
   PRUint32 mScriptableFlags : 31; // flags must not use more than 31 bits!
   PRUint32 mHasClassInterface : 1;
   PRUint32 mInterfacesBitmap;
-  PRBool mChromeOnly;
+  PRPackedBool mChromeOnly;
+  PRPackedBool mDisabled;
 #ifdef NS_DEBUG
   PRUint32 mDebugID;
 #endif
 };
 
 struct nsExternalDOMClassInfoData : public nsDOMClassInfoData
 {
   const nsCID *mConstructorCID;
@@ -354,16 +355,23 @@ public:
   static jsid sOnmessage_id;
   static jsid sOnbeforescriptexecute_id;
   static jsid sOnafterscriptexecute_id;
   static jsid sWrappedJSObject_id;
   static jsid sURL_id;
   static jsid sKeyPath_id;
   static jsid sAutoIncrement_id;
   static jsid sUnique_id;
+  
+  static jsid sOntouchstart_id;
+  static jsid sOntouchend_id;
+  static jsid sOntouchmove_id;
+  static jsid sOntouchenter_id;
+  static jsid sOntouchleave_id;
+  static jsid sOntouchcancel_id;
 
 protected:
   static JSPropertyOp sXPCNativeWrapperGetPropertyOp;
   static JSPropertyOp sXrayWrapperPropertyHolderGetPropertyOp;
 };
 
 
 inline
@@ -1499,16 +1507,36 @@ protected:
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsPaintRequestListSH(aData);
   }
 };
 
+class nsDOMTouchListSH : public nsArraySH
+{
+protected:
+  nsDOMTouchListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
+  {
+  }
+
+  virtual ~nsDOMTouchListSH()
+  {
+  }
+
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsWrapperCache **aCache, nsresult *aResult);
+
+public:
+  static nsIClassInfo* doCreate(nsDOMClassInfoData* aData)
+  {
+    return new nsDOMTouchListSH(aData);
+  }
+};
 
 #ifdef MOZ_XUL
 // TreeColumns helper
 
 class nsTreeColumnsSH : public nsNamedArraySH
 {
 protected:
   nsTreeColumnsSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -508,14 +508,18 @@ DOMCI_CLASS(IDBCursorWithValue)
 DOMCI_CLASS(IDBKeyRange)
 DOMCI_CLASS(IDBIndex)
 DOMCI_CLASS(IDBVersionChangeEvent)
 DOMCI_CLASS(IDBVersionChangeRequest)
 DOMCI_CLASS(IDBDatabaseException)
 
 DOMCI_CLASS(EventException)
 
+DOMCI_CLASS(TouchPoint)
+DOMCI_CLASS(TouchList)
+DOMCI_CLASS(TouchEvent)
+
 #ifdef MOZ_CSS_ANIMATIONS
 DOMCI_CLASS(MozCSSKeyframeRule)
 DOMCI_CLASS(MozCSSKeyframesRule)
 #endif
 
 DOMCI_CLASS(MediaQueryList)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1856,8 +1856,21 @@ nsDOMWindowUtils::LeafLayersPartitionWin
     *aResult = PR_FALSE;
   }
   if (!coveredRegion.IsEqual(root->GetVisibleRegion())) {
     *aResult = PR_FALSE;
   }
 #endif
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsDOMWindowUtils::GetMayHaveTouchEventListeners(PRBool* aResult)
+{
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  nsPIDOMWindow* innerWindow = mWindow->GetCurrentInnerWindow();
+  *aResult = innerWindow ? innerWindow->HasTouchEventListeners() : PR_FALSE;
+  return NS_OK;
+}
+
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -106,16 +106,17 @@
 #include "nsIHTMLDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #ifndef MOZ_DISABLE_DOMCRYPTO
 #include "nsIDOMCrypto.h"
 #endif
 #include "nsIDOMDocument.h"
 #include "nsIDOMNSDocument.h"
+#include "nsIDOMDocumentView.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMDocumentEvent.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMMessageEvent.h"
 #include "nsIDOMPopupBlockedEvent.h"
 #include "nsIDOMPopStateEvent.h"
@@ -1328,16 +1329,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
   NS_INTERFACE_MAP_ENTRY(nsIDOMJSWindow)
   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
   NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOM3EventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsPIDOMWindow)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMViewCSS)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMAbstractView)
   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageWindow)
   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageIndexedDB)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWindow_2_0_BRANCH)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window)
   OUTER_WINDOW_ONLY
     NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
@@ -7931,16 +7934,20 @@ nsGlobalWindow::UpdateCanvasFocus(PRBool
           nsCanvasFrame* canvasFrame = FindCanvasFrame(frame);
           if (canvasFrame) {
               canvasFrame->SetHasFocus(PR_FALSE);
           }
       }      
   }
 }
 
+//*****************************************************************************
+// nsGlobalWindow::nsIDOMViewCSS
+//*****************************************************************************
+
 NS_IMETHODIMP
 nsGlobalWindow::GetComputedStyle(nsIDOMElement* aElt,
                                  const nsAString& aPseudoElt,
                                  nsIDOMCSSStyleDeclaration** aReturn)
 {
   FORWARD_TO_OUTER(GetComputedStyle, (aElt, aPseudoElt, aReturn),
                    NS_ERROR_NOT_INITIALIZED);
 
@@ -7968,16 +7975,37 @@ nsGlobalWindow::GetComputedStyle(nsIDOME
   NS_ENSURE_SUCCESS(rv, rv);
 
   *aReturn = compStyle.forget().get();
 
   return NS_OK;
 }
 
 //*****************************************************************************
+// nsGlobalWindow::nsIDOMAbstractView
+//*****************************************************************************
+
+NS_IMETHODIMP
+nsGlobalWindow::GetDocument(nsIDOMDocumentView ** aDocumentView)
+{
+  NS_ENSURE_ARG_POINTER(aDocumentView);
+
+  nsresult rv = NS_OK;
+
+  if (mDocument) {
+    rv = CallQueryInterface(mDocument, aDocumentView);
+  }
+  else {
+    *aDocumentView = nsnull;
+  }
+
+  return rv;
+}
+
+//*****************************************************************************
 // nsGlobalWindow::nsIDOMStorageWindow
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)
 {
   FORWARD_TO_INNER(GetSessionStorage, (aSessionStorage), NS_ERROR_UNEXPECTED);
 
@@ -8803,24 +8831,24 @@ nsGlobalWindow::SetTimeoutOrInterval(nsI
     return NS_OK;
   }
 
   // Disallow negative intervals.  If aIsInterval also disallow 0,
   // because we use that as a "don't repeat" flag.
   interval = NS_MAX(aIsInterval ? 1 : 0, interval);
 
   // Make sure we don't proceed with an interval larger than our timer
-  // code can handle.
-  if (interval > PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE)) {
-    interval = PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE);
+  // code can handle. (Note: we already forced |interval| to be non-negative,
+  // so the PRUint32 cast (to avoid compiler warnings) is ok.)
+  PRUint32 maxTimeoutMs = PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE);
+  if (static_cast<PRUint32>(interval) > maxTimeoutMs) {
+    interval = maxTimeoutMs;
   }
 
   nsTimeout *timeout = new nsTimeout();
-  if (!timeout)
-    return NS_ERROR_OUT_OF_MEMORY;
 
   // Increment the timeout's reference count to represent this function's hold
   // on the timeout.
   timeout->AddRef();
 
   if (aIsInterval) {
     timeout->mInterval = interval;
   }
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -57,16 +57,17 @@
 
 // Interfaces Needed
 #include "nsDOMWindowList.h"
 #include "nsIBaseWindow.h"
 #include "nsIBrowserDOMWindow.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocShellTreeItem.h"
 #include "nsIDOMClientInformation.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOM3EventTarget.h"
 #include "nsIDOMNSEventTarget.h"
 #include "nsIDOMNavigator.h"
 #include "nsIDOMNavigatorGeolocation.h"
 #include "nsIDOMNavigatorDesktopNotification.h"
 #include "nsIDOMLocation.h"
 #include "nsIDOMWindowInternal.h"
@@ -274,16 +275,17 @@ JSObject *NS_NewOuterWindowProxy(JSConte
 class nsGlobalWindow : public nsPIDOMWindow,
                        public nsIScriptGlobalObject,
                        public nsIDOMJSWindow,
                        public nsIScriptObjectPrincipal,
                        public nsIDOMEventTarget,
                        public nsPIDOMEventTarget,
                        public nsIDOM3EventTarget,
                        public nsIDOMNSEventTarget,
+                       public nsIDOMViewCSS,
                        public nsIDOMStorageWindow,
                        public nsIDOMStorageIndexedDB,
                        public nsSupportsWeakReference,
                        public nsIInterfaceRequestor,
                        public nsIDOMWindow_2_0_BRANCH,
                        public nsWrapperCache,
                        public PRCListStr
 {
@@ -412,16 +414,22 @@ public:
 
   virtual NS_HIDDEN_(PRBool) CanClose();
   virtual NS_HIDDEN_(nsresult) ForceClose();
 
   virtual NS_HIDDEN_(void) SetHasOrientationEventListener();
   virtual NS_HIDDEN_(void) MaybeUpdateTouchState();
   virtual NS_HIDDEN_(void) UpdateTouchState();
 
+  // nsIDOMViewCSS
+  NS_DECL_NSIDOMVIEWCSS
+
+  // nsIDOMAbstractView
+  NS_DECL_NSIDOMABSTRACTVIEW
+
   // nsIDOMStorageWindow
   NS_DECL_NSIDOMSTORAGEWINDOW
 
   // nsIInterfaceRequestor
   NS_DECL_NSIINTERFACEREQUESTOR
 
   // Object Management
   nsGlobalWindow(nsGlobalWindow *aOuterWindow);
--- a/dom/base/nsPIDOMWindow.h
+++ b/dom/base/nsPIDOMWindow.h
@@ -73,18 +73,18 @@ class nsIDocument;
 class nsIScriptTimeoutHandler;
 struct nsTimeout;
 class nsScriptObjectHolder;
 class nsXBLPrototypeHandler;
 class nsIArray;
 class nsPIWindowRoot;
 
 #define NS_PIDOMWINDOW_IID \
-{ 0x8d8be7db, 0xffaa, 0x4962, \
-  { 0xa7, 0x27, 0xb7, 0x0f, 0xc9, 0xfa, 0xd3, 0x0e } }
+{ 0xafc4849b, 0x21d3, 0x45ea, \
+  { 0x8b, 0xfd, 0x61, 0xec, 0x12, 0x5d, 0x38, 0x64 } }
 
 class nsPIDOMWindow : public nsIDOMWindowInternal
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_PIDOMWINDOW_IID)
 
   virtual nsPIDOMWindow* GetPrivateRoot() = 0;
 
@@ -437,16 +437,21 @@ public:
    * or content in that document) has a touch event listener.
    */
   void SetHasTouchEventListeners()
   {
     mMayHaveTouchEventListener = PR_TRUE;
     MaybeUpdateTouchState();
   }
 
+  PRBool HasTouchEventListeners()
+  {
+    return mMayHaveTouchEventListener;
+  }
+
   /**
    * Call this to check whether some node (this window, its document,
    * or content in that document) has a MozAudioAvailable event listener.
    */
   PRBool HasAudioAvailableEventListeners()
   {
     return mMayHaveAudioAvailableEventListener;
   }
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -488,17 +488,18 @@ nsScriptNameSpaceManager::LookupName(con
                                      const nsGlobalNameStruct **aNameStruct,
                                      const PRUnichar **aClassName)
 {
   GlobalNameMapEntry *entry =
     static_cast<GlobalNameMapEntry *>
                (PL_DHashTableOperate(&mGlobalNames, &aName,
                                         PL_DHASH_LOOKUP));
 
-  if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
+  if (PL_DHASH_ENTRY_IS_BUSY(entry) &&
+      !((&entry->mGlobalName)->mDisabled)) {
     *aNameStruct = &entry->mGlobalName;
     if (aClassName) {
       *aClassName = entry->mKey.get();
     }
   } else {
     *aNameStruct = nsnull;
     if (aClassName) {
       *aClassName = nsnull;
@@ -507,16 +508,17 @@ nsScriptNameSpaceManager::LookupName(con
 
   return NS_OK;
 }
 
 nsresult
 nsScriptNameSpaceManager::RegisterClassName(const char *aClassName,
                                             PRInt32 aDOMClassInfoID,
                                             PRBool aPrivileged,
+                                            PRBool aDisabled,
                                             const PRUnichar **aResult)
 {
   if (!nsCRT::IsAscii(aClassName)) {
     NS_ERROR("Trying to register a non-ASCII class name");
     return NS_OK;
   }
   nsGlobalNameStruct *s = AddToHash(aClassName, aResult);
   NS_ENSURE_TRUE(s, NS_ERROR_OUT_OF_MEMORY);
@@ -534,16 +536,17 @@ nsScriptNameSpaceManager::RegisterClassN
 
   NS_ASSERTION(s->mType == nsGlobalNameStruct::eTypeNotInitialized ||
                s->mType == nsGlobalNameStruct::eTypeInterface,
                "Whaaa, JS environment name clash!");
 
   s->mType = nsGlobalNameStruct::eTypeClassConstructor;
   s->mDOMClassInfoID = aDOMClassInfoID;
   s->mChromeOnly = aPrivileged;
+  s->mDisabled = aDisabled;
 
   return NS_OK;
 }
 
 nsresult
 nsScriptNameSpaceManager::RegisterClassProto(const char *aClassName,
                                              const nsIID *aConstructorProtoIID,
                                              PRBool *aFoundOld)
--- a/dom/base/nsScriptNameSpaceManager.h
+++ b/dom/base/nsScriptNameSpaceManager.h
@@ -81,16 +81,17 @@ struct nsGlobalNameStruct
     eTypeClassConstructor,
     eTypeClassProto,
     eTypeExternalClassInfoCreator,
     eTypeExternalClassInfo,
     eTypeExternalConstructorAlias
   } mType;
 
   PRBool mChromeOnly;
+  PRBool mDisabled;
 
   union {
     PRInt32 mDOMClassInfoID; // eTypeClassConstructor
     nsIID mIID; // eTypeInterface, eTypeClassProto
     nsExternalDOMClassInfoData* mData; // eTypeExternalClassInfo
     ConstructorAlias* mAlias; // eTypeExternalConstructorAlias
     nsCID mCID; // All other types...
   };
@@ -126,16 +127,17 @@ public:
   // in the nsGlobalNameStruct.
   nsresult LookupName(const nsAString& aName,
                       const nsGlobalNameStruct **aNameStruct,
                       const PRUnichar **aClassName = nsnull);
 
   nsresult RegisterClassName(const char *aClassName,
                              PRInt32 aDOMClassInfoID,
                              PRBool aPrivileged,
+                             PRBool aDisabled,
                              const PRUnichar **aResult);
 
   nsresult RegisterClassProto(const char *aClassName,
                               const nsIID *aConstructorProtoIID,
                               PRBool *aFoundOld);
 
   nsresult RegisterExternalInterfaces(PRBool aAsProto);
 
--- a/dom/interfaces/base/domstubs.idl
+++ b/dom/interfaces/base/domstubs.idl
@@ -72,16 +72,20 @@ interface DOMException;
 interface RangeException;
 
 // Style Sheets
 interface nsIDOMStyleSheetList;
 interface nsIDOMLinkStyle;
 interface nsIDOMStyleSheet;
 interface nsIDOMMediaList;
 
+// Views
+interface nsIDOMAbstractView;
+interface nsIDOMDocumentView;
+
 // Base
 interface nsIDOMWindow;
 interface nsIDOMWindowInternal;
 interface nsIDOMWindowCollection;
 interface nsIDOMPlugin;
 interface nsIDOMPluginArray;
 interface nsIDOMMimeType;
 interface nsIDOMMimeTypeArray;
@@ -121,8 +125,9 @@ interface nsIDOMHTMLTableSectionElement;
 
 // Range
 interface nsIDOMRange;
 
 // Crypto
 interface nsIDOMCRMFObject;
 interface nsIDOMCrypto;
 interface nsIDOMPkcs11;
+
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -42,20 +42,21 @@
 interface nsISelection;
 
 /**
  * The nsIDOMWindow interface is the primary interface for a DOM
  * window object. It represents a single window object that may
  * contain child windows if the document in the window contains a
  * HTML frameset document or if the document contains iframe elements.
  *
- * @see <http://www.whatwg.org/html/#window>
+ * This interface is not officially defined by any standard bodies, it
+ * originates from the defacto DOM Level 0 standard.
  */
 
-[scriptable, uuid(ff7d278f-93db-4078-b89a-058c8e1270b4)]
+[scriptable, uuid(a6cf906b-15b3-11d2-932e-00805f8add32)]
 interface nsIDOMWindow : nsISupports
 {
   /**
    * Accessor for the document in this window.
    */
   readonly attribute nsIDOMDocument                     document;
 
   /**
@@ -144,15 +145,9 @@ interface nsIDOMWindow : nsISupports
    * Method for scrolling this window by a number of pages.
    */
   void                      scrollByPages(in long numPages);
 
   /**
    * Method for sizing this window to the content in the window.
    */
   void                      sizeToContent();
-
-  /**
-   * @see <http://dev.w3.org/csswg/cssom/#dom-window-getcomputedstyle>
-   */
-  nsIDOMCSSStyleDeclaration getComputedStyle(in nsIDOMElement elt, 
-                                             [optional] in DOMString pseudoElt);
 };
--- a/dom/interfaces/base/nsIDOMWindow2.idl
+++ b/dom/interfaces/base/nsIDOMWindow2.idl
@@ -35,17 +35,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMWindow.idl"
 
 interface nsIDOMOfflineResourceList;
 interface nsIDOMBlob;
 
-[scriptable, uuid(e2796e00-14de-4ce0-acfe-0374bc0e715d)]
+[scriptable, uuid(efff0d88-3b94-4375-bdeb-676a847ecd7d)]
 interface nsIDOMWindow2 : nsIDOMWindow
 {
   /**
    * Get the window root for this window. This is useful for hooking
    * up event listeners to this window and every other window nested
    * in the window root.
    */
   [noscript] readonly attribute nsIDOMEventTarget windowRoot;
--- a/dom/interfaces/base/nsIDOMWindowInternal.idl
+++ b/dom/interfaces/base/nsIDOMWindowInternal.idl
@@ -41,17 +41,17 @@
 
 interface nsIPrompt;
 interface nsIControllers;
 interface nsIDOMLocation;
 interface nsIVariant;
 interface nsIAnimationFrameListener;
 interface nsIDOMMediaQueryList;
 
-[scriptable, uuid(4d95736f-8130-43cb-a276-5bc554eca80a)]
+[scriptable, uuid(04eafa93-efbe-4254-9d65-91c344fa7ff2)]
 interface nsIDOMWindowInternal : nsIDOMWindow2
 {
   readonly attribute nsIDOMWindowInternal        window;
 
   /* [replaceable] self */
   readonly attribute nsIDOMWindowInternal        self;
 
   readonly attribute nsIDOMNavigator             navigator;
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -61,17 +61,17 @@ interface nsIDOMNode;
 interface nsIDOMNodeList;
 interface nsIDOMElement;
 interface nsIDOMHTMLCanvasElement;
 interface nsIDOMEvent;
 interface nsITransferable;
 interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 
-[scriptable, uuid(3828e648-af61-47e1-b9bc-89ca51bc19f2)]
+[scriptable, uuid(663e33d7-eca2-42e8-af92-5df6a5e222df)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -876,9 +876,14 @@ interface nsIDOMWindowUtils : nsISupport
 
   /**
    * Checks the layer tree for this window and returns true
    * if all layers have transforms that are translations by integers,
    * no leaf layers overlap, and the union of the leaf layers is exactly
    * the bounds of the window. Always returns true in non-DEBUG builds.
    */
   boolean leafLayersPartitionWindow();
+
+  /**
+   * true if the (current inner) window may have event listeners for touch events.
+   */
+  readonly attribute boolean mayHaveTouchEventListeners;
 };
--- a/dom/interfaces/core/nsIDOMDocument.idl
+++ b/dom/interfaces/core/nsIDOMDocument.idl
@@ -47,17 +47,17 @@
  * cannot exist outside the context of a Document, the nsIDOMDocument 
  * interface also contains the factory methods needed to create these 
  * objects.
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[scriptable, uuid(d12f0ecf-434a-4b5c-81ad-354e3b9037b9)]
+[scriptable, uuid(2d305b95-a030-4d24-a12c-7fabf61a8c3c)]
 interface nsIDOMDocument : nsIDOMNode
 {
   readonly attribute nsIDOMDocumentType         doctype;
   readonly attribute nsIDOMDOMImplementation    implementation;
   readonly attribute nsIDOMElement              documentElement;
   nsIDOMElement                 createElement(in DOMString tagName)
                                   raises(DOMException);
   nsIDOMDocumentFragment        createDocumentFragment();
@@ -103,16 +103,9 @@ interface nsIDOMDocument : nsIDOMNode
                                         // raises(DOMException) on setting
   // Introduced in DOM Level 3:
            attribute DOMString       documentURI;
   // Introduced in DOM Level 3:
   nsIDOMNode         adoptNode(in nsIDOMNode source)
                                         raises(DOMException);
   // Introduced in DOM Level 3:
   void               normalizeDocument();
-
-  /**
-   * The window associated with this document.
-   *
-   * @see http://www.whatwg.org/html/#dom-document-defaultview
-   */
-  readonly attribute nsIDOMWindow    defaultView;
 };
--- a/dom/interfaces/core/nsIDOMXMLDocument.idl
+++ b/dom/interfaces/core/nsIDOMXMLDocument.idl
@@ -33,17 +33,17 @@
  * 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 "nsIDOMDocument.idl"
 
-[scriptable, uuid(68e4448c-eb64-48ea-801a-0c83008d2607)]
+[scriptable, uuid(f493687c-ea80-471b-965b-11467ebea24b)]
 interface nsIDOMXMLDocument : nsIDOMDocument
 {
   // DOM Level 3 Load & Save, DocumentLS
   // http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS
   /**
    * Whether to load synchronously or asynchronously.
    * The default is async==true.
    */
--- a/dom/interfaces/css/Makefile.in
+++ b/dom/interfaces/css/Makefile.in
@@ -66,16 +66,17 @@ XPIDLSRCS =					\
 	nsIDOMCSSMozDocumentRule.idl		\
 	nsIDOMCSSPageRule.idl			\
 	nsIDOMCSSStyleRule.idl			\
 	nsIDOMCSSUnknownRule.idl		\
 	nsIDOMCounter.idl			\
 	nsIDOMDocumentCSS.idl			\
 	nsIDOMRGBColor.idl			\
 	nsIDOMRect.idl				\
+	nsIDOMViewCSS.idl			\
 	nsIDOMNSRGBAColor.idl			\
 	$(NULL)
 
 ifdef MOZ_CSS_ANIMATIONS
 XPIDLSRCS +=					\
 	nsIDOMMozCSSKeyframeRule.idl		\
 	nsIDOMMozCSSKeyframesRule.idl		\
 	$(NULL)
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/css/nsIDOMViewCSS.idl
@@ -0,0 +1,49 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Johnny Stenback <jst@netscape.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDOMAbstractView.idl"
+
+[scriptable, uuid(0b9341f3-95d4-4fa4-adcd-e119e0db2889)]
+interface nsIDOMViewCSS : nsIDOMAbstractView
+{
+  /**
+   * @see <http://dev.w3.org/csswg/cssom/#dom-window-getcomputedstyle>
+   */
+  nsIDOMCSSStyleDeclaration getComputedStyle(in nsIDOMElement elt, 
+                                             [optional] in DOMString pseudoElt);
+};
--- a/dom/interfaces/events/Makefile.in
+++ b/dom/interfaces/events/Makefile.in
@@ -83,16 +83,17 @@ XPIDLSRCS =					\
 	nsIDOMNSMouseEvent.idl			\
 	nsIDOMMozTouchEvent.idl			\
 	nsIDOMOrientationEvent.idl              \
 	nsIDOMScrollAreaEvent.idl		\
 	nsIDOMTransitionEvent.idl		\
 	nsIDOMPopStateEvent.idl			\
 	nsIDOMCloseEvent.idl			\
 	nsIDOMEventException.idl		\
+	nsIDOMTouchEvent.idl			\
 	nsIDOMHashChangeEvent.idl		\
 	$(NULL)
 
 ifdef MOZ_CSS_ANIMATIONS
 XPIDLSRCS +=					\
 	nsIDOMAnimationEvent.idl		\
 	$(NULL)
 endif
--- a/dom/interfaces/events/nsIDOMDragEvent.idl
+++ b/dom/interfaces/events/nsIDOMDragEvent.idl
@@ -33,27 +33,28 @@
  * 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 "domstubs.idl"
 #include "nsIDOMMouseEvent.idl"
 
+interface nsIDOMAbstractView;
 interface nsIDOMDataTransfer;
 
-[scriptable, uuid(0f4fef03-c0e9-406c-a754-c01148e431ae)]
+[scriptable, uuid(98351627-62d7-4b07-bbf3-78009b20764b)]
 interface nsIDOMDragEvent : nsIDOMMouseEvent
 {
   readonly attribute nsIDOMDataTransfer dataTransfer;
 
   void initDragEvent(in DOMString typeArg,
                      in boolean canBubbleArg,
                      in boolean cancelableArg,
-                     in nsIDOMWindow aView,
+                     in nsIDOMAbstractView aView,
                      in long aDetail,
                      in long aScreenX,
                      in long aScreenY,
                      in long aClientX,
                      in long aClientY,
                      in boolean aCtrlKey,
                      in boolean aAltKey,
                      in boolean aShiftKey,
--- a/dom/interfaces/events/nsIDOMKeyEvent.idl
+++ b/dom/interfaces/events/nsIDOMKeyEvent.idl
@@ -34,17 +34,17 @@
  * 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 "nsIDOMUIEvent.idl"
 
-[scriptable, uuid(e44d7977-20f2-442e-bc13-0f2f52992a4c)]
+[scriptable, uuid(028e0e6e-8b01-11d3-aae7-0010838a3123)]
 interface nsIDOMKeyEvent : nsIDOMUIEvent
 {
   const unsigned long DOM_VK_CANCEL         = 0x03;
   const unsigned long DOM_VK_HELP           = 0x06;
   const unsigned long DOM_VK_BACK_SPACE     = 0x08;
   const unsigned long DOM_VK_TAB            = 0x09;
   const unsigned long DOM_VK_CLEAR          = 0x0C;
   const unsigned long DOM_VK_RETURN         = 0x0D;
@@ -188,16 +188,16 @@ interface nsIDOMKeyEvent : nsIDOMUIEvent
   readonly attribute boolean          altKey;
   readonly attribute boolean          ctrlKey;
   readonly attribute boolean          shiftKey;
   readonly attribute boolean          metaKey;
 
   void                      initKeyEvent(in DOMString typeArg,
                                          in boolean canBubbleArg,
                                          in boolean cancelableArg,
-                                         in nsIDOMWindow viewArg,
+                                         in nsIDOMAbstractView viewArg,
                                          in boolean ctrlKeyArg,
                                          in boolean altKeyArg,
                                          in boolean shiftKeyArg,
                                          in boolean metaKeyArg,
                                          in unsigned long keyCodeArg,
                                          in unsigned long charCodeArg);
 };
--- a/dom/interfaces/events/nsIDOMMouseEvent.idl
+++ b/dom/interfaces/events/nsIDOMMouseEvent.idl
@@ -42,17 +42,17 @@
 /**
  * The nsIDOMMouseEvent interface is the datatype for all mouse events
  * in the Document Object Model.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Events/
  */
 
-[scriptable, uuid(73558605-f479-493e-86d1-9794cd117fef)]
+[scriptable, uuid(ff751edc-8b02-aae7-0010-8301838a3123)]
 interface nsIDOMMouseEvent : nsIDOMUIEvent
 {
   readonly attribute long               screenX;
   readonly attribute long               screenY;
 
   readonly attribute long               clientX;
   readonly attribute long               clientY;
 
@@ -62,17 +62,17 @@ interface nsIDOMMouseEvent : nsIDOMUIEve
   readonly attribute boolean            metaKey;
 
   readonly attribute unsigned short     button;
   readonly attribute nsIDOMEventTarget  relatedTarget;
 
   void                      initMouseEvent(in DOMString typeArg,
                                            in boolean canBubbleArg,
                                            in boolean cancelableArg,
-                                           in nsIDOMWindow viewArg,
+                                           in nsIDOMAbstractView viewArg,
                                            in long detailArg,
                                            in long screenXArg,
                                            in long screenYArg,
                                            in long clientXArg,
                                            in long clientYArg,
                                            in boolean ctrlKeyArg,
                                            in boolean altKeyArg,
                                            in boolean shiftKeyArg,
--- a/dom/interfaces/events/nsIDOMMouseScrollEvent.idl
+++ b/dom/interfaces/events/nsIDOMMouseScrollEvent.idl
@@ -33,28 +33,28 @@
  * 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 "nsIDOMMouseEvent.idl"
 
-[scriptable, uuid(af08bce0-6821-4bac-8964-0fcee4be549a)]
+[scriptable, uuid(ba8d1a7e-b475-4542-8d32-01e7ea7b8091)]
 interface nsIDOMMouseScrollEvent : nsIDOMMouseEvent
 {
   const long HORIZONTAL_AXIS = 1;
   const long VERTICAL_AXIS = 2;
 
   readonly attribute long axis;
 
   void                initMouseScrollEvent(in DOMString typeArg,
                                            in boolean canBubbleArg,
                                            in boolean cancelableArg,
-                                           in nsIDOMWindow viewArg,
+                                           in nsIDOMAbstractView viewArg,
                                            in long detailArg,
                                            in long screenXArg,
                                            in long screenYArg,
                                            in long clientXArg,
                                            in long clientYArg,
                                            in boolean ctrlKeyArg,
                                            in boolean altKeyArg,
                                            in boolean shiftKeyArg,
--- a/dom/interfaces/events/nsIDOMMozTouchEvent.idl
+++ b/dom/interfaces/events/nsIDOMMozTouchEvent.idl
@@ -35,25 +35,25 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 
 #include "nsIDOMMouseEvent.idl"
 
 
-[scriptable, uuid(e9ed248b-1995-482f-8407-33ae7744bb9c)]
+[scriptable, uuid(9b454391-0190-4313-a070-1e26e9bf6f31)]
 interface nsIDOMMozTouchEvent : nsIDOMMouseEvent
 {
   readonly attribute unsigned long streamId;
 
   void initMozTouchEvent(in DOMString typeArg,
                          in boolean canBubbleArg,
                          in boolean cancelableArg,
-                         in nsIDOMWindow viewArg,
+                         in nsIDOMAbstractView viewArg,
                          in long detailArg,
                          in long screenXArg,
                          in long screenYArg,
                          in long clientXArg,
                          in long clientYArg,
                          in boolean ctrlKeyArg,
                          in boolean altKeyArg,
                          in boolean shiftKeyArg,
--- a/dom/interfaces/events/nsIDOMNSMouseEvent.idl
+++ b/dom/interfaces/events/nsIDOMNSMouseEvent.idl
@@ -38,17 +38,17 @@
 
 #include "nsIDOMMouseEvent.idl"
 
 /**
  * The nsIDOMNSMouseEvent interface extends nsIDOMMouseEvent
  * by providing various information related to the mouse event.
  */
 
-[scriptable, uuid(8418a402-3c9b-431a-80a7-a59b23ed57a0)]
+[scriptable, uuid(f5dd5fbb-f4ff-4277-819c-f31aa1dafc32)]
 interface nsIDOMNSMouseEvent : nsIDOMMouseEvent
 {
   // Finger or touch pressure event value
   // ranges between 0.0 and 1.0
   readonly attribute float mozPressure;
 
   const unsigned short    MOZ_SOURCE_UNKNOWN    = 0;
   const unsigned short    MOZ_SOURCE_MOUSE      = 1;
@@ -58,17 +58,17 @@ interface nsIDOMNSMouseEvent : nsIDOMMou
   const unsigned short    MOZ_SOURCE_TOUCH      = 5;
   const unsigned short    MOZ_SOURCE_KEYBOARD   = 6;
 
   readonly attribute unsigned short mozInputSource;
 
   void                initNSMouseEvent(in DOMString typeArg,
                                        in boolean canBubbleArg,
                                        in boolean cancelableArg,
-                                       in nsIDOMWindow viewArg,
+                                       in nsIDOMAbstractView viewArg,
                                        in long detailArg,
                                        in long screenXArg,
                                        in long screenYArg,
                                        in long clientXArg,
                                        in long clientYArg,
                                        in boolean ctrlKeyArg,
                                        in boolean altKeyArg,
                                        in boolean shiftKeyArg,
--- a/dom/interfaces/events/nsIDOMScrollAreaEvent.idl
+++ b/dom/interfaces/events/nsIDOMScrollAreaEvent.idl
@@ -32,27 +32,27 @@
  * 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 "nsIDOMUIEvent.idl"
 
-[scriptable, uuid(911c3352-6690-421c-9bbe-6bd34f1600dc)]
+[scriptable, uuid(b2f49035-4a2f-4e62-8fb0-deb68b0de4d9)]
 interface nsIDOMScrollAreaEvent : nsIDOMUIEvent
 {
   // Scroll area client rect
   readonly attribute float x;
   readonly attribute float y;
   readonly attribute float width;
   readonly attribute float height;
 
   void initScrollAreaEvent(in DOMString aEventType,
                            in boolean aCanBubble,
                            in boolean aCancelable,
-                           in nsIDOMWindow aView,
+                           in nsIDOMAbstractView aView,
                            in long aDetail,
                            in float x,
                            in float y,
                            in float width,
                            in float height);
 };
--- a/dom/interfaces/events/nsIDOMSimpleGestureEvent.idl
+++ b/dom/interfaces/events/nsIDOMSimpleGestureEvent.idl
@@ -92,17 +92,17 @@
  * Default behavior:
  *
  * Some operating systems support default behaviors for gesture events
  * when they are not handled by the application. Consumers should
  * use event.preventDefault() to prevent default behavior when
  * consuming events.
  */
 
-[scriptable, uuid(fe6b7df3-be7c-4a0b-99a2-da84e956e2f5)]
+[scriptable, uuid(cb68e879-f710-415d-a871-9a550860df01)]
 interface nsIDOMSimpleGestureEvent : nsIDOMMouseEvent
 {
   /* Swipe direction constants */
   const unsigned long DIRECTION_UP = 1;
   const unsigned long DIRECTION_DOWN = 2;
   const unsigned long DIRECTION_LEFT = 4;
   const unsigned long DIRECTION_RIGHT = 8;
   
@@ -143,17 +143,17 @@ interface nsIDOMSimpleGestureEvent : nsI
    * and current/final width between the two touch points on the input
    * device and are measured in pixels.
    */
   readonly attribute double delta;
 
   void initSimpleGestureEvent(in DOMString typeArg,
                               in boolean canBubbleArg,
                               in boolean cancelableArg,
-                              in nsIDOMWindow viewArg,
+                              in nsIDOMAbstractView viewArg,
                               in long detailArg,
                               in long screenXArg,
                               in long screenYArg,
                               in long clientXArg,
                               in long clientYArg,
                               in boolean ctrlKeyArg,
                               in boolean altKeyArg,
                               in boolean shiftKeyArg,
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/events/nsIDOMTouchEvent.idl
@@ -0,0 +1,109 @@
+/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
+/* ***** 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 nsIDOMTouchEvent.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Olli Pettay <Olli.Pettay@helsinki.fi> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIDOMUIEvent.idl"
+interface nsIVariant;
+
+/**
+ * @see http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
+ */
+
+[scriptable, uuid(f9f200ad-228f-4879-bc9e-a13bd6bb82ef)]
+interface nsIDOMTouchPoint : nsISupports {
+  readonly attribute long              identifier;
+  readonly attribute nsIDOMEventTarget target;
+  readonly attribute long              pageX;
+  readonly attribute long              pageY;
+  readonly attribute long              screenX;
+  readonly attribute long              screenY;
+  readonly attribute long              clientX;
+  readonly attribute long              clientY;
+  readonly attribute long              radiusX;
+  readonly attribute long              radiusY;
+  readonly attribute float             rotationAngle;
+  readonly attribute float             force;
+};
+
+[scriptable, uuid(60706eb7-d50d-4379-b01c-e78e6af84213)]
+interface nsIDOMTouchList : nsISupports {
+  readonly attribute unsigned long length;
+  nsIDOMTouchPoint item(in unsigned long index);
+  nsIDOMTouchPoint identifiedPoint(in long identifier);
+};
+
+[scriptable, uuid(df94b20b-7998-4f00-935c-ee2c6b179711)]
+interface nsIDOMTouchEvent : nsIDOMUIEvent {
+  readonly attribute nsIDOMTouchList touches;
+  readonly attribute nsIDOMTouchList targetTouches;
+  readonly attribute nsIDOMTouchList changedTouches;
+  readonly attribute boolean         altKey;
+  readonly attribute boolean         metaKey;
+  readonly attribute boolean         ctrlKey;
+  readonly attribute boolean         shiftKey;
+  void initTouchEvent(in DOMString type,
+                      in boolean canBubble,
+                      in boolean cancelable,
+                      in nsIDOMAbstractView view,
+                      in long detail,
+                      in boolean ctrlKey,
+                      in boolean altKey,
+                      in boolean shiftKey,
+                      in boolean metaKey,
+                      in nsIDOMTouchList touches,
+                      in nsIDOMTouchList targetTouches,
+                      in nsIDOMTouchList changedTouches);
+};
+
+[scriptable, uuid(922e0f11-28b9-4560-9fb8-869fe143845f)]
+interface nsIDOMDocumentTouch : nsISupports {
+  nsIDOMTouchPoint createTouch([optional] in nsIDOMAbstractView view,
+                               [optional] in nsIDOMEventTarget target,
+                               [optional] in long identifier,
+                               [optional] in long pageX,
+                               [optional] in long pageY,
+                               [optional] in long screenX,
+                               [optional] in long screenY,
+                               [optional] in long clientX,
+                               [optional] in long clientY,
+                               [optional] in long radiusX,
+                               [optional] in long radiusY,
+                               [optional] in float rotationAngle,
+                               [optional] in float force);
+  
+
+  nsIDOMTouchList createTouchList([optional] in nsIVariant aPoints);
+};
--- a/dom/interfaces/events/nsIDOMUIEvent.idl
+++ b/dom/interfaces/events/nsIDOMUIEvent.idl
@@ -42,19 +42,19 @@
 /**
  * The nsIDOMUIEvent interface is the datatype for all UI events in the
  * Document Object Model.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Events/
  */
 
-[scriptable, uuid(25f28689-3f78-47e8-8d76-15b936faf8c1)]
+[scriptable, uuid(a6cf90c3-15b3-11d2-932e-00805f8add32)]
 interface nsIDOMUIEvent : nsIDOMEvent
 {
-  readonly attribute nsIDOMWindow       view;
+  readonly attribute nsIDOMAbstractView view;
   readonly attribute long               detail;
   void                      initUIEvent(in DOMString typeArg,
                                         in boolean canBubbleArg,
                                         in boolean cancelableArg,
-                                        in nsIDOMWindow viewArg,
+                                        in nsIDOMAbstractView viewArg,
                                         in long detailArg);
 };
--- a/dom/interfaces/html/nsIDOMHTMLDocument.idl
+++ b/dom/interfaces/html/nsIDOMHTMLDocument.idl
@@ -45,17 +45,17 @@
  *
  * This interface is trying to follow the DOM Level 2 HTML specification:
  * http://www.w3.org/TR/DOM-Level-2-HTML/
  *
  * with changes from the work-in-progress WHATWG HTML specification:
  * http://www.whatwg.org/specs/web-apps/current-work/
  */
 
-[scriptable, uuid(42bb545e-be46-4f4f-8c0a-6c948ea0c1d4)]
+[scriptable, uuid(2d7a0f2e-6b1c-4e93-bbea-122eb0a8a513)]
 interface nsIDOMHTMLDocument : nsIDOMDocument
 {
            attribute DOMString            title;
   readonly attribute DOMString            referrer;
   // domain is readonly per spec, but it's settable in
   // nsIDOMNSHTMLDocument
   [noscript] readonly attribute DOMString domain;
   readonly attribute DOMString            URL;
--- a/dom/interfaces/smil/nsIDOMTimeEvent.idl
+++ b/dom/interfaces/smil/nsIDOMTimeEvent.idl
@@ -40,18 +40,18 @@
 /**
  * The SMIL TimeEvent interface.
  *
  * For more information please refer to:
  * http://www.w3.org/TR/SMIL/smil-timing.html#Events-TimeEvent
  * http://www.w3.org/TR/SVG/animate.html#InterfaceTimeEvent
  */
 
-[scriptable, uuid(873785cc-d8be-48af-8b30-5c566e3f4e6e)]
+[scriptable, uuid(0d309c26-ddbb-44cb-9af1-3008972349e3)]
 interface nsIDOMTimeEvent : nsIDOMEvent
 {
   readonly attribute long detail;
-  readonly attribute nsIDOMWindow view;
+  readonly attribute nsIDOMAbstractView view;
   
   void initTimeEvent(in DOMString typeArg,
-                     in nsIDOMWindow viewArg,
+                     in nsIDOMAbstractView viewArg,
                      in long detailArg);
 };
--- a/dom/interfaces/svg/nsIDOMSVGDocument.idl
+++ b/dom/interfaces/svg/nsIDOMSVGDocument.idl
@@ -34,17 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMDocument.idl"
 
 interface nsIDOMSVGSVGElement;
 
-[scriptable, uuid(907f1ada-5ace-4789-8c25-0c79f251044d)]
+[scriptable, uuid(dcac0765-b258-4e0b-9862-6470eb9876ba)]
 interface nsIDOMSVGDocument : nsIDOMDocument
                          /* , nsIDOMDocumentEvent */
 {
   readonly attribute DOMString title;
   readonly attribute DOMString referrer;
   readonly attribute DOMString domain;
   readonly attribute DOMString URL;
   readonly attribute nsIDOMSVGSVGElement rootElement;
--- a/dom/interfaces/svg/nsIDOMSVGZoomEvent.idl
+++ b/dom/interfaces/svg/nsIDOMSVGZoomEvent.idl
@@ -40,17 +40,17 @@
 /**
  * For more information on this interface please see
  * http://www.w3.org/TR/SVG11/script.html#InterfaceSVGZoomEvent
  */
 
 interface nsIDOMSVGRect;
 interface nsIDOMSVGPoint;
 
-[scriptable, uuid(7298880d-127d-470d-a8ac-e5a8e5969270)]
+[scriptable, uuid(339a8c7a-552e-4cbc-8d96-8370a3939358)]
 interface nsIDOMSVGZoomEvent : nsIDOMUIEvent
 {
   readonly attribute nsIDOMSVGRect  zoomRectScreen;
   readonly attribute float          previousScale;
   readonly attribute nsIDOMSVGPoint previousTranslate;
   readonly attribute float          newScale;
   readonly attribute nsIDOMSVGPoint newTranslate;
 };
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/views/Makefile.in
@@ -0,0 +1,54 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= dom
+XPIDL_MODULE	= dom_views
+GRE_MODULE	= 1
+
+SDK_XPIDLSRCS =                                 \
+	nsIDOMDocumentView.idl			\
+	nsIDOMAbstractView.idl			\
+	$(NULL)
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/views/nsIDOMAbstractView.idl
@@ -0,0 +1,53 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Johnny Stenback <jst@netscape.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "domstubs.idl"
+
+/**
+ * The nsIDOMAbstractView interface is a datatype for a view in the
+ * Document Object Model.
+ *
+ * For more information on this interface please see
+ * http://www.w3.org/TR/DOM-Level-2-Views
+ */
+
+[scriptable, uuid(F51EBADE-8B1A-11D3-AAE7-0010830123B4)]
+interface nsIDOMAbstractView : nsISupports
+{
+  readonly attribute nsIDOMDocumentView     document;
+};
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/views/nsIDOMDocumentView.idl
@@ -0,0 +1,54 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Johnny Stenback <jst@netscape.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "domstubs.idl"
+
+/**
+ * The nsIDOMDocumentView interface is a datatype for a document that
+ * supports views in the Document Object Model.
+ *
+ * For more information on this interface please see
+ * http://www.w3.org/TR/DOM-Level-2-Views
+ */
+
+[scriptable, uuid(1ACDB2BA-1DD2-11B2-95BC-9542495D2569)]
+interface nsIDOMDocumentView : nsISupports
+{
+  readonly attribute nsIDOMAbstractView     defaultView;
+};
+
--- a/dom/interfaces/xul/nsIDOMXULCommandEvent.idl
+++ b/dom/interfaces/xul/nsIDOMXULCommandEvent.idl
@@ -38,17 +38,17 @@
 
 /**
  * This interface is supported by command events, which are dispatched to
  * XUL elements as a result of mouse or keyboard activation.
  */
 
 #include "nsIDOMUIEvent.idl"
 
-[scriptable, uuid(1d78da1e-2177-4b8f-9b11-41e78d1e60f7)]
+[scriptable, uuid(f9fa8205-a988-4828-9228-f3332d5475ac)]
 interface nsIDOMXULCommandEvent : nsIDOMUIEvent
 {
   /**
    * Command events support the same set of modifier keys as mouse and key
    * events.
    */
   readonly attribute boolean ctrlKey;
   readonly attribute boolean shiftKey;
@@ -63,16 +63,16 @@ interface nsIDOMXULCommandEvent : nsIDOM
   readonly attribute nsIDOMEvent sourceEvent;
 
   /**
    * Creates a new command event with the given attributes.
    */
   void initCommandEvent(in DOMString typeArg,
                         in boolean canBubbleArg,
                         in boolean cancelableArg,
-                        in nsIDOMWindow viewArg,
+                        in nsIDOMAbstractView viewArg,
                         in long detailArg,
                         in boolean ctrlKeyArg,
                         in boolean altKeyArg,
                         in boolean shiftKeyArg,
                         in boolean metaKeyArg,
                         in nsIDOMEvent sourceEvent);
 };
--- a/dom/src/threads/nsDOMWorker.cpp
+++ b/dom/src/threads/nsDOMWorker.cpp
@@ -378,21 +378,16 @@ nsDOMWorkerFunctions::LoadScripts(JSCont
   return JS_TRUE;
 }
 
 JSBool
 nsDOMWorkerFunctions::NewXMLHttpRequest(JSContext* aCx,
                                         uintN aArgc,
                                         jsval* aVp)
 {
-  JSObject *obj = JS_THIS_OBJECT(aCx, aVp);
-  if (!obj) {
-    return JS_FALSE;
-  }
-
   nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
   NS_ASSERTION(worker, "This should be set by the DOM thread service!");
 
   if (worker->IsCanceled()) {
     return JS_FALSE;
   }
 
   if (aArgc) {
@@ -415,17 +410,17 @@ nsDOMWorkerFunctions::NewXMLHttpRequest(
   rv = worker->AddFeature(xhr, aCx);
   if (NS_FAILED(rv)) {
     JS_ReportOutOfMemory(aCx);
     return JS_FALSE;
   }
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> xhrWrapped;
   jsval v;
-  rv = nsContentUtils::WrapNative(aCx, obj,
+  rv = nsContentUtils::WrapNative(aCx, JSVAL_TO_OBJECT(JS_CALLEE(aCx, aVp)),
                                   static_cast<nsIXMLHttpRequest*>(xhr), &v,
                                   getter_AddRefs(xhrWrapped));
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Failed to wrap XMLHttpRequest!");
     return JS_FALSE;
   }
 
   JS_SET_RVAL(aCs, aVp, v);
@@ -654,21 +649,18 @@ nsDOMWorkerFunctions::GetInstanceCommon(
 }
 
 JSBool
 nsDOMWorkerFunctions::MakeNewWorker(JSContext* aCx,
                                     uintN aArgc,
                                     jsval* aVp,
                                     WorkerPrivilegeModel aPrivilegeModel)
 {
-  JSObject *obj = JS_THIS_OBJECT(aCx, aVp);
-  if (!obj) {
-    return JS_FALSE;
-  }
-
+  JSObject *obj = JSVAL_TO_OBJECT(JS_CALLEE(aCx, aVp));
+    
   nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
   NS_ASSERTION(worker, "This should be set by the DOM thread service!");
 
   if (worker->IsCanceled()) {
     return JS_FALSE;
   }
 
   if (!aArgc) {
@@ -698,18 +690,18 @@ nsDOMWorkerFunctions::MakeNewWorker(JSCo
                                               JS_ARGV(aCx, aVp));
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Couldn't initialize new worker!");
     return JS_FALSE;
   }
 
   nsCOMPtr<nsIXPConnectJSObjectHolder> workerWrapped;
   jsval v;
-  rv = nsContentUtils::WrapNative(aCx, obj, static_cast<nsIWorker*>(newWorker),
-                                  &v, getter_AddRefs(workerWrapped));
+  rv = nsContentUtils::WrapNative(aCx, obj, static_cast<nsIWorker*>(newWorker), &v, 
+                                  getter_AddRefs(workerWrapped));
   if (NS_FAILED(rv)) {
     JS_ReportError(aCx, "Failed to wrap new worker!");
     return JS_FALSE;
   }
 
   JS_SET_RVAL(aCx, aVp, v);
   return JS_TRUE;
 }
@@ -762,37 +754,33 @@ nsDOMWorkerFunctions::CTypesLazyGetter(J
   jsval ctypes;
   return JS_DeletePropertyById(aCx, aObj, aId) &&
          JS_InitCTypesClass(aCx, aObj) &&
          JS_GetProperty(aCx, aObj, "ctypes", &ctypes) &&
          JS_SetCTypesCallbacks(aCx, JSVAL_TO_OBJECT(ctypes), &sCallbacks) &&
          JS_GetPropertyById(aCx, aObj, aId, aVp);
 }
 #endif
-
 JSFunctionSpec gDOMWorkerFunctions[] = {
   { "dump",                nsDOMWorkerFunctions::Dump,                1, 0 },
   { "setTimeout",          nsDOMWorkerFunctions::SetTimeout,          1, 0 },
   { "clearTimeout",        nsDOMWorkerFunctions::KillTimeout,         1, 0 },
   { "setInterval",         nsDOMWorkerFunctions::SetInterval,         1, 0 },
   { "clearInterval",       nsDOMWorkerFunctions::KillTimeout,         1, 0 },
   { "importScripts",       nsDOMWorkerFunctions::LoadScripts,         1, 0 },
-  { "XMLHttpRequest",      nsDOMWorkerFunctions::NewXMLHttpRequest,   0, 0 },
-  { "Worker",              nsDOMWorkerFunctions::NewWorker,           1, 0 },
+  { "XMLHttpRequest",      nsDOMWorkerFunctions::NewXMLHttpRequest,   0, JSFUN_CONSTRUCTOR },
+  { "Worker",              nsDOMWorkerFunctions::NewWorker,           1, JSFUN_CONSTRUCTOR },
   { "atob",                nsDOMWorkerFunctions::AtoB,                1, 0 },
   { "btoa",                nsDOMWorkerFunctions::BtoA,                1, 0 },
   { nsnull,                nsnull,                                    0, 0 }
 };
-
 JSFunctionSpec gDOMWorkerChromeFunctions[] = {
-  { "ChromeWorker",        nsDOMWorkerFunctions::NewChromeWorker,     1, 0 },
+  { "ChromeWorker",        nsDOMWorkerFunctions::NewChromeWorker,     1, JSFUN_CONSTRUCTOR },
   { nsnull,                nsnull,                                    0, 0 }
 };
-
-
 enum DOMWorkerStructuredDataType
 {
   // We have a special tag for XPCWrappedNatives that are being passed between
   // threads. This will not work across processes and cannot be persisted. Only
   // for ChromeWorker use at present.
   DOMWORKER_SCTAG_WRAPPEDNATIVE = JS_SCTAG_USER_MIN + 0x1000,
 
   DOMWORKER_SCTAG_END
--- a/dom/tests/mochitest/geolocation/geolocation.html
+++ b/dom/tests/mochitest/geolocation/geolocation.html
@@ -1,10 +1,13 @@
 <html>
   <head>
     <title>Simple access of geolocation</title>
   <head>
     <script>
-      navigator.geolocation.getCurrentPosition(function () {}, null, {timeout:30000});
+      function loadedWindow() {
+        opener.postMessage("loaded", "*");
+      }
+      navigator.geolocation.getCurrentPosition(loadedWindow, loadedWindow, {timeout:30000});
     </script>
   </head>
   <body></body>
 </html>
--- a/dom/tests/mochitest/geolocation/test_clearWatch.html
+++ b/dom/tests/mochitest/geolocation/test_clearWatch.html
@@ -31,32 +31,30 @@ function failureCallback(error)
 {
   ok(0, "we should not be seeing failures from this watchPosition");
 }
 
 function successCallback(position) {
   if (hasBeenCleared == true) {
     successWasCalledAfterClear = true;
   }
+  SimpleTest.executeSoon(clearWatch);
 }
 
 function clearWatch() {
   navigator.geolocation.clearWatch(watchID);
   hasBeenCleared = true;
+  SimpleTest.executeSoon(testAccepted);
 }
 
 function testAccepted() {
   ok(!successWasCalledAfterClear, "The successCallback should not be called after clear");
   reset_prompt();
   SimpleTest.finish();
 }
 
 
 watchID = navigator.geolocation.watchPosition(successCallback, failureCallback, null);
 
-setTimeout(clearWatch, 250);
-
-setTimeout(testAccepted, 2000);
-
 </script>
 </pre>
 </body>
 </html>
--- a/dom/tests/mochitest/geolocation/test_manyWindows.html
+++ b/dom/tests/mochitest/geolocation/test_manyWindows.html
@@ -23,45 +23,44 @@ href="https://bugzilla.mozilla.org/show_
 
 // ensure we are using the right testing provider
 resume_geolocationProvider();
 force_prompt(true);
 
 /** Test for Bug  **/
 
 var numberOfWindows = 5;  // 20 seems to be the default max popups during the mochitest run
-var totalWindows = numberOfWindows;
+var loadedWindows = 0;
 
 var windows = new Array(numberOfWindows);
 
+addEventListener("message", function() {
+  ++loadedWindows;
+  if (loadedWindows == numberOfWindows) {
+    SimpleTest.executeSoon(closeWindows);
+  }
+}, false);
+
 for(var i = 0; i < numberOfWindows; i++) {
   windows[i] = window.open("geolocation.html", "_blank", "width=700,height=400");
 }
 
 function closeWindows()
 {
   for(var i = 0; i < numberOfWindows; i++) {
     windows[i].close();
-    totalWindows --;
   }
+  SimpleTest.waitForFocus(done);
 }
 
 SimpleTest.waitForExplicitFinish();
 
-function checkDone()
+function done()
 {
-    if (totalWindows == 0)
-    {
-        ok(navigator.geolocation, "Opened a bunch of windows and didn't crash.");
-        clearInterval(timer);
-        reset_prompt();
-        SimpleTest.finish();
-    }
+  ok(navigator.geolocation, "Opened a bunch of windows and didn't crash.");
+  reset_prompt();
+  SimpleTest.finish();
 }
 
-var timer = setInterval(checkDone, 1000);
-
-setTimeout(closeWindows, 5000);
-
 </script>
 </pre>
 </body>
 </html>
--- a/dom/tests/mochitest/whatwg/test_bug500328.html
+++ b/dom/tests/mochitest/whatwg/test_bug500328.html
@@ -47,17 +47,24 @@ var gGen;
 function statusMsg(msg) {
   var msgElem = document.createElement("p");
   msgElem.appendChild(document.createTextNode(msg));
 
   document.getElementById("status").appendChild(msgElem);
 }
 
 function longWait() {
-  setTimeout(function() { gGen.next(); }, 1000);
+  function hitEventLoop(times, func) {
+    if (times > 0) {
+      setTimeout(hitEventLoop, 0, times - 1, func);
+    } else {
+      setTimeout(func, 0);
+    }
+  }
+  hitEventLoop(100, function() { gGen.next(); });
 }
 
 function shortWait() {
   setTimeout(function() { gGen.next(); }, 0);
 }
 
 function onChildPopState(e) {
   gNumPopStates++;
@@ -351,48 +358,48 @@ function runTest() {
 
   // Poll the document until the link has the correct color, or this test times
   // out.  Unfortunately I can't come up with a more elegant way to do this.
   // We could listen to MozAfterPaint, but that doesn't guarantee that we'll
   // observe the new color.
   while (getColor(ifLink) != unvisitedColor) {
     // Dump so something shows up in the mochitest logs if we spin here.
     dump("ifLink has wrong initial color.  Spinning...\n");
-    setTimeout(function() { gGen.next(); }, 10);
+    setTimeout(function() { gGen.next(); }, 0);
     yield;
   }
 
   // Navigate iframe2 to dir/${rand}
   iframe2.onload = onChildLoad;
   enableChildLoadCallback();
   iframe2Cw.location = "mytestdir/" + rand;
   yield;
 
   // PushState the iframe into the mytestdir directory.  This should cause
   // ifLink to turn purple, since we just visited mytestdir/${rand} in iframe2.
   iframeCw.history.pushState(null, "foo", "mytestdir/foo");
 
   // Check that the link's color is now visitedColor
   while (getColor(ifLink) != visitedColor) {
     dump("ifLink has wrong color after pushstate.  Spinning...\n");
-    setTimeout(function() { gGen.next(); }, 10);
+    setTimeout(function() { gGen.next(); }, 0);
     yield;
   }
 
   ok(ifLink.href.match("mytestdir\\/" + rand + "$"),
      "inner frame's link should end with 'mytestdir/${rand}'");
 
   // Navigate out of the mytestdir directory.  This should cause ifLink to turn
   // blue again.
   iframeCw.history.pushState(null, "bar", "../file_bug500328_1.html");
 
   // Check that the link's color is back to the unvisited color.
   while (getColor(ifLink) != unvisitedColor) {
     dump("ifLink has wrong color after pushstating out of dir.  Spinning...\n");
-    setTimeout(function() { gGen.next(); }, 10);
+    setTimeout(function() { gGen.next(); }, 0);
     yield;
   }
 
   ok(!ifLink.href.match("mytestdir"),
      "inner frame's link shouldn't contain 'mytestdir'.");
 
   /*
    * TEST 2 tests that pushstate's same-origin checks are correct.
@@ -656,20 +663,16 @@ function runTest() {
   yield;
   iframe.onload = null;
 
   enableChildLoadCallback();
   // navigate to http://mochi.test:8888/[...]/file_bug500328_1.html
   iframeCw.location = innerLoc;
   yield;
 
-  // Let the load handler finish.
-  longWait();
-  yield;
-
   // PushState to a URL which doesn't exist
   iframeCw.history.pushState({}, "", rand);
 
   // Refresh.  We'll end up a 404 page.
   iframe.onload = onChildLoad;
   enableChildLoadCallback();
   iframeCw.location.reload(true);
   yield;
--- a/dom/tests/mochitest/whatwg/test_postMessage_special.xhtml
+++ b/dom/tests/mochitest/whatwg/test_postMessage_special.xhtml
@@ -78,22 +78,16 @@ function b64(str)
   return out;
 }
 
 
 var aboutBlankWindow = null;
 var aboutBlank2Window = null;
 var dataWindow = null;
 
-var aboutBlankResponseReceived = false;
-var aboutBlank2ResponseReceived = false;
-var dataResponseReceived = false;
-
-var finished = false;
-
 /** Convert a nullable string to a pretty representation */
 function sourceify(v)
 {
   if (typeof v == "string")
     return "'" + v + "'";
   return String(v);
 }
 
@@ -130,39 +124,36 @@ function messageReceiver(evt)
       // not codified yet which of these two causes the identifier tokens on
       // the event generated by the new window to be those of this window, but
       // in either case this is what they should be.
       is(evt.origin, "http://mochi.test:8888",
          "wrong origin for event from about:blank");
       is(evt.source, aboutBlankWindow, "wrong source");
 
       // ...and onto the next test
-      aboutBlankResponseReceived = true;
       setupBlank2();
     }
     else if (evt.data === "about:blank2-response")
     {
       is(evt.origin, "http://mochi.test:8888",
          "wrong origin for event from about:blank #2");
       is(evt.source, aboutBlank2Window, "wrong source");
-      aboutBlank2ResponseReceived = true;
 
       setupData();
     }
     else if (evt.data === "data-response")
     {
       // HTML5 defines the origin of a data: URI as the origin of the window or
       // script that opened the data: URI.
       is(evt.origin, "http://mochi.test:8888",
          "wrong origin for event from data URL (should be the origin of the " +
          "window/script that opened the URL, in this case the origin of this " +
          "file)");
       is(evt.source, dataWindow, "wrong source");
 
-      dataResponseReceived = true;
       finish();
     }
     else
     {
       ok(false, "unexpected message: " + evt.data);
     }
   }
   catch (e)
@@ -203,64 +194,43 @@ function getContents(description, respon
     "  </script>\n" +
     "</head>\n" +
     "<body><p>" + description + "</p></body>\n" +
     "</html>";
 
   return contents;
 }
 
-/** Finish the test, but don't finish twice if we timed out. */
 function finish()
 {
-  if (!finished)
-  {
-    finished = true;
-    SimpleTest.finish();
-  }
+  SimpleTest.finish();
 }
 
 var xhtmlns = "http://www.w3.org/1999/xhtml";
 
 function insert(el)
 {
   var content = $("content");
   content.parentNode.insertBefore(el, content);
 }
 
-var LOAD_TIMEOUT = 5000;
-
 function setupBlank()
 {
   var aboutBlankFrame = document.createElementNS(xhtmlns, "iframe");
   aboutBlankFrame.setAttribute("src", "about:blank");
   insert(aboutBlankFrame);
 
   aboutBlankWindow = aboutBlankFrame.contentWindow;
   var doc = aboutBlankWindow.document;
   doc.open();
   doc.write(getContents("This was about:blank #1", "about:blank-response"));
   doc.close();
 
   // I don't believe anything guarantees sync parsing, so we have to wait for
   // the new window to poke us to actually do the test.  :-\
-
-  // Catch recalcitrant browsers that fail inside the iframe document code.
-  setTimeout(blankFailed, LOAD_TIMEOUT);
-}
-
-function blankFailed()
-{
-  if (!aboutBlankResponseReceived && !finished)
-  {
-    ok(false,
-       "test timed out (postMessage not accessible on window.parent in " +
-       "the first about:blank iframe?)");
-    finish();
-  }
 }
 
 function setupBlank2()
 {
   var aboutBlank2Frame = document.createElementNS(xhtmlns, "iframe");
   aboutBlank2Frame.addEventListener("load", nextTest, false);
   aboutBlank2Frame.setAttribute("src", "about:blank");
 
@@ -276,30 +246,16 @@ function setupData()
 {
   var dataFrame = document.createElementNS(xhtmlns, "iframe");
   dataFrame.setAttribute("src", dataURI);
   insert(dataFrame);
 
   dataWindow = dataFrame.contentWindow;
 
   // ...and wait again for the window to load...
-
-  // Catch recalcitrant browsers that fail inside the iframe document code.
-  setTimeout(dataFailed, LOAD_TIMEOUT);
-}
-
-function dataFailed()
-{
-  if (!dataResponseReceived && !finished)
-  {
-    ok(false,
-       "test timed out (postMessage not accessible on window.parent in " +
-       "the data: iframe?)");
-    finish();
-  }
 }
 
 var count = 0;
 function nextTest()
 {
   switch (count++)
   {
     case 0:
--- a/editor/libeditor/html/nsHTMLAbsPosition.cpp
+++ b/editor/libeditor/html/nsHTMLAbsPosition.cpp
@@ -685,24 +685,23 @@ nsHTMLEditor::CheckPositionedElementBGan
   if (bgImageStr.EqualsLiteral("none")) {
     nsAutoString bgColorStr;
     res =
       mHTMLCSSUtils->GetComputedProperty(aElement,
                                          nsEditProperty::cssBackgroundColor,
                                          bgColorStr);
     NS_ENSURE_SUCCESS(res, res);
     if (bgColorStr.EqualsLiteral("transparent")) {
-      nsCOMPtr<nsIDOMWindow> window;
-      res = mHTMLCSSUtils->GetDefaultViewCSS(aElement, getter_AddRefs(window));
+
+      nsCOMPtr<nsIDOMViewCSS> viewCSS;
+      res = mHTMLCSSUtils->GetDefaultViewCSS(aElement, getter_AddRefs(viewCSS));
       NS_ENSURE_SUCCESS(res, res);
-
       nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
-      res = window->GetComputedStyle(aElement, EmptyString(), getter_AddRefs(cssDecl));
+      res = viewCSS->GetComputedStyle(aElement, EmptyString(), getter_AddRefs(cssDecl));
       NS_ENSURE_SUCCESS(res, res);
-
       // from these declarations, get the one we want and that one only
       nsCOMPtr<nsIDOMCSSValue> colorCssValue;
       res = cssDecl->GetPropertyCSSValue(NS_LITERAL_STRING("color"), getter_AddRefs(colorCssValue));
       NS_ENSURE_SUCCESS(res, res);
 
       PRUint16 type;
       res = colorCssValue->GetCssValueType(&type);
       NS_ENSURE_SUCCESS(res, res);
--- a/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
+++ b/editor/libeditor/html/nsHTMLAnonymousUtils.cpp
@@ -425,23 +425,23 @@ nsHTMLEditor::GetPositionAndDimensions(n
                                        positionStr);
     isPositioned = positionStr.EqualsLiteral("absolute");
   }
 
   if (isPositioned) {
     // Yes, it is absolutely positioned
     mResizedObjectIsAbsolutelyPositioned = PR_TRUE;
 
-    nsCOMPtr<nsIDOMWindow> window;
-    res = mHTMLCSSUtils->GetDefaultViewCSS(aElement, getter_AddRefs(window));
-    NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+    nsCOMPtr<nsIDOMViewCSS> viewCSS;
+    res = mHTMLCSSUtils->GetDefaultViewCSS(aElement, getter_AddRefs(viewCSS));
+    NS_ENSURE_TRUE(viewCSS, NS_ERROR_FAILURE);
 
     nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
     // Get the all the computed css styles attached to the element node
-    res = window->GetComputedStyle(aElement, EmptyString(), getter_AddRefs(cssDecl));
+    res = viewCSS->GetComputedStyle(aElement, EmptyString(), getter_AddRefs(cssDecl));
     NS_ENSURE_SUCCESS(res, res);
 
     aBorderLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-left-width"));
     aBorderTop  = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("border-top-width"));
     aMarginLeft = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-left"));
     aMarginTop  = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("margin-top"));
 
     aX = GetCSSFloatValue(cssDecl, NS_LITERAL_STRING("left")) +
--- a/editor/libeditor/html/nsHTMLCSSUtils.cpp
+++ b/editor/libeditor/html/nsHTMLCSSUtils.cpp
@@ -42,16 +42,17 @@
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsIServiceManager.h"
 #include "nsEditProperty.h"
 #include "ChangeCSSInlineStyleTxn.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMElementCSSInlineStyle.h"
 #include "nsIDOMDocument.h"
+#include "nsIDOMDocumentView.h"
 #include "nsIContent.h"
 #include "nsIAtom.h"
 #include "nsTextEditUtils.h"
 #include "nsReadableUtils.h"
 #include "nsUnicharUtils.h"
 #include "nsHTMLCSSUtils.h"
 #include "nsColor.h"
 #include "nsAttrName.h"
@@ -532,46 +533,45 @@ nsHTMLCSSUtils::GetSpecifiedProperty(nsI
 {
   return GetCSSInlinePropertyBase(aNode, aProperty, aValue, nsnull, SPECIFIED_STYLE_TYPE);
 }
 
 nsresult
 nsHTMLCSSUtils::GetComputedProperty(nsIDOMNode *aNode, nsIAtom *aProperty,
                                     nsAString & aValue)
 {
-  nsCOMPtr<nsIDOMWindow> window;
-  nsresult res = GetDefaultViewCSS(aNode, getter_AddRefs(window));
+  nsCOMPtr<nsIDOMViewCSS> viewCSS = nsnull;
+  nsresult res = GetDefaultViewCSS(aNode, getter_AddRefs(viewCSS));
   NS_ENSURE_SUCCESS(res, res);
 
-  return GetCSSInlinePropertyBase(aNode, aProperty, aValue, window, COMPUTED_STYLE_TYPE);
+  return GetCSSInlinePropertyBase(aNode, aProperty, aValue, viewCSS, COMPUTED_STYLE_TYPE);
 }
 
 nsresult
 nsHTMLCSSUtils::GetCSSInlinePropertyBase(nsIDOMNode *aNode, nsIAtom *aProperty,
-                                         nsAString& aValue,
-                                         nsIDOMWindow* aWindow,
-                                         PRUint8 aStyleType)
+                                        nsAString &aValue,
+                                        nsIDOMViewCSS *aViewCSS,
+                                        PRUint8 aStyleType)
 {
   aValue.Truncate();
   NS_ENSURE_TRUE(aProperty, NS_ERROR_NULL_POINTER);
 
-  nsCOMPtr<nsIDOMElement> element;
+  nsCOMPtr<nsIDOMElement>element;
   nsresult res = GetElementContainerOrSelf(aNode, getter_AddRefs(element));
   NS_ENSURE_SUCCESS(res, res);
 
   switch (aStyleType) {
     case COMPUTED_STYLE_TYPE:
-      if (element && aWindow) {
+      if (element && aViewCSS) {
         nsAutoString value, propString;
         nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
         aProperty->ToString(propString);
         // Get the all the computed css styles attached to the element node
-        res = aWindow->GetComputedStyle(element, EmptyString(), getter_AddRefs(cssDecl));
-        if (NS_FAILED(res) || !cssDecl)
-          return res;
+        res = aViewCSS->GetComputedStyle(element, EmptyString(), getter_AddRefs(cssDecl));
+        if (NS_FAILED(res) || !cssDecl) return res;
         // from these declarations, get the one we want and that one only
         res = cssDecl->GetPropertyValue(propString, value);
         NS_ENSURE_SUCCESS(res, res);
         aValue.Assign(value);
       }
       break;
     case SPECIFIED_STYLE_TYPE:
       if (element) {
@@ -586,38 +586,43 @@ nsHTMLCSSUtils::GetCSSInlinePropertyBase
         aValue.Assign(value);
       }
       break;
   }
   return NS_OK;
 }
 
 nsresult
-nsHTMLCSSUtils::GetDefaultViewCSS(nsIDOMNode *aNode, nsIDOMWindow **aViewCSS)
+nsHTMLCSSUtils::GetDefaultViewCSS(nsIDOMNode *aNode, nsIDOMViewCSS **aViewCSS)
 {
-  *aViewCSS = nsnull;
-  nsCOMPtr<nsIDOMElement> element;
+  nsCOMPtr<nsIDOMElement>element;
   nsresult res = GetElementContainerOrSelf(aNode, getter_AddRefs(element));
   NS_ENSURE_SUCCESS(res, res);
 
-  if (!element) {
-    return NS_OK;
+  // if we have an element node
+  if (element) {
+    // find the owner document
+    nsCOMPtr<nsIDOMDocument> doc;
+    nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
+    res = node->GetOwnerDocument(getter_AddRefs(doc));
+    NS_ENSURE_SUCCESS(res, res);
+    if (doc) {
+      nsCOMPtr<nsIDOMDocumentView> documentView = do_QueryInterface(doc);
+      nsCOMPtr<nsIDOMAbstractView> abstractView;
+      // from the document, get the abtractView
+      res = documentView->GetDefaultView(getter_AddRefs(abstractView));
+      NS_ENSURE_SUCCESS(res, res);
+      if (abstractView) {
+        // from the abstractView, get the CSS view
+        CallQueryInterface(abstractView, aViewCSS);
+        return NS_OK;
+      }
+    }
   }
-  // find the owner document
-  nsCOMPtr<nsIDOMDocument> doc;
-  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
-  res = node->GetOwnerDocument(getter_AddRefs(doc));
-  NS_ENSURE_SUCCESS(res, res);
-  if (!doc) {
-    return NS_OK;
-  }
-  nsCOMPtr<nsIDOMWindow> window;
-  res = doc->GetDefaultView(getter_AddRefs(window));
-  NS_ENSURE_SUCCESS(res, res);
-  window.forget(aViewCSS);
+  *aViewCSS = nsnull;
   return NS_OK;
 }
 
 nsresult
 NS_NewHTMLCSSUtils(nsHTMLCSSUtils** aInstancePtrResult)
 {
   nsHTMLCSSUtils * rules = new nsHTMLCSSUtils();
   if (rules) {
@@ -1077,34 +1082,34 @@ nsHTMLCSSUtils::GetCSSEquivalentToHTMLIn
   aValueString.Truncate();
   nsCOMPtr<nsIDOMElement> theElement;
   nsresult res = GetElementContainerOrSelf(aNode, getter_AddRefs(theElement));
   NS_ENSURE_SUCCESS(res, res);
 
   if (theElement && IsCSSEditableProperty(theElement, aHTMLProperty, aAttribute)) {
     // Yes, the requested HTML style has a CSS equivalence in this implementation
     // Retrieve the default ViewCSS if we are asked for computed styles
-    nsCOMPtr<nsIDOMWindow> window;
+    nsCOMPtr<nsIDOMViewCSS> viewCSS = nsnull;
     if (COMPUTED_STYLE_TYPE == aStyleType) {
-      res = GetDefaultViewCSS(theElement, getter_AddRefs(window));
+      res = GetDefaultViewCSS(theElement, getter_AddRefs(viewCSS));
       NS_ENSURE_SUCCESS(res, res);
     }
     nsTArray<nsIAtom*> cssPropertyArray;
     nsTArray<nsString> cssValueArray;
     // get the CSS equivalence with last param PR_TRUE indicating we want only the
     // "gettable" properties
     GenerateCSSDeclarationsFromHTMLStyle(theElement, aHTMLProperty, aAttribute, nsnull,
                                          cssPropertyArray, cssValueArray, PR_TRUE);
     PRInt32 count = cssPropertyArray.Length();
     PRInt32 index;
     for (index = 0; index < count; index++) {
       nsAutoString valueString;
       // retrieve the specified/computed value of the property
       res = GetCSSInlinePropertyBase(theElement, cssPropertyArray[index],
-                                     valueString, window, aStyleType);
+                                     valueString, viewCSS, aStyleType);
       NS_ENSURE_SUCCESS(res, res);
       // append the value to aValueString (possibly with a leading whitespace)
       if (index) aValueString.Append(PRUnichar(' '));
       aValueString.Append(valueString);
     }
   }
   return NS_OK;
 }
--- a/editor/libeditor/html/nsHTMLCSSUtils.h
+++ b/editor/libeditor/html/nsHTMLCSSUtils.h
@@ -37,28 +37,28 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsHTMLCSSUtils_h__
 #define nsHTMLCSSUtils_h__
 
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsTArray.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMElement.h"
 #include "nsIHTMLEditor.h"
 #include "ChangeCSSInlineStyleTxn.h"
 #include "nsEditProperty.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 
 #define SPECIFIED_STYLE_TYPE    1
 #define COMPUTED_STYLE_TYPE     2
 
 class nsHTMLEditor;
-class nsIDOMWindow;
 
 typedef void (*nsProcessValueFunc)(const nsAString * aInputString, nsAString & aOutputString,
                                    const char * aDefaultValueString,
                                    const char * aPrependString, const char* aAppendString);
 
 class nsHTMLCSSUtils
 {
 public:
@@ -307,23 +307,22 @@ public:
   /** returns aNode itself if it is an element node, or the first ancestors being an element
     * node if aNode is not one itself
     *
     * @param aNode           [IN] a node
     * @param aElement        [OUT] the deepest element node containing aNode (possibly aNode itself)
     */
   nsresult GetElementContainerOrSelf(nsIDOMNode * aNode, nsIDOMElement ** aElement);
 
-  /**
-   * Gets the default Window for a given node.
+  /** Gets the default DOMView for a given node
    *
-   * @param aNode    the node we want the default Window for
-   * @param aWindow  [OUT] the default Window
+   * @param aNode               the node we want the default DOMView for
+   * @param aViewCSS            [OUT] the default DOMViewCSS
    */
-  nsresult        GetDefaultViewCSS(nsIDOMNode* aNode, nsIDOMWindow** aWindow);
+  nsresult        GetDefaultViewCSS(nsIDOMNode * aNode, nsIDOMViewCSS ** aViewCSS);
 
 
 private:
 
   /** retrieves the css property atom from an enum
     *
     * @param aProperty          [IN] the enum value for the property
     * @param aAtom              [OUT] the corresponding atom
@@ -379,27 +378,27 @@ private:
     */
   nsresult    CreateCSSPropertyTxn(nsIDOMElement * aElement, 
                                    nsIAtom * aProperty,
                                    const nsAString & aValue,
                                    ChangeCSSInlineStyleTxn ** aTxn,
                                    PRBool aRemoveProperty);
 
   /** back-end for GetSpecifiedProperty and GetComputedProperty
-   *
-   * @param aNode               [IN] a DOM node
-   * @param aProperty           [IN] a CSS property
-   * @param aValue              [OUT] the retrieved value for this property
-   * @param aWindow             [IN] the window we need in case we query computed styles
-   * @param aStyleType          [IN] SPECIFIED_STYLE_TYPE to query the specified style values
-   *                                 COMPUTED_STYLE_TYPE  to query the computed style values
-   */
+    *
+    * @param aNode               [IN] a DOM node
+    * @param aProperty           [IN] a CSS property
+    * @param aValue              [OUT] the retrieved value for this property
+    * @param aViewCSS            [IN] the ViewCSS we need in case we query computed styles
+    * @param aStyleType          [IN] SPECIFIED_STYLE_TYPE to query the specified style values
+                                      COMPUTED_STYLE_TYPE  to query the computed style values
+    */
   nsresult    GetCSSInlinePropertyBase(nsIDOMNode * aNode, nsIAtom * aProperty,
                                        nsAString & aValue,
-                                       nsIDOMWindow* aWindow,
+                                       nsIDOMViewCSS * aViewCSS,
                                        PRUint8 aStyleType);
 
 
 private:
   nsHTMLEditor            *mHTMLEditor;
   PRBool                  mIsCSSPrefChecked; 
 
 };
--- a/embedding/android/GeckoApp.java
+++ b/embedding/android/GeckoApp.java
@@ -260,29 +260,29 @@ abstract public class GeckoApp
     }
 
     boolean IsNewInstall() {
         File appIni = new File(sGREDir, "application.ini");
         return !appIni.exists();
     }
 
     boolean IsUnsupportedDevice() {
-        // We don't currently support devices with less than 256Mb of RAM, warn on first run
+        // We don't currently support devices with less than 512Mb of RAM, warn on first run
         File meminfo = new File("/proc/meminfo");
         try {
             BufferedReader br = new BufferedReader(new FileReader(meminfo));
             String totalMem = "";
             while(!totalMem.contains("MemTotal:") && totalMem != null)
                 totalMem = br.readLine();
             StringTokenizer st = new StringTokenizer(totalMem, " ");
             st.nextToken(); // "MemInfo:"
             totalMem = st.nextToken();
 
             Log.i("GeckoMemory", "MemTotal: " + Integer.parseInt(totalMem));
-            return Integer.parseInt(totalMem) <= 262144L;
+            return Integer.parseInt(totalMem) <= 524288L;
         } catch (Exception ex) {
             // Will catch  NullPointerException if totalMem isn't found,
             // a NumberFormatException if the token isn't parsible
             // IOException from the file reading or NoSuchElementException
             // if totalMem doesn't have 2 tokens. None of these are fatal,
             // so log it and move on.
             Log.w("GeckoMemTest", "Exception when finding total memory", ex);
         }
--- a/embedding/browser/webBrowser/nsContextMenuInfo.cpp
+++ b/embedding/browser/webBrowser/nsContextMenuInfo.cpp
@@ -1,10 +1,11 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
+/* -*- 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,
@@ -45,17 +46,19 @@
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMHTMLHtmlElement.h"
 #include "nsIDOMHTMLAnchorElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIDOMHTMLAreaElement.h"
 #include "nsIDOMHTMLLinkElement.h"
-#include "nsIDOMWindow.h"
+#include "nsIDOMDocumentView.h"
+#include "nsIDOMAbstractView.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMCSSValue.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsNetUtil.h"
 #include "nsUnicharUtils.h"
 #include "nsIDocument.h"
 #include "nsIPrincipal.h"
 #include "nsIChannelPolicy.h"
@@ -285,20 +288,23 @@ nsContextMenuInfo::GetBackgroundImageReq
 {
   NS_ENSURE_ARG_POINTER(aDOMNode);
 
   nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
   nsCOMPtr<nsIDOMNode> parentNode;
 
   nsCOMPtr<nsIDOMDocument> document;
   domNode->GetOwnerDocument(getter_AddRefs(document));
-  NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
+  nsCOMPtr<nsIDOMDocumentView> docView(do_QueryInterface(document));
+  NS_ENSURE_TRUE(docView, NS_ERROR_FAILURE);
 
-  nsCOMPtr<nsIDOMWindow> window;
-  document->GetDefaultView(getter_AddRefs(window));
+  nsCOMPtr<nsIDOMAbstractView> defaultView;
+  docView->GetDefaultView(getter_AddRefs(defaultView));
+  nsCOMPtr<nsIDOMViewCSS> defaultCSSView(do_QueryInterface(defaultView));
+  NS_ENSURE_TRUE(defaultCSSView, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
   nsAutoString bgStringValue;
 
   // get Content Security Policy to pass to LoadImage
   nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
   nsCOMPtr<nsIPrincipal> principal;
   nsCOMPtr<nsIChannelPolicy> channelPolicy;
@@ -316,18 +322,18 @@ nsContextMenuInfo::GetBackgroundImageReq
   
   while (PR_TRUE) {
     nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode));
     // bail for the parent node of the root element or null argument
     if (!domElement)
       break;
     
     nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
-    window->GetComputedStyle(domElement, EmptyString(),
-                             getter_AddRefs(computedStyle));
+    defaultCSSView->GetComputedStyle(domElement, EmptyString(),
+                                     getter_AddRefs(computedStyle));
     if (computedStyle) {
       nsCOMPtr<nsIDOMCSSValue> cssValue;
       computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-image"),
                                          getter_AddRefs(cssValue));
       primitiveValue = do_QueryInterface(cssValue);
       if (primitiveValue) {
         primitiveValue->GetStringValue(bgStringValue);
         if (!bgStringValue.EqualsLiteral("none")) {
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozInlineSpellWordUtil.h"
 #include "nsDebug.h"
 #include "nsIAtom.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIDOMCSSStyleDeclaration.h"
+#include "nsIDOMDocumentView.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMNSRange.h"
 #include "nsIDOMRange.h"
 #include "nsIEditor.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMHTMLBRElement.h"
 #include "nsUnicharUtilCIID.h"
 #include "nsServiceManagerUtils.h"
@@ -97,20 +98,23 @@ mozInlineSpellWordUtil::Init(nsWeakPtr a
 
   mDocument = do_QueryInterface(domDoc, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mDOMDocumentRange = do_QueryInterface(domDoc, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // view
-  nsCOMPtr<nsIDOMWindow> window;
-  rv = domDoc->GetDefaultView(getter_AddRefs(window));
+  nsCOMPtr<nsIDOMDocumentView> docView = do_QueryInterface(domDoc, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
-  mCSSView = window;
+  nsCOMPtr<nsIDOMAbstractView> abstractView;
+  rv = docView->GetDefaultView(getter_AddRefs(abstractView));
+  NS_ENSURE_SUCCESS(rv, rv);
+  mCSSView = do_QueryInterface(abstractView, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   // Find the root node for the editor. For contenteditable we'll need something
   // cleverer here.
   nsCOMPtr<nsIDOMElement> rootElt;
   rv = editor->GetRootElement(getter_AddRefs(rootElt));
   NS_ENSURE_SUCCESS(rv, rv);
   
   mRootNode = rootElt;
@@ -489,17 +493,17 @@ ContainsDOMWordSeparator(nsIDOMNode* aNo
       *aSeparatorOffset = i;
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 static PRBool
-IsBreakElement(nsIDOMWindow* aDocView, nsIDOMNode* aNode)
+IsBreakElement(nsIDOMViewCSS* aDocView, nsIDOMNode* aNode)
 {
   nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
   if (!element)
     return PR_FALSE;
     
   if (IsBRElement(aNode))
     return PR_TRUE;
   
@@ -528,18 +532,18 @@ IsBreakElement(nsIDOMWindow* aDocView, n
   if (!position.EqualsLiteral("static"))
     return PR_TRUE;
     
   // XXX What about floats? What else?
   return PR_FALSE;
 }
 
 struct CheckLeavingBreakElementClosure {
-  nsIDOMWindow* mDocView;
-  PRPackedBool  mLeftBreakElement;
+  nsIDOMViewCSS* mDocView;
+  PRPackedBool   mLeftBreakElement;
 };
 
 static void
 CheckLeavingBreakElement(nsIDOMNode* aNode, void* aClosure)
 {
   CheckLeavingBreakElementClosure* cl =
     static_cast<CheckLeavingBreakElementClosure*>(aClosure);
   if (!cl->mLeftBreakElement && IsBreakElement(cl->mDocView, aNode)) {
--- a/extensions/spellcheck/src/mozInlineSpellWordUtil.h
+++ b/extensions/spellcheck/src/mozInlineSpellWordUtil.h
@@ -33,16 +33,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsCOMPtr.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentRange.h"
+#include "nsIDOMViewCSS.h"
 #include "nsIDocument.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIUGenCategory.h"
 
 //#define DEBUG_SPELLCHECK
 
 class nsIDOMRange;
@@ -120,17 +121,17 @@ public:
   nsIDOMNode* GetRootNode() { return mRootNode; }
   nsIUGenCategory* GetCategories() { return mCategories; }
   
 private:
 
   // cached stuff for the editor, set by Init
   nsCOMPtr<nsIDOMDocumentRange> mDOMDocumentRange;
   nsCOMPtr<nsIDocument>         mDocument;
-  nsCOMPtr<nsIDOMWindow>        mCSSView;
+  nsCOMPtr<nsIDOMViewCSS>       mCSSView;
   nsCOMPtr<nsIUGenCategory>     mCategories;
 
   // range to check, see SetRange
   nsIDOMNode* mRootNode;
   NodeOffset  mSoftBegin;
   NodeOffset  mSoftEnd;
 
   // DOM text covering the soft range, with newlines added at block boundaries
--- a/extensions/widgetutils/src/nsWidgetUtils.cpp
+++ b/extensions/widgetutils/src/nsWidgetUtils.cpp
@@ -34,17 +34,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 "nsCURILoader.h"
 #include "nsICategoryManager.h"
+#include "nsIDOMAbstractView.h"
 #include "nsIDOMDocument.h"
+#include "nsIDOMDocumentView.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMHTMLIFrameElement.h"
 #include "nsIDOMNSDocument.h"
 #include "nsIDOMNSElement.h"
 #include "nsIDOMNSHTMLElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeList.h"
 #include "nsIDOMWindow.h"
@@ -61,16 +63,17 @@
 #include "nsRect.h"
 #include "nsStringGlue.h"
 #include "nsWeakReference.h"
 #include "nsIWebBrowser.h"
 #include "nsIObserverService.h"
 #include "nsIDOMEventTarget.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMWindow.h"
+//#include ".h"
 #include "nsIDOM3EventTarget.h"
 #include "nsIDOMKeyListener.h"
 #include "nsIDOMCompositionListener.h"
 #include "nsIDOMTextListener.h"
 #include "nsIDOMMouseMotionListener.h"
 #include "nsIDOMMouseListener.h"
 #include "nsIDOMMouseEvent.h"
 #include "nsIDOMNSEvent.h"
@@ -420,32 +423,38 @@ nsWidgetUtils::IsXULNode(nsIDOMNode *aNo
     *aType = 2; // Magic
   else if (sorigNode.EqualsLiteral("xul:scrollbarbutton"))
     *aType = 3; // Magic
 
   return retval;
 }
 
 nsresult
-nsWidgetUtils::GetDOMWindowByNode(nsIDOMNode* aNode, nsIDOMWindow** aDOMWindow)
+nsWidgetUtils::GetDOMWindowByNode(nsIDOMNode *aNode, nsIDOMWindow * *aDOMWindow)
 {
+  nsresult rv;
   nsCOMPtr<nsIDOMDocument> nodeDoc;
-  nsresult rv = aNode->GetOwnerDocument(getter_AddRefs(nodeDoc));
+  rv = aNode->GetOwnerDocument(getter_AddRefs(nodeDoc));
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIDOMDocumentView> docView = do_QueryInterface(nodeDoc, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIDOMWindow> window;
-  rv = nodeDoc->GetDefaultView(getter_AddRefs(window));
+  nsCOMPtr<nsIDOMAbstractView> absView;
+  NS_ENSURE_SUCCESS(rv, rv);
+  rv = docView->GetDefaultView(getter_AddRefs(absView));
   NS_ENSURE_SUCCESS(rv, rv);
-  window.forget(aDOMWindow);
+  nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(absView, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+  *aDOMWindow = window;
+  NS_IF_ADDREF(*aDOMWindow);
   return rv;
 }
 
 void
 nsWidgetUtils::GetChromeEventHandler(nsIDOMWindow *aDOMWin,
-                                     nsIDOMEventTarget **aChromeTarget)
+                                 nsIDOMEventTarget **aChromeTarget)
 {
     nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(aDOMWin));
     nsPIDOMEventTarget* chromeEventHandler = nsnull;
     if (privateDOMWindow) {
         chromeEventHandler = privateDOMWindow->GetChromeEventHandler();
     }
 
     nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(chromeEventHandler));
new file mode 100644
--- /dev/null
+++ b/gfx/ots/README.mozilla
@@ -0,0 +1,10 @@
+This is the Sanitiser for OpenType project, from http://code.google.com/p/ots/.
+
+Current revision: r62
+
+Applied local patches:
+    ots-fix-vc10.patch - workaround for VS10 STL wrappers (bug 602558)
+
+    ots-fix-gcc46.patch - fix os2.cc compile error for GCC 4.6 (bug 628252)
+
+    ots-fix-sparc64.patch - fix alignment error on sparc64 (bug 643137)
--- a/gfx/ots/include/opentype-sanitiser.h
+++ b/gfx/ots/include/opentype-sanitiser.h
@@ -1,34 +1,28 @@
 // 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.
 
 #ifndef OPENTYPE_SANITISER_H_
 #define OPENTYPE_SANITISER_H_
 
-#if defined(_MSC_VER)
+#if defined(_WIN32)
 typedef signed char int8_t;
 typedef unsigned char uint8_t;
 typedef short int16_t;
 typedef unsigned short uint16_t;
 typedef int int32_t;
 typedef unsigned int uint32_t;
 typedef __int64 int64_t;
 typedef unsigned __int64 uint64_t;
-#else
-#include <stdint.h>
-#endif
-
-#ifdef _WIN32
 #include <winsock2.h>  // for htons/ntohs
-#undef min
-#undef max
 #else
 #include <arpa/inet.h>
+#include <stdint.h>
 #endif
 
 #include <algorithm>  // for std::min
 #include <cassert>
 #include <cstring>
 
 namespace ots {
 
@@ -99,26 +93,35 @@ class OTSStream {
     while (bytes) {
       static const uint8_t kZerob = 0;
       if (!Write(&kZerob, 1)) return false;
       bytes--;
     }
     return true;
   }
 
+  bool WriteU8(uint8_t v) {
+    return Write(&v, sizeof(v));
+  }
+
   bool WriteU16(uint16_t v) {
     v = htons(v);
     return Write(&v, sizeof(v));
   }
 
   bool WriteS16(int16_t v) {
     v = htons(v);
     return Write(&v, sizeof(v));
   }
 
+  bool WriteU24(uint32_t v) {
+    v = htonl(v);
+    return Write(reinterpret_cast<uint8_t*>(&v)+1, 3);
+  }
+
   bool WriteU32(uint32_t v) {
     v = htonl(v);
     return Write(&v, sizeof(v));
   }
 
   bool WriteS32(int32_t v) {
     v = htonl(v);
     return Write(&v, sizeof(v));
@@ -172,21 +175,18 @@ class OTSStream {
 
 // -----------------------------------------------------------------------------
 // Process a given OpenType file and write out a sanitised version
 //   output: a pointer to an object implementing the OTSStream interface. The
 //     sanitisied output will be written to this. In the even of a failure,
 //     partial output may have been written.
 //   input: the OpenType file
 //   length: the size, in bytes, of |input|
-//   preserve_otl_tables: whether to preserve OpenType Layout tables
-//                        (GDEF/GPOS/GSUB) without verification
 // -----------------------------------------------------------------------------
-bool Process(OTSStream *output, const uint8_t *input, size_t length,
-             bool preserve_otl_tables = false);
+bool Process(OTSStream *output, const uint8_t *input, size_t length);
 
 // Force to disable debug output even when the library is compiled with
 // -DOTS_DEBUG.
 void DisableDebugOutput();
 
 }  // namespace ots
 
 #endif  // OPENTYPE_SANITISER_H_
--- a/gfx/ots/include/ots-memory-stream.h
+++ b/gfx/ots/include/ots-memory-stream.h
@@ -13,34 +13,34 @@
 namespace ots {
 
 class MemoryStream : public OTSStream {
  public:
   MemoryStream(void *ptr, size_t length)
       : ptr_(ptr), length_(length), off_(0) {
   }
 
-  bool WriteRaw(const void *data, size_t length) {
+  virtual bool WriteRaw(const void *data, size_t length) {
     if ((off_ + length > length_) ||
         (length > std::numeric_limits<size_t>::max() - off_)) {
       return false;
     }
     std::memcpy(static_cast<char*>(ptr_) + off_, data, length);
     off_ += length;
     return true;
   }
 
-  bool Seek(off_t position) {
+  virtual bool Seek(off_t position) {
     if (position < 0) return false;
     if (static_cast<size_t>(position) > length_) return false;
     off_ = position;
     return true;
   }
 
-  off_t Tell() const {
+  virtual off_t Tell() const {
     return off_;
   }
 
  private:
   void* const ptr_;
   size_t length_;
   off_t off_;
 };
new file mode 100644
--- /dev/null
+++ b/gfx/ots/ots-fix-gcc46.patch
@@ -0,0 +1,18 @@
+diff --git a/gfx/ots/src/os2.cc b/gfx/ots/src/os2.cc
+--- a/gfx/ots/src/os2.cc
++++ b/gfx/ots/src/os2.cc
+@@ -1,12 +1,14 @@
+ // 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.
+ 
++#include <cstddef>
++
+ #include "os2.h"
+ 
+ #include "head.h"
+ 
+ // OS/2 - OS/2 and Windows Metrics
+ // http://www.microsoft.com/opentype/otspec/os2.htm
+ 
+ namespace ots {
new file mode 100644
--- /dev/null
+++ b/gfx/ots/ots-fix-sparc64.patch
@@ -0,0 +1,26 @@
+diff --git a/gfx/ots/include/opentype-sanitiser.h b/gfx/ots/include/opentype-sanitiser.h
+--- a/gfx/ots/include/opentype-sanitiser.h
++++ b/gfx/ots/include/opentype-sanitiser.h
+@@ -57,18 +57,20 @@ class OTSStream {
+ 
+     if (chksum_buffer_offset_ == 4) {
+       // TODO(yusukes): This cast breaks the strict-aliasing rule.
+       chksum_ += ntohl(*reinterpret_cast<const uint32_t*>(chksum_buffer_));
+       chksum_buffer_offset_ = 0;
+     }
+ 
+     while (length >= 4) {
+-      chksum_ += ntohl(*reinterpret_cast<const uint32_t*>(
+-          reinterpret_cast<const uint8_t*>(data) + offset));
++      uint32_t tmp;
++      std::memcpy(&tmp, reinterpret_cast<const uint8_t *>(data) + offset,
++        sizeof(uint32_t));
++      chksum_ += ntohl(tmp);
+       length -= 4;
+       offset += 4;
+     }
+ 
+     if (length) {
+       if (chksum_buffer_offset_ != 0) return false;  // not reached
+       if (length > 4) return false;  // not reached
+       std::memcpy(chksum_buffer_,
new file mode 100644
--- /dev/null
+++ b/gfx/ots/ots-fix-vc10.patch
@@ -0,0 +1,60 @@
+diff --git a/gfx/ots/src/gasp.h b/gfx/ots/src/gasp.h
+--- a/gfx/ots/src/gasp.h
++++ b/gfx/ots/src/gasp.h
+@@ -1,15 +1,16 @@
+ // 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.
+ 
+ #ifndef OTS_GASP_H_
+ #define OTS_GASP_H_
+ 
++#include <new>
+ #include <utility>  // std::pair
+ #include <vector>
+ 
+ #include "ots.h"
+ 
+ namespace ots {
+ 
+ struct OpenTypeGASP {
+diff --git a/gfx/ots/src/glyf.h b/gfx/ots/src/glyf.h
+--- a/gfx/ots/src/glyf.h
++++ b/gfx/ots/src/glyf.h
+@@ -1,15 +1,16 @@
+ // 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.
+ 
+ #ifndef OTS_GLYF_H_
+ #define OTS_GLYF_H_
+ 
++#include <new>
+ #include <utility>  // std::pair
+ #include <vector>
+ 
+ #include "ots.h"
+ 
+ namespace ots {
+ 
+ struct OpenTypeGLYF {
+diff --git a/gfx/ots/src/metrics.h b/gfx/ots/src/metrics.h
+--- a/gfx/ots/src/metrics.h
++++ b/gfx/ots/src/metrics.h
+@@ -1,15 +1,16 @@
+ // Copyright (c) 2011 The Chromium Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ 
+ #ifndef OTS_METRICS_H_
+ #define OTS_METRICS_H_
+ 
++#include <new>
+ #include <utility>  // std::pair
+ #include <vector>
+ 
+ #include "ots.h"
+ 
+ namespace ots {
+ 
+ struct OpenTypeMetricsHeader {
--- a/gfx/ots/src/Makefile.in
+++ b/gfx/ots/src/Makefile.in
@@ -47,25 +47,29 @@ CPPSRCS	= \
   fpgm.cc \
   gasp.cc \
   glyf.cc \
   hdmx.cc \
   head.cc \
   hhea.cc \
   hmtx.cc \
   kern.cc \
+  layout.cc \
   loca.cc \
   ltsh.cc \
   maxp.cc \
+  metrics.cc \
   name.cc \
   os2.cc  \
   ots.cc  \
   post.cc \
   prep.cc \
   vdmx.cc \
+  vhea.cc \
+  vmtx.cc \
   vorg.cc \
   gdef.cc \
   gpos.cc \
   gsub.cc \
   $(NULL)
 
 EXPORTS = \
   ../include/opentype-sanitiser.h \
@@ -77,8 +81,14 @@ LOCAL_INCLUDES  += -I$(srcdir)
 FORCE_STATIC_LIB = 1
 # This library is used by other shared libs in a static build
 FORCE_USE_PIC = 1
 
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -DPACKAGE_VERSION="\"moz\""
 DEFINES += -DPACKAGE_BUGREPORT="\"http://bugzilla.mozilla.org/\""
+DEFINES += -DNOMINMAX
+
+# Suppress ANSI strict warnings
+# because Googlers don't care about comma-at-end-of-enumerator errors.
+CXXFLAGS := $(filter-out -pedantic,$(CXXFLAGS))
+CFLAGS := $(filter-out -pedantic,$(CFLAGS))
--- a/gfx/ots/src/cff.cc
+++ b/gfx/ots/src/cff.cc
@@ -14,22 +14,22 @@
 // http://www.microsoft.com/opentype/otspec/cff.htm
 // http://www.microsoft.com/opentype/otspec/5176.CFF.pdf
 
 namespace {
 
 enum DICT_OPERAND_TYPE {
   DICT_OPERAND_INTEGER,
   DICT_OPERAND_REAL,
-  DICT_OPERATOR
+  DICT_OPERATOR,
 };
 
 enum DICT_DATA_TYPE {
   DICT_DATA_TOPLEVEL,
-  DICT_DATA_FDARRAY
+  DICT_DATA_FDARRAY,
 };
 
 // see Appendix. A
 const size_t kNStdString = 390;
 
 bool ReadOffset(ots::Buffer *table, uint8_t off_size, uint32_t *offset) {
   if (off_size > 4) {
     return OTS_FAILURE();
@@ -99,16 +99,18 @@ bool ParseIndex(ots::Buffer *table, ots:
       return OTS_FAILURE();
     }
 
     index->offsets.push_back(
         object_data_offset + (rel_offset - 1));  // less than length(), 1GB.
   }
 
   for (unsigned i = 1; i < index->offsets.size(); ++i) {
+    // We allow consecutive identical offsets here for zero-length strings.
+    // See http://crbug.com/69341 for more details.
     if (index->offsets[i] < index->offsets[i - 1]) {
       return OTS_FAILURE();
     }
   }
 
   index->offset_to_next = index->offsets.back();
   return true;
 }
@@ -970,17 +972,17 @@ bool ots_cff_parse(OpenTypeFile *file, c
       return OTS_FAILURE();
     }
   }
 
   return true;
 }
 
 bool ots_cff_should_serialise(OpenTypeFile *file) {
-  return file->cff;
+  return file->cff != NULL;
 }
 
 bool ots_cff_serialise(OTSStream *out, OpenTypeFile *file) {
   // TODO(yusukes): would be better to transcode the data,
   //                rather than simple memcpy.
   if (!out->Write(file->cff->data, file->cff->length)) {
     return OTS_FAILURE();
   }
--- a/gfx/ots/src/cff_type2_charstring.h
+++ b/gfx/ots/src/cff_type2_charstring.h
@@ -85,16 +85,16 @@ enum Type2CharStringOperator {
   kSqrt = (12 << 8) + 26,
   kDup = (12 << 8) + 27,
   kExch = (12 << 8) + 28,
   kIndex = (12 << 8) + 29,
   kRoll = (12 << 8) + 30,
   kHFlex = (12 << 8) + 34,
   kFlex = (12 << 8) + 35,
   kHFlex1 = (12 << 8) + 36,
-  kFlex1 = (12 << 8) + 37
+  kFlex1 = (12 << 8) + 37,
   // Operators that are obsoleted or undocumented, such as 'blend', will be
   // rejected.
 };
 
 }  // namespace ots
 
 #endif  // OTS_CFF_TYPE2_CHARSTRING_H_
--- a/gfx/ots/src/cmap.cc
+++ b/gfx/ots/src/cmap.cc
@@ -27,32 +27,46 @@ struct CMAPSubtableHeader {
 struct Subtable314Range {
   uint16_t start_range;
   uint16_t end_range;
   int16_t id_delta;
   uint16_t id_range_offset;
   uint32_t id_range_offset_offset;
 };
 
-// The maximum number of groups in format 12 or 13 subtables.
+// The maximum number of groups in format 12, 13 or 14 subtables.
 // Note: 0xFFFF is the maximum number of glyphs in a single font file.
 const unsigned kMaxCMAPGroups = 0xFFFF;
 
 // Glyph array size for the Mac Roman (format 0) table.
 const size_t kFormat0ArraySize = 256;
 
 // The upper limit of the Unicode code point.
 const uint32_t kUnicodeUpperLimit = 0x10FFFF;
 
-// Parses either 3.0.4 or 3.1.4 tables.
-bool Parse3x4(ots::OpenTypeFile *file, int encoding,
+// The maximum number of UVS records (See below).
+const uint32_t kMaxCMAPSelectorRecords = 259;
+// The range of UVSes are:
+//   0x180B-0x180D (3 code points)
+//   0xFE00-0xFE0F (16 code points)
+//   0xE0100-0xE01EF (240 code points)
+const uint32_t kMongolianVSStart = 0x180B;
+const uint32_t kMongolianVSEnd = 0x180D;
+const uint32_t kVSStart = 0xFE00;
+const uint32_t kVSEnd = 0xFE0F;
+const uint32_t kIVSStart = 0xE0100;
+const uint32_t kIVSEnd = 0xE01EF;
+const uint32_t kUVSUpperLimit = 0xFFFFFF;
+
+// Parses Format 4 tables
+bool ParseFormat4(ots::OpenTypeFile *file, int platform, int encoding,
               const uint8_t *data, size_t length, uint16_t num_glyphs) {
   ots::Buffer subtable(data, length);
 
-  // 3.0.4 or 3.1.4 subtables are complex and, rather than expanding the
+  // 0.3.4, 3.0.4 or 3.1.4 subtables are complex and, rather than expanding the
   // whole thing and recompacting it, we validate it and include it verbatim
   // in the output.
 
   if (!file->os2) {
     return OTS_FAILURE();
   }
 
   if (!subtable.Skip(4)) {
@@ -224,22 +238,25 @@ bool Parse3x4(ots::OpenTypeFile *file, i
           return OTS_FAILURE();
         }
       }
     }
   }
 
   // We accept the table.
   // TODO(yusukes): transcode the subtable.
-  if (encoding == 0) {
+  if (platform == 3 && encoding == 0) {
     file->cmap->subtable_3_0_4_data = data;
     file->cmap->subtable_3_0_4_length = length;
-  } else if (encoding == 1) {
+  } else if (platform == 3 && encoding == 1) {
     file->cmap->subtable_3_1_4_data = data;
     file->cmap->subtable_3_1_4_length = length;
+  } else if (platform == 0 && encoding == 3) {
+    file->cmap->subtable_0_3_4_data = data;
+    file->cmap->subtable_0_3_4_length = length;
   } else {
     return OTS_FAILURE();
   }
 
   return true;
 }
 
 bool Parse31012(ots::OpenTypeFile *file,
@@ -384,118 +401,147 @@ bool Parse31013(ots::OpenTypeFile *file,
     if (groups[i].start_range <= groups[i - 1].end_range) {
       return OTS_FAILURE();
     }
   }
 
   return true;
 }
 
-// Parses 0.5.14 tables.
 bool Parse0514(ots::OpenTypeFile *file,
                const uint8_t *data, size_t length, uint16_t num_glyphs) {
+  // Unicode Variation Selector table
   ots::Buffer subtable(data, length);
 
-  // Format 14 subtables are a bit complex, so rather than rebuilding the
-  // entire thing, we validate it and then include it verbatim in the output.
+  // Format 14 tables are simple. We parse these and fully serialise them
+  // later.
 
-  const off_t offset_var_selector_records = 10;
-  const size_t size_of_var_selector_record = 11;
-  const size_t size_of_def_uvs_table = 4;
-  const size_t size_of_non_def_uvs_table = 5;
-
-  if (!subtable.Skip(6)) { // skip format and length
+  // Skip format (USHORT) and length (ULONG)
+  if (!subtable.Skip(6)) {
     return OTS_FAILURE();
   }
-  uint32_t num_var_selector_records = 0;
-  if (!subtable.ReadU32(&num_var_selector_records)) {
+
+  uint32_t num_records = 0;
+  if (!subtable.ReadU32(&num_records)) {
     return OTS_FAILURE();
   }
-  if ((length - offset_var_selector_records) / size_of_var_selector_record <
-      num_var_selector_records) {
+  if (num_records == 0 || num_records > kMaxCMAPSelectorRecords) {
     return OTS_FAILURE();
   }
 
-  uint32_t prev_var_selector = 0;
-  for (uint32_t i = 0; i < num_var_selector_records; i++) {
-    uint32_t var_selector, def_uvs_offset, non_def_uvs_offset;
-    if (!subtable.ReadU24(&var_selector) ||
-        !subtable.ReadU32(&def_uvs_offset) ||
-        !subtable.ReadU32(&non_def_uvs_offset)) {
+  std::vector<ots::OpenTypeCMAPSubtableVSRecord>& records
+      = file->cmap->subtable_0_5_14;
+  records.resize(num_records);
+
+  for (unsigned i = 0; i < num_records; ++i) {
+    if (!subtable.ReadU24(&records[i].var_selector) ||
+        !subtable.ReadU32(&records[i].default_offset) ||
+        !subtable.ReadU32(&records[i].non_default_offset)) {
+      return OTS_FAILURE();
+    }
+    // Checks the value of variation selector
+    if (!((records[i].var_selector >= kMongolianVSStart &&
+           records[i].var_selector <= kMongolianVSEnd) ||
+          (records[i].var_selector >= kVSStart &&
+           records[i].var_selector <= kVSEnd) ||
+          (records[i].var_selector >= kIVSStart &&
+           records[i].var_selector <= kIVSEnd))) {
+      return OTS_FAILURE();
+    }
+    if (i > 0 &&
+        records[i-1].var_selector >= records[i].var_selector) {
       return OTS_FAILURE();
     }
-    if (var_selector <= prev_var_selector ||
-        var_selector > kUnicodeUpperLimit ||
-        def_uvs_offset > length - 4 ||
-        non_def_uvs_offset > length - 4) {
+
+    // Checks offsets
+    if (!records[i].default_offset && !records[i].non_default_offset) {
+      return OTS_FAILURE();
+    }
+    if (records[i].default_offset &&
+        records[i].default_offset >= length) {
       return OTS_FAILURE();
     }
-    prev_var_selector = var_selector;
+    if (records[i].non_default_offset &&
+        records[i].non_default_offset >= length) {
+      return OTS_FAILURE();
+    }
+  }
 
-    if (def_uvs_offset) {
-      uint32_t num_unicode_value_ranges;
-      memcpy(&num_unicode_value_ranges, data + def_uvs_offset, 4);
-      num_unicode_value_ranges = ntohl(num_unicode_value_ranges);
-      if ((length - def_uvs_offset) / size_of_def_uvs_table <
-           num_unicode_value_ranges) {
+  for (unsigned i = 0; i < num_records; ++i) {
+    // Checks default UVS table
+    if (records[i].default_offset) {
+      subtable.set_offset(records[i].default_offset);
+      uint32_t num_ranges = 0;
+      if (!subtable.ReadU32(&num_ranges)) {
+        return OTS_FAILURE();
+      }
+      if (!num_ranges || num_ranges > kMaxCMAPGroups) {
         return OTS_FAILURE();
       }
 
-      const uint8_t *tables = data + def_uvs_offset + 4;
-      uint32_t prev_end_unicode = 0;
-      for (uint32_t j = 0; j < num_unicode_value_ranges;
-           j++, tables += size_of_def_uvs_table) {
-        uint32_t start_unicode = 0, end_unicode;
-        memcpy(reinterpret_cast<uint8_t*>(&start_unicode) + 1, tables, 3);
-        start_unicode = ntohl(start_unicode);
-        end_unicode = start_unicode + *(tables + 3);
-        if ((j > 0 && start_unicode <= prev_end_unicode) ||
-            end_unicode > kUnicodeUpperLimit) {
+      uint32_t last_unicode_value = 0;
+      std::vector<ots::OpenTypeCMAPSubtableVSRange>& ranges
+          = records[i].ranges;
+      ranges.resize(num_ranges);
+
+      for (unsigned j = 0; j < num_ranges; ++j) {
+        if (!subtable.ReadU24(&ranges[j].unicode_value) ||
+            !subtable.ReadU8(&ranges[j].additional_count)) {
           return OTS_FAILURE();
         }
-        prev_end_unicode = end_unicode;
+        const uint32_t check_value =
+            ranges[j].unicode_value + ranges[i].additional_count;
+        if (ranges[j].unicode_value == 0 ||
+            ranges[j].unicode_value > kUnicodeUpperLimit ||
+            check_value > kUVSUpperLimit ||
+            (last_unicode_value &&
+             ranges[j].unicode_value <= last_unicode_value)) {
+          return OTS_FAILURE();
+        }
+        last_unicode_value = check_value;
       }
     }
 
-    if (non_def_uvs_offset) {
-      uint32_t num_uvs_mappings;
-      memcpy(&num_uvs_mappings, data + non_def_uvs_offset, 4);
-      num_uvs_mappings = ntohl(num_uvs_mappings);
-      if ((length - non_def_uvs_offset) / size_of_non_def_uvs_table <
-          num_uvs_mappings) {
+    // Checks non default UVS table
+    if (records[i].non_default_offset) {
+      subtable.set_offset(records[i].non_default_offset);
+      uint32_t num_mappings = 0;
+      if (!subtable.ReadU32(&num_mappings)) {
+        return OTS_FAILURE();
+      }
+      if (!num_mappings || num_mappings > kMaxCMAPGroups) {
         return OTS_FAILURE();
       }
 
-      const uint8_t *tables = data + non_def_uvs_offset + 4;
-      uint32_t prev_unicode = 0;
-      for (uint32_t j = 0; j < num_uvs_mappings;
-           j++, tables += size_of_non_def_uvs_table) {
-        uint32_t unicode_value = 0;
-        memcpy(reinterpret_cast<uint8_t*>(&unicode_value) + 1, tables, 3);
-        unicode_value = ntohl(unicode_value);
-        if ((j > 0 && unicode_value <= prev_unicode) ||
-            unicode_value > kUnicodeUpperLimit) {
+      uint32_t last_unicode_value = 0;
+      std::vector<ots::OpenTypeCMAPSubtableVSMapping>& mappings
+          = records[i].mappings;
+      mappings.resize(num_mappings);
+
+      for (unsigned j = 0; j < num_mappings; ++j) {
+        if (!subtable.ReadU24(&mappings[j].unicode_value) ||
+            !subtable.ReadU16(&mappings[j].glyph_id)) {
           return OTS_FAILURE();
         }
-        uint16_t glyph;
-        memcpy(&glyph, tables + 3, 2);
-        glyph = ntohs(glyph);
-        if (glyph >= num_glyphs) {
+        if (mappings[j].glyph_id == 0 ||
+            mappings[j].unicode_value == 0 ||
+            mappings[j].unicode_value > kUnicodeUpperLimit ||
+            (last_unicode_value &&
+             mappings[j].unicode_value <= last_unicode_value)) {
           return OTS_FAILURE();
         }
-        prev_unicode = unicode_value;
+        last_unicode_value = mappings[j].unicode_value;
       }
     }
   }
 
-  // We accept the table.
-  // TODO: transcode the subtable.
-  file->cmap->subtable_0_5_14_data = data;
-  file->cmap->subtable_0_5_14_length = length;
-
+  if (subtable.offset() != length) {
+    return OTS_FAILURE();
+  }
+  file->cmap->subtable_0_5_14_length = subtable.offset();
   return true;
 }
 
 bool Parse100(ots::OpenTypeFile *file, const uint8_t *data, size_t length) {
   // Mac Roman table
   ots::Buffer subtable(data, length);
 
   if (!subtable.Skip(4)) {
@@ -680,40 +726,41 @@ bool ots_cmap_parse(OpenTypeFile *file, 
   //   3             0            4       (MS Symbol)
   //   3             1            4       (MS Unicode BMP)
   //   3             10           12      (MS Unicode UCS-4)
   //   3             10           13      (MS UCS-4 Fallback mapping)
   //
   // Note:
   //  * 0-0-4 table is (usually) written as a 3-1-4 table. If 3-1-4 table
   //    also exists, the 0-0-4 table is ignored.
-  //  * 0-3-4 table is written as a 3-1-4 table. If 3-1-4 table also exists,
-  //    the 0-3-4 table is ignored.
+  //  * Unlike 0-0-4 table, 0-3-4 table is written as a 0-3-4 table.
+  //    Some fonts which include 0-5-14 table seems to be required 0-3-4
+  //    table. The 0-3-4 table will be wriiten even if 3-1-4 table also exists.
   //  * 0-3-12 table is written as a 3-10-12 table. If 3-10-12 table also
   //    exists, the 0-3-12 table is ignored.
   //
 
   for (unsigned i = 0; i < num_tables; ++i) {
     if (subtable_headers[i].platform == 0) {
       // Unicode platform
 
       if ((subtable_headers[i].encoding == 0) &&
           (subtable_headers[i].format == 4)) {
         // parse and output the 0-0-4 table as 3-1-4 table. Sometimes the 0-0-4
         // table actually points to MS symbol data and thus should be parsed as
         // 3-0-4 table (e.g., marqueem.ttf and quixotic.ttf). This error will be
         // recovered in ots_cmap_serialise().
-        if (!Parse3x4(file, 1, data + subtable_headers[i].offset,
+        if (!ParseFormat4(file, 3, 1, data + subtable_headers[i].offset,
                       subtable_headers[i].length, num_glyphs)) {
           return OTS_FAILURE();
         }
       } else if ((subtable_headers[i].encoding == 3) &&
                  (subtable_headers[i].format == 4)) {
-        // parse and output the 0-3-4 table as 3-1-4 table.
-        if (!Parse3x4(file, 1, data + subtable_headers[i].offset,
+        // parse and output the 0-3-4 table as 0-3-4 table.
+        if (!ParseFormat4(file, 0, 3, data + subtable_headers[i].offset,
                       subtable_headers[i].length, num_glyphs)) {
           return OTS_FAILURE();
         }
       } else if ((subtable_headers[i].encoding == 3) &&
                  (subtable_headers[i].format == 12)) {
         // parse and output the 0-3-12 table as 3-10-12 table.
         if (!Parse31012(file, data + subtable_headers[i].offset,
                         subtable_headers[i].length, num_glyphs)) {
@@ -721,38 +768,37 @@ bool ots_cmap_parse(OpenTypeFile *file, 
         }
       } else if ((subtable_headers[i].encoding == 5) &&
                  (subtable_headers[i].format == 14)) {
         if (!Parse0514(file, data + subtable_headers[i].offset,
                        subtable_headers[i].length, num_glyphs)) {
           return OTS_FAILURE();
         }
       }
-
     } else if (subtable_headers[i].platform == 1) {
       // Mac platform
 
       if ((subtable_headers[i].encoding == 0) &&
           (subtable_headers[i].format == 0)) {
         // parse and output the 1-0-0 table.
         if (!Parse100(file, data + subtable_headers[i].offset,
                       subtable_headers[i].length)) {
           return OTS_FAILURE();
         }
       }
-
     } else if (subtable_headers[i].platform == 3) {
       // MS platform
 
       switch (subtable_headers[i].encoding) {
         case 0:
         case 1:
           if (subtable_headers[i].format == 4) {
             // parse 3-0-4 or 3-1-4 table.
-            if (!Parse3x4(file, subtable_headers[i].encoding,
+            if (!ParseFormat4(file, subtable_headers[i].platform,
+                          subtable_headers[i].encoding,
                           data + subtable_headers[i].offset,
                           subtable_headers[i].length, num_glyphs)) {
               return OTS_FAILURE();
             }
           }
           break;
         case 10:
           if (subtable_headers[i].format == 12) {
@@ -772,52 +818,113 @@ bool ots_cmap_parse(OpenTypeFile *file, 
       }
     }
   }
 
   return true;
 }
 
 bool ots_cmap_should_serialise(OpenTypeFile *file) {
-  return file->cmap;
+  return file->cmap != NULL;
 }
 
 bool ots_cmap_serialise(OTSStream *out, OpenTypeFile *file) {
-  const bool have_0514 = file->cmap->subtable_0_5_14_data;
-  const bool have_100 = file->cmap->subtable_1_0_0.size();
-  const bool have_304 = file->cmap->subtable_3_0_4_data;
+  const bool have_034 = file->cmap->subtable_0_3_4_data != NULL;
+  const bool have_0514 = file->cmap->subtable_0_5_14.size() != 0;
+  const bool have_100 = file->cmap->subtable_1_0_0.size() != 0;
+  const bool have_304 = file->cmap->subtable_3_0_4_data != NULL;
   // MS Symbol and MS Unicode tables should not co-exist.
   // See the comment above in 0-0-4 parser.
   const bool have_314 = (!have_304) && file->cmap->subtable_3_1_4_data;
-  const bool have_31012 = file->cmap->subtable_3_10_12.size();
-  const bool have_31013 = file->cmap->subtable_3_10_13.size();
-  const unsigned num_subtables = static_cast<unsigned>(have_0514) +
+  const bool have_31012 = file->cmap->subtable_3_10_12.size() != 0;
+  const bool have_31013 = file->cmap->subtable_3_10_13.size() != 0;
+  const unsigned num_subtables = static_cast<unsigned>(have_034) +
+                                 static_cast<unsigned>(have_0514) +
                                  static_cast<unsigned>(have_100) +
                                  static_cast<unsigned>(have_304) +
                                  static_cast<unsigned>(have_314) +
                                  static_cast<unsigned>(have_31012) +
                                  static_cast<unsigned>(have_31013);
   const off_t table_start = out->Tell();
 
   // Some fonts don't have 3-0-4 MS Symbol nor 3-1-4 Unicode BMP tables
   // (e.g., old fonts for Mac). We don't support them.
-  if (!have_304 && !have_314) {
+  if (!have_304 && !have_314 && !have_034) {
     return OTS_FAILURE();
   }
 
   if (!out->WriteU16(0) ||
       !out->WriteU16(num_subtables)) {
     return OTS_FAILURE();
   }
 
   const off_t record_offset = out->Tell();
   if (!out->Pad(num_subtables * 8)) {
     return OTS_FAILURE();
   }
 
+  const off_t offset_034 = out->Tell();
+  if (have_034) {
+    if (!out->Write(file->cmap->subtable_0_3_4_data,
+                    file->cmap->subtable_0_3_4_length)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  const off_t offset_0514 = out->Tell();
+  if (have_0514) {
+    const std::vector<ots::OpenTypeCMAPSubtableVSRecord> &records
+        = file->cmap->subtable_0_5_14;
+    const unsigned num_records = records.size();
+    if (!out->WriteU16(14) ||
+        !out->WriteU32(file->cmap->subtable_0_5_14_length) ||
+        !out->WriteU32(num_records)) {
+      return OTS_FAILURE();
+    }
+    for (unsigned i = 0; i < num_records; ++i) {
+      if (!out->WriteU24(records[i].var_selector) ||
+          !out->WriteU32(records[i].default_offset) ||
+          !out->WriteU32(records[i].non_default_offset)) {
+        return OTS_FAILURE();
+      }
+    }
+    for (unsigned i = 0; i < num_records; ++i) {
+      if (records[i].default_offset) {
+        const std::vector<ots::OpenTypeCMAPSubtableVSRange> &ranges
+            = records[i].ranges;
+        const unsigned num_ranges = ranges.size();
+        if (!out->Seek(records[i].default_offset + offset_0514) ||
+            !out->WriteU32(num_ranges)) {
+          return OTS_FAILURE();
+        }
+        for (unsigned j = 0; j < num_ranges; ++j) {
+          if (!out->WriteU24(ranges[j].unicode_value) ||
+              !out->WriteU8(ranges[j].additional_count)) {
+            return OTS_FAILURE();
+          }
+        }
+      }
+      if (records[i].non_default_offset) {
+        const std::vector<ots::OpenTypeCMAPSubtableVSMapping> &mappings
+            = records[i].mappings;
+        const unsigned num_mappings = mappings.size();
+        if (!out->Seek(records[i].non_default_offset + offset_0514) ||
+            !out->WriteU32(num_mappings)) {
+          return OTS_FAILURE();
+        }
+        for (unsigned j = 0; j < num_mappings; ++j) {
+          if (!out->WriteU24(mappings[j].unicode_value) ||
+              !out->WriteU16(mappings[j].glyph_id)) {
+            return OTS_FAILURE();
+          }
+        }
+      }
+    }
+  }
+
   const off_t offset_100 = out->Tell();
   if (have_100) {
     if (!out->WriteU16(0) ||  // format
         !out->WriteU16(6 + kFormat0ArraySize) ||  // length
         !out->WriteU16(0)) {  // language
       return OTS_FAILURE();
     }
     if (!out->Write(&(file->cmap->subtable_1_0_0[0]), kFormat0ArraySize)) {
@@ -880,35 +987,35 @@ bool ots_cmap_serialise(OTSStream *out, 
       if (!out->WriteU32(groups[i].start_range) ||
           !out->WriteU32(groups[i].end_range) ||
           !out->WriteU32(groups[i].start_glyph_id)) {
         return OTS_FAILURE();
       }
     }
   }
 
-  const off_t offset_0514 = out->Tell();
-  if (have_0514) {
-    if (!out->Write(file->cmap->subtable_0_5_14_data,
-                    file->cmap->subtable_0_5_14_length)) {
-      return OTS_FAILURE();
-    }
-  }
-
   const off_t table_end = out->Tell();
   // We might have hanging bytes from the above's checksum which the OTSStream
   // then merges into the table of offsets.
   OTSStream::ChecksumState saved_checksum = out->SaveChecksumState();
   out->ResetChecksum();
 
   // Now seek back and write the table of offsets
   if (!out->Seek(record_offset)) {
     return OTS_FAILURE();
   }
 
+  if (have_034) {
+    if (!out->WriteU16(0) ||
+        !out->WriteU16(3) ||
+        !out->WriteU32(offset_034 - table_start)) {
+      return OTS_FAILURE();
+    }
+  }
+
   if (have_0514) {
     if (!out->WriteU16(0) ||
         !out->WriteU16(5) ||
         !out->WriteU32(offset_0514 - table_start)) {
       return OTS_FAILURE();
     }
   }
 
--- a/gfx/ots/src/cmap.h
+++ b/gfx/ots/src/cmap.h
@@ -12,35 +12,59 @@
 namespace ots {
 
 struct OpenTypeCMAPSubtableRange {
   uint32_t start_range;
   uint32_t end_range;
   uint32_t start_glyph_id;
 };
 
+struct OpenTypeCMAPSubtableVSRange {
+  uint32_t unicode_value;
+  uint8_t additional_count;
+};
+
+struct OpenTypeCMAPSubtableVSMapping {
+  uint32_t unicode_value;
+  uint16_t glyph_id;
+};
+
+struct OpenTypeCMAPSubtableVSRecord {
+  uint32_t var_selector;
+  uint32_t default_offset;
+  uint32_t non_default_offset;
+  std::vector<OpenTypeCMAPSubtableVSRange> ranges;
+  std::vector<OpenTypeCMAPSubtableVSMapping> mappings;
+};
+
 struct OpenTypeCMAP {
   OpenTypeCMAP()
-      : subtable_3_0_4_data(NULL),
+      : subtable_0_3_4_data(NULL),
+        subtable_0_3_4_length(0),
+        subtable_0_5_14_length(0),
+        subtable_3_0_4_data(NULL),
         subtable_3_0_4_length(0),
         subtable_3_1_4_data(NULL),
-        subtable_3_1_4_length(0),
-        subtable_0_5_14_data(NULL),
-        subtable_0_5_14_length(0) {
+        subtable_3_1_4_length(0) {
   }
 
+  // Platform 0, Encoding 3, Format 4, Unicode BMP table.
+  const uint8_t *subtable_0_3_4_data;
+  size_t subtable_0_3_4_length;
+
+  // Platform 0, Encoding 5, Format 14, Unicode Variation Sequence table.
+  size_t subtable_0_5_14_length;
+  std::vector<OpenTypeCMAPSubtableVSRecord> subtable_0_5_14;
+
   // Platform 3, Encoding 0, Format 4, MS Symbol table.
   const uint8_t *subtable_3_0_4_data;
   size_t subtable_3_0_4_length;
   // Platform 3, Encoding 1, Format 4, MS Unicode BMP table.
   const uint8_t *subtable_3_1_4_data;
   size_t subtable_3_1_4_length;
-  // Platform 0, Encoding 5, Format 14, Unicode Variation Sequences table.
-  const uint8_t *subtable_0_5_14_data;
-  size_t subtable_0_5_14_length;
 
   // Platform 3, Encoding 10, Format 12, MS Unicode UCS-4 table.
   std::vector<OpenTypeCMAPSubtableRange> subtable_3_10_12;
   // Platform 3, Encoding 10, Format 13, MS UCS-4 Fallback table.
   std::vector<OpenTypeCMAPSubtableRange> subtable_3_10_13;
   // Platform 1, Encoding 0, Format 0, Mac Roman table.
   std::vector<uint8_t> subtable_1_0_0;
 };
--- a/gfx/ots/src/gasp.cc
+++ b/gfx/ots/src/gasp.cc
@@ -1,13 +1,12 @@
 // 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.
 
-#include <new>
 #include "gasp.h"
 
 // gasp - Grid-fitting And Scan-conversion Procedure
 // http://www.microsoft.com/opentype/otspec/gasp.htm
 
 #define DROP_THIS_TABLE \
   do { delete file->gasp; file->gasp = 0; } while (0)
 
@@ -74,17 +73,17 @@ bool ots_gasp_parse(OpenTypeFile *file, 
 
     gasp->gasp_ranges.push_back(std::make_pair(max_ppem, behavior));
   }
 
   return true;
 }
 
 bool ots_gasp_should_serialise(OpenTypeFile *file) {
-  return file->gasp;
+  return file->gasp != NULL;
 }
 
 bool ots_gasp_serialise(OTSStream *out, OpenTypeFile *file) {
   const OpenTypeGASP *gasp = file->gasp;
 
   if (!out->WriteU16(gasp->version) ||
       !out->WriteU16(gasp->gasp_ranges.size())) {
     return OTS_FAILURE();
--- a/gfx/ots/src/gasp.h
+++ b/gfx/ots/src/gasp.h
@@ -1,15 +1,16 @@
 // 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.
 
 #ifndef OTS_GASP_H_
 #define OTS_GASP_H_
 
+#include <new>
 #include <utility>  // std::pair
 #include <vector>
 
 #include "ots.h"
 
 namespace ots {
 
 struct OpenTypeGASP {
--- a/gfx/ots/src/gdef.cc
+++ b/gfx/ots/src/gdef.cc
@@ -1,45 +1,393 @@
-// Copyright (c) 2010 Mozilla Foundation. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "gdef.h"
 
-// GDEF - Glyph Definition Table
+#include <limits>
+#include <vector>
+
+#include "gpos.h"
+#include "gsub.h"
+#include "layout.h"
+#include "maxp.h"
+
+// GDEF - The Glyph Definition Table
 // http://www.microsoft.com/typography/otspec/gdef.htm
 
+namespace {
+
+// The maximum class value in class definition tables.
+const uint16_t kMaxClassDefValue = 0xFFFF;
+// The maximum class value in the glyph class definision table.
+const uint16_t kMaxGlyphClassDefValue = 4;
+// The maximum format number of caret value tables.
+// We don't support format 3 for now. See the comment in
+// ParseLigCaretListTable() for the reason.
+const uint16_t kMaxCaretValueFormat = 2;
+
+bool ParseGlyphClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
+                             size_t length, const uint16_t num_glyphs) {
+  return ots::ParseClassDefTable(data, length, num_glyphs,
+                                 kMaxGlyphClassDefValue);
+}
+
+bool ParseAttachListTable(ots::OpenTypeFile *file, const uint8_t *data,
+                          size_t length, const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t offset_coverage = 0;
+  uint16_t glyph_count = 0;
+  if (!subtable.ReadU16(&offset_coverage) ||
+      !subtable.ReadU16(&glyph_count)) {
+    return OTS_FAILURE();
+  }
+  const unsigned attach_points_end = static_cast<unsigned>(4) + 2*glyph_count;
+  if (attach_points_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  if (offset_coverage == 0 || offset_coverage >= length ||
+      offset_coverage < attach_points_end) {
+    return OTS_FAILURE();
+  }
+  if (glyph_count > num_glyphs) {
+    OTS_WARNING("bad glyph count: %u", glyph_count);
+    return OTS_FAILURE();
+  }
+
+  std::vector<uint16_t> attach_points;
+  attach_points.resize(glyph_count);
+  for (unsigned i = 0; i < glyph_count; ++i) {
+    if (!subtable.ReadU16(&attach_points[i])) {
+      return OTS_FAILURE();
+    }
+    if (attach_points[i] >= length ||
+        attach_points[i] < attach_points_end) {
+      return OTS_FAILURE();
+    }
+  }
+
+  // Parse coverage table
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage, num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  // Parse attach point table
+  for (unsigned i = 0; i < attach_points.size(); ++i) {
+    subtable.set_offset(attach_points[i]);
+    uint16_t point_count = 0;
+    if (!subtable.ReadU16(&point_count)) {
+      return OTS_FAILURE();
+    }
+    if (point_count == 0) {
+      return OTS_FAILURE();
+    }
+    uint16_t last_point_index = 0;
+    uint16_t point_index = 0;
+    for (unsigned j = 0; j < point_count; ++j) {
+      if (!subtable.ReadU16(&point_index)) {
+        return OTS_FAILURE();
+      }
+      // Contour point indeces are in increasing numerical order
+      if (last_point_index != 0 && last_point_index >= point_index) {
+        OTS_WARNING("bad contour indeces: %u >= %u",
+                    last_point_index, point_index);
+        return OTS_FAILURE();
+      }
+      last_point_index = point_index;
+    }
+  }
+  return true;
+}
+
+bool ParseLigCaretListTable(ots::OpenTypeFile *file, const uint8_t *data,
+                            size_t length, const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+  uint16_t offset_coverage = 0;
+  uint16_t lig_glyph_count = 0;
+  if (!subtable.ReadU16(&offset_coverage) ||
+      !subtable.ReadU16(&lig_glyph_count)) {
+    return OTS_FAILURE();
+  }
+  const unsigned lig_glyphs_end = static_cast<unsigned>(4) + 2*lig_glyph_count;
+  if (lig_glyphs_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  if (offset_coverage == 0 || offset_coverage >= length ||
+      offset_coverage < lig_glyphs_end) {
+    return OTS_FAILURE();
+  }
+  if (lig_glyph_count > num_glyphs) {
+    OTS_WARNING("bad ligature glyph count: %u", lig_glyph_count);
+    return OTS_FAILURE();
+  }
+
+  std::vector<uint16_t> lig_glyphs;
+  lig_glyphs.resize(lig_glyph_count);
+  for (unsigned i = 0; i < lig_glyph_count; ++i) {
+    if (!subtable.ReadU16(&lig_glyphs[i])) {
+      return OTS_FAILURE();
+    }
+    if (lig_glyphs[i] >= length || lig_glyphs[i] < lig_glyphs_end) {
+      return OTS_FAILURE();
+    }
+  }
+
+  // Parse coverage table
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage, num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  // Parse ligature glyph table
+  for (unsigned i = 0; i < lig_glyphs.size(); ++i) {
+    subtable.set_offset(lig_glyphs[i]);
+    uint16_t caret_count = 0;
+    if (!subtable.ReadU16(&caret_count)) {
+      return OTS_FAILURE();
+    }
+    if (caret_count == 0) {
+      OTS_WARNING("bad caret value count: %u", caret_count);
+      return OTS_FAILURE();
+    }
+
+    std::vector<uint16_t> caret_values;
+    caret_values.resize(caret_count);
+    uint16_t last_offset_caret = 0;
+    unsigned caret_values_end = static_cast<unsigned>(2) * 2*caret_count;
+    for (unsigned j = 0; j < caret_count; ++j) {
+      if (!subtable.ReadU16(&caret_values[j])) {
+        return OTS_FAILURE();
+      }
+      if (caret_values[j] >= length || caret_values[j] < caret_values_end) {
+        return OTS_FAILURE();
+      }
+      // Caret offsets are in increasing coordinate order
+      if (last_offset_caret != 0 && last_offset_caret >= caret_values[j]) {
+        OTS_WARNING("offset isn't in increasing coordinate order: %u >= %u",
+                    last_offset_caret, caret_values[j]);
+        return OTS_FAILURE();
+      }
+      last_offset_caret = caret_values[j];
+    }
+
+    // Parse caret values table
+    for (unsigned j = 0; j < caret_count; ++j) {
+      subtable.set_offset(lig_glyphs[i] + caret_values[j]);
+      uint16_t caret_format = 0;
+      if (!subtable.ReadU16(&caret_format)) {
+        return OTS_FAILURE();
+      }
+      // TODO(bashi): We only support caret value format 1 and 2 for now
+      // because there are no fonts which contain caret value format 3
+      // as far as we investigated.
+      if (caret_format == 0 || caret_format > kMaxCaretValueFormat) {
+        OTS_WARNING("bad caret value format: %u", caret_format);
+        return OTS_FAILURE();
+      }
+      // CaretValueFormats contain a 2-byte field which could be
+      // arbitrary value.
+      if (!subtable.Skip(2)) {
+        return OTS_FAILURE();
+      }
+    }
+  }
+  return true;
+}
+
+bool ParseMarkAttachClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
+                                  size_t length, const uint16_t num_glyphs) {
+  return ots::ParseClassDefTable(data, length, num_glyphs, kMaxClassDefValue);
+}
+
+bool ParseMarkGlyphSetsDefTable(ots::OpenTypeFile *file, const uint8_t *data,
+                                size_t length, const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+  uint16_t format = 0;
+  uint16_t mark_set_count = 0;
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&mark_set_count)) {
+    return OTS_FAILURE();
+  }
+  if (format != 1) {
+    OTS_WARNING("bad mark glyph set table format: %u", format);
+    return OTS_FAILURE();
+  }
+
+  const unsigned mark_sets_end = static_cast<unsigned>(4) + 2*mark_set_count;
+  if (mark_sets_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < mark_set_count; ++i) {
+    uint32_t offset_coverage = 0;
+    if (!subtable.ReadU32(&offset_coverage)) {
+      return OTS_FAILURE();
+    }
+    if (offset_coverage >= length ||
+        offset_coverage < mark_sets_end) {
+      return OTS_FAILURE();
+    }
+    if (!ots::ParseCoverageTable(data + offset_coverage,
+                                 length - offset_coverage, num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  }
+  file->gdef->num_mark_glyph_sets = mark_set_count;
+  return true;
+}
+
+}  // namespace
+
+#define DROP_THIS_TABLE \
+  do { file->gdef->data = 0; file->gdef->length = 0; } while (0)
+
 namespace ots {
 
 bool ots_gdef_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  // Grab the number of glyphs in the file from the maxp table to check
+  // GlyphIDs in GDEF table.
+  if (!file->maxp) {
+    return OTS_FAILURE();
+  }
+  const uint16_t num_glyphs = file->maxp->num_glyphs;
+
   Buffer table(data, length);
 
   OpenTypeGDEF *gdef = new OpenTypeGDEF;
   file->gdef = gdef;
 
-  if (!table.Skip(length)) {
+  uint32_t version = 0;
+  if (!table.ReadU32(&version)) {
+    return OTS_FAILURE();
+  }
+  if (version < 0x00010000 || version == 0x00010001) {
+    OTS_WARNING("bad GDEF version");
+    DROP_THIS_TABLE;
+    return true;
+  }
+
+  if (version >= 0x00010002) {
+    gdef->version_2 = true;
+  }
+
+  uint16_t offset_glyph_class_def = 0;
+  uint16_t offset_attach_list = 0;
+  uint16_t offset_lig_caret_list = 0;
+  uint16_t offset_mark_attach_class_def = 0;
+  if (!table.ReadU16(&offset_glyph_class_def) ||
+      !table.ReadU16(&offset_attach_list) ||
+      !table.ReadU16(&offset_lig_caret_list) ||
+      !table.ReadU16(&offset_mark_attach_class_def)) {
+    return OTS_FAILURE();
+  }
+  uint16_t offset_mark_glyph_sets_def = 0;
+  if (gdef->version_2) {
+    if (!table.ReadU16(&offset_mark_glyph_sets_def)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  const unsigned gdef_header_end = static_cast<unsigned>(8) +
+      gdef->version_2 ? static_cast<unsigned>(2) : static_cast<unsigned>(0);
+  if (gdef_header_end > std::numeric_limits<uint16_t>::max()) {
     return OTS_FAILURE();
   }
 
+  // Parse subtables
+  if (offset_glyph_class_def) {
+    if (offset_glyph_class_def >= length ||
+        offset_glyph_class_def < gdef_header_end) {
+      return OTS_FAILURE();
+    }
+    if (!ParseGlyphClassDefTable(file, data + offset_glyph_class_def,
+                                 length - offset_glyph_class_def,
+                                 num_glyphs)) {
+      DROP_THIS_TABLE;
+      return true;
+    }
+    gdef->has_glyph_class_def = true;
+  }
+
+  if (offset_attach_list) {
+    if (offset_attach_list >= length ||
+        offset_attach_list < gdef_header_end) {
+      return OTS_FAILURE();
+    }
+    if (!ParseAttachListTable(file, data + offset_attach_list,
+                              length - offset_attach_list,
+                              num_glyphs)) {
+      DROP_THIS_TABLE;
+      return true;
+    }
+  }
+
+  if (offset_lig_caret_list) {
+    if (offset_lig_caret_list >= length ||
+        offset_lig_caret_list < gdef_header_end) {
+      return OTS_FAILURE();
+    }
+    if (!ParseLigCaretListTable(file, data + offset_lig_caret_list,
+                              length - offset_lig_caret_list,
+                              num_glyphs)) {
+      DROP_THIS_TABLE;
+      return true;
+    }
+  }
+
+  if (offset_mark_attach_class_def) {
+    if (offset_mark_attach_class_def >= length ||
+        offset_mark_attach_class_def < gdef_header_end) {
+      return OTS_FAILURE();
+    }
+    if (!ParseMarkAttachClassDefTable(file,
+                                      data + offset_mark_attach_class_def,
+                                      length - offset_mark_attach_class_def,
+                                      num_glyphs)) {
+      DROP_THIS_TABLE;
+      return true;
+    }
+    gdef->has_mark_attachment_class_def = true;
+  }
+
+  if (offset_mark_glyph_sets_def) {
+    if (offset_mark_glyph_sets_def >= length ||
+        offset_mark_glyph_sets_def < gdef_header_end) {
+      return OTS_FAILURE();
+    }
+    if (!ParseMarkGlyphSetsDefTable(file,
+                                    data + offset_mark_glyph_sets_def,
+                                    length - offset_mark_glyph_sets_def,
+                                    num_glyphs)) {
+      DROP_THIS_TABLE;
+      return true;
+    }
+    gdef->has_mark_glyph_sets_def = true;
+  }
   gdef->data = data;
   gdef->length = length;
   return true;
 }
 
 bool ots_gdef_should_serialise(OpenTypeFile *file) {
-  return file->preserve_otl && file->gdef;
+  const bool needed_tables_dropped =
+      (file->gsub && file->gsub->data == NULL) ||
+      (file->gpos && file->gpos->data == NULL);
+  return file->gdef != NULL && file->gdef->data != NULL &&
+      !needed_tables_dropped;
 }
 
 bool ots_gdef_serialise(OTSStream *out, OpenTypeFile *file) {
-  const OpenTypeGDEF *gdef = file->gdef;
-
-  if (!out->Write(gdef->data, gdef->length)) {
+  if (!out->Write(file->gdef->data, file->gdef->length)) {
     return OTS_FAILURE();
   }
 
   return true;
 }
 
 void ots_gdef_free(OpenTypeFile *file) {
   delete file->gdef;
 }
 
 }  // namespace ots
+
--- a/gfx/ots/src/gdef.h
+++ b/gfx/ots/src/gdef.h
@@ -1,19 +1,36 @@
-// Copyright (c) 2010 Mozilla Foundation. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef OTS_GDEF_H_
 #define OTS_GDEF_H_
 
 #include "ots.h"
 
 namespace ots {
 
 struct OpenTypeGDEF {
+  OpenTypeGDEF()
+      : version_2(false),
+        has_glyph_class_def(false),
+        has_mark_attachment_class_def(false),
+        has_mark_glyph_sets_def(false),
+        num_mark_glyph_sets(0),
+        data(NULL),
+        length(0) {
+  }
+
+  bool version_2;
+  bool has_glyph_class_def;
+  bool has_mark_attachment_class_def;
+  bool has_mark_glyph_sets_def;
+  uint16_t num_mark_glyph_sets;
+
   const uint8_t *data;
-  uint32_t length;
+  size_t length;
 };
 
 }  // namespace ots
 
-#endif  // OTS_GDEF_H_
+#endif
+
--- a/gfx/ots/src/glyf.cc
+++ b/gfx/ots/src/glyf.cc
@@ -1,13 +1,12 @@
 // 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.
 
-#include <new>
 #include "glyf.h"
 
 #include <algorithm>
 #include <limits>
 
 #include "head.h"
 #include "loca.h"
 #include "maxp.h"
@@ -274,17 +273,17 @@ bool ots_glyf_parse(OpenTypeFile *file, 
     file->head->index_to_loc_format = 1;
   }
 
   file->loca->offsets = resulting_offsets;
   return true;
 }
 
 bool ots_glyf_should_serialise(OpenTypeFile *file) {
-  return file->glyf;
+  return file->glyf != NULL;
 }
 
 bool ots_glyf_serialise(OTSStream *out, OpenTypeFile *file) {
   const OpenTypeGLYF *glyf = file->glyf;
 
   for (unsigned i = 0; i < glyf->iov.size(); ++i) {
     if (!out->Write(glyf->iov[i].first, glyf->iov[i].second)) {
       return OTS_FAILURE();
--- a/gfx/ots/src/glyf.h
+++ b/gfx/ots/src/glyf.h
@@ -1,15 +1,16 @@
 // 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.
 
 #ifndef OTS_GLYF_H_
 #define OTS_GLYF_H_
 
+#include <new>
 #include <utility>  // std::pair
 #include <vector>
 
 #include "ots.h"
 
 namespace ots {
 
 struct OpenTypeGLYF {
--- a/gfx/ots/src/gpos.cc
+++ b/gfx/ots/src/gpos.cc
@@ -1,45 +1,810 @@
-// Copyright (c) 2010 Mozilla Foundation. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "gpos.h"
 
-// GPOS - Glyph Positioning Table
+#include <limits>
+#include <vector>
+
+#include "gdef.h"
+#include "gsub.h"
+#include "layout.h"
+#include "maxp.h"
+
+// GPOS - The Glyph Positioning Table
 // http://www.microsoft.com/typography/otspec/gpos.htm
 
+namespace {
+
+enum GPOS_TYPE {
+  GPOS_TYPE_SINGLE_ADJUSTMENT = 1,
+  GPOS_TYPE_PAIR_ADJUSTMENT = 2,
+  GPOS_TYPE_CURSIVE_ATTACHMENT = 3,
+  GPOS_TYPE_MARK_TO_BASE_ATTACHMENT = 4,
+  GPOS_TYPE_MARK_TO_LIGATURE_ATTACHMENT = 5,
+  GPOS_TYPE_MARK_TO_MARK_ATTACHMENT = 6,
+  GPOS_TYPE_CONTEXT_POSITIONING = 7,
+  GPOS_TYPE_CHAINED_CONTEXT_POSITIONING = 8,
+  GPOS_TYPE_EXTENSION_POSITIONING = 9,
+  GPOS_TYPE_RESERVED = 10
+};
+
+// The size of gpos header.
+const unsigned kGposHeaderSize = 10;
+// The maximum format number for anchor tables.
+const uint16_t kMaxAnchorFormat = 3;
+// The maximum number of class value.
+const uint16_t kMaxClassDefValue = 0xFFFF;
+
+// Lookup type parsers.
+bool ParseSingleAdjustment(const ots::OpenTypeFile *file,
+                           const uint8_t *data, const size_t length);
+bool ParsePairAdjustment(const ots::OpenTypeFile *file,
+                         const uint8_t *data, const size_t length);
+bool ParseCursiveAttachment(const ots::OpenTypeFile *file,
+                            const uint8_t *data, const size_t length);
+bool ParseMarkToBaseAttachment(const ots::OpenTypeFile *file,
+                               const uint8_t *data, const size_t length);
+bool ParseMarkToLigatureAttachment(const ots::OpenTypeFile *file,
+                                   const uint8_t *data, const size_t length);
+bool ParseMarkToMarkAttachment(const ots::OpenTypeFile *file,
+                               const uint8_t *data, const size_t length);
+bool ParseContextPositioning(const ots::OpenTypeFile *file,
+                             const uint8_t *data, const size_t length);
+bool ParseChainedContextPositioning(const ots::OpenTypeFile *file,
+                                    const uint8_t *data, const size_t length);
+bool ParseExtensionPositioning(const ots::OpenTypeFile *file,
+                               const uint8_t *data, const size_t length);
+
+const ots::LookupSubtableParser::TypeParser kGposTypeParsers[] = {
+  {GPOS_TYPE_SINGLE_ADJUSTMENT, ParseSingleAdjustment},
+  {GPOS_TYPE_PAIR_ADJUSTMENT, ParsePairAdjustment},
+  {GPOS_TYPE_CURSIVE_ATTACHMENT, ParseCursiveAttachment},
+  {GPOS_TYPE_MARK_TO_BASE_ATTACHMENT, ParseMarkToBaseAttachment},
+  {GPOS_TYPE_MARK_TO_LIGATURE_ATTACHMENT, ParseMarkToLigatureAttachment},
+  {GPOS_TYPE_MARK_TO_MARK_ATTACHMENT, ParseMarkToMarkAttachment},
+  {GPOS_TYPE_CONTEXT_POSITIONING, ParseContextPositioning},
+  {GPOS_TYPE_CHAINED_CONTEXT_POSITIONING, ParseChainedContextPositioning},
+  {GPOS_TYPE_EXTENSION_POSITIONING, ParseExtensionPositioning}
+};
+
+const ots::LookupSubtableParser kGposLookupSubtableParser = {
+  GPOS_TYPE_RESERVED, GPOS_TYPE_EXTENSION_POSITIONING, kGposTypeParsers
+};
+
+// Shared Tables: ValueRecord, Anchor Table, and MarkArray
+
+bool ParseValueRecord(ots::Buffer* subtable, const uint8_t *data,
+                      const size_t length, const uint16_t value_format) {
+  // Check existence of adjustment fields.
+  for (unsigned i = 0; i < 4; ++i) {
+    if ((value_format >> i) & 0x1) {
+      // Just read the field since these fileds could take an arbitrary values.
+      if (!subtable->Skip(2)) {
+        return OTS_FAILURE();
+      }
+    }
+  }
+
+  // Check existence of offsets to device table.
+  for (unsigned i = 0; i < 4; ++i) {
+    if ((value_format >> (i + 4)) & 0x1) {
+      uint16_t offset = 0;
+      if (!subtable->ReadU16(&offset)) {
+        return OTS_FAILURE();
+      }
+      if (offset) {
+        // TODO(bashi): Is it possible that device tables locate before
+        // this record? No fonts contain such offset AKAIF.
+        if (offset >= length) {
+          return OTS_FAILURE();
+        }
+        if (!ots::ParseDeviceTable(data + offset, length - offset)) {
+          return OTS_FAILURE();
+        }
+      }
+    }
+  }
+  return true;
+}
+
+bool ParseAnchorTable(const uint8_t *data, const size_t length) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  // Read format and skip 2 2-byte fields that could be arbitrary values.
+  if (!subtable.ReadU16(&format) ||
+      !subtable.Skip(4)) {
+    return OTS_FAILURE();
+  }
+
+  if (format == 0 || format > kMaxAnchorFormat) {
+    return OTS_FAILURE();
+  }
+
+  // Format 2 and 3 has additional fields.
+  if (format == 2) {
+    // Format 2 provides an index to a glyph contour point, which will take
+    // arbitrary value.
+    uint16_t anchor_point = 0;
+    if (!subtable.ReadU16(&anchor_point)) {
+      return OTS_FAILURE();
+    }
+  } else if (format == 3) {
+    uint16_t offset_x_device = 0;
+    uint16_t offset_y_device = 0;
+    if (!subtable.ReadU16(&offset_x_device) ||
+        !subtable.ReadU16(&offset_y_device)) {
+      return OTS_FAILURE();
+    }
+    const unsigned format_end = static_cast<unsigned>(10);
+    if (offset_x_device) {
+      if (offset_x_device < format_end || offset_x_device >= length) {
+        return OTS_FAILURE();
+      }
+      if (!ots::ParseDeviceTable(data + offset_x_device,
+                                 length - offset_x_device)) {
+        return OTS_FAILURE();
+      }
+    }
+    if (offset_y_device) {
+      if (offset_y_device < format_end || offset_y_device >= length) {
+        return OTS_FAILURE();
+      }
+      if (!ots::ParseDeviceTable(data + offset_y_device,
+                                 length - offset_y_device)) {
+        return OTS_FAILURE();
+      }
+    }
+  }
+  return true;
+}
+
+bool ParseMarkArrayTable(const uint8_t *data, const size_t length,
+                         const uint16_t class_count) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t mark_count = 0;
+  if (!subtable.ReadU16(&mark_count)) {
+    return OTS_FAILURE();
+  }
+
+  // MarkRecord consists of 4-bytes.
+  const unsigned mark_records_end = static_cast<unsigned>(2) + mark_count * 4;
+  if (mark_records_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < mark_count; ++i) {
+    uint16_t class_value = 0;
+    uint16_t offset_mark_anchor = 0;
+    if (!subtable.ReadU16(&class_value) ||
+        !subtable.ReadU16(&offset_mark_anchor)) {
+      return OTS_FAILURE();
+    }
+    // |class_value| may take arbitrary values including 0 here so we don't
+    // check the value.
+    if (offset_mark_anchor < mark_records_end ||
+        offset_mark_anchor >= length) {
+      return OTS_FAILURE();
+    }
+    if (!ParseAnchorTable(data + offset_mark_anchor,
+                          length - offset_mark_anchor)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  return true;
+}
+
+// Lookup Type 1:
+// Single Adjustment Positioning Subtable
+bool ParseSingleAdjustment(const ots::OpenTypeFile *file, const uint8_t *data,
+                           const size_t length) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  uint16_t offset_coverage = 0;
+  uint16_t value_format = 0;
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&offset_coverage) ||
+      !subtable.ReadU16(&value_format)) {
+    return OTS_FAILURE();
+  }
+
+  if (format == 1) {
+    // Format 1 exactly one value record.
+    if (!ParseValueRecord(&subtable, data, length, value_format)) {
+      return OTS_FAILURE();
+    }
+  } else if (format == 2) {
+    uint16_t value_count = 0;
+    if (!subtable.ReadU16(&value_count)) {
+      return OTS_FAILURE();
+    }
+    for (unsigned i = 0; i < value_count; ++i) {
+      if (!ParseValueRecord(&subtable, data, length, value_format)) {
+        return OTS_FAILURE();
+      }
+    }
+  } else {
+    return OTS_FAILURE();
+  }
+
+  if (offset_coverage < subtable.offset() || offset_coverage >= length) {
+    return OTS_FAILURE();
+  }
+
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage,
+                               file->maxp->num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+bool ParsePairSetTable(const uint8_t *data, const size_t length,
+                       const uint16_t value_format1,
+                       const uint16_t value_format2,
+                       const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t value_count = 0;
+  if (!subtable.ReadU16(&value_count)) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < value_count; ++i) {
+    // Check pair value record.
+    uint16_t glyph_id = 0;
+    if (!subtable.ReadU16(&glyph_id)) {
+      return OTS_FAILURE();
+    }
+    if (glyph_id >= num_glyphs) {
+      return OTS_FAILURE();
+    }
+    if (!ParseValueRecord(&subtable, data, length, value_format1)) {
+      return OTS_FAILURE();
+    }
+    if (!ParseValueRecord(&subtable, data, length, value_format2)) {
+      return OTS_FAILURE();
+    }
+  }
+  return true;
+}
+
+bool ParsePairPosFormat1(const uint8_t *data, const size_t length,
+                         const uint16_t value_format1,
+                         const uint16_t value_format2,
+                         const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  // Skip 8 bytes that are already read before.
+  if (!subtable.Skip(8)) {
+    return OTS_FAILURE();
+  }
+
+  uint16_t pair_set_count = 0;
+  if (!subtable.ReadU16(&pair_set_count)) {
+    return OTS_FAILURE();
+  }
+
+  const unsigned pair_pos_end = static_cast<unsigned>(10) +
+      pair_set_count * 2;
+  if (pair_pos_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < pair_set_count; ++i) {
+    uint16_t pair_set_offset = 0;
+    if (!subtable.ReadU16(&pair_set_offset)) {
+      return OTS_FAILURE();
+    }
+    if (pair_set_offset < pair_pos_end || pair_set_offset >= length) {
+      return OTS_FAILURE();
+    }
+    // Check pair set tables
+    if (!ParsePairSetTable(data + pair_set_offset, length - pair_set_offset,
+                           value_format1, value_format2,
+                           num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  return true;
+}
+
+bool ParsePairPosFormat2(const uint8_t *data, const size_t length,
+                         const uint16_t value_format1,
+                         const uint16_t value_format2,
+                         const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  // Skip 8 bytes that are already read before.
+  if (!subtable.Skip(8)) {
+    return OTS_FAILURE();
+  }
+
+  uint16_t offset_class_def1 = 0;
+  uint16_t offset_class_def2 = 0;
+  uint16_t class1_count = 0;
+  uint16_t class2_count = 0;
+  if (!subtable.ReadU16(&offset_class_def1) ||
+      !subtable.ReadU16(&offset_class_def2) ||
+      !subtable.ReadU16(&class1_count) ||
+      !subtable.ReadU16(&class2_count)) {
+    return OTS_FAILURE();
+  }
+
+  // Check class 1 records.
+  for (unsigned i = 0; i < class1_count; ++i) {
+    // Check class 2 records.
+    for (unsigned j = 0; j < class2_count; ++j) {
+      if (value_format1 && !ParseValueRecord(&subtable, data, length,
+                                             value_format1)) {
+        return OTS_FAILURE();
+      }
+      if (value_format2 && !ParseValueRecord(&subtable, data, length,
+                                             value_format2)) {
+        return OTS_FAILURE();
+      }
+    }
+  }
+
+  // Check class definition tables.
+  if (offset_class_def1 < subtable.offset() || offset_class_def1 >= length ||
+      offset_class_def2 < subtable.offset() || offset_class_def2 >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseClassDefTable(data + offset_class_def1,
+                               length - offset_class_def1,
+                               num_glyphs, kMaxClassDefValue)) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseClassDefTable(data + offset_class_def2,
+                               length - offset_class_def2,
+                               num_glyphs, kMaxClassDefValue)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+// Lookup Type 2:
+// Pair Adjustment Positioning Subtable
+bool ParsePairAdjustment(const ots::OpenTypeFile *file, const uint8_t *data,
+                         const size_t length) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  uint16_t offset_coverage = 0;
+  uint16_t value_format1 = 0;
+  uint16_t value_format2 = 0;
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&offset_coverage) ||
+      !subtable.ReadU16(&value_format1) ||
+      !subtable.ReadU16(&value_format2)) {
+    return OTS_FAILURE();
+  }
+
+  if (format == 1) {
+    if (!ParsePairPosFormat1(data, length, value_format1, value_format2,
+                             file->maxp->num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  } else if (format == 2) {
+    if (!ParsePairPosFormat2(data, length, value_format1, value_format2,
+                             file->maxp->num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  } else {
+    return OTS_FAILURE();
+  }
+
+  if (offset_coverage < subtable.offset() || offset_coverage >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage,
+                               file->maxp->num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+// Lookup Type 3
+// Cursive Attachment Positioning Subtable
+bool ParseCursiveAttachment(const ots::OpenTypeFile *file, const uint8_t *data,
+                            const size_t length) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  uint16_t offset_coverage = 0;
+  uint16_t entry_exit_count = 0;
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&offset_coverage) ||
+      !subtable.ReadU16(&entry_exit_count)) {
+    return OTS_FAILURE();
+  }
+
+  if (format != 1) {
+    return OTS_FAILURE();
+  }
+
+  // Check entry exit records.
+  const unsigned entry_exit_records_end = static_cast<unsigned>(6) +
+      entry_exit_count * 2;
+  if (entry_exit_records_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < entry_exit_count; ++i) {
+    uint16_t offset_entry_anchor = 0;
+    uint16_t offset_exit_anchor = 0;
+    if (!subtable.ReadU16(&offset_entry_anchor) ||
+        !subtable.ReadU16(&offset_exit_anchor)) {
+      return OTS_FAILURE();
+    }
+    // These offsets could be NULL.
+    if (offset_entry_anchor) {
+      if (offset_entry_anchor < entry_exit_records_end ||
+          offset_entry_anchor >= length) {
+        return OTS_FAILURE();
+      }
+      if (!ParseAnchorTable(data + offset_entry_anchor,
+                            length - offset_entry_anchor)) {
+        return OTS_FAILURE();
+      }
+    }
+    if (offset_exit_anchor) {
+      if (offset_exit_anchor < entry_exit_records_end ||
+         offset_exit_anchor >= length) {
+        return OTS_FAILURE();
+      }
+      if (!ParseAnchorTable(data + offset_exit_anchor,
+                            length - offset_exit_anchor)) {
+        return OTS_FAILURE();
+      }
+    }
+  }
+
+  if (offset_coverage < subtable.offset() || offset_coverage >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage,
+                               file->maxp->num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+bool ParseAnchorArrayTable(const uint8_t *data, const size_t length,
+                           const uint16_t class_count) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t record_count = 0;
+  if (!subtable.ReadU16(&record_count)) {
+    return OTS_FAILURE();
+  }
+
+  const unsigned anchor_array_end = static_cast<unsigned>(2) +
+      record_count * class_count * 2;
+  if (anchor_array_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < record_count; ++i) {
+    for (unsigned j = 0; j < class_count; ++j) {
+      uint16_t offset_record = 0;
+      if (!subtable.ReadU16(&offset_record)) {
+        return OTS_FAILURE();
+      }
+      // |offset_record| could be NULL.
+      if (offset_record) {
+        if (offset_record < anchor_array_end || offset_record >= length) {
+          return OTS_FAILURE();
+        }
+        if (!ParseAnchorTable(data + offset_record,
+                              length - offset_record)) {
+          return OTS_FAILURE();
+        }
+      }
+    }
+  }
+  return true;
+}
+
+bool ParseLigatureArrayTable(const uint8_t *data, const size_t length,
+                             const uint16_t class_count) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t ligature_count = 0;
+  if (!subtable.ReadU16(&ligature_count)) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < ligature_count; ++i) {
+    uint16_t offset_ligature_attach = 0;
+    if (!subtable.ReadU16(&offset_ligature_attach)) {
+      return OTS_FAILURE();
+    }
+    if (offset_ligature_attach < 2 || offset_ligature_attach >= length) {
+      return OTS_FAILURE();
+    }
+    if (!ParseAnchorArrayTable(data + offset_ligature_attach,
+                               length - offset_ligature_attach, class_count)) {
+      return OTS_FAILURE();
+    }
+  }
+  return true;
+}
+
+// Common parser for Lookup Type 4, 5 and 6.
+bool ParseMarkToAttachmentSubtables(const ots::OpenTypeFile *file,
+                                    const uint8_t *data, const size_t length,
+                                    const GPOS_TYPE type) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  uint16_t offset_coverage1 = 0;
+  uint16_t offset_coverage2 = 0;
+  uint16_t class_count = 0;
+  uint16_t offset_mark_array = 0;
+  uint16_t offset_type_specific_array = 0;
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&offset_coverage1) ||
+      !subtable.ReadU16(&offset_coverage2) ||
+      !subtable.ReadU16(&class_count) ||
+      !subtable.ReadU16(&offset_mark_array) ||
+      !subtable.ReadU16(&offset_type_specific_array)) {
+    return OTS_FAILURE();
+  }
+
+  if (format != 1) {
+    return OTS_FAILURE();
+  }
+
+  const unsigned header_end = static_cast<unsigned>(subtable.offset());
+  if (header_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  if (offset_coverage1 < header_end || offset_coverage1 >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseCoverageTable(data + offset_coverage1,
+                               length - offset_coverage1,
+                               file->maxp->num_glyphs)) {
+    return OTS_FAILURE();
+  }
+  if (offset_coverage2 < header_end || offset_coverage2 >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseCoverageTable(data + offset_coverage2,
+                               length - offset_coverage2,
+                               file->maxp->num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  if (offset_mark_array < header_end || offset_mark_array >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ParseMarkArrayTable(data + offset_mark_array,
+                           length - offset_mark_array, class_count)) {
+    return OTS_FAILURE();
+  }
+
+  if (offset_type_specific_array < header_end ||
+      offset_type_specific_array >= length) {
+    return OTS_FAILURE();
+  }
+  if (type == GPOS_TYPE_MARK_TO_BASE_ATTACHMENT ||
+      type == GPOS_TYPE_MARK_TO_MARK_ATTACHMENT) {
+    if (!ParseAnchorArrayTable(data + offset_type_specific_array,
+                               length - offset_type_specific_array,
+                               class_count)) {
+      return OTS_FAILURE();
+    }
+  } else if (type == GPOS_TYPE_MARK_TO_LIGATURE_ATTACHMENT) {
+    if (!ParseLigatureArrayTable(data + offset_type_specific_array,
+                                 length - offset_type_specific_array,
+                                 class_count)) {
+      return OTS_FAILURE();
+    }
+  } else {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+// Lookup Type 4:
+// MarkToBase Attachment Positioning Subtable
+bool ParseMarkToBaseAttachment(const ots::OpenTypeFile *file,
+                               const uint8_t *data, const size_t length) {
+  return ParseMarkToAttachmentSubtables(file, data, length,
+                                        GPOS_TYPE_MARK_TO_BASE_ATTACHMENT);
+}
+
+// Lookup Type 5:
+// MarkToLigature Attachment Positioning Subtable
+bool ParseMarkToLigatureAttachment(const ots::OpenTypeFile *file,
+                                   const uint8_t *data, const size_t length) {
+  return ParseMarkToAttachmentSubtables(file, data, length,
+                                        GPOS_TYPE_MARK_TO_LIGATURE_ATTACHMENT);
+}
+
+// Lookup Type 6:
+// MarkToMark Attachment Positioning Subtable
+bool ParseMarkToMarkAttachment(const ots::OpenTypeFile *file,
+                               const uint8_t *data, const size_t length) {
+  return ParseMarkToAttachmentSubtables(file, data, length,
+                                        GPOS_TYPE_MARK_TO_MARK_ATTACHMENT);
+}
+
+// Lookup Type 7:
+// Contextual Positioning Subtables
+bool ParseContextPositioning(const ots::OpenTypeFile *file,
+                             const uint8_t *data, const size_t length) {
+  return ots::ParseContextSubtable(data, length, file->maxp->num_glyphs,
+                                   file->gpos->num_lookups);
+}
+
+// Lookup Type 8:
+// Chaining Contexual Positioning Subtable
+bool ParseChainedContextPositioning(const ots::OpenTypeFile *file,
+                                    const uint8_t *data, const size_t length) {
+  return ots::ParseChainingContextSubtable(data, length,
+                                           file->maxp->num_glyphs,
+                                           file->gpos->num_lookups);
+}
+
+// Lookup Type 9:
+// Extension Positioning
+bool ParseExtensionPositioning(const ots::OpenTypeFile *file,
+                               const uint8_t *data, const size_t length) {
+  return ots::ParseExtensionSubtable(file, data, length,
+                                     &kGposLookupSubtableParser);
+}
+
+}  // namespace
+
+#define DROP_THIS_TABLE \
+  do { file->gpos->data = 0; file->gpos->length = 0; } while (0)
+
 namespace ots {
 
+// As far as I checked, following fonts contain invalid GPOS table and
+// OTS will drop their GPOS table.
+//
+// # invalid delta format in device table
+// samanata.ttf
+//
+// # bad size range in device table
+// Sarai_07.ttf
+//
+// # bad offset to PairSetTable
+// chandas1-2.ttf
+//
+// # bad offset to FeatureTable
+// glrso12.ttf
+// gllr12.ttf
+// glbo12.ttf
+// glb12.ttf
+// glro12.ttf
+// glbso12.ttf
+// glrc12.ttf
+// glrsc12.ttf
+// glbs12.ttf
+// glrs12.ttf
+// glr12.ttf
+//
+// # ScriptRecords aren't sorted by tag
+// Garogier_unhinted.otf
+//
+// # bad start coverage index in CoverageFormat2
+// AndBasR.ttf
+// CharisSILB.ttf
+// CharisSILBI.ttf
+// CharisSILI.ttf
+// CharisSILR.ttf
+// DoulosSILR.ttf
+// GenBasBI.ttf
+// GenBasI.ttf
+// GenBkBasI.ttf
+// GenBkBasB.ttf
+// GenBkBasR.ttf
+// Padauk-Bold.ttf
+// Padauk.ttf
+//
+// # Contour point indexes aren't sorted
+// Arial Unicode.ttf
+
 bool ots_gpos_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  // Parsing GPOS table requires num_glyphs which is contained in maxp table.
+  if (!file->maxp) {
+    return OTS_FAILURE();
+  }
+
   Buffer table(data, length);
 
   OpenTypeGPOS *gpos = new OpenTypeGPOS;
   file->gpos = gpos;
 
-  if (!table.Skip(length)) {
+  uint32_t version = 0;
+  uint16_t offset_script_list = 0;
+  uint16_t offset_feature_list = 0;
+  uint16_t offset_lookup_list = 0;
+  if (!table.ReadU32(&version) ||
+      !table.ReadU16(&offset_script_list) ||
+      !table.ReadU16(&offset_feature_list) ||
+      !table.ReadU16(&offset_lookup_list)) {
     return OTS_FAILURE();
   }
 
+  if (version != 0x00010000) {
+    OTS_WARNING("bad GPOS version");
+    DROP_THIS_TABLE;
+    return true;
+  }
+  if ((offset_script_list < kGposHeaderSize ||
+       offset_script_list >= length) ||
+      (offset_feature_list < kGposHeaderSize ||
+       offset_feature_list >= length) ||
+      (offset_lookup_list < kGposHeaderSize ||
+       offset_lookup_list >= length)) {
+    OTS_WARNING("bad offset in GPOS header");
+    DROP_THIS_TABLE;
+    return true;
+  }
+
+  if (!ParseLookupListTable(file, data + offset_lookup_list,
+                            length - offset_lookup_list,
+                            &kGposLookupSubtableParser,
+                            &gpos->num_lookups)) {
+    OTS_WARNING("faild to parse lookup list table");
+    DROP_THIS_TABLE;
+    return true;
+  }
+
+  uint16_t num_features = 0;
+  if (!ParseFeatureListTable(data + offset_feature_list,
+                             length - offset_feature_list, gpos->num_lookups,
+                             &num_features)) {
+    OTS_WARNING("faild to parse feature list table");
+    DROP_THIS_TABLE;
+    return true;
+  }
+
+  if (!ParseScriptListTable(data + offset_script_list,
+                            length - offset_script_list, num_features)) {
+    OTS_WARNING("faild to parse script list table");
+    DROP_THIS_TABLE;
+    return true;
+  }
+
   gpos->data = data;
   gpos->length = length;
   return true;
 }
 
 bool ots_gpos_should_serialise(OpenTypeFile *file) {
-  return file->preserve_otl && file->gpos;
+  const bool needed_tables_dropped =
+      (file->gdef && file->gdef->data == NULL) ||
+      (file->gsub && file->gsub->data == NULL);
+  return file->gpos != NULL && file->gpos->data != NULL &&
+      !needed_tables_dropped;
 }
 
 bool ots_gpos_serialise(OTSStream *out, OpenTypeFile *file) {
-  const OpenTypeGPOS *gpos = file->gpos;
-
-  if (!out->Write(gpos->data, gpos->length)) {
+  if (!out->Write(file->gpos->data, file->gpos->length)) {
     return OTS_FAILURE();
   }
 
   return true;
 }
 
 void ots_gpos_free(OpenTypeFile *file) {
   delete file->gpos;
 }
 
 }  // namespace ots
+
--- a/gfx/ots/src/gpos.h
+++ b/gfx/ots/src/gpos.h
@@ -1,19 +1,29 @@
-// Copyright (c) 2010 Mozilla Foundation. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef OTS_GPOS_H_
 #define OTS_GPOS_H_
 
 #include "ots.h"
 
 namespace ots {
 
 struct OpenTypeGPOS {
+  OpenTypeGPOS()
+      : num_lookups(0),
+        data(NULL),
+        length(0) {
+  }
+
+  // Number of lookups in GPOS table
+  uint16_t num_lookups;
+
   const uint8_t *data;
-  uint32_t length;
+  size_t length;
 };
 
 }  // namespace ots
 
-#endif  // OTS_GPOS_H_
+#endif
+
--- a/gfx/ots/src/gsub.cc
+++ b/gfx/ots/src/gsub.cc
@@ -1,45 +1,691 @@
-// Copyright (c) 2010 Mozilla Foundation. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "gsub.h"
 
-// GSUB - Glyph Substitution Table
+#include <limits>
+#include <vector>
+
+#include "gdef.h"
+#include "gpos.h"
+#include "layout.h"
+#include "maxp.h"
+
+// GSUB - The Glyph Substitution Table
 // http://www.microsoft.com/typography/otspec/gsub.htm
 
+namespace {
+
+// The GSUB header size
+const size_t kGsubHeaderSize = 8;
+
+enum GSUB_TYPE {
+  GSUB_TYPE_SINGLE = 1,
+  GSUB_TYPE_MULTIPLE = 2,
+  GSUB_TYPE_ALTERNATE = 3,
+  GSUB_TYPE_LIGATURE = 4,
+  GSUB_TYPE_CONTEXT = 5,
+  GSUB_TYPE_CHANGING_CONTEXT = 6,
+  GSUB_TYPE_EXTENSION_SUBSTITUTION = 7,
+  GSUB_TYPE_REVERSE_CHAINING_CONTEXT_SINGLE = 8,
+  GSUB_TYPE_RESERVED = 9
+};
+
+// Lookup type parsers.
+bool ParseSingleSubstitution(const ots::OpenTypeFile *file,
+                             const uint8_t *data, const size_t length);
+bool ParseMutipleSubstitution(const ots::OpenTypeFile *file,
+                              const uint8_t *data, const size_t length);
+bool ParseAlternateSubstitution(const ots::OpenTypeFile *file,
+                                const uint8_t *data, const size_t length);
+bool ParseLigatureSubstitution(const ots::OpenTypeFile *file,
+      const uint8_t *data, const size_t length);
+bool ParseContextSubstitution(const ots::OpenTypeFile *file,
+                              const uint8_t *data, const size_t length);
+bool ParseChainingContextSubstitution(const ots::OpenTypeFile *file,
+                                      const uint8_t *data,
+                                      const size_t length);
+bool ParseExtensionSubstitution(const ots::OpenTypeFile *file,
+                                const uint8_t *data, const size_t length);
+bool ParseReverseChainingContextSingleSubstitution(
+    const ots::OpenTypeFile *file, const uint8_t *data, const size_t length);
+
+const ots::LookupSubtableParser::TypeParser kGsubTypeParsers[] = {
+  {GSUB_TYPE_SINGLE, ParseSingleSubstitution},
+  {GSUB_TYPE_MULTIPLE, ParseMutipleSubstitution},
+  {GSUB_TYPE_ALTERNATE, ParseAlternateSubstitution},
+  {GSUB_TYPE_LIGATURE, ParseLigatureSubstitution},
+  {GSUB_TYPE_CONTEXT, ParseContextSubstitution},
+  {GSUB_TYPE_CHANGING_CONTEXT, ParseChainingContextSubstitution},
+  {GSUB_TYPE_EXTENSION_SUBSTITUTION, ParseExtensionSubstitution},
+  {GSUB_TYPE_REVERSE_CHAINING_CONTEXT_SINGLE,
+    ParseReverseChainingContextSingleSubstitution}
+};
+
+const ots::LookupSubtableParser kGsubLookupSubtableParser = {
+  GSUB_TYPE_RESERVED, GSUB_TYPE_EXTENSION_SUBSTITUTION, kGsubTypeParsers
+};
+
+// Lookup Type 1:
+// Single Substitution Subtable
+bool ParseSingleSubstitution(const ots::OpenTypeFile *file,
+                             const uint8_t *data, const size_t length) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  uint16_t offset_coverage = 0;
+
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&offset_coverage)) {
+    return OTS_FAILURE();
+  }
+
+  const uint16_t num_glyphs = file->maxp->num_glyphs;
+  if (format == 1) {
+    // Parse SingleSubstFormat1
+    int16_t delta_glyph_id = 0;
+    if (!subtable.ReadS16(&delta_glyph_id)) {
+      return OTS_FAILURE();
+    }
+    if (std::abs(delta_glyph_id) >= num_glyphs) {
+      return OTS_FAILURE();
+    }
+  } else if (format == 2) {
+    // Parse SingleSubstFormat2
+    uint16_t glyph_count = 0;
+    if (!subtable.ReadU16(&glyph_count)) {
+      return OTS_FAILURE();
+    }
+    if (glyph_count > num_glyphs) {
+      return OTS_FAILURE();
+    }
+    for (unsigned i = 0; i < glyph_count; ++i) {
+      uint16_t substitute = 0;
+      if (!subtable.ReadU16(&substitute)) {
+        return OTS_FAILURE();
+      }
+      if (substitute >= num_glyphs) {
+        OTS_WARNING("too large substitute: %u", substitute);
+        return OTS_FAILURE();
+      }
+    }
+  } else {
+    return OTS_FAILURE();
+  }
+
+  if (offset_coverage < subtable.offset() || offset_coverage >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage, num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+bool ParseSequenceTable(const uint8_t *data, const size_t length,
+                        const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t glyph_count = 0;
+  if (!subtable.ReadU16(&glyph_count)) {
+    return OTS_FAILURE();
+  }
+  if (glyph_count > num_glyphs) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < glyph_count; ++i) {
+    uint16_t substitute = 0;
+    if (!subtable.ReadU16(&substitute)) {
+      return OTS_FAILURE();
+    }
+    if (substitute >= num_glyphs) {
+      return OTS_FAILURE();
+    }
+  }
+
+  return true;
+}
+
+// Lookup Type 2:
+// Multiple Substitution Subtable
+bool ParseMutipleSubstitution(const ots::OpenTypeFile *file,
+                              const uint8_t *data, const size_t length) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  uint16_t offset_coverage = 0;
+  uint16_t sequence_count = 0;
+
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&offset_coverage) ||
+      !subtable.ReadU16(&sequence_count)) {
+    return OTS_FAILURE();
+  }
+
+  if (format != 1) {
+    return OTS_FAILURE();
+  }
+
+  const uint16_t num_glyphs = file->maxp->num_glyphs;
+  const unsigned sequence_end = static_cast<unsigned>(6) +
+      sequence_count * 2;
+  if (sequence_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < sequence_count; ++i) {
+    uint16_t offset_sequence = 0;
+    if (!subtable.ReadU16(&offset_sequence)) {
+      return OTS_FAILURE();
+    }
+    if (offset_sequence < sequence_end || offset_sequence >= length) {
+      return OTS_FAILURE();
+    }
+    if (!ParseSequenceTable(data + offset_sequence, length - offset_sequence,
+                            num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  if (offset_coverage < sequence_end || offset_coverage >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage, num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+bool ParseAlternateSetTable(const uint8_t *data, const size_t length,
+                            const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t glyph_count = 0;
+  if (!subtable.ReadU16(&glyph_count)) {
+    return OTS_FAILURE();
+  }
+  if (glyph_count > num_glyphs) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < glyph_count; ++i) {
+    uint16_t alternate = 0;
+    if (!subtable.ReadU16(&alternate)) {
+      return OTS_FAILURE();
+    }
+    if (alternate >= num_glyphs) {
+      OTS_WARNING("too arge alternate: %u", alternate);
+      return OTS_FAILURE();
+    }
+  }
+  return true;
+}
+
+// Lookup Type 3:
+// Alternate Substitution Subtable
+bool ParseAlternateSubstitution(const ots::OpenTypeFile *file,
+                                const uint8_t *data, const size_t length) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  uint16_t offset_coverage = 0;
+  uint16_t alternate_set_count = 0;
+
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&offset_coverage) ||
+      !subtable.ReadU16(&alternate_set_count)) {
+    return OTS_FAILURE();
+  }
+
+  if (format != 1) {
+    return OTS_FAILURE();
+  }
+
+  const uint16_t num_glyphs = file->maxp->num_glyphs;
+  const unsigned alternate_set_end = static_cast<unsigned>(6) +
+      alternate_set_count * 2;
+  if (alternate_set_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < alternate_set_count; ++i) {
+    uint16_t offset_alternate_set = 0;
+    if (!subtable.ReadU16(&offset_alternate_set)) {
+      return OTS_FAILURE();
+    }
+    if (offset_alternate_set < alternate_set_end ||
+        offset_alternate_set >= length) {
+      return OTS_FAILURE();
+    }
+    if (!ParseAlternateSetTable(data + offset_alternate_set,
+                                length - offset_alternate_set,
+                                num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  if (offset_coverage < alternate_set_end || offset_coverage >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage, num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+bool ParseLigatureTable(const uint8_t *data, const size_t length,
+                        const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t lig_glyph = 0;
+  uint16_t comp_count = 0;
+
+  if (!subtable.ReadU16(&lig_glyph) ||
+      !subtable.ReadU16(&comp_count)) {
+    return OTS_FAILURE();
+  }
+
+  if (lig_glyph >= num_glyphs) {
+    OTS_WARNING("too large lig_glyph: %u", lig_glyph);
+    return OTS_FAILURE();
+  }
+  if (comp_count == 0 || comp_count > num_glyphs) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < comp_count - static_cast<unsigned>(1); ++i) {
+    uint16_t component = 0;
+    if (!subtable.ReadU16(&component)) {
+      return OTS_FAILURE();
+    }
+    if (component >= num_glyphs) {
+      return OTS_FAILURE();
+    }
+  }
+
+  return true;
+}
+
+bool ParseLigatureSetTable(const uint8_t *data, const size_t length,
+                           const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t ligature_count = 0;
+
+  if (!subtable.ReadU16(&ligature_count)) {
+    return OTS_FAILURE();
+  }
+
+  const unsigned ligature_end = static_cast<unsigned>(2) + ligature_count * 2;
+  if (ligature_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < ligature_count; ++i) {
+    uint16_t offset_ligature = 0;
+    if (!subtable.ReadU16(&offset_ligature)) {
+      return OTS_FAILURE();
+    }
+    if (offset_ligature < ligature_end || offset_ligature >= length) {
+      return OTS_FAILURE();
+    }
+    if (!ParseLigatureTable(data + offset_ligature, length - offset_ligature,
+                            num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  return true;
+}
+
+// Lookup Type 4:
+// Ligature Substitution Subtable
+bool ParseLigatureSubstitution(const ots::OpenTypeFile *file,
+                               const uint8_t *data, const size_t length) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  uint16_t offset_coverage = 0;
+  uint16_t lig_set_count = 0;
+
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&offset_coverage) ||
+      !subtable.ReadU16(&lig_set_count)) {
+    return OTS_FAILURE();
+  }
+
+  if (format != 1) {
+    return OTS_FAILURE();
+  }
+
+  const uint16_t num_glyphs = file->maxp->num_glyphs;
+  const unsigned ligature_set_end = static_cast<unsigned>(6) +
+      lig_set_count * 2;
+  if (ligature_set_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < lig_set_count; ++i) {
+    uint16_t offset_ligature_set = 0;
+    if (!subtable.ReadU16(&offset_ligature_set)) {
+      return OTS_FAILURE();
+    }
+    if (offset_ligature_set < ligature_set_end ||
+        offset_ligature_set >= length) {
+      return OTS_FAILURE();
+    }
+    if (!ParseLigatureSetTable(data + offset_ligature_set,
+                               length - offset_ligature_set, num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  if (offset_coverage < ligature_set_end || offset_coverage >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage, num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  return true;
+}
+
+bool ParseSubstLookupRecord(ots::Buffer *subtable, const uint16_t num_glyphs,
+                            const uint16_t num_lookups) {
+  uint16_t sequence_index = 0;
+  uint16_t lookup_list_index = 0;
+
+  if (!subtable->ReadU16(&sequence_index) ||
+      !subtable->ReadU16(&lookup_list_index)) {
+    return OTS_FAILURE();
+  }
+  if (sequence_index >= num_glyphs) {
+    return OTS_FAILURE();
+  }
+  if (lookup_list_index >= num_lookups) {
+    return OTS_FAILURE();
+  }
+  return true;
+}
+
+// Lookup Type 5:
+// Contextual Substitution Subtable
+bool ParseContextSubstitution(const ots::OpenTypeFile *file,
+                              const uint8_t *data, const size_t length) {
+  return ots::ParseContextSubtable(data, length, file->maxp->num_glyphs,
+                                   file->gsub->num_lookups);
+}
+
+// Lookup Type 6:
+// Chaining Contextual Substitution Subtable
+bool ParseChainingContextSubstitution(const ots::OpenTypeFile *file,
+                                      const uint8_t *data,
+                                      const size_t length) {
+  return ots::ParseChainingContextSubtable(data, length,
+                                           file->maxp->num_glyphs,
+                                           file->gsub->num_lookups);
+}
+
+// Lookup Type 7:
+// Extension Substition
+bool ParseExtensionSubstitution(const ots::OpenTypeFile *file,
+                                const uint8_t *data, const size_t length) {
+  return ots::ParseExtensionSubtable(file, data, length,
+                                     &kGsubLookupSubtableParser);
+}
+
+// Lookup Type 8:
+// Reverse Chaining Contexual Single Substitution Subtable
+bool ParseReverseChainingContextSingleSubstitution(
+    const ots::OpenTypeFile *file, const uint8_t *data, const size_t length) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t format = 0;
+  uint16_t offset_coverage = 0;
+
+  if (!subtable.ReadU16(&format) ||
+      !subtable.ReadU16(&offset_coverage)) {
+    return OTS_FAILURE();
+  }
+
+  const uint16_t num_glyphs = file->maxp->num_glyphs;
+
+  uint16_t backtrack_glyph_count = 0;
+  if (!subtable.ReadU16(&backtrack_glyph_count)) {
+    return OTS_FAILURE();
+  }
+  if (backtrack_glyph_count > num_glyphs) {
+    return OTS_FAILURE();
+  }
+  std::vector<uint16_t> offsets_backtrack;
+  offsets_backtrack.reserve(backtrack_glyph_count);
+  for (unsigned i = 0; i < backtrack_glyph_count; ++i) {
+    uint16_t offset = 0;
+    if (!subtable.ReadU16(&offset)) {
+      return OTS_FAILURE();
+    }
+    offsets_backtrack.push_back(offset);
+  }
+
+  uint16_t lookahead_glyph_count = 0;
+  if (!subtable.ReadU16(&lookahead_glyph_count)) {
+    return OTS_FAILURE();
+  }
+  if (lookahead_glyph_count > num_glyphs) {
+    return OTS_FAILURE();
+  }
+  std::vector<uint16_t> offsets_lookahead;
+  offsets_lookahead.reserve(lookahead_glyph_count);
+  for (unsigned i = 0; i < lookahead_glyph_count; ++i) {
+    uint16_t offset = 0;
+    if (!subtable.ReadU16(&offset)) {
+      return OTS_FAILURE();
+    }
+    offsets_lookahead.push_back(offset);
+  }
+
+  uint16_t glyph_count = 0;
+  if (!subtable.ReadU16(&glyph_count)) {
+    return OTS_FAILURE();
+  }
+  if (glyph_count > num_glyphs) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < glyph_count; ++i) {
+    uint16_t substitute = 0;
+    if (!subtable.ReadU16(&substitute)) {
+      return OTS_FAILURE();
+    }
+    if (substitute >= num_glyphs) {
+      return OTS_FAILURE();
+    }
+  }
+
+  const unsigned substitute_end = static_cast<unsigned>(10) +
+      (backtrack_glyph_count + lookahead_glyph_count + glyph_count) * 2;
+  if (substitute_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+
+  if (offset_coverage < substitute_end || offset_coverage >= length) {
+    return OTS_FAILURE();
+  }
+  if (!ots::ParseCoverageTable(data + offset_coverage,
+                               length - offset_coverage, num_glyphs)) {
+    return OTS_FAILURE();
+  }
+
+  for (unsigned i = 0; i < backtrack_glyph_count; ++i) {
+    if (offsets_backtrack[i] < substitute_end ||
+        offsets_backtrack[i] >= length) {
+      return OTS_FAILURE();
+    }
+    if (!ots::ParseCoverageTable(data + offsets_backtrack[i],
+                                 length - offsets_backtrack[i], num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  for (unsigned i = 0; i < lookahead_glyph_count; ++i) {
+    if (offsets_lookahead[i] < substitute_end ||
+        offsets_lookahead[i] >= length) {
+      return OTS_FAILURE();
+    }
+    if (!ots::ParseCoverageTable(data + offsets_lookahead[i],
+                                 length - offsets_lookahead[i], num_glyphs)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  return true;
+}
+
+}  // namespace
+
+#define DROP_THIS_TABLE \
+  do { file->gsub->data = 0; file->gsub->length = 0; } while (0)
+
 namespace ots {
 
+// As far as I checked, following fonts contain invalid values in GSUB table.
+// OTS will drop their GSUB table.
+//
+// # too large substitute (value is 0xFFFF)
+// kaiu.ttf
+// mingliub2.ttf
+// mingliub1.ttf
+// mingliub0.ttf
+// GraublauWeb.otf
+// GraublauWebBold.otf
+//
+// # too large alternate (value is 0xFFFF)
+// ManchuFont.ttf
+//
+// # bad offset to lang sys table (NULL offset)
+// DejaVuMonoSansBold.ttf
+// DejaVuMonoSansBoldOblique.ttf
+// DejaVuMonoSansOblique.ttf
+// DejaVuSansMono-BoldOblique.ttf
+// DejaVuSansMono-Oblique.ttf
+// DejaVuSansMono-Bold.ttf
+//
+// # bad start coverage index
+// GenBasBI.ttf
+// GenBasI.ttf
+// AndBasR.ttf
+// GenBkBasI.ttf
+// CharisSILR.ttf
+// CharisSILBI.ttf
+// CharisSILI.ttf
+// CharisSILB.ttf
+// DoulosSILR.ttf
+// CharisSILBI.ttf
+// GenBkBasB.ttf
+// GenBkBasR.ttf
+// GenBkBasBI.ttf
+// GenBasB.ttf
+// GenBasR.ttf
+//
+// # glyph range is overlapping
+// KacstTitleL.ttf
+// KacstDecorative.ttf
+// KacstTitle.ttf
+// KacstArt.ttf
+// KacstPoster.ttf
+// KacstQurn.ttf
+// KacstDigital.ttf
+// KacstBook.ttf
+// KacstFarsi.ttf
+
 bool ots_gsub_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
+  // Parsing gsub table requires |file->maxp->num_glyphs|
+  if (!file->maxp) {
+    return OTS_FAILURE();
+  }
+
   Buffer table(data, length);
 
   OpenTypeGSUB *gsub = new OpenTypeGSUB;
   file->gsub = gsub;
 
-  if (!table.Skip(length)) {
+  uint32_t version = 0;
+  uint16_t offset_script_list = 0;
+  uint16_t offset_feature_list = 0;
+  uint16_t offset_lookup_list = 0;
+  if (!table.ReadU32(&version) ||
+      !table.ReadU16(&offset_script_list) ||
+      !table.ReadU16(&offset_feature_list) ||
+      !table.ReadU16(&offset_lookup_list)) {
     return OTS_FAILURE();
   }
 
+  if (version != 0x00010000) {
+    OTS_WARNING("bad GSUB version");
+    DROP_THIS_TABLE;
+    return true;
+  }
+  if ((offset_script_list < kGsubHeaderSize ||
+       offset_script_list >= length) ||
+      (offset_feature_list < kGsubHeaderSize ||
+       offset_feature_list >= length) ||
+      (offset_lookup_list < kGsubHeaderSize ||
+       offset_lookup_list >= length)) {
+    OTS_WARNING("bad offset in GSUB header");
+    DROP_THIS_TABLE;
+    return true;
+  }
+
+  if (!ParseLookupListTable(file, data + offset_lookup_list,
+                            length - offset_lookup_list,
+                            &kGsubLookupSubtableParser,
+                            &gsub->num_lookups)) {
+    OTS_WARNING("faild to parse lookup list table");
+    DROP_THIS_TABLE;
+    return true;
+  }
+
+  uint16_t num_features = 0;
+  if (!ParseFeatureListTable(data + offset_feature_list,
+                             length - offset_feature_list, gsub->num_lookups,
+                             &num_features)) {
+    OTS_WARNING("faild to parse feature list table");
+    DROP_THIS_TABLE;
+    return true;
+  }
+
+  if (!ParseScriptListTable(data + offset_script_list,
+                            length - offset_script_list, num_features)) {
+    OTS_WARNING("faild to parse script list table");
+    DROP_THIS_TABLE;
+    return true;
+  }
+
   gsub->data = data;
   gsub->length = length;
   return true;
 }
 
 bool ots_gsub_should_serialise(OpenTypeFile *file) {
-  return file->preserve_otl && file->gsub;
+  const bool needed_tables_dropped =
+      (file->gdef && file->gdef->data == NULL) ||
+      (file->gpos && file->gpos->data == NULL);
+  return file->gsub != NULL && file->gsub->data != NULL
+      && !needed_tables_dropped;
 }
 
 bool ots_gsub_serialise(OTSStream *out, OpenTypeFile *file) {
-  const OpenTypeGSUB *gsub = file->gsub;
-
-  if (!out->Write(gsub->data, gsub->length)) {
+  if (!out->Write(file->gsub->data, file->gsub->length)) {
     return OTS_FAILURE();
   }
 
   return true;
 }
 
 void ots_gsub_free(OpenTypeFile *file) {
   delete file->gsub;
 }
 
 }  // namespace ots
+
--- a/gfx/ots/src/gsub.h
+++ b/gfx/ots/src/gsub.h
@@ -1,19 +1,29 @@
-// Copyright (c) 2010 Mozilla Foundation. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef OTS_GSUB_H_
 #define OTS_GSUB_H_
 
 #include "ots.h"
 
 namespace ots {
 
 struct OpenTypeGSUB {
+  OpenTypeGSUB()
+      : num_lookups(0),
+        data(NULL),
+        length(0) {
+  }
+
+  // Number of lookups in GPSUB table
+  uint16_t num_lookups;
+
   const uint8_t *data;
-  uint32_t length;
+  size_t length;
 };
 
 }  // namespace ots
 
 #endif  // OTS_GSUB_H_
+
--- a/gfx/ots/src/head.cc
+++ b/gfx/ots/src/head.cc
@@ -110,17 +110,17 @@ bool ots_head_parse(OpenTypeFile *file, 
       glyph_data_format) {
     return OTS_FAILURE();
   }
 
   return true;
 }
 
 bool ots_head_should_serialise(OpenTypeFile *file) {
-  return file->head;
+  return file->head != NULL;
 }
 
 bool ots_head_serialise(OTSStream *out, OpenTypeFile *file) {
   if (!out->WriteU32(0x00010000) ||
       !out->WriteU32(file->head->revision) ||
       !out->WriteU32(0) ||  // check sum not filled in yet
       !out->WriteU32(0x5F0F3CF5) ||
       !out->WriteU16(file->head->flags) ||
--- a/gfx/ots/src/hhea.cc
+++ b/gfx/ots/src/hhea.cc
@@ -4,147 +4,46 @@
 
 #include "hhea.h"
 
 #include "head.h"
 #include "maxp.h"
 
 // hhea - Horizontal Header
 // http://www.microsoft.com/opentype/otspec/hhea.htm
-// vhea - Vertical Header
-// http://www.microsoft.com/opentype/otspec/vhea.htm
-// This file is used for both tables because they share the same structures.
 
 namespace ots {
 
-bool ots_Xhea_parse(OpenTypeFile *file, const uint8_t *data, size_t length,
-                    OpenTypeHHEA **out_hhea) {
+bool ots_hhea_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
   Buffer table(data, length);
   OpenTypeHHEA *hhea = new OpenTypeHHEA;
-  *out_hhea = hhea;
+  file->hhea = hhea;
 
-  if (!table.ReadU32(&hhea->version)) {
-    return OTS_FAILURE();
-  }
-  if (hhea->version >> 16 != 1) {
+  if (!table.ReadU32(&hhea->header.version)) {
     return OTS_FAILURE();
   }
-
-  if (!table.ReadS16(&hhea->ascent) ||
-      !table.ReadS16(&hhea->descent) ||
-      !table.ReadS16(&hhea->linegap) ||
-      !table.ReadU16(&hhea->adv_width_max) ||
-      !table.ReadS16(&hhea->min_lsb) ||
-      !table.ReadS16(&hhea->min_rsb) ||
-      !table.ReadS16(&hhea->x_max_extent) ||
-      !table.ReadS16(&hhea->caret_slope_rise) ||
-      !table.ReadS16(&hhea->caret_slope_run) ||
-      !table.ReadS16(&hhea->caret_offset)) {
+  if (hhea->header.version >> 16 != 1) {
     return OTS_FAILURE();
   }
 
-  if (hhea->ascent < 0) {
-    OTS_WARNING("bad ascent: %d", hhea->ascent);
-    hhea->ascent = 0;
-  }
-  if (hhea->linegap < 0) {
-    OTS_WARNING("bad linegap: %d", hhea->linegap);
-    hhea->linegap = 0;
-  }
-
-  if (!file->head) {
-    return OTS_FAILURE();
-  }
-
-  // if the font is non-slanted, caret_offset should be zero.
-  if (!(file->head->mac_style & 2) &&
-      (hhea->caret_offset != 0)) {
-    OTS_WARNING("bad caret offset: %d", hhea->caret_offset);
-    hhea->caret_offset = 0;
-  }
-
-  // skip the reserved bytes
-  if (!table.Skip(8)) {
-    return OTS_FAILURE();
-  }
-
-  int16_t data_format;
-  if (!table.ReadS16(&data_format)) {
-    return OTS_FAILURE();
-  }
-  if (data_format) {
-    return OTS_FAILURE();
-  }
-
-  if (!table.ReadU16(&hhea->num_hmetrics)) {
-    return OTS_FAILURE();
-  }
-
-  if (!file->maxp) {
-    return OTS_FAILURE();
-  }
-
-  if (hhea->num_hmetrics > file->maxp->num_glyphs) {
+  if (!ParseMetricsHeader(file, &table, &hhea->header)) {
     return OTS_FAILURE();
   }
 
   return true;
 }
 
-bool ots_hhea_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
-  return ots_Xhea_parse(file, data, length, &file->hhea);
-}
-
-bool ots_vhea_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
-  return ots_Xhea_parse(file, data, length, &file->vhea);
-}
-
 bool ots_hhea_should_serialise(OpenTypeFile *file) {
-  return file->hhea;
-}
-
-bool ots_vhea_should_serialise(OpenTypeFile *file) {
-  return file->preserve_otl && file->vhea;
-}
-
-bool ots_Xhea_serialise(OTSStream *out, OpenTypeFile *file, const OpenTypeHHEA *hhea) {
-  if (!out->WriteS16(hhea->ascent) ||
-      !out->WriteS16(hhea->descent) ||
-      !out->WriteS16(hhea->linegap) ||
-      !out->WriteU16(hhea->adv_width_max) ||
-      !out->WriteS16(hhea->min_lsb) ||
-      !out->WriteS16(hhea->min_rsb) ||
-      !out->WriteS16(hhea->x_max_extent) ||
-      !out->WriteS16(hhea->caret_slope_rise) ||
-      !out->WriteS16(hhea->caret_slope_run) ||
-      !out->WriteS16(hhea->caret_offset) ||
-      !out->WriteR64(0) ||  // reserved
-      !out->WriteS16(0) ||  // metric data format
-      !out->WriteU16(hhea->num_hmetrics)) {
-    return OTS_FAILURE();
-  }
-
-  return true;
+  return file->hhea != NULL;
 }
 
 bool ots_hhea_serialise(OTSStream *out, OpenTypeFile *file) {
-  if (!out->WriteU32(0x00010000)) {
+  if (!SerialiseMetricsHeader(out, &file->hhea->header)) {
     return OTS_FAILURE();
   }
-  return ots_Xhea_serialise(out, file, file->hhea);
-}
-
-bool ots_vhea_serialise(OTSStream *out, OpenTypeFile *file) {
-  if (!out->WriteU32(file->vhea->version)) {
-    return OTS_FAILURE();
-  }
-  return ots_Xhea_serialise(out, file, file->vhea);
+  return true;
 }
 
 void ots_hhea_free(OpenTypeFile *file) {
   delete file->hhea;
 }
 
-void ots_vhea_free(OpenTypeFile *file) {
-  delete file->vhea;
-}
-
 }  // namespace ots
--- a/gfx/ots/src/hhea.h
+++ b/gfx/ots/src/hhea.h
@@ -1,29 +1,19 @@
 // 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.
 
 #ifndef OTS_HHEA_H_
 #define OTS_HHEA_H_
 
+#include "metrics.h"
 #include "ots.h"
 
 namespace ots {
 
 struct OpenTypeHHEA {
-  uint32_t version;
-  int16_t ascent;
-  int16_t descent;
-  int16_t linegap;
-  uint16_t adv_width_max;
-  int16_t min_lsb;
-  int16_t min_rsb;
-  int16_t x_max_extent;
-  int16_t caret_slope_rise;
-  int16_t caret_slope_run;
-  int16_t caret_offset;
-  uint16_t num_hmetrics;
+  OpenTypeMetricsHeader header;
 };
 
 }  // namespace ots
 
 #endif  // OTS_HHEA_H_
--- a/gfx/ots/src/hmtx.cc
+++ b/gfx/ots/src/hmtx.cc
@@ -1,134 +1,47 @@
 // 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.
 
-#include <new>
 #include "hmtx.h"
 
 #include "hhea.h"
 #include "maxp.h"
 
 // hmtx - Horizontal Metrics
 // http://www.microsoft.com/opentype/otspec/hmtx.htm
-// vmtx - Vertical Metrics
-// http://www.microsoft.com/opentype/otspec/vmtx.htm
-// This file is used for both tables because they share the same structures.
 
 namespace ots {
 
-bool ots_Xmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length,
-                    const OpenTypeHHEA *hhea, OpenTypeHMTX **out_hmtx) {
+bool ots_hmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
   Buffer table(data, length);
   OpenTypeHMTX *hmtx = new OpenTypeHMTX;
-  *out_hmtx = hmtx;
+  file->hmtx = hmtx;
 
-  if (!hhea || !file->maxp) {
+  if (!file->hhea || !file->maxp) {
     return OTS_FAILURE();
   }
 
-  // |num_hmetrics| is a uint16_t, so it's bounded < 65536. This limits that
-  // amount of memory that we'll allocate for this to a sane amount.
-  const unsigned num_hmetrics = hhea->num_hmetrics;
-
-  if (num_hmetrics > file->maxp->num_glyphs) {
-    return OTS_FAILURE();
-  }
-  if (!num_hmetrics) {
+  if (!ParseMetricsTable(&table, file->maxp->num_glyphs,
+                         &file->hhea->header, &hmtx->metrics)) {
     return OTS_FAILURE();
   }
-  const unsigned num_lsbs = file->maxp->num_glyphs - num_hmetrics;
-
-  hmtx->metrics.reserve(num_hmetrics);
-  for (unsigned i = 0; i < num_hmetrics; ++i) {
-    uint16_t adv = 0;
-    int16_t lsb = 0;
-    if (!table.ReadU16(&adv) || !table.ReadS16(&lsb)) {
-      return OTS_FAILURE();
-    }
-
-    // Since so many fonts don't have proper value on |adv| and |lsb|,
-    // we should not call ots_failure() here. For example, about 20% of fonts
-    // in http://www.princexml.com/fonts/ (200+ fonts) fails these tests.
-    if (adv > hhea->adv_width_max) {
-      OTS_WARNING("bad adv: %u > %u", adv, hhea->adv_width_max);
-      adv = hhea->adv_width_max;
-    }
-    if (lsb < hhea->min_lsb) {
-      OTS_WARNING("bad lsb: %d < %d", lsb, hhea->min_lsb);
-      lsb = hhea->min_lsb;
-    }
-
-    hmtx->metrics.push_back(std::make_pair(adv, lsb));
-  }
-
-  hmtx->lsbs.reserve(num_lsbs);
-  for (unsigned i = 0; i < num_lsbs; ++i) {
-    int16_t lsb;
-    if (!table.ReadS16(&lsb)) {
-      // Some Japanese fonts (e.g., mona.ttf) fail this test.
-      return OTS_FAILURE();
-    }
-
-    if (lsb < hhea->min_lsb) {
-      // The same as above. Three fonts in http://www.fontsquirrel.com/fontface
-      // (e.g., Notice2Std.otf) have weird lsb values.
-      OTS_WARNING("bad lsb: %d < %d", lsb, hhea->min_lsb);
-      lsb = hhea->min_lsb;
-    }
-
-    hmtx->lsbs.push_back(lsb);
-  }
 
   return true;
 }
 
-bool ots_hmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
-  return ots_Xmtx_parse(file, data, length, file->hhea, &file->hmtx);
-}
-
-bool ots_vmtx_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
-  return ots_Xmtx_parse(file, data, length, file->vhea, &file->vmtx);
-}
-
 bool ots_hmtx_should_serialise(OpenTypeFile *file) {
-  return file->hmtx;
-}
-
-bool ots_vmtx_should_serialise(OpenTypeFile *file) {
-  return file->preserve_otl && file->vmtx;
-}
-
-bool ots_Xmtx_serialise(OTSStream *out, OpenTypeFile *file, const OpenTypeHMTX *hmtx) {
-  for (unsigned i = 0; i < hmtx->metrics.size(); ++i) {
-    if (!out->WriteU16(hmtx->metrics[i].first) ||
-        !out->WriteS16(hmtx->metrics[i].second)) {
-      return OTS_FAILURE();
-    }
-  }
-
-  for (unsigned i = 0; i < hmtx->lsbs.size(); ++i) {
-    if (!out->WriteS16(hmtx->lsbs[i])) {
-      return OTS_FAILURE();
-    }
-  }
-
-  return true;
+  return file->hmtx != NULL;
 }
 
 bool ots_hmtx_serialise(OTSStream *out, OpenTypeFile *file) {
-  return ots_Xmtx_serialise(out, file, file->hmtx);
-}
-
-bool ots_vmtx_serialise(OTSStream *out, OpenTypeFile *file) {
-  return ots_Xmtx_serialise(out, file, file->vmtx);
+  if (!SerialiseMetricsTable(out, &file->hmtx->metrics)) {
+    return OTS_FAILURE();
+  }
+  return true;
 }
 
 void ots_hmtx_free(OpenTypeFile *file) {
   delete file->hmtx;
 }
 
-void ots_vmtx_free(OpenTypeFile *file) {
-  delete file->vmtx;
-}
-
 }  // namespace ots
--- a/gfx/ots/src/hmtx.h
+++ b/gfx/ots/src/hmtx.h
@@ -1,22 +1,19 @@
 // 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.
 
 #ifndef OTS_HMTX_H_
 #define OTS_HMTX_H_
 
-#include <utility>  // std::pair
-#include <vector>
-
+#include "metrics.h"
 #include "ots.h"
 
 namespace ots {
 
 struct OpenTypeHMTX {
-  std::vector<std::pair<uint16_t, int16_t> > metrics;
-  std::vector<int16_t> lsbs;
+  OpenTypeMetricsTable metrics;
 };
 
 }  // namespace ots
 
 #endif  // OTS_HMTX_H_
--- a/gfx/ots/src/kern.cc
+++ b/gfx/ots/src/kern.cc
@@ -150,17 +150,17 @@ bool ots_kern_parse(OpenTypeFile *file, 
     return true;
   }
 
   return true;
 }
 
 bool ots_kern_should_serialise(OpenTypeFile *file) {
   if (!file->glyf) return false;  // this table is not for CFF fonts.
-  return file->kern;
+  return file->kern != NULL;
 }
 
 bool ots_kern_serialise(OTSStream *out, OpenTypeFile *file) {
   const OpenTypeKERN *kern = file->kern;
 
   if (!out->WriteU16(kern->version) ||
       !out->WriteU16(kern->subtables.size())) {
     return OTS_FAILURE();
new file mode 100644
--- /dev/null
+++ b/gfx/ots/src/layout.cc
@@ -0,0 +1,1477 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "layout.h"
+
+#include <limits>
+#include <vector>
+
+#include "gdef.h"
+
+// OpenType Layout Common Table Formats
+// http://www.microsoft.com/typography/otspec/chapter2.htm
+
+namespace {
+
+// The 'DFLT' tag of script table.
+const uint32_t kScriptTableTagDflt = 0x44464c54;
+// The value which represents there is no required feature index.
+const uint16_t kNoRequiredFeatureIndexDefined = 0xFFFF;
+// The lookup flag bit which indicates existence of MarkFilteringSet.
+const uint16_t kUseMarkFilteringSetBit = 0x0010;
+// The lookup flags which require GDEF table.
+const uint16_t kGdefRequiredFlags = 0x0002 | 0x0004 | 0x0008;
+// The mask for MarkAttachmentType.
+const uint16_t kMarkAttachmentTypeMask = 0xFF00;
+// The maximum type number of format for device tables.
+const uint16_t kMaxDeltaFormatType = 3;
+// The maximum number of class value.
+const uint16_t kMaxClassDefValue = 0xFFFF;
+
+struct ScriptRecord {
+  uint32_t tag;
+  uint16_t offset;
+};
+
+struct LangSysRecord {
+  uint32_t tag;
+  uint16_t offset;
+};
+
+struct FeatureRecord {
+  uint32_t tag;
+  uint16_t offset;
+};
+
+bool ParseLangSysTable(ots::Buffer *subtable, const uint32_t tag,
+                       const uint16_t num_features) {
+  uint16_t offset_lookup_order = 0;
+  uint16_t req_feature_index = 0;
+  uint16_t feature_count = 0;
+  if (!subtable->ReadU16(&offset_lookup_order) ||
+      !subtable->ReadU16(&req_feature_index) ||
+      !subtable->ReadU16(&feature_count)) {
+    return OTS_FAILURE();
+  }
+  // |offset_lookup_order| is reserved and should be NULL.
+  if (offset_lookup_order != 0) {
+    return OTS_FAILURE();
+  }
+  if (req_feature_index != kNoRequiredFeatureIndexDefined &&
+      req_feature_index >= num_features) {
+    return OTS_FAILURE();
+  }
+  if (feature_count > num_features) {
+    return OTS_FAILURE();
+  }
+
+  for (unsigned i = 0; i < feature_count; ++i) {
+    uint16_t feature_index = 0;
+    if (!subtable->ReadU16(&feature_index)) {
+      return OTS_FAILURE();
+    }
+    if (feature_index >= num_features) {
+      return OTS_FAILURE();
+    }
+  }
+  return true;
+}
+
+bool ParseScriptTable(const uint8_t *data, const size_t length,
+                      const uint32_t tag, const uint16_t num_features) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t offset_default_lang_sys = 0;
+  uint16_t lang_sys_count = 0;
+  if (!subtable.ReadU16(&offset_default_lang_sys) ||
+      !subtable.ReadU16(&lang_sys_count)) {
+    return OTS_FAILURE();
+  }
+
+  // The spec requires a script table for 'DFLT' tag must contain non-NULL
+  // |offset_default_lang_sys| and |lang_sys_count| == 0
+  if (tag == kScriptTableTagDflt &&
+      (offset_default_lang_sys == 0 || lang_sys_count != 0)) {
+    OTS_WARNING("DFLT table doesn't satisfy the spec.");
+    return OTS_FAILURE();
+  }
+
+  const unsigned lang_sys_record_end = static_cast<unsigned>(4) +
+      lang_sys_count * 6;
+  if (lang_sys_record_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+
+  std::vector<LangSysRecord> lang_sys_records;
+  lang_sys_records.resize(lang_sys_count);
+  uint32_t last_tag = 0;
+  for (unsigned i = 0; i < lang_sys_count; ++i) {
+    if (!subtable.ReadU32(&lang_sys_records[i].tag) ||
+        !subtable.ReadU16(&lang_sys_records[i].offset)) {
+      return OTS_FAILURE();
+    }
+    // The record array must store the records alphabetically by tag
+    if (last_tag != 0 && last_tag > lang_sys_records[i].tag) {
+      return OTS_FAILURE();
+    }
+    if (lang_sys_records[i].offset < lang_sys_record_end ||
+        lang_sys_records[i].offset >= length) {
+      OTS_WARNING("bad offset to lang sys table: %x",
+                  lang_sys_records[i].offset);
+      return OTS_FAILURE();
+    }
+    last_tag = lang_sys_records[i].tag;
+  }
+
+  // Check lang sys tables
+  for (unsigned i = 0; i < lang_sys_count; ++i) {
+    subtable.set_offset(lang_sys_records[i].offset);
+    if (!ParseLangSysTable(&subtable, lang_sys_records[i].tag, num_features)) {
+      return OTS_FAILURE();
+    }
+  }
+
+  return true;
+}
+
+bool ParseFeatureTable(const uint8_t *data, const size_t length,
+                       const uint16_t num_lookups) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t offset_feature_params = 0;
+  uint16_t lookup_count = 0;
+  if (!subtable.ReadU16(&offset_feature_params) ||
+      !subtable.ReadU16(&lookup_count)) {
+    return OTS_FAILURE();
+  }
+
+  const unsigned feature_table_end = static_cast<unsigned>(4) +
+      num_lookups * 2;
+  if (feature_table_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  // |offset_feature_params| is generally set to NULL.
+  if (offset_feature_params != 0 &&
+      (offset_feature_params < feature_table_end ||
+       offset_feature_params >= length)) {
+    return OTS_FAILURE();
+  }
+
+  for (unsigned i = 0; i < lookup_count; ++i) {
+    uint16_t lookup_index = 0;
+    if (!subtable.ReadU16(&lookup_index)) {
+      return OTS_FAILURE();
+    }
+    // lookup index starts with 0.
+    if (lookup_index >= num_lookups) {
+      return OTS_FAILURE();
+    }
+  }
+  return true;
+}
+
+bool ParseLookupTable(ots::OpenTypeFile *file, const uint8_t *data,
+                      const size_t length,
+                      const ots::LookupSubtableParser* parser) {
+  ots::Buffer subtable(data, length);
+
+  uint16_t lookup_type = 0;
+  uint16_t lookup_flag = 0;
+  uint16_t subtable_count = 0;
+  if (!subtable.ReadU16(&lookup_type) ||
+      !subtable.ReadU16(&lookup_flag) ||
+      !subtable.ReadU16(&subtable_count)) {
+    return OTS_FAILURE();
+  }
+
+  if (lookup_type == 0 || lookup_type > parser->num_types) {
+    return OTS_FAILURE();
+  }
+
+  // Check lookup flags.
+  if ((lookup_flag & kGdefRequiredFlags) &&
+      (!file->gdef || !file->gdef->has_glyph_class_def)) {
+    return OTS_FAILURE();
+  }
+  if ((lookup_flag & kMarkAttachmentTypeMask) &&
+      (!file->gdef || !file->gdef->has_mark_attachment_class_def)) {
+    return OTS_FAILURE();
+  }
+  bool use_mark_filtering_set = false;
+  if (lookup_flag & kUseMarkFilteringSetBit) {
+    if (!file->gdef || !file->gdef->has_mark_glyph_sets_def) {
+      return OTS_FAILURE();
+    }
+    use_mark_filtering_set = true;
+  }
+
+  std::vector<uint16_t> subtables;
+  subtables.reserve(subtable_count);
+  // If the |kUseMarkFilteringSetBit| of |lookup_flag| is set,
+  // extra 2 bytes will follow after subtable offset array.
+  const unsigned lookup_table_end =
+      static_cast<unsigned>(use_mark_filtering_set ? 8 : 6) +
+      subtable_count * 2;
+  if (lookup_table_end > std::numeric_limits<uint16_t>::max()) {
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < subtable_count; ++i) {
+    uint16_t offset_subtable = 0;
+    if (!subtable.ReadU16(&offset_subtable)) {
+      return OTS_FAILURE();
+    }
+    if (offset_subtable < lookup_table_end ||
+        offset_subtable >= length) {
+      return OTS_FAILURE();
+    }
+    subtables.push_back(offset_subtable);
+  }
+  if (subtables.size() != subtable_count) {
+    return OTS_FAILURE();
+  }
+
+  if (use_mark_filtering_set) {
+    uint16_t mark_filtering_set = 0;
+    if (!subtable.ReadU16(&mark_filtering_set)) {
+      return OTS_FAILURE();
+    }
+    if (file->gdef->num_mark_glyph_sets == 0 ||
+        mark_filtering_set >= file->gdef->num_mark_glyph_sets) {
+      return OTS_FAILURE();
+    }
+  }
+
+  // Parse lookup subtables for this lookup type.
+  for (unsigned i = 0; i < subtable_count; ++i) {
+    if (!parser->Parse(file, data + subtables[i], length - subtables[i],
+                       lookup_type)) {
+      return OTS_FAILURE();
+    }
+  }
+  return true;
+}
+
+bool ParseClassDefFormat1(const uint8_t *data, size_t length,
+                          const uint16_t num_glyphs,
+                          const uint16_t num_classes) {
+  ots::Buffer subtable(data, length);
+
+  // Skip format field.
+  if (!subtable.Skip(2)) {
+    return OTS_FAILURE();
+  }
+
+  uint16_t start_glyph = 0;
+  if (!subtable.ReadU16(&start_glyph)) {
+    return OTS_FAILURE();
+  }
+  if (start_glyph > num_glyphs) {
+    OTS_WARNING("bad start glyph ID: %u", start_glyph);
+    return OTS_FAILURE();
+  }
+
+  uint16_t glyph_count = 0;
+  if (!subtable.ReadU16(&glyph_count)) {
+    return OTS_FAILURE();
+  }
+  if (glyph_count > num_glyphs) {
+    OTS_WARNING("bad glyph count: %u", glyph_count);
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < glyph_count; ++i) {
+    uint16_t class_value = 0;
+    if (!subtable.ReadU16(&class_value)) {
+      return OTS_FAILURE();
+    }
+    if (class_value > num_classes) {
+      OTS_WARNING("bad class value: %u", class_value);
+      return OTS_FAILURE();
+    }
+  }
+
+  return true;
+}
+
+bool ParseClassDefFormat2(const uint8_t *data, size_t length,
+                          const uint16_t num_glyphs,
+                          const uint16_t num_classes) {
+  ots::Buffer subtable(data, length);
+
+  // Skip format field.
+  if (!subtable.Skip(2)) {
+    return OTS_FAILURE();
+  }
+
+  uint16_t range_count = 0;
+  if (!subtable.ReadU16(&range_count)) {
+    return OTS_FAILURE();
+  }
+  if (range_count > num_glyphs) {
+    OTS_WARNING("bad range count: %u", range_count);
+    return OTS_FAILURE();
+  }
+
+  uint16_t last_end = 0;
+  for (unsigned i = 0; i < range_count; ++i) {
+    uint16_t start = 0;
+    uint16_t end = 0;
+    uint16_t class_value = 0;
+    if (!subtable.ReadU16(&start) ||
+        !subtable.ReadU16(&end) ||
+        !subtable.ReadU16(&class_value)) {
+      return OTS_FAILURE();
+    }
+    if (start > end || (last_end && start <= last_end)) {
+      OTS_WARNING("glyph range is overlapping.");
+      return OTS_FAILURE();
+    }
+    if (class_value > num_classes) {
+      OTS_WARNING("bad class value: %u", class_value);
+      return OTS_FAILURE();
+    }
+    last_end = end;
+  }
+
+  return true;
+}
+
+bool ParseCoverageFormat1(const uint8_t *data, size_t length,
+                          const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  // Skip format field.
+  if (!subtable.Skip(2)) {
+    return OTS_FAILURE();
+  }
+
+  uint16_t glyph_count = 0;
+  if (!subtable.ReadU16(&glyph_count)) {
+    return OTS_FAILURE();
+  }
+  if (glyph_count > num_glyphs) {
+    OTS_WARNING("bad glyph count: %u", glyph_count);
+    return OTS_FAILURE();
+  }
+  for (unsigned i = 0; i < glyph_count; ++i) {
+    uint16_t glyph = 0;
+    if (!subtable.ReadU16(&glyph)) {
+      return OTS_FAILURE();
+    }
+    if (glyph > num_glyphs) {
+      OTS_WARNING("bad glyph ID: %u", glyph);
+      return OTS_FAILURE();
+    }
+  }
+
+  return true;
+}
+
+bool ParseCoverageFormat2(const uint8_t *data, size_t length,
+                          const uint16_t num_glyphs) {
+  ots::Buffer subtable(data, length);
+
+  // Skip format field.
+  if (!subtable.Skip(2)) {
+    return OTS_FAILURE();
+  }
+
+  uint16_t range_count = 0;
+  if (!subtable.ReadU16(&range_count)) {
+    return OTS_FAILURE();
+  }
+  if (range_count > num_glyphs) {
+    OTS_WARNING("bad range count: %u", range_count);
+    return OTS_FAILURE();
+  }
+  uint16_t last_end = 0;
+  uint16_t last_start_coverage_index = 0;
+  for (unsigned i = 0; i < range_count; ++i) {
+    uint16_t start = 0;
+    uint16_t end = 0;
+    uint16_t start_