(FFOS Gecko & Gaia) OTA - 真正的download

  前面分析了这么多,还没有真正的走到download流程。这篇就去了解真正的downloader。

1. UpdateService.downloadUpdate

  看来这正的worker就是最后new出来的Downloader。

downloadUpdate: function AUS_downloadUpdate(update, background) {
  if (!update)
    throw Cr.NS_ERROR_NULL_POINTER;

  // Don‘t download the update if the update‘s version is less than the
  // current application‘s version or the update‘s version is the same as the
  // application‘s version and the build ID is the same as the application‘s
  // build ID.
  if (update.appVersion &&
      (Services.vc.compare(update.appVersion, Services.appinfo.version) < 0 ||
       update.buildID && update.buildID == Services.appinfo.appBuildID &&
       update.appVersion == Services.appinfo.version)) {
    LOG("UpdateService:downloadUpdate - canceling download of update since " +
        "it is for an earlier or same application version and build ID.\n" +
        "current application version: " + Services.appinfo.version + "\n" +
        "update application version : " + update.appVersion + "\n" +
        "current build ID: " + Services.appinfo.appBuildID + "\n" +
        "update build ID : " + update.buildID);
    cleanupActiveUpdate();
    return STATE_NONE;
  }

  // If a download request is in progress vs. a download ready to resume
  if (this.isDownloading) {
    if (update.isCompleteUpdate == this._downloader.isCompleteUpdate &&
        background == this._downloader.background) {
      LOG("UpdateService:downloadUpdate - no support for downloading more " +
          "than one update at a time");
      return readStatusFile(getUpdatesDir());
    }
    this._downloader.cancel();
  }
  if (AppConstants.platform == "gonk") {
    let um = Cc["@mozilla.org/updates/update-manager;1"].
             getService(Ci.nsIUpdateManager);
    let activeUpdate = um.activeUpdate;
    if (activeUpdate &&
        (activeUpdate.appVersion != update.appVersion ||
         activeUpdate.buildID != update.buildID)) {
      // We have an activeUpdate (which presumably was interrupted), and are
      // about start downloading a new one. Make sure we remove all traces
      // of the active one (otherwise we‘ll start appending the new update.mar
      // the the one that‘s been partially downloaded).
      LOG("UpdateService:downloadUpdate - removing stale active update.");
      cleanupActiveUpdate();
    }
  }
  // Set the previous application version prior to downloading the update.
  update.previousAppVersion = Services.appinfo.version;
  this._downloader = new Downloader(background, this);
  return this._downloader.downloadUpdate(update);
},

2. Downloader.downloadUpdate

  由于downloadUpdate函数比较长,这里只贴出部分代码

/**
 * Download and stage the given update.
 * @param   update
 *          A nsIUpdate object to download a patch for. Cannot be null.
 */
downloadUpdate: function Downloader_downloadUpdate(update) {  ...  // 获取update保存位置  var updateDir = getUpdatesDir();  ...  //根据预设的policy,返回Update中的一个UpdatePatch以下载  this._patch = this._selectPatch(update, updateDir);  ...

   // Only used by gonk
    let status = STATE_NONE;
    if (AppConstants.platform == "gonk") {

    ...

    // 检测之前是否有interrupted update

  }  ...  // 获取patch的URL  var uri = Services.io.newURI(this._patch.URL, null, null);  // 创建一个nsIIncrementalDownload组件去下载  this._request = Cc["@mozilla.org/network/incremental-download;1"].createInstance(Ci.nsIIncrementalDownload);

   LOG("Downloader:downloadUpdate - downloading from " + uri.spec + " to " + patchFile.path);
   var interval = this.background ? getPref("getIntPref",
   PREF_APP_UPDATE_BACKGROUND_INTERVAL, DOWNLOAD_BACKGROUND_INTERVAL) : DOWNLOAD_FOREGROUND_INTERVAL;
   this._request.init(uri, patchFile, DOWNLOAD_CHUNK_SIZE, interval);

   //传递了this,因为Downloader实现了nsIRequest和nsIProcessEventSink接口,实现下载完成、下载进度等的回调
   this._request.start(this, null);


   writeStatusFile(updateDir, STATE_DOWNLOADING);
   this._patch.QueryInterface(Ci.nsIWritablePropertyBag);

   this._patch.state = STATE_DOWNLOADING;

   // 通过UpdateManager保存当前的下载update

   var um = Cc["@mozilla.org/updates/update-manager;1"].getService(Ci.nsIUpdateManager);
   um.saveUpdates();

   return STATE_DOWNLOADING;

}

3. Downloader.onStopRequest 下载完成

  代码很长,贴关键部分

/**
   * When data transfer ceases
   * @param   request
   *          The nsIRequest object for the transfer
   * @param   context
   *          Additional data
   * @param   status
   *          Status code containing the reason for the cessation.
   */
  onStopRequest: function  Downloader_onStopRequest(request, context, status) {
    // 判断是否下载成功
    if (Components.isSuccessCode(status)) {
      // 验证update package
      if (this._verifyDownload()) {
        ...
      }
    } else {
        ...
    }
    ...
    this._patch.state = state;
    // UpdateManager保存状态
    var um = Cc["@mozilla.org/updates/update-manager;1"].
             getService(Ci.nsIUpdateManager);
    if (deleteActiveUpdate) {
      this._update.installDate = (new Date()).getTime();
      um.activeUpdate = null;
    }
    else {
      if (um.activeUpdate) {
        um.activeUpdate.state = state;
      }
    }
    um.saveUpdates();
    ...
    if (shouldShowPrompt) {
      // Notify the user that an update has been downloaded and is ready for
      // installation (i.e. that they should restart the application). We do
      // not notify on failed update attempts.
      let prompter = Cc["@mozilla.org/updates/update-prompt;1"].
                     createInstance(Ci.nsIUpdatePrompt);
      // 通知UpdatePrompt,update下载完成
      prompter.showUpdateDownloaded(this._update, true);
    }
  }
时间: 2024-11-07 08:10:37

(FFOS Gecko & Gaia) OTA - 真正的download的相关文章

(FFOS Gecko &amp; Gaia) OTA - Do real check

虽然代码分析了很多,但是还没有真正做check的工作,下面就来找到真正的checker. 代码位置:gecko/toolkit/mozapps/update/nsUpdateService.js.参考之前的(FFOS Gecko & Gaia) OTA - 代码模块总览,nsUpdateService.js中的Checker对象,实现了nsIUpdateChecker这个interface.下面就来分析Checker对象的实现. 1.  checkForUpdates函数: 实现略长,在代码中添

(FFOS Gecko &amp; Gaia) OTA - 又回到UpdatePrompt

当download完成时,又回到了UpdatePrompt,因为此时需要提示user下载完成,确认apply. 1. UpdatePrompt.showUpdateDownloaded showUpdateDownloaded: function UP_showUpdateDownloaded(aUpdate, aBackground) { if (this._systemUpdateListener) { this._systemUpdateListener.onUpdateReady();

(FFOS Gecko &amp; Gaia) OTA - 代码模块总览

OTA整体框架里会涉及以下代码,从gaia到gecko都有,而且由于历史原因,复用了desktop browser的一些模块,还有一些冗余代码,分析时走了不少弯路. 1. Gaia部分 (a) gaia/apps/settings/js/panels/about/update_check.js 这个Settings中OTA功能的入口,通过AMD(Asynchronous Module Definition)规范,定义了一个模块UpdateCheck. (b) gaia/apps/system/j

(FFOS Gecko &amp; 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”这个XPC

(FFOS Gecko &amp; 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出来的,Upda

(FFOS Gecko &amp; Gaia) OTA - 关键的apply

这篇分析已经是尾声了,在UpdatePrompt中,调用了UpdateService的applyOsUpdate函数. 1. UpdateService.applyOsUpdate 这个函数很简单,就是获取到update.zip以后,调用recovery service去完成更新. applyOsUpdate: function AUS_applyOsUpdate(aUpdate) { if (!aUpdate.isOSUpdate || aUpdate.state != STATE_APPLI

(FFOS Gecko &amp; Gaia) OTA - 转移至System App

代码位置:gaia/apps/system/js/update_manager.js 1. update_manager.js向全局的window对象导出了一个对象UpdateManager,其他的js module可以直接访问UpdateManager. exports.UpdateManager = UpdateManager; 2. UpdateManager监听了settings app中对于‘gaia.system.checkForUpdates’的设置,也就是当‘gaia.syste

(FFOS Gecko &amp; Gaia) OTA - 处理check结果

当通过Checker检测到update以后,会通知UpdatePrompt中的updateCheckListener. 1. UpdateCheckListener.onCheckComplete onCheckComplete: function UCL_onCheckComplete(request, updates, updateCount) { if (Services.um.activeUpdate) { // We're actively downloading an update,

(FFOS Gecko) - several ways of registering a XPCOM Component

1. JavaScript Component (1) add a CustomComponent.manifest # The {classID} here must match the classID in CustomComponent.js component {e6b866e3-41b2-4f05-a4d2-3d4bde0f7ef8} components/CustomComponent.js contract @foobar/customcomponent;1 {e6b866e3-4