发布者: Zero

Chrome启动代码流程:(v2.0版,Windows平台)

应用程序启动过程: 1) WinMain函数为入口点,定义在文件\chrome\app\chrome_exe_main.cc文件中(位于chrome_exe工程项目中)
2) WinMain从注册表中找到当前版本的子目录,然后装载chrome.dll文件。如果没找到,则直接从当前exe目录查找dll文件,并装载。
3) 直接从chrome.dll中找到函数ChromeMain,然后调用它。ChromeMain函数定义在\chrome\app\chrome_dll_main.cc文件中,位于chrome_dll工程项目中。

HINSTANCE dll_handle = ::LoadLibraryEx (dll_name, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);                                    
	// Initialize the crash reporter.
	InitCrashReporter( client_util::GetDLLPath (dll_name, dll_path));	
	bool exit_now = true ;
	if ( ShowRestartDialogIfCrashed(&exit_now )) {
		// We have restarted because of a previous crash. The user might
		// decide that he does not want to continue.
		if ( exit_now) return ResultCodes ::NORMAL_EXIT;	
	}
	
	if ( NULL != dll_handle ) {
		client_util:: DLL_MAIN entry = reinterpret_cast< client_util::DLL_MAIN >(
			:: GetProcAddress(dll_handle , "ChromeMain"));
	if ( NULL != entry )
		return (entry )(instance, & sandbox_info, command_line );
	}

4) ChromeMain函数做一些通用组件的初始化工作,之后则根据命令行中的参数选项,要么调用RenderMain,要么调用BrowserMain函数,或者调用WorkMain或者PluginMain函数:

int rv = -1;
    if ( process_type == switches ::kRendererProcess) 
	{
        rv = RendererMain(main_params );
    } else if (process_type == switches:: kPluginProcess) 
	{
#if defined (OS_WIN)
		rv = PluginMain(main_params );
#endif
    } 
	else if (process_type == switches:: kWorkerProcess) 
	{
#if defined (OS_WIN)
		rv = WorkerMain(main_params );
#endif
    }
	else if (process_type .empty()) 
	{
#if defined (OS_LINUX)
		// gtk_init() can change |argc| and |argv|, but nobody else uses them.
		gtk_init(&argc, const_cast<char***>(&argv));
#endif

    ScopedOleInitializer ole_initializer;
    rv = BrowserMain(main_params );
    } 
	else 
    {
		NOTREACHED() << "Unknown process type";
    }

5) 这里以BrowserMain函数入口为例(通常我们会进入到这里,表示启动一个Browser application)。BrowserMain函数会做一些Browser相关的初始化工作,然后根据命令行参数,来决定是以什么方式来启动Browser Window。
a) 根据命令行参数来初始化BrowserProcess对象:

scoped_ptr< BrowserProcess> browser_process ;
	if ( parsed_command_line.HasSwitch (switches:: kImport)) {
		// We use different BrowserProcess when importing so no GoogleURLTracker is
		// instantiated (as it makes a URLRequest and we don't have an IO thread,
		// see bug #1292702).
		browser_process. reset(new FirstRunBrowserProcess(parsed_command_line ));
		is_first_run = false;
    } else {
		browser_process. reset(new BrowserProcessImpl( parsed_command_line));
    }

在BrowserProcessImpl的构造函数中,会将一个全局的browserProcess*指针进行初始化:

g_browser_process = this;  // line 112 of browser_process_impl.cc

BrowserProcessImpl继承于BrowserProcess和NonThreadSafe。
FirstRunBrowserProcess继承于BrowserProcessImpl.

b) 调用BrowserInit::ProcessCommandLine,这个函数调用LaunchBrowser(调用LaunchBrowserImpl函数)去启动,OpenURLsInBrowser (这个函数将会初始化一个Browser实例对象,然后在其上调用AddTabWithURL函数去实例化一些TabContents对象。 之后便调用browser->window()->Show()去显示browser window。最后便进入了UI事件循环系统。

int result_code = ResultCodes ::NORMAL_EXIT;
	if ( parameters .ui_task ) {
	if ( pool ) pool -> Recycle();
		MessageLoopForUI:: current ()->PostTask ( FROM_HERE, parameters .ui_task );
		RunUIMessageLoop( browser_process .get ());
	} else if (BrowserInit :: ProcessCommandLine( parsed_command_line ,
											std ::wstring (), local_state, true ,
											profile , &result_code )) {
	if ( pool ) pool -> Recycle();
		RunUIMessageLoop( browser_process .get ());
	}

BrowserInit::LaunchBrowserImpl这个函数做以下事情:

LaunchWithProfile lwp(cur_dir, command_line);
	bool launched = lwp.Launch(profile, process_startup);

BrowserInit::Launch() 这个函数实际上做以下事情:

// Open the required browser windows and tabs.
    // First, see if we're being run as a web application (thin frame window).
	if (!OpenApplicationURL(profile)) {
		std::vector<GURL> urls_to_open = GetURLsFromCommandLine(profile_);
		RecordLaunchModeHistogram(urls_to_open.empty()?
									LM_TO_BE_DECIDED : LM_WITH_URLS);
		// Always attempt to restore the last session. OpenStartupURLs only opens
		// the home pages if no additional URLs were passed on the command line.
		if (!OpenStartupURLs(process_startup, urls_to_open)) {
			// Add the home page and any special first run URLs.
			Browser* browser = NULL;
			if (urls_to_open.empty())
			AddStartupURLs(&urls_to_open);
			else
			browser = BrowserList::GetLastActive();
			OpenURLsInBrowser(browser, process_startup, urls_to_open);
			// NOTE: 这个函数返回的browser指针并没有被销毁,内存泄漏?
			// 其实并没有,Browser生命期交给了BrowserView来管理
		}
	} else {
		RecordLaunchModeHistogram(LM_AS_WEBAPP);
	}

// OpenURLsInBrowser 添加Tag with URL到browser windows,然后返回一个Browser实例化对象。

Browser * BrowserInit :: LaunchWithProfile::OpenURLsInBrowser (
    					Browser* browser ,
    					bool process_startup ,
    					const std ::vector < GURL>& urls ) {
    DCHECK(! urls .empty ());
	if (! browser || browser -> type() != Browser ::TYPE_NORMAL )
    browser = Browser ::Create ( profile_);

	for ( size_t i = 0; i < urls .size (); ++ i) {
		TabContents* tab = browser -> AddTabWithURL(
        urls [i ], GURL(), PageTransition ::START_PAGE , ( i == 0), NULL );
		if ( i == 0 && process_startup )
			AddCrashedInfoBarIfNecessary (tab );
	}
    browser-> window ()->Show ();
    // TODO(jcampan): http://crbug.com/8123 we should not need to set the initial
    //                focus explicitly.
    browser-> GetSelectedTabContents ()->SetInitialFocus ();
    return browser ;
}


-EOF-
睿初科技软件开发技术博客,转载请注明出处

blog comments powered by Disqus