我們知道一般的Windows程序都會有一個WinMain函數,Chrome的這個函數在chrome\app\chrome_exe_main_win.cc這個文件中:
1 int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prev, wchar_t*, int) { 2 3 // Initialize the commandline singleton from the environment. 4 CommandLine::Init(0, NULL); 5 // The exit manager is in charge of calling the dtors of singletons. 6 base::AtExitManager exit_manager; 7 8 MetroDriver metro_driver; 9 if (metro_driver.in_metro_mode()) 10 return metro_driver.RunInMetro(instance, &RunChrome); 11 // Not in metro mode, proceed as normal. 12 return RunChrome(instance); 13 }
首先,這個函數初始化了CommandLine,它是一個singleton,用來保存和管理當前進程中的所有參數。然后又創建了一個AtExitManager,它是用來負責所有singleton的銷毀工作的。若是在Win8下並滿足MetroDriver的檢測的話,就可能通過MetroDriver::RunInMetro來啟動Chrome。下面將詳細看一下用的比較多的RunChrome函數。
1 int RunChrome(HINSTANCE instance) { 2 bool exit_now = true; 3 // We restarted because of a previous crash. Ask user if we should relaunch. 4 if (ShowRestartDialogIfCrashed(&exit_now)) { 5 if (exit_now) 6 return content::RESULT_CODE_NORMAL_EXIT; 7 } 8 9 // Initialize the sandbox services. 10 sandbox::SandboxInterfaceInfo sandbox_info = {0}; 11 content::InitializeSandboxInfo(&sandbox_info); 12 13 // Load and launch the chrome dll. *Everything* happens inside. 14 MainDllLoader* loader = MakeMainDllLoader(); 15 int rc = loader->Launch(instance, &sandbox_info); 16 loader->RelaunchChromeBrowserWithNewCommandLineIfNeeded(); 17 delete loader; 18 return rc; 19 }
RunChrome中的第一個先調用ShowRestartDialogIfCrashed,Chrome若是之前崩潰了,這個函數就互彈出一個MessageBox,告訴你崩潰的情況,是否需要再開啟Chrome,若要開啟,下面的代碼再跑一遍,重新打開Chrome。
接下來初始化sandbox,sandbox對象創建完后,必須要用content::InitializeSandboxInfo初始化。
由於,Chrome的實際內容並不在Chrome.exe中,而在Chrome.dll中,所以下面有個創建MainDllLoader對象的過程 —— MakeMainDllLoader()。然后通過這個對象的Launch方法將整個Chrome加載起來,這個方法有兩個參數:一個是WinMain中的HINSTANCE,另一個是之前創建的那個sandbox。
1 int MainDllLoader::Launch(HINSTANCE instance, 2 sandbox::SandboxInterfaceInfo* sbox_info) { 3 string16 version; 4 string16 file; 5 dll_ = Load(&version, &file); 6 if (!dll_) 7 return chrome::RESULT_CODE_MISSING_DATA; 8 9 scoped_ptr<base::Environment> env(base::Environment::Create()); 10 env->SetVar(chrome::kChromeVersionEnvVar, WideToUTF8(version)); 11 12 InitCrashReporter(); 13 OnBeforeLaunch(file); 14 15 DLL_MAIN entry_point = 16 reinterpret_cast<DLL_MAIN>(::GetProcAddress(dll_, "ChromeMain")); 17 if (!entry_point) 18 return chrome::RESULT_CODE_BAD_PROCESS_TYPE; 19 20 int rc = entry_point(instance, sbox_info); 21 return OnBeforeExit(rc, file); 22 }
這個函數中,先通過Load方法將Chrome.dll加載進來,dll_中保存了DLL句柄,下面還有其他一些准備工作。接着在GetProcAddress這里進入正題了,尋找Chrome.dll這個模塊中名為ChromeMain的函數,entry_point中保存了這個函數指針,最后通過調用這個函數進到Chrome.dll模塊中執行剩余的工作。
