سؤال

أحاول إنشاء تطبيق nsIProtocolHandler في دلفي.(لقد فعلت iinternetprotocol من قبل بالنجاح ، وأريد أن يكون في Firefox ما لدي في Internet Explorer.) بفضل د أبو بريص المشروع، الذي يربط بطريقة ما سحر TInterfacedObject بسحر nsISupports، فأنا قادر على إنشاء ملف DLL يوفر nsIModule عند الطلب، والذي يوفر nsIFactory عند الطلب، والذي يوفر واحدًا من nsIProtocolHandler عند الطلب، والذي يوفر إحدى قنوات nsIChannel الخاصة بي /nsIHttpChannel عند السؤال.

عند تصحيح الأخطاء باستخدام firefox.exe كعملية مضيفة، يمكنني رؤية تحميل مكتبتي، واستدعاء NewURI ثلاث مرات، واستدعاء NewChannel، وتمرير كائن ينفذ nsIChannel و nsIHttpChannel.

هذا هو المكان الذي أشعر فيه بالاضطراب.ليس من المفترض أن أتصل بـ OnStartRequest وOnDataAvailable على nsIStreamListener الذي أحصل عليه، حتى أعيد التحكم من AsyncOpen، ولكن لا يبدو أنني أستعيد التحكم في سلسلة الرسائل التي تم استدعاء AsyncOpen فيها.

لقد حاولت تصحيح الأخطاء باستخدام برنامج مجمع ذاتي الصنع حول معالج http الافتراضي (تم الحصول عليه مع CreateInstanceByContractID('@mozilla.org/network/protocol;1?name=http',...).أنا ملفوفة أيضا مرت المستمع.ومن الغريب أن أرى أنه يتم استدعاء OnStartRequest وOnDataAvailable بعد يموت غلاف قناتي في نفس الموضوع.لكن من المتصل؟إذا كانت هي قناة http التي كنت أحاول تغليفها، فكيف يمكنها البقاء (في نفس الموضوع) وكيف يمكنها التحكم في استدعاء المستمع؟أنا في حيرة.و عالقة.

لقد حاولت الاتصال بالمطور الرئيسي لمشروع d-gecko، لكن لم أتلق أي رد.

(وأيضًا، هل لاحظ أحد ما دعاية مغالى فيها في الجزء السفلي من ملف صفحة نقاش على MDC على nsIProtocolHandler?)

(أوه شيء آخر، نعم أعلم أن "الحياة ستكون أبسط" إذا كنت سأرث من nsBaseChannel في C++.ولكن النقطة المهمة هي إضافة معالج بروتوكول FireFox إلى نواة مشروع دلفي الموجودة.)

تحديث: لقد فعلت المزيد من القراءة، وقد ذكر ذلك هنا أيضًا:"تتم استدعاء أساليب المستمع دبليو على الموضوع الذي يدعو إلى عدم التزامن [...] ولكن كيف يمكن استدعاؤه من "تطبيق الاستضافة" أولاً ، ليس واضحًا بالنسبة لي.هل هذه خدعة XPCOM؟أعتقد أنني سأضطر إلى قراءة المزيد من مصادر فايرفوكس قبل أن أحصل عليها.

هل كانت مفيدة؟

المحلول

ليس لدي أي فكرة عن برمجة موزيلا، ولكن هنا يذهب.

وفق nsIChannel::asyncOpen(),

فتح هذه القناة بشكل غير متزامن.يتم تغذية البيانات إلى مستمع الدفق المحدد عند توفره.تتم استدعاء أساليب المستمع دبليو على الخيط الذي يستدعي عدم التزامن ولا يتم استدعاؤه حتى بعد عودة عدم التزامن.في حالة عودة Asyncopen بنجاح ، تعد القناة بالاتصال على الأقل onStarTrequest و onstopRequest.

لذا، باعتبارك معالج البروتوكول، تقوم بتنفيذ كائن قناة بنفسك أو إعادة توجيهه إلى كائن قناة، ويقوم مستهلك القناة باستدعاء قناتك باستخدام asyncOpen().نظرًا لأنها مكالمة غير متزامنة، فإن الفكرة هي إعادة التحكم إلى المستهلك على الفور، ومن المفترض استدعاء عمليات الاسترجاعات أثناء تحميل البيانات.

لست متأكدًا مما إذا كنت أفهم ما تعنيه "لكن لا يبدو أنني أعيد السيطرة في الخيط الذي تم استدعاء عدم التزامن". يتم إنشاء الخيط بواسطة مستهلك بروتوكولك ، ويفتح القناة.

أيضا من nsIChannel::asyncOpen():

إذا عادت Asyncopen بنجاح ، فإن القناة مسؤولة عن الحفاظ على نفسها على قيد الحياة حتى يتم استدعاء OnstopRequest على Alistener أو تسمى OnChannelRedirect.

وبما أن asyncOpen يعيد التحكم مباشرة، فإن القناة نفسها تحتاج إلى الحفاظ على نفسها حية في مكان ما.

إذا كنت تبحث عن نموذج للتعليمات البرمجية، فقد وجدت أن codese مفيد جدًا.يرى nsIProtocolHandler وnsIChannel.باستخدام ذلك جئت عبر بروتوكول عرض المصدر (قد يكون هذا التنفيذ أقدم، ولكن لا يهم).

nsViewSourceHandler تنفذ قناة مخصصة.

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

هنا nsViewSourceChannelAsyncOpen:

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

على أية حال، هذه طريقة طويلة ومعقدة لطرح السؤال، كيف تقوم بإنشاء قناتك؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top