![Chromium擴(kuò)展(Extension)加載過(guò)程分析_第1頁(yè)](http://file4.renrendoc.com/view/c841f68c8594b0763232c25d97ad992e/c841f68c8594b0763232c25d97ad992e1.gif)
![Chromium擴(kuò)展(Extension)加載過(guò)程分析_第2頁(yè)](http://file4.renrendoc.com/view/c841f68c8594b0763232c25d97ad992e/c841f68c8594b0763232c25d97ad992e2.gif)
![Chromium擴(kuò)展(Extension)加載過(guò)程分析_第3頁(yè)](http://file4.renrendoc.com/view/c841f68c8594b0763232c25d97ad992e/c841f68c8594b0763232c25d97ad992e3.gif)
![Chromium擴(kuò)展(Extension)加載過(guò)程分析_第4頁(yè)](http://file4.renrendoc.com/view/c841f68c8594b0763232c25d97ad992e/c841f68c8594b0763232c25d97ad992e4.gif)
![Chromium擴(kuò)展(Extension)加載過(guò)程分析_第5頁(yè)](http://file4.renrendoc.com/view/c841f68c8594b0763232c25d97ad992e/c841f68c8594b0763232c25d97ad992e5.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Chromium擴(kuò)展(Extension)加載過(guò)程分析Chromium在啟動(dòng)的時(shí)候,會(huì)根據(jù)當(dāng)前用戶的Profile創(chuàng)建一個(gè)ExtensionService。ExtensionService在創(chuàng)建過(guò)程中,會(huì)加載當(dāng)前已經(jīng)安裝的所有Extension,并且將它們注冊(cè)在一個(gè)ExtensionRegistry中。以后通過(guò)這個(gè)ExtensionRegistry,就可以得到當(dāng)前可用的Extension的信息了。本文接下來(lái)就分析Extension的加載過(guò)程。Chromium的啟動(dòng),指的實(shí)際上是Chromium的Browser進(jìn)程的啟動(dòng)。關(guān)于Chromium的多進(jìn)程架構(gòu),可以參考前面的文章。Chromium的Browser進(jìn)程在啟動(dòng)之后,會(huì)創(chuàng)建一系列的StartupTask。每一個(gè)StartupTask都會(huì)負(fù)責(zé)初始化相應(yīng)的模塊。上述的ExtensionService就是在一個(gè)StartupTask中創(chuàng)建的,如圖1所示:ExtensionService在創(chuàng)建的過(guò)程中,會(huì)通過(guò)一個(gè)InstalledLoader加載當(dāng)前已經(jīng)安裝的所有Extension,并且將那些設(shè)置為Enabled的Extension注冊(cè)到ExtensionRegistry中,從而得到一個(gè)當(dāng)前可用的Extension列表。接下來(lái),我們就從Chromium的Browser進(jìn)程的啟動(dòng)開(kāi)始,分析它加載Extension的過(guò)程。在前面文章一文中,我們以ContentShellAPK為例,分析了Browser進(jìn)程的啟動(dòng)過(guò)程。在這個(gè)啟動(dòng)過(guò)程中,會(huì)創(chuàng)建一個(gè)BrowserStartupController對(duì)象,并且調(diào)用這個(gè)BrowserStartupController對(duì)象的成員函數(shù)startBrowserProcessesAsync異步啟動(dòng)和初始化Chromium的Content模塊,如下所示:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicclassBrowserStartupController{publicvoidstartBrowserProcessesAsync(finalStartupCallbackcallback)throwsProcessInitException{//Browserprocesshasnotbeenfullystartedyet,sowedeferexecutingthecallback.mAsyncStartupCallbacks.add(callback);if(!mHasStartedInitializingBrowserProcess){prepareToStartBrowserProcess(MAX_RENDERERS_LIMIT);if(contentStart()>0){//Failed.Thecallbacksmaynothaverun,sorunthem.enqueueCallbackExecution(STARTUP_FAILURE,NOT_ALREADY_STARTED);}}}}這個(gè)函數(shù)定義在文件external/chromium_org/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java中。在Browser進(jìn)程的Content模塊還沒(méi)有啟動(dòng)過(guò)的情況下,BrowserStartupController類的成員變量mHasStartedInitializingBrowserProcess的值會(huì)等于false。在這種情況下,BrowserStartupController類的成員函數(shù)startBrowserProcessesAsync會(huì)做兩件事情:1.調(diào)用成員函數(shù)prepareToStartBrowserProcess在VM中加載libcontent_shell_content_view.so。2.調(diào)用成員函數(shù)contentStart啟動(dòng)和初始化Content模塊。從文章這篇文章可以知道,VM在加載so的過(guò)程中,將會(huì)調(diào)用它導(dǎo)出的一個(gè)名稱為JNI_OnLoad的函數(shù)。對(duì)libcontent_shell_content_view.so來(lái)說(shuō),它導(dǎo)出的JNI_OnLoad函數(shù)的實(shí)現(xiàn)如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片//ThisiscalledbytheVMwhenthesharedlibraryisfirstloaded.JNI_EXPORTjintJNI_OnLoad(JavaVM*vm,void*reserved){content::SetContentMainDelegate(newcontent::ShellMainDelegate());returnJNI_VERSION_1_4;}這個(gè)函數(shù)定義在文件external/chromium_org/content/shell/android/shell_library_loader.cc中。函數(shù)JNI_OnLoad將會(huì)創(chuàng)建一個(gè)ShellMainDelegate對(duì)象,并且調(diào)用函數(shù)SetContentMainDelegate將它保存在一個(gè)全局變量g_content_main_delegate中,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片namespace{LazyInstance<scoped_ptr<contentmaindelegate>>g_content_main_delegate=LAZY_INSTANCE_INITIALIZER;}//namespacevoidSetContentMainDelegate(ContentMainDelegate*delegate){DCHECK(!g_content_main_delegate.Get().get());g_content_main_delegate.Get().reset(delegate);}這個(gè)函數(shù)定義在文件external/chromium_org/content/app/android/content_main.cc中。這一步執(zhí)行完成后,回到前面分析的BrowserStartupController類的成員函數(shù)startBrowserProcessesAsync中,它接下來(lái)將會(huì)調(diào)用另外一個(gè)成員函數(shù)contentStart啟動(dòng)和初始化Content模塊,如下所示:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicclassBrowserStartupController{intcontentStart(){returnContentMain.start();}}這個(gè)函數(shù)定義在文件external/chromium_org/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java中。BrowserStartupController類的成員函數(shù)contentStart調(diào)用ContentMain類的靜態(tài)成員函數(shù)start在Browser進(jìn)程中啟動(dòng)和初始化Content模塊。在前面文章一文中,我們已經(jīng)分析過(guò)ContentMain類的靜態(tài)成員函數(shù)start的實(shí)現(xiàn)了。它最終會(huì)調(diào)用到C++層的一個(gè)函數(shù)Start啟動(dòng)和初始化Content模塊,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片namespace{LazyInstance<scoped_ptr<ContentMainRunner>>g_content_runner=LAZY_INSTANCE_INITIALIZER;}//namespacestaticjintStart(JNIEnv*env,jclassclazz){if(!g_content_runner.Get().get()){ContentMainParamsparams(g_content_main_delegate.Get().get());g_content_runner.Get().reset(ContentMainRunner::Create());g_content_runner.Get()->Initialize(params);}returng_content_runner.Get()->Run();}這個(gè)函數(shù)定義在文件external/chromium_org/content/app/Android/content_main.cc中。函數(shù)Start首先判斷一個(gè)全局變量g_content_runner是否已經(jīng)指向了一個(gè)ContentMainRunner對(duì)象。如果還沒(méi)有指向,那么就會(huì)調(diào)用ContentMainRunner類的靜態(tài)成員函數(shù)Create創(chuàng)建一個(gè)ContentMainRunner對(duì)象,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片ContentMainRunner*ContentMainRunner::Create(){returnnewContentMainRunnerImpl();}這個(gè)函數(shù)定義在文件external/chromium_org/content/app/content_main_runner.cc中。從這里可以看到,ContentMainRunner類的靜態(tài)成員函數(shù)Create創(chuàng)建的實(shí)際上是一個(gè)ContentMainRunnerImpl對(duì)象。這個(gè)ContentMainRunnerImpl對(duì)象返回給前面分析的函數(shù)Start之后,就會(huì)保存在全局變量g_content_runner中。函數(shù)Start獲得了新創(chuàng)建的ContentMainRunnerImpl對(duì)象之后,會(huì)調(diào)用它的成員函數(shù)Initialize,并且將全局變量g_content_main_delegate指向的ShellMainDelegate對(duì)象封裝在一個(gè)類型為ContentMainParams的參數(shù)中傳遞給它,讓它執(zhí)行初始化工作。ContentMainRunnerImpl類的成員函數(shù)Initialize的實(shí)現(xiàn)如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片classContentMainRunnerImpl:publicContentMainRunner{public:virtualintInitialize(constContentMainParams¶ms)OVERRIDE{delegate_=params.delegate;}private:ContentMainDelegate*delegate_;};這個(gè)函數(shù)定義在文件external/chromium_org/content/app/content_main_runner.cc中。ContentMainRunnerImpl類的成員函數(shù)Initialize將封裝在參數(shù)params中的一個(gè)ShellMainDelegate對(duì)象保存在成員變量delegate_中,也就是ContentMainRunnerImpl類的成員變量delegate_指向了一個(gè)ShellMainDelegate對(duì)象?;氐角懊娣治龅暮瘮?shù)Start中,它最后調(diào)用前面創(chuàng)建的ContentMainRunnerImpl對(duì)象的成員函數(shù)Run啟動(dòng)和初始化Content模塊,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片classContentMainRunnerImpl:publicContentMainRunner{public:virtualintRun()OVERRIDE{constCommandLine&command_line=*CommandLine::ForCurrentProcess();std::stringprocess_type=command_line.GetSwitchValueASCII(switches::kProcessType);MainFunctionParamsmain_params(command_line);#if!defined(OS_IOS)returnRunNamedProcessTypeMain(process_type,main_params,delegate_);#elsereturn1;#endif}};這個(gè)函數(shù)定義在文件external/chromium_org/content/app/content_main_runner.cc中。ContentMainRunnerImpl類的成員函數(shù)Run首先檢查當(dāng)前進(jìn)程是否指定了switches::kProcessType啟動(dòng)選項(xiàng)。如果指定了,那么就會(huì)獲取它的值。獲取到的值保存在本地變量process_type中,表示當(dāng)前進(jìn)程的類型。Browser進(jìn)程沒(méi)有指定switches::kProcessType啟動(dòng)選項(xiàng),因此本地變量process_type的值將為空,表示當(dāng)前進(jìn)程是Browser進(jìn)程。ContentMainRunnerImpl類的成員函數(shù)Run接下來(lái)調(diào)用函數(shù)RunNamedProcessTypeMain啟動(dòng)和初始化Content模塊,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片intRunNamedProcessTypeMain(conststd::string&process_type,constMainFunctionParams&main_function_params,ContentMainDelegate*delegate){staticconstMainFunctionkMainFunctions[]={#if!defined(CHROME_MULTIPLE_DLL_CHILD){"",BrowserMain},#endif#if!defined(CHROME_MULTIPLE_DLL_BROWSER)#ifdefined(ENABLE_PLUGINS)#if!defined(OS_LINUX){switches::kPluginProcess,PluginMain},#endif{switches::kWorkerProcess,WorkerMain},{switches::kPpapiPluginProcess,PpapiPluginMain},{switches::kPpapiBrokerProcess,PpapiBrokerMain},#endif//ENABLE_PLUGINS{switches::kUtilityProcess,UtilityMain},{switches::kRendererProcess,RendererMain},{switches::kGpuProcess,GpuMain},#endif//!CHROME_MULTIPLE_DLL_BROWSER};for(size_ti=0;i<arraysize(kMainFunctions);++i){if(process_type==kMainFunctions[i].name){if(delegate){intexit_code=delegate->RunProcess(process_type,main_function_params);#ifdefined(OS_ANDROID)//InAndroid'sbrowserprocess,thenegativeexitcodedoesn'tmeanthe//defaultbehaviorshouldbeusedastheUImessageloopismanagedby//theJavaandthebrowserprocess'sdefaultbehaviorisalways//overridden.if(process_type.empty())returnexit_code;#endifif(exit_code>=0)returnexit_code;}returnkMainFunctions[i].function(main_function_params);}}return1;}這個(gè)函數(shù)定義在文件external/chromium_org/content/app/content_main_runner.cc中。函數(shù)RunNamedProcessTypeMain在內(nèi)部定義了一個(gè)靜態(tài)數(shù)組kMainFunctions,它會(huì)根據(jù)參數(shù)process_type的值在這個(gè)數(shù)組中找到對(duì)應(yīng)的函數(shù)執(zhí)行,也就是不同的進(jìn)程執(zhí)行不同的函數(shù)來(lái)啟動(dòng)和初始化Content模塊。從前面文章這三篇文章可以知道,Render進(jìn)程、GPU進(jìn)程和Plugin進(jìn)程分別通過(guò)調(diào)用函數(shù)RendererMain、GpuMain和PluginMain啟動(dòng)和初始化Content模塊。對(duì)于Browser進(jìn)程來(lái)說(shuō),情況有點(diǎn)特殊,它并沒(méi)有調(diào)用函數(shù)BrowserMain來(lái)啟動(dòng)和初始化Content模塊。這是因?yàn)楫?dāng)參數(shù)process_type的值等于空時(shí),函數(shù)RunNamedProcessTypeMain調(diào)用完成另外一個(gè)參數(shù)delegate指向的一個(gè)ShellMainDelegate對(duì)象的成員函數(shù)RunProcess后,就會(huì)直接直接返回,從而不會(huì)執(zhí)行函數(shù)BrowserMain。這意味著B(niǎo)rowser進(jìn)程是通過(guò)調(diào)用ShellMainDelegate類的成員函數(shù)RunProcess來(lái)啟動(dòng)和初始化Content模塊的,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片intShellMainDelegate::RunProcess(conststd::string&process_type,constMainFunctionParams&main_function_params){browser_runner_.reset(BrowserMainRunner::Create());returnShellBrowserMain(main_function_params,browser_runner_);}這個(gè)函數(shù)定義在文件external/chromium_org/content/shell/app/shell_main_delegate.cc中。ShellMainDelegate類的成員函數(shù)RunProcess首先調(diào)用BrowserMainRunner類的靜態(tài)成員函數(shù)Create創(chuàng)建一個(gè)BrowserMainRunnerImpl對(duì)象,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片BrowserMainRunner*BrowserMainRunner::Create(){returnnewBrowserMainRunnerImpl();}這個(gè)函數(shù)定義在文件external/chromium_org/content/browser/browser_main_runner.cc中。創(chuàng)建出來(lái)的BrowserMainRunnerImpl對(duì)象將會(huì)保存在ShellMainDelegate類的成員變量browser_runner_中,并且這個(gè)BrowserMainRunnerImpl對(duì)象會(huì)傳遞給另外一個(gè)函數(shù)ShellBrowserMain進(jìn)行處理,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片//MainroutineforrunningastheBShellBrowserMain(constcontent::MainFunctionParams¶meters,constscoped_ptr<content::BrowserMainRunner>&main_runner){intexit_code=main_runner->Initialize(parameters);if(exit_code>=0)returnexit_code;returnexit_code;}這個(gè)函數(shù)定義在文件external/chromium_org/content/shell/browser/shell_browser_main.cc中。函數(shù)ShellBrowserMain主要是調(diào)用參數(shù)main_runner指向的一個(gè)BrowserMainRunnerImpl對(duì)象的成員函數(shù)Initialize在Browser進(jìn)程中初始化Content模塊。BrowserMainRunnerImpl類的成員函數(shù)Initialize的返回值將會(huì)大于等于0,這時(shí)候函數(shù)ShellBrowserMain就會(huì)沿著調(diào)用路徑一直返回到Java層去了,從而使得當(dāng)前線程(Browser進(jìn)程的主線程)在Java層進(jìn)入到消息循環(huán)中去。以上就是ContentShellAPK的Browser進(jìn)程的啟動(dòng)流程。ChromeAPK的Browser進(jìn)程的啟動(dòng)流程也是類似的,它們最后都會(huì)通過(guò)調(diào)用BrowserMainRunnerImpl類的成員函數(shù)Initialize初始化Content模塊。為了方便描述,接下來(lái)我們就將以ChromeAPK為例,繼續(xù)分析BrowserMainRunnerImpl類的成員函數(shù)Initialize的實(shí)現(xiàn),從中就可以看到Extension的加載過(guò)程。BrowserMainRunnerImpl類的成員函數(shù)Initialize的實(shí)現(xiàn)如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片classBrowserMainRunnerImpl:publicBrowserMainRunner{public:virtualintInitialize(constMainFunctionParams¶meters)OVERRIDE{if(!initialization_started_){initialization_started_=true;main_loop_.reset(newBrowserMainLoop(parameters));main_loop_->Init();}main_loop_->CreateStartupTasks();intresult_code=main_loop_->GetResultCode();if(result_code>0)returnresult_code;//Return-1toindicatenoearlytermination.return-1;}};這個(gè)函數(shù)定義在文件external/chromium_org/content/browser/browser_main_runner.cc中。BrowserMainRunnerImpl類的成員函數(shù)Initialize首先檢查成員變量initialization_started_的值是否不等于true。如果不等于true,那么就說(shuō)明Browser進(jìn)程還沒(méi)有執(zhí)行過(guò)初始化操作。在這種情況下,BrowserMainRunnerImpl類的成員函數(shù)Initialize接下來(lái)就會(huì)創(chuàng)建一個(gè)BrowserMainLoop對(duì)象,并且調(diào)用這個(gè)BrowserMainLoop對(duì)象的成員函數(shù)Init執(zhí)行初始化工作,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidBrowserMainLoop::Init(){parts_.reset(GetContentClient()->browser()->CreateBrowserMainParts(parameters_));}這個(gè)函數(shù)定義在文件external/chromium_org/content/browser/browser_main_loop.cc中。BrowserMainLoop對(duì)象的成員函數(shù)Init的主要任務(wù)是創(chuàng)建一個(gè)BrowserMainParts對(duì)象,并且保存在成員變量parts_中。后面會(huì)通過(guò)這個(gè)BrowserMainParts對(duì)象執(zhí)行一些初始化工作。為了創(chuàng)建這個(gè)BrowserMainParts對(duì)象,BrowserMainLoop對(duì)象的成員函數(shù)Init首先調(diào)用函數(shù)GetContentClient獲得一個(gè)ContentClient對(duì)象。對(duì)于ChromeAPK來(lái)說(shuō),這個(gè)ContentClient對(duì)象的實(shí)際類型為ChromeContentClient,也就是這里調(diào)用函數(shù)GetContentClient獲得的是一個(gè)ChromeContentClient對(duì)象。有了這個(gè)ChromeContentClient對(duì)象之后,就可以調(diào)用它的成員函數(shù)browser獲得一個(gè)ChromeContentBrowserClient對(duì)象。有了這個(gè)ChromeContentBrowserClient對(duì)象,就可以調(diào)用它的成員函數(shù)CreateBrowserMainParts創(chuàng)建一個(gè)BrowserMainParts對(duì)象了,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片content::BrowserMainParts*ChromeContentBrowserClient::CreateBrowserMainParts(constcontent::MainFunctionParams¶meters){ChromeBrowserMainParts*main_parts;//ConstructtheMainbrowserpartsbasedontheOStype.#ifdefined(OS_WIN)main_parts=newChromeBrowserMainPartsWin(parameters);#elifdefined(OS_MACOSX)main_parts=newChromeBrowserMainPartsMac(parameters);#elifdefined(OS_CHROMEOS)main_parts=newchromeos::ChromeBrowserMainPartsChromeos(parameters);#elifdefined(OS_LINUX)main_parts=newChromeBrowserMainPartsLinux(parameters);#elifdefined(OS_ANDROID)main_parts=newChromeBrowserMainPartsAndroid(parameters);#elifdefined(OS_POSIX)main_parts=newChromeBrowserMainPartsPosix(parameters);#elseNOTREACHED();main_parts=newChromeBrowserMainParts(parameters);#endifreturnmain_parts;}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/chrome_content_browser_client.cc中。從這里可以看到,在Android平臺(tái)上,ChromeContentBrowserClient類的成員函數(shù)CreateBrowserMainParts創(chuàng)建的是一個(gè)ChromeBrowserMainPartsAndroid對(duì)象。這個(gè)ChromeBrowserMainPartsAndroid對(duì)象是從ChromeBrowserMainParts類繼承下來(lái)的。這一步執(zhí)行完成之后,BrowserMainLoop對(duì)象的成員函數(shù)Init就創(chuàng)建了一個(gè)ChromeBrowserMainPartsAndroid對(duì)象,并且保存在成員變量parts_中。回到前面分析的BrowserMainRunnerImpl類的成員函數(shù)Initialize中,它最后會(huì)調(diào)用前面已經(jīng)初始化好的BrowserMainLoop對(duì)象的成員函數(shù)CreateStartupTasks創(chuàng)建一系列StartupTasks,用來(lái)初始化Content模塊。這其中就包含了一個(gè)類型為PreMainMessageLoopRun的StartupTask,也就是在Browser進(jìn)程的主線程進(jìn)入消息循環(huán)前執(zhí)行的StartupTask,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidBrowserMainLoop::CreateStartupTasks(){//Firsttimethrough,wereallywanttocreateallthetasksif(!startup_task_runner_.get()){#ifdefined(OS_ANDROID)startup_task_runner_=make_scoped_ptr(newStartupTaskRunner(base::Bind(&BrowserStartupComplete),base::MessageLoop::current()->message_loop_proxy()));#elsestartup_task_runner_=make_scoped_ptr(newStartupTaskRunner(base::Callback<void(int)>(),base::MessageLoop::current()->message_loop_proxy()));#endifStartupTaskpre_main_message_loop_run=base::Bind(&BrowserMainLoop::PreMainMessageLoopRun,base::Unretained(this));startup_task_runner_->AddTask(pre_main_message_loop_run);}#ifdefined(OS_ANDROID)if(!BrowserMayStartAsynchronously()){//Asecondrequestforasynchronousstartupcanbeignored,so//StartupRunningTasksAsyncisonlycalledfirsttimethrough.If,however,//thisisarequestforsynchronousstartupthenitmustoverrideany//previouscallforasyncstartup,sowecallRunAllTasksNow()//unconditionally.startup_task_runner_->RunAllTasksNow();}#elsestartup_task_runner_->RunAllTasksNow();#endif}這個(gè)函數(shù)定義在文件external/chromium_org/content/browser/browser_main_loop.cc中。BrowserMainLoop類的成員函數(shù)CreateStartupTasks首先會(huì)檢查成員變量startup_task_runner_是否還沒(méi)有指向一個(gè)StartupTaskRunner對(duì)象。如果沒(méi)有指向,那么就會(huì)創(chuàng)建一個(gè)StartupTaskRunner對(duì)象讓它指向。這個(gè)StartupTaskRunner對(duì)象可以用來(lái)向當(dāng)前線程(Browser進(jìn)程的主線程)的消息隊(duì)列發(fā)送消息,從而可以執(zhí)行指定的StartupTask。類型為PreMainMessageLoopRun的StartupTask綁定了BrowserMainLoop類的成員函數(shù)PreMainMessageLoopRun。這意味著接下來(lái)BrowserMainLoop類的成員函數(shù)PreMainMessageLoopRun會(huì)在Browser進(jìn)程的主線程執(zhí)行,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片intBrowserMainLoop::PreMainMessageLoopRun(){if(parts_){parts_->PreMainMessageLoopRun();}returnresult_code_;}這個(gè)函數(shù)定義在文件external/chromium_org/content/browser/browser_main_loop.cc中。從前面的分析可以知道,BrowserMainLoop類的成員變量parts_指向的是一個(gè)ChromeBrowserMainPartsAndroid對(duì)象。BrowserMainLoop類的成員函數(shù)PreMainMessageLoopRun調(diào)用這個(gè)ChromeBrowserMainPartsAndroid對(duì)象的成員函數(shù)PreMainMessageLoopRun執(zhí)行Browser進(jìn)程在PreMainMessageLoopRun階段的初始化工作。ChromeBrowserMainPartsAndroid類的成員函數(shù)PreMainMessageLoopRun是從父類ChromeBrowserMainParts繼承下來(lái)的,它的實(shí)現(xiàn)如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidChromeBrowserMainParts::PreMainMessageLoopRun(){result_code_=PreMainMessageLoopRunImpl();}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/chrome_browser_main.cc中。ChromeBrowserMainParts類的成員函數(shù)PreMainMessageLoopRun調(diào)用另外一個(gè)成員函數(shù)PreMainMessageLoopRunImpl執(zhí)行Browser進(jìn)程在PreMainMessageLoopRun階段的初始化工作,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片intChromeBrowserMainParts::PreMainMessageLoopRunImpl(){profile_=CreatePrimaryProfile(parameters(),user_data_dir_,parsed_command_line());returnresult_code_;}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/chrome_browser_main.cc中。ChromeBrowserMainParts類的成員函數(shù)PreMainMessageLoopRunImpl執(zhí)行了一系列的初始化工作。其中的一個(gè)初始化工作是為當(dāng)前登錄的用戶創(chuàng)建Profile。這是通過(guò)調(diào)用函數(shù)CreatePrimaryProfile實(shí)現(xiàn)的。在創(chuàng)建Profile的過(guò)程中,就會(huì)加載為當(dāng)前登錄的用戶安裝的Extension。接下來(lái)我們就繼續(xù)分析函數(shù)CreatePrimaryProfile的實(shí)現(xiàn),如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片Profile*CreatePrimaryProfile(constcontent::MainFunctionParams¶meters,constbase::FilePath&user_data_dir,constCommandLine&parsed_command_line){Profile*profile=NULL;#ifdefined(OS_CHROMEOS)||defined(OS_ANDROID)profile=ProfileManager::GetActiveUserProfile();#else#endifif(profile){returnprofile;}returnNULL;}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/chrome_browser_main.cc中。在Android平臺(tái)上,函數(shù)CreatePrimaryProfile調(diào)用ProfileManager類的靜態(tài)成員函數(shù)GetActiveUserProfile獲得當(dāng)前用戶的Profile,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片Profile*ProfileManager::GetActiveUserProfile(){ProfileManager*profile_manager=g_browser_process->profile_manager();Profile*profile=profile_manager->GetActiveUserOrOffTheRecordProfileFromPath(profile_manager->user_data_dir());returnprofile;}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/profiles/profile_manager.cc中。ProfileManager類的靜態(tài)成員函數(shù)GetActiveUserProfile首先在當(dāng)前進(jìn)程(Browser進(jìn)程)中獲得一個(gè)ProfileManager單例對(duì)象。通過(guò)調(diào)用這個(gè)ProfileManager單例對(duì)象的成員函數(shù)user_data_dir可以獲得當(dāng)前用戶的數(shù)據(jù)目錄。有了這個(gè)數(shù)據(jù)目錄之后,再調(diào)用上述ProfileManager單例對(duì)象的成員函數(shù)GetActiveUserOrOffTheRecordProfileFromPath就可以獲得當(dāng)前用戶的Profile,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片Profile*ProfileManager::GetActiveUserOrOffTheRecordProfileFromPath(constbase::FilePath&user_data_dir){#ifdefined(OS_CHROMEOS)#elsebase::FilePathdefault_profile_dir(user_data_dir);default_profile_dir=default_profile_dir.Append(GetInitialProfileDir());returnGetProfile(default_profile_dir);#endif}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/profiles/profile_manager.cc中。ProfileManager類的成員函數(shù)GetActiveUserOrOffTheRecordProfileFromPath首先調(diào)用另外一個(gè)成員函數(shù)etInitialProfileDir獲得Profile目錄。這個(gè)Profile目錄是相對(duì)參數(shù)user_data_dir描述的數(shù)據(jù)目錄之下的。將Profile目錄添加到數(shù)據(jù)目錄之后,就得到Profile目錄的絕對(duì)路徑。有了這個(gè)絕對(duì)路徑之后,ProfileManager類的成員函數(shù)GetActiveUserOrOffTheRecordProfileFromPath就調(diào)用成員函數(shù)GetProfile獲得當(dāng)前用戶的Profile,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片Profile*ProfileManager::GetProfile(constbase::FilePath&profile_dir){TRACE_EVENT0("browser","ProfileManager::GetProfile")//Iftheprofileisalreadyloaded(e.g.,chrome.exelaunchedtwice),just//returnit.Profile*profile=GetProfileByPath(profile_dir);if(NULL!=profile)returnprofile;profile=CreateProfileHelper(profile_dir);DCHECK(profile);if(profile){boolresult=AddProfile(profile);DCHECK(result);}returnprofile;}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/profiles/profile_manager.cc中。ProfileManager類的成員函數(shù)GetProfile首先調(diào)用成員函數(shù)GetProfileInfoByPath檢查是否已經(jīng)為參數(shù)profile_dir描述的Profile目錄創(chuàng)建過(guò)Profile。如果已經(jīng)創(chuàng)建,那么就將該P(yáng)rofile返回給調(diào)用者。否則的話,就會(huì)調(diào)用成員函數(shù)CreateProfileHelper為參數(shù)profile_dir描述的Profile目錄創(chuàng)建一個(gè)Profile,并且調(diào)用另外一個(gè)成員函數(shù)AddProfile將其保存在內(nèi)部,以及返回給調(diào)用者。ProfileManager類的成員函數(shù)AddProfile在將當(dāng)前用戶的Profile保存在內(nèi)部之后,會(huì)根據(jù)Profile的內(nèi)容執(zhí)行相應(yīng)初始化工作,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片boolProfileManager::AddProfile(Profile*profile){RegisterProfile(profile,true);DoFinalInit(profile,ShouldGoOffTheRecord(profile));returntrue;}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/profiles/profile_manager.cc中。ProfileManager類的成員函數(shù)AddProfile首先調(diào)用成員函數(shù)RegisterProfile將參數(shù)profile描述的Profile保存在內(nèi)部,接下來(lái)調(diào)用另外一個(gè)成員函數(shù)DoFinalnit根據(jù)該P(yáng)rofile執(zhí)行相應(yīng)的初始化工作,其中就包括創(chuàng)建ExtensionService,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidProfileManager::DoFinalInit(Profile*profile,boolgo_off_the_record){DoFinalInitForServices(profile,go_off_the_record);}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/profiles/profile_manager.cc中。ProfileManager類的成員函數(shù)DoFinalnit是在調(diào)用成員函數(shù)DoFinalInitForServices的過(guò)程中創(chuàng)建ExtensionService的,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidProfileManager::DoFinalInitForServices(Profile*profile,boolgo_off_the_record){#ifdefined(ENABLE_EXTENSIONS)extensions::ExtensionSystem::Get(profile)->InitForRegularProfile(!go_off_the_record);#endif}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/profiles/profile_manager.cc中。從這里可以看到,在定義了宏ENABLE_EXTENSIONS的情況下,Chromium才會(huì)支持Extension。這時(shí)候ProfileManager類的成員函數(shù)DoFinalInitForServices首先根據(jù)參數(shù)profile描述的Profile獲得一個(gè)ExtensionSystemImpl對(duì)象,然后再調(diào)用這個(gè)ExtensionSystemImpl對(duì)象的成員函數(shù)InitForRegularProfile創(chuàng)建一個(gè)ExtensionService,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidExtensionSystemImpl::InitForRegularProfile(boolextensions_enabled){process_manager_.reset(ProcessManager::Create(profile_));shared_->Init(extensions_enabled);}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/extensions/extension_system_impl.cc中。ExtensionSystemImpl類的成員函數(shù)InitForRegularProfile首先會(huì)調(diào)用ProcessManager類的靜態(tài)成員函數(shù)Create創(chuàng)建一個(gè)ProcessManager對(duì)象,并且保存在成員變量process_manager_。在接下來(lái)一篇文章中,我們就會(huì)看到,Extension的BackgroundPage就是通過(guò)這個(gè)ProcessManager對(duì)象加載起來(lái)的。ExtensionSystemImpl類的成員變量shared_指向的是一個(gè)ExtensionSystemImpl::Shared對(duì)象。ExtensionSystemImpl類的成員函數(shù)InitForRegularProfile調(diào)用這個(gè)ExtensionSystemImpl::Shared對(duì)象的成員函數(shù)Init創(chuàng)建一個(gè)ExtensionService,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidExtensionSystemImpl::Shared::Init(boolextensions_enabled){user_script_master_=newUserScriptMaster(profile_);extension_service_.reset(newExtensionService(ofile_,CommandLine::ForCurrentProcess(),profile_->GetPath().AppendASCII(extensions::kInstallDirectoryName),ExtensionPrefs::Get(profile_),blacklist_.get(),autoupdate_enabled,extensions_enabled,&ready_));extension_service_->Init();}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/extensions/extension_system_impl.cc中。ExtensionService通過(guò)一個(gè)ExtensionService對(duì)象描述。ExtensionSystemImpl::Shared類的成員函數(shù)Init創(chuàng)建了這個(gè)ExtensionService對(duì)象之后,會(huì)保存在成員變量extension_service_中,并且調(diào)用這個(gè)ExtensionService對(duì)象的成員函數(shù)對(duì)其描述的ExtensionService進(jìn)行初始化,如下所示:此外,我們還看到,ExtensionSystemImpl::Shared類的成員函數(shù)Init還創(chuàng)建了一個(gè)UserScriptMaster對(duì)象保存在成員變量user_script_master_中。這個(gè)UserScriptMaster是用來(lái)管理接下來(lái)要加載的Extension的ContentScript的。這一點(diǎn)我們?cè)诤竺娴奈恼聲?huì)進(jìn)行詳細(xì)分析。現(xiàn)在,我們主要關(guān)注ExtensionService的初始化過(guò)程。因此,接下來(lái)我們繼續(xù)分析ExtensionService類的成員函數(shù)Init的實(shí)現(xiàn),如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidExtensionService::Init(){constCommandLine*cmd_line=CommandLine::ForCurrentProcess();if(cmd_line->HasSwitch(switches::kInstallFromWebstore)||cmd_line->HasSwitch(switches::kLimitedInstallFromWebstore)){}else{//LoadAllExtensions()callsOnLoadedInstalledExtensions().extensions::InstalledLoader(this).LoadAllExtensions();//Attempttore-enableextensionswhoseonlydisablereasonisreloading.std::vector<std::string>extensions_to_able;constExtensionSet&disabled_extensions=registry_->disabled_extensions();for(ExtensionSet::const_iteratoriter=disabled_extensions.begin();iter!=disabled_extensions.end();++iter){constExtension*e=iter->get();if(extension_prefs_->GetDisableReasons(e->id())==Extension::DISABLE_RELOAD){extensions_to_enable.push_back(e->id());}}for(std::vector<std::string>::iteratorit=extensions_to_enable.begin();it!=extensions_to_enable.end();++it){EnableExtension(*it);}}}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/extensions/extension_service.cc中。ExtensionService類的成員函數(shù)Init首先檢查Browser進(jìn)程的啟動(dòng)參數(shù)是否包含有switches::kInstallFromWebstore或者switches::kLimitedInstallFromWebstore選項(xiàng)。如果包含有,那么就只會(huì)從WebStore上加載當(dāng)前用戶的Extension。我們假設(shè)沒(méi)有包含這兩個(gè)選項(xiàng),那么ExtensionService類的成員函數(shù)Init將會(huì)從本地加載當(dāng)前用戶的Extension。ExtensionService類的成員函數(shù)Init首先構(gòu)造一個(gè)InstalledLoader對(duì)象,然后再調(diào)用這個(gè)InstalledLoader對(duì)象的成員函數(shù)LoadAllExtensions加載當(dāng)前用戶安裝的所有Extension。這些加載的Extension,即有Enabled的,也有Disabled的。加載后的Extension會(huì)保存在ExtensionService類的成員變量registry_描述的一個(gè)ExtensionRegistry中。ExtensionService類的成員函數(shù)Init最后會(huì)從這個(gè)ExtensionRegistry獲得那些處于Enabled狀態(tài)的Extension,并且調(diào)用另外一個(gè)成員函數(shù)EnableExtension啟用它們。接下來(lái),我們主要關(guān)注Extension的加載過(guò)程。因此,我們繼續(xù)分析InstalledLoader類的成員函數(shù)LoadAllExtensions的實(shí)現(xiàn),如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidInstalledLoader::LoadAllExtensions(){Profile*profile=extension_service_->profile();scoped_ptr<ExtensionPrefs::ExtensionsInfo>extensions_info(extension_prefs_->GetInstalledExtensionsInfo());for(size_ti=0;i<extensions_info->size();++i){if(extensions_info->at(i)->extension_location!=Manifest::COMMAND_LINE)Load(*extensions_info->at(i),should_write_prefs);}}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/extensions/installed_loader.cc中。InstalledLoader類的成員函數(shù)LoadAllExtensions首先獲得當(dāng)前用戶安裝的所有Extension。注意,這些Extension既包括用戶在“chrome://extensions”頁(yè)面中安裝的Extension,也包括用戶在啟動(dòng)Chromium時(shí)通過(guò)命令行參數(shù)“--load-extension”指定的Extension。不過(guò),InstalledLoader類的成員函數(shù)LoadAllExtensions只會(huì)加載那些非命令行參數(shù)指定的Extension。對(duì)于命令行參數(shù)指定的Extension,在ExtensionService初始化結(jié)束后,ExtensionSystem會(huì)通過(guò)另外一個(gè)UnpackedInstaller來(lái)加載它們。InstalledLoader類的成員函數(shù)LoadAllExtensions是通過(guò)調(diào)用另外一個(gè)成員函數(shù)Load加載那些非命令行參數(shù)指定的Extension的,如下所示:[cpp]viewplaincopy在CODE上查看代碼片派生到我的代碼片voidInstalledLoader::Load(constExtensionInfo&info,boolwrite_to_prefs){std::stringerror;scoped_refptr<constExtension>extension(NULL);if(info.extension_manifest){extension=Extension::Create(info.extension_path,info.extension_location,*info.extension_manifest,GetCreationFlags(&info),&error);}else{error=errors::kManifestUnreadable;}extension_service_->AddExtension(extension.get());}這個(gè)函數(shù)定義在文件external/chromium_org/chrome/browser/extensions/installed_loader.cc中。InstalledLoader類的成員函數(shù)Load首先是根據(jù)參數(shù)info描述的Ex
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 紡織布海棉復(fù)合行業(yè)深度研究分析報(bào)告(2024-2030版)
- 2025年度企業(yè)數(shù)字化轉(zhuǎn)型咨詢服務(wù)合同-@-2
- 2025年普通粉項(xiàng)目可行性研究報(bào)告
- 2025-2030年中國(guó)水性環(huán)氧酯金屬防護(hù)漆行業(yè)深度研究分析報(bào)告
- 2025年度新能源技術(shù)研發(fā)與應(yīng)用合作協(xié)議-@-2
- 運(yùn)送頂行業(yè)深度研究報(bào)告
- 成立社團(tuán)申請(qǐng)書(shū)范文
- 少先隊(duì)先鋒入隊(duì)申請(qǐng)書(shū)
- 中國(guó)禮品十字繡行業(yè)市場(chǎng)深度分析及投資規(guī)劃建議報(bào)告
- 2025年分裝竹炭木炭行業(yè)深度研究分析報(bào)告
- 山西省太原市杏花嶺區(qū)年三年級(jí)數(shù)學(xué)第一學(xué)期期末考試模擬試題含解析
- 《農(nóng)機(jī)化促進(jìn)法解讀》課件
- 最高法院示范文本發(fā)布版3.4民事起訴狀答辯狀示范文本
- 2023-2024學(xué)年度上期七年級(jí)英語(yǔ)期末試題
- 2024年燃?xì)廨啓C(jī)值班員技能鑒定理論知識(shí)考試題庫(kù)-下(多選、判斷題)
- 交通法規(guī)課件
- (優(yōu)化版)高中地理新課程標(biāo)準(zhǔn)【2024年修訂版】
- 《Python程序設(shè)計(jì)》課件-1:Python簡(jiǎn)介與應(yīng)用領(lǐng)域
- 各類心理量表大全
- DB12T990-2020建筑類建設(shè)工程規(guī)劃許可證設(shè)計(jì)方案規(guī)范
- DB11T 1481-2024生產(chǎn)經(jīng)營(yíng)單位生產(chǎn)安全事故應(yīng)急預(yù)案評(píng)審規(guī)范
評(píng)論
0/150
提交評(píng)論