(FFOS Gecko & Gaia) OTA - 重回Gaia层
SystemApp中的UpdateManager作为gaia和gecko的通信桥梁,会接收gecko中UpdatePrompt发送的'update-available'事件。
1. UpdateManager.handleEvent
var detail = evt.detail; if (detail.type && detail.type === 'update-available') {
// systemUpdatable是在UpdateManager初始化时new出来的,UpdateManager中只会存在一个SystemUpdatable。 this.systemUpdatable.size = detail.size; this.systemUpdatable.rememberKnownUpdate();
// 添加到UpdateManager中的updatesQueue队列。 this.addToUpdatesQueue(this.systemUpdatable); }
2. UpdateManager.addToUpdatesQueue
逻辑比较简单,做一些check之后,push到updatesQueue中,然后render UI。
addToUpdatesQueue: function um_addToUpdatesQueue(updatable) { if (this._downloading) { return; } if (updatable.app && updatable.app.installState !== 'installed') { return; } if (updatable.app && this.updatableApps.indexOf(updatable) === -1) { return; } var alreadyThere = this.updatesQueue.some(function lookup(u) { return (u.app === updatable.app); }); if (alreadyThere) { return; } this.updatesQueue.push(updatable); if (this._notificationTimeout === null) { this._notificationTimeout = setTimeout( this.displayNotificationAndToaster.bind(this), this.NOTIFICATION_BUFFERING_TIMEOUT); } this.render(); },
3. 触发下载
UpdateManager是gaia层的,在它初始化时会做一些UI相关的操作,比如download button的bind和listen。
this.downloadButton = document.getElementById('updates-download-button'); this.downloadButton.onclick = this.requestDownloads.bind(this);
下载的启动又分为以下几个步骤:
(1) UpdateManager.requestDownloads
requestDownloads: function um_requestDownloads(evt) { evt.preventDefault();
// 通过DataConnection去下载 if (evt.target == this.downloadViaDataConnectionButton) { this._startedDownloadUsingDataConnection = true; this.startDownloads(); } else { this.promptOrDownload(); } },
(2) UpdateManager.promptOrDownload
promptOrDownload: function um_promptOrDownload() { var self = this; if (self.downloadDialog.dataset.online == 'false') { self.showPromptNoConnection(); return; } // check wifi if (self._wifiAvailable()) { self._startedDownloadUsingDataConnection = false; self.startDownloads(); return; } …… }
(3) UpdateManager.startDownloads
startDownloads: function um_startDownloads() { this.downloadViaDataConnectionDialog.classList.remove('visible'); this._closeDownloadDialog(); Service.request('UtilityTray:show'); var checkValues = {}; var dialog = this.downloadDialogList; var checkboxes = dialog.querySelectorAll('input[type="checkbox"]'); for (var i = 0; i < checkboxes.length; i++) { var checkbox = checkboxes[i]; checkValues[checkbox.dataset.position] = checkbox.checked; }
// 遍历updatesQueue this.updatesQueue.forEach(function(updatable, index) { // The user opted out of the download if (updatable.app && !checkValues[index]) { return; } updatable.download(); }); this._downloadedBytes = 0; this.render(); },
(4) SystemUpdatable.download()
代码位置:gaia/apps/system/js/updatable.js
由走回了UpdateManager,添加到downloadsQueue,并且发送了一个'update-available-result'
SystemUpdatable.prototype.download = function() { if (this.downloading) { return; } this.downloading = true; this.paused = false; UpdateManager.addToDownloadsQueue(this); this.progress = 0; this._dispatchEvent('update-available-result', 'download'); };
(5) UpdateManager.addToDownloadsQueue
addToDownloadsQueue: function um_addToDownloadsQueue(updatable) { if (updatable.app && this.updatableApps.indexOf(updatable) === -1) { return; } var alreadyThere = this.downloadsQueue.some(function lookup(u) { return (u.app === updatable.app); }); if (alreadyThere) { return; } this.downloadsQueue.push(updatable); if (this.downloadsQueue.length === 1) { this._downloading = true; Service.request('incDownloads'); this._wifiLock = navigator.requestWakeLock('wifi'); this.displayNotificationIfHidden(); this.render(); } },
4. 触发下载2
看完了‘3’的分析,调来调去的好像也没有触发什么下载。
回头看看本文最开始的部分,是从接收到'update-available'开始的,最后也只是向UpdatePrompt返回了一个'update-available-result'。
其实UpdateManager和UpdatePrompt都是通过这种event来通信的,UpdateManager会做一些UI相关的操作,实际动作还是会交给UpdatePrompt去转发和实现。
(1) UpdatePrompt --- update-xxx ---> UpdateManager
(2) UpdateManager --- update-xxx-result ---> UpdatePrompt