diff options
Diffstat (limited to 'netwerk/test/browser/browser_nsIFormPOSTActionChannel.js')
-rw-r--r-- | netwerk/test/browser/browser_nsIFormPOSTActionChannel.js | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/netwerk/test/browser/browser_nsIFormPOSTActionChannel.js b/netwerk/test/browser/browser_nsIFormPOSTActionChannel.js new file mode 100644 index 000000000..150c4feca --- /dev/null +++ b/netwerk/test/browser/browser_nsIFormPOSTActionChannel.js @@ -0,0 +1,284 @@ +/* + * Tests for bug 1241377: A channel with nsIFormPOSTActionChannel interface + * should be able to accept form POST. + */ + +Components.utils.import("resource://gre/modules/Services.jsm"); +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Task.jsm"); + +const SCHEME = "x-bug1241377"; + +const FORM_BASE = SCHEME + "://dummy/form/"; +const NORMAL_FORM_URI = FORM_BASE + "normal.html"; +const UPLOAD_FORM_URI = FORM_BASE + "upload.html"; +const POST_FORM_URI = FORM_BASE + "post.html"; + +const ACTION_BASE = SCHEME + "://dummy/action/"; +const NORMAL_ACTION_URI = ACTION_BASE + "normal.html"; +const UPLOAD_ACTION_URI = ACTION_BASE + "upload.html"; +const POST_ACTION_URI = ACTION_BASE + "post.html"; + +function CustomProtocolHandler() { +} +CustomProtocolHandler.prototype = { + /** nsIProtocolHandler */ + get scheme() { + return SCHEME; + }, + get defaultPort() { + return -1; + }, + get protocolFlags() { + return Ci.nsIProtocolHandler.URI_NORELATIVE | + Ci.nsIProtocolHandler.URI_IS_LOCAL_RESOURCE; + }, + newURI: function(aSpec, aOriginCharset, aBaseURI) { + var uri = Cc["@mozilla.org/network/standard-url;1"]. + createInstance(Ci.nsIURI); + uri.spec = aSpec; + return uri; + }, + newChannel2: function(aURI, aLoadInfo) { + return new CustomChannel(aURI, aLoadInfo); + }, + newChannel: function(aURI) { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + allowPort: function(port, scheme) { + return port != -1; + }, + + /** nsIFactory */ + createInstance: function(aOuter, aIID) { + if (aOuter) { + throw Cr.NS_ERROR_NO_AGGREGATION; + } + return this.QueryInterface(aIID); + }, + lockFactory: function() {}, + + /** nsISupports */ + QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler, + Ci.nsIFactory]), + classID: Components.ID("{16d594bc-d9d8-47ae-a139-ea714dc0c35c}") +}; + +function CustomChannel(aURI, aLoadInfo) { + this.uri = aURI; + this.loadInfo = aLoadInfo; + + this._uploadStream = null; + + var interfaces = [Ci.nsIRequest, Ci.nsIChannel]; + if (this.uri.spec == POST_ACTION_URI) { + interfaces.push(Ci.nsIFormPOSTActionChannel); + } else if (this.uri.spec == UPLOAD_ACTION_URI) { + interfaces.push(Ci.nsIUploadChannel); + } + this.QueryInterface = XPCOMUtils.generateQI(interfaces); +} +CustomChannel.prototype = { + /** nsIUploadChannel */ + get uploadStream() { + return this._uploadStream; + }, + set uploadStream(val) { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + setUploadStream: function(aStream, aContentType, aContentLength) { + this._uploadStream = aStream; + }, + + /** nsIChannel */ + get originalURI() { + return this.uri; + }, + get URI() { + return this.uri; + }, + owner: null, + notificationCallbacks: null, + get securityInfo() { + return null; + }, + get contentType() { + return "text/html"; + }, + set contentType(val) { + }, + contentCharset: "UTF-8", + get contentLength() { + return -1; + }, + set contentLength(val) { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + open: function() { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + open2: function() { + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + }, + asyncOpen: function(aListener, aContext) { + var data = ` +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>test bug 1241377</title> +</head> +<body> +`; + + if (this.uri.spec.startsWith(FORM_BASE)) { + data += ` +<form id="form" action="${this.uri.spec.replace(FORM_BASE, ACTION_BASE)}" + method="post" enctype="text/plain" target="frame"> +<input type="hidden" name="foo" value="bar"> +<input type="submit"> +</form> + +<iframe id="frame" name="frame" width="200" height="200"></iframe> + +<script type="text/javascript"> +<!-- +document.getElementById('form').submit(); +//--> +</script> +`; + } else if (this.uri.spec.startsWith(ACTION_BASE)) { + var postData = ""; + if (this._uploadStream) { + var bstream = Cc["@mozilla.org/binaryinputstream;1"] + .createInstance(Ci.nsIBinaryInputStream); + bstream.setInputStream(this._uploadStream); + postData = bstream.readBytes(bstream.available()); + } + data += ` +<input id="upload_stream" value="${this._uploadStream ? "yes" : "no"}"> +<input id="post_data" value="${btoa(postData)}"> +`; + } + + data += ` +</body> +</html> +`; + + var stream = Cc["@mozilla.org/io/string-input-stream;1"] + .createInstance(Ci.nsIStringInputStream); + stream.setData(data, data.length); + + var runnable = { + run: () => { + try { + aListener.onStartRequest(this, aContext); + } catch(e) {} + try { + aListener.onDataAvailable(this, aContext, stream, 0, stream.available()); + } catch(e) {} + try { + aListener.onStopRequest(this, aContext, Cr.NS_OK); + } catch(e) {} + } + }; + Services.tm.currentThread.dispatch(runnable, Ci.nsIEventTarget.DISPATCH_NORMAL); + }, + asyncOpen2: function(aListener) { + this.asyncOpen(aListener, null); + }, + + /** nsIRequest */ + get name() { + return this.uri.spec; + }, + isPending: function () { + return false; + }, + get status() { + return Cr.NS_OK; + }, + cancel: function(status) {}, + loadGroup: null, + loadFlags: Ci.nsIRequest.LOAD_NORMAL | + Ci.nsIRequest.INHIBIT_CACHING | + Ci.nsIRequest.LOAD_BYPASS_CACHE, +}; + +function frameScript() { + addMessageListener("Test:WaitForIFrame", function() { + var check = function() { + if (content) { + var frame = content.document.getElementById("frame"); + if (frame) { + var upload_stream = frame.contentDocument.getElementById("upload_stream"); + var post_data = frame.contentDocument.getElementById("post_data"); + if (upload_stream && post_data) { + sendAsyncMessage("Test:IFrameLoaded", [upload_stream.value, post_data.value]); + return; + } + } + } + + setTimeout(check, 100); + }; + + check(); + }); +} + +function loadTestTab(uri) { + gBrowser.selectedTab = gBrowser.addTab(uri); + var browser = gBrowser.selectedBrowser; + + let manager = browser.messageManager; + browser.messageManager.loadFrameScript("data:,(" + frameScript.toString() + ")();", true); + + return new Promise(resolve => { + function listener({ data: [hasUploadStream, postData] }) { + manager.removeMessageListener("Test:IFrameLoaded", listener); + resolve([hasUploadStream, atob(postData)]); + } + + manager.addMessageListener("Test:IFrameLoaded", listener); + manager.sendAsyncMessage("Test:WaitForIFrame"); + }); +} + +add_task(function*() { + var handler = new CustomProtocolHandler(); + var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar); + registrar.registerFactory(handler.classID, "", + "@mozilla.org/network/protocol;1?name=" + handler.scheme, + handler); + registerCleanupFunction(function() { + registrar.unregisterFactory(handler.classID, handler); + }); +}); + +add_task(function*() { + var [hasUploadStream, postData] = yield loadTestTab(NORMAL_FORM_URI); + is(hasUploadStream, "no", "normal action should not have uploadStream"); + + gBrowser.removeCurrentTab(); +}); + +add_task(function*() { + var [hasUploadStream, postData] = yield loadTestTab(UPLOAD_FORM_URI); + is(hasUploadStream, "no", "upload action should not have uploadStream"); + + gBrowser.removeCurrentTab(); +}); + +add_task(function*() { + var [hasUploadStream, postData] = yield loadTestTab(POST_FORM_URI); + is(hasUploadStream, "yes", "post action should have uploadStream"); + is(postData, + "Content-Type: text/plain\r\n" + + "Content-Length: 9\r\n" + + "\r\n" + + "foo=bar\r\n", "POST data is received correctly"); + + gBrowser.removeCurrentTab(); +}); |