接01。http://blog.youkuaiyun.com/binzhouweichao/article/details/8089115
2012.10.22 于济南
查找类WebCore::ResourceRequest,位置:src\3rdparty\webkit\Source\WebCore\platform\network\qt\ResourceRequest.h。
这里发现构造函数重载了,有很多,我们需要根据具体的调用时的入口参数来确定到底用了哪个构造函数。
调用语句:
WebCore::ResourceRequest request(url);
看到,对象request带有参数url,这个url的类型是QUrl,找到对应的构造函数的声明与定义初始化(放在一块了):
ResourceRequest(const KURL& url)
: ResourceRequestBase(url, UseProtocolCachePolicy)
{
}
应该就是这个了。可以看到类ResourceRequest继承于父类ResourceRequestBase。这里面就出现了一个问题,入口参数应该是QUrl类型的,这里却成了KURL类型,这两者之间的关系是什么?
KURL类位于位置:src\3rdparty\webkit\Source\WebCore\platform\KURL.h,网上说,此处暗含了QUrl到KURL类间的转换,到底什么意思我也看不懂,毕竟涉及到WebCore的东西,已经没有官方的技术文档了。
这个地方,对于ResourceRequest可以告一段落,要想深入了解,我们只能从其父类ResourceRequestBase来看了。
位置:src\3rdparty\webkit\Source\WebCore\platform\network\ResourceRequestBase.h。
根据入口参数,我们需要找对应的构造函数。
ResourceRequestBase(const KURL& url, ResourceRequestCachePolicy policy)
: m_url(url)
, m_cachePolicy(policy)
, m_timeoutInterval(s_defaultTimeoutInterval)
, m_httpMethod("GET")
, m_allowCookies(true)
, m_resourceRequestUpdated(true)
, m_platformRequestUpdated(false)
, m_reportUploadProgress(false)
, m_reportLoadTiming(false)
, m_reportRawHeaders(false)
, m_priority(ResourceLoadPriorityLow)
, m_targetType(TargetIsSubresource)
{
}
此构造函数自带了很多变量的初始化。同样,在对应的ResourceRequestBase.cpp中,有关于各变量、函数的定义及使用,如果后面需要用到这些东西,我们再去看。这里,我们仅需要知道,url为我们在load中输入的url,绝对的(absolute),不包含query等字符串;policy是UseProtocolCachePolicy。
下面我们再来看对类型为ResourceRequest的对象request进行的操作(继承于父类ResourceRequestBase,如果有些成员方法在类ResourceRequest中找不到,则直接去其父类中查找)。
来看qwebframe.cpp中的switch语句。在上一章节对load2的定位中,我们仅仅输入了url,并没有指定operation。而在load2的声明中,对operation和body都做了默认赋值,那么此处应该先分析默认值情况下的case,至于其他case,当程序运行过程中遇到时再来此处分析。
这样就只剩下了:
case QNetworkAccessManager::GetOperation:
request.setHTTPMethod("GET");
这样就将程序定位到了setHTTPMethod()。先到类ResourceRequest中查找,发现ResourceRequest.h头文件很简单,并没有定义其他的函数,那么再去ResourceRequestBase类中去查找。
//声明:
void setHTTPMethod(const String& httpMethod);
//定义:
void ResourceRequestBase::setHTTPMethod(const String& httpMethod)
{
updateResourceRequest();
m_httpMethod = httpMethod;
if (url().protocolInHTTPFamily())
m_platformRequestUpdated = false;
}
从定义看,首先是updateResourceRequest(),字面意思理解为更新本类的对象,来看具体的程序。
void ResourceRequestBase::updateResourceRequest() const
{
if (m_resourceRequestUpdated)
return;
ASSERT(m_platformRequestUpdated);
const_cast<ResourceRequest&>(asResourceRequest()).doUpdateResourceRequest();
m_resourceRequestUpdated = true;
}
m_resourceRequestUpdated是bool型变量,用于判断是否需要更新。每次更新完成都置为true,当需要更新的部件有所更新时,此值设为false。
ASSERT语句,人为加上编译器可能测不出来的错误。如果m_platformRequestUpdated为假时,程序中止,弹出报错界面;当为真时,执行下面的程序。
const_cast一行,首先,将asResourceRequest()强制转换非const,类型不变,然后调用ResourceRequest类成员函数doUpdateResourceRequest()。此函数是类ResourceRequest中为数不多的成员函数,其定义放于类内:
void doUpdateResourceRequest() {}
至此,发现此处的updateResourceRequest()具体意义不明,几乎是个空操作。
那么我们在返回去看看asResourceRequest()做了哪些操作。
inline const ResourceRequest& ResourceRequestBase::asResourceRequest() const
{
return *static_cast<const ResourceRequest*>(this);
}
类ResourceRequestBase的内联函数,const,类型为ResourceRequest引用。操作是,将此类(this,ResourceRequestBase)的对象强制转换成const ResourceRequest 指针类型,再返回这个指针的指针。。。。绕不过来了。就把这一系列操作当作对此类的对象的更新吧。告一段落。
对于updateResourceRequest()就先到这,下面来看setHTTPMethod()里面的下一条程序。
m_httpMethod = httpMethod;
此处我们可以使用“GET”直接替换掉httpMethod,此句就是一个简单的赋值,可能后面要用到m_httpMethod的值,根据具体的字符串来调用不同的函数,先放这。
再看下一条的if判断语句。需要说一个常识,做if判断时,其功能不仅仅是判断,还执行了判断语句中的内容,例如此处就是执行了url().protocolInHTTPFamily()。
我们先查找此类(ResourceRequestBase)中的url():
const KURL& ResourceRequestBase::url() const
{
updateResourceRequest();
return m_url;
}
看到,此函数是类ResourceRequestBase的成员函数,类型是KURL引用,也就是说,如果url()要调用成员方法,则此成员方法应该是KURL类中的。这个url()执行的操作也很简单,更新ResourceRequest对象,返回类型为KURL的m_url作为url()引用的值,用意未知。来看类KURL的成员函数protocolInHTTPFamily():
// FIXME: Remove this after changing all callers to use protocolIsInHTTPFamily.
bool protocolInHTTPFamily() const { return protocolIsInHTTPFamily(); }
又跳!定义放在了类内,所以要在KURL.h才能找到。再看protocolIsInHTTPFamily():
inline bool KURL::protocolIsInHTTPFamily() const
{
return m_protocolIsInHTTPFamily;
}
。。。再来找m_protocolIsInHTTPFamily:
bool m_protocolIsInHTTPFamily : 1;
初始化是置1的,其值在两个地方被修改,一个是KURL的invalidate()函数中,将此值置为false,另一个就是在KURL::parse()中添加了url头“http:”或“https:”:
m_protocolIsInHTTPFamily = isLetterMatchIgnoringCase(url[0], 'h')
&& isLetterMatchIgnoringCase(url[1], 't')
&& isLetterMatchIgnoringCase(url[2], 't')
&& isLetterMatchIgnoringCase(url[3], 'p')
&& (url[4] == ':' || (isLetterMatchIgnoringCase(url[4], 's') && url[5] == ':'));
现在我们知道,url().protocolInHTTPFamily()操作,要么返回false,要么将url置头为“http:”或“https:”。当返回false时,函数setHTTPMethod()到此就结束了;当返回“http:”或“https:”时,执行if下面的操作m_platformRequestedUpdated = false,目测跟updateResourceRequest类似,设为false说明在更新程序中执行更新。
这里,我们对对象request的成员setHTTPMethod()做一个小节:
1.按字面意思,设置了request的成员变量m_httpMethod = httpMethod,也就是:request.m_httpMethod = "GET"。
2.隐含操作,将url前5(6)个字符设为"http:"("https:"),但是这里仍然有个问题,就是QUrl与KURL是如何转换的。KURL有三个构造函数,但都有url输入,每个也都调用了parse函数给url加http头,难道是在转换的时候,最基本的操作就是将QUrl类型的url加上了http:头作为了KURL?
带着这些疑问,又去类ResourceRequestBase的构造函数看了一下,发现一开始就有个m_url = url 初始化操作,而这个m_url就是KURL类型。然后发现对m_url的操作也很多,最后还有返回m_url的操作,如果有必要,我们再分析对这个m_url进行的一系列操作。
下面再分析qwebframe.cpp中,load2的其他操作。
本文详细解读了WebCore::ResourceRequest类的构造函数重载及其内部操作,包括对象初始化、HTTP方法设置、URL处理过程,以及与QUrl到KURL类转换的实现方式。
1万+

被折叠的 条评论
为什么被折叠?



