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

2012년 4월 3일 화요일

ContentMain - ContentMainRunner (2)


지난 포스트에서는 ContentMain()에서 ShellMainDelegate 가 처음 참조되어 사용도는 부분인
ContentMainRunner 의 Initialize()를 살펴보았다.

이번 포스트에서는 ContentMain()의 핵심 호출인 ContentMainRunner::Run()에 대해 살펴보자.

아래의 ContentMain()를 보면 Run()은 Chromium 브라우저가 실행되는 동안 호출되는 함수이다.
Run()이 리턴되면 Chromium도 종료가 된다.


Run() 구현부분을 보자. 아래 소스코드에서 처럼 process type 값과, 생성한 content::MainFunctionParams 객체, 그리고 delegate_ (ShellMainDelegate)를 RunNamedProcessTypeMain()의 매개변수로 전달한다. Run()이 하는일은 이것이 전부다.


process type이 무엇일까? CommandLine(src/base/command_line.cc) 객체에서 가져오는것을 보니 command line에서 전달되는 값인것 같 Initialize()다. switches::kProcessType(src/content/public/common/content_switches.cc)은 "type" 문자열이다.
content_shell을 실행시키고 ps 를 통해 content_shell 관련 정보를 보면 다음과 같다.


총 다섯개의 프로세스가 떠있고, 두개는 type이 없으며 나머지 세개의 프로세스의 type은 각각 zygote, renderer, gpu-process 이다.

Run()에서 가져오는 type이 위의 type switch의 값이다.
사용자가 content_shell을 실행할 때는 파리미터 전달없이 실행시키므로 아래의 복잡한 파라미터들이 설정되어 실행되는 content_shell 프로세스들은 런타임이 fork()가 된것들일 것이다.

이렇게 process type이 설정이 된다음, MainFunctionParams 객체가 생성이 되는데, 이 객체는 Platform 의존적인 부분이 포함된 ComandLine의 Wrapper 객체이다.

이제 Run()에서 마지막으로 호출되는 RunNamedProcessTypeMain()에 대해 살펴보자.


RunNamedProcessTypeMain()은 process_type 으로 전달된 문자열을 가지고 kMainFunctions 배열에서 실행시킬 함수포인터를 찾는다. 지금은 빈 문자열("")이 전달되었기때문에 BrowserMain이 실행될 함수포인터에 해당된다.
이 함수가 실행되기전!!! 드디어 우리의 관심사인 delegate(ShellMainDelegate)가 참조되고 있는 것을 볼수 있다.
ShellMainDelegate::RunProcess()이 호출되고 kMainFunction[] 배열에서 process_type("")에 해당하는 BrowserMain이 호출이됨으로써 content_shell 이 실행이 되고 있다.

이번 포스트에서는 ContentMainRunner::Run() 에 대해 살펴보았다.
다음 포스트에서는 ShellMainDelegate::RunProcess()가 호출하는 ShellBrowserMain()에 대해 알아보자.

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 등록인것 같다.