(FFOS Gecko & Gaia) OTA - 进入Gecko层
代码位置:gecko/b2g/components/UpdatePrompt.js
SystemApp发出'force-update-check'事件,也就从gaia进入到了gecko层。
1. 首先大概介绍一下UpdatePrompt.js。
(a) UpdatePrompt.js里包含了2个对象,分别是UpdatePrompt和UpdateCheckListener。
(b) UpdatePrompt实现了“@mozilla.org/updates/update-prompt;1”这个XPCOM组件。在gecko/b2g/components/B2GComponents.manifest中有注册:
#ifdef MOZ_UPDATER # UpdatePrompt.js component {88b3eb21-d072-4e3b-886d-f89d8c49fe59} UpdatePrompt.js contract @mozilla.org/updates/update-prompt;1 {88b3eb21-d072-4e3b-886d-f89d8c49fe59} category system-update-provider MozillaProvider @mozilla.org/updates/update-prompt;1,{88b3eb21-d072-4e3b-886d-f89d8c49fe59} #endif
(c) UpdatePrompt还实现了5个interface,分别是nsISystemUpdateProvider、nsIUpdatePrompt、nsIObserver、nsIRequestObserver和nsIProgressEventSink。
(d) UpdateCheckListener实现了nsIUpdateCheckListener。
2. “@mozilla.org/updates/update-prompt;1”在B2G启动后会自动被加载,代码在gecko/b2g/chrome/content/shell.js中:
window.addEventListener('ContentStart', function update_onContentStart() { Cu.import('resource://gre/modules/WebappsUpdater.jsm'); WebappsUpdater.handleContentStart(shell); let promptCc = Cc["@mozilla.org/updates/update-prompt;1"]; if (!promptCc) { return; } let updatePrompt = promptCc.createInstance(Ci.nsIUpdatePrompt); if (!updatePrompt) { return; } updatePrompt.wrappedJSObject.handleContentStart(shell); });
3. handleContentStart:
通过SystemAppProxy注册event listener来监听‘mozContentEvent’。
handleContentStart: function UP_handleContentStart() { SystemAppProxy.addEventListener("mozContentEvent", this); },
4. SystemAppProxy的代码位置在:gecko/b2g/components/SystemAppProxy.jsm
// Listen for dom events on the system app addEventListener: function systemApp_addEventListener() { let content = this._frame ? this._frame.contentWindow : null; if (!content) { this._pendingListeners.push(arguments); return false; } content.addEventListener.apply(content, arguments); return true; },
5. UpdatePrompt.handleEvent
上一步注册了mozContentEvent的监听,handleEvent是回调函数,主要对4种消息进行处理。其中‘force-update-check’正是上一篇分析的从SystemApp发送过来的event。此时OTA流程从gaia走到了gecko中。
handleEvent: function UP_handleEvent(evt) { if (evt.type !== "mozContentEvent") { return; } let detail = evt.detail; if (!detail) { return; } switch (detail.type) { case "force-update-check": this.forceUpdateCheck(); break; case "update-available-result": this.handleAvailableResult(detail); // If we started the apply prompt timer, this means that we're waiting // for the user to press Later or Install Now. In this situation we // don't want to clear this._update, becuase handleApplyPromptResult // needs it. if (this._applyPromptTimer == null && !this._waitingForIdle) { this._update = null; } break; case "update-download-cancel": this.handleDownloadCancel(); break; case "update-prompt-apply-result": this.handleApplyPromptResult(detail); break; } },
6. UpdatePrompt.forceUpdateCheck函数
check的工作交给了另外一个XPCOM组件"@mozilla.org/updates/update-checker;1",调用它的checkForUpdates函数,并传递一个UpdateCheckListener进去,这个UpdateCheckListener是UpdatePrompt对象初始化时,内部new出来的,用于接收checker的事件回调。
forceUpdateCheck: function UP_forceUpdateCheck() { log("Forcing update check"); let checker = Cc["@mozilla.org/updates/update-checker;1"] .createInstance(Ci.nsIUpdateChecker); checker.checkForUpdates(this._updateCheckListener, true); },