65.9K
CodeProject 正在变化。 阅读更多。
Home

为 Mozilla Firefox 创建新协议(C++)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.31/5 (11投票s)

2005年2月18日

4分钟阅读

viewsIcon

96620

downloadIcon

1186

为 Firefox 创建新协议。

Sample Image - FirefoxProtocol.jpg

引言

本文将向您展示如何为 Mozilla Firefox 浏览器创建新协议。Mozilla Firefox 支持通用的 Web 协议,例如 HTTP 和 FTP,并且还支持 Chrome 等自己的协议。有时需要为您的项目创建自定义协议,该协议将插入到现有的 Firefox 安装中。

要创建新协议,您需要实现一个 XPCOM 组件。XPCOM 非常类似于 MS COM(本文不涵盖 XPCOM 的基础知识,您可以在网上找到许多关于 XPCOM 的优秀文章和在线书籍)。您可以使用 JavaScript 或 C++ 来实现 XPCOM。我找到了一篇由 Doron Rosenberg 撰写的非常有用的文章,其中介绍了如何使用 JavaScript 为 Mozilla 构建新协议。

在本文中,我们将使用 C++ 来构建协议的 XPCOM。本文的目的是提供一个非常简单的自定义协议示例,该协议用 C++ 编写,当您急需为 Mozilla Firefox 创建自定义协议时,可以重复使用大部分代码,并专注于协议功能逻辑,而不是到处搜索 Mozilla 协议的基本框架。

您可以在Mozilla 网站上找到 C++ 实现协议的另一个地方,但它稍微复杂且文档较少。

本示例协议的作用是什么?

本文的示例将构建“find:”协议,该协议将使用用户的默认搜索引擎来发起搜索,类似于 Doron Rosenberg 用 JavaScript 创建的“x-search:”协议。

当此协议安装在 Mozilla Firefox 中时,可以通过输入以下内容来调用它:

find:<search term>

或者

find://<search term>

到 URL 栏并按 Enter。

如何安装此协议?

只需下载文件“findprotocol.xpi”并用 Mozilla Firefox 打开它。Firefox 将其作为新协议安装。.xpi 文件就是一个重命名为 .xpi 的 .zip 文件。

或者,您可以将 XPCOM(这是一个 DLL 文件)复制到现有 Mozilla Firefox 安装的“components”文件夹中,然后从“C:\Documents and Settings\<user>\application Data\Mozilla\Firefox\Profiles\<wtimmm.default>" 中删除“Compreg.dat”文件,并重新启动 Firefox,Firefox 将注册新的 XPCOM DLL。

如何编译源代码?

此示例是在安装了 Service Pack 5 的 VC++ 6 中编译的。您需要构建 Mozilla Firefox,因为构建 Firefox 后,您将获得创建 XPCOM 所需的所有头文件和库。构建 Mozilla 并非易事,您可以在网上找到许多有关构建 Mozilla 的指南。构建完成后,它将生成一个名为“Dist”的文件夹,其中包含所有需要与您的代码链接以构建此文件的库和头文件。

注意:- 此代码在警告级别 3 下可以干净地编译,没有任何警告。在警告级别 4 下会出现警告。

使用代码

要创建新协议,您必须实现 nsIProtocolHandler 接口。协议处理程序是实现 nsIProtocolHandler 的类。它负责向网络库返回关于协议的基本信息(例如默认端口和 URI 格式),并负责创建适当类型的通道来处理请求。

以下是在 nsFindHandler.h 中实现的:

#ifndef nsFindHandler_h___
#define nsFindHandler_h___

#include "nsIProtocolHandler.h"

#define FIND_PORT -1 


//this is the UUID
#define NS_FINDHANDLER_CID     \
{ 0x7F1D8DA4, 0x668F, 0x4c3c, \
   {0xBD, 0x7B, 0xEA, 0x95, 0xB2, 0x8D, 0x5A, 0xD0} }

#define kPROTOCOL_CONTRACTID "@mozilla.org/network/protocol;1?name=find"

#define kIOSERVICE_CONTRACTID  "@mozilla.org/network/io-service;1"

class nsFindHandler : public nsIProtocolHandler
{
public:
    NS_DECL_ISUPPORTS
    NS_DECL_NSIPROTOCOLHANDLER

    // nsFindHandler methods:
    nsFindHandler();
    virtual ~nsFindHandler();

    // Define a Create method to be used with a factory:
    static NS_METHOD Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult);

private:
 

    char *pStr;//for holding the total url typed
};

#endif /* nsFindHandler_h___ */

NS_FINDHANDLER_CID 应该唯一;您可以使用 GUIDgen.exe 生成它。

这是 nsFindHandler.cpp

#ifndef XP_WIN
#define XP_WIN
#endif

#include <Windows.h>

#include "nspr.h"
#include "nsFindHandler.h"
#include "nsIURL.h"
#include "nsCRT.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIProgressEventSink.h"
#include "nsNetCID.h"
#include "nsIIOService.h"
#include "nsIChannel.h"
#include "nsEmbedString.h"

#include "BuildSearchString.h"


static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);

////////////////////////////////////////////////////////////////////////////////

nsFindHandler::nsFindHandler() {

}

nsFindHandler::~nsFindHandler() {
}

NS_IMPL_ISUPPORTS1(nsFindHandler, nsIProtocolHandler);

NS_METHOD
nsFindHandler::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult) {

    nsFindHandler* ph = new nsFindHandler();
    if (ph == nsnull)
        return NS_ERROR_OUT_OF_MEMORY;
    NS_ADDREF(ph);
    nsresult rv = ph->QueryInterface(aIID, aResult);
    NS_RELEASE(ph);
    return rv;
}
    
////////////////////////////////////////////////////////////////////////////////
// nsIProtocolHandler methods:

NS_IMETHODIMP
nsFindHandler::GetScheme(nsACString &result) {
      result = "find";
      return NS_OK;
  }

NS_IMETHODIMP
nsFindHandler::GetDefaultPort(PRInt32 *result) {
    *result = FIND_PORT;
    return NS_OK;
}


NS_IMETHODIMP
nsFindHandler::NewURI(const nsACString &aSpec,
                         const char *aCharset, // ignore charset info
                         nsIURI *aBaseURI,
                         nsIURI **result) {
     
    

    const char* data;
    NS_CStringGetData(aSpec, &data);

    //Copy the whole url in pStr
    pStr = _strdup( data );


    //standard implementation
    //***********************************
     nsresult rv;
 
     nsIURI* url;
     rv = CallCreateInstance(kSimpleURICID, &url);
     if (NS_FAILED(rv)) return rv;
 
     rv = url->SetSpec(aSpec);
     if (NS_FAILED(rv)) {
         NS_RELEASE(url);
         return rv;
     }
 
     *result = url;
     return rv;
 }

//******************************************************
//function:- NewChannel
//This is the most important function 
//You'll have to return a Channel(pointer
//of nsIChannel, so that the protocol works
//******************************************************
NS_IMETHODIMP
nsFindHandler::NewChannel(nsIURI* aURI, nsIChannel* *result)
{


    nsCOMPtr<nsIServiceManager> servMan;
    nsresult rv=NS_GetServiceManager(getter_AddRefs(servMan));

    if(NS_FAILED(rv))
    {
        MessageBox(0,"Service Manager failed...","Err",0);
        return rv;
    }

    //Create a smart pointer to  nsIIOService
    nsCOMPtr<nsIIOService> ioser;
    
    rv=servMan->GetServiceByContractID("@mozilla.org/network/io-service;1",
                           NS_GET_IID(nsIIOService),getter_AddRefs(ioser));

    if(NS_FAILED(rv))
    {
        MessageBox(0,"IO failed....","err",0);
        return rv;
    }


    //We need to extract the search
    //term from the total typed url
    CBuildSearchString asStr;



    char  *strFinalURL;
    //get the final searching url
    asStr.BuildString (pStr,&strFinalURL);

    free( pStr );

        
    //create a new channel
    nsCOMPtr<nsIChannel> tempChannel;

    ioser->NewChannel(nsEmbedCString(strFinalURL),nsnull, 
                                       nsnull, getter_AddRefs(tempChannel));

    NS_ENSURE_TRUE (tempChannel, NS_ERROR_FAILURE);

    //Now the Channel is returned
    *result =tempChannel.get();

    NS_ADDREF(*result);

    delete [] strFinalURL;


    return NS_OK;
}

////////////////////////////////////////////////////////////////////////////////
 NS_IMETHODIMP 
 nsFindHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval)
 {
     if (port == FIND_PORT)
         *_retval = PR_TRUE;
     else
         *_retval = PR_FALSE;
     return NS_OK;
 }
 ////////////////////////////////////////////////////////////////////////////////
 NS_IMETHODIMP
  nsFindHandler::GetProtocolFlags(PRUint32 *result) {
      *result = URI_NORELATIVE | URI_NOAUTH | ALLOWS_PROXY;
      return NS_OK;
  }

大部分代码都可以重复用于您的自定义协议。

有四个区域可能需要自定义才能将此用于您的协议

  • GetScheme

    更改此项以返回协议使用的前缀。

  • GetDefaultPort

    更改此项以返回协议运行的默认端口。对于不使用端口的协议,可以返回 -1。此示例不使用任何端口,因此返回 -1。

  • NewURI

    此处使用 NS_SIMPLEURI_CID,它解析简单的 URL,例如没有路径的 URL。此函数获取整个输入的 URL。每当用户输入“find://<anything>”时,Firefox 就会调用此函数,字符串将作为第一个参数传递给此函数。代码如下:

    NS_IMETHODIMP
    nsFindHandler::NewURI(const nsACString &aSpec,
                             const char *aCharset, // ignore charset info
                             nsIURI *aBaseURI,
                             nsIURI **result) {
         
        const char* data;
        NS_CStringGetData(aSpec, &data);
    
        //Copy the whole url in pStr
        pStr = _strdup( data );
    
  • NewChannel

    您必须在此处返回一个通道,即 nsIChannel 接口的一个指针。这是来自 NewChannel 函数的代码。

    //create a new channel
        nsCOMPtr<NSICHANNEL> 
    
        tempChannel;ioser->NewChannel(nsEmbedCString(strFinalURL),nsnull, 
                                        nsnull, getter_AddRefs(tempChannel));
    
        NS_ENSURE_TRUE (tempChannel, NS_ERROR_FAILURE);
    
        //Now the Channel is returned
        *result =tempChannel.get();

您也可以实现 nsIChannel,就像finger 协议示例一样。此示例中还使用了另一个类 CBuildSearchString,用于从整个 URL 中提取搜索词并构建最终的 URL 字符串。

结论

我希望这个示例能帮助大家在准备 Mozilla Firefox 的协议时有所帮助。如果您有任何疑问,或者有任何需要,可以联系

致谢/鸣谢

  1. 感谢Brian Ryner先生,他实现了finger 协议。这是网上唯一一个使用 C++ 的示例协议。
  2. 感谢 Doron Rosenberg 先生,他用 JavaScript 简洁地实现了协议
  3. 感谢 Prasadarao 先生和 Dileep C. George 先生构建了 Mozilla Firefox。
© . All rights reserved.