Question

Je suis en train de construire une implémentation nsIProtocolHandler en Delphi. (Je l'ai fait un IInternetProtocol avant avec succès, et que vous voulez avoir dans FireFox ce que j'ai dans Internet Explorer.) Merci le d-gecko projet, qui relie en quelque sorte la magie TInterfacedObject à la magie nsISupports, je « m capable de faire une DLL qui fournit un nsIModule lorsqu'on lui a demandé, qui fournit un nsIFactory lorsqu'on lui a demandé, ce qui fournit un de mes quand de nsIProtocolHandler demandé, qui fournit un de mes de nsIChannel / nsIHttpChannel lorsqu'on lui a demandé.

Lors du débogage en utilisant firefox.exe comme processus hôte, je peux voir ma bibliothèque se charge, NewURI est appelé trois fois, NewChannel est appelé, et je passe un objet qui implémente nsIChannel et nsIHttpChannel .

est où je suis troublé. Je ne suis pas censé appeler OnStartRequest et OnDataAvailable sur le nsIStreamListener que je reçois, jusqu'à ce que je retourne le contrôle de AsyncOpen, mais je ne semble pas obtenir le contrôle de retour dans le thread qui AsyncOpen a été appelé.

Je l'ai essayé avec le débogage d'une enveloppe en auto-gestionnaire autour d'un défaut de http (obtenu avec CreateInstanceByContractID('@mozilla.org/network/protocol;1?name=http', ...). J'enroulai aussi l'auditeur passé. Curieusement, je vois OnStartRequest et OnDataAvailable me appelé après mon enveloppe de canal meurt, dans le même fil. Mais qui appelle? Si c'est le canal http je tentais de terminer, comment faut-il survivre (dans le même fil) et comment est-elle le contrôle d'appeler l'auditeur? Je suis déconcerté. Et coincé.

J'ai essayé de contacter le développeur principal du projet d-gecko, mais on m'a donné aucune réponse.

(Aussi, quelqu'un jamais remarqué mon texte de présentation au bas de la MDC nsIProtocolHandler ?)

(Oh une chose, oui je sais « la vie serait plus simple » si je voudrais juste hériter de nsBaseChannel en C ++. Mais le point est d'ajouter un protocole gestionnaire FireFox à un noyau de projet Delphi existant.)

Mise à jour: Je l'ai fait un peu plus de lecture, il est mentionné

Était-ce utile?

La solution

Je ne sais pas sur le codage Mozilla, mais ici il va.

Selon nsIChannel :: asyncOpen () ,

  

ouvrir ce canal de manière asynchrone. Les données   est introduit dans le flux spécifié   auditeur comme il devient disponible. le   Les méthodes d'écoute de flux sont appelés   sur le thread qui appelle asyncOpen et   ne sont pas appelés qu'après asyncOpen   résultats. Si le rendement asyncOpen   avec succès, promet le canal   appeler au moins onStartRequest et   onStopRequest.

comme protocole clapoteuses, vous implémentez un objet de canal sur votre propre ou rediriger vers un objet de canal, le consommateur du canal appelle votre canal à l'aide asyncOpen(). Comme il est un appel asynchrone, l'idée est de remettre le contrôle au consommateur immédiatement, et il est supposé appeler les callbacks comme charge dans les données.

Je ne sais pas si je comprends ce que vous entendez par « mais je ne semble pas obtenir le contrôle de retour dans le thread qui AsyncOpen a été appelé. » Le fil est créé par le consommateur de votre protocole, et il ouvre la voie.

En outre de nsIChannel :: asyncOpen () :

  

Si asyncOpen retourne avec succès, la   canal est responsable de la tenue   lui-même en vie jusqu'à ce qu'il a appelé   onStopRequest sur ou appelé un écouteur   onChannelRedirect.

Depuis asyncOpen retourne le contrôle de retour, le canal lui-même a besoin de se maintenir en vie quelque part.

Si vous cherchez un exemple de code, j'ai trouvé codase très utile. Voir nsIProtocolHandler nsIChannel . L'utilisation que je suis tombé sur protocole vue source (cette mise en œuvre peut être plus, mais n'a pas d'importance).

nsViewSourceHandler implémente canal personnalisé.

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;
}

Voici le nsViewSourceChannel AsyncOpen de:

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;
}

Quoi qu'il en soit, c'est une façon longue et sinueuse de demander, comment créer vous votre chaîne?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top