以image为例解析image资源的加载过程:
1. HTMLImageElement被创建时在构造函数HTMLImageElement()中将HTMLImageElement对象传递给HTMLImageLoader创建出m_imageLoader
2. 第一次页面初始化时或者image的src属性发生改变时会调用HTMLImageElement的parseMappedAttribute方法
3. parseMappedAttribute判断attrName ==srcAttr则调用m_imageLoader.updateFromElementIgnoringPreviousError();
4. 进而调用HTMLImageLoader基类ImageLoader中的updateFromElement方法
5. 在updateFromElement中用下面这句话向CachedResourceLoader申请CachedImage对象
newImage =document->cachedResourceLoader()->requestImage(sourceURI(attr));
CachedResourceLoader会更具缓存的情况,从MemoryCache中找到之前的资源,如果没有Cache可用则调用loadResource创建新的CachedResource对象。
6. loadResource并非只是创建CachedResource对象,并且调用CachedResource的load方法,并传递CachedResourceLoader对象,一个参数的load再调用4个参数load
1.resource->load(this);
2.virtual voidload(CachedResourceLoader* cachedResourceLoader) { load(cachedResourceLoader, false,DoSecurityCheck, true); }
void load(CachedResourceLoader*, bool incremental, SecurityCheckPolicy,bool sendResourceLoadCallbacks);
3.void CachedResource::load(CachedResourceLoader*cachedResourceLoader, bool incremental, SecurityCheckPolicy securityCheck, boolsendResourceLoadCallbacks)
{
m_sendResourceLoadCallbacks =sendResourceLoadCallbacks;
cachedResourceLoader->load(this,incremental, securityCheck, sendResourceLoadCallbacks);
m_loading = true;
}
又调用回CachedResourceLoader对象的load方法,这个CachedResourceLoader和创建CachedResource的是同一个对象,
voidCachedResourceLoader::load(CachedResource* resource, bool incremental,SecurityCheckPolicy securityCheck, bool sendResourceLoadCallbacks)
{
incrementRequestCount(resource);
RefPtr<CachedResourceRequest> request= CachedResourceRequest::load(this, resource, incremental, securityCheck,sendResourceLoadCallbacks);
if (request)
m_requests.add(request);
}
没弄明白为什么要这么做。
7. CachedResourceLoader的load方法调用CachedResourceRequest的静态方法load并将CachedResourceLoader对象传入,创建CachedResourceRequest对象,
8. 调用ResourceLoaderScheduler::scheduleSubresourceLoad创建SubresourceLoader对象
9. 调用ResourceLoaderScheduler的scheduleLoad方法将SubresourceLoader加入清单列表中,并设置优先级别,如果优先级足够高就调用servePendingRequests开始下 载
10. 调用 ResourceLoader::start
11. 调用 ResourceHandle::create创建ResourceHandle并调用ResourceHandle的start方法
12. 如果是android平台调用的就是ResourceHandleAndroid.cpp中的ResourceHandle::start方法,再调用ResourceLoaderAndroid::start
13. WebUrlLoader::start 创建WebUrlLoader和WebUrlLoaderClient,在WebUrlLoaderClient中则会创建WebRequest
14. WebUrlLoaderClient的start方法,这里会根据同步或异步作不同的处理,异步同步模式中都会创建NewRunnableMethod将WebRequest的start加入线程中运行,只是同步模式会等待完成后才退出函数
15 WebRequest的start会调用m_request的start方法,m_request是net::URLRequest对象,这个对象已经不是webkit中的对象,是chromium中的对象。
16. 从这里开始就是chromium的流程了
17. Chromium接收到数据后调用ResourceLoader的didReceiveResponse
和didReceiveData,将数据交给SubresourceLoader CachedResourceRequest 处理。
18. 接收完数据后,回到ImageLoader的流程中,从CachedResourceLoader中申请到CachedImage对象后,
对比是否是新的对象,并做初始化处理,如下:
CachedImage* oldImage = m_image.get();
if (newImage != oldImage) {
if (!m_firedBeforeLoad)
beforeLoadEventSender().cancelEvent(this);
if (!m_firedLoad)
loadEventSender().cancelEvent(this);
m_image = newImage;
m_firedBeforeLoad = !newImage;
m_firedLoad = !newImage;
m_imageComplete = !newImage;
if (newImage) {
newImage->addClient(this);
if(!m_element->document()->hasListenerType(Document::BEFORELOAD_LISTENER))
dispatchPendingBeforeLoadEvent();
else
beforeLoadEventSender().dispatchEventSoon(this);
}
if (oldImage)
oldImage->removeClient(this);
}
18. 最后一步调用renderImageResource渲染