在移植gecko的时候发现一些问题,比如gecko连alert对话框这种基本的控件都没有默认实现,包括b2g,在firefox os(那个ui叫gaia)中是纯粹地用html实现的。起初觉得把gaia的的代码,拷过来点就是了,后来发现gaia写得有点复杂,会产生很多依赖,还不如直接用native的控件来实现。做法是参考android的firefox,用js处理部分逻辑,gui相关部分用java,就会产生js调java的需求。我是要js调c++,做法差不多。
android中有一个叫AndroidBridge的类,把它注册为一个service,js就调用这个类的handleGeckoMessage()方法。这里简单介绍下操作步骤
1. widget/YOUR_OS/nsINativeBridge.idl
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" [scriptable, uuid(0e93d8f4-5392-48bc-9f4d-3a151773b14c)] interface nsINativeBridge : nsISupports { AString handleGeckoMessage(in AString message); };
XPIDLSRCS = \ nsINativeBridge.idl
3.加入nsNativeBridge.h和nsNativeBridge.cpp。其实在idl生成的头文件的注释里包含了如何写这些文件的方法,稍微改改就行
widget/YOUR_OS/nsNativeBridge.h:
#ifndef nsNativeBridge_h__ #define nsNativeBridge_h__ #include "nsINativeBridge.h" #define NS_NATIVEBRIDGE_CID \ { 0x6a63ba66, 0xc72f, 0x431f, \ { 0xb9, 0x7d, 0x42, 0x0b, 0xa5, 0xde, 0x19, 0xf5 } } class nsNativeBridge : public nsINativeBridge { public: NS_DECL_ISUPPORTS NS_DECL_NSINATIVEBRIDGE nsNativeBridge(); private: ~nsNativeBridge(); protected: }; #endif
/* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsNativeBridge.h" #include "nsDOMClassInfoID.h" NS_IMPL_ISUPPORTS1(nsNativeBridge, nsINativeBridge) nsNativeBridge::nsNativeBridge() { } nsNativeBridge::~nsNativeBridge() { } /* void handleGeckoEvent (in AString message); */ NS_IMETHODIMP nsNativeBridge::HandleGeckoMessage(const nsAString & message, nsAString &aRet) { nsCString cMessage = NS_ConvertUTF16toUTF8(message); aRet = NS_ConvertUTF8toUTF16(gGeckoAppShellFuncs->handleGeckoMessage(cMessage.get())); return NS_OK; }
其中HandleGeckoMessage就是对应与idl中的handleGeckoMessage。这里我们吧message交给其他函数处理。作为测试,你可以在这里打印写东西
在nsWidgetFactory.cpp中注册.
加上
#include "nsNativeBridge.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeBridge) NS_DEFINE_NAMED_CID(NS_NATIVEBRIDGE_CID);在 static const mozilla::Module::CIDEntry kWidgetCIDs[] 加上
{ &kNS_NATIVEBRIDGE_CID, false, NULL, nsNativeBridgeConstructor },
在static const mozilla::Module::ContractIDEntry kWidgetContracts[]加上
{ "@mozilla.org/native/bridge;1", &kNS_NATIVEBRIDGE_CID },
在js中调用nsNativeBridge就是通过上面的contract id
4. 在Makefile.in中加上新增的cpp
比如
const Cc = Components.classes; let data = Cc["@mozilla.org/native/bridge;1"].getService(Ci.nsINativeBridge).handleGeckoMessage(JSON.stringify({ gecko: aMsg }));
注:这里js是gecko启动时调用的那些js,比如核心的shell.js,用户使用的js直接用js扩展好了