WebKitの内部について少し

WebKitが何らかの形で動作する方法、リソースのロードプロセスがどのように行われるか、そしてこれらすべてで実際に何ができるかについて、私はタスクを自問し、最新のすべてのブラウザーの基礎を知りました。 原則として、問題に関する文書で十分です。



*構造化されているがカバーしていない、およびAppleの 10番目の部分。

*詳細や報道の程度が異なるwiki記事が散在しています



この記事の目的は、上から見たシステムの一般的な見解ではなく、システムで発生するプロセスの1つを正確かつ詳細に分析することです。 私の意見では、これは抽象的な視点よりもシステム全体のより良い考えを与えることがあります。 あるいは、それは単なる小さなレンガであり、開発者は彼のシステムのアイデアの散在するモザイクから情報をコンパイルする必要があります。



構造






ドキュメントの読み込みプロセス、 ローダー


programm1.c

mainWidget = new QWebView(parent); // mainWidget->setHtml("<html><body>HEIL</body></html>"); mainWidget->page()->mainFrame()->setHtml( "<html><body>HEIL</body></html>",QUrl() );
      
      







 QWebFrame::setHtml() → QWebFrameAdapter::setHtml // qt/qtwebkit/Source/WebKit/qt/WebCoreSupport/QWebFrameAdapter.cpp:284 ... → WebCore::FrameLoader::load // frame->loader()->load(WebCore::FrameLoadRequest(frame, request, substituteData)); // "request" description WebCore::FrameLoadRequest( WebCore::Frame WebCore::ResourceRequest // Request Description -   WebCore::SubstituteData // Data description - qt/qtwebkit/Source/WebCore/loader/SubstituteData.h // data - WTF::RefPtr<WebCore::SharedBuffer> // mime-type - "text/html" // encoding - "utf-8" // failingURL ) ) → FrameLoaderClientQt::createDocumentLoader() // RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request,substitute_data) // WebCore::FrameLoaderClient() → FrameLoader::load(DocumentLoader* newDocumentLoader) // FrameLoader::load(loader.get()) newDocumentLoader.m_frame = 0 ; → FrameLoader::loadWithDocumentLoader(newDocumentLoader, type, 0) → FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> prpFormState) ... setPolicyDocumentLoader(loader); //       m_frame  loader. → loader→setFrame(m_frame); → m_writer.setFrame(frame); ... // Check policies and with callback jump to callContinueLoadAfterNavigationPolicy via static jumper FrameLoader::callContinueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState> formState, bool shouldContinue ) → //   : m_policyDocumentLoader.get()->substituteData().content()->data(); setProvisionalDocumentLoader(m_policyDocumentLoader.get()); // m_provisionalDocumentLoader = m_policyDocumentLoader.get(); FrameLoader::continueLoadAfterWillSubmitForm // RefPtr<DocumentLoader> m_provisionalDocumentLoader; m_provisionalDocumentLoader→startLoadingMainResource // DocumentLoader::m_mainResource - CachedResourceHandle<CachedRawResource> // DocumentLoader::ResourceRequest m_request; //    m_substituteData.content()->data() → handleSubstituteDataLoadSoon → handleSubstituteDataLoadNow WebCore::ResourceResponse response(url, m_substituteData.mimeType(), m_substituteData.content()→size(), m_substituteData.textEncoding(), ""); → DocumentLoader::responseReceived(0, response) // responseReceived(CachedResource* resource, const ResourceResponse& response) m_response = response; // m_m_identifierForLoadWithoutResourceLoader=1 // notifier()       View . → frameLoader()→notifier()→dispatchDidReceiveResponse(this, m_identifierForLoadWithoutResourceLoader, m_response, 0); → DocumentLoader::continueAfterContentPolicy(PolicyUse); // PolicyUse is enum val enum PolicyAction {PolicyUse,PolicyDownload,PolicyIgnore}; // m_response.isHTTP()=0 isLoadingMainResource()=1 isStopping()=0 ... → DocumentLoader::dataReceived(0, m_substituteData.content()→data(), m_substituteData.content()→size()); → frameLoader()→notifier()→dispatchDidReceiveData(this, m_identifierForLoadWithoutResourceLoader, data, length, -1); → DocumentLoader::commitLoad(const char* data, int length) // data – our html data → frameLoader→client()→committedLoad(this, data, length); // FrameLoaderClient::committedLoad → FrameLoaderClientQt::committedLoad → void DocumentLoader::commitData(const char* bytes, size_t length) // loader->commitData(data, length) –     DocumentWriter,  documentLoader   m_frame. m_writer.begin(documentURL(), false); m_writer.setDocumentWasLoadedAsPartOfNavigation(); → void m_writer.addData(bytes, length); // DocumentWriter::addData ... → finishLoading(0)
      
      







上記のCallStackは、setHtmlからDocumentと通信するための一連の呼び出しです。 ポリシーとさまざまな種類のデータロードの配置プロセスに関心がある場合は、そこを掘る必要があります。 トランジションの一部を破棄し、ある種のセマンティック操作を反映するもののみを残しました。

上記の「コールスタック」で関心のあるプロセスは、ドキュメントへの書き込みの開始であり、これに必要なものです。 DocumentLoader :: commitDataでDocumentWriterがどのように準備されているかを確認した後、programm1.cppを「単純化」できます(コードの意味ではなく、地面に近づける意味で)。



programm2.c



  QWebPage *page = mainWidget->page(); QWebFrame *qtWebFrame = mainWidget->page()->mainFrame(); QWebFramePrivate *qtWebFramePrivate = qtWebFrame->d; WebCore::Frame *frame = qtWebFramePrivate->frame; WebCore::DocumentWriter m_writer(frame); m_writer.setFrame(frame); m_writer.begin(url, false); m_writer.setDocumentWasLoadedAsPartOfNavigation(); m_writer.setEncoding("utf-8", true); m_writer.addData(html ,strlen(html) ); m_writer.end();
      
      







同様に、解析(WebCore :: DocumentParserファミリーのクラス)に進む必要があります。 Writerレイヤーを完全に取り除くことはできません。appendBytes呼び出しにはライターが含まれ、さらにWriterはデコードインターフェイスの作成とView: DocumentWriter::reportDataReceived



との通信を担当しView: DocumentWriter::reportDataReceived



- m_frame->document()->recalcStyle(Node::Force).







 void DecodedDataDocumentParser::appendBytes(DocumentWriter* writer, const char* data, size_t length) { ... String decoded = writer->createDecoderIfNeeded()->decode(data, length); ... writer->reportDataReceived(); ... }
      
      







DocumentWriter ::から初期化手順を実行すると、programm3.cppが取得されます。



programm3.cpp



  const char *html = "<html><body>HEIL<b>IGO</b><script>document.write(1234);</script></body></html>"; size_t htmlen = strlen(html); RefPtr<WebCore::Document> document = WebCore::DOMImplementation::createDocument("text/html", frame, url, false); document->createDOMWindow(); frame->setDocument(document); document->implicitOpen(); frame->script()->updatePlatformScriptObjects(); RefPtr<WebCore::DocumentParser> parser = document->parser(); WebCore::DocumentWriter writer(frame); m_parser->appendBytes(&writer,html ,htmlen); m_parser->finish();
      
      







PS


これにより、WebKitへの旅は中断されます。 誰かにとって、このテキストがプロジェクトへの入り口を下げることを願っています。



最後のセクションには、実験環境を迅速に展開するためのレシピが含まれています。



編集


基礎は、 qt-everywhere-opensource-src-5.3.1パッケージによって採用されました。 そこからすべてを取得する必要はありません-qtbase i qtwebkitで十分です。 ビルドするとき、次の問題に遭遇しました:-debug( ./configure -static -debug )フラグをオンにした静的ビルドは、8GBマシンで動作する例としてリンクできなかった厄介なライブラリを作成します。 まあ、待っていてもリンクはオプションです。数分待って最も単純な例を再コンパイルするのはあまり適していません。 シンボル情報がない場合、リンクには数秒かかります。libWebkit.a〜54Mb自体です。



共有ライブラリには別の問題があります:qt-webkita APIをエクスポートしませんが、それ自体を隠します。 hiddenの代わりに「 -fvisibility = default 」で処理さます。 ハックの場合、これで十分です-ライブラリ内に重複する名前はありませんが、通常のプロジェクトでは、 WTF_EXPORTディレクティブを使用して、長時間シャベルでエクスポートされた関数を定義する必要があります。 エクスポートに関する情報はここにありますが 、助けにはなりませんでした。



また、 QWebFrameqtwebkit / Source / WebKit / qt / WidgetApi / qwebframe.h )でWebCoreワールドへのアクセスを開く必要があります-実装はプライベート変数QWebFramePrivate* QWebFrame::d



背後に隠されています-それを公開する必要があります その後、WebCore :: Frameに到達することが可能になります

WebCore::Frame *frame = [ QWebView ]->page()->mainFrame()->d->frame;









それにもかかわらず、テストについては、動的アセンブリをお勧めします。そうしないと、gdbもリンクだけでも楽しみが得られません。 私の大まかな設定は次のとおりです。



cd ./qtbase

./configure -opensource -confirm-license -release -nomake tools -nomake examples -no-compile-examples -no-opengl -no-openvg -no-egl -no-eglfs -no-sql-sqlite2 -D QT_NO_GRAPHICSVIEW -D QT_NO_GRAPHICSEFFECT -D QT_NO_STYLESHEET -D QT_NO_STYLE_CDE -D QT_NO_STYLE_CLEANLOOKS -D QT_NO_STYLE_MOTIF -D QT_NO_st--no -no -nonono -no -nonononono qml -no-kms -no-libudev -no-linuxfb -no-mtdev -no-nis -no-pulseaudio -no-sm -no-xinerama -no-xinput2 -no-xkb -no-xrender -openssl -openssl-linked -icu -fontconfig -system-freetype -system-libpng -system-libjpeg -system-zlib -qt-pcre -qt-harfbuzz -qt-sql-sqlite -qt-xcb -debug

make -j 8



cd ../qtwebkit

../qtbase/bin/qmake WEBKIT_CONFIG- = use_glib \ use_gstreamer \ use_gstreamer010 \ use_native_fullscreen_video \ legacy_web_audio \ web_audio \ video \ gamepad -o Makefile.WebCore.Target WebKit.pro



#受け取ったmakeから-fvisibility = defaultを削除します。これはおそらくオプションで実行できます。



make -f Makefile.WebCore.Target -j 8





../lib/



からすべてのライブラリを../lib/



するために残り、プロジェクトをリンクできます。 最低限必要でした:



 libQt5Core.so libQt5Gui.so libQt5PrintSupport.so libQt5WebKit.so libQt5WebKitWidgets.so libQt5Widgets.so libQt5Newtork.so libQt5Core.so.5 libQt5Gui.so.5 libQt5PrintSupport.so.5 libQt5WebKit.so.5 libQt5WebKitWidgets.so.5 libQt5Widgets.so.5 libQt5Network.so.5
      
      







ビルドの問題


見た場合:

This application failed to start because it could not find or load the Qt platform plugin "xcb".





そのため、静的ビルドの場合、次のことを忘れました

Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)







動的なものについては、 libxcb.soが失われたか、または-qt-xcbスイッチを使用してqtbaseを構築した場合、プロジェクトのコンテンツqt / qtbase / plugins / platformで./platformsフォルダーを作成する必要があります( libqxcb.soファイルは1つで十分です )。



テストモジュールをコンパイルするときは、 インライン関数無効にする( -fno-inline-small-functions )か 、ライブラリがコンパイルされた定義のリスト全体を取得する必要があります。そうでない場合は、コンパイルされたWebKitと同じincludeヘッダーに分類されます。 WebCore :: Documentでは、m_parser変数のこのエラーが原因で、クライアントコードのオフセットで8バイトが失われ、さまざまな場所でエラーが発生しました。



All Articles