Although the code analysis a lot, but not really do check the work, the following to find the real checker.
Code location: Gecko/toolkit/mozapps/update/nsupdateservice.js. Refer to the previous (Ffos Gecko & Gaia) OTA-code module overview, nsupdateservice.js Checker object, implemented Nsiupdatechecker this interface. The following is an analysis of the implementation of the Checker object.
1. Checkforupdates function:
Implement a slightly longer, add comment analysis in your code.
Checkforupdates:functionuc_checkforupdates (Listener, Force) {LOG ("Checker:checkforupdates, Force:" +Force ); if(!listener)ThrowCr.ns_error_null_pointer;
//Notice ' Update-check-start ' event, who is the listener? Remember the last analysis of the updateprompt realized the Nsiobserver? Services.obs.notifyObservers (NULL, "Update-check-start",NULL);
This function is very important, it gets many settings and preferences, also through the Libutils library, to get a lot of system parameters, stitching into a URL,
//This URL is the OTA server URL varURL = This. Getupdateurl (force); if(!url | | (! This. Enabled &&!Force )) return;
//Send GET request via XHR, get update information This. _request = cc["@mozilla. Org/xmlextras/xmlhttprequest;1"]. CreateInstance (Ci.nsisupports); //This is the here and let Unit test code override XHR if( This. _request.wrappedjsobject) { This. _request = This. _request.wrappedjsobject; } This. _request.open ("GET", URL,true); varAllownonbuiltin =!getpref ("Getboolpref", Pref_app_update_cert_requirebuiltin,true); This. _request.channel.notificationcallbacks =NewGcertutils.badcerthandler (Allownonbuiltin); //Prevent the request from reading from the cache. This. _request.channel.loadflags |=Ci.nsIRequest.LOAD_BYPASS_CACHE; //Prevent the request from writing to the cache. This. _request.channel.loadflags |=Ci.nsIRequest.INHIBIT_CACHING; This. _request.overridemimetype ("Text/xml"); //The Cache-control header is a interpreted by proxies and the //Final destination. It does if a resource is already //cached locally. This. _request.setrequestheader ("Cache-control", "No-cache"); //http/1.0 servers might not implement Cache-control and //might only implement Pragma:no-cache This. _request.setrequestheader ("Pragma", "No-cache"); varSelf = This;
//Set XHR event listener This. _request.addeventlistener ("Error",function(event) {Self.onerror (event);} ,false); This. _request.addeventlistener ("Load",function(event) {Self.onload (event);},false); LOG ("Checker:checkforupdates-sending request to:" +URL); This. _request.send (NULL); //Save the incoming listener in the XHR event handler callback This. _callback =Listener;},
2. onload function
When request requests return, the OnLoad function is recalled
OnLoad:functionUc_onload (Event) {LOG ("Checker:onload-request completed downloading document"); varPrefs =services.prefs; varCerts =NULL; if(!getpref ("Getcharpref", Pref_app_update_url_override,NULL) &&Getpref ("Getboolpref", Pref_app_update_cert_checkattrs,true) ) {certs=gcertutils.readcertprefs (Pref_app_update_certs_branch); } Try { //Analyze the resulting DOM and determine the set of updates.
I did not find the part for the request response parsing, in fact, the secret is here, Checker does not show the definition _updates attribute, but defines a get _updates () function.
This is the feature of JS, and if the Get/set property () function is defined, it means that you can get/set the attribute named in the properties.
varUpdates = This. _updates; LOG ("Checker:onload-number of Updates available:" +updates.length); varAllownonbuiltin =!getpref ("Getboolpref", Pref_app_update_cert_requirebuiltin,true); Gcertutils.checkcert ( This. _request.channel, Allownonbuiltin, certs); if(Services.prefs.prefHasUserValue (pref_app_update_cert_errors)) Services.prefs.clearUserPref (pref_app_update _cert_errors); if(Services.prefs.prefHasUserValue (pref_app_update_backgrounderrors)) Services.prefs.clearUserPref (pref_app_ Update_backgrounderrors); //Tell the callback about the updates
This. _callback.oncheckcomplete (Event.target, updates, updates.length); } Catch(e) {LOG ("Checker:onload-there is a problem checking for updates." + "Exception:" +e); varRequest =Event.target; varStatus = This. _getchannelstatus (Request); LOG ("Checker:onload-request.status:" +status); varUpdate =NewUpdate (NULL); Update.errorcode=status; Update.statustext= Getstatustextfromcode (Status, 404); if( This. _ishttpstatuscode (status)) {Update.errorcode= Http_error_offset +status; } if(E.result && E.result = =cr.ns_error_illegal_value) {Update.errorcode= Updates[0]?cert_attr_check_failed_has_update:cert_attr_check_failed_no_update; } This. _callback.onerror (Request, update); } This. _callback =NULL; This. _request =NULL;},
3. Get _updates () function
Parse request response, according to Mozilla's documentation, this response is a update.xml file, please refer to https://wiki.mozilla.org/Software_Update for the specific format: Updates.xml_format.
By parsing the Update.xml file, a nsiupdate array is returned, which is an array of update objects. The update's constructor resolves all patch tags in update.xml, and each patch tag generates a Nsiupdatepatch, which is updatepatch, which means that the update object contains 1-Multiple Updatepatch objects, and that the U Pdate object will save some other information, such as whether the OS update, etc., the specific parsing process please refer to the code.
/**
* Returns An array of Nsiupdate objects discovered by the update check.
* @throws If the XML document element node name is not updates.
*/
get _updates () {varUpdateselement = This. _request.responsexml.documentelement; if(!updateselement) {LOG ("Checker:_updates get-empty Updates document?!"); return []; } if(Updateselement.nodename! = "Updates") {LOG ("Checker:_updates get-unexpected node name!"); Throw NewError ("Unexpected node name, Expected:updates, got:" +updateselement.nodename); } Const Element_node=Ci.nsIDOMNode.ELEMENT_NODE; varUpdates = []; for(vari = 0; i < updatesElement.childNodes.length; ++i) {varUpdateelement =UpdatesElement.childNodes.item (i); if(Updateelement.nodetype! = Element_node | |Updateelement.localname! = "Update") Continue; Updateelement.queryinterface (ci.nsidomelement); Let update; Try{ update = new Update (updateelement); } Catch(e) {LOG ("Checker:_updates get-invalid <update/>, ignoring ..."); Continue; } Update.serviceurl= This. Getupdateurl ( This. _forced); Update.channel=Updatechannel.get (); Updates.push (update); } returnupdates;},
(Ffos Gecko & Gaia) ota-do Real Check