forked from mirrors/gecko-dev
		
	 a259026c9d
			
		
	
	
		a259026c9d
		
	
	
	
	
		
			
			This also removes any redundant Ci.nsISupports elements in the interface
lists.
This was done using the following script:
acecb401b7/processors/chromeutils-generateQI.jsm
MozReview-Commit-ID: AIx10P8GpZY
--HG--
extra : rebase_source : a29c07530586dc18ba040f19215475ac20fcfb3b
		
	
			
		
			
				
	
	
		
			260 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			260 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| 
 | |
| ChromeUtils.import("resource://testing-common/httpd.js");
 | |
| ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
 | |
| ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 | |
| ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
 | |
| 
 | |
| XPCOMUtils.defineLazyGetter(this, "URL", function() {
 | |
|   return "http://localhost:" + httpServer.identity.primaryPort;
 | |
| });
 | |
| 
 | |
| var httpServer = null;
 | |
| 
 | |
| function make_uri(url) {
 | |
|   var ios = Cc["@mozilla.org/network/io-service;1"].
 | |
|             getService(Ci.nsIIOService);
 | |
|   return ios.newURI(url);
 | |
| }
 | |
| 
 | |
| function isParentProcess() {
 | |
|     let appInfo = Cc["@mozilla.org/xre/app-info;1"];
 | |
|     return (!appInfo || appInfo.getService(Ci.nsIXULRuntime).processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT);
 | |
| }
 | |
| 
 | |
| if (isParentProcess()) {
 | |
|   // ensure the cache service is prepped when running the test
 | |
|   // We only do this in the main process, as the cache storage service leaks
 | |
|   // when instantiated in the content process.
 | |
|   Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
 | |
| }
 | |
| 
 | |
| var gotOnProgress;
 | |
| var gotOnStatus;
 | |
| 
 | |
| function make_channel(url, body, cb) {
 | |
|   gotOnProgress = false;
 | |
|   gotOnStatus = false;
 | |
|   var chan = NetUtil.newChannel({uri: url, loadUsingSystemPrincipal: true})
 | |
|                     .QueryInterface(Ci.nsIHttpChannel);
 | |
|   chan.notificationCallbacks = {
 | |
|     numChecks: 0,
 | |
|     QueryInterface: ChromeUtils.generateQI([Ci.nsINetworkInterceptController,
 | |
|                                             Ci.nsIInterfaceRequestor,
 | |
|                                             Ci.nsIProgressEventSink]),
 | |
|     getInterface: function(iid) {
 | |
|       return this.QueryInterface(iid);
 | |
|     },
 | |
|     onProgress: function(request, context, progress, progressMax) {
 | |
|       gotOnProgress = true;
 | |
|     },
 | |
|     onStatus: function(request, context, status, statusArg) {
 | |
|       gotOnStatus = true;
 | |
|     },
 | |
|     shouldPrepareForIntercept: function() {
 | |
|       Assert.equal(this.numChecks, 0);
 | |
|       this.numChecks++;
 | |
|       return true;
 | |
|     },
 | |
|     channelIntercepted: function(channel) {
 | |
|       channel.QueryInterface(Ci.nsIInterceptedChannel);
 | |
|       if (body) {
 | |
|         var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
 | |
|                             .createInstance(Ci.nsIStringInputStream);
 | |
|         synthesized.data = body;
 | |
| 
 | |
|         channel.startSynthesizedResponse(synthesized, null, null, '', false);
 | |
|         channel.finishSynthesizedResponse();
 | |
|       }
 | |
|       if (cb) {
 | |
|         cb(channel);
 | |
|       }
 | |
|       return {
 | |
|         dispatch: function() { }
 | |
|       };
 | |
|     },
 | |
|   };
 | |
|   return chan;
 | |
| }
 | |
| 
 | |
| const REMOTE_BODY = "http handler body";
 | |
| const NON_REMOTE_BODY = "synthesized body";
 | |
| const NON_REMOTE_BODY_2 = "synthesized body #2";
 | |
| 
 | |
| function bodyHandler(metadata, response) {
 | |
|   response.setHeader('Content-Type', 'text/plain');
 | |
|   response.write(REMOTE_BODY);
 | |
| }
 | |
| 
 | |
| function run_test() {
 | |
|   httpServer = new HttpServer();
 | |
|   httpServer.registerPathHandler('/body', bodyHandler);
 | |
|   httpServer.start(-1);
 | |
| 
 | |
|   run_next_test();
 | |
| }
 | |
| 
 | |
| function handle_synthesized_response(request, buffer) {
 | |
|   Assert.equal(buffer, NON_REMOTE_BODY);
 | |
|   Assert.ok(gotOnStatus);
 | |
|   Assert.ok(gotOnProgress);
 | |
|   run_next_test();
 | |
| }
 | |
| 
 | |
| function handle_synthesized_response_2(request, buffer) {
 | |
|   Assert.equal(buffer, NON_REMOTE_BODY_2);
 | |
|   Assert.ok(gotOnStatus);
 | |
|   Assert.ok(gotOnProgress);
 | |
|   run_next_test();
 | |
| }
 | |
| 
 | |
| function handle_remote_response(request, buffer) {
 | |
|   Assert.equal(buffer, REMOTE_BODY);
 | |
|   Assert.ok(gotOnStatus);
 | |
|   Assert.ok(gotOnProgress);
 | |
|   run_next_test();
 | |
| }
 | |
| 
 | |
| // hit the network instead of synthesizing
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(chan) {
 | |
|     chan.resetInterception();
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(handle_remote_response, null));
 | |
| });
 | |
| 
 | |
| // synthesize a response
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', NON_REMOTE_BODY);
 | |
|   chan.asyncOpen2(new ChannelListener(handle_synthesized_response, null, CL_ALLOW_UNKNOWN_CL));
 | |
| });
 | |
| 
 | |
| // hit the network instead of synthesizing, to test that no previous synthesized
 | |
| // cache entry is used.
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(chan) {
 | |
|     chan.resetInterception();
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(handle_remote_response, null));
 | |
| });
 | |
| 
 | |
| // synthesize a different response to ensure no previous response is cached
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', NON_REMOTE_BODY_2);
 | |
|   chan.asyncOpen2(new ChannelListener(handle_synthesized_response_2, null, CL_ALLOW_UNKNOWN_CL));
 | |
| });
 | |
| 
 | |
| // ensure that the channel waits for a decision and synthesizes headers correctly
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(channel) {
 | |
|     do_timeout(100, function() {
 | |
|       var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
 | |
|                           .createInstance(Ci.nsIStringInputStream);
 | |
|       synthesized.data = NON_REMOTE_BODY;
 | |
|       channel.synthesizeHeader("Content-Length", NON_REMOTE_BODY.length);
 | |
|       channel.startSynthesizedResponse(synthesized, null, null, '', false);
 | |
|       channel.finishSynthesizedResponse();
 | |
|     });
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(handle_synthesized_response, null));
 | |
| });
 | |
| 
 | |
| // ensure that the channel waits for a decision
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(chan) {
 | |
|     do_timeout(100, function() {
 | |
|       chan.resetInterception();
 | |
|     });
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(handle_remote_response, null));
 | |
| });
 | |
| 
 | |
| // ensure that the intercepted channel supports suspend/resume
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(intercepted) {
 | |
|     var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
 | |
|                         .createInstance(Ci.nsIStringInputStream);
 | |
|     synthesized.data = NON_REMOTE_BODY;
 | |
| 
 | |
|     // set the content-type to ensure that the stream converter doesn't hold up notifications
 | |
|     // and cause the test to fail
 | |
|     intercepted.synthesizeHeader("Content-Type", "text/plain");
 | |
|     intercepted.startSynthesizedResponse(synthesized, null, null, '', false);
 | |
|     intercepted.finishSynthesizedResponse();
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(handle_synthesized_response, null,
 | |
| 				     CL_ALLOW_UNKNOWN_CL | CL_SUSPEND | CL_EXPECT_3S_DELAY));
 | |
| });
 | |
| 
 | |
| // ensure that the intercepted channel can be cancelled
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(intercepted) {
 | |
|     intercepted.cancelInterception(Cr.NS_BINDING_ABORTED);
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(run_next_test, null, CL_EXPECT_FAILURE));
 | |
| });
 | |
| 
 | |
| // ensure that the channel can't be cancelled via nsIInterceptedChannel after making a decision
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(chan) {
 | |
|     chan.resetInterception();
 | |
|     do_timeout(0, function() {
 | |
|       var gotexception = false;
 | |
|       try {
 | |
|         chan.cancelInterception();
 | |
|       } catch (x) {
 | |
|         gotexception = true;
 | |
|       }
 | |
|       Assert.ok(gotexception);
 | |
|     });
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(handle_remote_response, null));
 | |
| });
 | |
| 
 | |
| // ensure that the intercepted channel can be canceled during the response
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(intercepted) {
 | |
|     var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
 | |
|                         .createInstance(Ci.nsIStringInputStream);
 | |
|     synthesized.data = NON_REMOTE_BODY;
 | |
| 
 | |
|     let channel = intercepted.channel;
 | |
|     intercepted.startSynthesizedResponse(synthesized, null, null, '', false);
 | |
|     intercepted.finishSynthesizedResponse();
 | |
|     channel.cancel(Cr.NS_BINDING_ABORTED);
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(run_next_test, null,
 | |
|                                      CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL));
 | |
| });
 | |
| 
 | |
| // ensure that the intercepted channel can be canceled before the response
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(intercepted) {
 | |
|     var synthesized = Cc["@mozilla.org/io/string-input-stream;1"]
 | |
|                         .createInstance(Ci.nsIStringInputStream);
 | |
|     synthesized.data = NON_REMOTE_BODY;
 | |
| 
 | |
|     intercepted.channel.cancel(Cr.NS_BINDING_ABORTED);
 | |
| 
 | |
|     // This should not throw, but result in the channel firing callbacks
 | |
|     // with an error status.
 | |
|     intercepted.startSynthesizedResponse(synthesized, null, null, '', false);
 | |
|     intercepted.finishSynthesizedResponse();
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(run_next_test, null,
 | |
|                                      CL_EXPECT_FAILURE | CL_ALLOW_UNKNOWN_CL));
 | |
| });
 | |
| 
 | |
| // Ensure that nsIInterceptedChannel.channelIntercepted() can return an error.
 | |
| // In this case we should automatically ResetInterception() and complete the
 | |
| // network request.
 | |
| add_test(function() {
 | |
|   var chan = make_channel(URL + '/body', null, function(chan) {
 | |
|     throw('boom');
 | |
|   });
 | |
|   chan.asyncOpen2(new ChannelListener(handle_remote_response, null));
 | |
| });
 | |
| 
 | |
| add_test(function() {
 | |
|   httpServer.stop(run_next_test);
 | |
| });
 |