(FFOS Gecko & Gaia) OTA

  前面分析了这么多,还没有真正的走到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.
" +
        "current application version: " + Services.appinfo.version + "
" +
        "update application version : " + update.appVersion + "
" +
        "current build ID: " + Services.appinfo.appBuildID + "
" +
        "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);
    }
  }
原文地址:https://www.cnblogs.com/code-4-fun/p/4705388.html