Merge last PGO-green changeset of mozilla-inbound to mozilla-central a=merge
authorEd Morley <emorley@mozilla.com>
Tue, 24 Apr 2012 11:14:56 +0100
changeset 95505 1b2dbf32886bba885d4fde24fe1fff5079bf9ed2
parent 95463 f946709d44e13cffb4af0a39353930c499bae8d0 (current diff)
parent 95504 c9228e7f3ef7794632283ba062697a454f3d10d3 (diff)
child 95506 270848da27e44971abe90b5ad1f2a7562fdae479
child 95514 2f5d290dc23414758ae3f746153b986411c3c68f
child 96320 6e4a298defe37fc955c1feaa507806f489394208
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last PGO-green changeset of mozilla-inbound to mozilla-central a=merge
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -8033,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();
@@ -8349,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/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/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…">
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/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -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,
--- 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/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/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/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -5,17 +5,17 @@
       android:installLocation="auto"
       android:versionCode="@ANDROID_VERSION_CODE@"
       android:versionName="@MOZ_APP_VERSION@"
 #ifdef MOZ_ANDROID_SHARED_ID
       android:sharedUserId="@MOZ_ANDROID_SHARED_ID@"
 #endif
       >
     <uses-sdk android:minSdkVersion="8"
-              android:targetSdkVersion="14"/>
+              android:targetSdkVersion="11"/>
 
 #include ../sync/manifests/SyncAndroidManifest_permissions.xml.in
 
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
     <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
--- a/mobile/android/base/GeckoApp.java
+++ b/mobile/android/base/GeckoApp.java
@@ -625,51 +625,44 @@ abstract public class GeckoApp
                 Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.FAVICON);
             }
         });
 
         tab.setFaviconLoadId(id);
     }
 
     void handleLocationChange(final int tabId, final String uri,
-                              final String documentURI, final String contentType) {
+                              final String documentURI, final String contentType,
+                              final boolean sameDocument) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
         if (Tabs.getInstance().isSelectedTab(tab)) {
             if (uri.equals("about:home"))
                 showAboutHome();
             else 
                 hideAboutHome();
         }
         
-        String oldBaseURI = tab.getURL();
         tab.updateURL(uri);
         tab.setDocumentURI(documentURI);
-        tab.setContentType(contentType);
-
-        String baseURI = uri;
-        if (baseURI.indexOf('#') != -1)
-            baseURI = uri.substring(0, uri.indexOf('#'));
-
-        if (oldBaseURI != null && oldBaseURI.indexOf('#') != -1)
-            oldBaseURI = oldBaseURI.substring(0, oldBaseURI.indexOf('#'));
-        
-        if (baseURI.equals(oldBaseURI)) {
+
+        if (sameDocument) {
             mMainHandler.post(new Runnable() {
                 public void run() {
                     if (Tabs.getInstance().isSelectedTab(tab)) {
                         mBrowserToolbar.setTitle(uri);
                     }
                 }
             });
             return;
         }
 
+        tab.setContentType(contentType);
         tab.updateFavicon(null);
         tab.updateFaviconURL(null);
         tab.updateSecurityMode("unknown");
         tab.removeTransientDoorHangers();
         tab.setHasTouchListeners(false);
         tab.setCheckerboardColor(Color.WHITE);
 
         maybeCancelFaviconLoad(tab);
@@ -863,33 +856,35 @@ abstract public class GeckoApp
                 // generic log listener
                 final String msg = message.getString("msg");
                 Log.i(LOGTAG, "Log: " + msg);
             } else if (event.equals("Content:LocationChange")) {
                 final int tabId = message.getInt("tabID");
                 final String uri = message.getString("uri");
                 final String documentURI = message.getString("documentURI");
                 final String contentType = message.getString("contentType");
+                final boolean sameDocument = message.getBoolean("sameDocument");
                 Log.i(LOGTAG, "URI - " + uri);
-                handleLocationChange(tabId, uri, documentURI, contentType);
+                handleLocationChange(tabId, uri, documentURI, contentType, sameDocument);
             } else if (event.equals("Content:SecurityChange")) {
                 final int tabId = message.getInt("tabID");
                 final String mode = message.getString("mode");
                 Log.i(LOGTAG, "Security Mode - " + mode);
                 handleSecurityChange(tabId, mode);
             } else if (event.equals("Content:StateChange")) {
                 final int tabId = message.getInt("tabID");
+                final String uri = message.getString("uri");
                 final boolean success = message.getBoolean("success");
                 int state = message.getInt("state");
                 Log.i(LOGTAG, "State - " + state);
                 if ((state & GeckoAppShell.WPL_STATE_IS_NETWORK) != 0) {
                     if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
                         Log.i(LOGTAG, "Got a document start");
                         final boolean showProgress = message.getBoolean("showProgress");
-                        handleDocumentStart(tabId, showProgress);
+                        handleDocumentStart(tabId, showProgress, uri);
                     } else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
                         Log.i(LOGTAG, "Got a document stop");
                         handleDocumentStop(tabId, success);
                     }
                 }
             } else if (event.equals("Content:LoadError")) {
                 final int tabId = message.getInt("tabID");
                 final String uri = message.getString("uri");
@@ -1185,29 +1180,30 @@ abstract public class GeckoApp
                 if (tab == null)
                     return;
                 tab.removeDoorHanger(value);
                 mDoorHangerPopup.updatePopup();
             }
         });
     }
 
-    void handleDocumentStart(int tabId, final boolean showProgress) {
+    void handleDocumentStart(int tabId, final boolean showProgress, String uri) {
         final Tab tab = Tabs.getInstance().getTab(tabId);
         if (tab == null)
             return;
 
+        tab.updateURL(uri);
         tab.setState(Tab.STATE_LOADING);
         tab.updateSecurityMode("unknown");
 
         mMainHandler.post(new Runnable() {
             public void run() {
                 if (Tabs.getInstance().isSelectedTab(tab)) {
                     mBrowserToolbar.setSecurityMode(tab.getSecurityMode());
-                    if (showProgress)
+                    if (showProgress && tab.getState() == Tab.STATE_LOADING)
                         mBrowserToolbar.setProgressVisibility(true);
                 }
                 Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START);
             }
         });
     }
 
     void handleDocumentStop(int tabId, boolean success) {
@@ -2158,28 +2154,30 @@ abstract public class GeckoApp
         super.onLowMemory();
     }
 
     @Override
     public void onApplicationPause() {
         Log.i(LOGTAG, "application paused");
         GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true));
 
-        mConnectivityReceiver.unregisterFor(mAppContext);
+        if (mConnectivityReceiver != null)
+            mConnectivityReceiver.unregisterFor(mAppContext);
         GeckoNetworkManager.getInstance().stop();
         GeckoScreenOrientationListener.getInstance().stop();
     }
 
     @Override
     public void onApplicationResume() {
         Log.i(LOGTAG, "application resumed");
         if (checkLaunchState(LaunchState.GeckoRunning))
             GeckoAppShell.sendEventToGecko(GeckoEvent.createResumeEvent(true));
 
-        mConnectivityReceiver.registerFor(mAppContext);
+        if (mConnectivityReceiver != null)
+            mConnectivityReceiver.registerFor(mAppContext);
         GeckoNetworkManager.getInstance().start();
         GeckoScreenOrientationListener.getInstance().start();
     }
 
     abstract public String getPackageName();
     abstract public String getContentProcessName();
 
     public void addEnvToIntent(Intent intent) {
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -2079,38 +2079,40 @@ Tab.prototype = {
     let contentWin = aWebProgress.DOMWindow;
     if (contentWin != contentWin.top)
         return;
 
     let browser = BrowserApp.getBrowserForWindow(contentWin);
     let uri = browser.currentURI.spec;
     let documentURI = "";
     let contentType = "";
+    let sameDocument = (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) != 0;
     if (browser.contentDocument) {
       documentURI = browser.contentDocument.documentURIObject.spec;
       contentType = browser.contentDocument.contentType;
     }
 
     // Reset state of click-to-play plugin notifications.
     this.clickToPlayPluginDoorhangerShown = false;
     this.clickToPlayPluginsActivated = false;
 
     let message = {
       gecko: {
         type: "Content:LocationChange",
         tabID: this.id,
         uri: uri,
         documentURI: documentURI,
-        contentType: contentType
+        contentType: contentType,
+        sameDocument: sameDocument
       }
     };
 
     sendMessageToJava(message);
 
-    if ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) == 0) {
+    if (!sameDocument) {
       // XXX This code assumes that this is the earliest hook we have at which
       // browser.contentDocument is changed to the new document we're loading
       this.contentDocumentIsDisplayed = false;
     } else {
       this.sendViewportUpdate();
     }
   },
 
--- a/toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js
+++ b/toolkit/components/search/tests/xpcshell/test_nodb_pluschanges.js
@@ -18,59 +18,68 @@
  * to ensure that this test is independent from locale, commercial agreements
  * and configuration of Firefox.
  */
 
 do_load_httpd_js();
 
 function run_test()
 {
+  do_print("Preparing test");
   removeMetadata();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2");
   do_load_manifest("data/chrome.manifest");
 
   let httpServer = new nsHttpServer();
   httpServer.start(4444);
   httpServer.registerDirectory("/", do_get_cwd());
 
   let search = Services.search;
 
+  do_print("Setting up observer");
   function observer(aSubject, aTopic, aData) {
+    do_print("Observing topic " + aTopic);
     if ("engine-added" == aData) {
       let engine1 = search.getEngineByName("Test search engine");
       let engine2 = search.getEngineByName("Sherlock test search engine");
-      dumpn("Got engine 2: "+engine2);
+      do_print("Currently, engine1 is " + engine1);
+      do_print("Currently, engine2 is " + engine2);
       if(engine1 && engine2)
       {
         search.moveEngine(engine1, 0);
         search.moveEngine(engine2, 1);
+        do_print("Next step is forcing flush");
         do_timeout(0,
                    function() {
+                     do_print("Forcing flush");
                      // Force flush
                      // Note: the timeout is needed, to avoid some reentrency
                      // issues in nsSearchService.
                      search.QueryInterface(Ci.nsIObserver).
                        observe(observer, "quit-application", "<no verb>");
                    });
         afterCommit(
           function()
           {
+            do_print("Commit complete");
             // Check that search-metadata.json has been created
             let metadata = gProfD.clone();
             metadata.append("search-metadata.json");
             do_check_true(metadata.exists());
 
             // Check that the entries are placed as specified correctly
-	    let stream = NetUtil.newChannel(metadata).open();
+            let stream = NetUtil.newChannel(metadata).open();
             let json = parseJsonFromStream(stream);
             do_check_eq(json["[app]/test-search-engine.xml"].order, 1);
             do_check_eq(json["[profile]/sherlock-test-search-engine.xml"].order, 2);
-	    httpServer.stop(function() {});
-	    stream.close(); // Stream must be closed under Windows
-	    removeMetadata();
+
+            do_print("Cleaning up");
+            httpServer.stop(function() {});
+            stream.close(); // Stream must be closed under Windows
+            removeMetadata();
             do_test_finished();
           }
         );
       }
     }
   };
   Services.obs.addObserver(observer, "browser-search-engine-modified",
                            false);
@@ -79,9 +88,13 @@ function run_test()
 
   search.addEngine("http://localhost:4444/data/engine.xml",
                    Ci.nsISearchEngine.DATA_XML,
                    null, false);
   search.addEngine("http://localhost:4444/data/engine.src",
                    Ci.nsISearchEngine.DATA_TEXT,
                    "http://localhost:4444/data/ico-size-16x16-png.ico",
                    false);
+
+  do_timeout(120000, function() {
+    do_throw("Timeout");
+  });
 }
--- a/webapprt/win/webapprt.cpp
+++ b/webapprt/win/webapprt.cpp
@@ -282,16 +282,17 @@ namespace {
         return false;
       }
 
       ScopedXREAppData webShellAppData;
       rv = webShellAppData.create(rtINI);
       NS_ENSURE_SUCCESS(rv, rv);
 
       SetAllocatedString(webShellAppData->profile, profile);
+      SetAllocatedString(webShellAppData->name, profile);
 
       nsCOMPtr<nsILocalFile> directory;
       rv = XRE_GetFileFromPath(rtPath, getter_AddRefs(directory));
       NS_ENSURE_SUCCESS(rv, false);
 
       nsCOMPtr<nsILocalFile> xreDir;
       rv = XRE_GetFileFromPath(greDir, getter_AddRefs(xreDir));
       NS_ENSURE_SUCCESS(rv, false);
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -516,16 +516,17 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jo
         case ACTIVITY_RESUMING: {
             mFlags = jenv->GetIntField(jobj, jFlagsField);
             break;
         }
 
         case SCREENSHOT: {
             mMetaState = jenv->GetIntField(jobj, jMetaStateField);
             ReadPointArray(mPoints, jenv, jPoints, 2);
+            break;
         }
 
         case SCREENORIENTATION_CHANGED: {
             mScreenOrientation = jenv->GetShortField(jobj, jScreenOrientationField);
             break;
         }
 
         default:
@@ -697,18 +698,18 @@ AndroidGeckoLayerClient::SyncViewportInf
 
     jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncViewportInfoMethod,
                                                       aDisplayPort.x, aDisplayPort.y,
                                                       aDisplayPort.width, aDisplayPort.height,
                                                       aDisplayResolution, aLayersUpdated);
     NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
     viewTransform.Init(viewTransformJObj);
 
-    aScrollOffset = nsIntPoint(viewTransform.GetX(), viewTransform.GetY());
-    aScaleX = aScaleY = viewTransform.GetScale();
+    aScrollOffset = nsIntPoint(viewTransform.GetX(env), viewTransform.GetY(env));
+    aScaleX = aScaleY = viewTransform.GetScale(env);
 }
 
 jobject
 AndroidGeckoSurfaceView::GetSoftwareDrawBitmap()
 {
     JNIEnv *env = AndroidBridge::GetJNIEnv();
     if (!env)
         return nsnull;
@@ -824,37 +825,34 @@ AndroidLayerRendererFrame::EndDrawing()
     if (!env) {
         return;
     }
 
     env->CallVoidMethod(wrapped_obj, jEndDrawingMethod);
 }
 
 float
-AndroidViewTransform::GetX()
+AndroidViewTransform::GetX(JNIEnv *env)
 {
-    JNIEnv *env = GetJNIForThread();
     if (!env)
         return 0.0f;
     return env->GetFloatField(wrapped_obj, jXField);
 }
 
 float
-AndroidViewTransform::GetY()
+AndroidViewTransform::GetY(JNIEnv *env)
 {
-    JNIEnv *env = GetJNIForThread();
     if (!env)
         return 0.0f;
     return env->GetFloatField(wrapped_obj, jYField);
 }
 
 float
-AndroidViewTransform::GetScale()
+AndroidViewTransform::GetScale(JNIEnv *env)
 {
-    JNIEnv *env = GetJNIForThread();
     if (!env)
         return 0.0f;
     return env->GetFloatField(wrapped_obj, jScaleField);
 }
 
 void
 AndroidRect::Init(JNIEnv *jenv, jobject jobj)
 {
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -157,19 +157,19 @@ class AndroidViewTransform : public Wrap
 public:
     static void InitViewTransformClass(JNIEnv *jEnv);
 
     void Init(jobject jobj);
 
     AndroidViewTransform() {}
     AndroidViewTransform(jobject jobj) { Init(jobj); }
 
-    float GetX();
-    float GetY();
-    float GetScale();
+    float GetX(JNIEnv *env);
+    float GetY(JNIEnv *env);
+    float GetScale(JNIEnv *env);
 
 private:
     static jclass jViewTransformClass;
     static jfieldID jXField;
     static jfieldID jYField;
     static jfieldID jScaleField;
 };