首先回忆下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......