디지털 장인정신

블로그 이미지
WebKit개발자의 혼자쓰는 블로그
스페로

Article Category

All (71)
Technology (47)
Creativity (19)
Private (4)

Recent Comment

Recent Trackback

Calendar

«   2018/10   »
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Archive

My Link

  • Total336,154
  • Today30
  • Yesterday46

Refer to

http://lists.webkit.org/pipermail/webkit-gtk/2012-May/001078.html


WebProcess의 addon을 달 수 있는 기능. 현재는 거의 WebKitTestRunner때문에 만들어졌다고 봐도 과언이 아니다. 
일반적인 plugin mechanism과 달리 오직 하나의 InjectedBundle만 WebProcess에 inject할 수 있다.

일반적인 plugin mechanism이란? (recommend to read  http://www.apibook.com/blog/)
API를 plugin을 통해 extending하는 방법. 크롬이 NPAPI API를 통해 author가 작성한 플러그인을 사용하거나 3D Max에서 서드파티가 제공하는 addon을 붙이는 방법이다. author는 plugin API를 구현한뒤 shared library로 만든다. 어플리케이션이 런타임에 shared library를 로드하고 해당 API를 콜하게 된다.
보통 plugin manager를 만들어 여러 shared library를 동시에 로드할 수 있게끔 구현한다. (크롬이 flash plugin과 pdf reader plugin을 동시에 쓸수 있는것 처럼)
근데 Injected Bundle은 오직 하나의 shared library만 로드할 수 있도록 심플하게 구현되어있다. (가장위의 refer 참조)

Call Flow
1. initialize
in Source/WebKit2/WebProcess/WebProcess.cpp

void WebProcess::postInjectedBundleMessage(const CoreIPC::DataReference& messageData)

{

    InjectedBundle* injectedBundle = WebProcess::shared().injectedBundle();

    ...

}


in Tools/WebKitTestRunner/InjectedBundle/InjectedBundleMain.cpp

void WKBundleInitialize(WKBundleRef bundle, WKTypeRef initializationUserData)

{

    WTR::InjectedBundle::shared().initialize(bundle, initializationUserData);

}


in Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp

void InjectedBundle::initialize(WKBundleRef bundle, WKTypeRef initializationUserData)

{

    WKBundleClient client = {


    };

    WKBundleSetClient(m_bundle, &client);

}


in Source/WebKit2/WebProcess/InjectedBundle/InjectedBundle.cpp

void InjectedBundle::initializeClient(WKBundleClient* client)

{

    m_client.initialize(client);

}


2. create page

in Source/WebKit2/WebProcess/WebPage/WebPage/WebPage.cpp

PassRefPtr<WebPage> WebPage::create(uint64_t pageID, const WebPageCreationParameters& parameters)

{

    ....

    if (page->pageGroup()->isVisibleToInjectedBundle() && WebProcess::shared().injectedBundle())

        WebProcess::shared().injectedBundle()->didCreatePage(page.get());

    ....

}


in Tools/WebKitTestRunner/InjectedBundle/InjectedBundle.cpp

void InjectedBundle::didCreatePage(WKBundlePageRef page)

{

    m_pages.append(adoptPtr(new InjectedBundlePage(page)));

}


in Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp

InjectedBundlePage::InjectedBundlePage(WKBundlePageRef page)

    : m_page(page)

    , m_world(AdoptWK, WKBundleScriptWorldCreateWorld())

{

    WKBundlePageLoaderClient loaderClient = {    };

    WKBundlePageSetPageLoaderClient(m_page, &loaderClient);


    WKBundlePageResourceLoadClient resourceLoadClient = {    };

    WKBundlePageSetResourceLoadClient(m_page, &resourceLoadClient);


    WKBundlePagePolicyClient policyClient = {    };

    WKBundlePageSetPolicyClient(m_page, &policyClient);


    WKBundlePageUIClient uiClient = {    };

    WKBundlePageSetUIClient(m_page, &uiClient);


    WKBundlePageEditorClient editorClient = {    };

    WKBundlePageSetEditorClient(m_page, &editorClient);


#if ENABLE(FULLSCREEN_API)

    WKBundlePageFullScreenClient fullScreenClient = {    };

    WKBundlePageSetFullScreenClient(m_page, &fullScreenClient);

#endif

}


in Source/WebKit2/WebProcess/WebPage/WebPage/WebPage.cpp

void WebPage::initializeInjectedBundleLoaderClient(WKBundlePageLoaderClient* client)

{

    ....

    m_loaderClient.initialize(client);

}


3. loader callback

in Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp

void WebFrameLoaderClient::postProgressFinishedNotification()

{

    if (WebPage* webPage = m_frame->page()) {

        if (m_frame->isMainFrame()) {

            // Notify the bundle client.

            webPage->injectedBundleLoaderClient().didFinishProgress(webPage);


            webPage->send(Messages::WebPageProxy::DidFinishProgress());

        }

    }

}


in Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp

void InjectedBundlePage::didFinishProgress(WKBundlePageRef, const void *clientInfo)

{

    static_cast<InjectedBundlePage*>(const_cast<void*>(clientInfo))->didFinishProgress();

}



Build

InjectedBundle은 shared library로 따로 빌드된다. WebKitTestRunner를 실행히 env로 shared library의 path가 세팅된다.


in  Tools/WebKitTestRunner/GNUmakefile.am

# The InjectedBundle library allows the render process to load harness code.

if ENABLE_WEBKIT2

noinst_LTLIBRARIES += Libraries/libTestRunnerInjectedBundle.la

endif



How to send InjectedBundle path from UI Process to Web Process

위에서 서술하다 싶이 env로 UI Process의 TestController가 알아낸후 WebContext에게 알려준다.

in Tools/WebKitTestRunner/gtk/main.cpp

int main(int argc, char** argv)

{

    gtk_init(&argc, &argv);

    // Prefer the not installed web and plugin processes.

    WTR::TestController controller(argc, const_cast<const char**>(argv));

    return 0;

}


in Tools/WebKitTestRunner/TestController.cpp

void TestController::initialize(int argc, const char* argv[])

{

    ...

    initializeInjectedBundlePath();


    ...

    m_context.adopt(WKContextCreateWithInjectedBundlePath(injectedBundlePath()));

    ...

}


in Source/WebKit2/UIrocess/WebContext.cpp

PassRefPtr<WebContext> WebContext::create(const String& injectedBundlePath)

{

    JSC::initializeThreading();

    WTF::initializeMainThread();

    RunLoop::initializeMainRunLoop();

    return adoptRef(new WebContext(ProcessModelSharedSecondaryProcess, injectedBundlePath));

}


What is InjectedBundle in UI Process

UI Process에도 callback을 inject하는 듯한 코드들이 있다. (밑에처럼)

이것은 shared library를 ld하여 callback을 등록한다는 개념의 injected bundle보다는, 그냥 callback을 등록하는 코드이다.

코드를 reuse하기위해 콜백등록 패턴을 그냥 쓰는데, 코드를 읽는데 굉장한 혼란을 준다.


in Tools/WebKitTestRunner/TestController.cpp

void TestController::initialize(int argc, const char* argv[])

{

    ...

    WKContextInjectedBundleClient injectedBundleClient = {

        kWKContextInjectedBundleClientCurrentVersion,

        this,

        didReceiveMessageFromInjectedBundle,

        didReceiveSynchronousMessageFromInjectedBundle,

        0 // getInjectedBundleInitializationUserData

    };

    WKContextSetInjectedBundleClient(m_context.get(), &injectedBundleClient);

    ...

}


'Technology > Webkit' 카테고리의 다른 글

WebKit css3 animations on Accelerated Compositing  (1) 2012.10.23
WebKit Filters Animation Internal  (1) 2012.10.20
WebKit2 Injected Bundle  (1) 2012.10.15
oprofile  (2) 2012.06.02
massif 메모리 사용량을 측정하자  (0) 2012.05.31
cachegrind in valgrind  (5) 2012.05.31
Trackback 1 and Comment 1
prev Prev : [1] : [···] : [4] : [5] : [6] : [7] : [8] : [9] : [10] : [11] : [12] : [···] : [71] : Next next