Qt-Function-QWebFrame->load()_01

来源:互联网 发布:百度域名被劫持 编辑:程序博客网 时间:2024/06/16 01:20

前面只发布了QWebView的代码,并没有具体的解释过load()函数。在这里补充上。

2012.10.19 于济南

先贴上两个load的源码,分别命名为load1、load2,方便下文论述:

load1:

void QWebFrame::load(const QUrl &url){    // The load() overload ensures that the url is absolute.    load(QNetworkRequest(url));}

load2:

void QWebFrame::load(const QNetworkRequest &req,                     QNetworkAccessManager::Operation operation,                     const QByteArray &body){    if (d->parentFrame())        d->page->d->insideOpenCall = true;    QUrl url = ensureAbsoluteUrl(req.url());    WebCore::ResourceRequest request(url);    switch (operation) {        case QNetworkAccessManager::HeadOperation:            request.setHTTPMethod("HEAD");            break;        case QNetworkAccessManager::GetOperation:            request.setHTTPMethod("GET");            break;        case QNetworkAccessManager::PutOperation:            request.setHTTPMethod("PUT");            break;        case QNetworkAccessManager::PostOperation:            request.setHTTPMethod("POST");            break;        case QNetworkAccessManager::DeleteOperation:            request.setHTTPMethod("DELETE");            break;        case QNetworkAccessManager::CustomOperation:            request.setHTTPMethod(req.attribute(QNetworkRequest::CustomVerbAttribute).toByteArray().constData());            break;        case QNetworkAccessManager::UnknownOperation:            // eh?            break;    }    QVariant cacheLoad = req.attribute(QNetworkRequest::CacheLoadControlAttribute);    if (cacheLoad.isValid()) {        bool ok;        uint cacheLoadValue = cacheLoad.toUInt(&ok);        if (ok)            request.setCachePolicy(cacheLoadControlToCachePolicy(cacheLoadValue));    }    QList<QByteArray> httpHeaders = req.rawHeaderList();    for (int i = 0; i < httpHeaders.size(); ++i) {        const QByteArray &headerName = httpHeaders.at(i);        request.addHTTPHeaderField(QString::fromLatin1(headerName), QString::fromLatin1(req.rawHeader(headerName)));    }    if (!body.isEmpty())        request.setHTTPBody(WebCore::FormData::create(body.constData(), body.size()));    d->frame->loader()->load(request, false);    if (d->parentFrame())        d->page->d->insideOpenCall = false;}

先看load1的内容。入口形参为const QUrl url,对于形参使用const定义,是为了在程序中不修改此形参的值,只使用此值,简单的说,这种形参就是输入参数,运行完此段程序,此形参的值并不发生变化。那么使用此url做了些什么呢?可以看到此函数只有一行,load(QNetworkRequest (url));,调用了此类(QWebFrame)中的一个load()函数。在C++中,可以根据入口形参类型及个数等自动匹配重载函数。那么我们需要知道这个入口形参的类型是否跟下面的load2的形参类型相同,也就是:这个load()是否就是调用的下文形参较多的那个load()。

为了查找实参类型,我们需要找到QNetworkRequest,位于src/network/access/目录中,qnetworkrequest.cpp。

QNetworkRequest::QNetworkRequest(const QUrl &url)    : d(new QNetworkRequestPrivate){    d->url = url;}QNetworkRequest::QNetworkRequest(const QNetworkRequest &other)    : d(other.d){}

可以看到,类QNetworkRequest有两个构造函数,重载了。对应于我们调用的这个,匹配的是第一种,入口形参为url的那个。

我们看到,第一个构造函数,自带初始化d = new QNetworkRequestPrivate。类QNetworkRequestPrivate是类QNetworkRequest的友元类,位于此cpp文件的上方,类的构造函数的定义放在了类的声明内部,看起来比较长。而d就是此类的一个实例,通过d的初始化可以看出来,也可以去qnetworkrequest_p.h中去看。此类中就定义了一个QUrl类型的url变量。所以就有了上述d->url = url;语句。

上面寻找qnetworkrequest的步骤比较多余。。。

我们知道,构造函数是没有返回类型的,那么通过构造函数,运行出来的是什么呢?其实对于load1,我们可以这样写:

QNetworkRequest *myInstance;myInstance = new QNetworkRequest(url);load(myInstance);

看出来了吧,构造函数运行出来的,就是这个类的实例,只不过没有具体的名字而已。通过这里,我们就可以看出了,load1的入口形参就是一个类型为QNetworkRequest的变量,正好对应于load2的第一个形参类型。我们知道,在C++中,实参的个数可以少于形参,前提是多出来的形参有默认的赋值,我们来看一下load2的声明:

void load(const QNetworkRequest &request,              QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,              const QByteArray &body = QByteArray());

可以看到,除了第一个参数外,后面两个形参均已经赋了默认值,这样在调用的时候,后两个参数就可以省略不写了,符合C++的语法规范。

从上面的叙述中,我们就可以确定,load1中调用的load(),就是load2。下面我们只要分析load2就行了。

函数一开始,又出现了d,综合多个类(像QWebFrame、QWebPage、QNetworkRequest等)来看,d是每个类友元类(类名+Private)的实例,仅限类内部调用,私有,不是全局变量。例如在类QWebFrame中,调用QWebPagePrivate的d,需要:d->page->d->...,其中page是QWebFrame中的成员变量,类型为QWebPage。关于这里出现的if操作,就先跳过了。

语句:QUrl url = ensureAbsoluteUrl(req.url());

先看这个函数ensureAbsoluteUrl(),字面意思可以看出:确保绝对Url。这需要先了解一下http协议的知识。http/1.1 中规定,浏览器所请求资源(URL)的确定可以有四种方式,其中一种就是由Request-URI直接确定,叫做绝对URI。看看这两者之间是否有联系。F2找到函数定义:

static inline QUrl ensureAbsoluteUrl(const QUrl &url){    if (!url.isValid() || !url.isRelative())        return url;    // This contains the URL with absolute path but without     // the query and the fragment part.    QUrl baseUrl = QUrl::fromLocalFile(QFileInfo(url.toLocalFile()).absoluteFilePath());     // The path is removed so the query and the fragment parts are there.    QString pathRemoved = url.toString(QUrl::RemovePath);    QUrl toResolve(pathRemoved);        return baseUrl.resolved(toResolve);}

这个函数的作用是:如果url不是relative的(relative就是没有http://的网址),则返回此url;换句话说,如果url是绝对的(absolute),则不对此url做其他操作,直接返回此url。至于valid与下面的其他操作暂时先不讨论,目测就是没有http时就给加上。

再看load2的下一条语句:

WebCore::ResourceRequest request(url);

需要找到这个类,位置:src\3rdparty\webkit\Source\WebCore\platform\network\qt\ResourceRequest.h。



原创粉丝点击