레이블이 ShellMainDelegate인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ShellMainDelegate인 게시물을 표시합니다. 모든 게시물 표시

2012년 3월 28일 수요일

ContentMain - ContentMainRunner (1)

Content Shell main()의 두번째 라인이자 마지막 라인인 ContentMain() 호출이다.

int ContentMain(int argc,
                const char** argv,
                ContentMainDelegate* delegate);

ShellMainDelegate 객체를 생성한 뒤, ContentMain()를 호출하면서 Content Shell을 실행하고 있다.

이제 ContentMain()에 전달한 ShellMainDelegate 객체가 어디서 어떻게 쓰이는지 살펴보고,
클라이언트들(ShellContentBrowserClient, RendererClient, UtilityClient 등) 가
언제 어디서 참조되는지 알아보자.

ContentMain()... 긴 여정이 될 것 같은 느낌이다.

ContentMain()의 구현은 다음과 같다.



ContentMain()은 ContentMainRunner 클래스를 통해 content module의 초기화, 실행, 종료를
처리하고 있다.

사실 ContentMainRunner 는 추상클래스이고, ContentMainRunner::Create()를 통해 추상클래스를 구현한 ContentMainRunnerImpl 객체가 생성된다.

Chromium 코드를 보다보면 많은 패턴들을 만나게 되는데, 여기서는 factory method 패턴을 만난것 같다. :)


ContentMainDelegate  포인터는 Content State 를 초기화하는 Initialize()의 파라미터로 전달된다.

class ContentMainRunner {
virtual int Initialize(int argc,
                           const char** argv,
                           ContentMainDelegate* delegate) = 0;
};

Initialize()의 실제 구현부분으로 가보자.
Initialize()는 src/content/app/content_main_runner.cc 에 구현되어있다.

Initialize()에서 delegate를 참조하여 ShellMainDelegate 의 멤버함수를 호출하는 첫번째 부분이다.


BasicStartupComplete()를 호출하는 부분이다. ContentMainRunner의 아주 초기 시점에 호출이 되는 것을 알 수 있다. (ShellMainDelegate 클래스의 위 함수는 빈 함수임)

몇몇 함수들이 수행된 후 PreSandboxStartup()이 호출된다.


ShellMainDeleage 의 PreSandboxStartup()에서는 ShellContentClient 객체를 content module의 content client 등록하고 (content::SetContentClient()), process_type 에 맞는 sub client(browser client, renderer client 등)를 초기화한다.

다음으로 SandboxInitialized() 가 호출된다.



ShellMainDelegate의 SandboxInitialized()는 아무일도 하지 않는다.

ContentMainRunner의 Initialize() 에서 ShellMainDelegate 의 역할을 간단히 정리해보면,
content module에 content client 등록(ShellContentClient)과 sub client 등록인것 같다.

2012년 3월 27일 화요일

Content Shell 의 구조 - ShellMainDelegate 클래스(3)

Content Shell의 ShellMainDelegate 클래스의 구현에 대해 살펴보자.

shell_main_delegate.cc 파일을 보면 ContentMainDelegate의 많은 추상함수들이
빈 함수로 구현되어 있음을 알 수 있다.

아래는 ShellMainDelegate 클래스에서 실제로 구현한 함수들이다.
PreSandboxStartup()
RunProcess()
ZygoteForked()
InitializeShellContentClient()
InitializeResourceBundle()

PreSandboxStartup() 함수를 살펴보자.


content::SetContentClient() 함수가 이 Content Shell에서 중요한 역할을 하고 있는것 같다.
이전에 언급한 적이 있는것 같은데, Content Module이 Server가 되고, Content Module을 이용하여
구현한 브라우저가 Client가 되는형태라고 말이다.
ShellMainDelegate 클래스를 가볍게 보고나서, ContentMain() 함수를 알아볼 때
이 client 가 언제 어떻게 사용되는지 알 수 있을 것이다.

다음으로 InitializeShellContentClient() 함수를 호출하고 있다.
process_type을 파라미터로 전달해 주는데, 이 type이 무엇일까?
아래의 InitializeShellContentClient() 함수를 보면 process_type을 비교하여 type에 맞는 client 를
설정하고 있다. Content Client 도 세부적으로 browser client, renderer client, plugin client, utility client들이 필요한 것 같다.


type에 맞는 세부 클라이언트들은 content::GetContentClient()->set_XXX 함수를 이용하여 셋팅하고 있다. PreSandboxStartup() 에서 content::SetContentClient()를 이용하여 ShellContentClient 객체를 셋팅하고, content::GetContentClient()는 이 때 설정한 ShellContentClient를 리턴한다.
Content Module은 SetContentClient()를 통해 셋팅된 각각의 포인터를 통해 Embedder의 Client 객체들을 참조하게 될것이다. 여기서 Embedder가 무엇인가? 이제는 바로 답을 할 수 있어야 할 것이다!
다음으로 InitializeResourceBundle() 함수를 호출하고 있다.
이 함수는 content_shell.pak 이라는 pak 파일을 이용하여 ui::ResourceBundle에 초기화를 요청하는것 같다. 이 pak 파일은 content_shell 빌드시 생성된다.

PreSandboxStartup() 함수에 대해 알아보았다. PreSandboxStartup()은 Content Module 이 Embedder에게 Sandbox 초기화전에 할일하라고 알려줄 때 사용되는 추상함수이다. Content Module은 이 추상함수를 호출하고 Sandbox 관련 내용(?)을 초기화 할 것이다. 아마 이 부분은 content::ContentMain() 함수에서 수행될 것이다.

SandboxInitialized() 함수는 빈 함수로 보아 Content Shell 에서는 Sandbox 에 대한부분은 없는것 같다.

RunProcess() 함수를 살펴보자.
이 함수는 process type과 MainFunctionParams 라는 구조체를 파라미터로 전달받고 있고 파라미터 타입이 빈 문자열일 경우에 ShellBrowserMain() 함수를 호출하고 있다.
ShellBrowserMain() 함수는 src/content/shell/shell_browser_main.cc 에 정의되어 있고, 주석을 보면 이 함수가 Content Shell의 Main routine 임을 알 수있다. 이번 포스트는 ShellMainDelegate 클래스에 대한 이야기이므로 ShellBrowserMain은 다음에 알아보자.

마지막으로 ZygoteForked() 함수를 살펴보자. 프로세스가 fork() 된 후,  process type(switchs::kProcessType)을 보고 이 타입에 맞는 Content Client 를 InitializeShellContentClient() 함수에서 초기화하고 있다. 여기서 초기화되는 각각의 클라이언트들은 Content Module 내 프로세스들이 embedder에게 무언가 요청할 때 사용될 것이다.

지금까지 ShellMainDelegate 클래스에 대해 알아보았다. 이 클래스가 하는일은 크게 두가지로 볼 수 있겠다. 첫번째는 Content Module에서 사용되는 프로세스 타입에 맞는 Content Client 들을 초기화하는 일이고 두번째는 ShellBrowserMain을 통해 브라우저 메인 루틴을 실행하는 일이다. 이 두가지 모두 ContentMain() 이 호출되면서 그 안에서 참조되는 것들이다. 이것들의 자세한 내용은 ContentMain()에서 사용될 때 알아보자.

2012년 3월 22일 목요일

Content Shell 의 구조 - ShellMainDelegate 클래스(2)

이전 포스트에서는 ContentMainDelegate 인터페이스 클래스에 대해 알아보았다.
이제 ShellMainDelegate 클래스에 대해 살펴볼 시간이다.

ShellMainDelegate 클래스는 생성자, 소멸자, ContentMainDelegate 인터페이스 클래스의
멤버함수들, 그리고 두개의 private 멤버함수, 다섯개의 private 멤버함수로 구성되어 있다.

private 멤버함수는 다음과 같다.

InitializeShellContentClient()
InitializeResourceBundle()

private 멤버 변수는 다음과 같다.

content::ShellContentBrowserClient          browser_client_
content::ShellContentRendererClient         renderer_client_
content::ShellContentPluginClient             plugin_client_
content::ShellContentUtilityClient             utility_client_
content::ShellContentClient                     content_client_

위 변수들의 이름을 보면 ShellContentXXXClient 인 것을 알 수 있다.
여기서 잠깐,,, Client 이긴 한데 무엇의 Client 일까? Client가 있으면 Server도 있어야 하는데
여기서 Server는 무엇일까?

잠시 Content Module로 돌아가서 여기에서 말하는 Client - Server 가 무엇인지 알아보자.

Content Shell에 대한 포스트 에서 Content Shell은 Content Module을 이용한 레퍼런스
브라우저라고 잠깐 이야기를 했었다.

Chrome 이나 Content Shell 은 각각의 ContentMainDelegate 인터페이스 클래스를 구현하고
그 객체를 ContentMain() 함수에 매개변수로 전달하는것으로 브라우저가 시작이된다.

이 구조로 본다면, Content Module이 Server 가 되고, Delegate 가 Client 가 되겠다.
Content Shell 이라는 Client 가 Content Module 이라는 Server 를  이용해서 브라우저를 구성하고 있는것이다.

Content Module이 동작을 하면서 자신을 구동시킨 Client (Chrome or Content Shell)를
호출(?)하고 싶을때, 이 Delegate 내 Client 를 이용하여 함수들을 호출을 하는것이다.

Client 들이 무슨 일을 하는지, Content Module에서는 언제 Client 를 호출해서 이용하는지 궁금해진다.
차차 알아보자~^^;

다시 ShellMainDelegate 클래스로 돌아가서,,,

InitializeShellContentClient() 멤버 함수가 있다. 이름으로 미루어 이 함수를 이용해서
위에서 선언된 여러 Client 들을 초기화하지 않을까 싶다.

이것은 다음 포스트에서 실제 ShellMainDelegate 함수들의 구현을 살펴보면서 확인해보자.