Domanda

Sto cercando di costruire un'implementazione nsIProtocolHandler in Delphi. (Ho fatto un IInternetProtocol prima con successo, e vogliono avere in FireFox quello che ho in Internet Explorer.) Grazie il d-geco progetto, che collega in qualche modo la magia TInterfacedObject alla magia nsISupports, ho 'm in grado di fare una DLL che fornisce un nsIModule quando gli viene chiesto, che fornisce un nsIFactory quando gli viene chiesto, che fornisce uno dei miei nsIProtocolHandler di quando gli viene chiesto, che fornisce uno dei miei nsIChannel / di nsIHttpChannel quando richiesto.

Quando il debug utilizzando firefox.exe come processo host, posso vedere mia libreria viene caricato, NewURI viene chiamato tre volte, NewChannel viene chiamato, e mi passa un oggetto che implementa nsIChannel e nsIHttpChannel .

Questo è dove sono turbato. Non dovrei chiamare OnStartRequest e OnDataAvailable sul nsIStreamListener ottengo, fino al mio ritorno il controllo da AsyncOpen, ma non mi sembra di avere il controllo indietro nel thread che AsyncOpen fu chiamato.

Ho provato il debug con un involucro fatto da sé intorno a un gestore predefinito http (ottenuto con CreateInstanceByContractID('@mozilla.org/network/protocol;1?name=http', ...). Ho anche avvolto l'ascoltatore passato. Stranamente, vedo OnStartRequest e OnDataAvailable vieni chiamato dopo il mio involucro canale muore, nello stesso thread. Ma chi sta chiamando? Se è la http canale stavo cercando di avvolgere, come fa a sopravvivere (nello stesso thread) e come ottenere il controllo di chiamare l'ascoltatore? Sono sconcertato. E bloccato.

Ho provato a contattare lo sviluppatore principale del progetto D-geco, ma ho ottenuto alcuna risposta.

(Inoltre, qualcuno ha mai notato il mio trafiletto in fondo alla pagina di discussione href="https://developer.mozilla.org/Talk:En/NsIProtocolHandler" rel="nofollow su MDC su nsIProtocolHandler ?)

(Oh una cosa, sì, lo so "la vita sarebbe più semplice" se vorrei solo ereditare da nsBaseChannel in C ++. Ma il punto è quello di aggiungere un FireFox protocollo-gestore per un nucleo progetto Delphi esistente.)

Aggiornamento: Ho fatto un po 'di lettura, è menzionato qui così:" metodi di chi ascolta flusso sono  ha invitato il thread che chiama asyncOpen [...]", ma come ciò sia possibile senza essere chiamato dal 'hosting di applicazioni' prima, non è chiaro per me. È che un trucchetto XPCOM? Mi sa che dovrò leggere (molto) più firefox sorgente prima ho capito.

È stato utile?

Soluzione

Non ho idea di codifica Mozilla, ma qui va.

nsIChannel :: asyncOpen () ,

  

in modo asincrono aprire questo canale. Dati   viene alimentato al flusso specificato   ascoltatore appena sarà disponibile. Il   metodi flusso di chi ascolta sono chiamati   sul thread che chiama e asyncOpen   non sono chiamati solo dopo asyncOpen   ritorna. Se i rendimenti asyncOpen   con successo, il canale promette di   chiamare almeno onStartRequest e   onStopRequest.

Così come il protocollo di curva, si implementa un oggetto canale sul proprio o reindirizzare a un oggetto di canale, il consumatore del canale richiama il canale utilizzando asyncOpen(). Dal momento che si tratta di una chiamata asincrona, l'idea è di restituire il controllo al consumatore immediatamente, ed è supponiamo di chiamare i callback come carica nei dati.

Non sono sicuro se ho capito cosa si intende per "ma non mi sembra per ottenere il controllo indietro nel thread che AsyncOpen fu chiamato." Il filo è creato da parte del consumatore del protocollo, e si apre il canale.

Anche da nsIChannel :: asyncOpen () :

  

Se asyncOpen restituisce con successo, la   canale è responsabile della conservazione   si vive fino a quando non ha chiamato   onStopRequest su aListener o chiamato   onChannelRedirect.

Dal asyncOpen restituisce il controllo di terzino destro, il canale stesso deve mantenersi viva da qualche parte.

Se siete alla ricerca di codice di esempio, ho trovato codase per essere molto utile. Vedere nsIProtocolHandler nsIChannel . Utilizzando che mi sono imbattuto view-source del protocollo (questa implementazione può essere anteriore, ma non importa).

nsViewSourceHandler implementa canale personalizzato.

nsViewSourceHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
{
    nsresult rv;

    nsViewSourceChannel* channel;
    rv = nsViewSourceChannel::Create(nsnull, NS_GET_IID(nsIChannel), (void**)&channel);
    if (NS_FAILED(rv)) return rv;

    rv = channel->Init(uri);
    if (NS_FAILED(rv)) {
        NS_RELEASE(channel);
        return rv;
    }

    *result = NS_STATIC_CAST(nsIViewSourceChannel*, channel);
    return NS_OK;
}

Ecco il nsViewSourceChannel 's AsyncOpen:

nsViewSourceChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
    NS_ENSURE_TRUE(mChannel, NS_ERROR_FAILURE);

    mListener = aListener;

    /*
     * We want to add ourselves to the loadgroup before opening
     * mChannel, since we want to make sure we're in the loadgroup
     * when mChannel finishes and fires OnStopRequest()
     */

    nsCOMPtr<nsILoadGroup> loadGroup;
    mChannel->GetLoadGroup(getter_AddRefs(loadGroup));
    if (loadGroup)
        loadGroup->AddRequest(NS_STATIC_CAST(nsIViewSourceChannel*,
                                             this), nsnull);

    nsresult rv = mChannel->AsyncOpen(this, ctxt);

    if (NS_FAILED(rv) && loadGroup)
        loadGroup->RemoveRequest(NS_STATIC_CAST(nsIViewSourceChannel*,
                                                this),
                                 nsnull, rv);

    if (NS_SUCCEEDED(rv)) {
        mOpened = PR_TRUE;
    }

    return rv;
}

In ogni caso, questo è un modo lungo e tortuoso di chiedere, come stai creando il tuo canale?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top