WebKit 学习笔记(5) -- qt javascript 扩展

在 QT 目录中打开下面的文件:
/src/3rdparty/webkit/JavaScriptCore/bindings/runtime.cpp

有下面几行:

#if PLATFORM(QT)
        case Instance::QtLanguage: {
            newInstance = Bindings::QtInstance::getQtInstance((QObject *)nativeInstance, rootObject);
            break;
        }
#endif

这就表明,可以用 QtLanguage 来编写自定义的 javascript 对象。这里也有几个别的 Language,也就是说可以用它们来编写扩展 javascript 对象,应该也能自定义自己的 Language。既然是用 qt 的 GUI,使用 QtLanguage 应该是最合适的。

先打开它的例子文件:
/src/3rdparty/webkit/JavaScriptCore/bindings/testqtbindings.cpp

可以看到其中有这样几行:

static char code[] =
    "myInterface.foo();/n"
    "myInterface.testString = /"Hello/";/n"
    "str = myInterface.testString;/n"
    "myInterface.testInt = 10;/n"
    "i = myInterface.testInt;/n";

这就是说,testqtbindings.cpp 的内容可以对下面的 javascript 进行解析:

myInterface.foo();
myInterface.testString = "Hello";
var str = myInterface.testString;
myInterface.testInt = 10;
var i = myInterface.testInt;

我想定义自己的 javascript,比如在 myInterface 对象前面加上一个 CSDN 对象:

CSDN.myInterface.foo();
CSDN.myInterface.testString = "Hello";
var str = CSDN.myInterface.testString;

这件事情本来很简单,可是就象 CSDN.myInterface.foo() 这样,连接 CSDN 和 myInterface 两个对象的事情,在网上(中文和英文网站)找了半天没找着,结果还是我自己想到的。

1. 在原来的文件中再添加一个 MyCSDNObject 对象:

class MyCSDNObject : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString testString READ testString WRITE setTestString)
    Q_PROPERTY(int testInt READ testInt WRITE setTestInt)
 // 添加 QObject 成员作为 CSDN 对象的属性,映射到 testMyInterface 函数上
 Q_PROPERTY(QObject* myInterface READ testMyInterface)

public:
    MyCSDNObject() : QObject(0), integer(0), m_myObject(NULL){}

    void setTestString(const QString &str) {
        qDebug() << "called setTestString" << str;
        string = str;
    }
    void setTestInt(int i) {
        qDebug() << "called setTestInt" << i;
        integer = i;
    }
    QString testString() const {
        qDebug() << "called testString" << string;
        return string;
    }
    int testInt() const {
        qDebug() << "called testInt" << integer;
        return integer;
    }
 // 在这里返回一个 QObject 对象
 QObject *testMyInterface()
 {
  if (m_myObject == NULL)
   m_myObject = new MyObject();
  return m_myObject;
 }
    QString string;
    int integer;
 // 声名一个 QObject 对象
 MyObject *m_myObject;

public slots:
    void foo() { qDebug() << "foo invoked"; }
};


这样 MyCSDNObject 和 MyObject 这样两个对象就可以连起来了,成为 CSDN.testMyInterface


2. 修改一下创建的根对象的名字

global->put(exec, Identifier("CSDN"), Instance::createRuntimeObject(Instance::QtLanguage, (void*)myObject));

 
这样就可以了。这是个测试程序,需要把这些测试代码添加到 WebKit 浏览器中。打开文件:
./src/3rdparty/webkit/WebKit/qt/Api/qwebframe.h
把刚才的 MyObject 类和 MyCSDNObject 类在其中声名一下,然后添加 CSDN 根对象作为 QWebFrame 类的私有成员,如下所示:

class MyObject : public QObject
{
    Q_OBJECT
   // 省略 ...
};

class MyCSDNObject : public QObject
{
    Q_OBJECT   
    // 省略 ...
};

class QWEBKIT_EXPORT QWebFrame : public QObject
{
    Q_OBJECT
    Q_PROPERTY(qreal textSizeMultiplier READ textSizeMultiplier WRITE setTextSizeMultiplier)
    Q_PROPERTY(QString title READ title)
    Q_PROPERTY(QUrl url READ url WRITE setUrl)
    Q_PROPERTY(QIcon icon READ icon)
    Q_PROPERTY(QSize contentsSize READ contentsSize)
private:
    QWebFrame(QWebPage *parent, QWebFrameData *frameData);
    QWebFrame(QWebFrame *parent, QWebFrameData *frameData);
    ~QWebFrame();

    // 声名 CSDN 根对象
    MyCSDNObject *m_csdn;

    public:
  // 以下省略 ...
};


打开 qwebframe.cpp 文件,在 QWebFrame 的构造函数中创建 CSDN 根对象。

QWebFrame::QWebFrame(QWebPage *parent, QWebFrameData *frameData)
    : QObject(parent)
    , d(new QWebFramePrivate)
{
    d->page = parent;
    d->init(this, parent->d->page, frameData);

    // 在这里创建 CSDN 根对象
    {
    KJS::Bindings::RootObject *root = d->frame->bindingRootObject();
    KJS::ExecState *exec = root->interpreter()->globalExec();
    KJS::JSObject *global = root->interpreter()->globalObject();

    m_csdn = new MyCSDNObject();
    global->put(exec, KJS::Identifier("CSDN"), KJS::Bindings::Instance::createRuntimeObject(KJS::Bindings::Instance::QtLanguage, (void *)m_csdn, root));
    }

    if (!frameData->url.isEmpty()) {
        ResourceRequest request(frameData->url, frameData->referrer);
        d->frame->loader()->load(request, frameData->name);
    }
}

 在 QWebFrame 的析构函数中删除 CSDN 根对象

QWebFrame::~QWebFrame()
{
    if (d->frame && d->frame->loader() && d->frame->loader()->client())
        static_cast(d->frame->loader()->client())->m_webFrame = 0;

	if (m_csdn)
	{
		delete m_csdn;
		m_csdn = NULL;
	}
    delete d;
}

再手工编写一个 HTML 测试页 csdn1.htm,内容如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> New Document </title>
<script language="JavaScript">
<!--
function test()
{
 CSDN.myInterface.foo();
 CSDN.myInterface.testString = "Hello QtWebKit JavaScript";
 var str = CSDN.myInterface.testString;
 document.getElementById("txtMessage").innerHTML = str;
}
//-->
</script>
</head>

<body>
<p><a href="javascript:test();">test qt-webkit javascript</a></p>
<p id="txtMessage"></p>
</body>
</html>

编译并运行 WebKit 浏览器,让它打开刚才的测试页 csdn1.htm,点击上面的 test qt-webkit javascript 链接,可以得到下面的效果:

上面的 Hello QtWebKit JavaScript 就是 javascript 设置的 CSDN.myInterface.testString 内容。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值