浏览器探究——webkit部分——http响应

来源:互联网 发布:龙瞎皮肤淘宝 编辑:程序博客网 时间:2024/05/31 19:46

http://blog.csdn.net/hxwwf/article/details/7322120


浏览器探究——webkit部分——http响应

首先回忆下http发送的位置,在ResourceHandle::start中使用静态函数ResourceLoaderAndroid::start进行发送。这里创建了WebUrlLoader,它有个成员WebUrlLoadClient类,这个类有主要成员,WebFrame,WebCore::ResourceHandle,WebRequest,WebResponse。其中WebCore::ResourceHandle就是webkit中关于网络的平台无关的负责回调的类。而WebUrlLoader是android下平台相关的,最终的http的请求的发送会通过WebUrlLoadClient调用的chromium中的net部分进行发送。那么接收则也是从它开始的。

第一个收到的回调是voidWebUrlLoaderClient::didReceiveResponse(PassOwnPtr<WebResponse> webResponse)

看下调用栈情况:

#0android::WebUrlLoaderClient::didReceiveResponse

#1 DispatchToMethod

#2 RunnableMethod

#3 RunTask

#4WTF::dispatchFunctionsFromMainThread

#5 timeoutFired

#6android::JavaSharedClient::ServiceFunctionPtrQueue

#7 android::JavaBridge::ServiceFuncPtrQueue

#8 dvmPlatformInvoke

#9 dvmCallJNIMethod

#10dvmCheckCallJNIMethod

#11 dalvik_mterp

#12 dvmInterpret

#13 dvmCallMethodV

#14 dvmCallMethod

#15 interpThreadStart

#16 __thread_entry

#17 pthread_create

WebUrlLoaderClient::didReceiveResponse

先把接收到的WebResponse赋值给WebUrlLoaderClient的成员m_response。

接下来通过它的成员ResourceHandle的成员ResourceHandleClient的didReceiveResponse。

ResourceHandle的ResourceHandleClient是什么?是个接口类,定义了一些回调的接口,让ResourceHandle可以回调继承自ResourceHandleClient的类的didXXX回调函数。在ResourceHandle构造时,就会有参数ResourceHandleClient传入,并被记录在ResourceHandle中,供将来ResourceHandle回调时使用。也就是说创建ResourceHandle时,传入的ResourceHandleClient。那么ResourceHandle是在哪里创建的?接http发送那文,则是MainResourceLoader::loadNow中创建的。看下哪里,发现ResourceHandleClient其实就是MainResourceLoader。ResourceLoader继承了ResourceHandleClient接口,而MainResourceLoader又是ResourceLoader的子类。

由此可见ResourceHandle通过ResourceHandleClient的成员来执行回调操作,也就是执行了MainResourceLoader的回调函数。

另外说一下WebResponse::createResourceResponse函数可以利用WebResponse生成一个ResourceResponse。

回到WebUrlLoaderClient::didReceiveResponse,如上所述,该函数会通过WebUrlLoaderClient::m_resourceHandle找到ResourceLoader的didReceiveResponse。并把ResourceHandle和ResourceResponse作为参数传入。

ResourceLoader:: didReceiveResponse (ResourceHandle*, constResourceResponse&);

注意这里跟上述的不同,不是MainResourceLoader。原因是这样的,MainResourceLoader只继承了didReceiverResponse(const ResourceResponse&);回调接口,并没有继承双参数的。ResourceHandle参数只是先做一个判断的处理,貌似作为离线的一个处理。之后才会调用MainResourceLoader重写的方法didReceiverResponse(const ResourceResponse&);

MainResourceLoader:: didReceiverResponse(constResourceResponse& r)

参数ResourceResponse会设置给DocumentLoader的m_response(不是数组那个哦),还会设置给MainResourceLoader的m_response。回顾下,MainResourceLoader是DocumentLoader创建的。

之后做了一套Policy的一些检查机制,这里跨过不细看。

然后会调用到MainResourceLoader::continueAfterContentPolicy

在这个函数里,会又做一些Policy的处理后,调用到基类ResourceLoader的didReceiveResponse(const ResourceResponse& r)

ResourceLoader:: didReceiveResponse(constResourceResponse& r)

在这个函数里又设置了ResourceResponse给m_response,然后通过Frame找到FrameLoader,通过FrameLoader找到ResourceLoadNotifier,然后调用ResourceLoadNotifier的didReceiveResponse

看下调用栈情况:

#0 WebCore::ResourceLoadNotifier::didReceiveResponse

#1 WebCore::ResourceLoader::didReceiveResponse

#2 WebCore::MainResourceLoader::continueAfterContentPolicy

#3 WebCore::MainResourceLoader::continueAfterContentPolicy

#4 WebCore::MainResourceLoader::callContinueAfterContentPolicy

#5 WebCore::PolicyCallback::call

#6WebCore::PolicyChecker::continueAfterContentPolicy

#7 android::FrameLoaderClientAndroid::dispatchDecidePolicyForResponse

#8WebCore::PolicyChecker::checkContentPolicy

#9 WebCore::MainResourceLoader::didReceiveResponse

#10WebCore::ResourceLoader::didReceiveResponse

#11 android::WebUrlLoaderClient::didReceiveResponse

经过一层层的回调,终于到了ResourceLoadNotifier处了,其实回调的总体脉络并不乱,但是中间添加了很多这个Policy的处理。

ResourceLoadNotifier::didReceiveResponse

这里传入的参数是ResourceLoader和ResourceResponse。首先把ResourceResponse设置进DocumentLoader的ResourceResponse的数组里。之后通过Frame找到Page,然后调用如下语句page->progress()->incrementProgress(loader->identifier(),r);

也就是,到这里,回调已经达到了界面相关的地方,可以通知进度信息了。

之后调用个ResourceLoadNotifier::dispatchDidReceiveResponse,把回调又做了一次转发。

ResourceLoadNotifier::dispatchDidReceiveResponse

通过Frame找到FrameLoader,再找到FrameLoaderClient,这里是FrameLoaderClientAndroid。调用它的dispatchDidReceiveResponse,此处是空实现,即它把回调又一次发给可能需要的,平台相关的,一个FrameLoaderClient类。最后又调用InspectorInstrumentation的didReceiveResourceResponse。这个InspectorInstrumentation中的回调貌似是调试用的。

可见在ResourceLoadNotifier中会将回调的信息发给UI层,发给平台相关的FrameLoaderClient,发给调试类。即几个期望的到回调信息的类。

通过以上的回调情况大致可以看到如下的流程。

最先得到回调的是WebUrlLoaderClient的didXXX,它是从chromium的net相关接口处被回调的。

然后通过ResourceHandle找到ResourceHandleClient,这里即MainResourceLoader,调用他的回调didXXX。

MainResourceLoader是继承自ResourceLoader,MainResourceLoader会进一步调用基类ResourceLoader的didXXX。

ResourceLoader会通过Frame->FrameLoader->ResourceLoadNotifier。调用到ResourceLoadNotifier的didXXX。

ResourceLoadNotifier中会把将回调的信息发给UI层,发给平台相关的FrameLoaderClient,发给调试类。

在其他的几个http的相应回调中,大体的流程也是如此的。

接下来可以看下ReceiveData的调用栈:

#0 WebCore::ResourceLoadNotifier::didReceiveData

#1 WebCore::ResourceLoader::didReceiveData

#2 WebCore::MainResourceLoader::didReceiveData

#3 WebCore::ResourceLoader::didReceiveData

#4android::WebUrlLoaderClient::didReceiveData

#5DispatchToMethod

#6 RunnableMethod

#7 RunTask

……

最后再看下FinishLoad的调用栈:

#0 WebCore::ResourceLoadNotifier::didFinishLoad

#1 WebCore::ResourceLoader::didFinishLoadingOnePart

#2WebCore::ResourceLoader::didFinishLoading

#3 WebCore::MainResourceLoader::didFinishLoading

#4 WebCore::ResourceLoader::didFinishLoading

#5 android::WebUrlLoaderClient::didFinishLoading

#6 DispatchToMethod

#7 RunnableMethod

#8 RunTask

至此一个http请求完毕。注意这里并没有看资源(图片,CSS,JS等)的加载情况。

To be continued......