Bug 526686 - Add QueryInterface methods to all exposed types of objects in httpd.js. Also change nsIHttpRequestMetadata to nsIHttpRequest for a little conciseness. r=waylon, not worth someone's time to review trivial code changes and renamings

This commit is contained in:
Jeff Walden 2009-11-06 16:24:32 -08:00
Родитель 89744c4f05
Коммит 850d28f0dc
5 изменённых файлов: 371 добавлений и 133 удалений

Просмотреть файл

@ -812,6 +812,136 @@ function ServerIdentity()
}
ServerIdentity.prototype =
{
// NSIHTTPSERVERIDENTITY
//
// see nsIHttpServerIdentity.primaryScheme
//
get primaryScheme()
{
if (this._primaryPort === -1)
throw Cr.NS_ERROR_NOT_INITIALIZED;
return this._primaryScheme;
},
//
// see nsIHttpServerIdentity.primaryHost
//
get primaryHost()
{
if (this._primaryPort === -1)
throw Cr.NS_ERROR_NOT_INITIALIZED;
return this._primaryHost;
},
//
// see nsIHttpServerIdentity.primaryPort
//
get primaryPort()
{
if (this._primaryPort === -1)
throw Cr.NS_ERROR_NOT_INITIALIZED;
return this._primaryPort;
},
//
// see nsIHttpServerIdentity.add
//
add: function(scheme, host, port)
{
this._validate(scheme, host, port);
var entry = this._locations["x" + host];
if (!entry)
this._locations["x" + host] = entry = {};
entry[port] = scheme;
},
//
// see nsIHttpServerIdentity.remove
//
remove: function(scheme, host, port)
{
this._validate(scheme, host, port);
var entry = this._locations["x" + host];
if (!entry)
return false;
var present = port in entry;
delete entry[port];
if (this._primaryScheme == scheme &&
this._primaryHost == host &&
this._primaryPort == port &&
this._defaultPort !== -1)
{
// Always keep at least one identity in existence at any time, unless
// we're in the process of shutting down (the last condition above).
this._primaryPort = -1;
this._initialize(this._defaultPort, false);
}
return present;
},
//
// see nsIHttpServerIdentity.has
//
has: function(scheme, host, port)
{
this._validate(scheme, host, port);
return "x" + host in this._locations &&
scheme === this._locations["x" + host][port];
},
//
// see nsIHttpServerIdentity.has
//
getScheme: function(host, port)
{
this._validate("http", host, port);
var entry = this._locations["x" + host];
if (!entry)
return "";
return entry[port] || "";
},
//
// see nsIHttpServerIdentity.setPrimary
//
setPrimary: function(scheme, host, port)
{
this._validate(scheme, host, port);
this.add(scheme, host, port);
this._primaryScheme = scheme;
this._primaryHost = host;
this._primaryPort = port;
},
// NSISUPPORTS
//
// see nsISupports.QueryInterface
//
QueryInterface: function(iid)
{
if (iid.equals(Ci.nsIHttpServerIdentity) || iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
// PRIVATE IMPLEMENTATION
/**
* Initializes the primary name for the corresponding server, based on the
* provided port number.
@ -861,117 +991,6 @@ ServerIdentity.prototype =
}
},
//
// see nsIHttpServerIdentity.primaryScheme
//
get primaryScheme()
{
if (this._primaryPort === -1)
throw Cr.NS_ERROR_NOT_INITIALIZED;
return this._primaryScheme;
},
//
// see nsIHttpServerIdentity.primaryHost
//
get primaryHost()
{
if (this._primaryPort === -1)
throw Cr.NS_ERROR_NOT_INITIALIZED;
return this._primaryHost;
},
//
// see nsIHttpServerIdentity.primaryPort
//
get primaryPort()
{
if (this._primaryPort === -1)
throw Cr.NS_ERROR_NOT_INITIALIZED;
return this._primaryPort;
},
//
// see nsIHttpServerIdentity.add
//
add: function(scheme, host, port)
{
this._validate(scheme, host, port);
var entry = this._locations["x" + host];
if (!entry)
this._locations["x" + host] = entry = {};
entry[port] = scheme;
},
//
// see nsIHttpServerIdentity.remove
//
remove: function(scheme, host, port)
{
this._validate(scheme, host, port);
var entry = this._locations["x" + host];
if (!entry)
return false;
var present = port in entry;
delete entry[port];
if (this._primaryScheme == scheme &&
this._primaryHost == host &&
this._primaryPort == port &&
this._defaultPort !== -1)
{
// Always keep at least one identity in existence at any time, unless
// we're in the process of shutting down (the last condition above).
this._primaryPort = -1;
this._initialize(this._defaultPort, false);
}
return present;
},
//
// see nsIHttpServerIdentity.has
//
has: function(scheme, host, port)
{
this._validate(scheme, host, port);
return "x" + host in this._locations &&
scheme === this._locations["x" + host][port];
},
//
// see nsIHttpServerIdentity.has
//
getScheme: function(host, port)
{
this._validate("http", host, port);
var entry = this._locations["x" + host];
if (!entry)
return "";
return entry[port] || "";
},
//
// see nsIHttpServerIdentity.setPrimary
//
setPrimary: function(scheme, host, port)
{
this._validate(scheme, host, port);
this.add(scheme, host, port);
this._primaryScheme = scheme;
this._primaryHost = host;
this._primaryPort = port;
},
/**
* Ensures scheme, host, and port are all valid with respect to RFC 2396.
*
@ -3521,6 +3540,20 @@ Response.prototype =
},
// NSISUPPORTS
//
// see nsISupports.QueryInterface
//
QueryInterface: function(iid)
{
if (iid.equals(Ci.nsIHttpResponse) || iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
// POST-CONSTRUCTION API (not exposed externally)
/**
@ -4432,8 +4465,8 @@ function Request(port)
/**
* For the addition of ad-hoc properties and new functionality without having
* to change nsIHttpRequestMetadata every time; currently lazily created,
* as its only use is in directory listings.
* to change nsIHttpRequest every time; currently lazily created, as its only
* use is in directory listings.
*/
this._bag = null;
}
@ -4442,7 +4475,7 @@ Request.prototype =
// SERVER METADATA
//
// see nsIHttpRequestMetadata.scheme
// see nsIHttpRequest.scheme
//
get scheme()
{
@ -4450,7 +4483,7 @@ Request.prototype =
},
//
// see nsIHttpRequestMetadata.host
// see nsIHttpRequest.host
//
get host()
{
@ -4458,7 +4491,7 @@ Request.prototype =
},
//
// see nsIHttpRequestMetadata.port
// see nsIHttpRequest.port
//
get port()
{
@ -4468,7 +4501,7 @@ Request.prototype =
// REQUEST LINE
//
// see nsIHttpRequestMetadata.method
// see nsIHttpRequest.method
//
get method()
{
@ -4476,7 +4509,7 @@ Request.prototype =
},
//
// see nsIHttpRequestMetadata.httpVersion
// see nsIHttpRequest.httpVersion
//
get httpVersion()
{
@ -4484,7 +4517,7 @@ Request.prototype =
},
//
// see nsIHttpRequestMetadata.path
// see nsIHttpRequest.path
//
get path()
{
@ -4492,7 +4525,7 @@ Request.prototype =
},
//
// see nsIHttpRequestMetadata.queryString
// see nsIHttpRequest.queryString
//
get queryString()
{
@ -4502,7 +4535,7 @@ Request.prototype =
// HEADERS
//
// see nsIHttpRequestMetadata.getHeader
// see nsIHttpRequest.getHeader
//
getHeader: function(name)
{
@ -4510,7 +4543,7 @@ Request.prototype =
},
//
// see nsIHttpRequestMetadata.hasHeader
// see nsIHttpRequest.hasHeader
//
hasHeader: function(name)
{
@ -4518,7 +4551,7 @@ Request.prototype =
},
//
// see nsIHttpRequestMetadata.headers
// see nsIHttpRequest.headers
//
get headers()
{
@ -4535,7 +4568,7 @@ Request.prototype =
},
//
// see nsIHttpRequestMetadata.headers
// see nsIHttpRequest.headers
//
get bodyInputStream()
{
@ -4550,6 +4583,23 @@ Request.prototype =
this._ensurePropertyBag();
return this._bag.getProperty(name);
},
// NSISUPPORTS
//
// see nsISupports.QueryInterface
//
QueryInterface: function(iid)
{
if (iid.equals(Ci.nsIHttpRequest) || iid.equals(Ci.nsISupports))
return this;
throw Cr.NS_ERROR_NO_INTERFACE;
},
// PRIVATE IMPLEMENTATION
/** Ensures a property bag has been created for ad-hoc behaviors. */
_ensurePropertyBag: function()

Просмотреть файл

@ -46,7 +46,7 @@ interface nsISimpleEnumerator;
interface nsIHttpServer;
interface nsIHttpServerStoppedCallback;
interface nsIHttpRequestHandler;
interface nsIHttpRequestMetadata;
interface nsIHttpRequest;
interface nsIHttpResponse;
interface nsIHttpServerIdentity;
@ -261,8 +261,8 @@ interface nsIHttpServerIdentity : nsISupports
{
/**
* The primary scheme at which the corresponding server is located, defaulting
* to 'http'. This name will be the value of nsIHttpRequestMetadata.scheme
* for HTTP/1.0 requests.
* to 'http'. This name will be the value of nsIHttpRequest.scheme for
* HTTP/1.0 requests.
*
* This value is always set when the corresponding server is running. If the
* server is not running, this value is set only if it has been set to a
@ -273,8 +273,8 @@ interface nsIHttpServerIdentity : nsISupports
/**
* The primary name by which the corresponding server is known, defaulting to
* 'localhost'. This name will be the value of nsIHttpRequestMetadata.host
* for HTTP/1.0 requests.
* 'localhost'. This name will be the value of nsIHttpRequest.host for
* HTTP/1.0 requests.
*
* This value is always set when the corresponding server is running. If the
* server is not running, this value is set only if it has been set to a
@ -286,7 +286,7 @@ interface nsIHttpServerIdentity : nsISupports
/**
* The primary port on which the corresponding server runs, defaulting to the
* associated server's port. This name will be the value of
* nsIHttpRequestMetadata.port for HTTP/1.0 requests.
* nsIHttpRequest.port for HTTP/1.0 requests.
*
* This value is always set when the corresponding server is running. If the
* server is not running, this value is set only if it has been set to a
@ -383,7 +383,7 @@ interface nsIHttpRequestHandler : nsISupports
* an initially-empty response which must be modified to reflect the data
* which should be sent as the response to the request described by metadata
*/
void handle(in nsIHttpRequestMetadata metadata, in nsIHttpResponse response);
void handle(in nsIHttpRequest metadata, in nsIHttpResponse response);
};
@ -391,7 +391,7 @@ interface nsIHttpRequestHandler : nsISupports
* A representation of the data included in an HTTP request.
*/
[scriptable, uuid(80cbca71-dc51-4fa0-9010-1cec262dbd4a)]
interface nsIHttpRequestMetadata : nsIPropertyBag
interface nsIHttpRequest : nsIPropertyBag
{
/**
* The request type for this request (see RFC 2616, section 5.1.1).

Просмотреть файл

@ -0,0 +1,48 @@
const Ci = Components.interfaces;
function handleRequest(request, response)
{
var exstr, qid;
response.setStatusLine(request.httpVersion, 500, "FAIL");
var passed = false;
try
{
qid = request.QueryInterface(Ci.nsIHttpRequest);
passed = qid === request;
}
catch (e)
{
exstr = ("" + e).split(/[\x09\x20-\x7f\x81-\xff]+/)[0];
response.setStatusLine(request.httpVersion, 500,
"request doesn't QI: " + exstr);
return;
}
if (!passed)
{
response.setStatusLine(request.httpVersion, 500, "request QI'd wrongly?");
return;
}
passed = false;
try
{
qid = response.QueryInterface(Ci.nsIHttpResponse);
passed = qid === response;
}
catch (e)
{
exstr = ("" + e).split(/[\x09\x20-\x7f\x81-\xff]+/)[0];
response.setStatusLine(request.httpVersion, 500,
"response doesn't QI: " + exstr);
return;
}
if (!passed)
{
response.setStatusLine(request.httpVersion, 500, "response QI'd wrongly?");
return;
}
response.setStatusLine(request.httpVersion, 200, "SJS QI Tests Passed");
}

Просмотреть файл

@ -164,7 +164,7 @@ function expectLines(iter, expectedLines)
/**
* Spew a bunch of HTTP metadata from request into the body of response.
*
* @param request : nsIHttpRequestMetadata
* @param request : nsIHttpRequest
* the request whose metadata should be output
* @param response : nsIHttpResponse
* the response to which the metadata is written

Просмотреть файл

@ -0,0 +1,140 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is httpd.js code.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Jeff Walden <jwalden+code@mit.edu> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
* Verify the presence of explicit QueryInterface methods on XPCOM objects
* exposed by httpd.js, rather than allowing QueryInterface to be implicitly
* created by XPConnect.
*/
var tests =
[
new Test("http://localhost:4444/test",
null, start_test, null),
new Test("http://localhost:4444/sjs/qi.sjs",
null, start_sjs_qi, null),
];
function run_test()
{
var srv = createServer();
var qi;
try
{
qi = srv.identity.QueryInterface(Ci.nsIHttpServerIdentity);
}
catch (e)
{
var exstr = ("" + e).split(/[\x09\x20-\x7f\x81-\xff]+/)[0];
do_throw("server identity didn't QI: " + exstr);
return;
}
srv.registerPathHandler("/test", testHandler);
srv.registerDirectory("/", do_get_file("data/"));
srv.registerContentType("sjs", "sjs");
srv.start(4444);
runHttpTests(tests, testComplete(srv));
}
// TEST DATA
function start_test(ch, cx)
{
do_check_eq(ch.responseStatusText, "QI Tests Passed");
do_check_eq(ch.responseStatus, 200);
}
function start_sjs_qi(ch, cx)
{
do_check_eq(ch.responseStatusText, "SJS QI Tests Passed");
do_check_eq(ch.responseStatus, 200);
}
function testHandler(request, response)
{
var exstr;
var qid;
response.setStatusLine(request.httpVersion, 500, "FAIL");
var passed = false;
try
{
qid = request.QueryInterface(Ci.nsIHttpRequest);
passed = qid === request;
}
catch (e)
{
exstr = ("" + e).split(/[\x09\x20-\x7f\x81-\xff]+/)[0];
response.setStatusLine(request.httpVersion, 500,
"request doesn't QI: " + exstr);
return;
}
if (!passed)
{
response.setStatusLine(request.httpVersion, 500, "request QI'd wrongly?");
return;
}
passed = false;
try
{
qid = response.QueryInterface(Ci.nsIHttpResponse);
passed = qid === response;
}
catch (e)
{
exstr = ("" + e).split(/[\x09\x20-\x7f\x81-\xff]+/)[0];
response.setStatusLine(request.httpVersion, 500,
"response doesn't QI: " + exstr);
return;
}
if (!passed)
{
response.setStatusLine(request.httpVersion, 500, "response QI'd wrongly?");
return;
}
response.setStatusLine(request.httpVersion, 200, "QI Tests Passed");
}