Bug 786666 - workaround __exposedProps__ typed array issue in mozTCPSocket. r=fabrice
authorAndrew Sutherland <asutherland@asutherland.org>
Wed, 29 Aug 2012 12:47:24 -0300
changeset 103789 b739aa9d9ede6bd90794eabdacdb46fca8a011fd
parent 103788 c05251c5a7e3e96d7cd507e27db09f802a1f8a53
child 103790 58b937c070d67cde0e3e3da19264f8ea018d0b42
push id23376
push userryanvm@gmail.com
push dateThu, 30 Aug 2012 00:15:25 +0000
treeherdermozilla-central@706174d31a02 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice
bugs786666
milestone18.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
Bug 786666 - workaround __exposedProps__ typed array issue in mozTCPSocket. r=fabrice
dom/network/src/TCPSocket.js
--- a/dom/network/src/TCPSocket.js
+++ b/dom/network/src/TCPSocket.js
@@ -83,16 +83,25 @@ function TCPSocket() {
   this._onerror = null;
   this._onclose = null;
 
   this._binaryType = "string";
 
   this._host = "";
   this._port = 0;
   this._ssl = false;
+
+  // As a workaround for bug https://bugzilla.mozilla.org/show_bug.cgi?id=786639
+  // we want to create any Uint8Array's off of the owning window so that there
+  // is no need for a wrapper to exist around the typed array from the
+  // perspective of content.  (The wrapper is bad because it only lets content
+  // see length, and forbids access to the array indices unless we excplicitly
+  // list them all.)  We will then access the array through a wrapper, but
+  // since we are chrome-privileged, this does not pose a problem.
+  this.useWin = null;
 }
 
 TCPSocket.prototype = {
   __exposedProps__: {
     open: 'r',
     host: 'r',
     port: 'r',
     ssl: 'r',
@@ -267,16 +276,17 @@ TCPSocket.prototype = {
                  : Services.perms.testExactPermissionFromPrincipal(principal, "tcp-socket");
 
     this._hasPrivileges = perm == Ci.nsIPermissionManager.ALLOW_ACTION;
 
     let util = aWindow.QueryInterface(
       Ci.nsIInterfaceRequestor
     ).getInterface(Ci.nsIDOMWindowUtils);
 
+    this.useWin = XPCNativeWrapper.unwrap(aWindow);
     this.innerWindowID = util.currentInnerWindowID;
     LOG("window init: " + this.innerWindowID);
   },
 
   observe: function(aSubject, aTopic, aData) {
     if (aTopic == "inner-window-destroyed") {
       let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
       if (wId == this.innerWindowID) {
@@ -286,31 +296,34 @@ TCPSocket.prototype = {
         // so that we don't get a "can't access dead object" when the
         // underlying stream goes to tell us that we are closed
         this.onopen = null;
         this.ondrain = null;
         this.ondata = null;
         this.onerror = null;
         this.onclose = null;
 
+        this.useWin = null;
+
         // Clean up our socket
         this.close();
       }
     }
   },
 
   // nsIDOMTCPSocket
   open: function ts_open(host, port, options) {
     // in the testing case, init won't be called and
     // hasPrivileges will be null. We want to proceed to test.
     if (this._hasPrivileges !== true && this._hasPrivileges !== null) {
       throw new Error("TCPSocket does not have permission in this context.\n");
     }
     let that = new TCPSocket();
 
+    that.useWin = this.useWin;
     that.innerWindowID = this.innerWindowID;
 
     LOG("window init: " + that.innerWindowID);
     Services.obs.addObserver(that, "inner-window-destroyed", true);
 
     LOG("startup called\n");
     LOG("Host info: " + host + ":" + port + "\n");
 
@@ -471,17 +484,17 @@ TCPSocket.prototype = {
   // nsIRequestObserver (Triggered by _inputStreamPump.asyncRead)
   onStopRequest: function ts_onStopRequest(request, context, status) {
     let buffered_output = this._multiplexStream.count !== 0;
 
     this._inputStreamPump = null;
 
     if (buffered_output && !status) {
       // If we have some buffered output still, and status is not an
-      // error, the other side has done a half-close, but we don't 
+      // error, the other side has done a half-close, but we don't
       // want to be in the close state until we are done sending
       // everything that was buffered. We also don't want to call onclose
       // yet.
       return;
     }
 
     this._readyState = kCLOSED;
 
@@ -492,17 +505,18 @@ TCPSocket.prototype = {
     }
 
     this.callListener("onclose");
   },
 
   // nsIStreamListener (Triggered by _inputStreamPump.asyncRead)
   onDataAvailable: function ts_onDataAvailable(request, context, inputStream, offset, count) {
     if (this._binaryType === "arraybuffer") {
-      let ua = new Uint8Array(count);
+      let ua = this.useWin ? new this.useWin.Uint8Array(count)
+                           : new Uint8Array(count);
       ua.set(this._inputStreamBinary.readByteArray(count));
       this.callListener("ondata", ua);
     } else {
       this.callListener("ondata", this._inputStreamScriptable.read(count));
     }
   },
 
   classID: Components.ID("{cda91b22-6472-11e1-aa11-834fec09cd0a}"),