Merge m-c to s-c
authorGregory Szorc <gps@mozilla.com>
Tue, 24 Apr 2012 13:34:12 -0400
changeset 95729 e99c1619dbfdd0ad283328f781b2a4d99a5c6da1
parent 95728 01a2e8732a7c6a4bf514e2bd12c0f6d463717b52 (current diff)
parent 94483 424cb3a6141ba453e1226eceaf55e02ee95f5a29 (diff)
child 95730 2765184c38e739596356b7f71c46e84ac3a59386
push id1439
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 20:19:22 +0000
treeherdermozilla-aurora@ea74834dccd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone15.0a1
Merge m-c to s-c
--- a/.hgtags
+++ b/.hgtags
@@ -74,8 +74,9 @@ 54bfd8bf682e295ffd7f22fa921ca343957b6c1c
 a8506ab2c65480cf2f85f54e203ea746522c62bb AURORA_BASE_20111220
 462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R16
 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
 0000000000000000000000000000000000000000 AURORA_BASE_20120131
 0000000000000000000000000000000000000000 AURORA_BASE_20120131
 bbc7014db2de49e2301680d2a86be8a53108a88a AURORA_BASE_20120131
 b6627f28b7ec17e1b46a594df0f780d3a40847e4 FIREFOX_AURORA_13_BASE
+357da346ceb705d196a46574804c7c4ec44ac186 FIREFOX_AURORA_14_BASE
old mode 100644
new mode 100755
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -33,17 +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 *****
 
 MOZ_APP_BASENAME=B2G
 MOZ_APP_VENDOR=Mozilla
 
-MOZ_APP_VERSION=14.0a1
+MOZ_APP_VERSION=15.0a1
 MOZ_APP_UA_NAME=Firefox
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=
 MOZ_SERVICES_SYNC=1
--- a/browser/app/macbuild/Contents/Info.plist.in
+++ b/browser/app/macbuild/Contents/Info.plist.in
@@ -198,18 +198,16 @@
 				<string>file</string>
 			</array>
 		</dict>
 	</array>
 	<key>CFBundleVersion</key>
 	<string>%APP_VERSION%</string>
 	<key>NSAppleScriptEnabled</key>
 	<true/>
-	<key>CGDisableCoalescedUpdates</key>
-	<true/>
 	<key>LSMinimumSystemVersion</key>
 	<string>10.5</string>
 	<key>LSMinimumSystemVersionByArchitecture</key>
 	<dict>
 		<key>i386</key>
 		<string>10.5.0</string>
 		<key>x86_64</key>
 		<string>10.6.0</string>
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -872,17 +872,17 @@ pref("places.frecency.unvisitedTypedBonu
 // 1 - pre-populate site URL, but don't fetch certificate
 // 2 - pre-populate site URL and pre-fetch certificate
 pref("browser.ssl_override_behavior", 2);
 
 // Controls the display of domain in the identity box for SSL connections.
 // 0 - do not show domain
 // 1 - show effectiveTLD + 1 (e.g. mozilla.org)
 // 2 - show full domain (e.g. bugzilla.mozilla.org)
-pref("browser.identity.ssl_domain_display", 1);
+pref("browser.identity.ssl_domain_display", 0);
 
 // True if the user should be prompted when a web application supports
 // offline apps.
 pref("browser.offline-apps.notify", true);
 
 // if true, use full page zoom instead of text zoom
 pref("browser.zoom.full", true);
 
@@ -1147,8 +1147,13 @@ pref("browser.newtabpage.enabled", true)
 
 // Enable the DOM full-screen API.
 pref("full-screen-api.enabled", true);
 
 // Startup Crash Tracking
 // number of startup crashes that can occur before starting into safe mode automatically
 // (this pref has no effect if more than 6 hours have passed since the last crash)
 pref("toolkit.startup.max_resumed_crashes", 2);
+
+// The maximum amount of decoded image data we'll willingly keep around (we
+// might keep around more than this, but we'll try to get down to this value).
+// (This is intentionally on the high side; see bug 746055.)
+pref("image.mem.max_decoded_image_kb", 256000);
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -152,17 +152,17 @@ XPCOMUtils.defineLazyGetter(window, "gFi
   return this.PluralForm;
 });
 __defineSetter__("PluralForm", function (val) {
   delete this.PluralForm;
   return this.PluralForm = val;
 });
 
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
-                                  "resource:///modules/TelemetryStopwatch.jsm");
+                                  "resource://gre/modules/TelemetryStopwatch.jsm");
 
 #ifdef MOZ_SERVICES_SYNC
 XPCOMUtils.defineLazyGetter(this, "Weave", function() {
   let tmp = {};
   Cu.import("resource://services-sync/main.js", tmp);
   return tmp.Weave;
 });
 #endif
@@ -2681,38 +2681,19 @@ function SetPageProxyState(aState)
   gURLBar.setAttribute("pageproxystate", aState);
   gProxyFavIcon.setAttribute("pageproxystate", aState);
 
   // the page proxy state is set to valid via OnLocationChange, which
   // gets called when we switch tabs.
   if (aState == "valid") {
     gLastValidURLStr = gURLBar.value;
     gURLBar.addEventListener("input", UpdatePageProxyState, false);
-
-    PageProxySetIcon(gBrowser.getIcon());
   } else if (aState == "invalid") {
     gURLBar.removeEventListener("input", UpdatePageProxyState, false);
-    PageProxyClearIcon();
-  }
-}
-
-function PageProxySetIcon (aURL)
-{
-  if (!gProxyFavIcon)
-    return;
-
-  if (!aURL)
-    PageProxyClearIcon();
-  else if (gProxyFavIcon.getAttribute("src") != aURL)
-    gProxyFavIcon.setAttribute("src", aURL);
-}
-
-function PageProxyClearIcon ()
-{
-  gProxyFavIcon.removeAttribute("src");
+  }
 }
 
 function PageProxyClickHandler(aEvent)
 {
   if (aEvent.button == 1 && gPrefService.getBoolPref("middlemouse.paste"))
     middleMousePaste(aEvent);
 }
 
@@ -4624,21 +4605,16 @@ var XULBrowserWindow = {
     let [longHost, shortHost] =
       linkHost.length > docHost.length ? [linkHost, docHost] : [docHost, linkHost];
     if (longHost == "www." + shortHost)
       return originalTarget;
 
     return "_blank";
   },
 
-  onLinkIconAvailable: function (aIconURL) {
-    if (gProxyFavIcon && gBrowser.userTypedValue === null)
-      PageProxySetIcon(aIconURL); // update the favicon in the URL bar
-  },
-
   onProgressChange: function (aWebProgress, aRequest,
                               aCurSelfProgress, aMaxSelfProgress,
                               aCurTotalProgress, aMaxTotalProgress) {
     // Do nothing.
   },
 
   onProgressChange64: function (aWebProgress, aRequest,
                                 aCurSelfProgress, aMaxSelfProgress,
@@ -8057,28 +8033,34 @@ var gIdentityHandler = {
     delete this._overrideService;
     return this._overrideService = Cc["@mozilla.org/security/certoverride;1"]
                                      .getService(Ci.nsICertOverrideService);
   },
   get _identityIconCountryLabel () {
     delete this._identityIconCountryLabel;
     return this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
   },
+  get _identityIcon () {
+    delete this._identityIcon;
+    return this._identityIcon = document.getElementById("page-proxy-favicon");
+  },
 
   /**
    * Rebuild cache of the elements that may or may not exist depending
    * on whether there's a location bar.
    */
   _cacheElements : function() {
     delete this._identityBox;
     delete this._identityIconLabel;
     delete this._identityIconCountryLabel;
+    delete this._identityIcon;
     this._identityBox = document.getElementById("identity-box");
     this._identityIconLabel = document.getElementById("identity-icon-label");
     this._identityIconCountryLabel = document.getElementById("identity-icon-country-label");
+    this._identityIcon = document.getElementById("page-proxy-favicon");
   },
 
   /**
    * Handler for mouseclicks on the "More Information" button in the
    * "identity-popup" panel.
    */
   handleMoreInfoClick : function(event) {
     displaySecurityInfo();
@@ -8373,17 +8355,17 @@ var gIdentityHandler = {
     this._identityBox.setAttribute("open", "true");
     var self = this;
     this._identityPopup.addEventListener("popuphidden", function onPopupHidden(e) {
       e.currentTarget.removeEventListener("popuphidden", onPopupHidden, false);
       self._identityBox.removeAttribute("open");
     }, false);
 
     // Now open the popup, anchored off the primary chrome element
-    this._identityPopup.openPopup(this._identityBox, "bottomcenter topleft");
+    this._identityPopup.openPopup(this._identityIcon, "bottomcenter topleft");
   },
 
   onPopupShown : function(event) {
     let openingDuration = new Date() - this._popupOpenTime;
     this._popupOpenTime = null;
     try {
       Services.telemetry.getHistogramById("FX_IDENTITY_POPUP_OPEN_MS").add(openingDuration);
     } catch (ex) {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -537,19 +537,18 @@
                has focus, otherwise pressing F6 focuses it instead of the location bar -->
           <box id="identity-box" role="button"
                onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
                onkeypress="gIdentityHandler.handleIdentityButtonEvent(event);"
                ondragstart="gIdentityHandler.onDragStart(event);">
             <hbox id="identity-box-inner" align="center">
               <hbox id="page-proxy-stack"
                     onclick="PageProxyClickHandler(event);">
-                <image id="page-proxy-favicon" validate="never"
-                       pageproxystate="invalid"
-                       onerror="this.removeAttribute('src');"/>
+                <image id="page-proxy-favicon"
+                       pageproxystate="invalid"/>
               </hbox>
               <hbox id="identity-icon-labels">
                 <label id="identity-icon-label" class="plain" flex="1"/>
                 <label id="identity-icon-country-label" class="plain"/>
               </hbox>
             </hbox>
           </box>
           <box id="urlbar-display-box" align="center">
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -523,18 +523,26 @@ nsContextMenu.prototype = {
           this.onCompletedImage = true;
 
         this.mediaURL = this.target.currentURI.spec;
       }
       else if (this.target instanceof HTMLCanvasElement) {
         this.onCanvas = true;
       }
       else if (this.target instanceof HTMLVideoElement) {
-        this.onVideo = true;
         this.mediaURL = this.target.currentSrc || this.target.src;
+        // Firefox always creates a HTMLVideoElement when loading an ogg file
+        // directly. If the media is actually audio, be smarter and provide a
+        // context menu with audio operations.
+        if (this.target.readyState >= this.target.HAVE_METADATA &&
+            (this.target.videoWidth == 0 || this.target.videoHeight == 0)) {
+          this.onAudio = true;
+        } else {
+          this.onVideo = true;
+        }
       }
       else if (this.target instanceof HTMLAudioElement) {
         this.onAudio = true;
         this.mediaURL = this.target.currentSrc || this.target.src;
       }
       else if (this.target instanceof HTMLInputElement ) {
         this.onTextInput = this.isTargetATextBox(this.target);
         // Allow spellchecking UI on all text and search inputs.
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -72,16 +72,17 @@ include $(topsrcdir)/config/rules.mk
 		gZipOfflineChild.html^headers^ \
 		gZipOfflineChild.cacheManifest \
 		gZipOfflineChild.cacheManifest^headers^ \
 		$(NULL)
 
 # test_contextmenu.html is disabled on Linux due to bug 513558
 ifneq (gtk2,$(MOZ_WIDGET_TOOLKIT))
 _TEST_FILES += \
+		audio.ogg \
 		test_contextmenu.html \
 		subtst_contextmenu.html \
 		$(NULL)
 endif
 
 # The following tests are disabled because they are unreliable:
 #   browser_bug423833.js is bug 428712
 #   browser_sanitize-download-history.js is bug 432425
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..7e6ef77ec407eccb3e07bc21d85d8418ab84e011
GIT binary patch
literal 47411
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
XyT24_pfD-Z!Ja|1Dz)kjcVGKIz3Fi!
--- a/browser/base/content/test/browser_identity_UI.js
+++ b/browser/base/content/test/browser_identity_UI.js
@@ -1,11 +1,14 @@
 /* Tests for correct behaviour of getEffectiveHost on identity handler */
 function test() {
   waitForExplicitFinish();
+  registerCleanupFunction(function() {
+    Services.prefs.clearUserPref("browser.identity.ssl_domain_display");
+  });
 
   ok(gIdentityHandler, "gIdentityHandler should exist");
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", checkResult, true);
 
   nextTest();
 }
@@ -67,44 +70,58 @@ var tests = [
     effectiveHost: "127.0.0.1"
   },
 ]
 
 let gCurrentTest, gCurrentTestIndex = -1, gTestDesc;
 // Go through the tests in both directions, to add additional coverage for
 // transitions between different states.
 let gForward = true;
+let gCheckETLD = false;
 function nextTest() {
-  if (gForward)
-    gCurrentTestIndex++;
-  else
-    gCurrentTestIndex--;
+  if (!gCheckETLD) {
+    if (gForward)
+      gCurrentTestIndex++;
+    else
+      gCurrentTestIndex--;
 
-  if (gCurrentTestIndex == tests.length) {
-    // Went too far, reverse
-    gCurrentTestIndex--;
-    gForward = false;
-  }
+    if (gCurrentTestIndex == tests.length) {
+      // Went too far, reverse
+      gCurrentTestIndex--;
+      gForward = false;
+    }
 
-  if (gCurrentTestIndex == -1) {
-    gBrowser.selectedBrowser.removeEventListener("load", checkResult, true);
-    gBrowser.removeCurrentTab();
-    finish();
-    return;
+    if (gCurrentTestIndex == -1) {
+      gBrowser.selectedBrowser.removeEventListener("load", checkResult, true);
+      gBrowser.removeCurrentTab();
+      finish();
+      return;
+    }
+
+    gCurrentTest = tests[gCurrentTestIndex];
+    gTestDesc = "#" + gCurrentTestIndex + " (" + gCurrentTest.name + ")";
+    if (!gForward)
+      gTestDesc += " (second time)";
+    if (gCurrentTest.isHTTPS) {
+      gCheckETLD = true;
+      Services.prefs.setIntPref("browser.identity.ssl_domain_display", 1);
+    }
+    content.location = gCurrentTest.location;
+  } else {
+    gCheckETLD = false;
+    gTestDesc = "#" + gCurrentTestIndex + " (" + gCurrentTest.name + " without eTLD in identity icon label)";
+    if (!gForward)
+      gTestDesc += " (second time)";
+    Services.prefs.clearUserPref("browser.identity.ssl_domain_display");
+    content.location.reload(true);
   }
-
-  gCurrentTest = tests[gCurrentTestIndex];
-  gTestDesc = "#" + gCurrentTestIndex + " (" + gCurrentTest.name + ")";
-  if (!gForward)
-    gTestDesc += " (second time)";
-  content.location = gCurrentTest.location;
 }
 
 function checkResult() {
-  if (gCurrentTest.isHTTPS) {
+  if (gCurrentTest.isHTTPS && Services.prefs.getIntPref("browser.identity.ssl_domain_display") == 1) {
     // Check that the effective host is displayed in the UI
     let label = document.getElementById("identity-icon-label");
     is(label.value, gCurrentTest.effectiveHost, "effective host is displayed in identity icon label for test " + gTestDesc);
   }
 
   // Sanity check other values, and the value of gIdentityHandler.getEffectiveHost()
   is(gIdentityHandler._lastLocation.host, gCurrentTest.host, "host matches for test " + gTestDesc);
   is(gIdentityHandler.getEffectiveHost(), gCurrentTest.effectiveHost, "effectiveHost matches for test " + gTestDesc);
--- a/browser/base/content/test/subtst_contextmenu.html
+++ b/browser/base/content/test/subtst_contextmenu.html
@@ -8,16 +8,17 @@ Browser context menu subtest.
 
 <div id="test-text">Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</div>
 <a id="test-link" href="http://mozilla.com">Click the monkey!</a>
 <a id="test-mailto" href="mailto:codemonkey@mozilla.com">Mail the monkey!</a><br>
 <input id="test-input"><br>
 <img id="test-image" src="ctxmenu-image.png">
 <canvas id="test-canvas" width="100" height="100" style="background-color: blue"></canvas>
 <video controls id="test-video-ok"  src="video.ogg" width="100" height="100" style="background-color: green"></video>
+<video id="test-audio-in-video" src="audio.ogg" width="100" height="100" style="background-color: red"></video>
 <video controls id="test-video-bad" src="bogus.duh" width="100" height="100" style="background-color: orange"></video>
 <video controls id="test-video-bad2" width="100" height="100" style="background-color: yellow">
   <source src="bogus.duh" type="video/durrrr;">
 </video>
 <iframe id="test-iframe" width="98"  height="98" style="border: 1px solid black"></iframe>
 <iframe id="test-video-in-iframe" src="video.ogg" width="98" height="98" style="border: 1px solid black"></iframe>
 <iframe id="test-image-in-iframe" src="ctxmenu-image.png" width="98" height="98" style="border: 1px solid black"></iframe>
 <textarea id="test-textarea">chssseesbbbie</textarea> <!-- a weird word which generates only one suggestion -->
--- a/browser/base/content/test/test_contextmenu.html
+++ b/browser/base/content/test/test_contextmenu.html
@@ -364,20 +364,35 @@ function runTest(testNum) {
                           "context-viewvideo",          true,
                           "context-copyvideourl",       true,
                           "---",                        null,
                           "context-savevideo",          true,
                           "context-video-saveimage",    true,
                           "context-sendvideo",          true
                          ].concat(inspectItems));
         closeContextMenu();
+        openContextMenuFor(audio_in_video); // Invoke context menu for next test.
+        break;
+
+    case 9:
+        // Context menu for a video (with an audio-only file)
+          checkContextMenu(["context-media-play",         true,
+                            "context-media-mute",         true,
+                            "context-media-showcontrols", true,
+                            "---",                        null,
+                            "context-copyaudiourl",       true,
+                            "---",                        null,
+                            "context-saveaudio",          true,
+                            "context-sendaudio",          true
+                           ].concat(inspectItems));
+        closeContextMenu();
         openContextMenuFor(video_bad); // Invoke context menu for next test.
         break;
 
-    case 9:
+    case 10:
         // Context menu for a video (with an INVALID media source)
         checkContextMenu(["context-media-play",         false,
                           "context-media-mute",         false,
                           "context-media-hidecontrols", false,
                           "context-video-showstats",    false,
                           "context-video-fullscreen",   false,
                           "---",                        null,
                           "context-viewvideo",          true,
@@ -386,17 +401,17 @@ function runTest(testNum) {
                           "context-savevideo",          true,
                           "context-video-saveimage",    false,
                           "context-sendvideo",          true
                          ].concat(inspectItems));
         closeContextMenu();
         openContextMenuFor(video_bad2); // Invoke context menu for next test.
         break;
 
-    case 10:
+    case 11:
         // Context menu for a video (with an INVALID media source)
         checkContextMenu(["context-media-play",         false,
                           "context-media-mute",         false,
                           "context-media-hidecontrols", false,
                           "context-video-showstats",    false,
                           "context-video-fullscreen",   false,
                           "---",                        null,
                           "context-viewvideo",          false,
@@ -405,17 +420,17 @@ function runTest(testNum) {
                           "context-savevideo",          false,
                           "context-video-saveimage",    false,
                           "context-sendvideo",          false
                          ].concat(inspectItems));
         closeContextMenu();
         openContextMenuFor(iframe); // Invoke context menu for next test.
         break;
 
-    case 11:
+    case 12:
         // Context menu for an iframe
         checkContextMenu(["context-back",         false,
                           "context-forward",      false,
                           "context-reload",       true,
                           "context-stop",         false,
                           "---",                  null,
                           "context-bookmarkpage", true,
                           "context-savepage",     true,
@@ -440,17 +455,17 @@ function runTest(testNum) {
                           "---",                  null,
                           "context-viewsource",   true,
                           "context-viewinfo",     true
                          ].concat(inspectItems));
         closeContextMenu();
         openContextMenuFor(video_in_iframe); // Invoke context menu for next test.
         break;
 
-    case 12:
+    case 13:
         // Context menu for a video in an iframe
         checkContextMenu(["context-media-play",         true,
                           "context-media-mute",         true,
                           "context-media-hidecontrols", true,
                           "context-video-showstats",    true,
                           "context-video-fullscreen",   true,
                           "---",                        null,
                           "context-viewvideo",          true,
@@ -471,17 +486,17 @@ function runTest(testNum) {
                                "---",                       null,
                                "context-printframe",        true,
                                "---",                       null,
                                "context-viewframeinfo",     true], null].concat(inspectItems));
         closeContextMenu();
         openContextMenuFor(image_in_iframe); // Invoke context menu for next test.
         break;
 
-    case 13:
+    case 14:
         // Context menu for an image in an iframe
         checkContextMenu(["context-viewimage",            true,
                           "context-copyimage-contents",   true,
                           "context-copyimage",            true,
                           "---",                          null,
                           "context-saveimage",            true,
                           "context-sendimage",            true,
                           "context-setDesktopBackground", true,
@@ -498,17 +513,17 @@ function runTest(testNum) {
                                "---",                       null,
                                "context-printframe",        true,
                                "---",                       null,
                                "context-viewframeinfo",     true], null].concat(inspectItems));
         closeContextMenu();
         openContextMenuFor(textarea, false, true); // Invoke context menu for next test, but wait for the spellcheck.
         break;
 
-    case 14:
+    case 15:
         // Context menu for textarea
         checkContextMenu(["*chubbiness",         true, // spelling suggestion
                           "spell-add-to-dictionary", true,
                           "---",                 null,
                           "context-undo",        false,
                           "---",                 null,
                           "context-cut",         false,
                           "context-copy",        false,
@@ -523,24 +538,24 @@ function runTest(testNum) {
                                "---",                          null,
                                "spell-add-dictionaries",       true], null
                          ].concat(inspectItems));
         contextMenu.ownerDocument.getElementById("spell-add-to-dictionary").doCommand(); // Add to dictionary
         closeContextMenu();
         openContextMenuFor(text); // Invoke context menu for next test.
         break;
 
-    case 15:
+    case 16:
         // Re-check context menu for plain text to make sure it hasn't changed
         checkContextMenu(plainTextItems);
         closeContextMenu();
         openContextMenuFor(textarea, false, true); // Invoke context menu for next test.
         break;
 
-    case 16:
+    case 17:
         // Context menu for textarea after a word has been added
         // to the dictionary
         checkContextMenu(["spell-undo-add-to-dictionary", true,
                           "---",                 null,
                           "context-undo",        false,
                           "---",                 null,
                           "context-cut",         false,
                           "context-copy",        false,
@@ -555,17 +570,17 @@ function runTest(testNum) {
                                "---",                          null,
                                "spell-add-dictionaries",       true], null
                          ].concat(inspectItems));
         contextMenu.ownerDocument.getElementById("spell-undo-add-to-dictionary").doCommand(); // Undo add to dictionary
         closeContextMenu();
         openContextMenuFor(contenteditable);
         break;
 
-    case 17:
+    case 18:
         // Context menu for contenteditable
         checkContextMenu(["spell-no-suggestions", false,
                           "spell-add-to-dictionary", true,
                           "---",                 null,
                           "context-undo",        false,
                           "---",                 null,
                           "context-cut",         false,
                           "context-copy",        false,
@@ -580,17 +595,17 @@ function runTest(testNum) {
                                "---",                          null,
                                "spell-add-dictionaries",       true], null
                          ].concat(inspectItems));
 
         closeContextMenu();
         openContextMenuFor(inputspell); // Invoke context menu for next test.
         break;
 
-    case 18:
+    case 19:
         // Context menu for spell-check input
         checkContextMenu(["*prodigality",        true, // spelling suggestion
                           "spell-add-to-dictionary", true,
                           "---",                 null,
                           "context-undo",        false,
                           "---",                 null,
                           "context-cut",         false,
                           "context-copy",        false,
@@ -605,23 +620,23 @@ function runTest(testNum) {
                                "---",                          null,
                                "spell-add-dictionaries",       true], null
                          ].concat(inspectItems));
 
         closeContextMenu();
         openContextMenuFor(link); // Invoke context menu for next test.
         break;
 
-    case 19:
+    case 20:
         executeCopyCommand("cmd_copyLink", "http://mozilla.com/");
         closeContextMenu();
         openContextMenuFor(pagemenu); // Invoke context menu for next test.
         break;
 
-    case 20:
+    case 21:
         // Context menu for element with assigned content context menu
         checkContextMenu(["+Plain item",          {type: "", icon: "", checked: false, disabled: false},
                           "+Disabled item",       {type: "", icon: "", checked: false, disabled: true},
                           "+Item w/ textContent", {type: "", icon: "", checked: false, disabled: false},
                           "---",                  null,
                           "+Checkbox",            {type: "checkbox", icon: "", checked: true, disabled: false},
                           "---",                  null,
                           "+Radio1",              {type: "checkbox", icon: "", checked: true, disabled: false},
@@ -654,17 +669,17 @@ function runTest(testNum) {
                           "context-viewinfo",     true
                          ].concat(inspectItems));
 
         invokeItemAction("0");
         closeContextMenu();
         openContextMenuFor(pagemenu, true); // Invoke context menu for next test.
         break;
 
-    case 21:
+    case 22:
         // Context menu for element with assigned content context menu
         // The shift key should bypass content context menu processing
         checkContextMenu(["context-back",         false,
                           "context-forward",      false,
                           "context-reload",       true,
                           "context-stop",         false,
                           "---",                  null,
                           "context-bookmarkpage", true,
@@ -677,33 +692,33 @@ function runTest(testNum) {
                           "context-viewsource",   true,
                           "context-viewinfo",     true
                          ].concat(inspectItems));
         closeContextMenu();
         selectText(selecttext); // Select text prior to opening context menu.
         openContextMenuFor(selecttext); // Invoke context menu for next test.
         return;
 
-    case 22:
+    case 23:
         // Context menu for selected text
         if (Services.appinfo.OS == "Darwin") {
           // This test is only enabled on Mac due to bug 736399.
           checkContextMenu(["context-copy",                        true,
                             "context-selectall",                   true,
                             "---",                                 null,
                             "context-searchselect",                true,
                             "context-viewpartialsource-selection", true
                            ].concat(inspectItems));
         }
         closeContextMenu();
         selectText(selecttextlink); // Select text prior to opening context menu.
         openContextMenuFor(selecttextlink); // Invoke context menu for next test.
         return;
 
-    case 23:
+    case 24:
         // Context menu for selected text which matches valid URL pattern
         if (Services.appinfo.OS == "Darwin") {
           // This test is only enabled on Mac due to bug 736399.
           checkContextMenu(["context-openlinkincurrent",           true,
                             "context-openlinkintab",               true,
                             "context-openlink",                    true,
                             "---",                                 null,
                             "context-bookmarklink",                true,
@@ -737,17 +752,18 @@ function runTest(testNum) {
   }
 
 }
 
 
 var testNum = 1;
 var subwindow, chromeWin, contextMenu, lastElement;
 var text, link, mailto, input, img, canvas, video_ok, video_bad, video_bad2,
-    iframe, video_in_iframe, image_in_iframe, textarea, contenteditable, inputspell, pagemenu, plainTextItems;
+    iframe, video_in_iframe, image_in_iframe, textarea, contenteditable,
+    inputspell, pagemenu, plainTextItems, audio_in_video;
 
 function startTest() {
     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
     chromeWin = subwindow
                     .QueryInterface(Ci.nsIInterfaceRequestor)
                     .getInterface(Ci.nsIWebNavigation)
                     .QueryInterface(Ci.nsIDocShellTreeItem)
                     .rootTreeItem
@@ -767,16 +783,17 @@ function startTest() {
 
     text   = subwindow.document.getElementById("test-text");
     link   = subwindow.document.getElementById("test-link");
     mailto = subwindow.document.getElementById("test-mailto");
     input  = subwindow.document.getElementById("test-input");
     img    = subwindow.document.getElementById("test-image");
     canvas = subwindow.document.getElementById("test-canvas");
     video_ok   = subwindow.document.getElementById("test-video-ok");
+    audio_in_video = subwindow.document.getElementById("test-audio-in-video");
     video_bad  = subwindow.document.getElementById("test-video-bad");
     video_bad2 = subwindow.document.getElementById("test-video-bad2");
     iframe = subwindow.document.getElementById("test-iframe");
     video_in_iframe = subwindow.document.getElementById("test-video-in-iframe").contentDocument.getElementsByTagName("video")[0];
     video_in_iframe.pause();
     image_in_iframe = subwindow.document.getElementById("test-image-in-iframe").contentDocument.getElementsByTagName("img")[0];
     textarea = subwindow.document.getElementById("test-textarea");
     contenteditable = subwindow.document.getElementById("test-contenteditable");
--- a/browser/components/feeds/src/nsFeedSniffer.cpp
+++ b/browser/components/feeds/src/nsFeedSniffer.cpp
@@ -308,31 +308,33 @@ nsFeedSniffer::GetMIMETypeFromContent(ns
     return NS_OK;
   }
 
   // Now we need to potentially decompress data served with 
   // Content-Encoding: gzip
   nsresult rv = ConvertEncodedData(request, data, length);
   if (NS_FAILED(rv))
     return rv;
-  
-  const char* testData = 
-    mDecodedData.IsEmpty() ? (const char*)data : mDecodedData.get();
+
+  // We cap the number of bytes to scan at MAX_BYTES to prevent picking up 
+  // false positives by accidentally reading document content, e.g. a "how to
+  // make a feed" page.
+  const char* testData;
+  if (mDecodedData.IsEmpty()) {
+    testData = (const char*)data;
+    length = NS_MIN(length, MAX_BYTES);
+  } else {
+    testData = mDecodedData.get();
+    length = NS_MIN(mDecodedData.Length(), MAX_BYTES);
+  }
 
   // The strategy here is based on that described in:
   // http://blogs.msdn.com/rssteam/articles/PublishersGuide.aspx
   // for interoperarbility purposes.
 
-  // We cap the number of bytes to scan at MAX_BYTES to prevent picking up 
-  // false positives by accidentally reading document content, e.g. a "how to
-  // make a feed" page.
-  if (!mDecodedData.IsEmpty()) {
-    length = NS_MIN(mDecodedData.Length(), MAX_BYTES);
-  }
-
   // Thus begins the actual sniffing.
   nsDependentCSubstring dataString((const char*)testData, length);
 
   bool isFeed = false;
 
   // RSS 0.91/0.92/2.0
   isFeed = ContainsTopLevelSubstring(dataString, "<rss");
 
--- a/browser/components/feeds/test/Makefile.in
+++ b/browser/components/feeds/test/Makefile.in
@@ -53,12 +53,14 @@ include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES =	bug408328-data.xml \
 		bug368464-data.xml \
 		test_bug494328.html \
 		bug494328-data.xml \
 		test_bug589543.html \
 		bug589543-data.xml \
 		test_registerHandler.html \
+		valid-feed.xml \
+		valid-unsniffable-feed.xml \
 		$(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
--- a/browser/components/feeds/test/chrome/Makefile.in
+++ b/browser/components/feeds/test/chrome/Makefile.in
@@ -48,16 +48,17 @@ include $(topsrcdir)/config/rules.mk
 _HTTP_FILES	= \
 		sample_feed.atom \
 		$(NULL)
 
 _CHROME_FILES	= \
 		test_423060.xul \
 		test_bug368464.html \
 		test_bug408328.html \
+		test_maxSniffing.html \
 		$(NULL)
 
 libs:: $(_HTTP_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
 
copy from browser/components/feeds/test/chrome/test_bug368464.html
copy to browser/components/feeds/test/chrome/test_maxSniffing.html
--- a/browser/components/feeds/test/chrome/test_bug368464.html
+++ b/browser/components/feeds/test/chrome/test_maxSniffing.html
@@ -1,32 +1,37 @@
 <!DOCTYPE HTML>
 <html>
 <!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=368464
+https://bugzilla.mozilla.org/show_bug.cgi?id=739040
 -->
 <head>
-  <title>Test that RSS 0.90 isn't sniffed</title>
+  <title>Test that we only sniff 512 bytes</title>
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
 </head>
 <body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=368464">Mozilla Bug 368464</a>
-<p id="display"><iframe id="testFrame" src="http://mochi.test:8888/tests/browser/components/feeds/test/bug368464-data.xml"></iframe></p>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=739040">Mozilla Bug 739040</a>
+<p id="display">
+  <iframe id="validTestFrame" src="http://mochi.test:8888/tests/browser/components/feeds/test/valid-feed.xml"></iframe>
+  <iframe id="unsniffableTestFrame" src="http://mochi.test:8888/tests/browser/components/feeds/test/valid-unsniffable-feed.xml"></iframe>
+</p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
-/** Test for Bug 368464 **/
+/** Test for Bug 739040 **/
 SimpleTest.waitForExplicitFinish();
 
 addLoadEvent(function() {
-  ok($("testFrame").contentDocument.documentElement.id != "feedHandler",
-     "RSS 0.90 shouldn't be sniffed as a feed");
+  is($("validTestFrame").contentDocument.documentElement.id, "feedHandler",
+     "valid feed should be sniffed");
+  isnot($("unsniffableTestFrame").contentDocument.documentElement.id, "feedHandler",
+        "unsniffable feed should not be sniffed");
 });
 addLoadEvent(SimpleTest.finish);
 
 </script>
 </pre>
 </body>
 </html>
copy from browser/components/feeds/test/bug589543-data.xml
copy to browser/components/feeds/test/valid-feed.xml
copy from browser/components/feeds/test/bug589543-data.xml
copy to browser/components/feeds/test/valid-unsniffable-feed.xml
--- a/browser/components/feeds/test/bug589543-data.xml
+++ b/browser/components/feeds/test/valid-unsniffable-feed.xml
@@ -1,9 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!-- 512 bytes!
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+  -->
 <feed xmlns="http://www.w3.org/2005/Atom">
 
   <title>Example Feed</title>
   <link href="http://example.org/"/>
   <updated>2010-08-22T18:30:02Z</updated>
 
   <author>
     <name>John Doe</name>
--- a/browser/components/migration/content/migration.js
+++ b/browser/components/migration/content/migration.js
@@ -13,17 +13,16 @@ Cu.import("resource:///modules/Migration
 
 var MigrationWizard = {
   _source: "",                  // Source Profile Migrator ContractID suffix
   _itemsFlags: kIMig.ALL,       // Selected Import Data Sources (16-bit bitfield)
   _selectedProfile: null,       // Selected Profile name to import from
   _wiz: null,
   _migrator: null,
   _autoMigrate: null,
-  _bookmarks: false,
 
   init: function ()
   {
     var os = Components.classes["@mozilla.org/observer-service;1"]
                        .getService(Components.interfaces.nsIObserverService);
     os.addObserver(this, "Migration:Started", false);
     os.addObserver(this, "Migration:ItemBeforeMigrate", false);
     os.addObserver(this, "Migration:ItemAfterMigrate", false);
@@ -59,44 +58,25 @@ var MigrationWizard = {
     os.removeObserver(this, "Migration:ItemError");
     os.removeObserver(this, "Migration:Ended");
     MigrationUtils.finishMigration();
   },
 
   // 1 - Import Source
   onImportSourcePageShow: function ()
   {
-    // Reference to the "From File" radio button 
-    var fromfile = null;
-
-    // init is not called when openDialog opens the wizard, so check for bookmarks here.
-    if ("arguments" in window && window.arguments[0] == "bookmarks") {
-      this._bookmarks = true;
-
-      fromfile = document.getElementById("fromfile");
-      fromfile.hidden = false;
-
-      var importBookmarks = document.getElementById("importBookmarks");
-      importBookmarks.hidden = false;
-
-      var importAll = document.getElementById("importAll");
-      importAll.hidden = true;
-    }
-
     this._wiz.canRewind = false;
 
-    // The migrator to select. If the "fromfile" migrator is available, use it
-    // as the default in case we have no other migrators.
-    var selectedMigrator = fromfile;
+    var selectedMigrator = null;
 
     // Figure out what source apps are are available to import from:
     var group = document.getElementById("importSourceGroup");
     for (var i = 0; i < group.childNodes.length; ++i) {
       var migratorKey = group.childNodes[i].id;
-      if (migratorKey != "nothing" && migratorKey != "fromfile") {
+      if (migratorKey != "nothing") {
         var migrator = MigrationUtils.getMigrator(migratorKey);
         if (migrator) {
           // Save this as the first selectable item, if we don't already have
           // one, or if it is the migrator that was passed to us.
           if (!selectedMigrator || this._source == migratorKey)
             selectedMigrator = group.childNodes[i];
         } else {
           // Hide this option
@@ -123,19 +103,17 @@ var MigrationWizard = {
       this._wiz.canRewind = false;
     }
   },
   
   onImportSourcePageAdvanced: function ()
   {
     var newSource = document.getElementById("importSourceGroup").selectedItem.id;
     
-    if (newSource == "nothing" || newSource == "fromfile") {
-      if(newSource == "fromfile")
-        window.opener.fromFile = true;
+    if (newSource == "nothing") {
       document.documentElement.cancel();
       return false;
     }
     
     if (!this._migrator || (newSource != this._source)) {
       // Create the migrator for the selected source.
       this._migrator = MigrationUtils.getMigrator(newSource);
 
@@ -147,18 +125,16 @@ var MigrationWizard = {
     // check for more than one source profile
     var sourceProfiles = this._migrator.sourceProfiles;    
     if (sourceProfiles && sourceProfiles.length > 1) {
       this._wiz.currentPage.next = "selectProfile";
     }
     else {
       if (this._autoMigrate)
         this._wiz.currentPage.next = "homePageImport";
-      else if (this._bookmarks)
-        this._wiz.currentPage.next = "migrating"
       else
         this._wiz.currentPage.next = "importItems";
 
       if (sourceProfiles && sourceProfiles.length == 1)
         this._selectedProfile = sourceProfiles[0];
       else
         this._selectedProfile = "";
     }
@@ -200,18 +176,16 @@ var MigrationWizard = {
   onSelectProfilePageAdvanced: function ()
   {
     var profiles = document.getElementById("profiles");
     this._selectedProfile = profiles.selectedItem.id;
     
     // If we're automigrating or just doing bookmarks don't show the item selection page
     if (this._autoMigrate)
       this._wiz.currentPage.next = "homePageImport";
-    else if (this._bookmarks)
-      this._wiz.currentPage.next = "migrating"
   },
   
   // 3 - ImportItems
   onImportItemsPageShow: function ()
   {
     var dataSources = document.getElementById("dataSources");
     while (dataSources.hasChildNodes())
       dataSources.removeChild(dataSources.firstChild);
@@ -347,20 +321,16 @@ var MigrationWizard = {
     this._wiz.getButton("cancel").disabled = true;
     this._wiz.canRewind = false;
     this._wiz.canAdvance = false;
     
     // When automigrating, show all of the data that can be received from this source.
     if (this._autoMigrate)
       this._itemsFlags = this._migrator.getMigrateData(this._selectedProfile, this._autoMigrate);
 
-    // When importing bookmarks, show only bookmarks
-    if (this._bookmarks)
-      this._itemsFlags = 32;
-
     this._listItems("migratingItems");
     setTimeout(this.onMigratingMigrate, 0, this);
   },
 
   onMigratingMigrate: function (aOuter)
   {
     aOuter._migrator.migrate(aOuter._itemsFlags, aOuter._autoMigrate, aOuter._selectedProfile);
   },
--- a/browser/components/migration/content/migration.xul
+++ b/browser/components/migration/content/migration.xul
@@ -66,17 +66,16 @@
     <radiogroup id="importSourceGroup" align="start">
       <!-- If you are adding a migrator, please add the appropriate
            hooks to GetDefaultBrowserMigratorKey in
            browser/components/migration/src/nsProfileMigrator.cpp -->
       <radio id="safari"    label="&importFromSafari.label;"    accesskey="&importFromSafari.accesskey;"/>
       <radio id="ie"        label="&importFromIE.label;"        accesskey="&importFromIE.accesskey;"/>
       <radio id="chrome"    label="&importFromChrome.label;"    accesskey="&importFromChrome.accesskey;"/>
       <radio id="firefox"   label="&importFromFirefox.label;"   accesskey="&importFromFirefox.accesskey;"/>
-      <radio id="fromfile"  label="&importFromHTMLFile.label;"  accesskey="&importFromHTMLFile.accesskey;" hidden="true"/>
       <radio id="nothing"   label="&importFromNothing.label;"   accesskey="&importFromNothing.accesskey;" hidden="true"/>
     </radiogroup>
     <label id="noSources" hidden="true">&noMigrationSources.label;</label>
   </wizardpage>
 
   <wizardpage id="selectProfile" pageid="selectProfile" label="&selectProfile.title;"
               next="importItems"
               onpageshow="return MigrationWizard.onSelectProfilePageShow();"
--- a/browser/config/version.txt
+++ b/browser/config/version.txt
@@ -1,1 +1,1 @@
-14.0a1
+15.0a1
--- a/browser/locales/en-US/chrome/browser/migration/migration.dtd
+++ b/browser/locales/en-US/chrome/browser/migration/migration.dtd
@@ -10,18 +10,16 @@
 <!ENTITY importFromNothing.label        "Don't import anything">
 <!ENTITY importFromNothing.accesskey    "D">
 <!ENTITY importFromSafari.label         "Safari">
 <!ENTITY importFromSafari.accesskey     "S">
 <!ENTITY importFromChrome.label         "Chrome">
 <!ENTITY importFromChrome.accesskey     "C">
 <!ENTITY importFromFirefox.label        "Firefox">
 <!ENTITY importFromFirefox.accesskey    "X">
-<!ENTITY importFromHTMLFile.label       "From an HTML File">
-<!ENTITY importFromHTMLFile.accesskey   "F">
 
 <!ENTITY noMigrationSources.label       "No programs that contain bookmarks, history or password data could be found.">
 
 <!ENTITY importSource.title             "Import Settings and Data">
 <!ENTITY importItems.title              "Items to Import">
 <!ENTITY importItems.label              "Select which items to import:">
 
 <!ENTITY migrating.title                "Importing…">
--- a/browser/modules/WebappsIconHelpers.js
+++ b/browser/modules/WebappsIconHelpers.js
@@ -100,10 +100,12 @@ function getIconForApp(aShell, callback)
   } catch(e) {
     throw("getIconFromURI - Failure getting icon (" + e + ")");
   }
 }
 
 function onIconDownloaded(aShell, aMimeType, aStatusCode, aIcon, aCallback) {
   if (Components.isSuccessCode(aStatusCode)) {
     aShell.processIcon(aMimeType, aIcon, aCallback);
+  } else {
+    aCallback.call(aShell);
   }
 }
--- a/browser/modules/WebappsInstaller.jsm
+++ b/browser/modules/WebappsInstaller.jsm
@@ -3,19 +3,19 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 let EXPORTED_SYMBOLS = ["WebappsInstaller"];
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
-Cu.import("resource:///modules/Services.jsm");
-Cu.import("resource:///modules/FileUtils.jsm");
-Cu.import("resource:///modules/NetUtil.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
 
 let WebappsInstaller = {
   /**
    * Creates a native installation of the web app in the OS
    *
    * @param aData the manifest data provided by the web app
    *
    * @returns bool true on success, false if an error was thrown
@@ -490,17 +490,17 @@ MacNativeApp.prototype = {
       this._createDirectoryStructure();
       this._copyPrebuiltFiles();
       this._createConfigFiles();
     } catch (ex) {
       this._removeInstallation(false);
       throw(ex);
     }
 
-    getIconForApp(this);
+    getIconForApp(this, this._createPListFile);
   },
 
   _removeInstallation: function(keepProfile) {
     try {
       if(this.installDir.exists()) {
         this.installDir.followLinks = false;
         this.installDir.remove(true);
       }
@@ -531,20 +531,20 @@ MacNativeApp.prototype = {
 
   _copyPrebuiltFiles: function() {
     let webapprt = this.processFolder.clone();
     webapprt.append("webapprt-stub");
     webapprt.copyTo(this.macOSDir, "webapprt");
   },
 
   _createConfigFiles: function() {
-    // ${ProfileDir}/config.json
+    // ${ProfileDir}/webapp.json
     let json = {
+      "registryDir": this.profileFolder.path,
       "app": {
-        "profile": this.profileFolder.path,
         "origin": this.launchURI.prePath,
         "installOrigin": "apps.mozillalabs.com",
         "manifest": this.manifest
        }
     };
 
     let configJson = this.appProfileDir.clone();
     configJson.append("webapp.json");
@@ -556,17 +556,20 @@ MacNativeApp.prototype = {
 
     let factory = Cc["@mozilla.org/xpcom/ini-processor-factory;1"]
                     .getService(Ci.nsIINIParserFactory);
 
     let writer = factory.createINIParser(applicationINI).QueryInterface(Ci.nsIINIParserWriter);
     writer.setString("Webapp", "Name", this.appName);
     writer.setString("Webapp", "Profile", this.appProfileDir.leafName);
     writer.writeFile();
+  },
 
+  _createPListFile: function() {
+    // ${InstallDir}/Contents/Info.plist
     let infoPListContent = '<?xml version="1.0" encoding="UTF-8"?>\n\
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n\
 <plist version="1.0">\n\
   <dict>\n\
     <key>CFBundleDevelopmentRegion</key>\n\
     <string>English</string>\n\
     <key>CFBundleDisplayName</key>\n\
     <string>' + escapeXML(this.appName) + '</string>\n\
@@ -611,33 +614,35 @@ MacNativeApp.prototype = {
    * the URL by getIconForApp(). This will bundle the icon to the
    * app package at Contents/Resources/appicon.icns.
    *
    * @param aMimeType     the icon mimetype
    * @param aImageStream  the stream for the image data
    * @param aCallback     a callback function to be called
    *                      after the process finishes
    */
-  processIcon: function(aMimeType, aIcon) {
+  processIcon: function(aMimeType, aIcon, aCallback) {
     try {
       let process = Cc["@mozilla.org/process/util;1"]
                     .createInstance(Ci.nsIProcess);
       let sipsFile = Cc["@mozilla.org/file/local;1"]
                     .createInstance(Ci.nsILocalFile);
       sipsFile.initWithPath("/usr/bin/sips");
 
       process.init(sipsFile);
       process.run(true, ["-s",
                   "format", "icns",
                   aIcon.path,
                   "--out", this.iconFile.path,
                   "-z", "128", "128"],
                   9);
     } catch(e) {
       throw(e);
+    } finally {
+      aCallback.call(this);
     }
   }
 
 }
 
 #endif
 
 /* Helper Functions */
--- a/browser/modules/webappsUI.jsm
+++ b/browser/modules/webappsUI.jsm
@@ -6,17 +6,17 @@ let EXPORTED_SYMBOLS = ["webappsUI"];
 
 let Ci = Components.interfaces;
 let Cc = Components.classes;
 let Cu = Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Webapps.jsm");
-Cu.import("resource://gre/modules/WebappsInstaller.jsm");
+Cu.import("resource:///modules/WebappsInstaller.jsm");
 
 let webappsUI = {
   init: function webappsUI_init() {
     Services.obs.addObserver(this, "webapps-ask-install", false);
     Services.obs.addObserver(this, "webapps-launch", false);
   },
   
   uninit: function webappsUI_uninit() {
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -945,16 +945,20 @@ toolbar[iconsize="small"] #feed-button {
   padding: 0;
 }
 
 .urlbar-textbox-container {
   -moz-appearance: none;
   -moz-box-align: stretch;
 }
 
+.urlbar-input-box {
+  -moz-margin-start: 0;
+}
+
 .urlbar-history-dropmarker {
   -moz-appearance: toolbarbutton-dropdown;
 }
 
 #urlbar-container {
   -moz-box-orient: horizontal;
   -moz-box-align: stretch;
 }
@@ -1018,39 +1022,55 @@ toolbar[iconsize="small"] #feed-button {
   margin-bottom: -1px;
   -moz-border-end: 1px solid #AAA;
   -moz-margin-end: 3px;
 }
 
 #urlbar-display {
   margin-top: 0;
   margin-bottom: 0;
+  -moz-margin-start: 0;
   color: GrayText;
 }
 
 /* Favicon */
 #page-proxy-favicon {
   width: 16px;
   height: 16px;
-  margin: 2px 4px;
-}
-
-#page-proxy-favicon:not([src]) {
-  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
+  margin-top: 2px;
+  margin-bottom: 2px;
+  -moz-margin-start: 4px;
+  -moz-margin-end: 3px;
+  list-style-image: url(chrome://browser/skin/identity-icons-generic.png);
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}
+
+.verifiedDomain > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  list-style-image: url(chrome://browser/skin/identity-icons-https.png);
+}
+
+.verifiedIdentity > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  list-style-image: url(chrome://browser/skin/identity-icons-https-ev.png);
+}
+
+#identity-box:hover > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  -moz-image-region: rect(0, 32px, 16px, 16px);
+}
+
+#identity-box:hover:active > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon,
+#identity-box[open=true] > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  -moz-image-region: rect(0, 48px, 16px, 32px);
 }
 
 #page-proxy-favicon[pageproxystate="invalid"] {
   opacity: 0.3;
 }
 
 /* Identity indicator */
 #identity-box {
-  background-image: -moz-linear-gradient(hsl(0,0%,98%), hsl(0,0%,92%));
-  box-shadow: 0 1px 0 hsla(0,0%,0%,.05) inset;
-  -moz-border-end: 1px solid rgba(0,0,0,.1);
   padding: 1px;
   margin: -1px;
   -moz-margin-end: 0;
 }
 
 #identity-box:-moz-locale-dir(ltr) {
   border-top-left-radius: 2.5px;
   border-bottom-left-radius: 2.5px;
@@ -1061,54 +1081,26 @@ toolbar[iconsize="small"] #feed-button {
   border-bottom-right-radius: 2.5px;
 }
 
 #identity-box:-moz-focusring {
   outline: 1px dotted #000;
   outline-offset: -3px;
 }
 
-#identity-box:hover:active,
-#identity-box[open="true"] {
-  background-image: -moz-linear-gradient(hsl(0,0%,92%), hsl(0,0%,82%));
-  box-shadow: 0 1px 1px hsla(0,0%,0%,.3) inset,
-              0 1px 3px hsla(0,0%,0%,.3) inset;
-}
-
 #identity-icon-labels {
   -moz-padding-start: 2px;
   -moz-padding-end: 5px;
 }
 
-#identity-box.verifiedDomain {
-  background-image: -moz-linear-gradient(hsl(215,60%,92%), hsl(215,58%,88%));
-  box-shadow: 0 1px 0 hsla(215,54%,33%,.05) inset;
-  -moz-border-end-color: hsla(215,54%,33%,.2);
-  color: hsl(215,54%,33%);
-}
-
-#identity-box.verifiedDomain:hover:active,
-#identity-box.verifiedDomain[open="true"] {
-  background-image: -moz-linear-gradient(hsl(215,80%,80%), hsl(215,67%,65%));
-  box-shadow: 0 1px 1px hsla(215,54%,33%,.7) inset,
-              0 1px 3px 1px hsla(215,54%,33%,.5) inset;
-}
-
 #identity-box.verifiedIdentity {
-  background-image: -moz-linear-gradient(hsl(91,70%,90%), hsl(93,60%,81%));
-  box-shadow: 0 1px 0 hsla(92,81%,16%,.05) inset;
-  -moz-border-end-color: hsla(92,81%,16%,.2);
+  background-color: #fff;
   color: hsl(92,81%,16%);
-}
-
-#identity-box.verifiedIdentity:hover:active,
-#identity-box.verifiedIdentity[open="true"] {
-  background-image: -moz-linear-gradient(hsl(92,65%,70%), hsl(92,40%,48%));
-  box-shadow: 0 1px 1px hsla(92,81%,16%,.6) inset,
-              0 1px 3px 1px hsla(92,81%,16%,.5) inset;
+  -moz-border-end: 1px solid hsla(92,81%,16%,.2);
+  -moz-margin-end: 4px;
 }
 
 /* Identity popup icons */
 #identity-popup-icon {
   height: 64px;
   width: 64px;
   padding: 0;
   list-style-image: url("chrome://browser/skin/identity.png");
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a39e493c1eb1eaacc6b40c32fb6eebe683021b3f
GIT binary patch
literal 965
zc$@*n13LVPP)<h;3K|Lk000e1NJLTq001xm000mO1ONa4`lmEH0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#XGugsR5;6()JurfWf;ft&;QKDGv}PS
zo|!R^V`}OcNl_L-yKvDWrOV2}Y$49HC{U=NpcV>6Ar%z3$&p%kgOCbJp+JHn5Nu_X
z_e-8^@;Eo0IWx|g^S&)+yo@V*S1&y8_xbU>JbV-PbS|f4v}@CV2}7<b7s9=e$<52R
zi@a)`WjO15JD<OFNBesBmDgO~e4{(Gks6wJs&RMbh=Ib??Khv?#lL=OPQW+olieNJ
zw6saheiz5}zHs1H`z3>KU3<B?u3o(<Sr@1@?a6=W!p(?}*C)FdXR~s~boxmg*ZanS
zTLEA9r1w3ZG&rLu%DbXgHO37u9^i6H*WkADrj_O?Dv6qms8QAOMSh!NA@EU8cHgr}
zqhn487P_cjCB_YJ9w5cRuDI*Tq)pl~Eh+{CwU#EK|6ms~<uxNOJ*ZKgf}E;hQH_F;
zjpa2m?C6TSo=XaHR-13ic|pC$lF+}Sixgo?Ypzjn&5s5IK`<sE8@8f-xGz_q6_x#F
zXtq8f5$cBfbP%@`a_xdaU%DWQqER(c*|>EkU|o}c{plCevv?5vW3{jr`N{6AAr~E2
zoyDVQP`Al$ZG?60&iU0>DtGW_JR_{7mat;LB@=U&D{Hw%p&JcTZG*13F{hrkP{veV
z198O#r(B;?Z}x<|*gZ2rWyH83NC_Hb1P_?6B2+*aHz|rzqO`QApjDMBgi6V%AgC2I
zX%;+ci7BBnGr>8lSgKjhNiB+k8Y4==Sxh9u)eaWO%J@r8Nl;_Vh-BErP5xmWS{>Et
zl%UoXmxQx30f($Act{G5IBp!rbQ<6=2GggmcjPUW!ZPPf;)GU18c!P}9<pkgr_|tS
zKf8_}EOws5Ghg&s7%M6Yg0xO)L1I)G51-;{TYsD?DG7o)E$Rh~iIuipuFmkMomN$q
zalf1(r8LW@*i;OCA^stVqJ^f-*KQ()-c3c6n~vo7Mi*!6?W)?en3CVqbVQl$#n>0)
z(b*kaZrT!ylw<7OUc9A>T|N5SvkO!WNJ*5&_4Vz)t%~B?rHxH>dBLER#Au~sZ`TL6
zRq<|*{)O44rkz(K@%OmC_x8_`-RFzEc1u>@+4;&{vKw7f+FV{a-Ae6n=48k2=DTF~
n&RzWbb7gnWy3U~de{}sH<r$SwqU;WP00000NkvXXu0mjfm%Y@7
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..91c5dcb8830e76799d9371f183b4f07a03675dbf
GIT binary patch
literal 900
zc$@)*1AF|5P)<h;3K|Lk000e1NJLTq001xm000mO1^@s6P_F#30009^Nkl<Zc-pPi
zTS!z<6b4|M$xaA5nOYr!7|oo@@{(gp7jt4DyO0{BrV`S{BB+olqR2u_OHH8*C>2CR
zM8p&Y1<?g^6ng5VNQmgM*N`suwpu^@0~_bkL3;RLxAwncuQU4`Q$%FO?tE*Fa;a36
zrZSbSyegl(tYtEj%AS-s+-k1MP+640n%m6c4F6+*S;pbB)DpE)m8nW9V{HjC#t^g2
z1F_~&xyrAq$<LaHndAeUc)E6(3ad#9qn2O*7oSch4_GuZQQtf?9vmMS4g3PEQNtcH
zne1_yPo4){(K}vq;NXpt_bo%qrvPizu*Zx$;Q*m0<v#UYiHS8|oB?L5bhTKm8lI@z
z+dmrk+5fg$OsHWG8D`Vjn*tmtw<l85-ZHrS_nrZtm{9AD)Eq(v*@OdhJo1N?sOQQC
zt_6E$mRG=1*{VRTABb#zcj--)Tpru}>DJeVF2EW!>>-0Jdo1G`d6a+uNb&o|z5>}d
zTr_d@LwzS;jT-ilK{nw4#~+qWDp9skvswFLW_bnD_(V(9w%*rOQ$4RX3J$LS4guDv
z>E0h?m|e_X7uncr>MNLPxVTKNeXK`+6JU*+4iW9Q(Gz!oqxaVcIH~h4W~e;1K{a>3
z*dTy|n~Zuhvw7@wD~rEM+wKeb0_<z2kWp__KJ>&4aO7@jM9Duyi~&;Be7;;;x?gVk
za{k$RNd_5Y*)!kx@>H}A7Jl8;l`qL4gDiSt1~`1XM4T`Nu+#!otZF--t`jGaMGt!|
zm7{|7=az~S$f74^fP*)S#Q}4GxoQ!=^Se(!t`sMbWslAO!&cjC&*q5}$f74^fc+z@
z#ewMq*wFz_h1ZG$i3ZrQ^GvQdfo$9X+ODq>2c{3OFnWbT56Z;>^9n6Ae}V0%yy8IO
zUtsT*LUCaFJCMy6GT3q7FHRuKo^0bC2y8p)6(^95`wp}Y6-Jc&!`QU1&^+Z;<)Md_
zpN`%0OEQ|7K$bo8jIU7fuJZ+-w}!lu3^K@?U!fV}H$06`a48QKRCTIRwNN8#L1dWC
zVXs?R##IdPitI447BH@!^*;u1sW~d02lDc2lqkQdAU|r{^D>*xUKd%)!#z8J9A>QO
aU*f;6c*m;N5KuP&0000<MNUMnLSTZ>&#CGF
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3a22f7e0195088708f3838376551b95a42e87f7e
GIT binary patch
literal 553
zc%17D@N?(olHy`uVBq!ia0vp^20$#p!3HD)*8SPYz`*#y)5S5Q;?~t`2eYCaC0HLc
z-PU1>z01zAy|P(slgE6e^B45IPKJp9!AC|H7D1N@jy)P0N{?I|@1`d@dWh#Wr(7&4
zt*YD6y8FX^<L;D+N7*0GoS(>dNBcW-L;2gQd{#1i|Chd)<Md00bFq%-**&?9yLa#A
zHY(|nIBCPRMB~QWvisX^zdf9_wMuZ)G@ox8PqhNphUuTUV3?%xS?j|4@6J_9M_eOc
zXcV05u6w@pzs_{;Bc5v2M$Vqo`CoPlh^H>x?6Cg2F^g27!XncX7F;c}&ptaC)%~^V
zZ}$HC|3yGXrl_rSSQ=yqQ^GBg+{eO|6zQ-a-MvwN&x_MZ8yWQfHSf3Qiu69VcfZl(
zkOeV%@|+?^HZ?e$KgV=8Pu%J3SElq5<N4<mckElbe&X$jI_1r`ESCmxI-M5gF0qpJ
zF4*AJ=zs0j@tZkqDn`nim!H!R>z?)?;VRSHGHJUhOyQSbirA%myCT`@#AtVgX>Ay{
z+!m(mlTWgM1%KAa$$eoun<gxGh3WA}2_U&Mh7Tyx>&6UZFTThDByZ-30Y$!6$;w?R
zPq2_V)clJt#YnQ^0{4|HQ}2Qu*Z;NtsIli`V^(>1CjVUAJS*k7e$h>b|3=rInd`~9
oYf*OVo7hutvg^+5&Hm5ub=6M8`svs10+RrPr>mdKI;Vst0MAtN5&!@I
--- a/browser/themes/gnomestripe/jar.mn
+++ b/browser/themes/gnomestripe/jar.mn
@@ -14,16 +14,19 @@ browser.jar:
 #endif
   skin/classic/browser/actionicon-tab.png
 * skin/classic/browser/browser.css                    (browser.css)
 * skin/classic/browser/engineManager.css              (engineManager.css)
   skin/classic/browser/Geolocation-16.png
   skin/classic/browser/Geolocation-64.png
   skin/classic/browser/Go-arrow.png
   skin/classic/browser/identity.png
+  skin/classic/browser/identity-icons-generic.png
+  skin/classic/browser/identity-icons-https.png
+  skin/classic/browser/identity-icons-https-ev.png
   skin/classic/browser/Info.png
   skin/classic/browser/KUI-close.png
   skin/classic/browser/monitor.png
   skin/classic/browser/monitor_16-10.png
 * skin/classic/browser/pageInfo.css
   skin/classic/browser/pageInfo.png
   skin/classic/browser/page-livemarks.png
   skin/classic/browser/Privacy-16.png
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -970,21 +970,21 @@ toolbar[mode="icons"] #zoom-in-button {
 
 @conditionalForwardWithUrlbar@ + #urlbar-container:-moz-locale-dir(rtl),
 @conditionalForwardWithUrlbar@ + #urlbar-container > #urlbar:-moz-locale-dir(rtl) {
   /* let pinstripe-urlbar-back-button-mask clip the urlbar's right side for RTL */
   -moz-transform: scaleX(-1);
 }
 
 #identity-box {
-  background-image: -moz-linear-gradient(hsl(0,0%,98%), hsl(0,0%,92%));
-  box-shadow: 0 1px 0 hsla(0,0%,0%,.05) inset;
-  -moz-border-end: 1px solid hsla(0,0%,0%,.1);
   -moz-margin-end: 3px;
-  padding: 1px 4px;
+  padding-top: 1px;
+  padding-bottom: 1px;
+  -moz-padding-start: 4px;
+  -moz-padding-end: 0;
 }
 
 #identity-box:-moz-locale-dir(ltr) {
   border-top-left-radius: 2px;
   border-bottom-left-radius: 2px;
 }
 
 #identity-box:-moz-locale-dir(rtl) {
@@ -1019,58 +1019,31 @@ toolbar[mode="icons"] #zoom-in-button {
 @conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(ltr) {
   padding-left: 10.01px;
 }
 
 @conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
   padding-right: 10.01px;
 }
 
-#identity-box:active:hover,
-#identity-box[open="true"] {
-  background-image: -moz-linear-gradient(hsl(0,0%,93%), hsl(0,0%,80%));
-  box-shadow: 0 1px 1px hsla(0,0%,0%,.3) inset,
-              0 1px 3px hsla(0,0%,0%,.3) inset;
-}
-
-#identity-box.verifiedDomain {
-  background-image: -moz-linear-gradient(hsl(215,60%,92%), hsl(215,58%,88%));
-  -moz-border-end-color: hsla(215,54%,33%,.2);
-  color: hsl(215,54%,33%);
-}
-
-#identity-box.verifiedDomain:active:hover,
-#identity-box.verifiedDomain[open="true"] {
-  background-image: -moz-linear-gradient(hsl(215,85%,85%), hsl(215,70%,68%));
-  box-shadow: 0 1px 1px hsla(215,54%,33%,.7) inset,
-              0 1px 3px 1px hsla(215,54%,33%,.5) inset;
-}
-
 #identity-box.verifiedIdentity {
-  background-image: -moz-linear-gradient(hsl(91,70%,90%), hsl(93,60%,81%));
-  -moz-border-end-color: hsla(92,81%,16%,.2);
   color: hsl(92,100%,20%);
-}
-
-#identity-box.verifiedIdentity:active:hover,
-#identity-box.verifiedIdentity[open="true"] {
-  background-image: -moz-linear-gradient(hsl(92,69%,77%), hsl(92,44%,51%));
-  box-shadow: 0 1px 1px hsla(92,81%,16%,.6) inset,
-              0 1px 3px 1px hsla(92,81%,16%,.5) inset;
+  -moz-border-end: 1px solid hsla(92,81%,16%,.2);
+  -moz-padding-end: 4px;
 }
 
 #identity-box:-moz-focusring {
   box-shadow: 0 0 2px 1px -moz-mac-focusring inset,
               0 0 2px 2px -moz-mac-focusring;
   -moz-border-end-style: none;
   -moz-padding-end: 5px;
 }
 
 #identity-icon-labels {
-  -moz-margin-start: 6px;
+  -moz-margin-start: 4px;
 }
 
 .urlbar-input-box {
   -moz-margin-start: 0;
   padding: 3px 0 2px;
 }
 
 .urlbar-history-dropmarker {
@@ -1107,20 +1080,31 @@ toolbar[mode="icons"] #zoom-in-button {
   height: 22px;
 }
 
 #page-proxy-favicon {
   width: 16px;
   height: 16px;
   margin: 0px;
   padding: 0px;
-}
-
-#page-proxy-favicon:not([src]) {
-  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
+  list-style-image: url(chrome://browser/skin/identity-icons-generic.png);
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}
+
+.verifiedDomain > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  list-style-image: url(chrome://browser/skin/identity-icons-https.png);
+}
+
+.verifiedIdentity > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  list-style-image: url(chrome://browser/skin/identity-icons-https-ev.png);
+}
+
+#identity-box:hover:active > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon,
+#identity-box[open=true] > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  -moz-image-region: rect(0, 32px, 16px, 16px);
 }
 
 #page-proxy-favicon[pageproxystate="invalid"] {
   opacity: 0.5;
 }
 
 #wrapper-urlbar-container[place="palette"] {
   max-width: 20em;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..51f48bca43bf7755cfdb97324237d3d92cd1ec38
GIT binary patch
literal 634
zc$@)x0)_pFP)<h;3K|Lk000e1NJLTq001BW000mO1ONa4-3hhQ0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!97#k$R5(wqlkacRKp4mG4}rgH^>2Yd
zU<j<Ejqw)>!3HZqL~J{!+cc3FH={4yqEz<6s4;VHnPXA8KpacIetSd&d}q8*j_dWq
z^|^bVR*3)Ayr`G+I^KYEyu25k_h!`0nH_ULI%eLS_wIrxpJN+c_V@7MN>`iq#)2tZ
zSjQ&&HcS}OnD&mg7963E9o)wXw%~Ad184G=f>sPZ;RKIx5f{)zfuj)=e*0GBUcZMk
zjPL``&{C}7HCnP23B4X!?(fr{;usC+ifecRUFyn<rrxGJMUM-c6W)Zg<<KwbHT)z8
zjJ!1AX*g3}G`g>_$A})E|A!5HM57z}Tz3PzXmi`SDJl$+Q(n|Z58$Fc!wOS*jQUyV
zv!m;{gzOAg7;qn1<wb2!!<YuU%bnEVLvqWtVdyi1494i}m$^8@M1SWFGs+9ww_&qD
z9o|~U3*6;w7oS-Z+Yf!(Pb1CBY~n3$V3kEo<0alPjcMgYRj=YPi}a0r;n}Oi9*-(X
zDLsW-IK)@-fp=465jVqeoJ1>P^)064M6ttzSX^)imb6rvl96OT$pRlL+AxsB`S4dJ
z$7K|vqE&+1Oj?f|F#`{Ilxk3!yhsTx5fqrT1G2{wT8zIKB&OfRvR0N3&%ed$J4|F*
zmd{OT5!d3f$j7d-9#>IBT*hZSTPa$~m;BO@_`I6`SVSxu%g6lKkodg%%l~ux1@oI3
U>BLSBRR91007*qoM6N<$g2&e>6aWAK
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..997157d6b1f04c7acdbbf2638cab22a88e5e9f72
GIT binary patch
literal 541
zc$@(p0^<FNP)<h;3K|Lk000e1NJLTq001BW000mO1^@s6cL04^0005xNkl<Zc-pPi
z%}X0m6a{ceDC5evC_!eI_>m~Fj;&F*2D(U%SQ5}Gh7$ZnkW!)uVq1jPBBJ02G}uLv
zF1nBu+J*nX)U6u}g)UsW6%o|k?YVFZ1DTgRFpD3&oH>ERFq6~~(Y+mB<h+7V4-N28
zG)NZocKN%t9`FDZL?8kEA|aXLPSpX6KYLrD1XrTOS(O1nP|&`9lA4-6=sF$WZo6fC
z=8UgNC#W4z_|X%COCT@FVig9|L*#>-ni=0}yBXVzkr!v{Zfcf0+|>?v{XJ0vf@847
zv1FwR0~91Ci_YnbjVMig>in~NmU+YY%o$(f4k+z_S4Z7fKwx_^Te54-fB@JqFuD=F
z9r@Twd%rVl_&mz^%o#@9aYwoV-vJBXo)9z5Wq<`y$Pd47A%=4SW<<f0=OG4G*?{@4
zk6oZDT%Q37`f^+G^Xys+Rl*(af+`y@_oa(W_zVca)6CmuGQnL4l?|Bw?2rM!0XC$c
zuQrhh?t)!5V6ym#4Cn?74y{DU1b2N0<o7$sfc6fgm&0U0e+ORf#L0l}8AuK+g~<eW
zeV>8ccH9N3;+N(vaI){Bf1ee?R0(&u3#yiXMiw-J14&53pqFGxaHMP1azH>vC<uYA
f5t5Ge|CjI|Z2i9#R<I1@00000NkvXXu0mjf+^FzJ
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..71fe2aefd41a64289c8f7835feaa401e9fec9fb0
GIT binary patch
literal 306
zc$@(;0nPr2P)<h;3K|Lk000e1NJLTq001BW000mO1^@s6cL04^0002_Nkl<Zc-rmN
zF{*?x6ouipjVwT1q$nsTDB=P{1QA4#AX>PAy#0vG0?wSmV&1?dw|i4e@ihmM{9S$k
z{HxCl*!MjkOV`a(puMzdnt&`_H%oykVB5BkPQsg$LdD}DorE_hh2DU5T`hqQGPi?3
z))!FMwI$F&=5`RsdIPMr7lF*nW(f4~1yoga5y-r3hCmN*z_KhLcy>`)mLNdh<$!sf
z9l^s%j~7MZ2p&!hn5GFDQb3;P&=3R0afE^xkYyPZ<bYuqpdbdMX$l27pznJqhyh8G
zKtT@Zx(*6rKpe+VkOSJbbp(%JDIkg>NAUP_{`(s~0npR4SjUvOGXMYp07*qoM6N<$
Eg89IE$p8QV
--- a/browser/themes/pinstripe/jar.mn
+++ b/browser/themes/pinstripe/jar.mn
@@ -20,16 +20,19 @@ browser.jar:
   skin/classic/browser/hud-style-check-box-checked.png
   skin/classic/browser/hud-style-check-box-empty.png
   skin/classic/browser/hud-style-dropmarker-double-arrows.png
   skin/classic/browser/hud-style-expander-closed.png
   skin/classic/browser/hud-style-expander-open.png
   skin/classic/browser/hud-style-new-folder-plus-sign.png
   skin/classic/browser/hud-style-twisties.png
   skin/classic/browser/identity.png
+  skin/classic/browser/identity-icons-generic.png
+  skin/classic/browser/identity-icons-https.png
+  skin/classic/browser/identity-icons-https-ev.png
   skin/classic/browser/Info.png
   skin/classic/browser/KUI-background.png
   skin/classic/browser/KUI-close.png
   skin/classic/browser/menu-back.png
   skin/classic/browser/menu-forward.png
   skin/classic/browser/page-livemarks.png
   skin/classic/browser/pageInfo.css
   skin/classic/browser/Privacy-16.png
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -730,23 +730,23 @@ toolbar[mode=full] .toolbarbutton-1 > .t
   -moz-padding-start: 0;
   -moz-box-align: center;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-icon,
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
   padding: 2px 6px;
-  background: hsla(210,48%,90%,0) padding-box;
-  border-radius: 2.5px;
+  background: hsla(210,32%,93%,0) padding-box;
+  border-radius: 2px;
   border: 1px solid;
   border-color: hsla(210,54%,20%,0) hsla(210,54%,20%,0) hsla(210,54%,20%,0);
-  box-shadow: 0 1px 0 rgba(255,255,255,0) inset,
-              0 0 0 1px rgba(255,255,255,0) inset,
-              0 1px 0 hsla(210,54%,20%,0);
+  box-shadow: 0 1px hsla(0,0%,100%,0) inset,
+              0 1px hsla(210,54%,20%,0),
+              0 0 2px hsla(210,54%,20%,0);
   -moz-transition-property: background-color, border-color, box-shadow;
   -moz-transition-duration: 150ms;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon,
 @navbarLargeIcons@ .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
   padding: 3px 7px;
 }
@@ -759,63 +759,81 @@ toolbar[mode=full] .toolbarbutton-1 > .t
   -moz-margin-start: -15px;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
   -moz-border-end: none;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
-  -moz-border-start-color: rgba(0,0,0,0.1);
-  padding: 8px 2px 7px;
+  padding: 8px 3px 7px;
+}
+
+@navbarLargeIcons@ .toolbarbutton-1:not(:hover):not(:active):not([open]) > .toolbarbutton-menubutton-dropmarker::before {
+  content: "";
+  display: -moz-box;
+  width: 1px;
+  height: 18px;
+  -moz-margin-end: -1px;
+  background: hsla(210,54%,20%,.2) padding-box;
+  box-shadow: 0 0 0 1px hsla(0,0%,100%,.2);
 }
 
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon:-moz-locale-dir(ltr),
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-locale-dir(rtl) {
   border-top-right-radius: 0;
   border-bottom-right-radius: 0;
 }
 
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon:-moz-locale-dir(rtl),
 @navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-locale-dir(ltr) {
   border-top-left-radius: 0;
   border-bottom-left-radius: 0;
 }
 
-@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled=true]):not(:active):hover > .toolbarbutton-icon,
-@navbarLargeIcons@ .toolbarbutton-1:not([open=true]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled=true]) > .dropmarker-icon,
-@navbarLargeIcons@ .toolbarbutton-1:not([type=menu-button]):not([disabled=true]):not([checked=true]):not([open=true]):not(:active):hover > .toolbarbutton-icon {
-  background-image: -moz-linear-gradient(rgba(255,255,255,.8), rgba(255,255,255,.45) 49%,
-                                         rgba(255,255,255,.35) 51%, rgba(255,255,255,.1));
-  background-color: hsla(210,48%,96%,.75);
-  border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
-  box-shadow: 0 1px 0 rgba(255,255,255,.3) inset,
-              0 0 0 1px rgba(255,255,255,.3) inset,
-              0 1px 0 hsla(210,54%,20%,.03),
+@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):-moz-any(:hover,[open]) > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
+@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):hover > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
+@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):not([checked]):not([open]):not(:active):hover > .toolbarbutton-icon,
+@conditionalForwardWithUrlbar@ > .toolbarbutton-1:-moz-any([disabled],:not([open]):not([disabled]):not(:active)) > .toolbarbutton-icon {
+  background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
+  border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.2) hsla(210,54%,20%,.25);
+  box-shadow: 0 1px hsla(0,0%,100%,.3) inset,
+              0 1px hsla(210,54%,20%,.03),
               0 0 2px hsla(210,54%,20%,.1);
 }
 
-@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled=true]):hover:active > .toolbarbutton-icon,
-@navbarLargeIcons@ .toolbarbutton-1:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled=true]) > .dropmarker-icon,
-@navbarLargeIcons@ .toolbarbutton-1[open=true] > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon,
-@navbarLargeIcons@ .toolbarbutton-1:not([type=menu-button]):not([disabled=true]):hover:active > .toolbarbutton-icon,
-@navbarLargeIcons@ .toolbarbutton-1:not([type=menu-button])[checked=true] > .toolbarbutton-icon,
-@navbarLargeIcons@ .toolbarbutton-1[open=true] > .toolbarbutton-icon {
-  background-color: hsla(210,54%,20%,.2);
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled]):not([open]):not(:active):hover > .toolbarbutton-icon,
+@navbarLargeIcons@ .toolbarbutton-1:not([buttonover]):not([open]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled]) > .dropmarker-icon,
+@conditionalForwardWithUrlbar@ > #forward-button:not([open]):not(:active):not([disabled]):hover > .toolbarbutton-icon {
   border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
-  box-shadow: 0 1px 1px rgba(0,0,0,.1) inset,
-              0 0 2px rgba(0,0,0,.3) inset,
+  background-color: hsla(210,48%,96%,.75);
+  box-shadow: 0 0 1px hsla(210,54%,20%,.03),
+              0 0 2px hsla(210,54%,20%,.1);
+}
+
+@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled]):hover:active > .toolbarbutton-icon,
+@navbarLargeIcons@ .toolbarbutton-1[open] > .toolbarbutton-menubutton-dropmarker:not([disabled]) > .dropmarker-icon,
+@navbarLargeIcons@ .toolbarbutton-1:not([disabled]):-moz-any([open],[checked],:hover:active) > .toolbarbutton-icon {
+  background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
+  background-color: hsla(210,54%,20%,.15);
+  border-color: hsla(210,54%,20%,.3) hsla(210,54%,20%,.35) hsla(210,54%,20%,.4);
+  box-shadow: 0 1px 1px hsla(210,54%,20%,.1) inset,
+              0 0 1px hsla(210,54%,20%,.2) inset,
               /* allows winstripe-keyhole-forward-mask to be used for non-hover as well as hover: */
               0 1px 0 hsla(210,54%,20%,0),
               0 0 2px hsla(210,54%,20%,0);
   text-shadow: none;
   -moz-transition: none;
 }
 
-@navbarLargeIcons@ .toolbarbutton-1[checked=true]:not(:active):hover > .toolbarbutton-icon {
+@navbarLargeIcons@ .toolbarbutton-1:-moz-any(:hover,[open]) > .toolbarbutton-menubutton-dropmarker:not([disabled]) > .dropmarker-icon {
+  -moz-border-start-color: hsla(210,54%,20%,.35);
+}
+
+@navbarLargeIcons@ .toolbarbutton-1[checked]:not(:active):hover > .toolbarbutton-icon {
   background-color: rgba(90%,90%,90%,.4);
   -moz-transition: background-color .4s;
 }
 
 :-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1,
 :-moz-any(#TabsToolbar, #addon-bar) .toolbarbutton-1 > .toolbarbutton-menubutton-button,
 .tabbrowser-arrowscrollbox > .scrollbutton-up,
 .tabbrowser-arrowscrollbox > .scrollbutton-down {
@@ -881,29 +899,16 @@ toolbar[mode=full] .toolbarbutton-1 > .t
   mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask);
   -moz-margin-start: -6px !important;
   border-left-style: none;
   border-radius: 0;
   padding-left: 7px;
   padding-right: 3px;
 }
 
-@conditionalForwardWithUrlbar@ > :-moz-any(#forward-button:not(:hover):not(:active):not([open]),
-                                           #forward-button[disabled]) > .toolbarbutton-icon {
-  background-color: hsla(210,48%,90%,.1);
-  background-image: -moz-linear-gradient(rgba(255,255,255,.8), rgba(255,255,255,.45) 49%,
-                                         rgba(255,255,255,.35) 51%, rgba(255,255,255,.1));
-  border-color: hsla(210,54%,20%,.13) hsla(210,54%,20%,.16) hsla(210,54%,20%,.2);
-  box-shadow: 0 1px 0 rgba(255,255,255,.3) inset,
-              0 0 0 1px rgba(255,255,255,.3) inset,
-              0 1px 0 hsla(210,54%,20%,.02),
-              /* allows winstripe-keyhole-forward-mask to be used for non-hover as well as hover: */
-              0 0 2px hsla(210,54%,20%,0);
-}
-
 @conditionalForwardWithUrlbar@:not([switchingtabs]) > #forward-button {
   -moz-transition: opacity @forwardTransitionLength@ ease-out;
 }
 
 @conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] {
   opacity: 0;
 }
 
@@ -925,42 +930,47 @@ toolbar[mode=full] .toolbarbutton-1 > .t
 @conditionalForwardWithUrlbar@ > #back-button > menupopup {
   margin-top: -1px;
 }
 
 @conditionalForwardWithUrlbar@ > #back-button > .toolbarbutton-icon {
   border-radius: 10000px;
   padding: 5px;
   border: none;
-  background: hsla(210,48%,90%,.1)
-              -moz-linear-gradient(rgba(255,255,255,.88), rgba(255,255,255,.45) 49%,
-                                   rgba(255,255,255,.35) 51%, rgba(255,255,255,.67));
-  box-shadow: 0 1px 0 rgba(255,255,255,.3) inset,
-              0 0 0 1px rgba(255,255,255,.3) inset,
-              0 1px 0 hsla(210,54%,20%,.02),
-              0 0 0 1px rgba(0,0,0,.15);
+  background-image: -moz-linear-gradient(hsla(0,0%,100%,.6), hsla(0,0%,100%,.1));
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(210,54%,20%,.25),
+              0 1px 0 hsla(210,54%,20%,.35);
   -moz-transition-property: background-color, box-shadow;
   -moz-transition-duration: 250ms;
 }
 
 @conditionalForwardWithUrlbar@ > #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon {
   background-color: hsla(210,48%,96%,.75);
-  box-shadow: 0 1px 0 rgba(255,255,255,.3) inset,
-              0 0 0 1px rgba(255,255,255,.1) inset,
-              0 1px 0 hsla(210,54%,20%,.03),
-              0 0 0 1px rgba(0,0,0,.2),
-              0 0 2px 1px hsla(210,54%,20%,.2);
+  box-shadow: 0 1px 0 hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(0,0%,100%,.3) inset,
+              0 0 0 1px hsla(210,54%,20%,.3),
+              0 1px 0 hsla(210,54%,20%,.4),
+              0 0 4px hsla(210,54%,20%,.2);
 }
 
 @conditionalForwardWithUrlbar@ > #back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon,
 @conditionalForwardWithUrlbar@ > #back-button[open="true"] > .toolbarbutton-icon {
-  background-color: hsla(210,54%,20%,.2);
-  box-shadow: 0 1px 1px rgba(0,0,0,.1) inset,
-              0 0 2px rgba(0,0,0,.3) inset,
-              0 0 0 1px rgba(0,0,0,.2);
+  background-color: hsla(210,54%,20%,.15);
+  box-shadow: 0 1px 1px hsla(210,54%,20%,.1) inset,
+              0 0 1px hsla(210,54%,20%,.2) inset,
+              0 0 0 1px hsla(210,54%,20%,.4),
+              0 1px 0 hsla(210,54%,20%,.2);
+  -moz-transition: none;
+}
+
+@conditionalForwardWithUrlbar@ > #back-button[disabled] > .toolbarbutton-icon {
+  box-shadow: 0 0 0 1px hsla(210,54%,20%,.55),
+              0 1px 0 hsla(210,54%,20%,.65);
   -moz-transition: none;
 }
 
 .unified-nav-back[_moz-menuactive]:-moz-locale-dir(ltr),
 .unified-nav-forward[_moz-menuactive]:-moz-locale-dir(rtl) {
   list-style-image: url("chrome://browser/skin/menu-back.png") !important;
 }
 
@@ -1284,16 +1294,20 @@ html|*.urlbar-input:-moz-lwtheme:-moz-pl
 #urlbar-container {
   -moz-box-orient: horizontal;
   -moz-box-align: stretch;
 }
 
 .urlbar-textbox-container {
   -moz-box-align: stretch;
 }
+ 
+.urlbar-input-box {
+  -moz-margin-start: 0;
+}
 
 #urlbar-icons {
   -moz-box-align: center;
 }
 
 .urlbar-icon {
   padding: 3px 3px;
 }
@@ -1332,25 +1346,23 @@ html|*.urlbar-input:-moz-lwtheme:-moz-pl
 #urlbar-display-box {
   -moz-border-end: 1px solid #AAA;
   -moz-margin-end: 3px;
 }
 
 #urlbar-display {
   margin-top: 0;
   margin-bottom: 0;
+  -moz-margin-start: 0;
   color: GrayText;
 }
 
 /* identity box */
 
 #identity-box {
-  background-image: -moz-linear-gradient(hsl(0,0%,98%), hsl(0,0%,92%));
-  box-shadow: 0 1px 0 hsla(0,0%,0%,.05) inset;
-  -moz-border-end: 1px solid hsla(0,0%,0%,.1);
   padding: 2px;
 }
 
 #identity-box:-moz-locale-dir(ltr) {
   border-top-left-radius: 1.5px;
   border-bottom-left-radius: 1.5px;
 }
 
@@ -1388,71 +1400,34 @@ html|*.urlbar-input:-moz-lwtheme:-moz-pl
   padding-left: 5.01px;
 }
 
 @conditionalForwardWithUrlbar@[forwarddisabled]:not(:hover) + #urlbar-container > #urlbar > #notification-popup-box[hidden] + #identity-box:-moz-locale-dir(rtl) {
   /* when not hovered anymore, trigger a new non-delayed transition to react to the forward button hiding */
   padding-right: 5.01px;
 }
 
-#identity-box:hover {
-  background-image: -moz-linear-gradient(hsl(0,0%,95%), hsl(0,0%,87%));
-}
-
-#identity-box[open="true"],
-#identity-box:hover:active {
-  background-image: -moz-linear-gradient(hsl(0,0%,92%), hsl(0,0%,82%));
-  box-shadow: 0 1px 1px hsla(0,0%,0%,.3) inset,
-              0 1px 3px hsla(0,0%,0%,.3) inset;
-}
-
-#identity-box.verifiedDomain {
-  background-image: -moz-linear-gradient(hsl(215,60%,92%), hsl(215,58%,88%));
-  box-shadow: 0 1px 0 hsla(215,54%,33%,.05) inset;
-  -moz-border-end-color: hsla(215,54%,33%,.2);
-  color: hsl(215,54%,33%);
-}
-
-#identity-box.verifiedDomain:hover {
-  background-image: -moz-linear-gradient(hsl(215,85%,85%), hsl(215,70%,68%));
-}
-
-#identity-box.verifiedDomain[open="true"],
-#identity-box.verifiedDomain:hover:active {
-  background-image: -moz-linear-gradient(hsl(215,80%,80%), hsl(215,67%,65%));
-  box-shadow: 0 1px 1px hsla(215,54%,33%,.7) inset,
-              0 1px 3px 1px hsla(215,54%,33%,.5) inset;
-}
-
 #identity-box.verifiedIdentity {
-  background-image: -moz-linear-gradient(hsl(91,70%,90%), hsl(93,60%,81%));
-  box-shadow: 0 1px 0 hsla(92,81%,16%,.05) inset;
-  -moz-border-end-color: hsla(92,81%,16%,.2);
   color: hsl(92,100%,20%);
-}
-
-#identity-box.verifiedIdentity:hover {
-  background-image: -moz-linear-gradient(hsl(92,69%,77%), hsl(92,44%,51%));
-}
-
-#identity-box.verifiedIdentity[open="true"],
-#identity-box.verifiedIdentity:hover:active {
-  background-image: -moz-linear-gradient(hsl(92,65%,70%), hsl(92,40%,48%));
-  box-shadow: 0 1px 1px hsla(92,81%,16%,.6) inset,
-              0 1px 3px 1px hsla(92,81%,16%,.5) inset;
+  -moz-border-end: 1px solid hsla(92,81%,16%,.2);
+  -moz-margin-end: 4px;
+}
+
+#identity-box.verifiedIdentity:not(:-moz-lwtheme) {
+  background-color: #fff;
 }
 
 #identity-box:-moz-focusring {
   outline: 1px dotted #000;
   outline-offset: -3px;
 }
 
 #identity-icon-labels {
-  -moz-margin-start: 1px;
-  -moz-margin-end: 3px;
+  -moz-padding-start: 2px;
+  -moz-padding-end: 5px;
 }
 
 /* Location bar dropmarker */
 
 .urlbar-history-dropmarker {
   -moz-appearance: none;
   padding: 0 3px;
   background-color: transparent;
@@ -1477,21 +1452,36 @@ html|*.urlbar-input:-moz-lwtheme:-moz-pl
   -moz-image-region: rect(0px, 33px, 14px, 22px);
 }
 
 /* page proxy icon */
 
 #page-proxy-favicon {
   width: 16px;
   height: 16px;
-  margin: 1px 4px;
-}
-
-#page-proxy-favicon:not([src]) {
-  list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
+  margin: 1px 3px;
+  list-style-image: url(chrome://browser/skin/identity-icons-generic.png);
+  -moz-image-region: rect(0, 16px, 16px, 0);
+}
+
+.verifiedDomain > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  list-style-image: url(chrome://browser/skin/identity-icons-https.png);
+}
+
+.verifiedIdentity > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  list-style-image: url(chrome://browser/skin/identity-icons-https-ev.png);
+}
+
+#identity-box:hover > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  -moz-image-region: rect(0, 32px, 16px, 16px);
+}
+
+#identity-box:hover:active > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon,
+#identity-box[open=true] > #identity-box-inner > #page-proxy-stack > #page-proxy-favicon {
+  -moz-image-region: rect(0, 48px, 16px, 32px);
 }
 
 #page-proxy-favicon[pageproxystate="invalid"] {
   opacity: 0.5;
 }
 
 /* autocomplete */
 
@@ -2185,17 +2175,17 @@ toolbarbutton.bookmark-item[dragover="tr
 }
 
 .identity-popup-label {
   white-space: pre-wrap;
   -moz-padding-start: 15px;
   margin: 0;
 }
 
-#identity-popup-content-host ,
+#identity-popup-content-host,
 #identity-popup-content-box.verifiedIdentity > #identity-popup-content-owner {
   font-size: 1.2em;
 }
 
 #identity-popup-content-host {
   margin-top: 3px;
   margin-bottom: 5px;
   font-weight: bold;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..a39e493c1eb1eaacc6b40c32fb6eebe683021b3f
GIT binary patch
literal 965
zc$@*n13LVPP)<h;3K|Lk000e1NJLTq001xm000mO1ONa4`lmEH0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU#XGugsR5;6()JurfWf;ft&;QKDGv}PS
zo|!R^V`}OcNl_L-yKvDWrOV2}Y$49HC{U=NpcV>6Ar%z3$&p%kgOCbJp+JHn5Nu_X
z_e-8^@;Eo0IWx|g^S&)+yo@V*S1&y8_xbU>JbV-PbS|f4v}@CV2}7<b7s9=e$<52R
zi@a)`WjO15JD<OFNBesBmDgO~e4{(Gks6wJs&RMbh=Ib??Khv?#lL=OPQW+olieNJ
zw6saheiz5}zHs1H`z3>KU3<B?u3o(<Sr@1@?a6=W!p(?}*C)FdXR~s~boxmg*ZanS
zTLEA9r1w3ZG&rLu%DbXgHO37u9^i6H*WkADrj_O?Dv6qms8QAOMSh!NA@EU8cHgr}
zqhn487P_cjCB_YJ9w5cRuDI*Tq)pl~Eh+{CwU#EK|6ms~<uxNOJ*ZKgf}E;hQH_F;
zjpa2m?C6TSo=XaHR-13ic|pC$lF+}Sixgo?Ypzjn&5s5IK`<sE8@8f-xGz_q6_x#F
zXtq8f5$cBfbP%@`a_xdaU%DWQqER(c*|>EkU|o}c{plCevv?5vW3{jr`N{6AAr~E2
zoyDVQP`Al$ZG?60&iU0>DtGW_JR_{7mat;LB@=U&D{Hw%p&JcTZG*13F{hrkP{veV
z198O#r(B;?Z}x<|*gZ2rWyH83NC_Hb1P_?6B2+*aHz|rzqO`QApjDMBgi6V%AgC2I
zX%;+ci7BBnGr>8lSgKjhNiB+k8Y4==Sxh9u)eaWO%J@r8Nl;_Vh-BErP5xmWS{>Et
zl%UoXmxQx30f($Act{G5IBp!rbQ<6=2GggmcjPUW!ZPPf;)GU18c!P}9<pkgr_|tS
zKf8_}EOws5Ghg&s7%M6Yg0xO)L1I)G51-;{TYsD?DG7o)E$Rh~iIuipuFmkMomN$q
zalf1(r8LW@*i;OCA^stVqJ^f-*KQ()-c3c6n~vo7Mi*!6?W)?en3CVqbVQl$#n>0)
z(b*kaZrT!ylw<7OUc9A>T|N5SvkO!WNJ*5&_4Vz)t%~B?rHxH>dBLER#Au~sZ`TL6
zRq<|*{)O44rkz(K@%OmC_x8_`-RFzEc1u>@+4;&{vKw7f+FV{a-Ae6n=48k2=DTF~
n&RzWbb7gnWy3U~de{}sH<r$SwqU;WP00000NkvXXu0mjfm%Y@7
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..91c5dcb8830e76799d9371f183b4f07a03675dbf
GIT binary patch
literal 900
zc$@)*1AF|5P)<h;3K|Lk000e1NJLTq001xm000mO1^@s6P_F#30009^Nkl<Zc-pPi
zTS!z<6b4|M$xaA5nOYr!7|oo@@{(gp7jt4DyO0{BrV`S{BB+olqR2u_OHH8*C>2CR
zM8p&Y1<?g^6ng5VNQmgM*N`suwpu^@0~_bkL3;RLxAwncuQU4`Q$%FO?tE*Fa;a36
zrZSbSyegl(tYtEj%AS-s+-k1MP+640n%m6c4F6+*S;pbB)DpE)m8nW9V{HjC#t^g2
z1F_~&xyrAq$<LaHndAeUc)E6(3ad#9qn2O*7oSch4_GuZQQtf?9vmMS4g3PEQNtcH
zne1_yPo4){(K}vq;NXpt_bo%qrvPizu*Zx$;Q*m0<v#UYiHS8|oB?L5bhTKm8lI@z
z+dmrk+5fg$OsHWG8D`Vjn*tmtw<l85-ZHrS_nrZtm{9AD)Eq(v*@OdhJo1N?sOQQC
zt_6E$mRG=1*{VRTABb#zcj--)Tpru}>DJeVF2EW!>>-0Jdo1G`d6a+uNb&o|z5>}d
zTr_d@LwzS;jT-ilK{nw4#~+qWDp9skvswFLW_bnD_(V(9w%*rOQ$4RX3J$LS4guDv
z>E0h?m|e_X7uncr>MNLPxVTKNeXK`+6JU*+4iW9Q(Gz!oqxaVcIH~h4W~e;1K{a>3
z*dTy|n~Zuhvw7@wD~rEM+wKeb0_<z2kWp__KJ>&4aO7@jM9Duyi~&;Be7;;;x?gVk
za{k$RNd_5Y*)!kx@>H}A7Jl8;l`qL4gDiSt1~`1XM4T`Nu+#!otZF--t`jGaMGt!|
zm7{|7=az~S$f74^fP*)S#Q}4GxoQ!=^Se(!t`sMbWslAO!&cjC&*q5}$f74^fc+z@
z#ewMq*wFz_h1ZG$i3ZrQ^GvQdfo$9X+ODq>2c{3OFnWbT56Z;>^9n6Ae}V0%yy8IO
zUtsT*LUCaFJCMy6GT3q7FHRuKo^0bC2y8p)6(^95`wp}Y6-Jc&!`QU1&^+Z;<)Md_
zpN`%0OEQ|7K$bo8jIU7fuJZ+-w}!lu3^K@?U!fV}H$06`a48QKRCTIRwNN8#L1dWC
zVXs?R##IdPitI447BH@!^*;u1sW~d02lDc2lqkQdAU|r{^D>*xUKd%)!#z8J9A>QO
aU*f;6c*m;N5KuP&0000<MNUMnLSTZ>&#CGF
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3a22f7e0195088708f3838376551b95a42e87f7e
GIT binary patch
literal 553
zc%17D@N?(olHy`uVBq!ia0vp^20$#p!3HD)*8SPYz`*#y)5S5Q;?~t`2eYCaC0HLc
z-PU1>z01zAy|P(slgE6e^B45IPKJp9!AC|H7D1N@jy)P0N{?I|@1`d@dWh#Wr(7&4
zt*YD6y8FX^<L;D+N7*0GoS(>dNBcW-L;2gQd{#1i|Chd)<Md00bFq%-**&?9yLa#A
zHY(|nIBCPRMB~QWvisX^zdf9_wMuZ)G@ox8PqhNphUuTUV3?%xS?j|4@6J_9M_eOc
zXcV05u6w@pzs_{;Bc5v2M$Vqo`CoPlh^H>x?6Cg2F^g27!XncX7F;c}&ptaC)%~^V
zZ}$HC|3yGXrl_rSSQ=yqQ^GBg+{eO|6zQ-a-MvwN&x_MZ8yWQfHSf3Qiu69VcfZl(
zkOeV%@|+?^HZ?e$KgV=8Pu%J3SElq5<N4<mckElbe&X$jI_1r`ESCmxI-M5gF0qpJ
zF4*AJ=zs0j@tZkqDn`nim!H!R>z?)?;VRSHGHJUhOyQSbirA%myCT`@#AtVgX>Ay{
z+!m(mlTWgM1%KAa$$eoun<gxGh3WA}2_U&Mh7Tyx>&6UZFTThDByZ-30Y$!6$;w?R
zPq2_V)clJt#YnQ^0{4|HQ}2Qu*Z;NtsIli`V^(>1CjVUAJS*k7e$h>b|3=rInd`~9
oYf*OVo7hutvg^+5&Hm5ub=6M8`svs10+RrPr>mdKI;Vst0MAtN5&!@I
--- a/browser/themes/winstripe/jar.mn
+++ b/browser/themes/winstripe/jar.mn
@@ -20,16 +20,19 @@ browser.jar:
 *       skin/classic/browser/browser.css                             (browser.css)
 *       skin/classic/browser/engineManager.css                       (engineManager.css)
         skin/classic/browser/Geolocation-16.png
         skin/classic/browser/Geolocation-64.png
         skin/classic/browser/webapps-16.png
         skin/classic/browser/webapps-64.png
         skin/classic/browser/Info.png                                (Info.png)
         skin/classic/browser/identity.png                            (identity.png)
+        skin/classic/browser/identity-icons-generic.png
+        skin/classic/browser/identity-icons-https.png
+        skin/classic/browser/identity-icons-https-ev.png
         skin/classic/browser/keyhole-forward-mask.svg
         skin/classic/browser/KUI-background.png
         skin/classic/browser/KUI-close.png
         skin/classic/browser/pageInfo.css
         skin/classic/browser/pageInfo.png                            (pageInfo.png)
         skin/classic/browser/page-livemarks.png                      (feeds/feedIcon16.png)
         skin/classic/browser/livemark-folder.png                     (livemark-folder.png)
         skin/classic/browser/Privacy-16.png
@@ -203,16 +206,19 @@ browser.jar:
 *       skin/classic/aero/browser/browser.css                        (browser-aero.css)
 *       skin/classic/aero/browser/engineManager.css                  (engineManager.css)
         skin/classic/aero/browser/Geolocation-16.png
         skin/classic/aero/browser/Geolocation-64.png
         skin/classic/aero/browser/webapps-16.png
         skin/classic/aero/browser/webapps-64.png
         skin/classic/aero/browser/Info.png                           (Info-aero.png)
         skin/classic/aero/browser/identity.png                       (identity-aero.png)
+        skin/classic/aero/browser/identity-icons-generic.png
+        skin/classic/aero/browser/identity-icons-https.png
+        skin/classic/aero/browser/identity-icons-https-ev.png
         skin/classic/aero/browser/keyhole-forward-mask.svg
         skin/classic/aero/browser/KUI-background.png
         skin/classic/aero/browser/KUI-close.png
         skin/classic/aero/browser/pageInfo.css
         skin/classic/aero/browser/pageInfo.png                       (pageInfo-aero.png)
         skin/classic/aero/browser/page-livemarks.png                 (feeds/feedIcon16-aero.png)
         skin/classic/aero/browser/livemark-folder.png                (livemark-folder-aero.png)
         skin/classic/aero/browser/Privacy-16.png                     (Privacy-16-aero.png)
--- a/client.mk
+++ b/client.mk
@@ -193,16 +193,19 @@ all realbuild clean depend distclean exp
 	fi
 
 # Windows equivalents
 build_all: build
 build_all_dep: alldep
 build_all_depend: alldep
 clobber clobber_all: clean
 
+# helper target for mobile
+build_and_deploy: build package install
+
 # Do everything from scratch
 everything: clean build
 
 ####################################
 # Profile-Guided Optimization
 #  To use this, you should set the following variables in your mozconfig
 #    mk_add_options PROFILE_GEN_SCRIPT=/path/to/profile-script
 #
--- a/config/milestone.txt
+++ b/config/milestone.txt
@@ -5,9 +5,9 @@
 #    x.x.x.x
 #    x.x.x+
 #
 # Referenced by milestone.pl.
 # Hopefully I'll be able to automate replacement of *all*
 # hardcoded milestones in the tree from these two files.
 #--------------------------------------------------------
 
-14.0a1
+15.0a1
--- a/content/base/public/nsIWebSocket.idl
+++ b/content/base/public/nsIWebSocket.idl
@@ -54,17 +54,17 @@ class nsString;
 
 /**
  * The nsIWebSocket interface enables Web applications to maintain
  * bidirectional communications with server-side processes as described in:
  *
  * http://dev.w3.org/html5/websockets/
  *
  */
-[scriptable, uuid(f463b9b5-1408-4057-9224-e4f5bc33f17b)]
+[scriptable, uuid(e59c8c65-df29-485c-a00b-8fac3dc1573a)]
 interface nsIWebSocket : nsISupports
 {
   readonly attribute DOMString url;
   readonly attribute DOMString extensions;
   readonly attribute DOMString protocol;
 
   //ready state
   const unsigned short CONNECTING = 0;
@@ -88,17 +88,17 @@ interface nsIWebSocket : nsISupports
   /**
    * Transmits data to other end of the connection.
    * @param data The data to be transmitted.  Arraybuffers and Blobs are sent as
    * binary data.  Strings are sent as UTF-8 text data.  Other types are
    * converted to a String and sent as a String.
    * @return if the connection is still established and the data was queued or
    *         sent successfully.
    */
-  void send(in nsIVariant data);
+  [implicit_jscontext] void send(in nsIVariant data);
 
   /**
    * Closes the Web Socket connection or connection attempt, if any.
    * If the connection is already closed, it does nothing.
    */
   [optional_argc] void close([optional] in unsigned short code,
                              [optional] in DOMString reason);
 
--- a/content/base/public/nsIXMLHttpRequest.idl
+++ b/content/base/public/nsIXMLHttpRequest.idl
@@ -106,17 +106,17 @@ interface nsIXMLHttpRequestUpload : nsIX
  *   The 'onload', 'onerror', and 'onreadystatechange' attributes moved to
  *   nsIJSXMLHttpRequest, but if you're coding in C++ you should avoid using
  *   those.
  *
  * Conclusion: Do not use event listeners on XMLHttpRequest from C++, unless
  * you're aware of all the security implications.  And then think twice about
  * it.
  */
-[scriptable, uuid(88ffc45a-22e2-44f4-9a6e-f4586fbde376)]
+[scriptable, uuid(8681ffbc-4755-45de-9fc1-b63e6930e76a)]
 interface nsIXMLHttpRequest : nsISupports
 {
   /**
    * The request uses a channel in order to perform the
    * request.  This attribute represents the channel used
    * for the request.  NULL if the channel has not yet been
    * created.
    *
@@ -255,26 +255,26 @@ interface nsIXMLHttpRequest : nsISupport
    *             Content-Length header will be added to the HTTP request
    *             with a value given by nsIInputStream.available.  Any
    *             headers included at the top of the stream will be
    *             treated as part of the message body.  The MIME type of
    *             the stream should be specified by setting the Content-
    *             Type header via the setRequestHeader method before
    *             calling send.
    */
-  void   send([optional] in nsIVariant body);
+  [implicit_jscontext] void   send([optional] in nsIVariant body);
 
   /**
    * A variant of the send() method used to send binary data.
    *
    * @param body The request body as a DOM string.  The string data will be
    *             converted to a single-byte string by truncation (i.e., the
    *             high-order byte of each character will be discarded).
    */
-  void   sendAsBinary(in DOMString body);
+  [implicit_jscontext] void   sendAsBinary(in DOMString body);
 
   /**
    * Sets a HTTP request header for HTTP requests. You must call open
    * before setting the request headers.
    *
    * @param header The name of the header to set in the request.
    * @param value The body of the header.
    */
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -40,17 +40,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 /* A namespace class for static layout utilities. */
 
 #include "mozilla/Util.h"
 
 #include "jsapi.h"
 #include "jsdbgapi.h"
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 
 #include "nsJSUtils.h"
 #include "nsCOMPtr.h"
 #include "nsAString.h"
 #include "nsPrintfCString.h"
 #include "nsUnicharUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIScriptGlobalObject.h"
@@ -117,17 +117,17 @@
 #include "nsIXTFService.h"
 static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID);
 #endif
 #include "nsIMIMEService.h"
 #include "nsLWBrkCIID.h"
 #include "nsILineBreaker.h"
 #include "nsIWordBreaker.h"
 #include "nsUnicodeProperties.h"
-#include "harfbuzz/hb-common.h"
+#include "harfbuzz/hb.h"
 #include "nsIJSRuntimeService.h"
 #include "nsIDOMDocumentXBL.h"
 #include "nsBindingManager.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsXBLBinding.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsEscape.h"
@@ -5867,25 +5867,24 @@ nsresult
 nsContentUtils::CreateArrayBuffer(JSContext *aCx, const nsACString& aData,
                                   JSObject** aResult)
 {
   if (!aCx) {
     return NS_ERROR_FAILURE;
   }
 
   PRInt32 dataLen = aData.Length();
-  *aResult = js_CreateArrayBuffer(aCx, dataLen);
+  *aResult = JS_NewArrayBuffer(aCx, dataLen);
   if (!*aResult) {
     return NS_ERROR_FAILURE;
   }
 
   if (dataLen > 0) {
-    JSObject *abuf = js::ArrayBuffer::getArrayBuffer(*aResult);
-    NS_ASSERTION(abuf, "What happened?");
-    memcpy(JS_GetArrayBufferData(abuf), aData.BeginReading(), dataLen);
+    NS_ASSERTION(JS_IsArrayBufferObject(*aResult, aCx), "What happened?");
+    memcpy(JS_GetArrayBufferData(*aResult, aCx), aData.BeginReading(), dataLen);
   }
 
   return NS_OK;
 }
 
 void
 nsContentUtils::StripNullChars(const nsAString& aInStr, nsAString& aOutStr)
 {
--- a/content/base/src/nsDOMBlobBuilder.cpp
+++ b/content/base/src/nsDOMBlobBuilder.cpp
@@ -31,17 +31,17 @@
  * 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 "nsDOMBlobBuilder.h"
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 #include "nsAutoPtr.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIMultiplexInputStream.h"
 #include "nsStringStream.h"
 #include "nsTArray.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "DictionaryHelpers.h"
@@ -244,21 +244,18 @@ nsDOMMultipartFile::InitInternal(JSConte
               static_cast<nsIDOMBlob*>(blob));
           const nsTArray<nsCOMPtr<nsIDOMBlob> >*
               subBlobs = file->GetSubBlobs();
           if (subBlobs) {
             blobSet.AppendBlobs(*subBlobs);
           } else {
             blobSet.AppendBlob(blob);
           }
-        } else if (js_IsArrayBuffer(&obj)) {
-          JSObject* buffer = js::ArrayBuffer::getArrayBuffer(&obj);
-          if (!buffer)
-            return NS_ERROR_DOM_INVALID_STATE_ERR;
-          blobSet.AppendArrayBuffer(buffer);
+        } else if (JS_IsArrayBufferObject(&obj, aCx)) {
+          blobSet.AppendArrayBuffer(&obj, aCx);
         } else {
           // neither arraybuffer nor blob
           return NS_ERROR_DOM_INVALID_STATE_ERR;
         }
       } else if (element.isString()) {
         blobSet.AppendString(element.toString(), nativeEOL, aCx);
       } else {
         // neither object nor string
@@ -326,19 +323,20 @@ BlobSet::AppendBlobs(const nsTArray<nsCO
 {
   Flush();
   mBlobs.AppendElements(aBlob);
 
   return NS_OK;
 }
 
 nsresult
-BlobSet::AppendArrayBuffer(JSObject* aBuffer)
+BlobSet::AppendArrayBuffer(JSObject* aBuffer, JSContext *aCx)
 {
-  return AppendVoidPtr(JS_GetArrayBufferData(aBuffer), JS_GetArrayBufferByteLength(aBuffer));
+  return AppendVoidPtr(JS_GetArrayBufferData(aBuffer, aCx),
+                       JS_GetArrayBufferByteLength(aBuffer, aCx));
 }
 
 DOMCI_DATA(MozBlobBuilder, nsDOMBlobBuilder)
 
 NS_IMPL_ADDREF(nsDOMBlobBuilder)
 NS_IMPL_RELEASE(nsDOMBlobBuilder)
 NS_INTERFACE_MAP_BEGIN(nsDOMBlobBuilder)
   NS_INTERFACE_MAP_ENTRY(nsIDOMMozBlobBuilder)
@@ -431,20 +429,18 @@ nsDOMBlobBuilder::Append(const jsval& aD
       if (subBlobs) {
         return mBlobSet.AppendBlobs(*subBlobs);
       } else {
         return mBlobSet.AppendBlob(blob);
       }
     }
 
     // Is it an array buffer?
-    if (js_IsArrayBuffer(obj)) {
-      JSObject* buffer = js::ArrayBuffer::getArrayBuffer(obj);
-      if (buffer)
-        return mBlobSet.AppendArrayBuffer(buffer);
+    if (JS_IsArrayBufferObject(obj, aCx)) {
+      return mBlobSet.AppendArrayBuffer(obj, aCx);
     }
   }
 
   // If it's not a Blob or an ArrayBuffer, coerce it to a string
   JSString* str = JS_ValueToString(aCx, aData);
   NS_ENSURE_TRUE(str, NS_ERROR_FAILURE);
 
   return mBlobSet.AppendString(str, aEndings.EqualsLiteral("native"), aCx);
--- a/content/base/src/nsDOMBlobBuilder.h
+++ b/content/base/src/nsDOMBlobBuilder.h
@@ -108,17 +108,17 @@ class BlobSet {
 public:
   BlobSet()
     : mData(nsnull), mDataLen(0), mDataBufferLen(0)
   {}
 
   nsresult AppendVoidPtr(const void* aData, PRUint32 aLength);
   nsresult AppendString(JSString* aString, bool nativeEOL, JSContext* aCx);
   nsresult AppendBlob(nsIDOMBlob* aBlob);
-  nsresult AppendArrayBuffer(JSObject* aBuffer);
+  nsresult AppendArrayBuffer(JSObject* aBuffer, JSContext *aCx);
   nsresult AppendBlobs(const nsTArray<nsCOMPtr<nsIDOMBlob> >& aBlob);
 
   nsTArray<nsCOMPtr<nsIDOMBlob> >& GetBlobs() { Flush(); return mBlobs; }
 
 protected:
   bool ExpandBufferSize(PRUint64 aSize)
   {
     if (mDataBufferLen >= mDataLen + aSize) {
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -76,17 +76,17 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsBlobProtocolHandler.h"
 #include "mozilla/Preferences.h"
 #include "xpcpublic.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsDOMJSUtils.h"
 #include "nsDOMEventTargetHelper.h"
 
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 
 using namespace mozilla;
 
 #define LOAD_STR "load"
 #define LOADSTART_STR "loadstart"
 #define LOADEND_STR "loadend"
 
 using mozilla::dom::FileIOObject;
@@ -354,21 +354,19 @@ nsDOMFileReader::DoOnDataAvailable(nsIRe
     NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
 
     PRUint32 bytesRead = 0;
     aInputStream->ReadSegments(ReadFuncBinaryString, buf + oldLen, aCount,
                                &bytesRead);
     NS_ASSERTION(bytesRead == aCount, "failed to read data");
   }
   else if (mDataFormat == FILE_AS_ARRAYBUFFER) {
-    JSObject* abuf = js::ArrayBuffer::getArrayBuffer(mResultArrayBuffer);
-    NS_ASSERTION(abuf, "What happened?");
-  
     PRUint32 bytesRead = 0;
-    aInputStream->Read((char*)JS_GetArrayBufferData(abuf) + aOffset, aCount, &bytesRead);
+    aInputStream->Read((char*)JS_GetArrayBufferData(mResultArrayBuffer, NULL) + aOffset,
+                       aCount, &bytesRead);
     NS_ASSERTION(bytesRead == aCount, "failed to read data");
   }
   else {
     //Update memory buffer to reflect the contents of the file
     mFileData = (char *)PR_Realloc(mFileData, aOffset + aCount);
     NS_ENSURE_TRUE(mFileData, NS_ERROR_OUT_OF_MEMORY);
 
     PRUint32 bytesRead = 0;
@@ -465,17 +463,17 @@ nsDOMFileReader::ReadFileContent(JSConte
   NS_ENSURE_SUCCESS(rv, rv);
 
   //FileReader should be in loading state here
   mReadyState = nsIDOMFileReader::LOADING;
   DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR));
   
   if (mDataFormat == FILE_AS_ARRAYBUFFER) {
     RootResultArrayBuffer();
-    mResultArrayBuffer = js_CreateArrayBuffer(aCx, mTotal);
+    mResultArrayBuffer = JS_NewArrayBuffer(aCx, mTotal);
     if (!mResultArrayBuffer) {
       NS_WARNING("Failed to create JS array buffer");
       return NS_ERROR_FAILURE;
     }
   }
  
   return NS_OK;
 }
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -74,17 +74,17 @@
 #include "nsIScriptError.h"
 #include "nsNetUtil.h"
 #include "nsILoadGroup.h"
 #include "mozilla/Preferences.h"
 #include "nsDOMLists.h"
 #include "xpcpublic.h"
 #include "nsContentPolicyUtils.h"
 #include "nsContentErrors.h"
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 #include "prmem.h"
 #include "nsDOMFile.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsDOMEventTargetHelper.h"
 #include "nsIObserverService.h"
 
 using namespace mozilla;
 
@@ -1296,29 +1296,29 @@ ContainsUnpairedSurrogates(const nsAStri
       }
       continue;
     }
   }
   return false;
 }
 
 NS_IMETHODIMP
-nsWebSocket::Send(nsIVariant *aData)
+nsWebSocket::Send(nsIVariant *aData, JSContext *aCx)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 
   if (mReadyState == nsIWebSocket::CONNECTING) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   nsCString msgString;
   nsCOMPtr<nsIInputStream> msgStream;
   bool isBinary;
   PRUint32 msgLen;
-  nsresult rv = GetSendParams(aData, msgString, msgStream, isBinary, msgLen);
+  nsresult rv = GetSendParams(aData, msgString, msgStream, isBinary, msgLen, aCx);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Always increment outgoing buffer len, even if closed
   mOutgoingBufferedAmount += msgLen;
 
   if (mReadyState == nsIWebSocket::CLOSING ||
       mReadyState == nsIWebSocket::CLOSED) {
     return NS_OK;
@@ -1341,17 +1341,18 @@ nsWebSocket::Send(nsIVariant *aData)
   UpdateMustKeepAlive();
 
   return NS_OK;
 }
 
 nsresult
 nsWebSocket::GetSendParams(nsIVariant *aData, nsCString &aStringOut,
                            nsCOMPtr<nsIInputStream> &aStreamOut,
-                           bool &aIsBinary, PRUint32 &aOutgoingLength)
+                           bool &aIsBinary, PRUint32 &aOutgoingLength,
+                           JSContext *aCx)
 {
   // Get type of data (arraybuffer, blob, or string)
   PRUint16 dataType;
   nsresult rv = aData->GetDataType(&dataType);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (dataType == nsIDataType::VTYPE_INTERFACE ||
       dataType == nsIDataType::VTYPE_INTERFACE_IS) {
@@ -1363,19 +1364,19 @@ nsWebSocket::GetSendParams(nsIVariant *a
     nsMemory::Free(iid);
 
     // ArrayBuffer?
     jsval realVal;
     JSObject* obj;
     nsresult rv = aData->GetAsJSVal(&realVal);
     if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(realVal) &&
         (obj = JSVAL_TO_OBJECT(realVal)) &&
-        (js_IsArrayBuffer(obj))) {
-      PRInt32 len = JS_GetArrayBufferByteLength(obj);
-      char* data = (char*)JS_GetArrayBufferData(obj);
+        (JS_IsArrayBufferObject(obj, aCx))) {
+      PRInt32 len = JS_GetArrayBufferByteLength(obj, aCx);
+      char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(obj, aCx));
 
       aStringOut.Assign(data, len);
       aIsBinary = true;
       aOutgoingLength = len;
       return NS_OK;
     }
 
     // Blob?
--- a/content/base/src/nsWebSocket.h
+++ b/content/base/src/nsWebSocket.h
@@ -131,17 +131,18 @@ protected:
                                const PRUnichar **aFormatStrings,
                                PRUint32          aFormatStringsLen);
 
   nsresult ConvertTextToUTF8(const nsString& aMessage, nsCString& buf);
 
   // Get msg info out of JS variable being sent (string, arraybuffer, blob)
   nsresult GetSendParams(nsIVariant *aData, nsCString &aStringOut,
                          nsCOMPtr<nsIInputStream> &aStreamOut,
-                         bool &aIsBinary, PRUint32 &aOutgoingLength);
+                         bool &aIsBinary, PRUint32 &aOutgoingLength,
+                         JSContext *aCx);
 
   nsresult DoOnMessageAvailable(const nsACString & aMsg, bool isBinary);
   nsresult CreateAndDispatchSimpleEvent(const nsString& aName);
   nsresult CreateAndDispatchMessageEvent(const nsACString& aData,
                                          bool isBinary);
   nsresult CreateAndDispatchCloseEvent(bool aWasClean, PRUint16 aCode,
                                        const nsString &aReason);
   nsresult CreateResponseBlob(const nsACString& aData, JSContext *aCx,
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -94,21 +94,21 @@
 #include "nsIPromptFactory.h"
 #include "nsIWindowWatcher.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsIConsoleService.h"
 #include "nsIChannelPolicy.h"
 #include "nsChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsAsyncRedirectVerifyHelper.h"
-#include "jstypedarray.h"
 #include "nsStringBuffer.h"
 #include "nsDOMFile.h"
 #include "nsIFileChannel.h"
 #include "mozilla/Telemetry.h"
+#include "jsfriendapi.h"
 #include "sampler.h"
 #include "mozilla/dom/bindings/XMLHttpRequestBinding.h"
 #include "nsIDOMFormData.h"
 
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -2506,25 +2506,25 @@ nsXMLHttpRequest::ChangeStateToDone()
   }
   else if (!(mState & XML_HTTP_REQUEST_GOT_FINAL_STOP)) {
     // We're a multipart request, so we're not done. Reset to opened.
     ChangeState(XML_HTTP_REQUEST_OPENED);
   }
 }
 
 NS_IMETHODIMP
-nsXMLHttpRequest::SendAsBinary(const nsAString &aBody)
+nsXMLHttpRequest::SendAsBinary(const nsAString &aBody, JSContext *aCx)
 {
   nsresult rv = NS_OK;
-  SendAsBinary(aBody, rv);
+  SendAsBinary(aCx, aBody, rv);
   return rv;
 }
 
 void
-nsXMLHttpRequest::SendAsBinary(const nsAString &aBody, nsresult& aRv)
+nsXMLHttpRequest::SendAsBinary(JSContext *aCx, const nsAString &aBody, nsresult& aRv)
 {
   char *data = static_cast<char*>(NS_Alloc(aBody.Length() + 1));
   if (!data) {
     aRv = NS_ERROR_OUT_OF_MEMORY;
     return;
   }
 
   nsAString::const_iterator iter, end;
@@ -2551,17 +2551,17 @@ nsXMLHttpRequest::SendAsBinary(const nsA
 
   nsCOMPtr<nsIWritableVariant> variant = new nsVariant();
 
   aRv = variant->SetAsISupports(stream);
   if (NS_FAILED(aRv)) {
     return;
   }
 
-  aRv = Send(variant);
+  aRv = Send(variant, aCx);
 }
 
 static nsresult
 GetRequestBody(nsIDOMDocument* aDoc, nsIInputStream** aResult,
                nsACString& aContentType, nsACString& aCharset)
 {
   aContentType.AssignLiteral("application/xml");
   nsAutoString inputEncoding;
@@ -2622,38 +2622,38 @@ GetRequestBody(nsIInputStream* aStream, 
 static nsresult
 GetRequestBody(nsIXHRSendable* aSendable, nsIInputStream** aResult,
                nsACString& aContentType, nsACString& aCharset)
 {
   return aSendable->GetSendInfo(aResult, aContentType, aCharset);
 }
 
 static nsresult
-GetRequestBody(JSObject* aArrayBuffer, nsIInputStream** aResult,
+GetRequestBody(JSObject* aArrayBuffer, JSContext *aCx, nsIInputStream** aResult,
                nsACString& aContentType, nsACString& aCharset)
 {
-  NS_ASSERTION(js_IsArrayBuffer(aArrayBuffer), "Not an ArrayBuffer!");
+  NS_ASSERTION(JS_IsArrayBufferObject(aArrayBuffer, aCx), "Not an ArrayBuffer!");
   aContentType.SetIsVoid(true);
   aCharset.Truncate();
 
-  PRInt32 length = JS_GetArrayBufferByteLength(aArrayBuffer);
-  char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(aArrayBuffer));
+  PRInt32 length = JS_GetArrayBufferByteLength(aArrayBuffer, aCx);
+  char* data = reinterpret_cast<char*>(JS_GetArrayBufferData(aArrayBuffer, aCx));
 
   nsCOMPtr<nsIInputStream> stream;
   nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), data, length,
                                       NS_ASSIGNMENT_COPY);
   NS_ENSURE_SUCCESS(rv, rv);
 
   stream.forget(aResult);
 
   return NS_OK;
 }
 
 static nsresult
-GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult,
+GetRequestBody(nsIVariant* aBody, JSContext *aCx, nsIInputStream** aResult,
                nsACString& aContentType, nsACString& aCharset)
 {
   *aResult = nsnull;
 
   PRUint16 dataType;
   nsresult rv = aBody->GetDataType(&dataType);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -2694,18 +2694,18 @@ GetRequestBody(nsIVariant* aBody, nsIInp
     }
 
     // ArrayBuffer?
     jsval realVal;
     JSObject* obj;
     nsresult rv = aBody->GetAsJSVal(&realVal);
     if (NS_SUCCEEDED(rv) && !JSVAL_IS_PRIMITIVE(realVal) &&
         (obj = JSVAL_TO_OBJECT(realVal)) &&
-        (js_IsArrayBuffer(obj))) {
-      return GetRequestBody(obj, aResult, aContentType, aCharset);
+        (JS_IsArrayBufferObject(obj, aCx))) {
+      return GetRequestBody(obj, aCx, aResult, aContentType, aCharset);
     }
   }
   else if (dataType == nsIDataType::VTYPE_VOID ||
            dataType == nsIDataType::VTYPE_EMPTY) {
     // Makes us act as if !aBody, don't upload anything
     aContentType.AssignLiteral("text/plain");
     aCharset.AssignLiteral("UTF-8");
 
@@ -2720,31 +2720,31 @@ GetRequestBody(nsIVariant* aBody, nsIInp
   nsString string;
   string.Adopt(data, len);
 
   return GetRequestBody(string, aResult, aContentType, aCharset);
 }
 
 /* static */
 nsresult
-nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant,
+nsXMLHttpRequest::GetRequestBody(nsIVariant* aVariant, JSContext *aCx,
                                  const Nullable<RequestBody>& aBody,
                                  nsIInputStream** aResult,
                                  nsACString& aContentType, nsACString& aCharset)
 {
   if (aVariant) {
-    return ::GetRequestBody(aVariant, aResult, aContentType, aCharset);
+    return ::GetRequestBody(aVariant, aCx, aResult, aContentType, aCharset);
   }
 
   const RequestBody& body = aBody.Value();
   RequestBody::Value value = body.GetValue();
   switch (body.GetType()) {
     case nsXMLHttpRequest::RequestBody::ArrayBuffer:
     {
-      return ::GetRequestBody(value.mArrayBuffer, aResult, aContentType, aCharset);
+      return ::GetRequestBody(value.mArrayBuffer, aCx, aResult, aContentType, aCharset);
     }
     case nsXMLHttpRequest::RequestBody::Blob:
     {
       nsresult rv;
       nsCOMPtr<nsIXHRSendable> sendable = do_QueryInterface(value.mBlob, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
       return ::GetRequestBody(sendable, aResult, aContentType, aCharset);
@@ -2777,23 +2777,23 @@ nsXMLHttpRequest::GetRequestBody(nsIVari
   }
 
   NS_NOTREACHED("Default cases exist for a reason");
   return NS_OK;
 }
 
 /* void send (in nsIVariant aBody); */
 NS_IMETHODIMP
-nsXMLHttpRequest::Send(nsIVariant *aBody)
+nsXMLHttpRequest::Send(nsIVariant *aBody, JSContext *aCx)
 {
-  return Send(aBody, Nullable<RequestBody>());
+  return Send(aCx, aBody, Nullable<RequestBody>());
 }
 
 nsresult
-nsXMLHttpRequest::Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
+nsXMLHttpRequest::Send(JSContext *aCx, nsIVariant* aVariant, const Nullable<RequestBody>& aBody)
 {
   NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED);
 
   nsresult rv = CheckInnerWindowCorrectness();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Return error if we're already processing a request
   if (XML_HTTP_REQUEST_SENT & mState) {
@@ -2907,17 +2907,17 @@ nsXMLHttpRequest::Send(nsIVariant* aVari
   mUploadProgressMax = 0;
   if ((aVariant || !aBody.IsNull()) && httpChannel &&
       !method.EqualsLiteral("GET")) {
 
     nsCAutoString charset;
     nsCAutoString defaultContentType;
     nsCOMPtr<nsIInputStream> postDataStream;
 
-    rv = GetRequestBody(aVariant, aBody, getter_AddRefs(postDataStream),
+    rv = GetRequestBody(aVariant, aCx, aBody, getter_AddRefs(postDataStream),
                         defaultContentType, charset);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (postDataStream) {
       // If no content type header was set by the client, we set it to
       // application/xml.
       nsCAutoString contentType;
       if (NS_FAILED(httpChannel->
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -365,71 +365,72 @@ private:
     }
 
   private:
     Type mType;
     Value mValue;
   };
 
   static nsresult GetRequestBody(nsIVariant* aVariant,
+                                 JSContext* aCx,
                                  const Nullable<RequestBody>& aBody,
                                  nsIInputStream** aResult,
                                  nsACString& aContentType,
                                  nsACString& aCharset);
 
-  nsresult Send(nsIVariant* aVariant, const Nullable<RequestBody>& aBody);
-  nsresult Send(const Nullable<RequestBody>& aBody)
+  nsresult Send(JSContext *aCx, nsIVariant* aVariant, const Nullable<RequestBody>& aBody);
+  nsresult Send(JSContext *aCx, const Nullable<RequestBody>& aBody)
   {
-    return Send(nsnull, aBody);
+    return Send(aCx, nsnull, aBody);
   }
-  nsresult Send(const RequestBody& aBody)
+  nsresult Send(JSContext *aCx, const RequestBody& aBody)
   {
-    return Send(Nullable<RequestBody>(aBody));
+    return Send(aCx, Nullable<RequestBody>(aBody));
   }
 
 public:
-  void Send(nsresult& aRv)
+  void Send(JSContext *aCx, nsresult& aRv)
   {
-    aRv = Send(Nullable<RequestBody>());
+    aRv = Send(aCx, Nullable<RequestBody>());
   }
-  void Send(JSObject* aArrayBuffer, nsresult& aRv)
+  void Send(JSContext *aCx, JSObject* aArrayBuffer, nsresult& aRv)
   {
     NS_ASSERTION(aArrayBuffer, "Null should go to string version");
-    aRv = Send(RequestBody(aArrayBuffer));
+    aRv = Send(aCx, RequestBody(aArrayBuffer));
   }
-  void Send(nsIDOMBlob* aBlob, nsresult& aRv)
+  void Send(JSContext *aCx, nsIDOMBlob* aBlob, nsresult& aRv)
   {
     NS_ASSERTION(aBlob, "Null should go to string version");
-    aRv = Send(RequestBody(aBlob));
+    aRv = Send(aCx, RequestBody(aBlob));
   }
-  void Send(nsIDocument* aDoc, nsresult& aRv)
+  void Send(JSContext *aCx, nsIDocument* aDoc, nsresult& aRv)
   {
     NS_ASSERTION(aDoc, "Null should go to string version");
-    aRv = Send(RequestBody(aDoc));
+    aRv = Send(aCx, RequestBody(aDoc));
   }
-  void Send(const nsAString& aString, nsresult& aRv)
+  void Send(JSContext *aCx, const nsAString& aString, nsresult& aRv)
   {
     if (DOMStringIsNull(aString)) {
-      Send(aRv);
+      Send(aCx, aRv);
     }
     else {
-      aRv = Send(RequestBody(aString));
+      aRv = Send(aCx, RequestBody(aString));
     }
   }
-  void Send(nsIDOMFormData* aFormData, nsresult& aRv)
+  void Send(JSContext *aCx, nsIDOMFormData* aFormData, nsresult& aRv)
   {
     NS_ASSERTION(aFormData, "Null should go to string version");
-    aRv = Send(RequestBody(aFormData));
+    aRv = Send(aCx, RequestBody(aFormData));
   }
-  void Send(nsIInputStream* aStream, nsresult& aRv)
+  void Send(JSContext *aCx, nsIInputStream* aStream, nsresult& aRv)
   {
     NS_ASSERTION(aStream, "Null should go to string version");
-    aRv = Send(RequestBody(aStream));
+    aRv = Send(aCx, RequestBody(aStream));
   }
-  void SendAsBinary(const nsAString& aBody, nsresult& aRv);
+  void SendAsBinary(JSContext *aCx, const nsAString& aBody, nsresult& aRv);
 
   void Abort();
 
   // response
   uint32_t GetStatus();
   void GetStatusText(nsString& aStatusText);
   void GetResponseHeader(const nsACString& aHeader, nsACString& aResult,
                          nsresult& aRv);
@@ -470,17 +471,17 @@ public:
   void SetMultipart(bool aMultipart, nsresult& aRv);
 
   nsIChannel* GetChannel()
   {
     return mChannel;
   }
 
   // We need a GetInterface callable from JS for chrome JS
-  JS::Value GetInterface(JSContext*aCx, nsIJSIID* aIID, nsresult& aRv);
+  JS::Value GetInterface(JSContext* aCx, nsIJSIID* aIID, nsresult& aRv);
 
   // This creates a trusted readystatechange event, which is not cancelable and
   // doesn't bubble.
   static nsresult CreateReadystatechangeEvent(nsIDOMEvent** aDOMEvent);
   // For backwards compatibility aPosition should contain the headers for upload
   // and aTotalSize is LL_MAXUINT when unknown. Both those values are
   // used by nsXMLHttpProgressEvent. Normal progress event should not use
   // headers in aLoaded and aTotal is 0 when unknown.
--- a/content/base/test/TestGetURL.cpp
+++ b/content/base/test/TestGetURL.cpp
@@ -74,17 +74,17 @@ nsresult TestGetURL(const nsCString& aUR
   TEST_ENSURE_SUCCESS(rv, "Couldn't get system principal!");
 
   rv = xhr->Init(systemPrincipal, nsnull, nsnull, nsnull);
   TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!");
 
   rv = xhr->Open(getString, aURL, false, empty, empty);
   TEST_ENSURE_SUCCESS(rv, "OpenRequest failed!");
 
-  rv = xhr->Send(nsnull);
+  rv = xhr->Send(nsnull, nsnull);
   TEST_ENSURE_SUCCESS(rv, "Send failed!");
 
   nsAutoString response;
   rv = xhr->GetResponseText(response);
   TEST_ENSURE_SUCCESS(rv, "GetResponse failed!");
 
   nsCAutoString responseUTF8 = NS_ConvertUTF16toUTF8(response);
   printf("#BEGIN\n");
--- a/content/base/test/TestNativeXMLHttpRequest.cpp
+++ b/content/base/test/TestNativeXMLHttpRequest.cpp
@@ -90,17 +90,17 @@ nsresult TestNativeXMLHttpRequest()
   TEST_ENSURE_SUCCESS(rv, "Couldn't get system principal!");
 
   rv = xhr->Init(systemPrincipal, nsnull, nsnull, nsnull);
   TEST_ENSURE_SUCCESS(rv, "Couldn't initialize the XHR!");
 
   rv = xhr->Open(getString, testURL, false, empty, empty);
   TEST_ENSURE_SUCCESS(rv, "Open failed!");
 
-  rv = xhr->Send(nsnull);
+  rv = xhr->Send(nsnull, nsnull);
   TEST_ENSURE_SUCCESS(rv, "Send failed!");
 
   nsAutoString response;
   rv = xhr->GetResponseText(response);
   TEST_ENSURE_SUCCESS(rv, "GetResponse failed!");
 
   if (!response.EqualsLiteral(TEST_URL_CONTENT)) {
     fail("Response text does not match!");
--- a/content/base/test/test_websocket_basic.html
+++ b/content/base/test/test_websocket_basic.html
@@ -1,179 +1,255 @@
 <!DOCTYPE HTML>
 <html>
-<!--
--->
 <head>
-  <title>Basic websocket test</title>
+  <title>Basic WebSocket test</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
+
 <body onload="testWebSocket()">
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=472529">Mozilla Bug </a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=472529">Mozilla Bug 472529</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
+const kUrl = "ws://mochi.test:8888/tests/content/base/test/file_websocket_basic";
+
+var gTestElement;
 var ws;
 
-var params = ["protocol", "resource", "origin", "end"];
-var results = ["test", "/tests/content/base/test/file_websocket_basic", "http://mochi.test:8888", "end"];
-
-function forcegc(){
+function forcegc() {
   SpecialPowers.forceGC();
   SpecialPowers.gc();
 }
 
-function finishWSTest() {
-    SimpleTest.finish();
+function testWebSocket() {
+  gTestElement = document.getElementById("test");
+
+  SimpleTest.executeSoon(testWebSocket1);
 }
 
-function testWebSocket () {
-  var url = "ws://mochi.test:8888/tests/content/base/test/file_websocket_basic";
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
-  is(ws.url, url, "Wrong Websocket.url!");
+/**
+ * Sends message keywords, then receives their values.
+ */
+function testWebSocket1() {
+  gTestElement.textContent = "Running testWebSocket1()";
+
+  var results = ["test",
+                 "/tests/content/base/test/file_websocket_basic",
+                 "http://mochi.test:8888",
+                 "end"];
+
+  ws = new WebSocket(kUrl, "test");
+  is(ws.url, kUrl, "[1] WebSocket.url");
   ws.onopen = function(e) {
+    const params = ["protocol", "resource", "origin", "end"];
+
+    gTestElement.textContent += "\nSending :";
     for (var i = 0; i < params.length; ++i) {
-      document.getElementById('log').textContent += "sending " + params[i] + "\n";
+      gTestElement.textContent += " " + params[i];
       ws.send(params[i]);
     }
-  }
+
+    // Set this before onmessage() is called, so it is displayed once only.
+    gTestElement.textContent += "\nReceived:";
+  };
   ws.onclose = function(e) {
-    is(results.length, 0, "All the messages should have been processed!");
-    ok(e.wasClean, "Connection closed cleanly");
-    testWebSocket2();
-  }
+    is(results.length, 0, "[1] Number of unreceived messages");
+    ok(e.wasClean, "[1] Connection closed cleanly");
+
+    SimpleTest.executeSoon(testWebSocket2);
+  };
   ws.onerror = function(e) {
-    ok(false, "onerror called!");
-    finishWSTest();
-  }
+    ok(false, "[1] onerror() should not have been called!");
+    gTestElement.textContent += "\nonerror() should not have been called!";
+    SimpleTest.executeSoon(SimpleTest.finish);
+  };
   ws.onmessage = function(e) {
-    document.getElementById('log').textContent += "\n" + e.data;
-    is(e.data, results[0], "Unexpected message");
+    is(e.data, results[0], "[1] Received message");
+    gTestElement.textContent += " " + e.data;
     results.shift();
-  }
+  };
 }
 
+/**
+ * Sends 1000+1 test messages, then receives them.
+ */
 function testWebSocket2() {
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
-  var testCount = 1000; // Send lots of messages
+  gTestElement.textContent = "Running testWebSocket2()";
+
+  const displayInterval = 100;
+  const testCount = 1000;
+  const testMessage = "test message 2.";
+
   var messageCount = 0;
-  var testMessage = "test message";
+
+  ws = new WebSocket(kUrl, "test");
   ws.onopen = function(e) {
-    for (var i = 0; i < testCount; ++i) {
-      ws.send(testMessage + (i + 1));
+    gTestElement.textContent += "\nSending :";
+    for (var i = 1; i <= testCount; ++i) {
+      if (i % displayInterval == 1) {
+        gTestElement.textContent += " " + i;
+      }
+      ws.send(testMessage + i);
     }
+    gTestElement.textContent += " end";
     ws.send("end");
-  }
+
+    // Set this before onmessage() is called, so it is displayed once only.
+    gTestElement.textContent += "\nReceived:";
+  };
   ws.onclose = function(e) {
-    is(messageCount, testCount, "Didn't receive all the messages!");
-    ok(e.wasClean, "Connection closed cleanly");
-    testWebSocket3();
-  }
+    is(messageCount, testCount + 1, "[2] Number of received messages");
+    ok(e.wasClean, "[2] Connection closed cleanly");
+
+    SimpleTest.executeSoon(testWebSocket3);
+  };
   ws.onerror = function(e) {
-    ok(false, "onerror called!");
-    finishWSTest();
-  }
+    ok(false, "[2] onerror() should not have been called!");
+    gTestElement.textContent += "\nonerror() should not have been called!";
+    SimpleTest.executeSoon(SimpleTest.finish);
+  };
   ws.onmessage = function(e) {
     ++messageCount;
-    is(e.data, testMessage + messageCount, "Wrong message");
-    document.getElementById('log').textContent = messageCount;
-    if (messageCount == testCount) {
-      this.onmessage = null;
+    if (messageCount > testCount)
+      is(e.data, "end", "[2] Received message");
+    else
+      is(e.data, testMessage + messageCount, "[2] Received message");
+    if (messageCount % displayInterval == 1) {
+      gTestElement.textContent += " " + messageCount;
     }
-  }
+  };
 }
 
+/**
+ * Sends 100+1 test messages, then receives them, calling forcegc() at each step.
+ */
 function testWebSocket3() {
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
-  var testCount = 100; // Send lots of messages
+  gTestElement.textContent = "Running testWebSocket3() [can take a little while]";
+
+  const displayInterval = 10;
+  const testCount = 100;
+  const testMessage = "test message 3.";
+
   var messageCount = 0;
-  var testMessage = "test message";
+
+  ws = new WebSocket(kUrl, "test");
+  // Set this before onopen() is called,
+  // otherwise its display would be delayed by forcegc() calls...
+  gTestElement.textContent += "\nSending :";
   ws.onopen = function(e) {
-    for (var i = 0; i < testCount; ++i) {
-      forcegc(); // Do something evil, call cycle collector a lot.
-      ws.send(testMessage + (i + 1));
+    for (var i = 1; i <= testCount; ++i) {
+      forcegc();
+      if (i % displayInterval == 1) {
+        // Actual display is delayed by forcegc() calls...
+        gTestElement.textContent += " " + i;
+      }
+      ws.send(testMessage + i);
     }
+    forcegc();
+    gTestElement.textContent += " end";
     ws.send("end");
-  }
+
+    // Set this before onmessage() is called, so it is displayed once only.
+    gTestElement.textContent += "\nReceived:";
+  };
   ws.onclose = function(e) {
-    is(messageCount, testCount, "Didn't receive all the messages!");
-    ok(e.wasClean, "Connection closed cleanly");
-    testWebSocket4();
-  }
+    is(messageCount, testCount + 1, "[3] Number of received messages");
+    ok(e.wasClean, "[3] Connection closed cleanly");
+
+    SimpleTest.executeSoon(testWebSocket4);
+  };
   ws.onerror = function(e) {
-    ok(false, "onerror called!");
-    finishWSTest();
-  }
+    ok(false, "[3] onerror() should not have been called!");
+    gTestElement.textContent += "\nonerror() should not have been called!";
+    SimpleTest.executeSoon(SimpleTest.finish);
+  };
   ws.onmessage = function(e) {
-    forcegc(); // Do something evil, call cycle collector a lot.
+    forcegc();
     ++messageCount;
-    is(e.data, testMessage + messageCount, "Wrong message");
-    document.getElementById('log').textContent = messageCount;
-    if (messageCount == testCount) {
-      this.onmessage = null;
+    if (messageCount > testCount)
+      is(e.data, "end", "[3] Received message");
+    else
+      is(e.data, testMessage + messageCount, "[3] Received message");
+    if (messageCount % displayInterval == 1) {
+      // Actual display is delayed by forcegc() call(s)...
+      gTestElement.textContent += " " + messageCount;
     }
-  }
+  };
 }
 
+/**
+ * Sends a huge test message, then receives it, then closes the WebSocket from client-side.
+ */
 function testWebSocket4() {
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
-  // String length = (10,000 - 1) * 23 = 229,977 = almost 225 KiB.
-  var longString = new Array(10000).join("-huge websocket message");
+  gTestElement.textContent = "Running testWebSocket4()";
+
+  // String length = 13 + ((10,000 - 1) * 26) + 11 = 259,998 = almost 254 KiB.
+  const longString = "messageStart " + new Array(10000).join(" -huge WebSocket message- ") + " messageEnd";
+
+  ws = new WebSocket(kUrl, "test");
   ws.onopen = function(e) {
-    is(this, ws, "'this' should point to the WebSocket. (1)");
+    is(this, ws, "[4, onopen()] 'this' should point to the WebSocket.");
+    gTestElement.textContent += "\nSending the huge message";
     ws.send(longString);
-  }
+  };
   ws.onclose = function(e) {
-    is(this, ws, "'this' should point to the WebSocket. (2)");
-    ok(e.wasClean, "Connection closed cleanly");
-    testWebSocket5();
-  }
+    is(this, ws, "[4, onclose()] 'this' should point to the WebSocket.");
+    ok(e.wasClean, "[4] Connection closed cleanly");
+
+    SimpleTest.executeSoon(testWebSocket5);
+  };
   ws.onerror = function(e) {
-    ok(false, "onerror called!");
-    finishWSTest();
-  }
+    is(this, ws, "[4, onerror()] 'this' should point to the WebSocket.");
+    ok(false, "[4, onerror()] should not have been called!");
+    gTestElement.textContent += "\nonerror() should not have been called!";
+    SimpleTest.executeSoon(SimpleTest.finish);
+  };
   ws.onmessage = function(e) {
-    is(this, ws, "'this' should point to the WebSocket. (3)");
+    is(this, ws, "[4, onmessage()] 'this' should point to the WebSocket.");
     // Do not use |is(e.data, longString, "...");| that results in a _very_ long line.
-    is(e.data.length, longString.length, "Length of received message");
-    ok(e.data == longString, "Content of received message");
-    document.getElementById('log').textContent += "\nReceived the huge message";
+    is(e.data.length, longString.length, "[4] Length of received message");
+    ok(e.data == longString, "[4] Content of received message");
+    gTestElement.textContent += "\nReceived the huge message";
     this.close();
-  }
+  };
 }
 
+/**
+ * Closes the WebSocket from client-side, then sends a test message that should be buffered.
+ */
 function testWebSocket5() {
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
+  gTestElement.textContent = "Running testWebSocket5()";
+
+  ws = new WebSocket(kUrl, "test");
   ws.onopen = function(e) {
+    is(this.bufferedAmount, 0, "[5] Length of empty buffer before closing");
     this.close();
-  }
+  };
   ws.onclose = function(e) {
-    ok(e.wasClean, "Connection closed cleanly");
-    is(this.bufferedAmount, 0, "Shouldn't have anything buffered");
-    var msg = "some data";
+    ok(e.wasClean, "[5] Connection closed cleanly");
+    is(this.bufferedAmount, 0, "[5] Length of empty buffer after closing");
+
+    var msg = "test message to be buffered";
     this.send(msg);
-    is(this.bufferedAmount, msg.length, "Should have some data buffered");
-    finishWSTest();
-  }
+    is(this.bufferedAmount, msg.length, "[5] Length of buffered message sent after closing");
+
+    gTestElement.textContent += "\ntestWebSocket5() completed";
+
+    SimpleTest.executeSoon(SimpleTest.finish);
+  };
   ws.onerror = function(e) {
-    ok(false, "onerror called!");
-    finishWSTest();
-  }
+    ok(false, "[5] onerror() should not have been called!");
+    gTestElement.textContent += "\nonerror() should not have been called!";
+    SimpleTest.executeSoon(SimpleTest.finish);
+  };
 }
 
 SimpleTest.waitForExplicitFinish();
 
 </script>
-<pre id="log">
 </pre>
-</pre>
-<div>
-
-
-</div>
-
-
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/content/canvas/crashtests/743499-negative-size.html
@@ -0,0 +1,22 @@
+<html>
+<head>
+    <title></title>
+    <script type="text/javascript">
+        function go() {
+        var canvas = document.createElement("canvas");
+        var ctx = canvas.getContext('2d');
+        ctx.globalAlpha = 4
+        ctx.lineCap = "foo"
+        ctx.strokeRect(256,1024,8,4)
+        ctx.shadowColor = "black"
+        ctx.shadowOffsetY = 64
+        ctx.stroke()
+        ctx.moveTo(32,1024)
+        ctx.closePath()
+        }
+    </script>
+</head>
+<body onload="go()">
+<canvas id="canvas"></canvas>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/canvas/crashtests/745818-large-source.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+
+function boom()
+{
+  var a = document.getElementById("a");
+  var b = document.getElementById("b");
+  a.getContext('2d').createPattern(b, 'no-repeat');
+}
+
+</script>
+</head>
+
+<body onload="boom();">
+<canvas id="a" width="61" height="26"></canvas>
+<canvas id="b" width="611" height="439807"></canvas>
+</body>
+
+</html>
--- a/content/canvas/crashtests/crashtests.list
+++ b/content/canvas/crashtests/crashtests.list
@@ -1,8 +1,11 @@
 load 360293-1.html
 load 421715-1.html
 load 553938-1.html
 load 647480.html
 load 0px-size-font-667225.html
 load texImage2D.html
 load 729116.html
 load 745699-1.html
+# this test crashes in a bunch places still
+#load 745818-large-source.html
+load 743499-negative-size.html
--- a/content/canvas/src/CustomQS_Canvas2D.h
+++ b/content/canvas/src/CustomQS_Canvas2D.h
@@ -40,16 +40,17 @@
 
 #include "nsDOMError.h"
 #include "nsIDOMCanvasRenderingContext2D.h"
 #include "CheckedInt.h"
 #include "nsMathUtils.h"
 #include "CustomQS_Canvas.h"
 
 #include "jsapi.h"
+#include "jsfriendapi.h"
 
 typedef NS_STDCALL_FUNCPROTO(nsresult, CanvasStyleSetterType, nsIDOMCanvasRenderingContext2D,
                              SetStrokeStyle_multi, (const nsAString &, nsISupports *));
 typedef NS_STDCALL_FUNCPROTO(nsresult, CanvasStyleGetterType, nsIDOMCanvasRenderingContext2D,
                              GetStrokeStyle_multi, (nsAString &, nsISupports **, PRInt32 *));
 
 static JSBool
 Canvas2D_SetStyleHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
@@ -168,18 +169,17 @@ CreateImageData(JSContext* cx, JSObject*
         h = 1;
 
     CheckedInt<uint32_t> len = CheckedInt<uint32_t>(w) * h * 4;
     if (!len.valid()) {
         return xpc_qsThrow(cx, NS_ERROR_DOM_INDEX_SIZE_ERR);
     }
 
     // Create the fast typed array; it's initialized to 0 by default.
-    JSObject* darray =
-      js_CreateTypedArray(cx, js::TypedArray::TYPE_UINT8_CLAMPED, len.value());
+    JSObject* darray = JS_NewUint8ClampedArray(cx, len.value());
     JS::AutoObjectRooter rd(cx, darray);
     if (!darray) {
         return false;
     }
 
     XPCLazyCallContext lccx(JS_CALLER, cx, obj);
     const nsIID *iid = &NS_GET_IID(nsIDOMImageData);
     nsRefPtr<mozilla::dom::ImageData> imageData =
@@ -300,34 +300,38 @@ nsIDOMCanvasRenderingContext2D_PutImageD
         dirtyWidth = JS_DoubleToInt32(dw);
         dirtyHeight = JS_DoubleToInt32(dh);
 
         hasDirtyRect = true;
     }
 
     JS::AutoValueRooter tsrc_tvr(cx);
 
-    JSObject *tsrc = NULL;
-    if (js::GetObjectClass(darray.get()) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8] ||
-        js::GetObjectClass(darray.get()) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_UINT8_CLAMPED])
+    JSObject * tsrc = NULL;
+    if (JS_IsInt8Array(darray.get(), cx) ||
+        JS_IsUint8Array(darray.get(), cx) ||
+        JS_IsUint8ClampedArray(darray.get(), cx))
     {
         tsrc = darray.get();
-    } else if (JS_IsArrayObject(cx, darray.get()) || js_IsTypedArray(darray.get())) {
+    } else if (JS_IsTypedArrayObject(darray.get(), cx) || JS_IsArrayObject(cx, darray.get())) {
         // ugh, this isn't a uint8 typed array, someone made their own object; convert it to a typed array
-        JSObject *nobj = js_CreateTypedArrayWithArray(cx, js::TypedArray::TYPE_UINT8, darray.get());
+        JSObject *nobj = JS_NewUint8ClampedArrayFromArray(cx, darray.get());
         if (!nobj)
             return JS_FALSE;
 
         *tsrc_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj);
-        tsrc = js::TypedArray::getTypedArray(nobj);
+        tsrc = nobj;
     } else {
         // yeah, no.
         return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR);
     }
 
     // make the call
-    rv = self->PutImageData_explicit(x, y, w, h, static_cast<PRUint8*>(JS_GetTypedArrayData(tsrc)), JS_GetTypedArrayByteLength(tsrc), hasDirtyRect, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
+    MOZ_ASSERT(JS_IsTypedArrayObject(tsrc, cx));
+    PRUint8* data = reinterpret_cast<PRUint8*>(JS_GetArrayBufferViewData(tsrc, cx));
+    uint32_t byteLength = JS_GetTypedArrayByteLength(tsrc, cx);
+    rv = self->PutImageData_explicit(x, y, w, h, data, byteLength, hasDirtyRect, dirtyX, dirtyY, dirtyWidth, dirtyHeight);
     if (NS_FAILED(rv))
         return xpc_qsThrowMethodFailed(cx, rv, vp);
 
     *vp = JSVAL_VOID;
     return JS_TRUE;
 }
--- a/content/canvas/src/CustomQS_WebGL.h
+++ b/content/canvas/src/CustomQS_WebGL.h
@@ -36,17 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /*
  * Intended to be #included in dom_quickstubs.cpp via qsconf!
  */
 
 #include "jsapi.h"
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 #include "CustomQS_Canvas.h"
 
 #define GET_INT32_ARG(var, index) \
   int32_t var; \
   do { \
     if (!JS_ValueToECMAInt32(cx, argv[index], &(var))) \
       return JS_FALSE; \
   } while (0)
@@ -79,20 +79,20 @@ public:
         , target(aTarget)
         , level(aLevel)
         , internalformat(aInternalformat)
         , format(aFormat)
         , type(aType)
     {}
 
     nsresult DoCallForImageData(WebGLsizei width, WebGLsizei height,
-                                JSObject* pixels)
+                                JSObject* pixels, JSContext *cx)
     {
         return self->TexImage2D_imageData(target, level, internalformat, width,
-                                          height, 0, format, type, pixels);
+                                          height, 0, format, type, pixels, cx);
     }
     nsresult DoCallForElement(mozilla::dom::Element* elt)
     {
         return self->TexImage2D_dom(target, level, internalformat, format, type,
                                     elt);
     }
 };
 
@@ -121,21 +121,21 @@ public:
         , level(aLevel)
         , xoffset(aXoffset)
         , yoffset(aYoffset)
         , format(aFormat)
         , type(aType)
     {}
 
     nsresult DoCallForImageData(WebGLsizei width, WebGLsizei height,
-                                JSObject* pixels)
+                                JSObject* pixels, JSContext *cx)
     {
         return self->TexSubImage2D_imageData(target, level, xoffset, yoffset,
                                              width, height, format, type,
-                                             pixels);
+                                             pixels, cx);
     }
     nsresult DoCallForElement(mozilla::dom::Element* elt)
     {
         return self->TexSubImage2D_dom(target, level, xoffset, yoffset, format,
                                        type, elt);
     }
 };
 
@@ -155,21 +155,21 @@ TexImage2DImageDataOrElement(JSContext* 
 
     // Failed to interpret object as an Element, now try to interpret it as
     // ImageData.
     uint32_t int_width, int_height;
     JS::Anchor<JSObject*> obj_data;
     if (!GetImageData(cx, *object, &int_width, &int_height, &obj_data)) {
         return false;
     }
-    if (!js_IsTypedArray(obj_data.get())) {
+    if (!JS_IsTypedArrayObject(obj_data.get(), cx)) {
         return xpc_qsThrow(cx, NS_ERROR_FAILURE);
     }
 
-    nsresult rv = self.DoCallForImageData(int_width, int_height, obj_data.get());
+    nsresult rv = self.DoCallForImageData(int_width, int_height, obj_data.get(), cx);
     return NS_SUCCEEDED(rv) || xpc_qsThrow(cx, rv);
 }
 
 /*
  * TexImage2D takes:
  *    TexImage2D(uint, int, uint, int, int, int, uint, uint, ArrayBufferView)
  *    TexImage2D(uint, int, uint, uint, uint, nsIDOMElement)
  *    TexImage2D(uint, int, uint, uint, uint, ImageData)
@@ -220,21 +220,21 @@ nsIDOMWebGLRenderingContext_TexImage2D(J
         GET_UINT32_ARG(argv7, 7);
 
         JSObject *argv8 = JSVAL_TO_OBJECT(argv[8]);
 
         // then try to grab either a js::TypedArray, or null
         if (argv8 == nsnull) {
             rv = self->TexImage2D_array(argv0, argv1, argv2, argv3,
                                         argv4, argv5, argv6, argv7,
-                                        nsnull);
-        } else if (js_IsTypedArray(argv8)) {
+                                        nsnull, cx);
+        } else if (JS_IsTypedArrayObject(argv8, cx)) {
             rv = self->TexImage2D_array(argv0, argv1, argv2, argv3,
                                         argv4, argv5, argv6, argv7,
-                                        js::TypedArray::getTypedArray(argv8));
+                                        argv8, cx);
         } else {
             xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
             return JS_FALSE;
         }
     } else {
         xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
         return JS_FALSE;
     }
@@ -292,20 +292,20 @@ nsIDOMWebGLRenderingContext_TexSubImage2
         // implement the variants taking a buffer/array as argv[8]
         GET_INT32_ARG(argv4, 4);
         GET_INT32_ARG(argv5, 5);
         GET_UINT32_ARG(argv6, 6);
         GET_UINT32_ARG(argv7, 7);
 
         JSObject *argv8 = JSVAL_TO_OBJECT(argv[8]);
         // try to grab a js::TypedArray
-        if (js_IsTypedArray(argv8)) {
+        if (JS_IsTypedArrayObject(argv8, cx)) {
             rv = self->TexSubImage2D_array(argv0, argv1, argv2, argv3,
                                            argv4, argv5, argv6, argv7,
-                                           js::TypedArray::getTypedArray(argv8));
+                                           argv8, cx);
         } else {
             xpc_qsThrowBadArg(cx, NS_ERROR_FAILURE, vp, 8);
             return JS_FALSE;
         }
     } else {
         xpc_qsThrow(cx, NS_ERROR_XPC_NOT_ENOUGH_ARGS);
         return JS_FALSE;
     }
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -66,20 +66,35 @@
 
 #include "nsSVGEffects.h"
 
 #include "prenv.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
+#include "nsIObserverService.h"
+
+
 using namespace mozilla;
 using namespace mozilla::gl;
 using namespace mozilla::layers;
 
+NS_IMPL_ISUPPORTS1(WebGLMemoryPressureObserver, nsIObserver)
+
+NS_IMETHODIMP
+WebGLMemoryPressureObserver::Observe(nsISupports* aSubject,
+                                     const char* aTopic,
+                                     const PRUnichar* aSomeData)
+{
+  if (strcmp(aTopic, "memory-pressure") == 0)
+    mContext->ForceLoseContext();
+  return NS_OK;
+}
+
 
 nsresult NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult);
 
 nsresult
 NS_NewCanvasRenderingContextWebGL(nsIDOMWebGLRenderingContext** aResult)
 {
     Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
     nsIDOMWebGLRenderingContext* ctx = new WebGLContext();
@@ -162,35 +177,44 @@ WebGLContext::WebGLContext()
     
     // See OpenGL ES 2.0.25 spec, 6.2 State Tables, table 6.13
     mPixelStorePackAlignment = 4;
     mPixelStoreUnpackAlignment = 4;
 
     WebGLMemoryMultiReporterWrapper::AddWebGLContext(this);
 
     mAllowRestore = true;
-    mRobustnessTimerRunning = false;
-    mDrawSinceRobustnessTimerSet = false;
+    mContextLossTimerRunning = false;
+    mDrawSinceContextLossTimerSet = false;
     mContextRestorer = do_CreateInstance("@mozilla.org/timer;1");
     mContextStatus = ContextStable;
     mContextLostErrorSet = false;
-    mContextLostDueToTest = false;
 }
 
 WebGLContext::~WebGLContext()
 {
     DestroyResourcesAndContext();
     WebGLMemoryMultiReporterWrapper::RemoveWebGLContext(this);
-    TerminateRobustnessTimer();
+    TerminateContextLossTimer();
     mContextRestorer = nsnull;
 }
 
 void
 WebGLContext::DestroyResourcesAndContext()
 {
+    if (mMemoryPressureObserver) {
+        nsCOMPtr<nsIObserverService> observerService
+            = mozilla::services::GetObserverService();
+        if (observerService) {
+            observerService->RemoveObserver(mMemoryPressureObserver,
+                                            "memory-pressure");
+        }
+        mMemoryPressureObserver = nsnull;
+    }
+
     if (!gl)
         return;
 
     gl->MakeCurrent();
 
     mBound2DTextures.Clear();
     mBoundCubeMapTextures.Clear();
     mBoundArrayBuffer = nsnull;
@@ -1025,17 +1049,24 @@ WebGLContext::DummyFramebufferOperation(
 // fires.
 // Note that this timer mechanism is not used unless one of these 3 criteria
 // are met.
 // At a bare minimum, from context lost to context restores, it would take 3
 // full timer iterations: detection, webglcontextlost, webglcontextrestored.
 NS_IMETHODIMP
 WebGLContext::Notify(nsITimer* timer)
 {
-    TerminateRobustnessTimer();
+    TerminateContextLossTimer();
+
+    if (!HTMLCanvasElement()) {
+        // the canvas is gone. That happens when the page was closed before we got
+        // this timer event. In this case, there's nothing to do here, just don't crash.
+        return NS_OK;
+    }
+
     // If the context has been lost and we're waiting for it to be restored, do
     // that now.
     if (mContextStatus == ContextLostAwaitingEvent) {
         bool defaultAction;
         nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
                                              (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
                                              NS_LITERAL_STRING("webglcontextlost"),
                                              true,
@@ -1048,36 +1079,35 @@ WebGLContext::Notify(nsITimer* timer)
 
         // If the script handled the event and we are allowing restores, then
         // mark it to be restored. Otherwise, leave it as context lost
         // (unusable).
         if (!defaultAction && mAllowRestore) {
             ForceRestoreContext();
             // Restart the timer so that it will be restored on the next
             // callback.
-            SetupRobustnessTimer();
+            SetupContextLossTimer();
         } else {
             mContextStatus = ContextLost;
         }
     } else if (mContextStatus == ContextLostAwaitingRestore) {
         // Try to restore the context. If it fails, try again later.
         if (NS_FAILED(SetDimensions(mWidth, mHeight))) {
-            SetupRobustnessTimer();
+            SetupContextLossTimer();
             return NS_OK;
         }
         mContextStatus = ContextStable;
         nsContentUtils::DispatchTrustedEvent(HTMLCanvasElement()->OwnerDoc(),
                                              (nsIDOMHTMLCanvasElement*) HTMLCanvasElement(),
                                              NS_LITERAL_STRING("webglcontextrestored"),
                                              true,
                                              true);
         // Set all flags back to the state they were in before the context was
         // lost.
         mContextLostErrorSet = false;
-        mContextLostDueToTest = false;
         mAllowRestore = true;
     }
 
     MaybeRestoreContext();
     return NS_OK;
 }
 
 void
@@ -1085,24 +1115,16 @@ WebGLContext::MaybeRestoreContext()
 {
     // Don't try to handle it if we already know it's busted.
     if (mContextStatus != ContextStable || gl == nsnull)
         return;
 
     bool isEGL = gl->GetContextType() == GLContext::ContextTypeEGL,
          isANGLE = gl->IsANGLE();
 
-    // If was lost due to a forced context loss, don't try to handle it.
-    // Also, we also don't try to handle if if we don't have robustness.
-    // Note that the code in this function is used only for situations where
-    // we have an actual context loss, and not a simulated one.
-    if (mContextLostDueToTest ||
-        (!mHasRobustness && !isEGL))
-        return;
-
     GLContext::ContextResetARB resetStatus = GLContext::CONTEXT_NO_ERROR;
     if (mHasRobustness) {
         gl->MakeCurrent();
         resetStatus = (GLContext::ContextResetARB) gl->fGetGraphicsResetStatus();
     } else if (isEGL) {
         // Simulate a ARB_robustness guilty context loss for when we
         // get an EGL_CONTEXT_LOST error. It may not actually be guilty,
         // but we can't make any distinction, so we must assume the worst
@@ -1118,18 +1140,18 @@ WebGLContext::MaybeRestoreContext()
         ForceLoseContext();
     }
 
     switch (resetStatus) {
         case GLContext::CONTEXT_NO_ERROR:
             // If there has been activity since the timer was set, it's possible
             // that we did or are going to miss something, so clear this flag and
             // run it again some time later.
-            if (mDrawSinceRobustnessTimerSet)
-                SetupRobustnessTimer();
+            if (mDrawSinceContextLossTimerSet)
+                SetupContextLossTimer();
             break;
         case GLContext::CONTEXT_GUILTY_CONTEXT_RESET_ARB:
             NS_WARNING("WebGL content on the page caused the graphics card to reset; not restoring the context");
             mAllowRestore = false;
             break;
         case GLContext::CONTEXT_INNOCENT_CONTEXT_RESET_ARB:
             break;
         case GLContext::CONTEXT_UNKNOWN_CONTEXT_RESET_ARB:
@@ -1143,19 +1165,22 @@ WebGLContext::MaybeRestoreContext()
             }
             break;
     }
 }
 
 void
 WebGLContext::ForceLoseContext()
 {
+    if (mContextStatus == ContextLostAwaitingEvent)
+        return;
+
     mContextStatus = ContextLostAwaitingEvent;
     // Queue up a task to restore the event.
-    SetupRobustnessTimer();
+    SetupContextLossTimer();
     DestroyResourcesAndContext();
 }
 
 void
 WebGLContext::ForceRestoreContext()
 {
     mContextStatus = ContextLostAwaitingRestore;
 }
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -54,16 +54,17 @@
 #include "nsICanvasRenderingContextInternal.h"
 #include "nsHTMLCanvasElement.h"
 #include "nsWeakReference.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIMemoryReporter.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsContentUtils.h"
 #include "nsWrapperCache.h"
+#include "nsIObserver.h"
 
 #include "GLContextProvider.h"
 #include "Layers.h"
 
 #include "CheckedInt.h"
 #include "nsDataHashtable.h"
 
 #ifdef XP_MACOSX
@@ -98,18 +99,19 @@ namespace mozilla {
 class WebGLTexture;
 class WebGLBuffer;
 class WebGLProgram;
 class WebGLShader;
 class WebGLFramebuffer;
 class WebGLRenderbuffer;
 class WebGLUniformLocation;
 class WebGLExtension;
+class WebGLContext;
 struct WebGLVertexAttribData;
-
+class WebGLMemoryPressureObserver;
 class WebGLRectangleObject;
 class WebGLContextBoundObject;
 
 enum FakeBlackStatus { DoNotNeedFakeBlack, DoNeedFakeBlack, DontKnowIfNeedFakeBlack };
 
 struct VertexAttrib0Status {
     enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray };
 };
@@ -521,16 +523,17 @@ class WebGLContext :
     public nsICanvasRenderingContextInternal,
     public nsSupportsWeakReference,
     public nsITimerCallback,
     public WebGLRectangleObject
 {
     friend class WebGLMemoryMultiReporterWrapper;
     friend class WebGLExtensionLoseContext;
     friend class WebGLContextUserData;
+    friend class WebGLMemoryPressureObserver;
 
 public:
     WebGLContext();
     virtual ~WebGLContext();
 
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(WebGLContext, nsIDOMWebGLRenderingContext)
@@ -634,49 +637,37 @@ public:
         GLenum currentGLError;
         UpdateWebGLErrorAndClearGLError(&currentGLError);
     }
     
     bool MinCapabilityMode() const {
         return mMinCapability;
     }
 
-    // See the comment over WebGLContext::Notify() for more information on this.
-    bool ShouldEnableRobustnessTimer() {
-        return mHasRobustness ||
-               IsExtensionEnabled(WebGL_MOZ_WEBGL_lose_context) ||
-               (gl != nsnull && gl->GetContextType() == gl::GLContext::ContextTypeEGL);
-    }
-
-    // Sets up the GL_ARB_robustness timer if it isn't already, so that if the
-    // driver gets restarted, the context may get reset with it.
-    void SetupRobustnessTimer() {
-        if (!ShouldEnableRobustnessTimer())
-            return;
-
+    void SetupContextLossTimer() {
         // If the timer was already running, don't restart it here. Instead,
         // wait until the previous call is done, then fire it one more time.
         // This is an optimization to prevent unnecessary cross-communication
         // between threads.
-        if (mRobustnessTimerRunning) {
-            mDrawSinceRobustnessTimerSet = true;
+        if (mContextLossTimerRunning) {
+            mDrawSinceContextLossTimerSet = true;
             return;
         }
         
         mContextRestorer->InitWithCallback(static_cast<nsITimerCallback*>(this),
                                            PR_MillisecondsToInterval(1000),
                                            nsITimer::TYPE_ONE_SHOT);
-        mRobustnessTimerRunning = true;
-        mDrawSinceRobustnessTimerSet = false;
+        mContextLossTimerRunning = true;
+        mDrawSinceContextLossTimerSet = false;
     }
 
-    void TerminateRobustnessTimer() {
-        if (mRobustnessTimerRunning) {
+    void TerminateContextLossTimer() {
+        if (mContextLossTimerRunning) {
             mContextRestorer->Cancel();
-            mRobustnessTimerRunning = false;
+            mContextLossTimerRunning = false;
         }
     }
 
 protected:
     void SetDontKnowIfNeedFakeBlack() {
         mFakeBlackStatus = DontKnowIfNeedFakeBlack;
     }
 
@@ -695,21 +686,21 @@ protected:
                                       PRUint32 alignment);
 
     // Returns x rounded to the next highest multiple of y.
     static CheckedUint32 RoundedToNextMultipleOf(CheckedUint32 x, CheckedUint32 y) {
         return ((x + y - 1) / y) * y;
     }
 
     nsresult BufferData_size(WebGLenum target, WebGLsizei size, WebGLenum usage);
-    nsresult BufferData_buf(WebGLenum target, JSObject* data, WebGLenum usage);
-    nsresult BufferData_array(WebGLenum target, JSObject* data, WebGLenum usage);
-
-    nsresult BufferSubData_buf(WebGLenum target, PRInt32 offset, JSObject* data);
-    nsresult BufferSubData_array(WebGLenum target, PRInt32 offset, JSObject* data);
+    nsresult BufferData_buf(WebGLenum target, JSObject* data, WebGLenum usage, JSContext *cx);
+    nsresult BufferData_array(WebGLenum target, JSObject* data, WebGLenum usage, JSContext *cx);
+
+    nsresult BufferSubData_buf(WebGLenum target, PRInt32 offset, JSObject* data, JSContext *cx);
+    nsresult BufferSubData_array(WebGLenum target, PRInt32 offset, JSObject* data, JSContext *cx);
 
     nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
 
     nsRefPtr<gl::GLContext> gl;
 
     CheckedUint32 mGeneration;
 
     WebGLContextOptions mOptions;
@@ -950,31 +941,31 @@ protected:
     WebGLfloat mColorClearValue[4];
     WebGLint mStencilClearValue;
     WebGLfloat mDepthClearValue;
 
     int mBackbufferClearingStatus;
 
     nsCOMPtr<nsITimer> mContextRestorer;
     bool mAllowRestore;
-    bool mRobustnessTimerRunning;
-    bool mDrawSinceRobustnessTimerSet;
+    bool mContextLossTimerRunning;
+    bool mDrawSinceContextLossTimerSet;
     ContextStatus mContextStatus;
     bool mContextLostErrorSet;
-    bool mContextLostDueToTest;
 
 #ifdef XP_MACOSX
     // see bug 713305. This RAII helper guarantees that we're on the discrete GPU, during its lifetime
     // Debouncing note: we don't want to switch GPUs too frequently, so try to not create and destroy
     // these objects at high frequency. Having WebGLContext's hold one such object seems fine,
     // because WebGLContext objects only go away during GC, which shouldn't happen too frequently.
     // If in the future GC becomes much more frequent, we may have to revisit then (maybe use a timer).
     ForceDiscreteGPUHelperCGL mForceDiscreteGPUHelper;
 #endif
 
+    nsRefPtr<WebGLMemoryPressureObserver> mMemoryPressureObserver;
 
 public:
     // console logging helpers
     static void LogMessage(const char *fmt, ...);
     static void LogMessage(const char *fmt, va_list ap);
     void LogMessageIfVerbose(const char *fmt, ...);
     void LogMessageIfVerbose(const char *fmt, va_list ap);
 
@@ -2883,11 +2874,26 @@ class WebGLMemoryMultiReporterWrapper
         return result;
     }
 
     static PRInt64 GetContextCount() {
         return Contexts().Length();
     }
 };
 
+class WebGLMemoryPressureObserver MOZ_FINAL
+    : public nsIObserver
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+
+  WebGLMemoryPressureObserver(WebGLContext *context)
+    : mContext(context)
+  {}
+
+private:
+  WebGLContext *mContext;
+};
+
 }
 
 #endif
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -49,17 +49,17 @@
 //#include "nsIDOMHTMLCanvasElement.h"
 
 #include "nsContentUtils.h"
 #include "nsDOMError.h"
 #include "nsLayoutUtils.h"
 
 #include "CanvasUtils.h"
 
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 
 #include "WebGLTexelConversions.h"
 #include "WebGLValidateStrings.h"
 
 // needed to check if current OS is lower than 10.7
 #if defined(MOZ_WIDGET_COCOA)
 #include "nsCocoaFeatures.h"
 #endif
@@ -199,16 +199,19 @@ WebGLContext::BindAttribLocation(nsIWebG
     MakeContextCurrent();
     gl->fBindAttribLocation(progname, location, mappedName.get());
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindBuffer(WebGLenum target, nsIWebGLBuffer *bobj)
 {
+    if (!IsContextStable())
+        return NS_OK;
+
     WebGLuint bufname;
     WebGLBuffer* buf;
     bool isNull; // allow null objects
     bool isDeleted; // allow deleted objects
     if (!GetConcreteObjectAndGLName("bindBuffer", bobj, &buf, &bufname, &isNull, &isDeleted))
         return NS_OK;
 
     // silently ignore a deleted buffer
@@ -241,16 +244,19 @@ WebGLContext::BindBuffer(WebGLenum targe
     gl->fBindBuffer(target, bufname);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindFramebuffer(WebGLenum target, nsIWebGLFramebuffer *fbobj)
 {
+    if (!IsContextStable())
+        return NS_OK;
+
     WebGLuint framebuffername;
     bool isNull; // allow null objects
     bool isDeleted; // allow deleted objects
     WebGLFramebuffer *wfb;
 
     if (target != LOCAL_GL_FRAMEBUFFER)
         return ErrorInvalidEnum("BindFramebuffer: target must be GL_FRAMEBUFFER");
 
@@ -273,16 +279,19 @@ WebGLContext::BindFramebuffer(WebGLenum 
     mBoundFramebuffer = wfb;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindRenderbuffer(WebGLenum target, nsIWebGLRenderbuffer *rbobj)
 {
+    if (!IsContextStable())
+        return NS_OK;
+
     WebGLuint renderbuffername;
     bool isNull; // allow null objects
     bool isDeleted; // allow deleted objects
     WebGLRenderbuffer *wrb;
 
     if (target != LOCAL_GL_RENDERBUFFER)
         return ErrorInvalidEnumInfo("bindRenderbuffer: target", target);
 
@@ -303,16 +312,19 @@ WebGLContext::BindRenderbuffer(WebGLenum
     mBoundRenderbuffer = wrb;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::BindTexture(WebGLenum target, nsIWebGLTexture *tobj)
 {
+    if (!IsContextStable())
+        return NS_OK;
+
     WebGLuint texturename;
     WebGLTexture *tex;
     bool isNull; // allow null objects
     bool isDeleted; // allow deleted objects
     if (!GetConcreteObjectAndGLName("bindTexture", tobj, &tex, &texturename, &isNull, &isDeleted))
         return NS_OK;
 
     // silently ignore a deleted texture
@@ -438,22 +450,22 @@ WebGLContext::BufferData(PRInt32 target,
 {
     if (data.isNull()) {
         // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
         return ErrorInvalidValue("bufferData: null object passed");
     }
 
     if (data.isObject()) {
         JSObject& dataObj = data.toObject();
-        if (js_IsArrayBuffer(&dataObj)) {
-            return BufferData_buf(target, &dataObj, usage);
+        if (JS_IsArrayBufferObject(&dataObj, cx)) {
+            return BufferData_buf(target, &dataObj, usage, cx);
         }
 
-        if (js_IsTypedArray(&dataObj)) {
-            return BufferData_array(target, &dataObj, usage);
+        if (JS_IsTypedArrayObject(&dataObj, cx)) {
+            return BufferData_array(target, &dataObj, usage, cx);
         }
 
         return ErrorInvalidValue("bufferData: object passed that is not an "
                                  "ArrayBufferView or ArrayBuffer");
     }
 
     MOZ_ASSERT(data.isPrimitive());
     int32_t size;
@@ -499,21 +511,24 @@ WebGLContext::BufferData_size(WebGLenum 
     boundBuffer->InvalidateCachedMaxElements();
     if (!boundBuffer->ZeroDataIfElementArray())
         return ErrorOutOfMemory("bufferData: out of memory");
 
     return NS_OK;
 }
 
 nsresult
-WebGLContext::BufferData_buf(WebGLenum target, JSObject *wb, WebGLenum usage)
+WebGLContext::BufferData_buf(WebGLenum target, JSObject *wb, WebGLenum usage, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
+    if (!JS_IsArrayBufferObject(wb, cx))
+        return ErrorInvalidOperation("BufferData: incorrect type");
+
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
         return ErrorInvalidEnumInfo("bufferData: target", target);
@@ -523,34 +538,34 @@ WebGLContext::BufferData_buf(WebGLenum t
         return NS_OK;
 
     if (!boundBuffer)
         return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     MakeContextCurrent();
 
     GLenum error = CheckedBufferData(target,
-                                     JS_GetArrayBufferByteLength(wb),
-                                     JS_GetArrayBufferData(wb),
+                                     JS_GetArrayBufferByteLength(wb, cx),
+                                     JS_GetArrayBufferData(wb, cx),
                                      usage);
     if (error) {
         LogMessageIfVerbose("bufferData generated error %s", ErrorName(error));
         return NS_OK;
     }
 
-    boundBuffer->SetByteLength(JS_GetArrayBufferByteLength(wb));
+    boundBuffer->SetByteLength(JS_GetArrayBufferByteLength(wb, cx));
     boundBuffer->InvalidateCachedMaxElements();
-    if (!boundBuffer->CopyDataIfElementArray(JS_GetArrayBufferData(wb)))
+    if (!boundBuffer->CopyDataIfElementArray(JS_GetArrayBufferData(wb, cx)))
         return ErrorOutOfMemory("bufferData: out of memory");
 
     return NS_OK;
 }
 
 nsresult
-WebGLContext::BufferData_array(WebGLenum target, JSObject *wa, WebGLenum usage)
+WebGLContext::BufferData_array(WebGLenum target, JSObject *wa, WebGLenum usage, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
@@ -563,133 +578,144 @@ WebGLContext::BufferData_array(WebGLenum
     if (!ValidateBufferUsageEnum(usage, "bufferData: usage"))
         return NS_OK;
 
     if (!boundBuffer)
         return ErrorInvalidOperation("BufferData: no buffer bound!");
 
     MakeContextCurrent();
 
-    GLenum error = CheckedBufferData(target,
-                                     JS_GetTypedArrayByteLength(wa),
-                                     JS_GetTypedArrayData(wa),
-                                     usage);
+    if (!JS_IsTypedArrayObject(wa, cx))
+        return ErrorInvalidOperation("BufferData: incorrect type");
+
+    uint32_t byteLength = JS_GetTypedArrayByteLength(wa, cx);
+    void *data = JS_GetArrayBufferViewData(wa, cx);
+    GLenum error = CheckedBufferData(target, byteLength, data, usage);
     if (error) {
         LogMessageIfVerbose("bufferData generated error %s", ErrorName(error));
         return NS_OK;
     }
 
-    boundBuffer->SetByteLength(JS_GetTypedArrayByteLength(wa));
+    boundBuffer->SetByteLength(byteLength);
     boundBuffer->InvalidateCachedMaxElements();
-    if (!boundBuffer->CopyDataIfElementArray(JS_GetTypedArrayData(wa)))
+    if (!boundBuffer->CopyDataIfElementArray(data))
         return ErrorOutOfMemory("bufferData: out of memory");
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-WebGLContext::BufferSubData(PRInt32 target, PRInt32 offset, const JS::Value& data)
+WebGLContext::BufferSubData(PRInt32 target, PRInt32 offset, const JS::Value& data, JSContext *cx)
 {
+    if (!IsContextStable())
+        return NS_OK;
+
     if (data.isNull()) {
         // see http://www.khronos.org/bugzilla/show_bug.cgi?id=386
         return NS_OK;
     }
 
     if (!data.isObject()) {
         return NS_ERROR_FAILURE;
     }
 
     JSObject& dataObj = data.toObject();
-    if (js_IsArrayBuffer(&dataObj)) {
-        return BufferSubData_buf(target, offset, &dataObj);
+    if (JS_IsArrayBufferObject(&dataObj, cx)) {
+        return BufferSubData_buf(target, offset, &dataObj, cx);
     }
 
-    if (js_IsTypedArray(&dataObj)) {
-        return BufferSubData_array(target, offset, &dataObj);
+    if (JS_IsTypedArrayObject(&dataObj, cx)) {
+        return BufferSubData_array(target, offset, &dataObj, cx);
     }
 
     return NS_ERROR_FAILURE;
 }
 
 nsresult
-WebGLContext::BufferSubData_buf(GLenum target, WebGLsizei byteOffset, JSObject *wb)
+WebGLContext::BufferSubData_buf(GLenum target, WebGLsizei byteOffset, JSObject *wb, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
+    if (!JS_IsArrayBufferObject(wb, cx))
+        return ErrorInvalidOperation("BufferSubData: incorrect type");
+
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
         return ErrorInvalidEnumInfo("bufferSubData: target", target);
     }
 
     if (byteOffset < 0)
         return ErrorInvalidValue("bufferSubData: negative offset");
 
     if (!boundBuffer)
         return ErrorInvalidOperation("BufferData: no buffer bound!");
 
-    CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetArrayBufferByteLength(wb);
+    CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetArrayBufferByteLength(wb, cx);
     if (!checked_neededByteLength.valid())
         return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
 
     if (checked_neededByteLength.value() > boundBuffer->ByteLength())
         return ErrorInvalidOperation("BufferSubData: not enough data - operation requires %d bytes, but buffer only has %d bytes",
-                                     byteOffset, JS_GetArrayBufferByteLength(wb), boundBuffer->ByteLength());
+                                     byteOffset, JS_GetArrayBufferByteLength(wb, cx), boundBuffer->ByteLength());
 
     MakeContextCurrent();
 
-    boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetArrayBufferByteLength(wb), JS_GetArrayBufferData(wb));
+    boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetArrayBufferByteLength(wb, cx), JS_GetArrayBufferData(wb, cx));
     boundBuffer->InvalidateCachedMaxElements();
 
-    gl->fBufferSubData(target, byteOffset, JS_GetArrayBufferByteLength(wb), JS_GetArrayBufferData(wb));
+    gl->fBufferSubData(target, byteOffset, JS_GetArrayBufferByteLength(wb, cx), JS_GetArrayBufferData(wb, cx));
 
     return NS_OK;
 }
 
 nsresult
-WebGLContext::BufferSubData_array(WebGLenum target, WebGLsizei byteOffset, JSObject *wa)
+WebGLContext::BufferSubData_array(WebGLenum target, WebGLsizei byteOffset, JSObject *wa, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
+    if (!JS_IsTypedArrayObject(wa, cx))
+        return ErrorInvalidOperation("BufferSubData: incorrect type");
+
     WebGLBuffer *boundBuffer = NULL;
 
     if (target == LOCAL_GL_ARRAY_BUFFER) {
         boundBuffer = mBoundArrayBuffer;
     } else if (target == LOCAL_GL_ELEMENT_ARRAY_BUFFER) {
         boundBuffer = mBoundElementArrayBuffer;
     } else {
         return ErrorInvalidEnumInfo("bufferSubData: target", target);
     }
 
     if (byteOffset < 0)
         return ErrorInvalidValue("bufferSubData: negative offset");
 
     if (!boundBuffer)
         return ErrorInvalidOperation("BufferData: no buffer bound!");
 
-    CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetTypedArrayByteLength(wa);
+    CheckedUint32 checked_neededByteLength = CheckedUint32(byteOffset) + JS_GetTypedArrayByteLength(wa, cx);
     if (!checked_neededByteLength.valid())
         return ErrorInvalidOperation("bufferSubData: integer overflow computing the needed byte length");
 
     if (checked_neededByteLength.value() > boundBuffer->ByteLength())
         return ErrorInvalidOperation("BufferSubData: not enough data -- operation requires %d bytes, but buffer only has %d bytes",
-                                     byteOffset, JS_GetTypedArrayByteLength(wa), boundBuffer->ByteLength());
+                                     byteOffset, JS_GetTypedArrayByteLength(wa, cx), boundBuffer->ByteLength());
 
     MakeContextCurrent();
 
-    boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetTypedArrayByteLength(wa), JS_GetTypedArrayData(wa));
+    boundBuffer->CopySubDataIfElementArray(byteOffset, JS_GetTypedArrayByteLength(wa, cx), JS_GetArrayBufferViewData(wa, cx));
     boundBuffer->InvalidateCachedMaxElements();
 
-    gl->fBufferSubData(target, byteOffset, JS_GetTypedArrayByteLength(wa), JS_GetTypedArrayData(wa));
+    gl->fBufferSubData(target, byteOffset, JS_GetTypedArrayByteLength(wa, cx), JS_GetArrayBufferViewData(wa, cx));
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::CheckFramebufferStatus(WebGLenum target, WebGLenum *retval)
 {
     if (!IsContextStable())
@@ -1623,17 +1649,17 @@ WebGLContext::DrawArrays(GLenum mode, We
     } else {
         EnsureBackbufferClearedAsNeeded();
     }
 
     BindFakeBlackTextures();
     if (!DoFakeVertexAttrib0(checked_firstPlusCount.value()))
         return NS_OK;
 
-    SetupRobustnessTimer();
+    SetupContextLossTimer();
     gl->fDrawArrays(mode, first, count);
 
     UndoFakeVertexAttrib0();
     UnbindFakeBlackTextures();
 
     mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
     Invalidate();
 
@@ -1734,17 +1760,17 @@ WebGLContext::DrawElements(WebGLenum mod
     } else {
         EnsureBackbufferClearedAsNeeded();
     }
 
     BindFakeBlackTextures();
     if (!DoFakeVertexAttrib0(checked_maxIndexPlusOne.value()))
         return NS_OK;
 
-    SetupRobustnessTimer();
+    SetupContextLossTimer();
     gl->fDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(byteOffset));
 
     UndoFakeVertexAttrib0();
     UnbindFakeBlackTextures();
 
     mBackbufferClearingStatus = BackbufferClearingStatus::HasBeenDrawnTo;
     Invalidate();
 
@@ -2070,21 +2096,21 @@ WebGLContext::GetAttribLocation(nsIWebGL
     MakeContextCurrent();
     *retval = gl->fGetAttribLocation(progname, mappedName.get());
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
 {
+    *retval = nsnull;
+
     if (!IsContextStable())
         return NS_OK;
 
-    *retval = nsnull;
-
     nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
     NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
 
     MakeContextCurrent();
     
     if (MinCapabilityMode()) {
         bool override = true;
         switch(pname) {
@@ -2838,21 +2864,21 @@ WebGLContext::TexParameteri(WebGLenum ta
         return NS_OK;
 
     return TexParameter_base(target, pname, &param, nsnull);
 }
 
 NS_IMETHODIMP
 WebGLContext::GetTexParameter(WebGLenum target, WebGLenum pname, nsIVariant **retval)
 {
+    *retval = nsnull;
+
     if (!IsContextStable())
         return NS_OK;
 
-    *retval = nsnull;
-
     MakeContextCurrent();
 
     if (!ValidateTextureTargetEnum(target, "getTexParameter: target"))
         return NS_OK;
 
     if (!activeBoundTextureForTarget(target))
         return ErrorInvalidOperation("getTexParameter: no texture bound");
 
@@ -2888,21 +2914,21 @@ WebGLContext::GetTexParameter(WebGLenum 
 
     return NS_OK;
 }
 
 /* any getUniform(in WebGLProgram program, in WebGLUniformLocation location) raises(DOMException); */
 NS_IMETHODIMP
 WebGLContext::GetUniform(nsIWebGLProgram *pobj, nsIWebGLUniformLocation *ploc, nsIVariant **retval)
 {
+    *retval = nsnull;
+
     if (!IsContextStable())
         return NS_OK;
 
-    *retval = nsnull;
-
     WebGLuint progname;
     WebGLProgram *prog;
     if (!GetConcreteObjectAndGLName("getUniform: program", pobj, &prog, &progname))
         return NS_OK;
 
     WebGLUniformLocation *location;
     if (!GetConcreteObject("getUniform: location", ploc, &location))
         return NS_OK;
@@ -3046,21 +3072,21 @@ WebGLContext::GetUniformLocation(nsIWebG
     }
     *retval = loc;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetVertexAttrib(WebGLuint index, WebGLenum pname, nsIVariant **retval)
 {
+    *retval = nsnull;
+
     if (!IsContextStable())
         return NS_OK;
 
-    *retval = nsnull;
-
     if (!ValidateAttribIndex(index, "getVertexAttrib"))
         return NS_OK;
 
     nsCOMPtr<nsIWritableVariant> wrval = do_CreateInstance("@mozilla.org/variant;1");
     NS_ENSURE_TRUE(wrval, NS_ERROR_FAILURE);
 
     MakeContextCurrent();
 
@@ -3361,19 +3387,23 @@ WebGLContext::PixelStorei(WebGLenum pnam
     return NS_OK;
 }
 
 
 GL_SAME_METHOD_2(PolygonOffset, PolygonOffset, WebGLfloat, WebGLfloat)
 
 NS_IMETHODIMP
 WebGLContext::ReadPixels(WebGLint x, WebGLint y, WebGLsizei width, WebGLsizei height,
-                         WebGLenum format, WebGLenum type, const JS::Value& pixelsVal)
+                         WebGLenum format, WebGLenum type, const JS::Value& pixelsVal, JSContext *cx)
 {
-    if (!pixelsVal.isObject() || !js_IsTypedArray(&pixelsVal.toObject())) {
+    if (!pixelsVal.isObject()) {
+        return NS_ERROR_FAILURE;
+    }
+
+    if (!JS_IsTypedArrayObject(&pixelsVal.toObject(), cx)) {
         return NS_ERROR_FAILURE;
     }
 
     JSObject& pixels = pixelsVal.toObject();
 
     if (!IsContextStable()) {
         return NS_OK;
     }
@@ -3385,19 +3415,19 @@ WebGLContext::ReadPixels(WebGLint x, Web
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("ReadPixels: negative size passed");
 
     const WebGLRectangleObject *framebufferRect = FramebufferRectangleObject();
     WebGLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
     WebGLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
 
-    void* data = JS_GetTypedArrayData(&pixels);
-    PRUint32 dataByteLen = JS_GetTypedArrayByteLength(&pixels);
-    int dataType = JS_GetTypedArrayType(&pixels);
+    void* data = JS_GetArrayBufferViewData(&pixels, cx);
+    PRUint32 dataByteLen = JS_GetTypedArrayByteLength(&pixels, cx);
+    int dataType = JS_GetTypedArrayType(&pixels, cx);
 
     PRUint32 channels = 0;
 
     // Check the format param
     switch (format) {
         case LOCAL_GL_ALPHA:
             channels = 1;
             break;
@@ -3413,23 +3443,23 @@ WebGLContext::ReadPixels(WebGLint x, Web
 
     PRUint32 bytesPerPixel = 0;
     int requiredDataType = 0;
 
     // Check the type param
     switch (type) {
         case LOCAL_GL_UNSIGNED_BYTE:
             bytesPerPixel = 1 * channels;
-            requiredDataType = js::TypedArray::TYPE_UINT8;
+            requiredDataType = js::ArrayBufferView::TYPE_UINT8;
             break;
         case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
         case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
         case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
             bytesPerPixel = 2;
-            requiredDataType = js::TypedArray::TYPE_UINT16;
+            requiredDataType = js::ArrayBufferView::TYPE_UINT16;
             break;
         default:
             return ErrorInvalidEnum("readPixels: Bad type");
     }
 
     // Check the pixels param type
     if (dataType != requiredDataType)
         return ErrorInvalidOperation("readPixels: Mismatched type/pixels types");
@@ -4085,41 +4115,42 @@ WebGLContext::DOMElementToImageSurface(E
         default:
             NS_ASSERTION(false, "Unsupported image format. Unimplemented.");
             return NS_ERROR_NOT_IMPLEMENTED;
     }
 
     return NS_OK;
 }
 
-template<size_t type>
+template<JSBool TypedArrayTest(JSObject* obj, JSContext* cx),
+         JSObject* TypedArrayCopy(JSContext* cx, JSObject* src)>
 static JSObject*
 GetTypedArray(JSContext* aCx, const JS::Value& aValue)
 {
     if (!aValue.isObject()) {
         return NULL;
     }
 
     JSObject& value = aValue.toObject();
 
-    if (js::GetObjectClass(&value) == &js::TypedArray::fastClasses[type]) {
+    if (TypedArrayTest(&value, aCx)) {
         return &value;
     }
 
     if (JS_IsArrayObject(aCx, &value)) {
-        return js_CreateTypedArrayWithArray(aCx, type, &value);
+        return TypedArrayCopy(aCx, &value);
     }
 
     return NULL;
 }
 
 static JSObject*
 GetFloat32Array(JSContext* aCx, const JS::Value& aValue)
 {
-    return GetTypedArray<js::TypedArray::TYPE_FLOAT32>(aCx, aValue);
+    return GetTypedArray<JS_IsFloat32Array, JS_NewFloat32ArrayFromArray>(aCx, aValue);
 }
 
 #define OBTAIN_UNIFORM_LOCATION(info)                                   \
     WebGLUniformLocation *location_object;                              \
     bool isNull;                                                      \
     if (!GetConcreteObject(info, ploc, &location_object, &isNull))      \
         return NS_OK;                                                   \
     if (isNull)                                                         \
@@ -4133,39 +4164,36 @@ GetFloat32Array(JSContext* aCx, const JS
         return ErrorInvalidOperation("%s: This uniform location is obsolete since the program has been relinked", info); \
     GLint location = location_object->Location();
 
 #define SIMPLE_ARRAY_METHOD_UNIFORM(name, cnt, arrayType, ptrType)              \
 NS_IMETHODIMP                                                                   \
 WebGLContext::name(nsIWebGLUniformLocation *aLocation, const JS::Value& aValue, \
                    JSContext* aCx)                                              \
 {                                                                               \
-    JSObject* wa = GetTypedArray<js::TypedArray::arrayType>(aCx, aValue);       \
+    JSObject* wa = GetTypedArray<JS_Is ## arrayType ## Array, JS_New ## arrayType ## ArrayFromArray>(aCx, aValue); \
     if (!wa) {                                                                  \
         return NS_ERROR_FAILURE;                                                \
     }                                                                           \
                                                                                 \
     if (!IsContextStable()) {                                                   \
         return NS_OK;                                                           \
     }                                                                           \
                                                                                 \
     nsIWebGLUniformLocation* ploc = aLocation;                                  \
     OBTAIN_UNIFORM_LOCATION(#name ": location")                                 \
-    if (JS_GetTypedArrayType(wa) != js::TypedArray::arrayType) {                \
-        return ErrorInvalidOperation(#name ": array must be " #arrayType);      \
-    }                                                                           \
     int elementSize = location_object->ElementSize();                           \
     if (cnt != elementSize) {                                                   \
         return ErrorInvalidOperation(                                           \
             #name ": this function expected a uniform of element size %d,"      \
             " got a uniform of element size %d",                                \
             cnt,                                                                \
             elementSize);                                                       \
     }                                                                           \
-    PRUint32 arrayLength = JS_GetTypedArrayLength(wa);                          \
+    PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx);                     \
     const WebGLUniformInfo& info = location_object->Info();                     \
     PRUint32 expectedArrayLength = cnt * info.arraySize;                        \
     if (arrayLength < expectedArrayLength ||                                    \
         (arrayLength % cnt))                                                    \
     {                                                                           \
         return ErrorInvalidValue("%s: expected an array of length a multiple of" \
                                  " %d and at least %d, got an array of length %d", \
                                  #name,                                         \
@@ -4180,17 +4208,17 @@ WebGLContext::name(nsIWebGLUniformLocati
                                      " got an array of length %d", \
                                  #name,                                         \
                                  expectedArrayLength,                           \
                                  arrayLength);                                  \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
     gl->f##name(location, info.arraySize,                                       \
-                static_cast<ptrType*>(JS_GetTypedArrayData(wa)));               \
+                static_cast<ptrType*>(JS_GetArrayBufferViewData(wa, aCx)));     \
     return NS_OK;                                                               \
 }
 
 #define SIMPLE_MATRIX_METHOD_UNIFORM(name, dim)                                 \
 NS_IMETHODIMP                                                                   \
 WebGLContext::name(nsIWebGLUniformLocation* aLocation, bool aTranspose,         \
                    const JS::Value& aValue, JSContext* aCx)                     \
 {                                                                               \
@@ -4200,28 +4228,28 @@ WebGLContext::name(nsIWebGLUniformLocati
     }                                                                           \
                                                                                 \
     if (!IsContextStable()) {                                                   \
         return NS_OK;                                                           \
     }                                                                           \
                                                                                 \
     nsIWebGLUniformLocation* ploc = aLocation;                                  \
     OBTAIN_UNIFORM_LOCATION(#name ": location")                                 \
-    if (JS_GetTypedArrayType(wa) != js::TypedArray::TYPE_FLOAT32) {             \
+    if (!wa || !JS_IsFloat32Array(wa, aCx)) {                                   \
         return ErrorInvalidValue(#name ": array must be of Float32 type");      \
     }                                                                           \
     int elementSize = location_object->ElementSize();                           \
     if (dim*dim != elementSize) {                                               \
         return ErrorInvalidOperation(                                           \
             #name ": this function expected a uniform of element size %d,"      \
             " got a uniform of element size %d",                                \
             dim*dim,                                                            \
             elementSize);                                                       \
     }                                                                           \
-    PRUint32 arrayLength = JS_GetTypedArrayLength(wa);                          \
+    PRUint32 arrayLength = JS_GetTypedArrayLength(wa, aCx);                     \
     const WebGLUniformInfo& info = location_object->Info();                     \
     PRUint32 expectedArrayLength = dim * dim * info.arraySize;                  \
     if (arrayLength < expectedArrayLength ||                                    \
         (arrayLength % (dim*dim)))                                              \
     {                                                                           \
         return ErrorInvalidValue("%s: expected an array of length a multiple of" \
                                  " %d and at least %d, got an array of length %d", \
                                  #name,                                         \
@@ -4240,17 +4268,17 @@ WebGLContext::name(nsIWebGLUniformLocati
     }                                                                           \
     if (aTranspose) {                                                           \
         return ErrorInvalidValue(#name ": transpose must be FALSE as per the "  \
                                  "OpenGL ES 2.0 spec");                         \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
     gl->f##name(location, info.arraySize, false,                  \
-                static_cast<WebGLfloat*>(JS_GetTypedArrayData(wa)));            \
+                static_cast<WebGLfloat*>(JS_GetArrayBufferViewData(wa, aCx)));  \
     return NS_OK;                                                               \
 }
 
 #define SIMPLE_METHOD_UNIFORM_1(glname, name, t1)        \
 NS_IMETHODIMP WebGLContext::name(nsIWebGLUniformLocation *ploc, t1 a1) {      \
     if (!IsContextStable())                                    \
         return NS_OK;                                    \
     OBTAIN_UNIFORM_LOCATION(#name ": location") \
@@ -4286,25 +4314,25 @@ SIMPLE_METHOD_UNIFORM_2(Uniform2i, Unifo
 SIMPLE_METHOD_UNIFORM_3(Uniform3i, Uniform3i, WebGLint, WebGLint, WebGLint)
 SIMPLE_METHOD_UNIFORM_4(Uniform4i, Uniform4i, WebGLint, WebGLint, WebGLint, WebGLint)
 
 SIMPLE_METHOD_UNIFORM_1(Uniform1f, Uniform1f, WebGLfloat)
 SIMPLE_METHOD_UNIFORM_2(Uniform2f, Uniform2f, WebGLfloat, WebGLfloat)
 SIMPLE_METHOD_UNIFORM_3(Uniform3f, Uniform3f, WebGLfloat, WebGLfloat, WebGLfloat)
 SIMPLE_METHOD_UNIFORM_4(Uniform4f, Uniform4f, WebGLfloat, WebGLfloat, WebGLfloat, WebGLfloat)
 
-SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1iv, 1, TYPE_INT32, WebGLint)
-SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2iv, 2, TYPE_INT32, WebGLint)
-SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3iv, 3, TYPE_INT32, WebGLint)
-SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4iv, 4, TYPE_INT32, WebGLint)
-
-SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1fv, 1, TYPE_FLOAT32, WebGLfloat)
-SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2fv, 2, TYPE_FLOAT32, WebGLfloat)
-SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3fv, 3, TYPE_FLOAT32, WebGLfloat)
-SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4fv, 4, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1iv, 1, Int32, WebGLint)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2iv, 2, Int32, WebGLint)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3iv, 3, Int32, WebGLint)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4iv, 4, Int32, WebGLint)
+
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform1fv, 1, Float32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform2fv, 2, Float32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform3fv, 3, Float32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_UNIFORM(Uniform4fv, 4, Float32, WebGLfloat)
 
 SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix2fv, 2)
 SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix3fv, 3)
 SIMPLE_MATRIX_METHOD_UNIFORM(UniformMatrix4fv, 4)
 
 NS_IMETHODIMP
 WebGLContext::VertexAttrib1f(PRUint32 index, WebGLfloat x0)
 {
@@ -4389,55 +4417,52 @@ WebGLContext::VertexAttrib4f(PRUint32 in
         mVertexAttrib0Vector[3] = x3;
         if (gl->IsGLES2())
             gl->fVertexAttrib4f(index, x0, x1, x2, x3);
     }
 
     return NS_OK;
 }
 
-#define SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, arrayType, ptrType)             \
+#define SIMPLE_ARRAY_METHOD_NO_COUNT(name, cnt, ptrType)                        \
 NS_IMETHODIMP                                                                   \
 WebGLContext::name(WebGLuint idx, const JS::Value& aValue, JSContext* aCx)      \
 {                                                                               \
     JSObject* wa = GetFloat32Array(aCx, aValue);                                \
     if (!wa) {                                                                  \
         return NS_ERROR_FAILURE;                                                \
     }                                                                           \
                                                                                 \
     if (!IsContextStable()) {                                                   \
         return NS_OK;                                                           \
     }                                                                           \
-    if (JS_GetTypedArrayType(wa) != js::TypedArray::arrayType) {                \
-        return ErrorInvalidOperation(#name ": array must be " #arrayType);      \
-    }                                                                           \
-    if (JS_GetTypedArrayLength(wa) < cnt) {                                     \
+    if (JS_GetTypedArrayLength(wa, aCx) < cnt) {                                \
         return ErrorInvalidOperation(#name ": array must be >= %d elements",    \
                                      cnt);                                      \
     }                                                                           \
                                                                                 \
     MakeContextCurrent();                                                       \
-    ptrType *ptr = static_cast<ptrType*>(JS_GetTypedArrayData(wa));             \
+    ptrType *ptr = static_cast<ptrType*>(JS_GetFloat32ArrayData(wa, aCx));      \
     if (idx) {                                                                  \
         gl->f##name(idx, ptr);                                                  \
     } else {                                                                    \
         mVertexAttrib0Vector[0] = ptr[0];                                       \
         mVertexAttrib0Vector[1] = cnt > 1 ? ptr[1] : ptrType(0);                \
         mVertexAttrib0Vector[2] = cnt > 2 ? ptr[2] : ptrType(0);                \
         mVertexAttrib0Vector[3] = cnt > 3 ? ptr[3] : ptrType(1);                \
         if (gl->IsGLES2())                                                      \
             gl->f##name(idx, ptr);                                              \
     }                                                                           \
     return NS_OK;                                                               \
 }
 
-SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, TYPE_FLOAT32, WebGLfloat)
-SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, TYPE_FLOAT32, WebGLfloat)
-SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, 3, TYPE_FLOAT32, WebGLfloat)
-SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, TYPE_FLOAT32, WebGLfloat)
+SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib1fv, 1, WebGLfloat)
+SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib2fv, 2, WebGLfloat)
+SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib3fv, 3, WebGLfloat)
+SIMPLE_ARRAY_METHOD_NO_COUNT(VertexAttrib4fv, 4, WebGLfloat)
 
 NS_IMETHODIMP
 WebGLContext::UseProgram(nsIWebGLProgram *pobj)
 {
     if (!IsContextStable())
         return NS_OK;
 
     WebGLProgram *prog;
@@ -4713,19 +4738,19 @@ WebGLContext::CompileShader(nsIWebGLShad
 #endif
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::CompressedTexImage2D(WebGLenum target, WebGLint level, WebGLenum internalformat,
                                    WebGLsizei width, WebGLsizei height, WebGLint border,
-                                   const JS::Value& pixels)
+                                   const JS::Value& pixels, JSContext *cx)
 {
-    if (!pixels.isObject() || !js_IsTypedArray(&pixels.toObject())) {
+    if (!pixels.isObject() || !JS_IsTypedArrayObject(&pixels.toObject(), cx)) {
         return NS_ERROR_FAILURE;
     }
 
     if (!IsContextStable()) {
         return NS_OK;
     }
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
@@ -4733,19 +4758,19 @@ WebGLContext::CompressedTexImage2D(WebGL
         return ErrorInvalidOperation("compressedTexImage2D: no texture is bound to this target");
 
     return ErrorInvalidEnum("compressedTexImage2D: compressed textures are not supported");
 }
 
 NS_IMETHODIMP
 WebGLContext::CompressedTexSubImage2D(WebGLenum target, WebGLint level, WebGLint xoffset,
                                       WebGLint yoffset, WebGLsizei width, WebGLsizei height,
-                                      WebGLenum format, const JS::Value& pixels)
+                                      WebGLenum format, const JS::Value& pixels, JSContext *cx)
 {
-    if (!pixels.isObject() || !js_IsTypedArray(&pixels.toObject())) {
+    if (!pixels.isObject() || !JS_IsTypedArrayObject(&pixels.toObject(), cx)) {
         return NS_ERROR_FAILURE;
     }
 
     if (!IsContextStable()) {
         return NS_OK;
     }
 
     WebGLTexture *tex = activeBoundTextureForTarget(target);
@@ -5205,40 +5230,45 @@ WebGLContext::TexImage2D_base(WebGLenum 
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::TexImage2D_array(WebGLenum target, WebGLint level, WebGLenum internalformat,
                                WebGLsizei width, WebGLsizei height, WebGLint border,
                                WebGLenum format, WebGLenum type,
-                               JSObject *pixels)
+                               JSObject *pixels, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
+    if (pixels && !JS_IsTypedArrayObject(pixels, cx))
+        return ErrorInvalidValue("TexSubImage2D: pixels are wrong type!");
+
     return TexImage2D_base(target, level, internalformat, width, height, 0, border, format, type,
-                           pixels ? JS_GetTypedArrayData(pixels) : 0,
-                           pixels ? JS_GetTypedArrayByteLength(pixels) : 0,
-                           pixels ? (int)JS_GetTypedArrayType(pixels) : -1,
+                           pixels ? JS_GetArrayBufferViewData(pixels, cx) : 0,
+                           pixels ? JS_GetArrayBufferViewByteLength(pixels, cx) : 0,
+                           pixels ? (int)JS_GetTypedArrayType(pixels, cx) : -1,
                            WebGLTexelFormat::Auto, false);
 }
 
 NS_IMETHODIMP
 WebGLContext::TexImage2D_imageData(WebGLenum target, WebGLint level, WebGLenum internalformat,
-                               WebGLsizei width, WebGLsizei height, WebGLint border,
-                               WebGLenum format, WebGLenum type,
-                               JSObject *pixels)
+                                   WebGLsizei width, WebGLsizei height, WebGLint border,
+                                   WebGLenum format, WebGLenum type,
+                                   JSObject *pixels, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
+    NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(pixels, cx), "bad pixels object");
+
     return TexImage2D_base(target, level, internalformat, width, height, 4*width, border, format, type,
-                           pixels ? JS_GetTypedArrayData(pixels) : 0,
-                           pixels ? JS_GetTypedArrayByteLength(pixels) : 0,
+                           pixels ? JS_GetArrayBufferViewData(pixels, cx) : 0,
+                           pixels ? JS_GetArrayBufferViewByteLength(pixels, cx) : 0,
                            -1,
                            WebGLTexelFormat::RGBA8, false);
 }
 
 NS_IMETHODIMP
 WebGLContext::TexImage2D_dom(WebGLenum target, WebGLint level, WebGLenum internalformat,
                              WebGLenum format, GLenum type, Element* elt)
 {
@@ -5386,47 +5416,51 @@ WebGLContext::TexSubImage2D_base(WebGLen
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::TexSubImage2D_array(WebGLenum target, WebGLint level,
                                   WebGLint xoffset, WebGLint yoffset,
                                   WebGLsizei width, WebGLsizei height,
                                   WebGLenum format, WebGLenum type,
-                                  JSObject *pixels)
+                                  JSObject *pixels, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
     if (!pixels)
         return ErrorInvalidValue("TexSubImage2D: pixels must not be null!");
 
+    NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(pixels, cx), "bad pixels object");
+
     return TexSubImage2D_base(target, level, xoffset, yoffset,
                               width, height, 0, format, type,
-                              JS_GetTypedArrayData(pixels), JS_GetTypedArrayByteLength(pixels),
-                              JS_GetTypedArrayType(pixels),
+                              JS_GetArrayBufferViewData(pixels, cx), JS_GetArrayBufferViewByteLength(pixels, cx),
+                              JS_GetTypedArrayType(pixels, cx),
                               WebGLTexelFormat::Auto, false);
 }
 
 NS_IMETHODIMP
 WebGLContext::TexSubImage2D_imageData(WebGLenum target, WebGLint level,
                                       WebGLint xoffset, WebGLint yoffset,
                                       WebGLsizei width, WebGLsizei height,
                                       WebGLenum format, WebGLenum type,
-                                      JSObject *pixels)
+                                      JSObject *pixels, JSContext *cx)
 {
     if (!IsContextStable())
         return NS_OK;
 
     if (!pixels)
         return ErrorInvalidValue("TexSubImage2D: pixels must not be null!");
 
+    NS_ABORT_IF_FALSE(JS_IsTypedArrayObject(pixels, cx), "bad pixels object");
+
     return TexSubImage2D_base(target, level, xoffset, yoffset,
                               width, height, 4*width, format, type,
-                              JS_GetTypedArrayData(pixels), JS_GetTypedArrayByteLength(pixels),
+                              JS_GetArrayBufferViewData(pixels, cx), JS_GetArrayBufferViewByteLength(pixels, cx),
                               -1,
                               WebGLTexelFormat::RGBA8, false);
 }
 
 NS_IMETHODIMP
 WebGLContext::TexSubImage2D_dom(WebGLenum target, WebGLint level,
                                 WebGLint xoffset, WebGLint yoffset,
                                 WebGLenum format, WebGLenum type,
@@ -5454,17 +5488,16 @@ WebGLContext::TexSubImage2D_dom(WebGLenu
 }
 
 bool
 WebGLContext::LoseContext()
 {
     if (!IsContextStable())
         return false;
 
-    mContextLostDueToTest = true;
     ForceLoseContext();
 
     return true;
 }
 
 bool
 WebGLContext::RestoreContext()
 {
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -38,24 +38,26 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "WebGLContext.h"
 
 #include "mozilla/Preferences.h"
 
 #include "CheckedInt.h"
 
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 
 #if defined(USE_ANGLE)
 #include "angle/ShaderLang.h"
 #endif
 
 #include <algorithm>
 
+#include "nsIObserverService.h"
+
 using namespace mozilla;
 
 /*
  * Pull data out of the program, post-linking
  */
 bool
 WebGLProgram::UpdateInfo()
 {
@@ -399,20 +401,20 @@ PRUint32 WebGLContext::GetTexelSize(WebG
 
 bool WebGLContext::ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
                                               PRUint32 *texelSize, const char *info)
 {
     if (type == LOCAL_GL_UNSIGNED_BYTE ||
         (IsExtensionEnabled(WebGL_OES_texture_float) && type == LOCAL_GL_FLOAT))
     {
         if (jsArrayType != -1) {
-            if ((type == LOCAL_GL_UNSIGNED_BYTE && jsArrayType != js::TypedArray::TYPE_UINT8) ||
-                (type == LOCAL_GL_FLOAT && jsArrayType != js::TypedArray::TYPE_FLOAT32))
+            if ((type == LOCAL_GL_UNSIGNED_BYTE && jsArrayType != js::ArrayBufferView::TYPE_UINT8) ||
+                (type == LOCAL_GL_FLOAT && jsArrayType != js::ArrayBufferView::TYPE_FLOAT32))
             {
-                ErrorInvalidOperation("%s: invalid typed array type for given format", info);
+                ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
                 return false;
             }
         }
 
         int texMultiplier = type == LOCAL_GL_FLOAT ? 4 : 1;
         switch (format) {
             case LOCAL_GL_ALPHA:
             case LOCAL_GL_LUMINANCE:
@@ -433,31 +435,31 @@ bool WebGLContext::ValidateTexFormatAndT
 
         ErrorInvalidEnum("%s: invalid format 0x%x", info, format);
         return false;
     }
 
     switch (type) {
         case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
         case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
-            if (jsArrayType != -1 && jsArrayType != js::TypedArray::TYPE_UINT16) {
-                ErrorInvalidOperation("%s: invalid typed array type for given format", info);
+            if (jsArrayType != -1 && jsArrayType != js::ArrayBufferView::TYPE_UINT16) {
+                ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
                 return false;
             }
 
             if (format == LOCAL_GL_RGBA) {
                 *texelSize = 2;
                 return true;
             }
             ErrorInvalidOperation("%s: mutually incompatible format and type", info);
             return false;
 
         case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
-            if (jsArrayType != -1 && jsArrayType != js::TypedArray::TYPE_UINT16) {
-                ErrorInvalidOperation("%s: invalid typed array type for given format", info);
+            if (jsArrayType != -1 && jsArrayType != js::ArrayBufferView::TYPE_UINT16) {
+                ErrorInvalidOperation("%s: invalid typed array type for given texture data type", info);
                 return false;
             }
 
             if (format == LOCAL_GL_RGB) {
                 *texelSize = 2;
                 return true;
             }
             ErrorInvalidOperation("%s: mutually incompatible format and type", info);
@@ -674,10 +676,20 @@ WebGLContext::InitAndValidateGL()
     // notice that the point of calling GetAndClearError here is not only to check for error,
     // it is also to reset the error flags so that a subsequent WebGL getError call will give the correct result.
     error = gl->GetAndClearError();
     if (error != LOCAL_GL_NO_ERROR) {
         LogMessage("GL error 0x%x occurred during WebGL context initialization!", error);
         return false;
     }
 
+    mMemoryPressureObserver
+        = new WebGLMemoryPressureObserver(this);
+    nsCOMPtr<nsIObserverService> observerService
+        = mozilla::services::GetObserverService();
+    if (observerService) {
+        observerService->AddObserver(mMemoryPressureObserver,
+                                     "memory-pressure",
+                                     false);
+    }
+
     return true;
 }
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -108,17 +108,17 @@
 #include "nsIMemoryReporter.h"
 #include "nsStyleUtil.h"
 #include "CanvasImageCache.h"
 #include "CheckedInt.h"
 
 #include <algorithm>
 
 #include "jsapi.h"
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
 #include "mozilla/ipc/PDocumentRendererParent.h"
 
@@ -3930,23 +3930,22 @@ nsCanvasRenderingContext2D::GetImageData
 
     CheckedInt<int32_t> rightMost = CheckedInt<int32_t>(aX) + aWidth;
     CheckedInt<int32_t> bottomMost = CheckedInt<int32_t>(aY) + aHeight;
 
     if (!rightMost.valid() || !bottomMost.valid()) {
         return NS_ERROR_DOM_SYNTAX_ERR;
     }
 
-    JSObject* darray =
-      js_CreateTypedArray(aCx, js::TypedArray::TYPE_UINT8_CLAMPED, len.value());
+    JSObject* darray = JS_NewUint8ClampedArray(aCx, len.value());
     if (!darray) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    uint8_t* data = static_cast<uint8_t*>(JS_GetTypedArrayData(darray));
+    uint8_t* data = JS_GetUint8ClampedArrayData(darray, aCx);
 
     /* Copy the surface contents to the buffer */
     nsRefPtr<gfxImageSurface> tmpsurf =
         new gfxImageSurface(data,
                             gfxIntSize(aWidth, aHeight),
                             aWidth * 4,
                             gfxASurface::ImageFormatARGB32);
 
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -104,17 +104,17 @@
 #include "nsIMemoryReporter.h"
 #include "nsStyleUtil.h"
 #include "CanvasImageCache.h"
 #include "CheckedInt.h"
 
 #include <algorithm>
 
 #include "jsapi.h"
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ImageData.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/PathHelpers.h"
 #include "mozilla/ipc/DocumentRendererParent.h"
@@ -1968,17 +1968,17 @@ nsCanvasRenderingContext2DAzure::CreateP
     nsLayoutUtils::SurfaceFromElement(content->AsElement(),
       nsLayoutUtils::SFE_WANT_FIRST_FRAME | nsLayoutUtils::SFE_WANT_NEW_SURFACE);
 
   if (!res.mSurface) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // Ignore nsnull cairo surfaces! See bug 666312.
-  if (!res.mSurface->CairoSurface()) {
+  if (!res.mSurface->CairoSurface() || res.mSurface->CairoStatus()) {
     return NS_OK;
   }
 
   RefPtr<SourceSurface> srcSurf =
     gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(mTarget, res.mSurface);
 
   nsRefPtr<nsCanvasPatternAzure> pat =
     new nsCanvasPatternAzure(srcSurf, repeatMode, res.mPrincipal,
@@ -4098,28 +4098,27 @@ nsCanvasRenderingContext2DAzure::GetImag
 
   CheckedInt<int32_t> rightMost = CheckedInt<int32_t>(aX) + aWidth;
   CheckedInt<int32_t> bottomMost = CheckedInt<int32_t>(aY) + aHeight;
 
   if (!rightMost.valid() || !bottomMost.valid()) {
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
 
-  JSObject* darray =
-    js_CreateTypedArray(aCx, js::TypedArray::TYPE_UINT8_CLAMPED, len.value());
+  JSObject* darray = JS_NewUint8ClampedArray(aCx, len.value());
   if (!darray) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   if (mZero) {
     *aRetval = darray;
     return NS_OK;
   }
 
-  uint8_t* data = static_cast<uint8_t*>(JS_GetTypedArrayData(darray));
+  uint8_t* data = JS_GetUint8ClampedArrayData(darray, aCx);
 
   IntRect srcRect(0, 0, mWidth, mHeight);
   IntRect destRect(aX, aY, aWidth, aHeight);
 
   IntRect srcReadRect = srcRect.Intersect(destRect);
   IntRect dstWriteRect = srcReadRect;
   dstWriteRect.MoveBy(-aX, -aY);
 
--- a/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
+++ b/content/events/src/nsDOMNotifyAudioAvailableEvent.cpp
@@ -35,17 +35,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 "nsDOMNotifyAudioAvailableEvent.h"
 #include "nsDOMClassInfoID.h" // DOMCI_DATA, NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO
 #include "nsContentUtils.h" // NS_DROP_JS_OBJECTS
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 
 nsDOMNotifyAudioAvailableEvent::nsDOMNotifyAudioAvailableEvent(nsPresContext* aPresContext,
                                                                nsEvent* aEvent,
                                                                PRUint32 aEventType,
                                                                float* aFrameBuffer,
                                                                PRUint32 aFrameBufferLength,
                                                                float aTime)
   : nsDOMEvent(aPresContext, aEvent),
@@ -108,25 +108,22 @@ nsDOMNotifyAudioAvailableEvent::GetFrame
   if (mCachedArray) {
     *aResult = OBJECT_TO_JSVAL(mCachedArray);
     return NS_OK;
   }
 
   // Cache this array so we don't recreate on next call.
   NS_HOLD_JS_OBJECTS(this, nsDOMNotifyAudioAvailableEvent);
 
-  mCachedArray = js_CreateTypedArray(aCx, js::TypedArray::TYPE_FLOAT32, mFrameBufferLength);
+  mCachedArray = JS_NewFloat32Array(aCx, mFrameBufferLength);
   if (!mCachedArray) {
     NS_DROP_JS_OBJECTS(this, nsDOMNotifyAudioAvailableEvent);
-    NS_ERROR("Failed to get audio signal!");
     return NS_ERROR_FAILURE;
   }
-
-  JSObject *tdest = js::TypedArray::getTypedArray(mCachedArray);
-  memcpy(JS_GetTypedArrayData(tdest), mFrameBuffer.get(), mFrameBufferLength * sizeof(float));
+  memcpy(JS_GetFloat32ArrayData(mCachedArray, aCx), mFrameBuffer.get(), mFrameBufferLength * sizeof(float));
 
   *aResult = OBJECT_TO_JSVAL(mCachedArray);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMNotifyAudioAvailableEvent::GetTime(float *aRetVal)
 {
--- a/content/html/content/public/nsIFormControl.h
+++ b/content/html/content/public/nsIFormControl.h
@@ -53,17 +53,16 @@ class Element;
 
 enum FormControlsTypes {
   NS_FORM_FIELDSET = 1,
   NS_FORM_LABEL,
   NS_FORM_OUTPUT,
   NS_FORM_SELECT,
   NS_FORM_TEXTAREA,
   NS_FORM_OBJECT,
-  NS_FORM_PROGRESS,
   eFormControlsWithoutSubTypesMax,
   // After this, all types will have sub-types which introduce new enum lists.
   // eFormControlsWithoutSubTypesMax let us know if the previous types values
   // are not overlapping with sub-types/masks.
 
   // Elements with different types, the value is used as a mask.
   // Adding '_ELEMENT' because NS_FORM_INPUT is used for 'oninput' event.
   // When changing the order, adding or removing elements, be sure to update
@@ -279,17 +278,16 @@ nsIFormControl::IsLabelableControl() con
   // TODO: meter should be added, see bug 555985.
   // TODO: NS_FORM_INPUT_HIDDEN should be removed, see bug 597650.
   PRUint32 type = GetType();
   return type & NS_FORM_INPUT_ELEMENT ||
          type & NS_FORM_BUTTON_ELEMENT ||
          // type == NS_FORM_KEYGEN ||
          // type == NS_FORM_METER ||
          type == NS_FORM_OUTPUT ||
-         type == NS_FORM_PROGRESS ||
          type == NS_FORM_SELECT ||
          type == NS_FORM_TEXTAREA;
 }
 
 bool
 nsIFormControl::IsSubmittableControl() const
 {
   // TODO: keygen should be in that list, see bug 101019.
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -2913,18 +2913,17 @@ nsGenericHTMLFormElement::ForgetFieldSet
 bool
 nsGenericHTMLFormElement::CanBeDisabled() const
 {
   PRInt32 type = GetType();
   // It's easier to test the types that _cannot_ be disabled
   return
     type != NS_FORM_LABEL &&
     type != NS_FORM_OBJECT &&
-    type != NS_FORM_OUTPUT &&
-    type != NS_FORM_PROGRESS;
+    type != NS_FORM_OUTPUT;
 }
 
 bool
 nsGenericHTMLFormElement::IsHTMLFocusable(bool aWithMouse,
                                           bool* aIsFocusable,
                                           PRInt32* aTabIndex)
 {
   if (nsGenericHTMLElement::IsHTMLFocusable(aWithMouse, aIsFocusable, aTabIndex)) {
--- a/content/html/content/src/nsHTMLAudioElement.cpp
+++ b/content/html/content/src/nsHTMLAudioElement.cpp
@@ -52,17 +52,16 @@
 #include "nsXPCOMStrings.h"
 #include "prlock.h"
 #include "nsThreadUtils.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIXPConnect.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
-#include "jstypedarray.h"
 #include "nsJSUtils.h"
 
 #include "nsITimer.h"
 
 #include "nsEventDispatcher.h"
 #include "nsIDOMProgressEvent.h"
 #include "nsContentUtils.h"
 
@@ -179,57 +178,56 @@ nsHTMLAudioElement::MozSetup(PRUint32 aC
   }
 
   MetadataLoaded(aChannels, aRate);
   mAudioStream->SetVolume(mVolume);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsHTMLAudioElement::MozWriteAudio(const jsval &aData, JSContext *aCx, PRUint32 *aRetVal)
+nsHTMLAudioElement::MozWriteAudio(const JS::Value& aData, JSContext* aCx, PRUint32* aRetVal)
 {
   if (!mAudioStream) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
-  if (JSVAL_IS_PRIMITIVE(aData)) {
+  if (!aData.isObject()) {
     return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
   }
 
-  JSObject *darray = JSVAL_TO_OBJECT(aData);
-  JS::AutoValueRooter tsrc_tvr(aCx);
-  JSObject *tsrc = NULL;
+  JSObject* darray = &aData.toObject();
+  JS::AutoObjectRooter tvr(aCx);
+  JSObject* tsrc = NULL;
 
   // Allow either Float32Array or plain JS Array
-  if (js::GetObjectClass(darray) == &js::TypedArray::fastClasses[js::TypedArray::TYPE_FLOAT32])
-  {
-    tsrc = js::TypedArray::getTypedArray(darray);
+  if (JS_IsFloat32Array(darray, aCx)) {
+    tsrc = darray;
   } else if (JS_IsArrayObject(aCx, darray)) {
-    JSObject *nobj = js_CreateTypedArrayWithArray(aCx, js::TypedArray::TYPE_FLOAT32, darray);
+    JSObject* nobj = JS_NewFloat32ArrayFromArray(aCx, darray);
     if (!nobj) {
       return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
     }
-    *tsrc_tvr.jsval_addr() = OBJECT_TO_JSVAL(nobj);
-    tsrc = js::TypedArray::getTypedArray(nobj);
+    tsrc = nobj;
   } else {
     return NS_ERROR_DOM_TYPE_MISMATCH_ERR;
   }
+  tvr.setObject(tsrc);
 
-  PRUint32 dataLength = JS_GetTypedArrayLength(tsrc);
+  PRUint32 dataLength = JS_GetTypedArrayLength(tsrc, aCx);
 
   // Make sure that we are going to write the correct amount of data based
   // on number of channels.
   if (dataLength % mChannels != 0) {
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   // Don't write more than can be written without blocking.
   PRUint32 writeLen = NS_MIN(mAudioStream->Available(), dataLength / mChannels);
 
-  nsresult rv = mAudioStream->Write(JS_GetTypedArrayData(tsrc), writeLen);
+  nsresult rv = mAudioStream->Write(JS_GetFloat32ArrayData(tsrc, aCx), writeLen);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   // Return the actual amount written.
   *aRetVal = writeLen * mChannels;
   return rv;
 }
--- a/content/html/content/src/nsHTMLFieldSetElement.cpp
+++ b/content/html/content/src/nsHTMLFieldSetElement.cpp
@@ -155,18 +155,17 @@ nsHTMLFieldSetElement::GetType(nsAString
 }
 
 /* static */
 bool
 nsHTMLFieldSetElement::MatchListedElements(nsIContent* aContent, PRInt32 aNamespaceID,
                                            nsIAtom* aAtom, void* aData)
 {
   nsCOMPtr<nsIFormControl> formControl = do_QueryInterface(aContent);
-  return formControl && formControl->GetType() != NS_FORM_LABEL &&
-                        formControl->GetType() != NS_FORM_PROGRESS;
+  return formControl && formControl->GetType() != NS_FORM_LABEL;
 }
 
 NS_IMETHODIMP
 nsHTMLFieldSetElement::GetElements(nsIDOMHTMLCollection** aElements)
 {
   if (!mElements) {
     mElements = new nsContentList(this, MatchListedElements, nsnull, nsnull,
                                   true);
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -218,17 +218,16 @@ ShouldBeInElements(nsIFormControl* aForm
     return true;
   }
 
   // These form control types are not supposed to end up in the
   // form.elements array
   //
   // NS_FORM_INPUT_IMAGE
   // NS_FORM_LABEL
-  // NS_FORM_PROGRESS
 
   return false;
 }
 
 // nsHTMLFormElement implementation
 
 // construction, destruction
 nsGenericHTMLElement*
--- a/content/html/content/src/nsHTMLProgressElement.cpp
+++ b/content/html/content/src/nsHTMLProgressElement.cpp
@@ -36,43 +36,38 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIDOMHTMLProgressElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsAttrValue.h"
 #include "nsEventStateManager.h"
 
 
-class nsHTMLProgressElement : public nsGenericHTMLFormElement,
+class nsHTMLProgressElement : public nsGenericHTMLElement,
                               public nsIDOMHTMLProgressElement
 {
 public:
   nsHTMLProgressElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLProgressElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE(nsGenericHTMLFormElement::)
+  NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
   // nsIDOMElement
-  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLFormElement::)
+  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLElement
-  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLFormElement::)
+  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLProgressElement
   NS_DECL_NSIDOMHTMLPROGRESSELEMENT
 
-  // nsIFormControl
-  NS_IMETHOD_(PRUint32) GetType() const { return NS_FORM_PROGRESS; }
-  NS_IMETHOD Reset();
-  NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission);
-
   nsEventStates IntrinsicState() const;
 
   nsresult Clone(nsINodeInfo* aNodeInfo, nsINode** aResult) const;
 
   bool ParseAttribute(PRInt32 aNamespaceID, nsIAtom* aAttribute,
                         const nsAString& aValue, nsAttrValue& aResult);
 
   virtual nsXPCClassInfo* GetClassInfo();
@@ -95,17 +90,17 @@ protected:
 const double nsHTMLProgressElement::kIndeterminatePosition = -1.0;
 const double nsHTMLProgressElement::kDefaultValue          =  0.0;
 const double nsHTMLProgressElement::kDefaultMax            =  1.0;
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Progress)
 
 
 nsHTMLProgressElement::nsHTMLProgressElement(already_AddRefed<nsINodeInfo> aNodeInfo)
-  : nsGenericHTMLFormElement(aNodeInfo)
+  : nsGenericHTMLElement(aNodeInfo)
 {
   // We start out indeterminate
   AddStatesSilently(NS_EVENT_STATE_INDETERMINATE);
 }
 
 nsHTMLProgressElement::~nsHTMLProgressElement()
 {
 }
@@ -114,40 +109,26 @@ NS_IMPL_ADDREF_INHERITED(nsHTMLProgressE
 NS_IMPL_RELEASE_INHERITED(nsHTMLProgressElement, nsGenericElement)
 
 DOMCI_NODE_DATA(HTMLProgressElement, nsHTMLProgressElement)
 
 NS_INTERFACE_TABLE_HEAD(nsHTMLProgressElement)
   NS_HTML_CONTENT_INTERFACE_TABLE1(nsHTMLProgressElement,
                                    nsIDOMHTMLProgressElement)
   NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLProgressElement,
-                                               nsGenericHTMLFormElement)
+                                               nsGenericHTMLElement)
 NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLASSINFO(HTMLProgressElement)
 
 NS_IMPL_ELEMENT_CLONE(nsHTMLProgressElement)
 
 
-NS_IMETHODIMP
-nsHTMLProgressElement::Reset()
-{
-  // The progress element is not resettable.
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLProgressElement::SubmitNamesValues(nsFormSubmission* aFormSubmission)
-{
-  // The progress element is not submittable.
-  return NS_OK;
-}
-
 nsEventStates
 nsHTMLProgressElement::IntrinsicState() const
 {
-  nsEventStates state = nsGenericHTMLFormElement::IntrinsicState();
+  nsEventStates state = nsGenericHTMLElement::IntrinsicState();
 
   if (IsIndeterminate()) {
     state |= NS_EVENT_STATE_INDETERMINATE;
   }
 
   return state;
 }
 
@@ -156,24 +137,18 @@ nsHTMLProgressElement::ParseAttribute(PR
                                       const nsAString& aValue, nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::value || aAttribute == nsGkAtoms::max) {
       return aResult.ParseDoubleValue(aValue);
     }
   }
 
-  return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
-                                                  aValue, aResult);
-}
-
-NS_IMETHODIMP
-nsHTMLProgressElement::GetForm(nsIDOMHTMLFormElement** aForm)
-{
-  return nsGenericHTMLFormElement::GetForm(aForm);
+  return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute,
+                                              aValue, aResult);
 }
 
 NS_IMETHODIMP
 nsHTMLProgressElement::GetValue(double* aValue)
 {
   const nsAttrValue* attrValue = mAttrsAndChildren.GetAttr(nsGkAtoms::value);
   if (!attrValue || attrValue->Type() != nsAttrValue::eDoubleValue ||
       attrValue->GetDoubleValue() < 0.0) {
--- a/content/html/content/test/file_fullscreen-rollback.html
+++ b/content/html/content/test/file_fullscreen-rollback.html
@@ -49,36 +49,41 @@ function addListener(type, f) {
 function removeListener(type, f) {
   document.removeEventListener("mozfullscreen" + type, f, false);
 }
 
 function e(id) {
   return document.getElementById(id);
 }
 
+function requestFullscreen(element) {
+  element.focus();
+  element.mozRequestFullScreen();
+}
+
 function begin() {
   addListener("change", change1);
   e("fse").mozRequestFullScreen();
 }
 
 function change1() {
   removeListener("change", change1);
   addListener("error", error1);
   is(document.mozFullScreenElement, e("fse"), "Body should be FSE");
   
   // Request full-screen from element not descendent from current FSE.
-  e("non-fse").mozRequestFullScreen();
+  requestFullscreen(e("non-fse"));
 }
 
 function error1() {
   removeListener("error", error1);
   addListener("change", change2);
   is(document.mozFullScreenElement, e("fse"), "FSE should not change");
   var iframe = e("subdoc");
-  iframe.contentDocument.body.mozRequestFullScreen();
+  requestFullscreen(iframe.contentDocument.body);
 }
 
 function change2() {
   removeListener("change", change2);
   var iframe = e("subdoc");
   is(document.mozFullScreenElement, iframe, "Subdoc container should be FSE.");
   is(iframe.contentDocument.mozFullScreenElement, iframe.contentDocument.body, "Subdoc body should be FSE in subdoc");
   addListener("change", change3);
@@ -91,24 +96,24 @@ function change3() {
   addListener("change", change4);
   document.mozCancelFullScreen();
 }
 
 function change4() {
   removeListener("change", change4);
   is(document.mozFullScreenElement, null, "Should have left full-screen entirely");
   addListener("change", change5);
-  e("fse").mozRequestFullScreen();
+  requestFullscreen(e("fse"));
 }
 
 function change5() {
   removeListener("change", change5);
   addListener("change", change6);
   is(document.mozFullScreenElement, e("fse"), "FSE should be e('fse')");
-  e("fse-inner").mozRequestFullScreen();
+  requestFullscreen(e("fse-inner"));
 }
 
 function change6() {
   removeListener("change", change6);
   addListener("change", change7);
   var element = e('fse-inner');
   is(document.mozFullScreenElement, element, "FSE should be e('fse-inner')");
   element.parentNode.removeChild(element);
--- a/content/html/content/test/test_bug514437.html
+++ b/content/html/content/test/test_bug514437.html
@@ -24,17 +24,16 @@ and
 <script type="application/javascript">
 
 /** Test for Bug 514437 and Bug 633913 **/
 
 function checkFormIDLAttribute(aElement)
 {
   var form = document.forms[0];
   var content = document.getElementById('content');
-  is(aElement.form, form, "The form IDL attribute should be the parent form");
 
   content.removeChild(form);
   content.appendChild(aElement);
   is(aElement.form, null, "The form IDL attribute should be null");
 
   // Cleaning-up.
   content.appendChild(form);
   form.appendChild(aElement);
@@ -221,30 +220,16 @@ function checkIndeterminatePseudoClass()
   }
 }
 
 function checkFormListedElement(aElement)
 {
   is(document.forms[0].elements.length, 0, "the form should have no element");
 }
 
-function checkLabelable(aElement)
-{
-  var content = document.getElementById('content');
-  var label = document.createElement('label');
-
-  content.appendChild(label);
-  label.appendChild(aElement);
-  is(label.control, aElement, "progress should be labelable");
-
-  // Cleaning-up.
-  content.removeChild(label);
-  content.appendChild(aElement);
-}
-
 function checkNotResetableAndFormSubmission(aElement)
 {
   // Creating an input element to check the submission worked.
   var form = document.forms[0];
   var input = document.createElement('input');
 
   input.name = 'a';
   input.value = 'tulip';
@@ -307,16 +292,14 @@ checkValueAttribute();
 checkMaxAttribute();
 
 checkPositionAttribute();
 
 checkIndeterminatePseudoClass();
 
 checkFormListedElement(p);
 
-checkLabelable(p);
-
 checkNotResetableAndFormSubmission(p);
 
 </script>
 </pre>
 </body>
 </html>
--- a/content/html/content/test/test_bug588683-1.html
+++ b/content/html/content/test/test_bug588683-1.html
@@ -395,17 +395,17 @@ var content = document.getElementById('c
 var forms = [
   document.createElement('form'),
   document.createElement('form'),
   document.createElement('form'),
 ];
 
 var elementNames = [
   'button', 'fieldset', 'input', 'label', 'object', 'output', 'select',
-  'textarea', 'progress',
+  'textarea',
 ];
 
 var todoElements = [
   ['keygen', 'Keygen'],
   ['meter', 'Meter'],
 ];
 
 for each(var e in todoElements) {
--- a/content/xul/templates/src/crashtests/crashtests.list
+++ b/content/xul/templates/src/crashtests/crashtests.list
@@ -1,10 +1,10 @@
 load 257752-1-recursion.xul
 load 329335-1.xul
 load 329884-1.xul
-HTTP load 330010-1.xul
-load 330012-1.xul
-load 397148-1.xul
+skip-if(winWidget) HTTP load 330010-1.xul # bug 742455
+skip-if(winWidget) load 330012-1.xul # bug 742455
+skip-if(winWidget) load 397148-1.xul # bug 742455
 load 404346-1.xul
 load 415019-1.xul
 load 417840-1.xul
 load 424418-1.xul
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
@@ -221,17 +221,17 @@ nsXULTemplateQueryProcessorXML::GetDatas
 
     nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(req));
     rv = target->AddEventListener(NS_LITERAL_STRING("load"), this, false);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = target->AddEventListener(NS_LITERAL_STRING("error"), this, false);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = req->Send(nsnull);
+    rv = req->Send(nsnull, context->GetNativeContext());
     NS_ENSURE_SUCCESS(rv, rv);
 
     mTemplateBuilder = aBuilder;
     mRequest = req;
 
     *aShouldDelayBuilding = true;
     return NS_OK;
 }
--- a/dom/base/StructuredCloneTags.h
+++ b/dom/base/StructuredCloneTags.h
@@ -39,18 +39,24 @@
 
 #include "jsapi.h"
 
 namespace mozilla {
 namespace dom {
 
 enum StructuredCloneTags {
   SCTAG_BASE = JS_SCTAG_USER_MIN,
+
+  // These tags are used only for main thread structured clone.
   SCTAG_DOM_BLOB,
   SCTAG_DOM_FILE,
   SCTAG_DOM_FILELIST,
+
+  // These tags are used for both main thread and workers.
+  SCTAG_DOM_IMAGEDATA,
+
   SCTAG_DOM_MAX
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // StructuredCloneTags_h__
--- a/dom/base/Webapps.jsm
+++ b/dom/base/Webapps.jsm
@@ -42,26 +42,24 @@ let DOMApplicationRegistry = {
                     "Webapps:Launch", "Webapps:GetAll"];
 
     this.messages.forEach((function(msgName) {
       ppmm.addMessageListener(msgName, this);
     }).bind(this));
 
     Services.obs.addObserver(this, "xpcom-shutdown", false);
 
-    let appsDir = FileUtils.getDir(DIRECTORY_NAME, ["webapps"], true, true);
     this.appsFile = FileUtils.getFile(DIRECTORY_NAME, ["webapps", "webapps.json"], true);
 
-    if (!this.appsFile.exists())
-      return;
-
-    this._loadJSONAsync(this.appsFile, (function(aData) { this.webapps = aData; }).bind(this));
+    if (this.appsFile.exists()) {
+      this._loadJSONAsync(this.appsFile, (function(aData) { this.webapps = aData; }).bind(this));
+    }
 
     try {
-      let hosts = Services.prefs.getCharPref("dom.mozApps.whitelist")
+      let hosts = Services.prefs.getCharPref("dom.mozApps.whitelist");
       hosts.split(",").forEach(function(aHost) {
         Services.perms.add(Services.io.newURI(aHost, null, null), "webapps-manage",
                            Ci.nsIPermissionManager.ALLOW_ACTION);
       });
     } catch(e) { }
   },
 
   observe: function(aSubject, aTopic, aData) {
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -3617,17 +3617,17 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGTSpanElement, nsIDOMSVGTSpanElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTextPositioningElement)
     DOM_CLASSINFO_SVG_TEXT_CONTENT_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(SVGUnknownElement, nsIDOMSVGElement)
+  DOM_CLASSINFO_MAP_BEGIN(SVGUnknownElement, nsIDOMSVGElement)
     DOM_CLASSINFO_SVG_ELEMENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(SVGUseElement, nsIDOMSVGUseElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGUseElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGTests)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGURIReference)
     DOM_CLASSINFO_SVG_GRAPHIC_ELEMENT_MAP_ENTRIES
@@ -6095,17 +6095,20 @@ nsDOMConstructor::HasInstance(nsIXPConne
   if (!name_struct) {
     // This isn't a normal DOM object, see if this constructor lives on its
     // prototype chain.
     jsval val;
     if (!JS_GetProperty(cx, obj, "prototype", &val)) {
       return NS_ERROR_UNEXPECTED;
     }
 
-    JS_ASSERT(!JSVAL_IS_PRIMITIVE(val));
+    if (JSVAL_IS_PRIMITIVE(val)) {
+      return NS_OK;
+    }
+
     JSObject *dot_prototype = JSVAL_TO_OBJECT(val);
 
     JSObject *proto = JS_GetPrototype(dom_obj);
     for ( ; proto; proto = JS_GetPrototype(proto)) {
       if (proto == dot_prototype) {
         *bp = true;
         break;
       }
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2312,31 +2312,8 @@ nsDOMWindowUtils::GetPlugins(JSContext* 
 
   JSObject* jsPlugins = nsnull;
   rv = nsTArrayToJSArray(cx, plugins, &jsPlugins);
   NS_ENSURE_SUCCESS(rv, rv);
 
   *aPlugins = OBJECT_TO_JSVAL(jsPlugins);
   return NS_OK;
 }
-
-NS_IMETHODIMP
-nsDOMWindowUtils::SetScrollPositionClampingScrollPortSize(float aWidth, float aHeight)
-{
-  if (!IsUniversalXPConnectCapable()) {
-    return NS_ERROR_DOM_SECURITY_ERR;
-  }
-
-  if (!(aWidth >= 0.0 && aHeight >= 0.0)) {
-    return NS_ERROR_ILLEGAL_VALUE;
-  }
-
-  nsIPresShell* presShell = GetPresShell();
-  if (!presShell) {
-    return NS_ERROR_FAILURE;
-  }
-
-  presShell->SetScrollPositionClampingScrollPortSize(
-    nsPresContext::CSSPixelsToAppUnits(aWidth),
-    nsPresContext::CSSPixelsToAppUnits(aHeight));
-
-  return NS_OK;
-}
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -81,16 +81,18 @@
 #include "nsIArray.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsDOMScriptObjectHolder.h"
 #include "prmem.h"
 #include "WrapperFactory.h"
 #include "nsGlobalWindow.h"
 #include "nsScriptNameSpaceManager.h"
+#include "StructuredCloneTags.h"
+#include "mozilla/dom/ImageData.h"
 
 #include "nsJSPrincipals.h"
 
 #ifdef XP_MACOSX
 // AssertMacros.h defines 'check' and conflicts with AccessCheck.h
 #undef check
 #endif
 #include "AccessCheck.h"
@@ -108,16 +110,17 @@
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/bindings/Utils.h"
 
 #include "sampler.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 const size_t gStackSize = 8192;
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gJSDiagnostics;
 #endif
 
 // Thank you Microsoft!
@@ -3605,28 +3608,80 @@ SetMemoryGCSliceTimePrefChangedCallback(
 
 JSObject*
 NS_DOMReadStructuredClone(JSContext* cx,
                           JSStructuredCloneReader* reader,
                           uint32_t tag,
                           uint32_t data,
                           void* closure)
 {
-  // We don't currently support any extensions to structured cloning.
+  if (tag == SCTAG_DOM_IMAGEDATA) {
+    // Read the information out of the stream.
+    uint32_t width, height;
+    JS::Value dataArray;
+    if (!JS_ReadUint32Pair(reader, &width, &height) ||
+        !JS_ReadTypedArray(reader, &dataArray)) {
+      return nsnull;
+    }
+    MOZ_ASSERT(dataArray.isObject());
+
+    // Construct the ImageData.
+    nsCOMPtr<nsIDOMImageData> imageData = new ImageData(width, height,
+                                                        dataArray.toObject());
+    // Wrap it in a jsval.
+    JSObject* global = JS_GetGlobalForScopeChain(cx);
+    if (!global) {
+      return nsnull;
+    }
+    nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
+    JS::Value val;
+    nsresult rv =
+      nsContentUtils::WrapNative(cx, global, imageData, &val,
+                                 getter_AddRefs(wrapper));
+    if (NS_FAILED(rv)) {
+      return nsnull;
+    }
+    return val.toObjectOrNull();
+  }
+
+  // Don't know what this is. Bail.
   nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
   return nsnull;
 }
 
 JSBool
 NS_DOMWriteStructuredClone(JSContext* cx,
                            JSStructuredCloneWriter* writer,
                            JSObject* obj,
                            void *closure)
 {
-  // We don't currently support any extensions to structured cloning.
+  nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
+  nsContentUtils::XPConnect()->
+    GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
+  nsISupports *native = wrappedNative ? wrappedNative->Native() : nsnull;
+
+  nsCOMPtr<nsIDOMImageData> imageData = do_QueryInterface(native);
+  if (imageData) {
+    // Prepare the ImageData internals.
+    PRUint32 width, height;
+    JS::Value dataArray;
+    if (NS_FAILED(imageData->GetWidth(&width)) ||
+        NS_FAILED(imageData->GetHeight(&height)) ||
+        NS_FAILED(imageData->GetData(cx, &dataArray)))
+    {
+      return false;
+    }
+
+    // Write the internals to the stream.
+    return JS_WriteUint32Pair(writer, SCTAG_DOM_IMAGEDATA, 0) &&
+           JS_WriteUint32Pair(writer, width, height) &&
+           JS_WriteTypedArray(writer, dataArray);
+  }
+
+  // Don't know what this is. Bail.
   nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
   return JS_FALSE;
 }
 
 void
 NS_DOMStructuredCloneError(JSContext* cx,
                            uint32_t errorid)
 {
--- a/dom/base/nsScreen.cpp
+++ b/dom/base/nsScreen.cpp
@@ -421,15 +421,33 @@ nsScreen::FullScreenEventListener::Handl
   aEvent->GetType(eventType);
 
   MOZ_ASSERT(eventType.EqualsLiteral("mozfullscreenchange"));
 #endif
 
   nsCOMPtr<nsIDOMEventTarget> target;
   aEvent->GetCurrentTarget(getter_AddRefs(target));
 
+  // We have to make sure that the event we got is the event sent when
+  // fullscreen is disabled because we could get one when fullscreen
+  // got enabled if the lock call is done at the same moment.
+  nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(target);
+  MOZ_ASSERT(window);
+
+  nsCOMPtr<nsIDOMDocument> doc;
+  window->GetDocument(getter_AddRefs(doc));
+  // If we have no doc, we will just continue, remove the event and unlock.
+  // This is an edge case were orientation lock and fullscreen is meaningless.
+  if (doc) {
+    bool fullscreen;
+    doc->GetMozFullScreen(&fullscreen);
+    if (fullscreen) {
+      return NS_OK;
+    }
+  }
+
   target->RemoveSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"),
                                     this, true);
 
   hal::UnlockScreenOrientation();
 
   return NS_OK;
 }
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -50,17 +50,17 @@ DOMInterfaces = {
             'multipart', 'channel', 'upload', 'status'
         ],
         'getterOnly': [
             'responseType', 'timeout', 'onreadystatechange'
         ]
     },
     'implicitJSContext': {
         'all': [
-            'response', 'getInterface'
+            'response', 'getInterface', 'send', 'sendAsBinary'
         ],
         'setterOnly': [
             'onreadystatechange'
         ]
     },
     'resultNotAddRefed': [ 'upload', 'responseXML' ]
 },
 {
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -319,17 +319,17 @@ class CGHeaders(CGWrapper):
                 types.extend([a.type for a in arguments])
 
             attrs = [a for a in members if a.isAttr()]
             types.extend([a.type for a in attrs])
 
             for t in types:
                 if t.unroll().isInterface():
                     if t.unroll().isArrayBuffer():
-                        bindingHeaders.add("jstypedarray.h")
+                        bindingHeaders.add("jsfriendapi.h")
                     else:
                         typeDesc = d.getDescriptor(t.unroll().inner.identifier.name)
                         if typeDesc is not None:
                             implementationIncludes.add(typeDesc.headerFile)
                             bindingHeaders.add(self.getInterfaceFilename(typeDesc.interface))
 
         # Let the machinery do its thing.
         def _includeString(includes):
@@ -1184,17 +1184,17 @@ def getArgumentConversionTemplate(type, 
         if not argIsPointer:
             template += "  ${typeName} &${name} = *${name}_ptr;\n"
             
         return template
 
     if type.isArrayBuffer():
         template = (
             "  JSObject* ${name};\n"
-            "  if (${argVal}.isObject() && JS_IsArrayBufferObject(&${argVal}.toObject())) {\n"
+            "  if (${argVal}.isObject() && JS_IsArrayBufferObject(&${argVal}.toObject(), cx)) {\n"
             "    ${name} = &${argVal}.toObject();\n"
             "  }")
         if type.nullable():
             template += (
                 " else if (${argVal}.isNullOrUndefined()) {\n"
                 "    ${name} = NULL;\n"
                 "  }")
 
@@ -1895,17 +1895,17 @@ class CGMethodCall(CGThing):
             pickFirstSignature("%s.isNullOrUndefined()" % distinguishingArg,
                                lambda s: s[1][distinguishingIndex].type.nullable())
 
             # Now check for distinguishingArg being a platform object.
             # We can actually check separately for array buffers and
             # other things.
             # XXXbz Do we need to worry about security
             # wrappers around the array buffer?
-            pickFirstSignature("%s.isObject() && JS_IsArrayBufferObject(&%s.toObject())" %
+            pickFirstSignature("%s.isObject() && JS_IsArrayBufferObject(&%s.toObject(), cx)" %
                                (distinguishingArg, distinguishingArg),
                                lambda s: (s[1][distinguishingIndex].type.isArrayBuffer() or
                                           s[1][distinguishingIndex].type.isObject()))
             
             interfacesSigs = [
                 s for s in possibleSignatures
                 if (s[1][distinguishingIndex].type.isObject() or
                     (s[1][distinguishingIndex].type.isInterface() and
--- a/dom/bindings/Utils.h
+++ b/dom/bindings/Utils.h
@@ -5,17 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bindings_Utils_h__
 #define mozilla_dom_bindings_Utils_h__
 
 #include "mozilla/dom/bindings/DOMJSClass.h"
 
 #include "jsapi.h"
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 
 #include "XPCQuickStubs.h"
 #include "XPCWrapper.h"
 #include "nsTraceRefcnt.h"
 #include "nsWrapperCacheInlines.h"
 
 namespace mozilla {
 namespace dom {
@@ -164,17 +164,17 @@ IsPlatformObject(JSContext* cx, JSObject
     obj = XPCWrapper::Unwrap(cx, obj, false);
     if (!obj) {
       // Let's say it's not
       return false;
     }
     clasp = js::GetObjectJSClass(obj);
   }
   return IS_WRAPPER_CLASS(js::Valueify(clasp)) || IsDOMClass(clasp) ||
-    JS_IsArrayBufferObject(obj);
+    JS_IsArrayBufferObject(obj, cx);
 }
 
 template <class T>
 inline nsresult
 UnwrapObject(JSContext* cx, JSObject* obj, T* *value)
 {
   return UnwrapObject<static_cast<prototypes::ID>(
            PrototypeIDMap<T>::PrototypeID)>(cx, obj, value);
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -65,17 +65,17 @@ interface nsIDOMEvent;
 interface nsITransferable;
 interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 interface nsIDOMBlob;
 interface nsIDOMFile;
 interface nsIFile;
 interface nsIDOMTouch;
 
-[scriptable, uuid(66a68858-df38-40e1-a792-fda04ebcc084)]
+[scriptable, uuid(c7f303a1-4f7b-4d38-a192-c3f0e25dadb1)]
 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.
@@ -1105,17 +1105,9 @@ interface nsIDOMWindowUtils : nsISupport
    *
    * Cannot be accessed from unprivileged context (not content-accessible).
    * Will throw a DOM security error if called without UniversalXPConnect
    * privileges.
    *
    */
   [implicit_jscontext]
   readonly attribute jsval plugins;
-
-  /**
-   * Set the scrollport size for the purposes of clamping scroll positions for
-   * the root scroll frame of this document to be (aWidth,aHeight) in CSS pixels.
-   *
-   * The caller of this method must have UniversalXPConnect privileges.
-   */
-  void setScrollPositionClampingScrollPortSize(in float aWidth, in float aHeight);
 };
--- a/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
+++ b/dom/interfaces/canvas/nsIDOMWebGLRenderingContext.idl
@@ -172,17 +172,17 @@ interface nsIWebGLExtensionLoseContext :
 
 [scriptable, uuid(73bfb64d-94bd-4a7a-9eab-6b6d32e57aa0)]
 interface nsIWebGLExtensionTextureFilterAnisotropic : nsIWebGLExtension
 {
   const WebGLenum TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE;
   const WebGLenum MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF;
 };
 
-[scriptable, builtinclass, uuid(dcba5412-42b4-4897-b2f4-56a5cae7ef2d)]
+[scriptable, builtinclass, uuid(ba7635d7-98af-41ac-8bf9-9f08cf441958)]
 interface nsIDOMWebGLRenderingContext : nsISupports
 {
   //
   //  CONSTANTS
   //
 
   /* ClearBufferMask */
   const unsigned long DEPTH_BUFFER_BIT               = 0x00000100;
@@ -619,31 +619,31 @@ interface nsIDOMWebGLRenderingContext : 
   void blendEquation(in WebGLenum mode);
   void blendEquationSeparate(in WebGLenum modeRGB, in WebGLenum modeAlpha);
   void blendFunc(in WebGLenum sfactor, in WebGLenum dfactor);
   void blendFuncSeparate(in WebGLenum srcRGB, in WebGLenum dstRGB, in WebGLenum srcAlpha, in WebGLenum dstAlpha);
 
   // Modified: void glBufferData(WebGLenum target, long size, const void* data, WebGLenum usage);
   [implicit_jscontext] void bufferData(in long target, in jsval data, in long usage);
 
-  void bufferSubData(in long target, in long offset, in jsval data);
+  [implicit_jscontext] void bufferSubData(in long target, in long offset, in jsval data);
 
   WebGLenum checkFramebufferStatus(in WebGLenum target);
   void clear(in WebGLbitfield mask);
   void clearColor(in WebGLclampf red, in WebGLclampf green, in WebGLclampf blue, in WebGLclampf alpha);
   void clearDepth(in WebGLclampf depth);
   void clearStencil(in WebGLint s);
   void colorMask(in WebGLboolean red, in WebGLboolean green, in WebGLboolean blue, in WebGLboolean alpha);
   void compileShader([optional] in nsIWebGLShader shader);
 
-  void compressedTexImage2D(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
+  [implicit_jscontext] void compressedTexImage2D(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
                             in WebGLsizei width, in WebGLsizei height, in WebGLint border,
                             in jsval pixels);
 
-  void compressedTexSubImage2D(in WebGLenum target, in WebGLint level, in WebGLint xoffset,
+  [implicit_jscontext] void compressedTexSubImage2D(in WebGLenum target, in WebGLint level, in WebGLint xoffset,
                                in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height,
                                in WebGLenum format, in jsval pixels);
 
   void copyTexImage2D(in WebGLenum target, in WebGLint level, in WebGLenum internalformat, 
                       in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height, in WebGLint border);
   void copyTexSubImage2D(in WebGLenum target, in WebGLint level, in WebGLint xoffset, in WebGLint yoffset, 
                          in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height);
 
@@ -744,17 +744,17 @@ interface nsIDOMWebGLRenderingContext : 
   WebGLboolean isTexture(in nsIWebGLTexture texture);
 
   WebGLboolean isEnabled(in WebGLenum cap);
   void lineWidth(in WebGLfloat width);
   void linkProgram([optional] in nsIWebGLProgram program);
   void pixelStorei(in WebGLenum pname, in WebGLint param);
   void polygonOffset(in WebGLfloat factor, in WebGLfloat units);
 
-  void readPixels(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height,
+  [implicit_jscontext] void readPixels(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height,
                   in WebGLenum format, in WebGLenum type, in jsval pixels);
 
   //void glReleaseShaderCompiler();
 
   void renderbufferStorage(in WebGLenum target, in WebGLenum internalformat, in WebGLsizei width, in WebGLsizei height);
   void sampleCoverage(in WebGLclampf value, in WebGLboolean invert);
   void scissor(in WebGLint x, in WebGLint y, in WebGLsizei width, in WebGLsizei height);
 
@@ -764,32 +764,32 @@ interface nsIDOMWebGLRenderingContext : 
   void stencilFunc(in WebGLenum func, in WebGLint ref, in WebGLuint mask);
   void stencilFuncSeparate(in WebGLenum face, in WebGLenum func, in WebGLint ref, in WebGLuint mask);
   void stencilMask(in WebGLuint mask);
   void stencilMaskSeparate(in WebGLenum face, in WebGLuint mask);
   void stencilOp(in WebGLenum fail, in WebGLenum zfail, in WebGLenum zpass);
   void stencilOpSeparate(in WebGLenum face, in WebGLenum fail, in WebGLenum zfail, in WebGLenum zpass);
 
   void texImage2D([optional] in long dummy);
-  [noscript] void texImage2D_array(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
+  [noscript,implicit_jscontext] void texImage2D_array(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
                                    in WebGLsizei width, in WebGLsizei height,
                                    in WebGLint border, in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
-  [noscript] void texImage2D_imageData(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
+  [noscript,implicit_jscontext] void texImage2D_imageData(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
                                    in WebGLsizei width, in WebGLsizei height,
                                    in WebGLint border, in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
 
   // HTMLImageElement, HTMLCanvasElement, HTMLVideoElement
   [noscript] void texImage2D_dom(in WebGLenum target, in WebGLint level, in WebGLenum internalformat,
                                  in WebGLenum format, in WebGLenum type, in Element element);
 
   void texSubImage2D([optional] in long dummy);
-  [noscript] void texSubImage2D_array(in WebGLenum target, in WebGLint level,
+  [noscript,implicit_jscontext] void texSubImage2D_array(in WebGLenum target, in WebGLint level,
                                       in WebGLint xoffset, in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height,
                                       in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
-  [noscript] void texSubImage2D_imageData(in WebGLenum target, in WebGLint level,
+  [noscript,implicit_jscontext] void texSubImage2D_imageData(in WebGLenum target, in WebGLint level,
                                       in WebGLint xoffset, in WebGLint yoffset, in WebGLsizei width, in WebGLsizei height,
                                       in WebGLenum format, in WebGLenum type, in WebGLJSObjectPtr pixels);
   // HTMLImageElement, HTMLCanvasElement, HTMLVideoElement
   [noscript] void texSubImage2D_dom(in WebGLenum target, in WebGLint level,
                                     in WebGLint xoffset, in WebGLint yoffset, in WebGLenum format, in WebGLenum type,
                                     in Element element);
 
   // Modified: This replaces glTexParameterf, glTexParameterfv, glTexParameteri and glTexParameteriv
--- a/dom/interfaces/html/nsIDOMHTMLProgressElement.idl
+++ b/dom/interfaces/html/nsIDOMHTMLProgressElement.idl
@@ -42,21 +42,20 @@
  * <progress> element.
  *
  * For more information on this interface, please see
  * http://www.whatwg.org/specs/web-apps/current-work/#the-progress-element
  *
  * @status UNDER_DEVELOPMENT
  */
 
-[scriptable, uuid(842AEE33-8381-4DA4-A347-9E70C797BC3E)]
+[scriptable, uuid(275851c9-c3e2-4427-a770-3d2aaad6c546)]
 interface nsIDOMHTMLProgressElement : nsIDOMHTMLElement
 {
            attribute double value;
            attribute double max;
   readonly attribute double position;
-  readonly attribute nsIDOMHTMLFormElement form;
   /**
    * The labels attribute will be done with bug 567740.
    */
   //readonly attribute NodeList labels;
 };
 
--- a/dom/system/gonk/AudioManager.cpp
+++ b/dom/system/gonk/AudioManager.cpp
@@ -30,24 +30,76 @@
  * 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 <android/log.h> 
+
+#include "mozilla/Hal.h"
 #include "AudioManager.h"
 #include "gonk/AudioSystem.h"
 
 using namespace mozilla::dom::gonk;
 using namespace android;
+using namespace mozilla::hal;
+using namespace mozilla;
+
+#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "AudioManager" , ## args) 
 
 NS_IMPL_ISUPPORTS1(AudioManager, nsIAudioManager)
 
+static AudioSystem::audio_devices
+GetRoutingMode(int aType) {
+  if (aType == nsIAudioManager::FORCE_SPEAKER) {
+    return AudioSystem::DEVICE_OUT_SPEAKER;
+  } else if (aType == nsIAudioManager::FORCE_HEADPHONES) {
+    return AudioSystem::DEVICE_OUT_WIRED_HEADSET;
+  } else if (aType == nsIAudioManager::FORCE_BT_SCO) {
+    return AudioSystem::DEVICE_OUT_BLUETOOTH_SCO;
+  } else if (aType == nsIAudioManager::FORCE_BT_A2DP) {
+    return AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP;
+  } else {
+    return AudioSystem::DEVICE_IN_DEFAULT;
+  }
+}
+
+static void
+InternalSetAudioRoutes(SwitchState aState)
+{
+  if (aState == SWITCH_STATE_ON) {
+    AudioManager::SetAudioRoute(nsIAudioManager::FORCE_HEADPHONES);
+  } else if (aState == SWITCH_STATE_OFF) {
+    AudioManager::SetAudioRoute(nsIAudioManager::FORCE_SPEAKER);
+  }
+}
+
+class HeadphoneSwitchObserver : public SwitchObserver
+{
+public:
+  void Notify(const SwitchEvent& aEvent) {
+    InternalSetAudioRoutes(aEvent.status());
+  }
+};
+
+AudioManager::AudioManager() : mPhoneState(PHONE_STATE_CURRENT),
+                 mObserver(new HeadphoneSwitchObserver())
+{
+  RegisterSwitchObserver(SWITCH_HEADPHONES, mObserver);
+  
+  InternalSetAudioRoutes(GetCurrentSwitchState(SWITCH_HEADPHONES));
+}
+
+AudioManager::~AudioManager() {
+  UnregisterSwitchObserver(SWITCH_HEADPHONES, mObserver);
+}
+
 NS_IMETHODIMP
 AudioManager::GetMicrophoneMuted(bool* aMicrophoneMuted)
 {
   if (AudioSystem::isMicrophoneMuted(aMicrophoneMuted)) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
@@ -156,8 +208,17 @@ AudioManager::GetForceForUse(PRInt32 aUs
   } else if (static_cast<
              audio_policy_forced_cfg_t (*)(audio_policy_force_use_t)
              >(AudioSystem::getForceUse)) {
     // Dynamically resolved the ICS signature.
     *aForce = AudioSystem::getForceUse((audio_policy_force_use_t)aUsage);
   }
   return NS_OK;
 }
+
+void
+AudioManager::SetAudioRoute(int aRoutes) {
+  audio_io_handle_t handle = AudioSystem::getOutput(AudioSystem::SYSTEM);
+  
+  String8 cmd;
+  cmd.appendFormat("%s=%d", AudioParameter::keyRouting, GetRoutingMode(aRoutes));
+  AudioSystem::setParameters(handle, cmd);
+}
--- a/dom/system/gonk/AudioManager.h
+++ b/dom/system/gonk/AudioManager.h
@@ -33,40 +33,49 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_dom_system_b2g_audiomanager_h__
 #define mozilla_dom_system_b2g_audiomanager_h__
 
+#include "mozilla/Observer.h"
+#include "nsAutoPtr.h"
 #include "nsIAudioManager.h"
 
-
 // {b2b51423-502d-4d77-89b3-7786b562b084}
 #define NS_AUDIOMANAGER_CID {0x94f6fd70, 0x7615, 0x4af9, \
       {0x89, 0x10, 0xf9, 0x3c, 0x55, 0xe6, 0x62, 0xec}}
 #define NS_AUDIOMANAGER_CONTRACTID "@mozilla.org/telephony/audiomanager;1"
 
+
 namespace mozilla {
+namespace hal {
+class SwitchEvent;
+typedef Observer<SwitchEvent> SwitchObserver;
+} // namespace hal
+
 namespace dom {
 namespace gonk {
 
 class AudioManager : public nsIAudioManager
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIAUDIOMANAGER
 
-  AudioManager() : mPhoneState(PHONE_STATE_CURRENT)
-  {
-  }
+  AudioManager();
+  ~AudioManager();
 
+  static void SetAudioRoute(int aRoutes);
 protected:
   PRInt32 mPhoneState;
+
+private:
+  nsAutoPtr<mozilla::hal::SwitchObserver> mObserver;
 };
 
-
-} /* namespace telephony */
+} /* namespace gonk */
 } /* namespace dom */
 } /* namespace mozilla */
 
 #endif // mozilla_dom_system_b2g_audiomanager_h__
--- a/dom/system/gonk/Makefile.in
+++ b/dom/system/gonk/Makefile.in
@@ -62,8 +62,9 @@ EXTRA_JS_MODULES = \
   systemlibs.js \
   $(NULL)
 
 ifdef ENABLE_TESTS
 XPCSHELL_TESTS = tests
 endif
 
 include $(topsrcdir)/config/rules.mk
+include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -145,17 +145,17 @@ function RadioInterfaceLayer() {
   debug("Starting RIL Worker");
   this.worker = new ChromeWorker("resource://gre/modules/ril_worker.js");
   this.worker.onerror = this.onerror.bind(this);
   this.worker.onmessage = this.onmessage.bind(this);
 
   this.radioState = {
     radioState:     RIL.GECKO_RADIOSTATE_UNAVAILABLE,
     cardState:      RIL.GECKO_CARDSTATE_UNAVAILABLE,
-    msisdn:         null,
+    icc:            null,
 
     // These objects implement the nsIDOMMozMobileConnectionInfo interface,
     // although the actual implementation lives in the content process.
     voice:          {connected: false,
                      emergencyCallsOnly: false,
                      roaming: false,
                      operator: null,
                      type: null,
@@ -168,16 +168,17 @@ function RadioInterfaceLayer() {
                      type: null,
                      signalStrength: null,
                      relSignalStrength: null},
   };
   ppmm.addMessageListener("RIL:GetRadioState", this);
   Services.obs.addObserver(this, "xpcom-shutdown", false);
 
   this._sentSmsEnvelopes = {};
+  this.portAddressedSmsApps = {};
 }
 RadioInterfaceLayer.prototype = {
 
   classID:   RADIOINTERFACELAYER_CID,
   classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
                                     classDescription: "RadioInterfaceLayer",
                                     interfaces: [Ci.nsIWorkerHolder,
                                                  Ci.nsIRadioInterfaceLayer]}),
@@ -271,18 +272,18 @@ RadioInterfaceLayer.prototype = {
         // indicating the time, daylight savings flag, and timezone
         // sent from the network and a timestamp of when the message was received
         // so an offset can be added if/when the time is actually set.
         debug("nitzTime networkTime=" + message.networkTimeInSeconds +
               " timezone=" + message.networkTimeZoneInMinutes +
               " dst=" + message.dstFlag +
               " timestamp=" + message.localTimeStampInMS);
         break;
-      case "siminfo":
-        this.radioState.msisdn = message.msisdn;
+      case "iccinfochange":
+        this.radioState.icc = message;
         break;
       default:
         throw new Error("Don't know about this message type: " + message.type);
     }
   },
 
   updateVoiceConnection: function updateVoiceConnection(state) {
     let voiceInfo = this.radioState.voice;
@@ -455,18 +456,36 @@ RadioInterfaceLayer.prototype = {
         keepGoing = true;
       }
       if (!keepGoing) {
         break;
       }
     }
   },
 
+  portAddressedSmsApps: null,
   handleSmsReceived: function handleSmsReceived(message) {
     debug("handleSmsReceived: " + JSON.stringify(message));
+
+    // Dispatch to registered handler if application port addressing is
+    // available. Note that the destination port can possibly be zero when
+    // representing a UDP/TCP port.
+    if (message.header.destinationPort != null) {
+      let handler = this.portAddressedSmsApps[message.header.destinationPort];
+      if (handler) {
+        handler(message);
+      }
+      return;
+    }
+
+    if (message.encoding == RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
+      // Don't know how to handle binary data yet.
+      return;
+    }
+
     let id = gSmsDatabaseService.saveReceivedMessage(message.sender || null,
                                                      message.fullBody || null,
                                                      message.timestamp);
     let sms = gSmsService.createSmsMessage(id,
                                            DOM_SMS_DELIVERY_RECEIVED,
                                            message.sender || null,
                                            message.receiver || null,
                                            message.fullBody || null,
--- a/dom/system/gonk/SystemWorkerManager.cpp
+++ b/dom/system/gonk/SystemWorkerManager.cpp
@@ -41,17 +41,17 @@
 
 #include "nsIObserverService.h"
 #include "nsIJSContextStack.h"
 #include "nsIRadioInterfaceLayer.h"
 #include "nsIWifi.h"
 #include "nsIWorkerHolder.h"
 #include "nsIXPConnect.h"
 
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 #include "mozilla/dom/workers/Workers.h"
 #include "mozilla/ipc/Ril.h"
 #include "nsContentUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "nsRadioInterfaceLayer.h"
 #include "WifiWorker.h"
 
@@ -95,31 +95,31 @@ PostToRIL(JSContext *cx, unsigned argc, 
     if (!abs.encode(cx, str)) {
       return false;
     }
 
     size = JS_GetStringLength(str);
     data = abs.ptr();
   } else if (!JSVAL_IS_PRIMITIVE(v)) {
     JSObject *obj = JSVAL_TO_OBJECT(v);
-    if (!js_IsTypedArray(obj)) {
+    if (!JS_IsTypedArrayObject(obj, cx)) {
       JS_ReportError(cx, "Object passed in wasn't a typed array");
       return false;
     }
 
-    uint32_t type = JS_GetTypedArrayType(obj);
-    if (type != js::TypedArray::TYPE_INT8 &&
-        type != js::TypedArray::TYPE_UINT8 &&
-        type != js::TypedArray::TYPE_UINT8_CLAMPED) {
+    uint32_t type = JS_GetTypedArrayType(obj, cx);
+    if (type != js::ArrayBufferView::TYPE_INT8 &&
+        type != js::ArrayBufferView::TYPE_UINT8 &&
+        type != js::ArrayBufferView::TYPE_UINT8_CLAMPED) {
       JS_ReportError(cx, "Typed array data is not octets");
       return false;
     }
 
-    size = JS_GetTypedArrayByteLength(obj);
-    data = JS_GetTypedArrayData(obj);
+    size = JS_GetTypedArrayByteLength(obj, cx);
+    data = JS_GetArrayBufferViewData(obj, cx);
   } else {
     JS_ReportError(cx,
                    "Incorrect argument. Expecting a string or a typed array");
     return false;
   }
 
   if (size > RilRawData::MAX_DATA_SIZE) {
     JS_ReportError(cx, "Passed-in data is too large");
@@ -176,23 +176,22 @@ private:
   nsRefPtr<WorkerCrossThreadDispatcher> mDispatcher;
 };
 
 bool
 RILReceiver::DispatchRILEvent::RunTask(JSContext *aCx)
 {
   JSObject *obj = JS_GetGlobalObject(aCx);
 
-  JSObject *array =
-    js_CreateTypedArray(aCx, js::TypedArray::TYPE_UINT8, mMessage->mSize);
+  JSObject *array = JS_NewUint8Array(aCx, mMessage->mSize);
   if (!array) {
     return false;
   }
 
-  memcpy(JS_GetTypedArrayData(array), mMessage->mData, mMessage->mSize);
+  memcpy(JS_GetArrayBufferViewData(array, aCx), mMessage->mData, mMessage->mSize);
   jsval argv[] = { OBJECT_TO_JSVAL(array) };
   return JS_CallFunctionName(aCx, obj, "onRILMessage", NS_ARRAY_LENGTH(argv),
                              argv, argv);
 }
 
 } // anonymous namespace
 
 SystemWorkerManager::SystemWorkerManager()
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -368,51 +368,53 @@ const TOA_INTERNATIONAL = 0x91;
 const TOA_UNKNOWN = 0x81;
 
 const CALL_PRESENTATION_ALLOWED = 0;
 const CALL_PRESENTATION_RESTRICTED = 1;
 const CALL_PRESENTATION_UNKNOWN = 2;
 const CALL_PRESENTATION_PAYPHONE = 3;
 
 // ICC commands, see TS 27.007 +CRSM commands
+const ICC_COMMAND_SEEK = 0xa2;
 const ICC_COMMAND_READ_BINARY = 0xb0;
-const ICC_COMMAND_UPDATE_BINARY = 0xd6;
 const ICC_COMMAND_READ_RECORD = 0xb2;
+const ICC_COMMAND_GET_RESPONSE = 0xc0;
+const ICC_COMMAND_UPDATE_BINARY = 0xd6;
 const ICC_COMMAND_UPDATE_RECORD = 0xdc;
-const ICC_COMMAND_SEEK = 0xa2;
-const ICC_COMMAND_GET_RESPONSE = 0xc0;
 
 // ICC constants, GSM SIM file ids from TS 51.011
-const ICC_EF_ADN = 0x6F3A;
-const ICC_EF_FDN = 0x6F3B;
-const ICC_EF_SDN = 0x6F49;
-const ICC_EF_EXT1 = 0x6F4A;
-const ICC_EF_EXT2 = 0x6F4B;
-const ICC_EF_EXT3 = 0x6F4C;
-const ICC_EF_EXT6 = 0x6fc8;   // Ext record for EF[MBDN]
-const ICC_EF_MWIS = 0x6FCA;
-const ICC_EF_MBDN = 0x6fc7;
-const ICC_EF_PNN = 0x6fc5;
-const ICC_EF_SPN = 0x6F46;
-const ICC_EF_SMS = 0x6F3C;
-const ICC_EF_ICCID = 0x2fe2;
-const ICC_EF_AD = 0x6FAD;
-const ICC_EF_MBI = 0x6fc9;
+const ICC_EF_ICCID  = 0x2fe2;
+const ICC_EF_IMG    = 0x4f20;
+const ICC_EF_SST    = 0x6f38;
+const ICC_EF_UST    = 0x6f38; // For USIM
+const ICC_EF_ADN    = 0x6f3a;
+const ICC_EF_FDN    = 0x6f3b;
+const ICC_EF_SMS    = 0x6f3c;
 const ICC_EF_MSISDN = 0x6f40;
-const ICC_EF_SPDI = 0x6fcd;
-const ICC_EF_SST = 0x6f38;
-const ICC_EF_CFIS = 0x6FCB;
-const ICC_EF_IMG = 0x4f20;
+const ICC_EF_SPN    = 0x6f46;
+const ICC_EF_SDN    = 0x6f49;
+const ICC_EF_EXT1   = 0x6f4a;
+const ICC_EF_EXT2   = 0x6f4b;
+const ICC_EF_EXT3   = 0x6f4c;
+const ICC_EF_AD     = 0x6fad;
+const ICC_EF_PNN    = 0x6fc5;
+const ICC_EF_MBDN   = 0x6fc7;
+const ICC_EF_EXT6   = 0x6fc8;   // Ext record for EF[MBDN]
+const ICC_EF_MBI    = 0x6fc9;
+const ICC_EF_MWIS   = 0x6fca;
+const ICC_EF_CFIS   = 0x6fcb;
+const ICC_EF_SPDI   = 0x6fcd;
 
 // Types of files  TS 11.11 9.3
 const TYPE_RFU = 0;
 const TYPE_MF  = 1;
 const TYPE_DF  = 2;
 const TYPE_EF  = 4;
 
+const RESPONSE_DATA_FILE_SIZE = 2;
 const RESPONSE_DATA_FILE_ID_1 = 4;
 const RESPONSE_DATA_FILE_ID_2 = 5;
 const RESPONSE_DATA_FILE_TYPE = 6;
 const RESPONSE_DATA_RFU_3 = 7;
 const RESPONSE_DATA_ACCESS_CONDITION_1 = 8;
 const RESPONSE_DATA_ACCESS_CONDITION_2 = 9;
 const RESPONSE_DATA_ACCESS_CONDITION_3 = 10;
 const RESPONSE_DATA_FILE_STATUS = 11;
@@ -420,30 +422,31 @@ const RESPONSE_DATA_LENGTH = 12;
 const RESPONSE_DATA_STRUCTURE = 13;
 const RESPONSE_DATA_RECORD_LENGTH = 14;
 
 // Types of files  TS 11.11 9.3
 const EF_TYPE_TRANSPARENT = 0;
 const EF_TYPE_LINEAR_FIXED = 1;
 const EF_TYPE_CYCLIC = 3;
 
-// For retriveing MSISDN
-const FOOTER_SIZE_BYTES = 14;
-const MAX_NUMBER_SIZE_BYTES = 11;
+// For retrieving MSISDN, TS 151.011 clause 10.5.5
+const MSISDN_FOOTER_SIZE_BYTES = 14;
+const MSISDN_MAX_NUMBER_SIZE_BYTES = 10;
 
 // READ_RECORD mode,  TS 102.221
 const READ_RECORD_ABSOLUTE_MODE = 4;
 
 // GET_RESPONSE mandatory response size for EF, see TS 51.011 clause 9, 
 // 'Response data in case of an EF.'
 const GET_RESPONSE_EF_SIZE_BYTES = 15;
 
 // EF path
 const EF_PATH_MF_SIM = "3f00";
 const EF_PATH_DF_TELECOM = "7f10";
+const EF_PATH_DF_GSM = "7f20";
 
 // Status code of sw1 for ICC I/O,
 // see GSM11.11 and TS 51.011 clause 9.4, and ISO 7816-4
 const ICC_STATUS_NORMAL_ENDING = 0x90;
 const ICC_STATUS_NORMAL_ENDING_WITH_EXTRA = 0x91;
 const ICC_STATUS_WITH_SIM_DATA = 0x9e;
 const ICC_STATUS_WITH_RESPONSE_DATA = 0x9f;
 const ICC_STATUS_ERROR_WRONG_LENGTH = 0x67;
@@ -650,16 +653,20 @@ const PDU_IEI_CHARACTER_SIZE_WVG_OBJECT 
 const PDU_IEI_EXTENDED_OBJECT_DATA_REQUEST_COMMAND     = 0x1A;
 const PDU_IEI_RFC822_EMAIL_HEADER                      = 0x20;
 const PDU_IEI_HYPERLINK_FORMAT_ELEMENT                 = 0x21;
 const PDU_IEI_REPLY_ADDRESS_ELEMENT                    = 0x22;
 const PDU_IEI_ENHANCED_VOICE_MAIL_INFORMATION          = 0x23;
 const PDU_IEI_NATIONAL_LANGUAGE_SINGLE_SHIFT           = 0x24;
 const PDU_IEI_NATIONAL_LANGUAGE_LOCKING_SHIFT          = 0x25;
 
+// Application Port Addressing, see 3GPP TS 23.040 9.2.3.24.3
+const PDU_APA_RESERVED_8BIT_PORTS = 240;
+const PDU_APA_VALID_16BIT_PORTS   = 49152;
+
 // 7bit alphabet escape character. The encoded value of this code point is left
 // undefined in official spec. Its code value is internally assigned to \uffff,
 // <noncharacter-FFFF> in Unicode basic multilingual plane.
 const PDU_NL_EXTENDED_ESCAPE = 0x1B;
 
 // <SP>, <LF>, <CR> are only defined in locking shift tables.
 const PDU_NL_SPACE = 0x20;
 const PDU_NL_LINE_FEED = 0x0A;
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -70,16 +70,18 @@ importScripts("ril_consts.js", "systemli
 let DEBUG;
 
 const INT32_MAX   = 2147483647;
 const UINT8_SIZE  = 1;
 const UINT16_SIZE = 2;
 const UINT32_SIZE = 4;
 const PARCEL_SIZE_SIZE = UINT32_SIZE;
 
+const PDU_HEX_OCTET_SIZE = 4;
+
 let RILQUIRKS_CALLSTATE_EXTRA_UINT32 = false;
 let RILQUIRKS_DATACALLSTATE_DOWN_IS_UP = false;
 // This flag defaults to true since on RIL v6 and later, we get the
 // version number via the UNSOLICITED_RIL_CONNECTED parcel.
 let RILQUIRKS_V5_LEGACY = true;
 
 /**
  * This object contains helpers buffering incoming data & deconstructing it
@@ -197,27 +199,72 @@ let Buf = {
   },
 
   /**
    * Functions for reading data from the incoming buffer.
    *
    * These are all little endian, apart from readParcelSize();
    */
 
+  /**
+   * Ensure position specified is readable.
+   *
+   * @param index
+   *        Data position in incoming parcel, valid from 0 to
+   *        this.currentParcelSize.
+   */
+  ensureIncomingAvailable: function ensureIncomingAvailable(index) {
+    if (index >= this.currentParcelSize) {
+      throw new Error("Trying to read data beyond the parcel end!");
+    } else if (index < 0) {
+      throw new Error("Trying to read data before the parcel begin!");
+    }
+  },
+
+  /**
+   * Seek in current incoming parcel.
+   *
+   * @param offset
+   *        Seek offset in relative to current position.
+   */
+  seekIncoming: function seekIncoming(offset) {
+    // Translate to 0..currentParcelSize
+    let cur = this.currentParcelSize - this.readAvailable;
+
+    let newIndex = cur + offset;
+    this.ensureIncomingAvailable(newIndex);
+
+    // ... incomingReadIndex -->|
+    // 0               new     cur           currentParcelSize
+    // |================|=======|===================|
+    // |<--        cur       -->|<- readAvailable ->|
+    // |<-- newIndex -->|<--  new readAvailable  -->|
+    this.readAvailable = this.currentParcelSize - newIndex;
+
+    // Translate back:
+    if (this.incomingReadIndex < cur) {
+      // The incomingReadIndex is wrapped.
+      newIndex += this.INCOMING_BUFFER_LENGTH;
+    }
+    newIndex += (this.incomingReadIndex - cur);
+    newIndex %= this.INCOMING_BUFFER_LENGTH;
+    this.incomingReadIndex = newIndex;
+  },
+
   readUint8Unchecked: function readUint8Unchecked() {
     let value = this.incomingBytes[this.incomingReadIndex];
     this.incomingReadIndex = (this.incomingReadIndex + 1) %
                              this.INCOMING_BUFFER_LENGTH;
     return value;
   },
 
   readUint8: function readUint8() {
-    if (!this.readAvailable) {
-      throw new Error("Trying to read data beyond the parcel end!");
-    }
+    // Translate to 0..currentParcelSize
+    let cur = this.currentParcelSize - this.readAvailable;
+    this.ensureIncomingAvailable(cur);
 
     this.readAvailable--;
     return this.readUint8Unchecked();
   },
 
   readUint16: function readUint16() {
     return this.readUint8() | this.readUint8() << 8;
   },
@@ -562,19 +609,22 @@ let RIL = {
    */
   cardState: null,
 
   /**
    * Strings
    */
   IMEI: null,
   IMEISV: null,
-  IMSI: null,
   SMSC: null,
-  MSISDN: null,
+
+  /**
+   * ICC information, such as MSISDN, IMSI, ...etc.
+   */
+  iccInfo: {},
 
   voiceRegistrationState: {},
   dataRegistrationState: {},
 
   /**
    * List of strings identifying the network operator.
    */
   operator: null,
@@ -761,55 +811,219 @@ let RIL = {
    *  Request an ICC I/O operation.
    * 
    *  See TS 27.007 "restricted SIM" operation, "AT Command +CRSM".
    *  The sequence is in the same order as how libril reads this parcel,
    *  see the struct RIL_SIM_IO_v5 or RIL_SIM_IO_v6 defined in ril.h
    *
    *  @param command 
    *         The I/O command, one of the ICC_COMMAND_* constants.
-   *  @param fileid
+   *  @param fileId
    *         The file to operate on, one of the ICC_EF_* constants.
-   *  @param pathid
-   *         String type, check pathid from TS 27.007 +CRSM  
+   *  @param pathId
+   *         String type, check the 'pathid' parameter from TS 27.007 +CRSM.
    *  @param p1, p2, p3
    *         Arbitrary integer parameters for the command.
    *  @param data
    *         String parameter for the command.
    *  @param pin2 [optional]
    *         String containing the PIN2.
    */
   iccIO: function iccIO(options) {
     let token = Buf.newParcel(REQUEST_SIM_IO, options);
     Buf.writeUint32(options.command);
-    Buf.writeUint32(options.fileid);
-    Buf.writeString(options.pathid);
+    Buf.writeUint32(options.fileId);
+    Buf.writeString(options.pathId);
     Buf.writeUint32(options.p1);
     Buf.writeUint32(options.p2);
     Buf.writeUint32(options.p3);
     Buf.writeString(options.data);
     if (options.pin2 != null) {
       Buf.writeString(options.pin2);
     }
     Buf.sendParcel();
   },
 
   /**
+   * Fetch ICC records.
+   */
+  fetchICCRecords: function fetchICCRecords() {
+    this.getIMSI();
+    this.getMSISDN();
+    this.getAD();
+    this.getUST();
+  },
+
+  /**
+   * Update the ICC information to RadioInterfaceLayer.
+   */
+  _handleICCInfoChange: function _handleICCInfoChange() {
+    this.iccInfo.type = "iccinfochange";
+    this.sendDOMMessage(this.iccInfo);
+  },
+
+  getIMSI: function getIMSI() {
+    Buf.simpleRequest(REQUEST_GET_IMSI);
+  },
+
+  /**
    * Read the MSISDN from the ICC.
    */
   getMSISDN: function getMSISDN() {
+    function callback() {
+      let length = Buf.readUint32();
+      // Each octet is encoded into two chars.
+      let recordLength = length / 2;
+      // Skip prefixed alpha identifier
+      Buf.seekIncoming((recordLength - MSISDN_FOOTER_SIZE_BYTES) *
+                        PDU_HEX_OCTET_SIZE);
+
+      // Dialling Number/SSC String
+      let len = GsmPDUHelper.readHexOctet();
+      if (len > MSISDN_MAX_NUMBER_SIZE_BYTES) {
+        debug("ICC_EF_MSISDN: invalid length of BCD number/SSC contents - " + len);
+        return;
+      }
+      this.iccInfo.MSISDN = GsmPDUHelper.readAddress(len);
+      let delimiter = Buf.readUint16();
+      if (!(length & 1)) {
+        delimiter |= Buf.readUint16();
+      }
+      if (DEBUG) {
+        if (delimiter != 0) {
+          debug("Something's wrong, found string delimiter: " + delimiter);
+        }
+      }
+
+      if (DEBUG) debug("MSISDN: " + this.iccInfo.MSISDN);
+      if (this.iccInfo.MSISDN) {
+        this._handleICCInfoChange();
+      }
+    }
+
     this.iccIO({
-      command: ICC_COMMAND_GET_RESPONSE,
-      fileid:  ICC_EF_MSISDN,
-      pathid:  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM,
-      p1:      0, // For GET_RESPONSE, p1 = 0
-      p2:      0, // For GET_RESPONSE, p2 = 0
-      p3:      GET_RESPONSE_EF_SIZE_BYTES,
-      data:    null,
-      pin2:    null,
+      command:   ICC_COMMAND_GET_RESPONSE,
+      fileId:    ICC_EF_MSISDN,
+      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_TELECOM,
+      p1:        0, // For GET_RESPONSE, p1 = 0
+      p2:        0, // For GET_RESPONSE, p2 = 0
+      p3:        GET_RESPONSE_EF_SIZE_BYTES,
+      data:      null,
+      pin2:      null,
+      type:      EF_TYPE_LINEAR_FIXED,
+      callback:  callback,
+    });
+  },
+
+  /**
+   * Read the AD from the ICC.
+   */
+  getAD: function getAD() {
+    function callback() {
+      let length = Buf.readUint32();
+      // Each octet is encoded into two chars.
+      let len = length / 2;
+      this.iccInfo.AD = GsmPDUHelper.readHexOctetArray(len);
+      let delimiter = Buf.readUint16();
+      if (!(length & 1)) {
+        delimiter |= Buf.readUint16();
+      }
+      if (DEBUG) {
+        if (delimiter != 0) {
+          debug("Something's wrong, found string delimiter: " + delimiter);
+        }
+      }
+
+      if (DEBUG) {
+        let str = "";
+        for (let i = 0; i < this.iccInfo.AD.length; i++) {
+          str += this.iccInfo.AD[i] + ", ";
+        }
+        debug("AD: " + str);
+      }
+
+      if (this.iccInfo.IMSI) {
+        // MCC is the first 3 digits of IMSI
+        this.iccInfo.MCC = this.iccInfo.IMSI.substr(0,3);
+        // The 4th byte of the response is the length of MNC
+        this.iccInfo.MNC = this.iccInfo.IMSI.substr(3, this.iccInfo.AD[3]);
+        if (DEBUG) debug("MCC: " + this.iccInfo.MCC + " MNC: " + this.iccInfo.MNC);
+        this._handleICCInfoChange();
+      }
+    }
+
+    this.iccIO({
+      command:   ICC_COMMAND_GET_RESPONSE,
+      fileId:    ICC_EF_AD,
+      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_GSM,
+      p1:        0, // For GET_RESPONSE, p1 = 0
+      p2:        0, // For GET_RESPONSE, p2 = 0
+      p3:        GET_RESPONSE_EF_SIZE_BYTES,
+      data:      null,
+      pin2:      null,
+      type:      EF_TYPE_TRANSPARENT,
+      callback:  callback,
+    });
+  },
+
+  /**
+   * Get whether specificed USIM service is available.
+   *
+   * @param service
+   *        Service id, valid in 1..N. See 3GPP TS 31.102 4.2.8.
+   * @return
+   *        true if the service is enabled,
+   *        false otherwise.
+   */
+  isUSTServiceAvailable: function isUSTServiceAvailable(service) {
+    service -= 1;
+    let index = service / 8;
+    let bitmask = 1 << (service % 8);
+    return this.UST && (index < this.UST.length) && (this.UST[index] & bitmask);
+  },
+
+  /**
+   * Read the UST from the ICC.
+   */
+  getUST: function getUST() {
+    function callback() {
+      let length = Buf.readUint32();
+      // Each octet is encoded into two chars.
+      let len = length / 2;
+      this.iccInfo.UST = GsmPDUHelper.readHexOctetArray(len);
+      let delimiter = Buf.readUint16();
+      if (!(length & 1)) {
+        delimiter |= Buf.readUint16();
+      }
+      if (DEBUG) {
+        if (delimiter != 0) {
+          debug("Something's wrong, found string delimiter: " + delimiter);
+        }
+      }
+      
+      if (DEBUG) {
+        let str = "";
+        for (let i = 0; i < this.iccInfo.UST.length; i++) {
+          str += this.iccInfo.UST[i] + ", ";
+        }
+        debug("UST: " + str);
+      }
+    }
+
+    this.iccIO({
+      command:   ICC_COMMAND_GET_RESPONSE,
+      fileId:    ICC_EF_UST,
+      pathId:    EF_PATH_MF_SIM + EF_PATH_DF_GSM,
+      p1:        0, // For GET_RESPONSE, p1 = 0
+      p2:        0, // For GET_RESPONSE, p2 = 0
+      p3:        GET_RESPONSE_EF_SIZE_BYTES,
+      data:      null,
+      pin2:      null,
+      type:      EF_TYPE_TRANSPARENT,
+      callback:  callback,
     });
   },
 
   /**
    * Request the phone's radio power to be switched on or off.
    *
    * @param on
    *        Boolean indicating the desired power state.
@@ -1258,17 +1472,17 @@ let RIL = {
         newCardState = GECKO_CARDSTATE_PUK_REQUIRED;
         break;
       case CARD_APPSTATE_SUBSCRIPTION_PERSO:
         newCardState = GECKO_CARDSTATE_NETWORK_LOCKED;
         break;
       case CARD_APPSTATE_READY:
         this.requestNetworkInfo();
         this.getSignalStrength();
-        this.getMSISDN();
+        this.fetchICCRecords();
         newCardState = GECKO_CARDSTATE_READY;
         break;
       case CARD_APPSTATE_UNKNOWN:
       case CARD_APPSTATE_DETECTED:
       default:
         newCardState = GECKO_CARDSTATE_NOT_READY;
     }
 
@@ -1276,43 +1490,129 @@ let RIL = {
       return;
     }
     this.cardState = newCardState;
     this.sendDOMMessage({type: "cardstatechange",
                          cardState: this.cardState});
   },
 
   /**
-   * Process the MSISDN ICC I/O response.
+   * Process a ICC_COMMAND_GET_RESPONSE type command for REQUEST_SIM_IO.
    */
-  _processMSISDNResponse: function _processMSISDNResponse(options) {
+  _processICCIOGetResponse: function _processICCIOGetResponse(options) {
+    let length = Buf.readUint32();
+
+    // The format is from TS 51.011, clause 9.2.1
+
+    // Skip RFU, data[0] data[1]
+    Buf.seekIncoming(2 * PDU_HEX_OCTET_SIZE);
+
+    // File size, data[2], data[3]
+    let fileSize = (GsmPDUHelper.readHexOctet() << 8) |
+                    GsmPDUHelper.readHexOctet();
+
+    // 2 bytes File id. data[4], data[5]
+    let fileId = (GsmPDUHelper.readHexOctet() << 8) |
+                  GsmPDUHelper.readHexOctet();
+    if (fileId != options.fileId) {
+      if (DEBUG) {
+        debug("Expected file ID " + options.fileId + " but read " + fileId);
+      }
+      return;
+    }
+
+    // Type of file, data[6]
+    let fileType = GsmPDUHelper.readHexOctet();
+    if (fileType != TYPE_EF) {
+      if (DEBUG) {
+        debug("Unexpected file type " + fileType);
+      }
+      return;
+    }
+
+    // Skip 1 byte RFU, data[7],
+    //      3 bytes Access conditions, data[8] data[9] data[10],
+    //      1 byte File status, data[11],
+    //      1 byte Length of the following data, data[12].
+    Buf.seekIncoming(((RESPONSE_DATA_STRUCTURE - RESPONSE_DATA_FILE_TYPE - 1) *
+        PDU_HEX_OCTET_SIZE));
+
+    // Read Structure of EF, data[13]
+    let efType = GsmPDUHelper.readHexOctet();
+    if (efType != options.type) {
+      if (DEBUG) {
+        debug("Expected EF type " + options.type + " but read " + efType);
+      }
+      return;
+    }
+
+    // Length of a record, data[14]
+    let recordSize = GsmPDUHelper.readHexOctet();
+
+    let delimiter = Buf.readUint16();
+    if (!(length & 1)) {
+      delimiter |= Buf.readUint16();
+    }
+    if (DEBUG) {
+      if (delimiter != 0) {
+        debug("Something's wrong, found string delimiter: " + delimiter);
+      }
+    }
+
+    switch (options.type) {
+      case EF_TYPE_LINEAR_FIXED:
+        // Reuse the options object and update some properties.
+        options.command = ICC_COMMAND_READ_RECORD;
+        options.p1 = 1; // Record number, always use the 1st record
+        options.p2 = READ_RECORD_ABSOLUTE_MODE;
+        options.p3 = recordSize;
+        this.iccIO(options);
+        break;
+      case EF_TYPE_TRANSPARENT:
+        // Reuse the options object and update some properties.
+        options.command = ICC_COMMAND_READ_BINARY;
+        options.p3 = fileSize;
+        this.iccIO(options);
+        break;
+    }
+  },
+
+  /**
+   * Process a ICC_COMMAND_READ_RECORD type command for REQUEST_SIM_IO.
+   */
+  _processICCIOReadRecord: function _processICCIOReadRecord(options) {
+    if (options.callback) {
+      options.callback.call(this);
+    }
+  },
+
+  /**
+   * Process a ICC_COMMAND_READ_BINARY type command for REQUEST_SIM_IO.
+   */
+  _processICCIOReadBinary: function _processICCIOReadBinary(options) {
+    if (options.callback) {
+      options.callback.call(this);
+    }
+  },
+
+  /**
+   * Process ICC I/O response.
+   */
+  _processICCIO: function _processICCIO(options) {
     switch (options.command) {
       case ICC_COMMAND_GET_RESPONSE:
-        let response = Buf.readString();
-        let recordSize = parseInt(
-            response.substr(RESPONSE_DATA_RECORD_LENGTH * 2, 2), 16) & 0xff;
-        let options = {
-          command: ICC_COMMAND_READ_RECORD,
-          fileid:  ICC_EF_MSISDN,
-          pathid:  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM,
-          p1:      1, // Record number, MSISDN is always in the 1st record
-          p2:      READ_RECORD_ABSOLUTE_MODE,
-          p3:      recordSize,
-          data:    null,
-          pin2:    null,
-        };
-        this.iccIO(options);
+        this._processICCIOGetResponse(options);
         break;
 
       case ICC_COMMAND_READ_RECORD:
-        // Ignore 2 bytes prefix, which is 4 chars
-        let number = GsmPDUHelper.readStringAsBCD().toString().substr(4); 
-        if (DEBUG) debug("MSISDN: " + number);
-        this.MSISDN = number || null;
-        this.sendDOMMessage({type: "siminfo", msisdn: this.MSISDN});
+        this._processICCIOReadRecord(options);
+        break;
+
+      case ICC_COMMAND_READ_BINARY:
+        this._processICCIOReadBinary(options);
         break;
     } 
   },
 
   _processVoiceRegistrationState: function _processVoiceRegistrationState(state) {
     let rs = this.voiceRegistrationState;
     let stateChanged = false;
 
@@ -1545,17 +1845,23 @@ let RIL = {
       // of the short message but shall discard its contents.` ~ 3GPP TS 23.040
       // 9.2.3.9
       return PDU_FCS_OK;
     }
 
     if (message.header && (message.header.segmentMaxSeq > 1)) {
       message = this._processReceivedSmsSegment(message);
     } else {
-      message.fullBody = message.body;
+      if (message.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
+        message.fullData = message.data;
+        delete message.data;
+      } else {
+        message.fullBody = message.body;
+        delete message.body;
+      }
     }
 
     if (message) {
       message.type = "sms-received";
       this.sendDOMMessage(message);
     }
 
     return PDU_FCS_OK;
@@ -1624,17 +1930,17 @@ let RIL = {
 
     return PDU_FCS_OK;
   },
 
   /**
    * Helper for processing received multipart SMS.
    *
    * @return null for handled segments, and an object containing full message
-   *         body once all segments are received.
+   *         body/data once all segments are received.
    */
   _processReceivedSmsSegment: function _processReceivedSmsSegment(original) {
     let hash = original.sender + ":" + original.header.segmentRef;
     let seq = original.header.segmentSeq;
 
     let options = this._receivedSmsSegmentsMap[hash];
     if (!options) {
       options = original;
@@ -1647,33 +1953,53 @@ let RIL = {
       // Duplicated segment?
       if (DEBUG) {
         debug("Got duplicated segment no." + seq + " of a multipart SMS: "
               + JSON.stringify(original));
       }
       return null;
     }
 
-    options.segments[seq] = original.body;
+    if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
+      options.segments[seq] = original.data;
+      delete original.data;
+    } else {
+      options.segments[seq] = original.body;
+      delete original.body;
+    }
     options.receivedSegments++;
     if (options.receivedSegments < options.segmentMaxSeq) {
       if (DEBUG) {
         debug("Got segment no." + seq + " of a multipart SMS: "
               + JSON.stringify(options));
       }
       return null;
     }
 
     // Remove from map
     delete this._receivedSmsSegmentsMap[hash];
 
     // Rebuild full body
-    options.fullBody = "";
-    for (let i = 1; i <= options.segmentMaxSeq; i++) {
-      options.fullBody += options.segments[i];
+    if (options.encoding == PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
+      // Uint8Array doesn't have `concat`, so we have to merge all segements
+      // by hand.
+      let fullDataLen = 0;
+      for (let i = 1; i <= options.segmentMaxSeq; i++) {
+        fullDataLen += options.segments[i].length;
+      }
+
+      options.fullData = new Uint8Array(fullDataLen);
+      for (let d= 0, i = 1; i <= options.segmentMaxSeq; i++) {
+        let data = options.segments[i];
+        for (let j = 0; j < data.length; j++) {
+          options.fullData[d++] = data[j];
+        }
+      }
+    } else {
+      options.fullBody = options.segments.join("");
     }
 
     if (DEBUG) {
       debug("Got full multipart SMS: " + JSON.stringify(options));
     }
 
     return options;
   },
@@ -1864,17 +2190,17 @@ RIL[REQUEST_GET_CURRENT_CALLS] = functio
   this._processCalls(calls);
 };
 RIL[REQUEST_DIAL] = null;
 RIL[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
-  this.IMSI = Buf.readString();
+  this.iccInfo.IMSI = Buf.readString();
 };
 RIL[REQUEST_HANGUP] = function REQUEST_HANGUP(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.getCurrentCalls();
 }; 
@@ -2101,28 +2427,23 @@ RIL[REQUEST_SIM_IO] = function REQUEST_S
   }
 
   let sw1 = Buf.readUint32();
   let sw2 = Buf.readUint32();
   if (sw1 != ICC_STATUS_NORMAL_ENDING) {
     // See GSM11.11, TS 51.011 clause 9.4, and ISO 7816-4 for the error
     // description.
     if (DEBUG) {
-      debug("ICC I/O Error EF id = " + options.fileid.toString(16) +
+      debug("ICC I/O Error EF id = " + options.fileId.toString(16) +
             " command = " + options.command.toString(16) +
             "(" + sw1.toString(16) + "/" + sw2.toString(16) + ")");
     }
     return;
   }
-
-  switch (options.fileid) {
-    case ICC_EF_MSISDN:
-      this._processMSISDNResponse(options);
-      break;
-  }
+  this._processICCIO(options);
 };
 RIL[REQUEST_SEND_USSD] = null;
 RIL[REQUEST_CANCEL_USSD] = null;
 RIL[REQUEST_GET_CLIR] = null;
 RIL[REQUEST_SET_CLIR] = null;
 RIL[REQUEST_QUERY_CALL_FORWARD_STATUS] = null;
 RIL[REQUEST_SET_CALL_FORWARD] = null;
 RIL[REQUEST_QUERY_CALL_WAITING] = null;
@@ -2555,16 +2876,27 @@ let GsmPDUHelper = {
    *        The octet (represented as a number) to encode.
    */
   writeHexOctet: function writeHexOctet(octet) {
     this.writeHexNibble(octet >> 4);
     this.writeHexNibble(octet);
   },
 
   /**
+   * Read an array of hex-encoded octets.
+   */
+  readHexOctetArray: function readHexOctetArray(length) {
+    let array = new Uint8Array(length);
+    for (let i = 0; i < length; i++) {
+      array[i] = this.readHexOctet();
+    }
+    return array;
+  },
+
+  /**
    * Convert an octet (number) to a BCD number.
    *
    * Any nibbles that are not in the BCD range count as 0.
    *
    * @param octet
    *        The octet (a number, as returned by getOctet())
    *
    * @return the corresponding BCD number.
@@ -2858,16 +3190,45 @@ let GsmPDUHelper = {
           dataAvailable -= 3;
           if (max && seq && (seq <= max)) {
             header.segmentRef = ref;
             header.segmentMaxSeq = max;
             header.segmentSeq = seq;
           }
           break;
         }
+        case PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_8BIT: {
+          let dstp = this.readHexOctet();
+          let orip = this.readHexOctet();
+          dataAvailable -= 2;
+          if ((dstp < PDU_APA_RESERVED_8BIT_PORTS)
+              || (orip < PDU_APA_RESERVED_8BIT_PORTS)) {
+            // 3GPP TS 23.040 clause 9.2.3.24.3: "A receiving entity shall
+            // ignore any information element where the value of the
+            // Information-Element-Data is Reserved or not supported"
+            break;
+          }
+          header.destinationPort = dstp;
+          header.originatorPort = orip;
+          break;
+        }
+        case PDU_IEI_APPLICATION_PORT_ADDREESING_SCHEME_16BIT: {
+          let dstp = (this.readHexOctet() << 8) | this.readHexOctet();
+          let orip = (this.readHexOctet() << 8) | this.readHexOctet();
+          dataAvailable -= 4;
+          // 3GPP TS 23.040 clause 9.2.3.24.4: "A receiving entity shall
+          // ignore any information element where the value of the
+          // Information-Element-Data is Reserved or not supported"
+          if ((dstp < PDU_APA_VALID_16BIT_PORTS)
+              && (orip < PDU_APA_VALID_16BIT_PORTS)) {
+            header.destinationPort = dstp;
+            header.originatorPort = orip;
+          }
+          break;
+        }
         case PDU_IEI_CONCATENATED_SHORT_MESSAGES_16BIT: {
           let ref = (this.readHexOctet() << 8) | this.readHexOctet();
           let max = this.readHexOctet();
           let seq = this.readHexOctet();
           dataAvailable -= 4;
           if (max && seq && (seq <= max)) {
             header.segmentRef = ref;
             header.segmentMaxSeq = max;
@@ -3010,16 +3371,65 @@ let GsmPDUHelper = {
             return;
         }
         break;
     }
     msg.epid = PDU_PID_DEFAULT;
   },
 
   /**
+   * Read TP-Data-Coding-Scheme(TP-DCS)
+   *
+   * @param msg
+   *        message object for output.
+   *
+   * @see 3GPP TS 23.040 9.2.3.10, 3GPP TS 23.038 4.
+   */
+  readDataCodingScheme: function readDataCodingScheme(msg) {
+    let dcs = this.readHexOctet();
+
+    // 7 bit is the default fallback encoding.
+    let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
+    switch (dcs & 0xC0) {
+      case 0x0:
+        // bits 7..4 = 00xx
+        switch (dcs & 0x0C) {
+          case 0x4:
+            encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
+            break;
+          case 0x8:
+            encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
+            break;
+        }
+        break;
+      case 0xC0:
+        // bits 7..4 = 11xx
+        switch (dcs & 0x30) {
+          case 0x20:
+            encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
+            break;
+          case 0x30:
+            if (!dcs & 0x04) {
+              encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
+            }
+            break;
+        }
+        break;
+      default:
+        // Falling back to default encoding.
+        break;
+    }
+
+    msg.dcs = dcs;
+    msg.encoding = encoding;
+
+    if (DEBUG) debug("PDU: message encoding is " + encoding + " bit.");
+  },
+
+  /**
    * Read GSM TP-Service-Centre-Time-Stamp(TP-SCTS).
    *
    * @see 3GPP TS 23.040 9.2.3.11
    */
   readTimestamp: function readTimestamp() {
     let year   = this.readSwappedNibbleBCD(1) + PDU_TIMESTAMP_YEAR_OFFSET;
     let month  = this.readSwappedNibbleBCD(1) - 1;
     let day    = this.readSwappedNibbleBCD(1);
@@ -3046,87 +3456,53 @@ let GsmPDUHelper = {
    * (UCS2) data.
    *
    * @param msg
    *        message object for output.
    * @param length
    *        length of user data to read in octets.
    */
   readUserData: function readUserData(msg, length) {
-    let dcs = msg.dcs;
     if (DEBUG) {
       debug("Reading " + length + " bytes of user data.");
-      debug("Coding scheme: " + dcs);
     }
-    // 7 bit is the default fallback encoding.
-    let encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
-    switch (dcs & 0xC0) {
-      case 0x0:
-        // bits 7..4 = 00xx
-        switch (dcs & 0x0C) {
-          case 0x4:
-            encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
-            break;
-          case 0x8:
-            encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
-            break;
-        }
-        break;
-      case 0xC0:
-        // bits 7..4 = 11xx
-        switch (dcs & 0x30) {
-          case 0x20:
-            encoding = PDU_DCS_MSG_CODING_16BITS_ALPHABET;
-            break;
-          case 0x30:
-            if (!dcs & 0x04) {
-              encoding = PDU_DCS_MSG_CODING_8BITS_ALPHABET;
-            }
-            break;
-        }
-        break;
-      default:
-        // Falling back to default encoding.
-        break;
-    }
-
-    if (DEBUG) debug("PDU: message encoding is " + encoding + " bit.");
 
     let paddingBits = 0;
     if (msg.udhi) {
       msg.header = this.readUserDataHeader();
 
-      if (encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
+      if (msg.encoding == PDU_DCS_MSG_CODING_7BITS_ALPHABET) {
         let headerBits = (msg.header.length + 1) * 8;
         let headerSeptets = Math.ceil(headerBits / 7);
 
         length -= headerSeptets;
         paddingBits = headerSeptets * 7 - headerBits;
       } else {
         length -= (msg.header.length + 1);
       }
     }
 
     msg.body = null;
-    switch (encoding) {
+    msg.data = null;
+    switch (msg.encoding) {
       case PDU_DCS_MSG_CODING_7BITS_ALPHABET:
         // 7 bit encoding allows 140 octets, which means 160 characters
         // ((140x8) / 7 = 160 chars)
         if (length > PDU_MAX_USER_DATA_7BIT) {
           if (DEBUG) debug("PDU error: user data is too long: " + length);
           break;
         }
 
         let langIndex = msg.udhi ? msg.header.langIndex : PDU_NL_IDENTIFIER_DEFAULT;
         let langShiftIndex = msg.udhi ? msg.header.langShiftIndex : PDU_NL_IDENTIFIER_DEFAULT;
         msg.body = this.readSeptetsToString(length, paddingBits, langIndex,
                                             langShiftIndex);
         break;
       case PDU_DCS_MSG_CODING_8BITS_ALPHABET:
-        // Unsupported.
+        msg.data = this.readHexOctetArray(length);
         break;
       case PDU_DCS_MSG_CODING_16BITS_ALPHABET:
         msg.body = this.readUCS2String(length);
         break;
     }
   },
 
   /**
@@ -3152,24 +3528,25 @@ let GsmPDUHelper = {
       // afterwards.` ~ 3GPP TS 23.040 9.2.3.27
       pi = this.readHexOctet();
     } while (pi & PDU_PI_EXTENSION);
 
     // `If the TP-UDL bit is set to "1" but the TP-DCS bit is set to "0" then
     // the receiving entity shall for TP-DCS assume a value of 0x00, i.e. the
     // 7bit default alphabet.` ~ 3GPP 23.040 9.2.3.27
     msg.dcs = 0;
+    msg.encoding = PDU_DCS_MSG_CODING_7BITS_ALPHABET;
 
     // TP-Protocol-Identifier
     if (pi & PDU_PI_PROTOCOL_IDENTIFIER) {
       this.readProtocolIndicator(msg);
     }
     // TP-Data-Coding-Scheme
     if (pi & PDU_PI_DATA_CODING_SCHEME) {
-      msg.dcs = this.readHexOctet();
+      this.readDataCodingScheme(msg);
     }
     // TP-User-Data-Length
     if (pi & PDU_PI_USER_DATA_LENGTH) {
       let userDataLength = this.readHexOctet();
       this.readUserData(msg, userDataLength);
     }
   },
 
@@ -3189,17 +3566,19 @@ let GsmPDUHelper = {
       SMSC:      null, // M  M  M  M  M  M
       mti:       null, // M  M  M  M  M  M
       udhi:      null, // M  M  X  M  M  M
       sender:    null, // M  X  X  X  X  X
       recipient: null, // X  X  M  X  M  M
       pid:       null, // M  O  M  O  O  M
       epid:      null, // M  O  M  O  O  M
       dcs:       null, // M  O  M  O  O  X
+      encoding:  null, // M  O  M  O  O  X
       body:      null, // M  O  M  O  O  O
+      data:      null, // M  O  M  O  O  O
       timestamp: null, // M  X  X  X  X  X
       status:    null, // X  X  X  X  M  X
       scts:      null, // X  X  X  M  M  X
       dt:        null, // X  X  X  X  M  X
     };
 
     // SMSC info
     let smscLength = this.readHexOctet();
@@ -3241,17 +3620,17 @@ let GsmPDUHelper = {
    */
   readDeliverMessage: function readDeliverMessage(msg) {
     // - Sender Address info -
     let senderAddressLength = this.readHexOctet();
     msg.sender = this.readAddress(senderAddressLength);
     // - TP-Protocolo-Identifier -
     this.readProtocolIndicator(msg);
     // - TP-Data-Coding-Scheme -
-    msg.dcs = this.readHexOctet();
+    this.readDataCodingScheme(msg);
     // - TP-Service-Center-Time-Stamp -
     msg.timestamp = this.readTimestamp();
     // - TP-User-Data-Length -
     let userDataLength = this.readHexOctet();
 
     // - TP-User-Data -
     if (userDataLength > 0) {
       this.readUserData(msg, userDataLength);
--- a/dom/tests/mochitest/bugs/Makefile.in
+++ b/dom/tests/mochitest/bugs/Makefile.in
@@ -151,12 +151,16 @@ include $(topsrcdir)/config/rules.mk
 		iframe_bug304459-1.html \
 		iframe_bug304459-2.html \
 		test_bug38959.html \
 		iframe_bug38959-1.html \
 		iframe_bug38959-2.html \
 		test_onerror_message.html \
 		test_bug735237.html \
 		test_bug739038.html \
+		test_bug740811.html \
+		test_bug743615.html \
+		utils_bug743615.js \
+		worker_bug743615.js \
 		$(NULL)
 
 libs:: 	$(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug740811.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=740811
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 740811</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=740811">Mozilla Bug 740811</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 740811 **/
+is(Object.getPrototypeOf(SVGElement.prototype), Element.prototype,
+   "Bogus proto for SVGElement");
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug743615.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=743615
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 743615</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="utils_bug743615.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=743615">Mozilla Bug 743615</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<canvas id="c" width="200" height="200"><canvas>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for structured cloning ImageData. **/
+
+SimpleTest.waitForExplicitFinish();
+window.addEventListener('message', windowMessage);
+startTest();
+
+function startTest() {
+  // Make an ImageData.
+  var ctx = document.getElementById('c').getContext('2d');
+  ctx.fillStyle = 'rgb(';
+  ctx.fillRect(30, 30, 50, 50);
+
+  // Make a blank ImageData.
+  var imageData = ctx.createImageData(200, 200);
+  is(imageData.data.length, imageData.width * imageData.height * 4,
+   'right size for data');
+
+  // Write some things into it.
+  var pattern = makePattern(imageData.data.length, 42, 7);
+  setPattern(imageData, pattern);
+  ok(checkPattern(imageData, pattern), 'Can read it back before sending');
+
+  // PostMessage it to ourselves.
+  window.postMessage({ imageData: imageData,
+                       pattern: pattern,
+                       dataRef: imageData.data }, '*');
+}
+
+function windowMessage(evt) {
+  // Check the pattern we received.
+  var imageData = evt.data.imageData;
+  var pattern = evt.data.pattern;
+  ok(checkPattern(imageData, pattern),
+     'postMessage from self worked correctly');
+
+  // We're not spec compliant on this yet.
+  todo_is(imageData.data, evt.data.dataRef,
+          'Should have backrefs for imagedata buffer');
+
+  // Make a new pattern, and send it to a worker.
+  pattern = makePattern(imageData.data.length, 4, 3);
+  setPattern(imageData, pattern);
+  var worker = new Worker('worker_bug743615.js');
+  worker.onmessage = workerMessage;
+  worker.postMessage( {imageData: imageData, pattern: pattern });
+}
+
+function workerMessage(evt) {
+  // Relay the results of the worker-side tests.
+  is(evt.data.statusMessage, 'PASS', evt.data.statusMessage);
+
+  // Test what the worker sent us.
+  ok(checkPattern(evt.data.imageData, evt.data.pattern),
+     'postMessage from worker worked correctly');
+
+  // All done.
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/utils_bug743615.js
@@ -0,0 +1,25 @@
+function makePattern(len, start, inc) {
+  var pattern = [];
+  while(len) {
+    pattern.push(start);
+    start = (start + inc) % 256;
+    --len;
+  }
+  return pattern;
+}
+
+function setPattern(imageData, pattern) {
+  if (pattern.length != imageData.data.length)
+    throw Error('Invalid pattern');
+  for (var i = 0; i < pattern.length; ++i)
+    imageData.data[i] = pattern[i];
+}
+
+function checkPattern(imageData, pattern) {
+  if (pattern.length != imageData.data.length)
+    throw Error('Invalid pattern');
+  for (var i = 0; i < pattern.length; ++i)
+    if (imageData.data[i] != pattern[i])
+      return false;
+  return true;
+}
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/worker_bug743615.js
@@ -0,0 +1,38 @@
+importScripts('utils_bug743615.js');
+
+self.onmessage = function onMessage(evt) {
+  // Check the pattern that was sent.
+  var imageData = evt.data.imageData;
+  var pattern = evt.data.pattern;
+  var statusMessage = checkPattern(imageData, pattern)
+                       ? 'PASS' : 'Got corrupt typed array in worker';
+
+  // Check against the interface object.
+  if (!(imageData instanceof ImageData))
+    statusMessage += ", Bad interface object in worker";
+
+  // Check the getters.
+  if (imageData.width * imageData.height != imageData.data.length / 4) {
+    statusMessage += ", Bad ImageData getters in worker: "
+    statusMessage += [imageData.width, imageData.height].join(', ');
+  }
+
+  // Make sure that writing to .data is a no-op when not in strict mode.
+  var origData = imageData.data;
+  var threw = false;
+  try {
+    imageData.data = [];
+    imageData.width = 2;
+    imageData.height = 2;
+  } catch(e) { threw = true; }
+  if (threw || imageData.data !== origData)
+    statusMessage = statusMessage + ", Should silently ignore sets";
+
+
+
+  // Send back a new pattern.
+  pattern = makePattern(imageData.data.length, 99, 2);
+  setPattern(imageData, pattern);
+  self.postMessage({ statusMessage: statusMessage, imageData: imageData,
+                     pattern: pattern });
+}
--- a/dom/workers/FileReaderSync.cpp
+++ b/dom/workers/FileReaderSync.cpp
@@ -39,31 +39,29 @@
 
 #include "FileReaderSync.h"
 
 #include "nsIDOMFile.h"
 
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jsfriendapi.h"
-#include "jstypedarray.h"
 #include "nsJSUtils.h"
 
 #include "Exceptions.h"
 #include "File.h"
 #include "FileReaderSyncPrivate.h"
 #include "WorkerInlines.h"
 
 #define FUNCTION_FLAGS \
   JSPROP_ENUMERATE
 
 USING_WORKERS_NAMESPACE
 
 using mozilla::dom::workers::exceptions::ThrowFileExceptionForCode;
-using js::ArrayBuffer;
 
 namespace {
 
 inline bool
 EnsureSucceededOrThrow(JSContext* aCx, nsresult rv)
 {
   if (NS_SUCCEEDED(rv)) {
     return true;
@@ -189,23 +187,23 @@ private:
     }
 
     PRUint64 blobSize;
     nsresult rv = blob->GetSize(&blobSize);
     if (!EnsureSucceededOrThrow(aCx, rv)) {
       return false;
     }
 
-    JSObject* jsArrayBuffer = js_CreateArrayBuffer(aCx, blobSize);
+    JSObject* jsArrayBuffer = JS_NewArrayBuffer(aCx, blobSize);
     if (!jsArrayBuffer) {
       return false;
     }
 
-    uint32_t bufferLength = JS_GetArrayBufferByteLength(jsArrayBuffer);
-    uint8_t* arrayBuffer = JS_GetArrayBufferData(jsArrayBuffer);
+    uint32_t bufferLength = JS_GetArrayBufferByteLength(jsArrayBuffer, aCx);
+    uint8_t* arrayBuffer = JS_GetArrayBufferData(jsArrayBuffer, aCx);
 
     rv = fileReader->ReadAsArrayBuffer(blob, bufferLength, arrayBuffer);
     if (!EnsureSucceededOrThrow(aCx, rv)) {
       return false;
     }
 
     JS_SET_RVAL(aCx, aVp, OBJECT_TO_JSVAL(jsArrayBuffer));
     return true;
new file mode 100644
--- /dev/null
+++ b/dom/workers/ImageData.cpp
@@ -0,0 +1,202 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ImageData.h"
+
+#include "jsfriendapi.h"
+
+#include "nsTraceRefcnt.h"
+
+#define PROPERTY_FLAGS \
+  (JSPROP_ENUMERATE | JSPROP_SHARED)
+
+USING_WORKERS_NAMESPACE
+
+namespace {
+
+class ImageData
+{
+  static JSClass sClass;
+  static JSPropertySpec sProperties[];
+
+  enum SLOT {
+    SLOT_width = 0,
+    SLOT_height,
+    SLOT_data,
+
+    SLOT_COUNT
+  };
+
+public:
+  static JSObject*
+  InitClass(JSContext* aCx, JSObject* aObj)
+  {
+    return JS_InitClass(aCx, aObj, NULL, &sClass, Construct, 0, sProperties,
+                        NULL, NULL, NULL);
+  }
+
+  static JSObject*
+  Create(JSContext* aCx, uint32_t aWidth, uint32_t aHeight, JSObject *aData)
+  {
+    MOZ_ASSERT(aData);
+    MOZ_ASSERT(JS_IsTypedArrayObject(aData, aCx));
+    MOZ_ASSERT(JS_IsUint8ClampedArray(aData, aCx));
+
+    JSObject* obj = JS_NewObject(aCx, &sClass, NULL, NULL);
+    if (!obj) {
+      return NULL;
+    }
+
+    JS_SetReservedSlot(obj, SLOT_width, UINT_TO_JSVAL(aWidth));
+    JS_SetReservedSlot(obj, SLOT_height, UINT_TO_JSVAL(aHeight));
+    JS_SetReservedSlot(obj, SLOT_data, OBJECT_TO_JSVAL(aData));
+
+    // This is an empty object. The point is just to differentiate instances
+    // from the interface object.
+    ImageData* priv = new ImageData();
+    JS_SetPrivate(obj, priv);
+
+    return obj;
+  }
+
+  static bool
+  IsInstance(JSObject* aObj)
+  {
+    return JS_GetClass(aObj) == &sClass;
+  }
+
+  static uint32_t
+  GetWidth(JSObject* aObj)
+  {
+    MOZ_ASSERT(IsInstance(aObj));
+    return JS_DoubleToUint32(JS_GetReservedSlot(aObj, SLOT_width).toNumber());
+  }
+
+  static uint32_t
+  GetHeight(JSObject* aObj)
+  {
+    MOZ_ASSERT(IsInstance(aObj));
+    return JS_DoubleToUint32(JS_GetReservedSlot(aObj, SLOT_height).toNumber());
+  }
+
+  static
+  JSObject* GetData(JSObject* aObj)
+  {
+    MOZ_ASSERT(IsInstance(aObj));
+    return &JS_GetReservedSlot(aObj, SLOT_data).toObject();
+  }
+
+private:
+  ImageData()
+  {
+    MOZ_COUNT_CTOR(mozilla::dom::workers::ImageData);
+  }
+
+  ~ImageData()
+  {
+    MOZ_COUNT_DTOR(mozilla::dom::workers::ImageData);
+  }
+
+  static JSBool
+  Construct(JSContext* aCx, unsigned aArgc, jsval* aVp)
+  {
+    JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL, JSMSG_WRONG_CONSTRUCTOR,
+                         sClass.name);
+    return false;
+  }
+
+  static void
+  Finalize(JSFreeOp* aFop, JSObject* aObj)
+  {
+    MOZ_ASSERT(JS_GetClass(aObj) == &sClass);
+    delete static_cast<ImageData*>(JS_GetPrivate(aObj));
+  }
+
+  static JSBool
+  GetProperty(JSContext* aCx, JSObject* aObj, jsid aIdval, jsval* aVp)
+  {
+    JSClass* classPtr = JS_GetClass(aObj);
+    if (classPtr != &sClass) {
+      JS_ReportErrorNumber(aCx, js_GetErrorMessage, NULL,
+                           JSMSG_INCOMPATIBLE_PROTO, sClass.name, "GetProperty",
+                           classPtr->name);
+      return false;
+    }
+
+    MOZ_ASSERT(JSID_IS_INT(aIdval));
+    MOZ_ASSERT(JSID_TO_INT(aIdval) >= 0 && JSID_TO_INT(aIdval) < SLOT_COUNT);
+
+    *aVp = JS_GetReservedSlot(aObj, JSID_TO_INT(aIdval));
+    return true;
+  }
+};
+
+JSClass ImageData::sClass = {
+  "ImageData",
+  JSCLASS_HAS_PRIVATE | JSCLASS_HAS_RESERVED_SLOTS(SLOT_COUNT),
+  JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+  JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, Finalize
+};
+
+JSPropertySpec ImageData::sProperties[] = {
+  // These properties are read-only per spec, which means that sets must throw
+  // in strict mode and silently fail otherwise. This is a problem for workers
+  // in general (because js_GetterOnlyPropertyStub throws unconditionally). The
+  // general plan for fixing this involves the new DOM bindings. But Peace
+  // Keeper breaks if we throw when setting these properties, so we need to do
+  // something about it in the mean time. So we use NULL, which defaults to the
+  // class setter (JS_StrictPropertyStub), which is always a silent no-op,
+  // regardless of strict mode. Not ideal, but good enough for now.
+  { "width", SLOT_width, PROPERTY_FLAGS, GetProperty, NULL },
+  { "height", SLOT_height, PROPERTY_FLAGS, GetProperty, NULL },
+  { "data", SLOT_data, PROPERTY_FLAGS, GetProperty, NULL },
+  { 0, 0, 0, NULL, NULL }
+};
+
+} // anonymous namespace
+
+BEGIN_WORKERS_NAMESPACE
+
+namespace imagedata {
+
+bool
+InitClass(JSContext* aCx, JSObject* aGlobal)
+{
+  return !!ImageData::InitClass(aCx, aGlobal);
+}
+
+JSObject*
+Create(JSContext* aCx, uint32_t aWidth, uint32_t aHeight, JSObject* aData)
+{
+  return ImageData::Create(aCx, aWidth, aHeight, aData);
+}
+
+bool
+IsImageData(JSObject* aObj)
+{
+  return ImageData::IsInstance(aObj);
+}
+
+uint32_t
+GetWidth(JSObject* aObj)
+{
+  return ImageData::GetWidth(aObj);
+}
+
+uint32_t
+GetHeight(JSObject* aObj)
+{
+  return ImageData::GetHeight(aObj);
+}
+
+JSObject*
+GetData(JSObject* aObj)
+{
+  return ImageData::GetData(aObj);
+}
+
+
+} // namespace imagedata
+
+END_WORKERS_NAMESPACE
new file mode 100644
--- /dev/null
+++ b/dom/workers/ImageData.h
@@ -0,0 +1,41 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_workers_imagedata_h__
+#define mozilla_dom_workers_imagedata_h__
+
+#include "Workers.h"
+
+BEGIN_WORKERS_NAMESPACE
+
+namespace imagedata {
+
+bool
+InitClass(JSContext* aCx, JSObject* aGlobal);
+
+JSObject*
+Create(JSContext* aCx, uint32_t aWidth, uint32_t aHeight, JSObject* aData);
+
+/*
+ * All data members live in private slots on the JS Object. Callers must
+ * first check IsImageData, after which they may call the data accessors.
+ */
+
+bool
+IsImageData(JSObject* aObj);
+
+uint32_t
+GetWidth(JSObject* aObj);
+
+uint32_t
+GetHeight(JSObject* aObj);
+
+JSObject*
+GetData(JSObject* aObj);
+
+} // namespace imagedata
+
+END_WORKERS_NAMESPACE
+
+#endif // mozilla_dom_workers_imagedata_h__
--- a/dom/workers/Makefile.in
+++ b/dom/workers/Makefile.in
@@ -19,16 +19,17 @@ CPPSRCS = \
   DOMBindingBase.cpp \
   Events.cpp \
   EventListenerManager.cpp \
   EventTarget.cpp \
   Exceptions.cpp \
   File.cpp \
   FileReaderSync.cpp \
   FileReaderSyncPrivate.cpp \
+  ImageData.cpp \
   Location.cpp \
   Navigator.cpp \
   Principal.cpp \
   RuntimeService.cpp \
   ScriptLoader.cpp \
   Worker.cpp \
   WorkerPrivate.cpp \
   WorkerScope.cpp \
--- a/dom/workers/WorkerPrivate.cpp
+++ b/dom/workers/WorkerPrivate.cpp
@@ -74,16 +74,17 @@
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
 #include "Events.h"
 #include "Exceptions.h"
 #include "File.h"
+#include "ImageData.h"
 #include "Principal.h"
 #include "RuntimeService.h"
 #include "ScriptLoader.h"
 #include "Worker.h"
 #include "WorkerFeature.h"
 #include "WorkerScope.h"
 
 #if 0 // Define to run GC more often.
@@ -98,16 +99,17 @@
 
 using mozilla::MutexAutoLock;
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 using mozilla::dom::workers::exceptions::ThrowDOMExceptionForCode;
 
 USING_WORKERS_NAMESPACE
 using namespace mozilla::dom::workers::events;
+using namespace mozilla::dom;
 
 namespace {
 
 const char gErrorChars[] = "error";
 const char gMessageChars[] = "message";
 
 template <class T>
 class AutoPtrComparator
@@ -328,16 +330,35 @@ struct WorkerStructuredCloneCallbacks
 #endif
 
         // nsIDOMBlob should be threadsafe, thus we will use the same instance
         // in the worker.
         JSObject* jsBlob = file::CreateBlob(aCx, blob);
         return jsBlob;
       }
     }
+    // See if the object is an ImageData.
+    else if (aTag == SCTAG_DOM_IMAGEDATA) {
+      JS_ASSERT(!aData);
+
+      // Read the information out of the stream.
+      uint32_t width, height;
+      jsval dataArray;
+      if (!JS_ReadUint32Pair(aReader, &width, &height) ||
+          !JS_ReadTypedArray(aReader, &dataArray))
+      {
+        return nsnull;
+      }
+      MOZ_ASSERT(dataArray.isObject());
+
+      // Construct the ImageData.
+      JSObject* obj = imagedata::Create(aCx, width, height,
+                                        JSVAL_TO_OBJECT(dataArray));
+      return obj;
+    }
 
     Error(aCx, 0);
     return nsnull;
   }
 
   static JSBool
   Write(JSContext* aCx, JSStructuredCloneWriter* aWriter, JSObject* aObj,
         void* aClosure)
@@ -369,16 +390,29 @@ struct WorkerStructuredCloneCallbacks
             JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_BLOB, 0) &&
             JS_WriteBytes(aWriter, &blob, sizeof(blob))) {
           clonedObjects->AppendElement(blob);
           return true;
         }
       }
     }
 
+    // See if this is an ImageData object.
+    if (imagedata::IsImageData(aObj)) {
+      // Pull the properties off the object.
+      uint32_t width = imagedata::GetWidth(aObj);
+      uint32_t height = imagedata::GetHeight(aObj);
+      JSObject* data = imagedata::GetData(aObj);
+
+      // Write the structured clone.
+      return JS_WriteUint32Pair(aWriter, SCTAG_DOM_IMAGEDATA, 0) &&
+             JS_WriteUint32Pair(aWriter, width, height) &&
+             JS_WriteTypedArray(aWriter, OBJECT_TO_JSVAL(data));
+    }
+
     Error(aCx, 0);
     return false;
   }
 
   static void
   Error(JSContext* aCx, uint32_t /* aErrorId */)
   {
     ThrowDOMExceptionForCode(aCx, DATA_CLONE_ERR);
@@ -461,22 +495,16 @@ struct MainThreadWorkerStructuredCloneCa
           Error(aCx, DATA_CLONE_ERR);
           return nsnull;
         }
 
         return JSVAL_TO_OBJECT(wrappedBlob);
       }
     }
 
-    JSObject* clone =
-      WorkerStructuredCloneCallbacks::Read(aCx, aReader, aTag, aData, aClosure);
-    if (clone) {
-      return clone;
-    }
-
     JS_ClearPendingException(aCx);
     return NS_DOMReadStructuredClone(aCx, aReader, aTag, aData, nsnull);
   }
 
   static JSBool
   Write(JSContext* aCx, JSStructuredCloneWriter* aWriter, JSObject* aObj,
         void* aClosure)
   {
@@ -522,22 +550,16 @@ struct MainThreadWorkerStructuredCloneCa
               JS_WriteBytes(aWriter, &blobPtr, sizeof(blobPtr))) {
             clonedObjects->AppendElement(blob);
             return true;
           }
         }
       }
     }
 
-    JSBool ok =
-      WorkerStructuredCloneCallbacks::Write(aCx, aWriter, aObj, aClosure);
-    if (ok) {
-      return ok;
-    }
-
     JS_ClearPendingException(aCx);
     return NS_DOMWriteStructuredClone(aCx, aWriter, aObj, nsnull);
   }
 
   static void
   Error(JSContext* aCx, uint32_t aErrorId)
   {
     AssertIsOnMainThread();
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -50,16 +50,17 @@
 #include "mozilla/Mutex.h"
 #include "mozilla/TimeStamp.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsEventQueue.h"
 #include "nsStringGlue.h"
 #include "nsTArray.h"
 #include "nsTPriorityQueue.h"
+#include "StructuredCloneTags.h"
 
 #include "EventTarget.h"
 #include "Queue.h"
 #include "WorkerFeature.h"
 
 class JSAutoStructuredCloneBuffer;
 class nsIDocument;
 class nsIPrincipal;
@@ -807,17 +808,17 @@ private:
   ProcessAllControlRunnables();
 };
 
 WorkerPrivate*
 GetWorkerPrivateFromContext(JSContext* aCx);
 
 enum WorkerStructuredDataType
 {
-  DOMWORKER_SCTAG_FILE = JS_SCTAG_USER_MIN + 0x1000,
+  DOMWORKER_SCTAG_FILE = SCTAG_DOM_MAX,
   DOMWORKER_SCTAG_BLOB,
 
   DOMWORKER_SCTAG_END
 };
 
 JSStructuredCloneCallbacks*
 WorkerStructuredCloneCallbacks(bool aMainRuntime);
 
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -57,16 +57,17 @@
 #include "ChromeWorkerScope.h"
 #include "Events.h"
 #include "EventListenerManager.h"
 #include "EventTarget.h"
 #include "Exceptions.h"
 #include "File.h"
 #include "FileReaderSync.h"
 #include "Location.h"
+#include "ImageData.h"
 #include "Navigator.h"
 #include "Principal.h"
 #include "ScriptLoader.h"
 #include "Worker.h"
 #include "WorkerPrivate.h"
 #include "XMLHttpRequest.h"
 
 #include "WorkerInlines.h"
@@ -991,16 +992,17 @@ CreateDedicatedWorkerGlobalScope(JSConte
   }
 
   // Init other classes we care about.
   if (!events::InitClasses(aCx, global, false) ||
       !file::InitClasses(aCx, global) ||
       !filereadersync::InitClass(aCx, global) ||
       !exceptions::InitClasses(aCx, global) ||
       !location::InitClass(aCx, global) ||
+      !imagedata::InitClass(aCx, global) ||
       !navigator::InitClass(aCx, global)) {
     return NULL;
   }
 
   // Init other paris-bindings.
   if (!XMLHttpRequest_workers::CreateInterfaceObjects(aCx, global) ||
       !XMLHttpRequestUpload_workers::CreateInterfaceObjects(aCx, global)) {
     return NULL;
--- a/dom/workers/XMLHttpRequest.cpp
+++ b/dom/workers/XMLHttpRequest.cpp
@@ -8,17 +8,17 @@
 #include "nsIDOMEvent.h"
 #include "nsIDOMEventListener.h"
 #include "nsIDOMProgressEvent.h"
 #include "nsIRunnable.h"
 #include "nsIVariant.h"
 #include "nsIXMLHttpRequest.h"
 #include "nsIXPConnect.h"
 
-#include "jstypedarray.h"
+#include "jsfriendapi.h"
 #include "nsContentUtils.h"
 #include "nsJSUtils.h"
 #include "nsThreadUtils.h"
 #include "nsXMLHttpRequest.h"
 
 #include "Events.h"
 #include "EventTarget.h"
 #include "Exceptions.h"
@@ -1153,22 +1153,22 @@ public:
     mBody.swap(aBody);
     mClonedObjects.SwapElements(aClonedObjects);
   }
 
   int
   MainThreadRun()
   {
     nsCOMPtr<nsIVariant> variant;
+    RuntimeService::AutoSafeJSContext cx;
+
     if (mBody.data()) {
       nsIXPConnect* xpc = nsContentUtils::XPConnect();
       NS_ASSERTION(xpc, "This should never be null!");
 
-      RuntimeService::AutoSafeJSContext cx;
-
       int error = 0;
 
       JSStructuredCloneCallbacks* callbacks =
         mWorkerPrivate->IsChromeWorker() ?
         ChromeWorkerStructuredCloneCallbacks(true) :
         WorkerStructuredCloneCallbacks(true);
 
       jsval body;
@@ -1211,17 +1211,17 @@ public:
       NS_ASSERTION(!mProxy->mUploadEventListenersAttached, "Huh?!");
       if (!mProxy->AddRemoveEventListeners(true, true)) {
         NS_ERROR("This should never fail!");
       }
     }
 
     mProxy->mInnerChannelId++;
 
-    nsresult rv = mProxy->mXHR->Send(variant);
+    nsresult rv = mProxy->mXHR->Send(variant, cx);
 
     if (NS_SUCCEEDED(rv)) {
       mProxy->mOutstandingSendCount++;
 
       if (!mHasUploadListeners) {
         NS_ASSERTION(!mProxy->mUploadEventListenersAttached, "Huh?!");
         if (!mProxy->AddRemoveEventListeners(true, true)) {
           NS_ERROR("This should never fail!");
@@ -1982,17 +1982,17 @@ XMLHttpRequest::Send(JSObject* aBody, ns
   if (!mProxy) {
     aRv = NS_ERROR_DOM_INVALID_STATE_ERR;
     return;
   }
 
   JSContext* cx = GetJSContext();
 
   jsval valToClone;
-  if (js_IsArrayBuffer(aBody) || file::GetDOMBlobFromJSObject(aBody)) {
+  if (JS_IsArrayBufferObject(aBody, cx) || file::GetDOMBlobFromJSObject(aBody)) {
     valToClone = OBJECT_TO_JSVAL(aBody);
   }
   else {
     JSString* bodyStr = JS_ValueToString(cx, OBJECT_TO_JSVAL(aBody));
     if (!bodyStr) {
       aRv = NS_ERROR_OUT_OF_MEMORY;
       return;
     }
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -868,17 +868,17 @@ DrawTargetCG::Init(CGContextRef cgContex
   return true;
 }
 
 bool
 DrawTargetCG::Init(const IntSize &aSize, SurfaceFormat &)
 {
   // XXX: we should come up with some consistent semantics for dealing
   // with zero area drawtargets
-  if (aSize.width == 0 || aSize.height == 0 ||
+  if (aSize.width <= 0 || aSize.height <= 0 ||
       // 32767 is the maximum size supported by cairo
       // we clamp to that to make it easier to interoperate
       aSize.width > 32767 || aSize.height > 32767) {
     mColorSpace = NULL;
     mCg = NULL;
     mData = NULL;
     return false;
   }
--- a/gfx/graphite2/include/graphite2/Font.h
+++ b/gfx/graphite2/include/graphite2/Font.h
@@ -23,19 +23,19 @@
     of the Mozilla Public License (http://mozilla.org/MPL) or the GNU
     General Public License, as published by the Free Software Foundation,
     either version 2 of the License or (at your option) any later version.
 */
 #pragma once
 
 #include "graphite2/Types.h"
 
-#define GR2_VERSION_MAJOR   2
-#define GR2_VERSION_MINOR   0
-#define GR2_VERSION_BUGFIX  1
+#define GR2_VERSION_MAJOR   1
+#define GR2_VERSION_MINOR   1
+#define GR2_VERSION_BUGFIX  2
 
 #ifdef __cplusplus
 extern "C"
 {
 #endif
 
 typedef struct gr_face          gr_face;
 typedef struct gr_font          gr_font;
--- a/gfx/graphite2/include/graphite2/Segment.h
+++ b/gfx/graphite2/include/graphite2/Segment.h
@@ -89,17 +89,17 @@ enum gr_attrCode {
     gr_slatAttLevel,        
     /// Line break breakweight for this glyph
     gr_slatBreak,           
     /// Ligature component reference (not implemented)
     gr_slatCompRef,         
     /// bidi directionality of this glyph (not implemented)
     gr_slatDir,             
     /// Whether insertion is allowed before this glyph
-    gr_slatInsert,          
+    gr_slatInsert,
     /// Final positioned position of this glyph relative to its parent in x-direction in pixels
     gr_slatPosX,            
     /// Final positioned position of this glyph relative to its parent in y-direction in pixels
     gr_slatPosY,            
     /// Amount to shift glyph by in x-direction design units
     gr_slatShiftX,          
     /// Amount to shift glyph by in y-direction design units
     gr_slatShiftY,          
@@ -114,18 +114,20 @@ enum gr_attrCode {
     /// Amount this slot can shrink (not implemented)
     gr_slatJShrink,         
     /// Granularity by which this slot can stretch or shrink (not implemented)
     gr_slatJStep,           
     /// Justification weight for this glyph (not implemented)
     gr_slatJWeight,         
     /// Amount this slot mush shrink or stretch in design units
     gr_slatJWidth,          
+    /// SubSegment split point
+    gr_slatSegSplit = gr_slatJStretch + 29,
     /// User defined attribute, see subattr for user attr number
-    gr_slatUserDefn = gr_slatJStretch + 30,
+    gr_slatUserDefn,
                             
     /// not implemented
     gr_slatMax,             
     /// not implemented
     gr_slatNoEffect = gr_slatMax + 1    
 };
 
 enum gr_bidirtl {
--- a/gfx/graphite2/src/Bidi.cpp
+++ b/gfx/graphite2/src/Bidi.cpp
@@ -295,18 +295,18 @@ const bidi_action actionWeak[][10] =
 
 { /*ret*/xxx, xxx, xxx, xxx, xxE, xxR, xxE, xxN, xxN, xxE, /* ET following re           */ },
 { /*let*/xxx, xxx, xxx, xxx, xxL, xxR, xxL, xxN, xxN, xxL, /* ET following le           */ },
 };
 
 inline uint8    GetDeferredType(bidi_action a)          { return (a >> 4) & 0xF; }
 inline uint8    GetResolvedType(bidi_action a)          { return a & 0xF; }
 inline DirCode  EmbeddingDirection(int l)               { return l & 1 ? R : L; }
-inline bool     IsDeferredState(bidi_state a)           { return (1 << a) & (rtmask | ltmask | acmask | rcmask | rsmask | lcmask | lsmask); }
-inline bool     IsModifiedClass(DirCode a)              { return (1 << a) & (ALmask | NSMmask | ESmask | CSmask | ETmask | ENmask); }
+inline bool     IsDeferredState(bidi_state a)           { return 0 != ((1 << a) & (rtmask | ltmask | acmask | rcmask | rsmask | lcmask | lsmask)); }
+inline bool     IsModifiedClass(DirCode a)              { return 0 != ((1 << a) & (ALmask | NSMmask | ESmask | CSmask | ETmask | ENmask)); }
 
 void SetDeferredRunClass(Slot *s, Slot *sRun, int nval)
 {
     if (!sRun || s == sRun) return;
     for (Slot *p = s->prev(); p != sRun; p = p->prev())
         p->setBidiClass(nval);
 }
 
--- a/gfx/graphite2/src/CMakeLists.txt
+++ b/gfx/graphite2/src/CMakeLists.txt
@@ -49,16 +49,17 @@ if (GRAPHITE2_NTRACING)
     set(TRACING)
 endif (GRAPHITE2_NTRACING)
 
 
 set(GRAPHITE_HEADERS 
     ../include/graphite2/Font.h
     ../include/graphite2/Segment.h
     ../include/graphite2/Types.h
+    ../include/graphite2/Log.h
     )
 
 file(GLOB PRIVATE_HEADERS inc/*.h) 
 
 add_library(graphite2 SHARED
     ${GRAPHITE2_VM_TYPE}_machine.cpp
     gr_char_info.cpp
     gr_features.cpp
--- a/gfx/graphite2/src/CachedFace.cpp
+++ b/gfx/graphite2/src/CachedFace.cpp
@@ -51,93 +51,74 @@ bool CachedFace::setupCache(unsigned int
 }
 
 
 bool CachedFace::runGraphite(Segment *seg, const Silf *pSilf) const
 {
     assert(pSilf);
     pSilf->runGraphite(seg, 0, pSilf->substitutionPass());
 
-    SegCache * segCache = NULL;
     unsigned int silfIndex = 0;
+    for (; silfIndex < m_numSilf && &(m_silfs[silfIndex]) != pSilf; ++silfIndex);
+    if (silfIndex == m_numSilf)  return false;
+    SegCache * const segCache = m_cacheStore->getOrCreate(silfIndex, seg->getFeatures(0));
+    if (!segCache)
+    	return false;
 
-    for (unsigned int i = 0; i < m_numSilf; i++)
-    {
-        if (&(m_silfs[i]) == pSilf)
-        {
-            break;
-        }
-    }
-    assert(silfIndex < m_numSilf);
     assert(m_cacheStore);
-    segCache = m_cacheStore->getOrCreate(silfIndex, seg->getFeatures(0));
     // find where the segment can be broken
     Slot * subSegStartSlot = seg->first();
     Slot * subSegEndSlot = subSegStartSlot;
     uint16 cmapGlyphs[eMaxSpliceSize];
     int subSegStart = 0;
-    bool spaceOnly = true;
-    for (unsigned int i = 0; i < seg->charInfoCount(); i++)
+    for (unsigned int i = 0; i < seg->charInfoCount(); ++i)
     {
-        if (i - subSegStart < eMaxSpliceSize)
-        {
-            cmapGlyphs[i-subSegStart] = subSegEndSlot->gid();
-        }
-        if (!m_cacheStore->isSpaceGlyph(subSegEndSlot->gid()))
-        {
-            spaceOnly = false;
-        }
+    	const unsigned int length = i - subSegStart + 1;
+        if (length < eMaxSpliceSize)
+            cmapGlyphs[length-1] = subSegEndSlot->gid();
+        else return false;
+        const bool spaceOnly = m_cacheStore->isSpaceGlyph(subSegEndSlot->gid());
         // at this stage the character to slot mapping is still 1 to 1
-        int breakWeight = seg->charinfo(i)->breakWeight();
-        int nextBreakWeight = (i + 1 < seg->charInfoCount())?
-            seg->charinfo(i+1)->breakWeight() : 0;
-        if (((breakWeight > 0) &&
-             (breakWeight <= gr_breakWord)) ||
-            (i + 1 == seg->charInfoCount()) ||
-             m_cacheStore->isSpaceGlyph(subSegEndSlot->gid()) ||
-            ((i + 1 < seg->charInfoCount()) &&
-             (((nextBreakWeight < 0) &&
-              (nextBreakWeight >= gr_breakBeforeWord)) ||
-              (subSegEndSlot->next() && m_cacheStore->isSpaceGlyph(subSegEndSlot->next()->gid())))))
+        const int	breakWeight = seg->charinfo(i)->breakWeight(),
+        		 	nextBreakWeight = (i + 1 < seg->charInfoCount())?
+        		 			seg->charinfo(i+1)->breakWeight() : 0;
+        const uint8 f = seg->charinfo(i)->flags();
+        if (((spaceOnly
+				|| (breakWeight > 0 && breakWeight <= gr_breakWord)
+				|| i + 1 == seg->charInfoCount()
+				|| ((nextBreakWeight < 0 && nextBreakWeight >= gr_breakBeforeWord)
+					|| (subSegEndSlot->next() && m_cacheStore->isSpaceGlyph(subSegEndSlot->next()->gid()))))
+				&& f != 1)
+			|| f == 2)
         {
             // record the next slot before any splicing
             Slot * nextSlot = subSegEndSlot->next();
-            if (spaceOnly)
-            {
-                // spaces should be left untouched by graphite rules in any sane font
-            }
-            else
+            // spaces should be left untouched by graphite rules in any sane font
+            if (!spaceOnly)
             {
                 // found a break position, check for a cache of the sub sequence
-                const SegCacheEntry * entry = (segCache)?
-                    segCache->find(cmapGlyphs, i - subSegStart + 1) : NULL;
+                const SegCacheEntry * entry = segCache->find(cmapGlyphs, length);
                 // TODO disable cache for words at start/end of line with contextuals
                 if (!entry)
                 {
-                    unsigned int length = i - subSegStart + 1;
                     SegmentScopeState scopeState = seg->setScope(subSegStartSlot, subSegEndSlot, length);
                     pSilf->runGraphite(seg, pSilf->substitutionPass(), pSilf->numPasses());
-                    //entry =runGraphiteOnSubSeg(segCache, seg, cmapGlyphs,
-                    //                           subSegStartSlot, subSegEndSlot,
-                    //                           subSegStart, i - subSegStart + 1);
-                    if ((length < eMaxSpliceSize) && segCache)
+                    if (length < eMaxSpliceSize)
+                    {
+                        seg->associateChars();
                         entry = segCache->cache(m_cacheStore, cmapGlyphs, length, seg, subSegStart);
+                    }
                     seg->removeScope(scopeState);
                 }
                 else
-                {
-                    //seg->splice(subSegStart, i - subSegStart + 1, subSegStartSlot, subSegEndSlot, entry);
-                    seg->splice(subSegStart, i - subSegStart + 1, subSegStartSlot, subSegEndSlot,
+                    seg->splice(subSegStart, length, subSegStartSlot, subSegEndSlot,
                         entry->first(), entry->glyphLength());
-                }
             }
-            subSegEndSlot = nextSlot;
-            subSegStartSlot = nextSlot;
+            subSegStartSlot = subSegEndSlot = nextSlot;
             subSegStart = i + 1;
-            spaceOnly = true;
         }
         else
         {
             subSegEndSlot = subSegEndSlot->next();
         }
     }
     return true;
 }
--- a/gfx/graphite2/src/CmapCache.cpp
+++ b/gfx/graphite2/src/CmapCache.cpp
@@ -107,17 +107,17 @@ uint16 CmapCache::operator [] (const uin
     const uint32 block = 0xFFFF & (usv >> 8);
     if (m_blocks[block])
         return m_blocks[block][usv & 0xFF];
     return 0;
 };
 
 CmapCache::operator bool() const throw()
 {
-	return m_blocks;
+	return m_blocks != 0;
 }
 
 
 DirectCmap::DirectCmap(const void* cmap, size_t length)
 {
     _ctable = TtfUtil::FindCmapSubtable(cmap, 3, 1, length);
     if (!_ctable || !TtfUtil::CheckCmap31Subtable(_ctable))
     {
@@ -131,11 +131,11 @@ DirectCmap::DirectCmap(const void* cmap,
 
 uint16 DirectCmap::operator [] (const uint32 usv) const throw()
 {
     return usv > 0xFFFF ? (_stable ? TtfUtil::Cmap310Lookup(_stable, usv) : 0) : TtfUtil::Cmap31Lookup(_ctable, usv);
 }
 
 DirectCmap::operator bool () const throw()
 {
-	return _ctable;
+	return _ctable != 0;
 }
 
--- a/gfx/graphite2/src/Code.cpp
+++ b/gfx/graphite2/src/Code.cpp
@@ -587,17 +587,17 @@ void Machine::Code::release_buffers() th
 }
 
 
 int32 Machine::Code::run(Machine & m, slotref * & map) const
 {
     assert(_own);
     assert(*this);          // Check we are actually runnable
 
-    if (m.slotMap().size() <= _max_ref + m.slotMap().context())
+    if (m.slotMap().size() <= size_t(_max_ref + m.slotMap().context()))
     {
         m._status = Machine::slot_offset_out_bounds;
 //        return (m.slotMap().end() - map);
         return 1;
     }
 
     return  m.run(_code, _data, map);
 }
--- a/gfx/graphite2/src/Face.cpp
+++ b/gfx/graphite2/src/Face.cpp
@@ -80,17 +80,17 @@ bool Face::readGlyphs(uint32 faceOptions
     
     return true;
 }
 
 bool Face::readGraphite()
 {
     size_t lSilf;
     const byte * const pSilf = getTable(Tag::Silf, &lSilf),
-    		   *      p = pSilf;
+    		   *           p = pSilf;
     if (!p) return false;
 
     const uint32 version = be::read<uint32>(p);
     if (version < 0x00020000) return false;
     if (version >= 0x00030000)
     	be::skip<uint32>(p);		// compilerVersion
     m_numSilf = be::read<uint16>(p);
     be::skip<uint16>(p);			// reserved
--- a/gfx/graphite2/src/GlyphFaceCache.cpp
+++ b/gfx/graphite2/src/GlyphFaceCache.cpp
@@ -37,17 +37,19 @@ using namespace graphite2;
     if ((m_pHead = face.getTable(Tag::head)) == NULL) return false;
     if ((m_pGlyf = face.getTable(Tag::glyf, &m_lGlyf)) == NULL) return false;
     if ((m_pHmtx = face.getTable(Tag::hmtx, &m_lHmtx)) == NULL) return false;
     if ((m_pHHea = face.getTable(Tag::hhea)) == NULL) return false;
 
     const void* pMaxp = face.getTable(Tag::maxp);
     if (pMaxp == NULL) return false;
     m_nGlyphs = m_nGlyphsWithGraphics = (unsigned short)TtfUtil::GlyphCount(pMaxp);
-    
+    if (TtfUtil::LocaLookup(m_nGlyphs-1, m_pLoca, m_lLoca, m_pHead) == size_t(-1))
+    	return false; // This will fail if m_nGlyphs is wildly out of range.
+
     if (!dumb_font)
     {
 		if ((m_pGlat = face.getTable(Tag::Glat, &m_lGlat)) == NULL) return false;
 		m_fGlat = be::peek<uint32>(m_pGlat);
 		size_t lGloc;
 		if ((m_pGloc = face.getTable(Tag::Gloc, &lGloc)) == NULL) return false;
 		if (lGloc < 6) return false;
 		int version = be::read<uint32>(m_pGloc);
--- a/gfx/graphite2/src/Pass.cpp
+++ b/gfx/graphite2/src/Pass.cpp
@@ -58,92 +58,92 @@ Pass::~Pass()
     free(m_startStates);
     free(m_sTable);
     free(m_states);
     free(m_ruleMap);
 
     delete [] m_rules;
 }
 
-bool Pass::readPass(void *pass, size_t pass_length, size_t subtable_base, const Face & face)
+bool Pass::readPass(const byte * const pass_start, size_t pass_length, size_t subtable_base, const Face & face)
 {
-    const byte *                p = reinterpret_cast<const byte *>(pass),
-               * const pass_start = p,
+    const byte *                p = pass_start,
                * const pass_end   = p + pass_length;
     size_t numRanges;
 
     if (pass_length < 40) return false; 
     // Read in basic values
-    m_immutable = (*p++) & 0x1U;
-    m_iMaxLoop = *p++;
-    p++; // skip maxContext
-    p += sizeof(byte);     // skip maxBackup
+    m_immutable = be::read<byte>(p) & 0x1U;
+    m_iMaxLoop = be::read<byte>(p);
+    be::skip<byte>(p,2); // skip maxContext & maxBackup
     m_numRules = be::read<uint16>(p);
-    p += sizeof(uint16);   // not sure why we would want this
+    be::skip<uint16>(p);   // fsmOffset - not sure why we would want this
     const byte * const pcCode = pass_start + be::read<uint32>(p) - subtable_base,
                * const rcCode = pass_start + be::read<uint32>(p) - subtable_base,
                * const aCode  = pass_start + be::read<uint32>(p) - subtable_base;
-    p += sizeof(uint32);
+    be::skip<uint32>(p);
     m_sRows = be::read<uint16>(p);
     m_sTransition = be::read<uint16>(p);
     m_sSuccess = be::read<uint16>(p);
     m_sColumns = be::read<uint16>(p);
     numRanges = be::read<uint16>(p);
-    p += sizeof(uint16)   // skip searchRange
-         +  sizeof(uint16)   // skip entrySelector
-         +  sizeof(uint16);  // skip rangeShift
+    be::skip<uint16>(p, 3); // skip searchRange, entrySelector & rangeShift.
     assert(p - pass_start == 40);
     // Perform some sanity checks.
     if (   m_sTransition > m_sRows
             || m_sSuccess > m_sRows
             || m_sSuccess + m_sTransition < m_sRows)
         return false;
 
     if (p + numRanges * 6 - 4 > pass_end) return false;
     m_numGlyphs = be::peek<uint16>(p + numRanges * 6 - 4) + 1;
     // Caculate the start of vairous arrays.
     const byte * const ranges = p;
-    p += numRanges*sizeof(uint16)*3;
+    be::skip<uint16>(p, numRanges*3);
     const byte * const o_rule_map = p;
-    p += (m_sSuccess + 1)*sizeof(uint16);
+    be::skip<uint16>(p, m_sSuccess + 1);
 
     // More sanity checks
     if (   reinterpret_cast<const byte *>(o_rule_map) > pass_end
             || p > pass_end)
         return false;
     const size_t numEntries = be::peek<uint16>(o_rule_map + m_sSuccess*sizeof(uint16));
     const byte * const   rule_map = p;
-    p += numEntries*sizeof(uint16);
+    be::skip<uint16>(p, numEntries);
 
     if (p > pass_end) return false;
-    m_minPreCtxt = *p++;
-    m_maxPreCtxt = *p++;
+    m_minPreCtxt = be::read<uint8>(p);
+    m_maxPreCtxt = be::read<uint8>(p);
     const byte * const start_states = p;
-    p += (m_maxPreCtxt - m_minPreCtxt + 1)*sizeof(int16);
+    be::skip<int16>(p, m_maxPreCtxt - m_minPreCtxt + 1);
     const uint16 * const sort_keys = reinterpret_cast<const uint16 *>(p);
-    p += m_numRules*sizeof(uint16);
+    be::skip<uint16>(p, m_numRules);
     const byte * const precontext = p;
-    p += m_numRules;
-    p += sizeof(byte);     // skip reserved byte
+    be::skip<byte>(p, m_numRules);
+    be::skip<byte>(p);     // skip reserved byte
 
     if (p > pass_end) return false;
     const size_t pass_constraint_len = be::read<uint16>(p);
     const uint16 * const o_constraint = reinterpret_cast<const uint16 *>(p);
-    p += (m_numRules + 1)*sizeof(uint16);
+    be::skip<uint16>(p, m_numRules + 1);
     const uint16 * const o_actions = reinterpret_cast<const uint16 *>(p);
-    p += (m_numRules + 1)*sizeof(uint16);
+    be::skip<uint16>(p, m_numRules + 1);
     const byte * const states = p;
-    p += m_sTransition*m_sColumns*sizeof(int16);
-    p += sizeof(byte);          // skip reserved byte
+    be::skip<int16>(p, m_sTransition*m_sColumns);
+    be::skip<byte>(p);          // skip reserved byte
     if (p != pcCode || p >= pass_end) return false;
-    p += pass_constraint_len;
-    if (p != rcCode || p >= pass_end) return false;
-    p += be::peek<uint16>(o_constraint + m_numRules);
+    be::skip<byte>(p, pass_constraint_len);
+    if (p != rcCode || p >= pass_end
+        || size_t(rcCode - pcCode) != pass_constraint_len) return false;
+    be::skip<byte>(p, be::peek<uint16>(o_constraint + m_numRules));
     if (p != aCode || p >= pass_end) return false;
-    if (size_t(rcCode - pcCode) != pass_constraint_len) return false;
+    be::skip<byte>(p, be::peek<uint16>(o_actions + m_numRules));
+
+    // We should be at the end or within the pass
+    if (p > pass_end) return false;
 
     // Load the pass constraint if there is one.
     if (pass_constraint_len)
     {
         m_cPConstraint = vm::Machine::Code(true, pcCode, pcCode + pass_constraint_len, 
                                   precontext[0], be::peek<uint16>(sort_keys), *m_silf, face);
         if (!m_cPConstraint) return false;
     }
@@ -470,24 +470,25 @@ bool Pass::testPassConstraint(Machine & 
     if (dbgout)
     	*dbgout << "constraint" << (ret || m.status() != Machine::finished);
 #endif
 
     return ret || m.status() != Machine::finished;
 }
 
 
-bool Pass::testConstraint(const Rule &r, Machine & m) const
+bool Pass::testConstraint(const Rule & r, Machine & m) const
 {
-    if ((r.sort - r.preContext) > (m.slotMap().size() - m.slotMap().context()))    return false;
-    if (m.slotMap().context() - r.preContext < 0) return false;
-    if (!*r.constraint)                 return true;
+	const uint16 curr_context = m.slotMap().context();
+    if (unsigned(r.sort - r.preContext) > m.slotMap().size() - curr_context
+    	|| curr_context - r.preContext < 0) return false;
+    if (!*r.constraint) return true;
     assert(r.constraint->constraint());
 
-    vm::slotref * map = m.slotMap().begin() + m.slotMap().context() - r.preContext;
+    vm::slotref * map = m.slotMap().begin() + curr_context - r.preContext;
     for (int n = r.sort; n && map; --n, ++map)
     {
     	if (!*map) continue;
         const int32 ret = r.constraint->run(m, map);
         if (!ret || m.status() != Machine::finished)
             return false;
     }
 
--- a/gfx/graphite2/src/SegCache.cpp
+++ b/gfx/graphite2/src/SegCache.cpp
@@ -139,17 +139,17 @@ SegCacheEntry* SegCache::cache(SegCacheS
     }
     SegCacheEntry * pEntry = prefixEntry->cache(cmapGlyphs, length, seg, charOffset, m_totalAccessCount);
     if (pEntry) ++m_segmentCount;
     return pEntry;
 }
 
 void SegCache::purge(SegCacheStore * store)
 {
-    unsigned long long minAccessCount = m_totalAccessCount * m_purgeFactor + 1;
+    unsigned long long minAccessCount = static_cast<unsigned long long>(m_totalAccessCount * m_purgeFactor + 1);
     if (minAccessCount < 2) minAccessCount = 2;
     unsigned long long oldAccessTime = m_totalAccessCount - store->maxSegmentCount() / eAgeFactor;
     purgeLevel(store, m_prefixes, 0, minAccessCount, oldAccessTime);
 }
 
 void SegCache::purgeLevel(SegCacheStore * store, SegCachePrefixArray prefixes, size_t level,
                           unsigned long long minAccessCount, unsigned long long oldAccessTime)
 {
--- a/gfx/graphite2/src/SegCacheEntry.cpp
+++ b/gfx/graphite2/src/SegCacheEntry.cpp
@@ -47,89 +47,38 @@ SegCacheEntry::SegCacheEntry(const uint1
     }
     size_t glyphCount = seg->slotCount();
     const Slot * slot = seg->first();
     m_glyph = new Slot[glyphCount];
     m_attr = gralloc<int16>(glyphCount * seg->numAttrs());
     m_glyphLength = glyphCount;
     Slot * slotCopy = m_glyph;
     m_glyph->prev(NULL);
-    struct Index2Slot {
-        Index2Slot(uint16 i, const Slot * s) : m_i(i), m_slot(s) {};
-        Index2Slot() : m_i(0), m_slot(NULL) {};
-        uint16 m_i;
-        const Slot * m_slot;
-    };
-    struct Index2Slot parentGlyphs[eMaxSpliceSize];
-    struct Index2Slot childGlyphs[eMaxSpliceSize];
-    uint16 numParents = 0;
-    uint16 numChildren = 0;
+
     uint16 pos = 0;
     while (slot)
     {
         slotCopy->userAttrs(m_attr + pos * seg->numAttrs());
         slotCopy->set(*slot, -static_cast<int32>(charOffset), seg->numAttrs());
+        slotCopy->index(pos);
         if (slot->firstChild())
-        {
-            new(parentGlyphs + numParents) Index2Slot( pos, slot );
-            ++numParents;
-        }
+        	slotCopy->m_child = m_glyph + slot->firstChild()->index();
         if (slot->attachedTo())
-        {
-            new(childGlyphs + numChildren) Index2Slot( pos, slot );
-            ++numChildren;
-        }
+        	slotCopy->attachTo(m_glyph + slot->attachedTo()->index());
+        if (slot->nextSibling())
+        	slotCopy->m_sibling = m_glyph + slot->nextSibling()->index();
         slot = slot->next();
         ++slotCopy;
         ++pos;
         if (slot)
         {
             slotCopy->prev(slotCopy-1);
             (slotCopy-1)->next(slotCopy);
         }
     }
-    // loop over the attached children finding their siblings and parents
-    for (int16 i = 0; i < numChildren; i++)
-    {
-        if (childGlyphs[i].m_slot->nextSibling())
-        {
-            for (int16 j = i; j < numChildren; j++)
-            {
-                if (childGlyphs[i].m_slot->nextSibling() == childGlyphs[j].m_slot)
-                {
-                    m_glyph[childGlyphs[i].m_i].sibling(m_glyph + childGlyphs[j].m_i);
-                    break;
-                }
-            }
-            if (!m_glyph[childGlyphs[i].m_i].nextSibling())
-            {
-                // search backwards
-                for (int16 j = i-1; j >= 0; j--)
-                {
-                    if (childGlyphs[i].m_slot->nextSibling() == childGlyphs[j].m_slot)
-                    {
-                        m_glyph[childGlyphs[i].m_i].sibling(m_glyph + childGlyphs[j].m_i);
-                        break;
-                    }
-                }
-            }
-        }
-        // now find the parent glyph
-        for (int16 j = 0; j < numParents; j++)
-        {
-            if (childGlyphs[i].m_slot->attachedTo() == parentGlyphs[j].m_slot)
-            {
-                m_glyph[childGlyphs[i].m_i].attachTo(m_glyph + parentGlyphs[j].m_i);
-                if (parentGlyphs[j].m_slot->firstChild() == childGlyphs[i].m_slot)
-                {
-                    m_glyph[parentGlyphs[j].m_i].child(m_glyph + childGlyphs[i].m_i);
-                }
-            }
-        }
-    }
 }
 
 
 void SegCacheEntry::clear()
 {
     free(m_unicode);
     free(m_attr);
     delete [] m_glyph;
--- a/gfx/graphite2/src/Segment.cpp
+++ b/gfx/graphite2/src/Segment.cpp
@@ -199,96 +199,67 @@ void Segment::freeSlot(Slot *aSlot)
     if (!m_freeSlots)
         aSlot->next(NULL);
     else
         aSlot->next(m_freeSlots);
     m_freeSlots = aSlot;
 }
 
 #ifndef GRAPHITE2_NSEGCACHE
-void Segment::splice(size_t offset, size_t length, Slot * startSlot,
-                       Slot * endSlot, const Slot * firstSpliceSlot,
-                       size_t numGlyphs)
+void Segment::splice(size_t offset, size_t length, Slot * const startSlot,
+                       Slot * endSlot, const Slot * srcSlot,
+                       const size_t numGlyphs)
 {
-    const Slot * replacement = firstSpliceSlot;
-    Slot * slot = startSlot;
     extendLength(numGlyphs - length);
-    // insert extra slots if needed
-    while (numGlyphs > length)
-    {
-        Slot * extra = newSlot();
-        extra->prev(endSlot);
-        extra->next(endSlot->next());
-        endSlot->next(extra);
-        if (extra->next())
-            extra->next()->prev(extra);
-        if (m_last == endSlot)
-            m_last = extra;
-        endSlot = extra;
-        ++length;
-    }
     // remove any extra
     if (numGlyphs < length)
     {
-        Slot * afterSplice = endSlot->next();
+        Slot * end = endSlot->next();
         do
         {
             endSlot = endSlot->prev();
             freeSlot(endSlot->next());
-            --length;
-        } while (numGlyphs < length);
-        endSlot->next(afterSplice);
-        if (afterSplice)
-            afterSplice->prev(endSlot);
+        } while (numGlyphs < --length);
+        endSlot->next(end);
+        if (end)
+            end->prev(endSlot);
     }
-    assert(numGlyphs == length);
-    // keep a record of consecutive slots wrt start of splice to minimize
-    // iterative next/prev calls
-    Slot * slotArray[eMaxSpliceSize];
-    uint16 slotPosition = 0;
-    for (uint16 i = 0; i < numGlyphs; i++)
+    else
     {
-        if (slotPosition <= i)
-        {
-            slotArray[i] = slot;
-            slotPosition = i;
-        }
-        slot->set(*replacement, offset, m_silf->numUser());
-        if (replacement->attachedTo())
+        // insert extra slots if needed
+        while (numGlyphs > length)
         {
-            uint16 parentPos = replacement->attachedTo() - firstSpliceSlot;
-            while (slotPosition < parentPos)
-            {
-                slotArray[slotPosition+1] = slotArray[slotPosition]->next();
-                ++slotPosition;
-            }
-            slot->attachTo(slotArray[parentPos]);
+            Slot * extra = newSlot();
+            extra->prev(endSlot);
+            extra->next(endSlot->next());
+            endSlot->next(extra);
+            if (extra->next())
+                extra->next()->prev(extra);
+            if (m_last == endSlot)
+                m_last = extra;
+            endSlot = extra;
+            ++length;
         }
-        if (replacement->nextSibling())
-        {
-            uint16 pos = replacement->nextSibling() - firstSpliceSlot;
-            while (slotPosition < pos)
-            {
-                slotArray[slotPosition+1] = slotArray[slotPosition]->next();
-                ++slotPosition;
-            }
-            slot->sibling(slotArray[pos]);
-        }
-        if (replacement->firstChild())
-        {
-            uint16 pos = replacement->firstChild() - firstSpliceSlot;
-            while (slotPosition < pos)
-            {
-                slotArray[slotPosition+1] = slotArray[slotPosition]->next();
-                ++slotPosition;
-            }
-            slot->child(slotArray[pos]);
-        }
-        slot = slot->next();
-        replacement = replacement->next();
+    }
+
+    endSlot = endSlot->next();
+    assert(numGlyphs == length);
+    Slot * indexmap[eMaxSpliceSize*3];
+    assert(numGlyphs < sizeof indexmap/sizeof *indexmap);
+    Slot * slot = startSlot;
+    for (uint16 i=0; i < numGlyphs; slot = slot->next(), ++i)
+    	indexmap[i] = slot;
+
+    slot = startSlot;
+    for (slot=startSlot; slot != endSlot; slot = slot->next(), srcSlot = srcSlot->next())
+    {
+        slot->set(*srcSlot, offset, m_silf->numUser());
+        if (srcSlot->attachedTo())	slot->attachTo(indexmap[srcSlot->attachedTo()->index()]);
+        if (srcSlot->nextSibling())	slot->m_sibling = indexmap[srcSlot->nextSibling()->index()];
+        if (srcSlot->firstChild())	slot->m_child = indexmap[srcSlot->firstChild()->index()];
     }
 }
 #endif // GRAPHITE2_NSEGCACHE
 
 void Segment::linkClusters(Slot *s, Slot * end)
 {
 	end = end->next();
 
@@ -342,16 +313,34 @@ Position Segment::positionSlots(const Fo
             if (s->isBase())
                 currpos = s->finalise(this, font, currpos, bbox, cMin, 0, clusterMin = currpos.x);
         }
     }
     return currpos;
 }
 
 
+void Segment::associateChars()
+{
+    int i = 0;
+    for (Slot * s = m_first; s; s->index(i++), s = s->next())
+    {
+        int j = s->before();
+        if (j < 0)	continue;
+
+        for (const int after = s->after(); j <= after; ++j)
+		{
+			CharInfo & c = *charinfo(j);
+			if (c.before() == -1 || i < c.before()) 	c.before(i);
+			if (c.after() < i) 							c.after(i);
+		}
+    }
+}
+
+
 template <typename utf_iter>
 inline void process_utf_data(Segment & seg, const Face & face, const int fid, utf_iter c, size_t n_chars)
 {
 	const Cmap    & cmap = face.cmap();
 	int slotid = 0;
 
 	const typename utf_iter::codeunit_type * const base = c;
 	for (; n_chars; --n_chars, ++c, ++slotid)
@@ -377,48 +366,26 @@ void Segment::read_text(const Face *face
 	}
 }
 
 void Segment::prepare_pos(const Font * /*font*/)
 {
     // copy key changeable metrics into slot (if any);
 }
 
-void Segment::finalise(const Font *font)
-{
-	if (!m_first) return;
-
-    m_advance = positionSlots(font);
-    int i = 0;
-    for (Slot * s = m_first; s; s->index(i++), s = s->next())
-    {
-        int j = s->before();
-        if (j < 0)	continue;
-
-        for (const int after = s->after(); j <= after; ++j)
-		{
-			CharInfo & c = *charinfo(j);
-			if (c.before() == -1 || i < c.before()) 	c.before(i);
-			if (c.after() < i) 							c.after(i);
-		}
-    }
-    linkClusters(m_first, m_last);
-}
-
 void Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUSED justFlags flags, Slot *pFirst, Slot *pLast)
 {
     Slot *pEnd = pSlot;
     Slot *s, *end;
     int numBase = 0;
-    float currWidth = 0.;
-    float scale = font ? font->scale() : 1.0;
-    float base;
+    float currWidth = 0.0;
+    const float scale = font ? font->scale() : 1.0f;
 
     if (!pFirst) pFirst = pSlot;
-    base = pFirst->origin().x / scale;
+    const float base = pFirst->origin().x / scale;
     width = width / scale;
     end = pLast ? pLast->next() : NULL;
 
     for (s = pFirst; s != end; s=s->next())
     {
         float w = s->origin().x / scale + s->advance() - base;
         if (w > currWidth) currWidth = w;
         pEnd = s;
@@ -466,32 +433,32 @@ void Segment::bidiPass(uint8 aBidi, int 
 	if (slotCount() == 0)
 		return;
 
     Slot *s;
     int baseLevel = paradir ? 1 : 0;
     unsigned int bmask = 0;
     for (s = first(); s; s = s->next())
     {
-        unsigned int bAttr = glyphAttr(s->gid(), aBidi);
+    	unsigned int bAttr = glyphAttr(s->gid(), aBidi);
         s->setBidiClass((bAttr <= 16) * bAttr);
         bmask |= (1 << s->getBidiClass());
         s->setBidiLevel(baseLevel);
     }
     if (bmask & (paradir ? 0x92 : 0x9C))
     {
         if (bmask & 0xF800)
             resolveExplicit(baseLevel, 0, first(), 0);
         if (bmask & 0x10178)
             resolveWeak(baseLevel, first());
         if (bmask & 0x161)
             resolveNeutrals(baseLevel, first());
         resolveImplicit(first(), this, aMirror);
         resolveWhitespace(baseLevel, this, aBidi, last());
-        s = resolveOrder(s = first(), baseLevel);
+        s = resolveOrder(s = first(), baseLevel != 0);
         first(s); last(s->prev());
         s->prev()->next(0); s->prev(0);
     }
     else if (!(dir() & 4) && baseLevel && aMirror)
     {
         for (s = first(); s; s = s->next())
         {
             unsigned short g = glyphAttr(s->gid(), aMirror);
--- a/gfx/graphite2/src/Silf.cpp
+++ b/gfx/graphite2/src/Silf.cpp
@@ -59,127 +59,101 @@ void Silf::releaseBuffers() throw()
     m_passes= 0;
     m_pseudos = 0;
     m_classOffsets = 0;
     m_classData = 0;
     m_justs = 0;
 }
 
 
-bool Silf::readGraphite(const void* pSilf, size_t lSilf, const Face& face, uint32 version)
+bool Silf::readGraphite(const byte * const silf_start, size_t lSilf, const Face& face, uint32 version)
 {
-    const byte * p = (byte *)pSilf,
-    		   * const eSilf = p + lSilf;
+    const byte * p = silf_start,
+    		   * const silf_end = p + lSilf;
 
     if (version >= 0x00030000)
     {
-        if (lSilf < 27)		{ releaseBuffers(); return false; }
-        p += 8;
-    }
-    else if (lSilf < 19) 	{ releaseBuffers(); return false; }
-    p += 2;     // maxGlyphID
-    p += 4;     // extra ascent/descent
-    m_numPasses = uint8(*p++);
-    if (m_numPasses > 128)
-        return false;
-    m_passes = new Pass[m_numPasses];
-    m_sPass = uint8(*p++);
-    m_pPass = uint8(*p++);
-    if (m_pPass < m_sPass) {
-        releaseBuffers();
-        return false;
+        if (lSilf < 28)		{ releaseBuffers(); return false; }
+        be::skip<int32>(p);	   // ruleVersion
+        be::skip<uint16>(p,2); // passOffset & pseudosOffset
     }
-    m_jPass = uint8(*p++);
-    if (m_jPass < m_pPass) {
-        releaseBuffers();
-        return false;
-    }
-    m_bPass = uint8(*p++);     // when do we reorder?
-    if (m_bPass != 0xFF && (m_bPass < m_jPass || m_bPass > m_numPasses)) {
-        releaseBuffers();
-        return false;
-    }
-    m_flags = uint8(*p++);
-    p += 2;     // ignore line end contextuals for now
-    m_aPseudo = uint8(*p++);
-    m_aBreak = uint8(*p++);
-    m_aBidi = uint8(*p++);
-    m_aMirror = uint8(*p++);
-    p += 1;     // skip reserved stuff
-    m_numJusts = uint8(*p++);
+    else if (lSilf < 20) 	{ releaseBuffers(); return false; }
+    be::skip<uint16>(p);  // maxGlyphID
+    be::skip<int16>(p,2); // extra ascent & descent
+    m_numPasses = be::read<uint8>(p);
+    m_sPass     = be::read<uint8>(p);
+    m_pPass     = be::read<uint8>(p);
+    m_jPass     = be::read<uint8>(p);
+    m_bPass     = be::read<uint8>(p);
+    m_flags     = be::read<uint8>(p);
+    be::skip<uint8>(p,2); //  max{Pre,Post}Context.
+    m_aPseudo   = be::read<uint8>(p);
+    m_aBreak    = be::read<uint8>(p);
+    m_aBidi     = be::read<uint8>(p);
+    m_aMirror   = be::read<uint8>(p);
+    be::skip<byte>(p);     // skip reserved stuff
+
+    // Read Justification levels.
+    m_numJusts  = be::read<uint8>(p);
+    if (p + m_numJusts * 8 >= silf_end)  { releaseBuffers(); return false; }
     m_justs = gralloc<Justinfo>(m_numJusts);
     for (uint8 i = 0; i < m_numJusts; i++)
     {
         ::new(m_justs + i) Justinfo(p[0], p[1], p[2], p[3]);
-        p += 8;
-    }
-//    p += uint8(*p) * 8 + 1;     // ignore justification for now
-    if (p + 9 >= eSilf) { releaseBuffers(); return false; }
-    m_aLig = be::read<uint16>(p);
-    if (m_aLig > 127) {
-        releaseBuffers();
-        return false;
+        be::skip<byte>(p,8);
     }
-    m_aUser = uint8(*p++);
-    m_iMaxComp = uint8(*p++);
-    p += 5;     // skip direction and reserved
-    p += uint8(*p) * 2 + 1;        // don't need critical features yet
-    p++;        // reserved
-    if (p >= eSilf) 
-    {
-        releaseBuffers();
-        return false;
+
+    if (p + sizeof(uint16) + sizeof(uint8)*8 >= silf_end) { releaseBuffers(); return false; }
+    m_aLig      = be::read<uint16>(p);
+    m_aUser     = be::read<uint8>(p);
+    m_iMaxComp  = be::read<uint8>(p);
+    be::skip<byte>(p,5); 						// direction and 4 reserved bytes
+    be::skip<uint16>(p, be::read<uint8>(p)); 	// don't need critical features yet
+    be::skip<byte>(p);							// reserved
+    if (p >= silf_end)   { releaseBuffers(); return false; }
+    be::skip<uint32>(p, be::read<uint8>(p));	// don't use scriptTag array.
+    be::skip<uint16>(p); // lbGID
+    const byte * o_passes = p,
+               * const passes_start = silf_start + be::read<uint32>(p);
+
+    if (m_numPasses > 128 || passes_start >= silf_end
+    	|| m_pPass < m_sPass
+    	|| m_jPass < m_pPass
+    	|| (m_bPass != 0xFF && (m_bPass < m_jPass || m_bPass > m_numPasses))
+    	|| m_aLig > 127) {
+        releaseBuffers(); return false;
     }
-    p += uint8(*p) * 4 + 1;        // skip scripts
-    p += 2;     // skip lbGID
-    
-    if (p + 4 * (m_numPasses + 1) + 6 >= eSilf) 
-    {
-        releaseBuffers(); 
-        return false;
-    }
-    const byte * pPasses = p;
-    p += 4 * (m_numPasses + 1);
+    be::skip<uint32>(p, m_numPasses);
+    if (p + sizeof(uint16) >= passes_start)  { releaseBuffers(); return false; }
     m_numPseudo = be::read<uint16>(p);
-    p += 6;
-    if (p + m_numPseudo * 6 >= eSilf) 
-    {
-        releaseBuffers();
-        return false;
+    be::skip<uint16>(p, 3);	// searchPseudo, pseudoSelector, pseudoShift
+    if (p + m_numPseudo*(sizeof(uint32) + sizeof(uint16)) >= passes_start) {
+        releaseBuffers(); return false;
     }
     m_pseudos = new Pseudo[m_numPseudo];
     for (int i = 0; i < m_numPseudo; i++)
     {
         m_pseudos[i].uid = be::read<uint32>(p);
         m_pseudos[i].gid = be::read<uint16>(p);
     }
-    if (p >= eSilf) 
-    {
-        releaseBuffers();
-        return false;
-    }
 
-    int clen = readClassMap(p, be::peek<uint32>(pPasses) - (p - (byte *)pSilf), version);
-    if (clen < 0) {
-        releaseBuffers();
-        return false;
-    }
-    p += clen;
+    const size_t clen = readClassMap(p, passes_start - p, version);
+    if (clen == 0 || p + clen > passes_start)  { releaseBuffers(); return false; }
 
+    m_passes = new Pass[m_numPasses];
     for (size_t i = 0; i < m_numPasses; ++i)
     {
-        uint32 pOffset = be::read<uint32>(pPasses);
-        uint32 pEnd = be::peek<uint32>(pPasses);
-        if ((uint8 *)pSilf + pEnd > eSilf || pOffset > pEnd)
-        {
-            releaseBuffers();
-            return false;
+        const byte * const pass_start = silf_start + be::read<uint32>(o_passes),
+        		   * const pass_end = silf_start + be::peek<uint32>(o_passes);
+        if (pass_start > pass_end || pass_end > silf_end) {
+        	releaseBuffers(); return false;
         }
+
         m_passes[i].init(this);
-        if (!m_passes[i].readPass((char *)pSilf + pOffset, pEnd - pOffset, pOffset, face))
+        if (!m_passes[i].readPass(pass_start, pass_end - pass_start, pass_start - silf_start, face))
         {
         	releaseBuffers();
         	return false;
         }
     }
     return true;
 }
 
@@ -199,54 +173,54 @@ template<typename T> inline uint32 Silf:
 		if (*o > max_off)
 			return 0;
 	}
     return max_off;
 }
 
 size_t Silf::readClassMap(const byte *p, size_t data_len, uint32 version)
 {
-	if (data_len < sizeof(uint16)*2)	return -1;
+	if (data_len < sizeof(uint16)*2)	return 0;
 
 	m_nClass  = be::read<uint16>(p);
 	m_nLinear = be::read<uint16>(p);
 
 	// Check that numLinear < numClass,
 	// that there is at least enough data for numClasses offsets.
 	if (m_nLinear > m_nClass
 	 || (m_nClass + 1) * (version >= 0x00040000 ? sizeof(uint32) : sizeof(uint16))> (data_len - 4))
-		return -1;
+		return 0;
 
     
     uint32 max_off;
     if (version >= 0x00040000)
         max_off = readClassOffsets<uint32>(p, data_len);
     else
         max_off = readClassOffsets<uint16>(p, data_len);
 
-    if (max_off == 0) return -1;
+    if (max_off == 0) return 0;
 
 	// Check the linear offsets are sane, these must be monotonically increasing.
 	for (const uint32 *o = m_classOffsets, * const o_end = o + m_nLinear; o != o_end; ++o)
 		if (o[0] > o[1])
-			return -1;
+			return 0;
 
 	// Fortunately the class data is all uint16s so we can decode these now
     m_classData = gralloc<uint16>(max_off);
     for (uint16 *d = m_classData, * const d_end = d + max_off; d != d_end; ++d)
         *d = be::read<uint16>(p);
 
 	// Check the lookup class invariants for each non-linear class
 	for (const uint32 *o = m_classOffsets + m_nLinear, * const o_end = m_classOffsets + m_nClass; o != o_end; ++o)
 	{
 		const uint16 * lookup = m_classData + *o;
 		if (lookup[0] == 0							// A LookupClass with no looks is a suspicious thing ...
 		 || lookup[0] > (max_off - *o - 4)/2  	    // numIDs lookup pairs fits within (start of LookupClass' lookups array, max_off]
 		 || lookup[3] != lookup[0] - lookup[1])		// rangeShift:	 numIDs  - searchRange
-			return -1;
+			return 0;
 	}
 
 	return max_off;
 }
 
 uint16 Silf::findPseudo(uint32 uid) const
 {
     for (int i = 0; i < m_numPseudo; i++)
@@ -266,17 +240,17 @@ uint16 Silf::findClassIndex(uint16 cid, 
         return -1;
     }
     else
     {
     	const uint16 *	min = cls + 4,		// lookups array
     				 * 	max = min + cls[0]*2; // lookups aray is numIDs (cls[0]) uint16 pairs long
     	do
         {
-        	const uint16 * p = min + (-2U & ((max-min)/2));
+        	const uint16 * p = min + (-2 & ((max-min)/2));
         	if 	(p[0] > gid)	max = p;
         	else 				min = p;
         }
         while (max - min > 2);
         return min[0] == gid ? min[1] : -1;
     }
 }
 
--- a/gfx/graphite2/src/Slot.cpp
+++ b/gfx/graphite2/src/Slot.cpp
@@ -200,17 +200,17 @@ int Slot::getAttr(const Segment *seg, at
     {
         ind = gr_slatUserDefn;
         subindex = 0;
     }
     switch (ind)
     {
     case gr_slatAdvX :		return int(m_advance.x);
     case gr_slatAdvY :		return int(m_advance.y);
-    case gr_slatAttTo :		return 0;
+    case gr_slatAttTo :		return m_parent ? 1 : 0;
     case gr_slatAttX :		return int(m_attach.x);
     case gr_slatAttY :  	return int(m_attach.y);
     case gr_slatAttXOff :
     case gr_slatAttYOff :	return 0;
     case gr_slatAttWithX :  return int(m_with.x);
     case gr_slatAttWithY :  return int(m_with.y);
     case gr_slatAttWithXOff:
     case gr_slatAttWithYOff:return 0;
@@ -224,18 +224,19 @@ int Slot::getAttr(const Segment *seg, at
     case gr_slatShiftX :	return int(m_shift.x);
     case gr_slatShiftY :	return int(m_shift.y);
     case gr_slatMeasureSol:	return -1; // err what's this?
     case gr_slatMeasureEol: return -1;
     case gr_slatJStretch :
     case gr_slatJShrink :
     case gr_slatJStep :
     case gr_slatJWeight :	return 0;
-    case gr_slatJWidth :	return m_just;
+    case gr_slatJWidth :	return int(m_just);
     case gr_slatUserDefn :	return m_userAttr[subindex];
+    case gr_slatSegSplit :  return seg->charinfo(m_original)->flags() & 3;
     default :				return 0;
     }
 }
 
 void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map)
 {
     if (!this) return;
     if (ind == gr_slatUserDefnV1)
@@ -286,16 +287,17 @@ void Slot::setAttr(Segment *seg, attrCod
     case gr_slatShiftY :    m_shift.y = value; break;
     case gr_slatMeasureSol :	break;
     case gr_slatMeasureEol :	break;
     case gr_slatJStretch :      break;  // handle these later
     case gr_slatJShrink :       break;
     case gr_slatJStep :         break;
     case gr_slatJWeight :       break;
     case gr_slatJWidth :	m_just = value; break;
+    case gr_slatSegSplit :  seg->charinfo(m_original)->addflags(value & 3); break;
     case gr_slatUserDefn :  m_userAttr[subindex] = value; break;
     default :
     	break;
     }
 }
 
 bool Slot::child(Slot *ap)
 {
--- a/gfx/graphite2/src/Sparse.cpp
+++ b/gfx/graphite2/src/Sparse.cpp
@@ -45,17 +45,17 @@ namespace
 sparse::~sparse() throw()
 {
 	free(m_array.values);
 }
 
 
 sparse::value sparse::operator [] (int k) const throw()
 {
-	bool g = k < m_nchunks*SIZEOF_CHUNK;	// This will be 0 is were out of bounds
+	value g = value(k < m_nchunks*SIZEOF_CHUNK);	// This will be 0 is were out of bounds
 	k *= g;									// Force k to 0 if out of bounds making the map look up safe
 	const chunk & 		c = m_array.map[k/SIZEOF_CHUNK];
 	const mask_t 		m = c.mask >> (SIZEOF_CHUNK - 1 - (k%SIZEOF_CHUNK));
 	g *= m & 1;			// Extend the guard value to consider the residency bit
 
 	return g*m_array.values[c.offset + g*bit_set_count(m >> 1)];
 }
 
--- a/gfx/graphite2/src/TtfUtil.cpp
+++ b/gfx/graphite2/src/TtfUtil.cpp
@@ -793,17 +793,17 @@ bool HorMetrics(gid16 nGlyphId, const vo
 		reinterpret_cast<const Sfnt::HorizontalMetric *>(pHmtx);
 
 	const Sfnt::HorizontalHeader * phhea = 
 		reinterpret_cast<const Sfnt::HorizontalHeader *>(pHhea);
 
 	size_t cLongHorMetrics = be::swap(phhea->num_long_hor_metrics);
 	if (nGlyphId < cLongHorMetrics) 
 	{	// glyph id is acceptable
-                if (nGlyphId * sizeof(Sfnt::HorizontalMetric) > lHmtxSize) return false;
+		if (nGlyphId * sizeof(Sfnt::HorizontalMetric) >= lHmtxSize) return false;
 		nAdvWid = be::swap(phmtx[nGlyphId].advance_width);
 		nLsb = be::swap(phmtx[nGlyphId].left_side_bearing);
 	}
 	else
 	{
 		// guard against bad glyph id
 		size_t lLsbOffset = sizeof(Sfnt::HorizontalMetric) * cLongHorMetrics +
 			sizeof(int16) * (nGlyphId - cLongHorMetrics); // offset in bytes
@@ -1144,26 +1144,26 @@ size_t LocaLookup(gid16 nGlyphId,
 		const void * pLoca, size_t lLocaSize, 
 		const void * pHead) // throw (std::out_of_range)
 {
 	const Sfnt::FontHeader * pTable = reinterpret_cast<const Sfnt::FontHeader *>(pHead);
 
 	// CheckTable verifies the index_to_loc_format is valid
 	if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::ShortIndexLocFormat)
 	{ // loca entries are two bytes and have been divided by two
-		if (nGlyphId <= (lLocaSize >> 1) - 1) // allow sentinel value to be accessed
+		if (nGlyphId < (lLocaSize >> 1) - 1) // allow sentinel value to be accessed
 		{
 			const uint16 * pShortTable = reinterpret_cast<const uint16 *>(pLoca);
 			return (be::peek<uint16>(pShortTable + nGlyphId) << 1);
 		}
 	}
 	
 	if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::LongIndexLocFormat)
 	{ // loca entries are four bytes
-		if (nGlyphId <= (lLocaSize >> 2) - 1)
+		if (nGlyphId < (lLocaSize >> 2) - 1)
 		{
 			const uint32 * pLongTable = reinterpret_cast<const uint32 *>(pLoca);
 			return be::peek<uint32>(pLongTable + nGlyphId);
 		}
 	}
 
 	// only get here if glyph id was bad
 	return -1;
--- a/gfx/graphite2/src/call_machine.cpp
+++ b/gfx/graphite2/src/call_machine.cpp
@@ -99,17 +99,17 @@ namespace {
 }
 
 Machine::stack_t  Machine::run(const instr   * program,
                                const byte    * data,
                                slotref     * & map)
 
 {
     assert(program != 0);
-    assert(_status == finished);
+//    assert(_status == finished);
 
 
     // Declare virtual machine registers
     const instr   * ip = program-1;
     const byte    * dp = data;
     stack_t       * sp = _stack + Machine::STACK_GUARD,
             * const sb = sp;
     regbank         reg = {*map, map, _map, _map.begin()+_map.context(), ip, 0};
--- a/gfx/graphite2/src/direct_machine.cpp
+++ b/gfx/graphite2/src/direct_machine.cpp
@@ -102,17 +102,17 @@ const opcode_t * Machine::getOpcodeTable
 }
 
 
 Machine::stack_t  Machine::run(const instr   * program,
                                const byte    * data,
                                slotref     * & is)
 {
     assert(program != 0);
-    assert(_status == finished);
+//    assert(_status == finished);
     
     const stack_t *sp = static_cast<const stack_t *>(
                 direct_run(false, program, data, _stack, is, &_map));
     const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0;
     check_final_stack(sp);
     return ret;
 }
 
--- a/gfx/graphite2/src/gr_face.cpp
+++ b/gfx/graphite2/src/gr_face.cpp
@@ -116,31 +116,33 @@ void gr_tag_to_str(gr_uint32 tag, char *
     int i = 4;
     while (--i >= 0)
     {
         str[i] = tag & 0xFF;
         tag >>= 8;
     }
 }
         
+#define zeropad(x) if (x == 0x20202020) x = 0;                             \
+    else if ((x & 0x00FFFFFF) == 0x00202020) x = x & 0xFF000000;   \
+    else if ((x & 0x0000FFFF) == 0x00002020) x = x & 0xFFFF0000;   \
+    else if ((x & 0x000000FF) == 0x00000020) x = x & 0xFFFFFF00;
 
 gr_feature_val* gr_face_featureval_for_lang(const gr_face* pFace, gr_uint32 langname/*0 means clone default*/) //clones the features. if none for language, clones the default
 {
     assert(pFace);
-    if (langname == 0x20202020) langname = 0;
-    else if ((langname & 0x00FFFFFF) == 0x00202020) langname = langname & 0xFF000000;
-    else if ((langname & 0x0000FFFF) == 0x00002020) langname = langname & 0xFFFF0000;
-    else if ((langname & 0x000000FF) == 0x00000020) langname = langname & 0xFFFFFF00;
+    zeropad(langname)
     return static_cast<gr_feature_val *>(pFace->theSill().cloneFeatures(langname));
 }
 
 
 const gr_feature_ref* gr_face_find_fref(const gr_face* pFace, gr_uint32 featId)  //When finished with the FeatureRef, call destroy_FeatureRef
 {
     assert(pFace);
+    zeropad(featId)
     const FeatureRef* pRef = pFace->featureById(featId);
     return static_cast<const gr_feature_ref*>(pRef);
 }
 
 unsigned short gr_face_n_fref(const gr_face* pFace)
 {
     assert(pFace);
     return pFace->numFeatures();
--- a/gfx/graphite2/src/gr_logging.cpp
+++ b/gfx/graphite2/src/gr_logging.cpp
@@ -36,17 +36,17 @@ extern "C" {
 
 
 bool graphite_start_logging(FILE * logFile, GrLogMask mask)
 {
 	if (!logFile || !mask)	return false;
 
 #if !defined GRAPHITE2_NTRACING
 	dbgout = new json(logFile);
-	return dbgout;
+	return dbgout != 0;
 #else
 	return false;
 #endif
 }
 
 void graphite_stop_logging()
 {
 #if !defined GRAPHITE2_NTRACING
@@ -63,16 +63,17 @@ json *graphite2::dbgout = 0;
 
 
 json & graphite2::operator << (json & j, const CharInfo & ci) throw()
 {
 	return j << json::object
 				<< "offset"			<< ci.base()
 				<< "unicode"		<< ci.unicodeChar()
 				<< "break"			<< ci.breakWeight()
+				<< "flags"          << ci.flags()
 				<< "slot" << json::flat << json::object
 					<< "before"	<< ci.before()
 					<< "after"	<< ci.after()
 					<< json::close
 				<< json::close;
 }
 
 
@@ -87,17 +88,18 @@ json & graphite2::operator << (json & j,
 		<< "id"				<< slotid(&s)
 		<< "gid"			<< s.gid()
 		<< "charinfo" << json::flat << json::object
 			<< "original"		<< s.original()
 			<< "before"			<< s.before()
 			<< "after" 			<< s.after()
 			<< json::close
 		<< "origin"			<< s.origin()
-		<< "shift"			<< Position(s.getAttr(0, gr_slatShiftX, 0), s.getAttr(0, gr_slatShiftY, 0))
+		<< "shift"			<< Position(float(s.getAttr(0, gr_slatShiftX, 0)),
+										float(s.getAttr(0, gr_slatShiftY, 0)))
 		<< "advance"		<< s.advancePos()
 		<< "insert"			<< s.isInsertBefore()
 		<< "break"			<< s.getAttr(&seg, gr_slatBreak, 0);
 	if (s.just() > 0)
 		j << "justification"	<< s.just();
 	if (s.getBidiLevel() > 0)
 		j << "bidi"		<< s.getBidiLevel();
 	if (!s.isBase())
--- a/gfx/graphite2/src/gr_segment.cpp
+++ b/gfx/graphite2/src/gr_segment.cpp
@@ -163,12 +163,12 @@ const gr_slot* gr_seg_last_slot(gr_segme
     assert(pSeg);
     return static_cast<const gr_slot*>(pSeg->last());
 }
 
 void gr_seg_justify(gr_segment* pSeg/*not NULL*/, gr_slot* pSlot/*not NULL*/, const gr_font *pFont, double width, enum gr_justFlags flags, gr_slot *pFirst, gr_slot *pLast)
 {
     assert(pSeg);
     assert(pSlot);
-    pSeg->justify(pSlot, pFont, width, justFlags(flags), pFirst, pLast);
+    pSeg->justify(pSlot, pFont, float(width), justFlags(flags), pFirst, pLast);
 }
 
 } // extern "C"
--- a/gfx/graphite2/src/inc/CachedFace.h
+++ b/gfx/graphite2/src/inc/CachedFace.h
@@ -28,16 +28,17 @@ of the License or (at your option) any l
 
 #ifndef GRAPHITE2_NSEGCACHE
 
 #include "inc/Face.h"
 
 namespace graphite2 {
 
 class SegCacheStore;
+class SegCache;
 
 class CachedFace : public Face
 {
 public:
     CachedFace(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn getTable2);
     bool setupCache(unsigned int cacheSize);
     virtual ~CachedFace();
     virtual bool runGraphite(Segment *seg, const Silf *silf) const;
--- a/gfx/graphite2/src/inc/CharInfo.h
+++ b/gfx/graphite2/src/inc/CharInfo.h
@@ -29,36 +29,39 @@ of the License or (at your option) any l