webkit加载网页

一、读取url





以下内容部分引自 http://blog.csdn.net/dlmu2001/article/details/5936122
http的协议细节实现并不需要WebCore来关注,WebCore要关注的是,如何设置请求的相关头部信息,如何获取服务器返回回来的响应体部数据。
WebKit中同http打交道的类主要是ResourceRequest,ResourceResonse,ResourceHandle*,ResourceHandleManager等,这里先介绍同请求信息维护相关的ResourceRequest.
ResourceRequest类的作用比较好理解,基本上就是维护http请求相关的信息(app或者内核都有可能设置这些信息),然后当WebCore发起http请求的时候,可以获取这些信息,调用curl的接口设置对应的http请求字段。在这些信息中,最常用到的是url。
ResourceRequest类继承于ResourceRequestBase类,绝大部分功能在ResourceRequestBase类中实现。
一)ResourceRequest构造:构造一个ResourceRequest对象只需要url参数就够了,这是比较简单的一个类,没有维护其它类的对象或者句柄。
ResourceRequest(const String& url);
ResourceRequest(const KURL& url);
二)ResourceRequest对象的创建与维护
1.当用户输入网址,触发qt事件,由 MainWindow(WebKitBuild/Debug/QtTestBrowser/moc_mainwindow.cpp:87<--moc_launcherwindow.cpp:145) 调用 changeLocation 函数(另有 openLocation 等)。
MainWindow(Tools/QtTestBrowser/mainwindow.cpp:194) 获取地址栏中的url( QString类型/usr/include/QtCore/qstring.h ),创建QUrl类型( /usr/include/QtCore/qurl.h url规格化类,包括host、port、scheme等成员变量 ),加载页面( page()->mainFrame()->load(url) page()函数是全局函数? )。

最终调用 QWebFrame::load (Source/WebKit/qt/Api/qwebframe.cpp:885)函数,在该函数中,会构造出ResourceRequest( Source/WebCore/platform/network/qt/ResourceRequest.h 继承ResourceRequestBase Source/WebCore/platform/network/ResourceRequestBase.cpp )对象,并将这个对象作为一个参数,调用 FrameLoader 对象的load函数( Source/WebCore/loader/FrameLoader.cpp:1450 )。

FrameLoader类负责将documents加载到Frames。当你点击一个链接的时候,FrameLoader创建一个新的处于”policy”状态的DocumentLoader对象,等待WebKit客户端决定是否处理这个加载。通常WebKit客户端会指示FrameLoader将这个加载视为一个导航(navigation),而不是阻止加载等。

DocumentLoader 类中会维护这个ResourceRequest( FrameLoader.cpp :1460), policyChecker()
——>checkNavigationPolicy(
Source/WebCore/loader/FrameLoader.cpp:1585)
1585         policyChecker()->checkNavigationPolicy(loader->request(), loader, formState,
1586              callContinueLoadAfterNavigationPolicythis);// 回调函数?如下调用

——> m_frame->loader()->client()->dispatchDecidePolicyForNavigationAction(Source/WebCore/loader/PolicyChecker.cpp:87)
 84     m_callback. set(request, formState. get(),  function, argument);// callContinueLoadAfterNavigationPolicy


一旦客户端指示FrameLoader将本次加载视为一个导航,FrameLoader就推动DocumentLoader进入”provisional”状态,在该状态,DocumentLoader会发起一个网络请求,并等待以确定网络请求将发起一个下载还是一个新的document。
——>page->d->acceptNavigationRequestSource/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp:1271)
        callPolicyFunction(Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp:1283)
        回调函数?如上
         //——>(m_frame->loader()->policyChecker()->*function)(action) (245)
——>callback.call(Source/WebCore/loader/PolicyChecker.cpp:160)
——>m_navigationFunction(Source/WebCore/loader/PolicyCallback.cpp:103)
——>loader->continueLoadAfterNavigationPolicy(Source/WebCore/loader/FrameLoader.cpp:2977)

2974  void FrameLoader::callContinueLoadAfterNavigationPolicy( void* argument,
2975      const ResourceRequest& request, PassRefPtr<FormState> formState,  bool shouldContinue)
2976  {
2977     FrameLoader* loader = static_cast<FrameLoader*>(argument);
2978     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
2979 }

——>continueLoadAfterWillSubmitForm(Source/WebCore/loader/FrameLoader.cpp:3105)
——>m_provisionalDocumentLoader->startLoadingMainResource(Source/WebCore/loader/FrameLoader.cpp:2572)

接下去,DocumentLoader会创建一个MainResourceLoader对象,这个对象主要用来通过ResourceHandle接口同平台网络库进行交互。将MainResourceLoader和DocumentLoader分开来主要有两个目的:(1)MainResourceLoader让DocumentLoader从处理ResourceHandle回调的细节中抽身出来(2)降低MainResourceLoader的生命周期和DocumentLoader的生命周期(同Document绑定)的耦合度。

——>m_mainResourceLoader->load(Source/WebCore/loader/DocumentLoader.cpp:798)
——>loadNow(Source/WebCore/loader/MainResourceLoader.cpp:612)
——>ResourceHandle::create(Source/WebCore/loader/MainResourceLoader.cpp:585)
——>newHandle->start(Source/WebCore/platform/network/ResourceHandle.cpp:71)
——>new QNetworkReplyHandler(Source/WebCore/platform/network/qt/ResourceHandleQt.cpp:100)
       ——>r.toNetworkRequest(Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp:399) 设置http头
——>m_queue.push 提交事件? (Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp:401)
——>flush();(Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp:164)         
——>(m_replyHandler->*(m_enqueuedCalls.takeFirst()))();Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp:195)
——>QNetworkReplyHandler::start()(Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp:659) 
        建立连接(ESTABLISHED)、发送请求 665: QNetworkReply* reply = sendNetworkRequest(d->m_context->networkAccessManager(), d->m_firstRequest); 
         ——>601 WebCore::QNetworkReplyHandler::sendNetworkRequest 
               ——>626 manager->get(m_request)
      665     QNetworkReply* reply = sendNetworkRequest(d->m_context->networkAccessManager(), d->m_firstRequest);
      669     m_replyWrapper = new QNetworkReplyWrapper(&m_queue, reply, m_resourceHandle->shouldContentSniff() && d->m_context-
    >mimeSniffingEnabled(), this);
               ——>208 QNetworkReplyWrapper::QNetworkReplyWrapper(QNetworkReplyHandlerCallQueue* queue, QNetworkReply* reply, bool
    sniffMIMETypes, QObject* parent)
                  209     : QObject(parent)
                  210     , m_reply(reply)
                  211     , m_queue(queue)
                  212     , m_responseContainsData(false)
                  213     , m_sniffMIMETypes(sniffMIMETypes)
                  214 {
                   215     Q_ASSERT(m_reply);
                  216 
                  217     // setFinished() must be the first that we connect, so isFinished() is updated when running other slots.
                   //QT通过此种方式异步回调??(yes, 信号、槽机制,http://www.ibm.com/developerworks/cn/linux/guitoolkit/qt/signal-slot/ )
                  218     connect(m_reply, SIGNAL(finished()), this, SLOT(setFinished()));
                  219     connect(m_reply, SIGNAL(finished()), this, SLOT(receiveMetaData()));
                  220     connect(m_reply, SIGNAL(readyRead()), this, SLOT(receiveMetaData()));
                  221 }

一旦加载系统接收到足够的信息可以确定资源确实代表了document,FrameLoader就将DocumentLoader推向”committed”状态,在该状态中,frame将显示document。



下载完了之后
——>QtMIMETypeSniffer::qt_metacall()(WebKitBuild/Debug/WebCore/moc_QtMIMETypeSniffer.cpp:77) 
——>trySniffing()(Source/WebCore/platform/network/qt/QtMIMETypeSniffer.cpp:59
      ——>m_sniffer.sniff(data.constData(), data.size())(Source/WebCore/platform/network/qt/QtMIMETypeSniffer.cpp:51)

 50     QByteArray data = m_reply->peek(m_sniffer.dataSize());
 51      const  char* sniffedMimeType = m_sniffer.sniff(data.constData(), data.size());
       data.constData()保存着网页内容,涉及的变量包括 m_replym_sniffer

       ——>emit finished (Source/WebCore/platform/network/qt/QtMIMETypeSniffer.cpp:65)    
      ——> QMetaObject::activate( WebKitBuild/Debug/WebCore/moc_QtMIMETypeSniffer.cpp:88)
      ……
      W ebCore::QNetworkReplyWrapper::qt_metacall (WebKitBuild/Debug/WebCore/moc_QNetworkReplyHandler.cpp)
77      if (_c == QMetaObject::InvokeMetaMethod)  {
 78         switch (_id) {
 79         case 0: receiveMetaData(); break;
 80         case 1: didReceiveFinished(); break;
 81         case 2: didReceiveReadyRead(); break;
 82         case 3: receiveSniffedMIMEType(); break;
 83         case 4: setFinished(); break;
 84         default: ;
 85         }

 86         _id -= 5;
 87     }

       ——>receiveSniffedMIMEType()(WebKitBuild/Debug/WebCore/moc_QNetworkReplyHandler.cpp:82)
      ——> emitMetaDataChanged()( Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp:305)
         ——> QueueLocker lock(m_queue)(Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp)
         ——> ~QueueLocker() { m_queue->unlock(); } ( 203)
         ——> flush();( 178)
         ——> (m_replyHandler->*(m_enqueuedCalls.takeFirst()))(); (195)
         
         ——>1、 QNetworkReplyHandler::forwardData (572)
         ——> client->didReceiveData(m_resourceHandle, data.constData(), data.length(), -1); (586)
      ——>ResourceLoader::didReceiveData( ResourceHandle*, const char* data, int length, int encodedDataLength) ( Source/WebCore/loader/ResourceLoader.cpp: 427)
               data指向保存页面内容
      ——> MainResourceLoader::didReceiveData( Source/WebCore/loader/MainResourceLoader.cpp: 431)
      ——> ResourceLoader::didReceiveData ( Source/WebCore/loader/ResourceLoader.cpp:267)
279     addData(data, length, allAtOnce);
280      //  FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
281      //  However, with today's computers and networking speeds, this won't happen in practice.
282      //  Could be an issue with a giant local file.
283      if (m_sendResourceLoadCallbacks && m_frame)
284         frameLoader()->notifier()->didReceiveData( this, data, length, static_cast< int>(encodedDataLength));
            保存页面到cache 函数: addData()
      ——> ResourceLoadNotifier::didReceiveData( Source/WebCore/loader/ResourceLoadNotifier.cpp:77)
         ——> ResourceLoadNotifier::dispatchDidReceiveContentLength (133)
      ——> InspectorInstrumentation::didReceiveContentLengthSource/WebCore/inspector/InspectorInstrumentation.h:713)
      ——> InspectorInstrumentation::didReceiveContentLengthImplSource/WebCore/inspector/InspectorInstrumentation.cpp:487)
 
html解析     
      ——>2、 QNetworkReplyHandler::finish( Source/WebCore/platform/network/qt/QNetworkReplyHandler.cpp:437)
      ——> ResourceLoader::didFinishLoading (Source/WebCore/loader/ResourceLoader.cpp:434)
      ——> MainResourceLoader::didFinishLoading( Source/WebCore/loader/MainResourceLoader.cpp:466)
      ——> FrameLoader::finishedLoading ( Source/WebCore/loader/FrameLoader.cpp:2287)
      ——> DocumentLoader::finishedLoading ( Source/WebCore/loader/DocumentLoader.cpp:282)
         ——> FrameLoader::finishedLoadingDocument( DocumentLoader* loader) ( Source/WebCore/loader/FrameLoader.cpp:2333)
            ——> FrameLoaderClientQt::finishedLoading (DocumentLoader* loader)( Source/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp:626)
         ——> DocumentWriter::end() ( Source/WebCore/loader/DocumentWriter.cpp:211)
211  void DocumentWriter::end()
212  {
213     m_frame->loader()->didEndDocument();
214     endIfNotLoadingMainResource();
215 }
            213 ——> Document::finishParsing() ( Source/WebCore/dom/Document.cpp:2246)
            214: DocumentWriter::endIfNotLoadingMainResource() ( Source/WebCore/loader/ DocumentWriter.cpp  228
228     addData(0, 0,  true);
229     m_frame->document()->finishParsing();
               ——> DocumentWriter::addData() (208)               
                  ——> DecodedDataDocumentParser::appendBytes(DocumentWriter* writer , const char* data, int length, bool shouldFlush)Source/WebCore/dom/DecodedDataDocumentParser.cpp:40)
                  ——>  HTMLDocumentParser::append(const SegmentedString& source) (Source/WebCore/html/parser/HTMLDocumentParser.cpp:367)
                  ——>  HTMLDocumentParser::pumpTokenizerIfPossible(SynchronousMode mode) (175)
                  ——>  HTMLDocumentParser::pumpTokenizer(SynchronousMode mode) (261)
                  解析、执行script
                     ——>  HTMLDocumentParser::canTakeNextToken(SynchronousMode mode, PumpSession& session) (223)
                     ——>  HTMLDocumentParser::runScriptsForPausedTreeBuilder() (205)
                     ——>  HTMLScriptRunner::execute(PassRefPtr<Element> scriptElement, const TextPosition1& scriptStartPosition)  Source/WebCore/html/parser/HTMLScriptRunner.cpp:167)
                     ——>  WebCore::HTMLScriptRunner::runScript(this=0x81e2a58, script=0x832c040, scriptStartPosition=...) (296)
                     ——>  WebCore::ScriptElement::prepareScript (this=0x832c084, scriptStartPosition=...,     supportLegacyTypes=WebCore::ScriptElement::DisallowLegacyTypeInTypeAttribute)( Source/WebCore/dom/ScriptElement.cpp:240)
                     ——>  WebCore::ScriptElement::executeScript (this=0x832c084, sourceCode=...)(283)
                     ——>  WebCore::ScriptController::evaluate (this=0x828d1a4, sourceCode=...)( Source/WebCore/bindings/js/ScriptController.cpp:166)
                     ——>  WebCore::ScriptController::evaluateInWorld (143)
                     ——>  WebCore::JSMainThreadExecState::evaluate( Source/WebCore/bindings/js/JSMainThreadExecState.h:54)
                     ——>  JSC::evaluate(exec=0xae3f499c, scopeChain=0xae3ee5c8, source=..., thisValue=...) ( Source/JavaScriptCore/runtime/Completion.cpp:64)
                     ——>  JSC::Interpreter::execute(S ource/JavaScriptCore/interpreter/Interpreter.cpp:767)
                     ——>  JSC::JITCode::execute ( Source/JavaScriptCore/jit/JITCode.h:77)
                     ——>  ?? ()
                     ——> WebCore::jsHTMLDocumentPrototypeFunctionWrite( WebCore/generated/JSHTMLDocument.cpp:445)
                     ——>  WebCore::JSHTMLDocument::write( Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp:161)
                     ——>  WebCore::documentWrite (156)
                     ——> WebCore::Document::write ( Source/WebCore/dom/Document.cpp:2227)
                           ——>  WebCore::HTMLDocumentParser::insert( Source/WebCore/html/parser/HTMLDocumentParser.cpp:324)
                              回到了html的解析
                           ——>  WebCore::HTMLDocumentParser::pumpTokenizerIfPossible (175)
                           ——> WebCore::HTMLDocumentParser::pumpTokenizer  (299)
                                    查看是否有script,1、如果有,转到“ 解析、执行script”;2、如果没有转到下面“”
                  完成解析html
                   InspectorInstrumentation::didWriteHTML(cookie, m_tokenizer->lineNumber());
                  ——>  InspectorInstrumentation::didWriteHTML ( Source/WebCore/inspector/InspectorInstrumentation.h:803)
                  ——> 
            ——>  Document::finishParsing() ( Source/WebCore/dom/Document.cpp:2259)
                  ——> HTMLDocumentParser::finish() ( Source/WebCore/html/parser/HTMLDocumentParser.cpp:427)
                  ——> HTMLDocumentParser::attemptToEnd() ( 399)
                  ——> 
                  
 生成dom树     
      


附件(js)下载、解析



      


二、下载
三、加载

参考文档
1.官方文档: http://www.webkit.org/blog/1188/how-webkit-loads-a-web-page/
2.dlmu2001的译文: http://blog.csdn.net/dlmu2001/article/details/5941432
3.dlmu200:WebCore中的http请求信息维护  http://blog.csdn.net/dlmu2001/article/details/5936122 1
4.其他技术性文章:Introduction to WebKit Objective-C Programming Guide  http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DisplayWebContent/DisplayWebContent.html
5.其他技术性文章:Introduction to WebKit DOM Programming Topics http://developer.apple.com/library/mac/#documentation/AppleApplications/Conceptual/SafariJSProgTopics/WebKitJavaScript.html
6.  http://www.webkit.org/coding/technical-articles.html

相关技巧
1.cscope查找类的定义: cs find e class.*QString[^;]*($|{)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值