fixes bug 287648 "Unify 'request' object interface for DNS and PPS asyncResolve methods" r=biesi sr=bzbarsky

This commit is contained in:
darin%meer.net 2005-04-01 23:31:04 +00:00
Родитель ec53342255
Коммит 4dd371f200
7 изменённых файлов: 185 добавлений и 77 удалений

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

@ -65,6 +65,7 @@ XPIDLSRCS = \
nsIAsyncStreamCopier.idl \
nsISafeOutputStream.idl \
nsIBufferedStreams.idl \
nsICancelable.idl \
nsIDownloader.idl \
nsIEncodedChannel.idl \
nsIFileStreams.idl \

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

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Darin Fisher <darin@meer.net>
*
* 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 ***** */
#include "nsISupports.idl"
/**
* This interface provides a means to cancel an operation that is in progress.
*
* @status UNDER_REVIEW
*/
[scriptable, uuid(d94ac0a0-bb18-46b8-844e-84159064b0bd)]
interface nsICancelable : nsISupports
{
/**
* Call this method to request that this object abort whatever operation it
* may be performing.
*
* @param aReason
* Pass a failure code to indicate the reason why this operation is
* being canceled. It is an error to pass a success code.
*/
void cancel(in nsresult aReason);
};

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

@ -40,19 +40,22 @@
interface nsIURI;
interface nsIProxyInfo;
interface nsICancelable;
/**
* This interface servers as a closure for nsIProtocolProxyService's
* asyncResolve method.
*
* @status UNDER_REVIEW
*/
[scriptable, uuid(71eba501-2982-4abf-95ab-cf87afc853ad)]
[scriptable, uuid(a9967200-f95e-45c2-beb3-9b060d874bfd)]
interface nsIProtocolProxyCallback : nsISupports
{
/**
* This method is called when proxy info is available or when an error
* in the proxy resolution occurs.
*
* @param aContext
* @param aRequest
* The value returned from asyncResolve.
* @param aURI
* The URI passed to asyncResolve.
@ -66,7 +69,7 @@ interface nsIProtocolProxyCallback : nsISupports
* could not be satisfied, in which case the value of aStatus
* indicates the reason for the failure.
*/
void onProxyAvailable(in nsISupports aContext,
void onProxyAvailable(in nsICancelable aRequest,
in nsIURI aURI,
in nsIProxyInfo aProxyInfo,
in nsresult aStatus);

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

@ -39,6 +39,7 @@
#include "nsISupports.idl"
interface nsICancelable;
interface nsIProtocolProxyCallback;
interface nsIProtocolProxyFilter;
interface nsIProxyInfo;
@ -51,7 +52,7 @@ interface nsIURI;
*
* @status UNDER_REVIEW
*/
[scriptable, uuid(faea2185-8e5b-44a8-ae8f-5fd3f20972af)]
[scriptable, uuid(e38ab577-786e-4a7f-936b-7ae4c7d877b2)]
interface nsIProtocolProxyService : nsISupports
{
/**
@ -111,22 +112,10 @@ interface nsIProtocolProxyService : nsISupports
* @param aCallback
* The object to be notified when the result is available.
*
* @return a context for the operation that can be used to cancel the
* asychronous operation. See for example cancelAsyncResolve.
* @return An object that can be used to cancel the asychronous operation.
*/
nsISupports asyncResolve(in nsIURI aURI,
in unsigned long aFlags,
in nsIProtocolProxyCallback aCallback);
/**
* This method may be used to cancel a pending asyncResolve callback. When
* this is called, the callback object passed to asyncResolve will be
* notified with an error condition of NS_ERROR_ABORT.
*
* @param aContext
* The return value from asyncResolve.
*/
void cancelAsyncResolve(in nsISupports aContext);
nsICancelable asyncResolve(in nsIURI aURI, in unsigned long aFlags,
in nsIProtocolProxyCallback aCallback);
/**
* This method may be called to construct a nsIProxyInfo instance from

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

@ -48,6 +48,7 @@
#include "nsIObserverService.h"
#include "nsIProtocolHandler.h"
#include "nsIProtocolProxyCallback.h"
#include "nsICancelable.h"
#include "nsIDNSService.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch2.h"
@ -78,21 +79,14 @@ struct nsProtocolInfo {
//----------------------------------------------------------------------------
#define NS_ASYNCRESOLVECONTEXT_IID \
{ /* c5fb0580-0cea-4d6a-8f76-ae61dc644d3a */ \
0xc5fb0580, \
0x0cea, \
0x4d6a, \
{0x8f, 0x76, 0xae, 0x61, 0xdc, 0x64, 0x4d, 0x3a} \
}
class nsAsyncResolveContext : public PLEvent, public nsPACManCallback
class nsAsyncResolveRequest : public PLEvent
, public nsPACManCallback
, public nsICancelable
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ASYNCRESOLVECONTEXT_IID)
NS_DECL_ISUPPORTS
nsAsyncResolveContext(nsProtocolProxyService *pps, nsIURI *uri,
nsAsyncResolveRequest(nsProtocolProxyService *pps, nsIURI *uri,
nsIProtocolProxyCallback *callback)
: mStatus(NS_OK)
, mDispatched(PR_FALSE)
@ -100,43 +94,52 @@ public:
, mURI(uri)
, mCallback(callback)
{
NS_ASSERTION(mCallback, "null callback");
PL_InitEvent(this, nsnull, HandleEvent, CleanupEvent);
}
// Called on the main thread
void SetResult(nsresult status, nsIProxyInfo *pi)
{
mStatus = status;
mProxyInfo = pi;
}
// Called on the main thread
void Cancel()
NS_IMETHOD Cancel(nsresult reason)
{
if (mDispatched)
return;
SetResult(NS_ERROR_ABORT, nsnull);
DispatchCallback();
NS_ENSURE_ARG(NS_FAILED(reason));
// If we've already called DoCallback then, nothing more to do.
if (!mCallback)
return NS_OK;
SetResult(reason, nsnull);
return DispatchCallback();
}
// Called on any thread
nsresult DispatchCallback()
{
if (mDispatched) // Only need to dispatch once
return NS_OK;
nsCOMPtr<nsIEventQueue> eventQ;
nsresult rv = NS_GetCurrentEventQ(getter_AddRefs(eventQ));
if (NS_FAILED(rv)) {
if (NS_FAILED(rv))
NS_WARNING("could not get current event queue");
return rv;
else {
NS_ADDREF_THIS();
rv = eventQ->PostEvent(this);
if (NS_FAILED(rv)) {
NS_WARNING("unable to dispatch callback event");
PL_DestroyEvent(this);
}
else {
mDispatched = PR_TRUE;
return NS_OK;
}
}
NS_ADDREF_THIS();
rv = eventQ->PostEvent(this);
if (NS_FAILED(rv)) {
NS_WARNING("unable to dispatch callback event");
PL_DestroyEvent(this);
return rv;
}
mDispatched = PR_TRUE;
return NS_OK;
mCallback = nsnull; // break possible reference cycle
return rv;
}
private:
@ -145,16 +148,22 @@ private:
// before calling DoCallback.
void OnQueryComplete(nsresult status, const nsCString &pacString)
{
if (mDispatched)
// If we've already called DoCallback then, nothing more to do.
if (!mCallback)
return;
mDispatched = PR_TRUE;
mStatus = status;
mPACString = pacString;
// Provided we haven't been canceled...
if (mStatus == NS_OK) {
mStatus = status;
mPACString = pacString;
}
// In the cancelation case, we may still have another PLEvent in
// the queue that wants to call DoCallback. No need to wait for
// it, just run the callback now.
DoCallback();
}
// Called on the main thread
void DoCallback()
{
// Generate proxy info from the PAC string if appropriate
@ -177,8 +186,8 @@ private:
PR_STATIC_CALLBACK(void *) HandleEvent(PLEvent *ev)
{
nsAsyncResolveContext *self =
NS_STATIC_CAST(nsAsyncResolveContext *, ev);
nsAsyncResolveRequest *self =
NS_STATIC_CAST(nsAsyncResolveRequest *, ev);
if (self->mCallback)
self->DoCallback();
return nsnull;
@ -186,8 +195,8 @@ private:
PR_STATIC_CALLBACK(void) CleanupEvent(PLEvent *ev)
{
nsAsyncResolveContext *self =
NS_STATIC_CAST(nsAsyncResolveContext *, ev);
nsAsyncResolveRequest *self =
NS_STATIC_CAST(nsAsyncResolveRequest *, ev);
NS_RELEASE(self); // balance AddRef in DispatchCallback
}
@ -203,7 +212,7 @@ private:
nsCOMPtr<nsIProxyInfo> mProxyInfo;
};
NS_IMPL_ISUPPORTS1(nsAsyncResolveContext, nsAsyncResolveContext)
NS_IMPL_ISUPPORTS1(nsAsyncResolveRequest, nsICancelable)
//----------------------------------------------------------------------------
@ -806,10 +815,10 @@ nsProtocolProxyService::Resolve(nsIURI *uri, PRUint32 flags,
NS_IMETHODIMP
nsProtocolProxyService::AsyncResolve(nsIURI *uri, PRUint32 flags,
nsIProtocolProxyCallback *callback,
nsISupports **result)
nsICancelable **result)
{
nsCOMPtr<nsAsyncResolveContext> ctx =
new nsAsyncResolveContext(this, uri, callback);
nsRefPtr<nsAsyncResolveRequest> ctx =
new nsAsyncResolveRequest(this, uri, callback);
if (!ctx)
return NS_ERROR_OUT_OF_MEMORY;
@ -828,8 +837,7 @@ nsProtocolProxyService::AsyncResolve(nsIURI *uri, PRUint32 flags,
ApplyFilters(uri, info, pi);
ctx->SetResult(NS_OK, pi);
ctx->DispatchCallback();
return NS_OK;
return ctx->DispatchCallback();
}
// else kick off a PAC query
@ -841,15 +849,6 @@ nsProtocolProxyService::AsyncResolve(nsIURI *uri, PRUint32 flags,
return rv;
}
NS_IMETHODIMP
nsProtocolProxyService::CancelAsyncResolve(nsISupports *context)
{
nsCOMPtr<nsAsyncResolveContext> ctx = do_QueryInterface(context);
NS_ENSURE_ARG(ctx);
ctx->Cancel();
return NS_OK;
}
NS_IMETHODIMP
nsProtocolProxyService::NewProxyInfo(const nsACString &aType,
const nsACString &aHost,

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

@ -76,7 +76,7 @@ public:
NS_HIDDEN_(nsresult) Init();
protected:
friend class nsAsyncResolveContext;
friend class nsAsyncResolveRequest;
~nsProtocolProxyService() NS_HIDDEN;

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

@ -272,10 +272,10 @@ TestResolveCallback.prototype = {
},
onProxyAvailable:
function TestResolveCallback_onProxyAvailable(ctx, uri, pi, status) {
function TestResolveCallback_onProxyAvailable(req, uri, pi, status) {
dump("*** uri=" + uri.spec + ", status=" + status + "\n");
do_check_neq(ctx, null);
do_check_neq(req, null);
do_check_neq(uri, null);
do_check_eq(status, 0);
do_check_neq(pi, null);
@ -296,6 +296,7 @@ TestResolveCallback.prototype = {
prefs.setCharPref("network.proxy.autoconfig_url", "");
prefs.setIntPref("network.proxy.type", 0);
run_test_continued();
do_test_finished();
}
};
@ -329,7 +330,55 @@ function run_pac_test() {
}
do_check_eq(hit_exception, true);
var ctx = pps.asyncResolve(uri, 0, new TestResolveCallback());
var req = pps.asyncResolve(uri, 0, new TestResolveCallback());
do_test_pending();
}
function TestResolveCancelationCallback() {
}
TestResolveCancelationCallback.prototype = {
QueryInterface:
function TestResolveCallback_QueryInterface(iid) {
if (iid.equals(Components.interfaces.nsIProtocolProxyCallback) ||
iid.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
onProxyAvailable:
function TestResolveCancelationCallback_onProxyAvailable(req, uri, pi, status) {
dump("*** uri=" + uri.spec + ", status=" + status + "\n");
do_check_neq(req, null);
do_check_neq(uri, null);
do_check_eq(status, Components.results.NS_ERROR_ABORT);
do_check_eq(pi, null);
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
prefs.setCharPref("network.proxy.autoconfig_url", "");
prefs.setIntPref("network.proxy.type", 0);
run_test_continued_2();
do_test_finished();
}
};
function run_pac_cancel_test() {
var uri = ios.newURI("http://www.mozilla.org/", null, null);
// Configure PAC
var pac = 'data:text/plain,' +
'function FindProxyForURL(url, host) {' +
' return "PROXY foopy:8080; DIRECT";' +
'}';
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
prefs.setIntPref("network.proxy.type", 2);
prefs.setCharPref("network.proxy.autoconfig_url", pac);
var req = pps.asyncResolve(uri, 0, new TestResolveCancelationCallback());
req.cancel(Components.results.NS_ERROR_ABORT);
do_test_pending();
}
@ -339,4 +388,13 @@ function run_test() {
run_filter_test2();
run_pref_test();
run_pac_test();
// additional tests may be added to run_test_continued
}
function run_test_continued() {
run_pac_cancel_test();
// additional tests may be added to run_test_continued_2
}
function run_test_continued_2() {
}