ogre.rb 0.1-i686-linux → 0.2-i686-linux
Sign up to get free protection for your applications and to get access to all the features.
- data/README +43 -5
- data/Rakefile +67 -165
- data/lib/application.rb +2 -1
- data/lib/application_frame_listener.rb +17 -17
- data/lib/ogre.so +0 -0
- data/lib/ruby_ois.so +0 -0
- data/ogre.rb +3 -0
- data/samples/Ogre.log +358 -257
- data/samples/cel_shading.rb +85 -0
- data/samples/grass.rb +1 -1
- data/samples/media/materials/programs/CelShading.cg +63 -0
- data/samples/media/materials/scripts/CelShading.material +68 -0
- data/samples/media/materials/textures/cel_shading_diffuse.png +0 -0
- data/samples/media/materials/textures/cel_shading_edge.png +0 -0
- data/samples/media/materials/textures/cel_shading_specular.png +0 -0
- data/samples/ogre.cfg +1 -2
- data/samples/plugins.cfg +3 -2
- data/test/ogre.cfg +10 -0
- data/{samples/navi → test}/plugins.cfg +2 -4
- data/test/test_helper.rb +67 -0
- data/test/unit/constants_test.rb +66 -0
- data/test/unit/frame_stats_proxy_test.rb +28 -0
- data/test/unit/math_test.rb +20 -0
- data/test/unit/mesh_test.rb +15 -0
- data/test/unit/methods_test.rb +98 -0
- data/test/unit/movable_object_test.rb +19 -0
- data/test/unit/name_value_pair_list_test.rb +12 -0
- data/test/unit/overlay_element_test.rb +20 -0
- data/test/unit/render_target_test.rb +11 -0
- data/test/unit/resource_test.rb +26 -0
- data/test/unit/scene_manager_test.rb +21 -0
- metadata +25 -356
- data/samples/navi/Media/NaviDemo.material +0 -60
- data/samples/navi/Media/OgreCore.zip +0 -0
- data/samples/navi/Media/cerulean.jpg +0 -0
- data/samples/navi/Media/clouds.jpg +0 -0
- data/samples/navi/Media/controlsNaviMask.png +0 -0
- data/samples/navi/Media/grass.jpg +0 -0
- data/samples/navi/Media/knot.mesh +0 -0
- data/samples/navi/Media/testNaviMask.png +0 -0
- data/samples/navi/NaviLocal/Navi.js +0 -136
- data/samples/navi/NaviLocal/buttonBg.jpg +0 -0
- data/samples/navi/NaviLocal/controls.html +0 -303
- data/samples/navi/NaviLocal/knobBg.jpg +0 -0
- data/samples/navi/NaviLocal/moo.dropdownmenu.js +0 -87
- data/samples/navi/NaviLocal/mootools.v1.1.js +0 -6964
- data/samples/navi/NaviLocal/naviLogo.html +0 -32
- data/samples/navi/NaviLocal/naviLogo.png +0 -0
- data/samples/navi/NaviLocal/pageBg.jpg +0 -0
- data/samples/navi/NaviLocal/sliderBg.jpg +0 -0
- data/samples/navi/NaviLocal/test.html +0 -5
- data/samples/navi/NaviLocal/welcome.html +0 -36
- data/samples/navi/NaviLocal/welcome.png +0 -0
- data/samples/navi/chrome/chromelist.txt +0 -597
- data/samples/navi/chrome/classic.jar +0 -0
- data/samples/navi/chrome/classic.manifest +0 -4
- data/samples/navi/chrome/comm.jar +0 -0
- data/samples/navi/chrome/comm.manifest +0 -2
- data/samples/navi/chrome/en-US.jar +0 -0
- data/samples/navi/chrome/en-US.manifest +0 -9
- data/samples/navi/chrome/toolkit.jar +0 -0
- data/samples/navi/chrome/toolkit.manifest +0 -6
- data/samples/navi/components/FeedProcessor.js +0 -1825
- data/samples/navi/components/alerts.xpt +0 -0
- data/samples/navi/components/appshell.xpt +0 -0
- data/samples/navi/components/appstartup.xpt +0 -0
- data/samples/navi/components/auth.dll +0 -0
- data/samples/navi/components/autocomplete.xpt +0 -0
- data/samples/navi/components/autoconfig.dll +0 -0
- data/samples/navi/components/autoconfig.xpt +0 -0
- data/samples/navi/components/caps.xpt +0 -0
- data/samples/navi/components/chardet.xpt +0 -0
- data/samples/navi/components/chrome.xpt +0 -0
- data/samples/navi/components/commandhandler.xpt +0 -0
- data/samples/navi/components/commandlines.xpt +0 -0
- data/samples/navi/components/composer.xpt +0 -0
- data/samples/navi/components/compreg.dat +0 -1474
- data/samples/navi/components/content_base.xpt +0 -0
- data/samples/navi/components/content_html.xpt +0 -0
- data/samples/navi/components/content_htmldoc.xpt +0 -0
- data/samples/navi/components/content_xmldoc.xpt +0 -0
- data/samples/navi/components/content_xslt.xpt +0 -0
- data/samples/navi/components/content_xtf.xpt +0 -0
- data/samples/navi/components/directory.xpt +0 -0
- data/samples/navi/components/docshell_base.xpt +0 -0
- data/samples/navi/components/dom.xpt +0 -0
- data/samples/navi/components/dom_base.xpt +0 -0
- data/samples/navi/components/dom_canvas.xpt +0 -0
- data/samples/navi/components/dom_core.xpt +0 -0
- data/samples/navi/components/dom_css.xpt +0 -0
- data/samples/navi/components/dom_events.xpt +0 -0
- data/samples/navi/components/dom_html.xpt +0 -0
- data/samples/navi/components/dom_loadsave.xpt +0 -0
- data/samples/navi/components/dom_range.xpt +0 -0
- data/samples/navi/components/dom_sidebar.xpt +0 -0
- data/samples/navi/components/dom_storage.xpt +0 -0
- data/samples/navi/components/dom_stylesheets.xpt +0 -0
- data/samples/navi/components/dom_svg.xpt +0 -0
- data/samples/navi/components/dom_traversal.xpt +0 -0
- data/samples/navi/components/dom_views.xpt +0 -0
- data/samples/navi/components/dom_xbl.xpt +0 -0
- data/samples/navi/components/dom_xpath.xpt +0 -0
- data/samples/navi/components/dom_xul.xpt +0 -0
- data/samples/navi/components/downloads.xpt +0 -0
- data/samples/navi/components/editor.xpt +0 -0
- data/samples/navi/components/embed_base.xpt +0 -0
- data/samples/navi/components/extensions.xpt +0 -0
- data/samples/navi/components/exthandler.xpt +0 -0
- data/samples/navi/components/fastfind.xpt +0 -0
- data/samples/navi/components/feeds.xpt +0 -0
- data/samples/navi/components/find.xpt +0 -0
- data/samples/navi/components/gfx.xpt +0 -0
- data/samples/navi/components/gksvgrenderer.xpt +0 -0
- data/samples/navi/components/history.xpt +0 -0
- data/samples/navi/components/htmlparser.xpt +0 -0
- data/samples/navi/components/imglib2.xpt +0 -0
- data/samples/navi/components/inspector.xpt +0 -0
- data/samples/navi/components/intl.xpt +0 -0
- data/samples/navi/components/intlcmpt.xpt +0 -0
- data/samples/navi/components/jar.xpt +0 -0
- data/samples/navi/components/jsconsole-clhandler.js +0 -170
- data/samples/navi/components/jsconsole.xpt +0 -0
- data/samples/navi/components/jsdservice.xpt +0 -0
- data/samples/navi/components/layout_base.xpt +0 -0
- data/samples/navi/components/layout_printing.xpt +0 -0
- data/samples/navi/components/layout_xul.xpt +0 -0
- data/samples/navi/components/layout_xul_tree.xpt +0 -0
- data/samples/navi/components/locale.xpt +0 -0
- data/samples/navi/components/lwbrk.xpt +0 -0
- data/samples/navi/components/mimetype.xpt +0 -0
- data/samples/navi/components/mozbrwsr.xpt +0 -0
- data/samples/navi/components/mozfind.xpt +0 -0
- data/samples/navi/components/necko.xpt +0 -0
- data/samples/navi/components/necko_about.xpt +0 -0
- data/samples/navi/components/necko_cache.xpt +0 -0
- data/samples/navi/components/necko_cookie.xpt +0 -0
- data/samples/navi/components/necko_data.xpt +0 -0
- data/samples/navi/components/necko_dns.xpt +0 -0
- data/samples/navi/components/necko_file.xpt +0 -0
- data/samples/navi/components/necko_ftp.xpt +0 -0
- data/samples/navi/components/necko_http.xpt +0 -0
- data/samples/navi/components/necko_res.xpt +0 -0
- data/samples/navi/components/necko_socket.xpt +0 -0
- data/samples/navi/components/necko_strconv.xpt +0 -0
- data/samples/navi/components/necko_viewsource.xpt +0 -0
- data/samples/navi/components/nsCloseAllWindows.js +0 -143
- data/samples/navi/components/nsDefaultCLH.js +0 -231
- data/samples/navi/components/nsDictionary.js +0 -148
- data/samples/navi/components/nsExtensionManager.js +0 -8497
- data/samples/navi/components/nsHelperAppDlg.js +0 -990
- data/samples/navi/components/nsInterfaceInfoToIDL.js +0 -590
- data/samples/navi/components/nsKillAll.js +0 -200
- data/samples/navi/components/nsPostUpdateWin.js +0 -711
- data/samples/navi/components/nsProgressDialog.js +0 -949
- data/samples/navi/components/nsProxyAutoConfig.js +0 -396
- data/samples/navi/components/nsResetPref.js +0 -175
- data/samples/navi/components/nsURLFormatter.js +0 -179
- data/samples/navi/components/nsUpdateService.js +0 -3074
- data/samples/navi/components/nsXULAppInstall.js +0 -301
- data/samples/navi/components/nsXmlRpcClient.js +0 -1038
- data/samples/navi/components/oji.xpt +0 -0
- data/samples/navi/components/passwordmgr.xpt +0 -0
- data/samples/navi/components/pipboot.xpt +0 -0
- data/samples/navi/components/pipnss.xpt +0 -0
- data/samples/navi/components/plugin.xpt +0 -0
- data/samples/navi/components/pref.xpt +0 -0
- data/samples/navi/components/prefetch.xpt +0 -0
- data/samples/navi/components/profile.xpt +0 -0
- data/samples/navi/components/progressDlg.xpt +0 -0
- data/samples/navi/components/proxyObject.xpt +0 -0
- data/samples/navi/components/rdf.xpt +0 -0
- data/samples/navi/components/satchel.xpt +0 -0
- data/samples/navi/components/saxparser.xpt +0 -0
- data/samples/navi/components/shistory.xpt +0 -0
- data/samples/navi/components/storage.xpt +0 -0
- data/samples/navi/components/toolkitprofile.xpt +0 -0
- data/samples/navi/components/transformiix.dll +0 -0
- data/samples/navi/components/txmgr.xpt +0 -0
- data/samples/navi/components/txtsvc.xpt +0 -0
- data/samples/navi/components/uconv.xpt +0 -0
- data/samples/navi/components/unicharutil.xpt +0 -0
- data/samples/navi/components/universalchardet.dll +0 -0
- data/samples/navi/components/update.xpt +0 -0
- data/samples/navi/components/uriloader.xpt +0 -0
- data/samples/navi/components/urlformatter.xpt +0 -0
- data/samples/navi/components/webBrowser_core.xpt +0 -0
- data/samples/navi/components/webbrowserpersist.xpt +0 -0
- data/samples/navi/components/webshell_idls.xpt +0 -0
- data/samples/navi/components/websrvcs.dll +0 -0
- data/samples/navi/components/websrvcs.xpt +0 -0
- data/samples/navi/components/widget.xpt +0 -0
- data/samples/navi/components/windowds.xpt +0 -0
- data/samples/navi/components/windowwatcher.xpt +0 -0
- data/samples/navi/components/xml-rpc.xpt +0 -0
- data/samples/navi/components/xmlextras.dll +0 -0
- data/samples/navi/components/xpcom_base.xpt +0 -0
- data/samples/navi/components/xpcom_components.xpt +0 -0
- data/samples/navi/components/xpcom_ds.xpt +0 -0
- data/samples/navi/components/xpcom_io.xpt +0 -0
- data/samples/navi/components/xpcom_obsolete.xpt +0 -0
- data/samples/navi/components/xpcom_thread.xpt +0 -0
- data/samples/navi/components/xpcom_xpti.xpt +0 -0
- data/samples/navi/components/xpconnect.xpt +0 -0
- data/samples/navi/components/xpinstall.xpt +0 -0
- data/samples/navi/components/xpti.dat +0 -1424
- data/samples/navi/components/xulapp.xpt +0 -0
- data/samples/navi/components/xulapp_setup.xpt +0 -0
- data/samples/navi/components/xuldoc.xpt +0 -0
- data/samples/navi/components/xulrunner.xpt +0 -0
- data/samples/navi/components/xultmpl.xpt +0 -0
- data/samples/navi/components/xulutil.dll +0 -0
- data/samples/navi/controlsNaviMask.png +0 -0
- data/samples/navi/greprefs/all.js +0 -1344
- data/samples/navi/greprefs/security-prefs.js +0 -69
- data/samples/navi/greprefs/xpinstall.js +0 -2
- data/samples/navi/navi_demo.rb +0 -207
- data/samples/navi/plugins/NPSWF32.dll +0 -0
- data/samples/navi/plugins/flashplayer.xpt +0 -0
- data/samples/navi/plugins/npnul32.dll +0 -0
- data/samples/navi/res/EditorOverride.css +0 -359
- data/samples/navi/res/Thumbs.db +0 -0
- data/samples/navi/res/arrow.gif +0 -0
- data/samples/navi/res/arrowd.gif +0 -0
- data/samples/navi/res/bloatcycle.html +0 -40
- data/samples/navi/res/broken-image.gif +0 -0
- data/samples/navi/res/charsetData.properties +0 -199
- data/samples/navi/res/charsetalias.properties +0 -517
- data/samples/navi/res/cmessage.txt +0 -1
- data/samples/navi/res/dtd/xhtml11.dtd +0 -300
- data/samples/navi/res/entityTables/html40Latin1.properties +0 -146
- data/samples/navi/res/entityTables/html40Special.properties +0 -69
- data/samples/navi/res/entityTables/html40Symbols.properties +0 -164
- data/samples/navi/res/entityTables/htmlEntityVersions.properties +0 -50
- data/samples/navi/res/entityTables/transliterate.properties +0 -2367
- data/samples/navi/res/fonts/fontEncoding.properties +0 -127
- data/samples/navi/res/fonts/fontNameMap.properties +0 -134
- data/samples/navi/res/forms.css +0 -531
- data/samples/navi/res/grabber.gif +0 -0
- data/samples/navi/res/hiddenWindow.html +0 -1
- data/samples/navi/res/html/Thumbs.db +0 -0
- data/samples/navi/res/html/gopher-audio.gif +0 -0
- data/samples/navi/res/html/gopher-binary.gif +0 -0
- data/samples/navi/res/html/gopher-find.gif +0 -0
- data/samples/navi/res/html/gopher-image.gif +0 -0
- data/samples/navi/res/html/gopher-menu.gif +0 -0
- data/samples/navi/res/html/gopher-movie.gif +0 -0
- data/samples/navi/res/html/gopher-sound.gif +0 -0
- data/samples/navi/res/html/gopher-telnet.gif +0 -0
- data/samples/navi/res/html/gopher-text.gif +0 -0
- data/samples/navi/res/html/gopher-unknown.gif +0 -0
- data/samples/navi/res/html.css +0 -478
- data/samples/navi/res/langGroups.properties +0 -236
- data/samples/navi/res/language.properties +0 -259
- data/samples/navi/res/loading-image.gif +0 -0
- data/samples/navi/res/quirk.css +0 -282
- data/samples/navi/res/samples/Anieyes.gif +0 -0
- data/samples/navi/res/samples/Thumbs.db +0 -0
- data/samples/navi/res/samples/aform.css +0 -69
- data/samples/navi/res/samples/beeptest.html +0 -18
- data/samples/navi/res/samples/bform.css +0 -45
- data/samples/navi/res/samples/bg.jpg +0 -0
- data/samples/navi/res/samples/cform.css +0 -40
- data/samples/navi/res/samples/checkboxTest.xul +0 -47
- data/samples/navi/res/samples/demoform.css +0 -97
- data/samples/navi/res/samples/find.html +0 -97
- data/samples/navi/res/samples/gear1.gif +0 -0
- data/samples/navi/res/samples/image_props.html +0 -58
- data/samples/navi/res/samples/mozform.css +0 -256
- data/samples/navi/res/samples/printsetup.html +0 -175
- data/samples/navi/res/samples/raptor.jpg +0 -0
- data/samples/navi/res/samples/rock_gra.gif +0 -0
- data/samples/navi/res/samples/scrollbarTest1.xul +0 -66
- data/samples/navi/res/samples/scrollbarTest2.xul +0 -19
- data/samples/navi/res/samples/sliderTest1.xul +0 -14
- data/samples/navi/res/samples/soundtest.html +0 -20
- data/samples/navi/res/samples/test.wav +0 -0
- data/samples/navi/res/samples/test0.html +0 -220
- data/samples/navi/res/samples/test1.html +0 -84
- data/samples/navi/res/samples/test10.html +0 -16
- data/samples/navi/res/samples/test11.html +0 -42
- data/samples/navi/res/samples/test12.html +0 -79
- data/samples/navi/res/samples/test13.html +0 -126
- data/samples/navi/res/samples/test14.html +0 -5
- data/samples/navi/res/samples/test15.html +0 -5
- data/samples/navi/res/samples/test16.html +0 -124
- data/samples/navi/res/samples/test2.html +0 -41
- data/samples/navi/res/samples/test3.html +0 -126
- data/samples/navi/res/samples/test4.html +0 -335
- data/samples/navi/res/samples/test5.html +0 -199
- data/samples/navi/res/samples/test6.html +0 -335
- data/samples/navi/res/samples/test7.html +0 -11
- data/samples/navi/res/samples/test8-1.html +0 -66
- data/samples/navi/res/samples/test8.html +0 -662
- data/samples/navi/res/samples/test8dom.html +0 -64
- data/samples/navi/res/samples/test8sca.html +0 -308
- data/samples/navi/res/samples/test8siz.html +0 -224
- data/samples/navi/res/samples/test8tab.html +0 -9
- data/samples/navi/res/samples/test9.html +0 -12
- data/samples/navi/res/samples/test9a.html +0 -39
- data/samples/navi/res/samples/test9b.html +0 -16
- data/samples/navi/res/samples/test_ed.html +0 -5
- data/samples/navi/res/samples/test_form.html +0 -34
- data/samples/navi/res/samples/test_gfx.html +0 -75
- data/samples/navi/res/samples/test_lbox.html +0 -100
- data/samples/navi/res/samples/test_pr.html +0 -87
- data/samples/navi/res/samples/test_weight.html +0 -45
- data/samples/navi/res/samples/toolbarTest1.xul +0 -51
- data/samples/navi/res/samples/treeTest1.css +0 -62
- data/samples/navi/res/samples/treeTest1.xul +0 -110
- data/samples/navi/res/samples/xulTest.css +0 -130
- data/samples/navi/res/svg.css +0 -64
- data/samples/navi/res/table-add-column-after-active.gif +0 -0
- data/samples/navi/res/table-add-column-after-hover.gif +0 -0
- data/samples/navi/res/table-add-column-after.gif +0 -0
- data/samples/navi/res/table-add-column-before-active.gif +0 -0
- data/samples/navi/res/table-add-column-before-hover.gif +0 -0
- data/samples/navi/res/table-add-column-before.gif +0 -0
- data/samples/navi/res/table-add-row-after-active.gif +0 -0
- data/samples/navi/res/table-add-row-after-hover.gif +0 -0
- data/samples/navi/res/table-add-row-after.gif +0 -0
- data/samples/navi/res/table-add-row-before-active.gif +0 -0
- data/samples/navi/res/table-add-row-before-hover.gif +0 -0
- data/samples/navi/res/table-add-row-before.gif +0 -0
- data/samples/navi/res/table-remove-column-active.gif +0 -0
- data/samples/navi/res/table-remove-column-hover.gif +0 -0
- data/samples/navi/res/table-remove-column.gif +0 -0
- data/samples/navi/res/table-remove-row-active.gif +0 -0
- data/samples/navi/res/table-remove-row-hover.gif +0 -0
- data/samples/navi/res/table-remove-row.gif +0 -0
- data/samples/navi/res/throbber/Thumbs.db +0 -0
- data/samples/navi/res/throbber/anim.gif +0 -0
- data/samples/navi/res/throbber/anims00.gif +0 -0
- data/samples/navi/res/throbber/anims01.gif +0 -0
- data/samples/navi/res/throbber/anims02.gif +0 -0
- data/samples/navi/res/throbber/anims03.gif +0 -0
- data/samples/navi/res/throbber/anims04.gif +0 -0
- data/samples/navi/res/throbber/anims05.gif +0 -0
- data/samples/navi/res/throbber/anims06.gif +0 -0
- data/samples/navi/res/throbber/anims07.gif +0 -0
- data/samples/navi/res/throbber/anims08.gif +0 -0
- data/samples/navi/res/throbber/anims09.gif +0 -0
- data/samples/navi/res/throbber/anims10.gif +0 -0
- data/samples/navi/res/throbber/anims11.gif +0 -0
- data/samples/navi/res/throbber/anims12.gif +0 -0
- data/samples/navi/res/throbber/anims13.gif +0 -0
- data/samples/navi/res/throbber/anims14.gif +0 -0
- data/samples/navi/res/throbber/anims15.gif +0 -0
- data/samples/navi/res/throbber/anims16.gif +0 -0
- data/samples/navi/res/throbber/anims17.gif +0 -0
- data/samples/navi/res/throbber/anims18.gif +0 -0
- data/samples/navi/res/throbber/anims19.gif +0 -0
- data/samples/navi/res/throbber/anims20.gif +0 -0
- data/samples/navi/res/throbber/anims21.gif +0 -0
- data/samples/navi/res/throbber/anims22.gif +0 -0
- data/samples/navi/res/throbber/anims23.gif +0 -0
- data/samples/navi/res/throbber/anims24.gif +0 -0
- data/samples/navi/res/throbber/anims25.gif +0 -0
- data/samples/navi/res/throbber/anims26.gif +0 -0
- data/samples/navi/res/throbber/anims27.gif +0 -0
- data/samples/navi/res/throbber/anims28.gif +0 -0
- data/samples/navi/res/throbber/anims29.gif +0 -0
- data/samples/navi/res/ua.css +0 -235
- data/samples/navi/res/viewer.properties +0 -1
- data/samples/navi/res/viewsource.css +0 -118
- data/samples/navi/res/wincharset.properties +0 -55
- data/samples/navi/resources.cfg +0 -14
- data/samples/navi/testNaviMask.png +0 -0
- data/samples/render_run_log.5796 +0 -891
@@ -1,3074 +0,0 @@
|
|
1
|
-
//@line 42 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
2
|
-
|
3
|
-
const PREF_APP_UPDATE_ENABLED = "app.update.enabled";
|
4
|
-
const PREF_APP_UPDATE_AUTO = "app.update.auto";
|
5
|
-
const PREF_APP_UPDATE_MODE = "app.update.mode";
|
6
|
-
const PREF_APP_UPDATE_SILENT = "app.update.silent";
|
7
|
-
const PREF_APP_UPDATE_INTERVAL = "app.update.interval";
|
8
|
-
const PREF_APP_UPDATE_TIMER = "app.update.timer";
|
9
|
-
const PREF_APP_UPDATE_LOG_BRANCH = "app.update.log.";
|
10
|
-
const PREF_APP_UPDATE_URL = "app.update.url";
|
11
|
-
const PREF_APP_UPDATE_URL_OVERRIDE = "app.update.url.override";
|
12
|
-
const PREF_APP_UPDATE_URL_DETAILS = "app.update.url.details";
|
13
|
-
const PREF_APP_UPDATE_CHANNEL = "app.update.channel";
|
14
|
-
const PREF_APP_UPDATE_SHOW_INSTALLED_UI = "app.update.showInstalledUI";
|
15
|
-
const PREF_APP_UPDATE_LASTUPDATETIME_FMT = "app.update.lastUpdateTime.%ID%";
|
16
|
-
const PREF_APP_EXTENSIONS_VERSION = "app.extensions.version";
|
17
|
-
const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale";
|
18
|
-
const PREF_APP_UPDATE_INCOMPATIBLE_MODE = "app.update.incompatible.mode";
|
19
|
-
const PREF_UPDATE_NEVER_BRANCH = "app.update.never."
|
20
|
-
const PREF_PARTNER_BRANCH = "app.partner.";
|
21
|
-
|
22
|
-
const URI_UPDATE_PROMPT_DIALOG = "chrome://mozapps/content/update/updates.xul";
|
23
|
-
const URI_UPDATE_HISTORY_DIALOG = "chrome://mozapps/content/update/history.xul";
|
24
|
-
const URI_BRAND_PROPERTIES = "chrome://branding/locale/brand.properties";
|
25
|
-
const URI_UPDATES_PROPERTIES = "chrome://mozapps/locale/update/updates.properties";
|
26
|
-
const URI_UPDATE_NS = "http://www.mozilla.org/2005/app-update";
|
27
|
-
|
28
|
-
const KEY_APPDIR = "XCurProcD";
|
29
|
-
//@line 70 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
30
|
-
const KEY_UPDROOT = "UpdRootD";
|
31
|
-
const KEY_UAPPDATA = "UAppData";
|
32
|
-
//@line 73 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
33
|
-
|
34
|
-
const DIR_UPDATES = "updates";
|
35
|
-
const FILE_UPDATE_STATUS = "update.status";
|
36
|
-
const FILE_UPDATE_ARCHIVE = "update.mar";
|
37
|
-
const FILE_UPDATE_LOG = "update.log"
|
38
|
-
const FILE_UPDATES_DB = "updates.xml";
|
39
|
-
const FILE_UPDATE_ACTIVE = "active-update.xml";
|
40
|
-
const FILE_PERMS_TEST = "update.test";
|
41
|
-
const FILE_LAST_LOG = "last-update.log";
|
42
|
-
|
43
|
-
const MODE_RDONLY = 0x01;
|
44
|
-
const MODE_WRONLY = 0x02;
|
45
|
-
const MODE_CREATE = 0x08;
|
46
|
-
const MODE_APPEND = 0x10;
|
47
|
-
const MODE_TRUNCATE = 0x20;
|
48
|
-
|
49
|
-
const PERMS_FILE = 0644;
|
50
|
-
const PERMS_DIRECTORY = 0755;
|
51
|
-
|
52
|
-
const STATE_NONE = "null";
|
53
|
-
const STATE_DOWNLOADING = "downloading";
|
54
|
-
const STATE_PENDING = "pending";
|
55
|
-
const STATE_APPLYING = "applying";
|
56
|
-
const STATE_SUCCEEDED = "succeeded";
|
57
|
-
const STATE_DOWNLOAD_FAILED = "download-failed";
|
58
|
-
const STATE_FAILED = "failed";
|
59
|
-
|
60
|
-
// From updater/errors.h:
|
61
|
-
const WRITE_ERROR = 7;
|
62
|
-
|
63
|
-
const DOWNLOAD_CHUNK_SIZE = 300000; // bytes
|
64
|
-
const DOWNLOAD_BACKGROUND_INTERVAL = 600; // seconds
|
65
|
-
const DOWNLOAD_FOREGROUND_INTERVAL = 0;
|
66
|
-
|
67
|
-
// Values for the PREF_APP_UPDATE_INCOMPATIBLE_MODE pref. See documentation in
|
68
|
-
// code below.
|
69
|
-
const INCOMPATIBLE_MODE_NEWVERSIONS = 0;
|
70
|
-
const INCOMPATIBLE_MODE_NONEWVERSIONS = 1;
|
71
|
-
|
72
|
-
const POST_UPDATE_CONTRACTID = "@mozilla.org/updates/post-update;1";
|
73
|
-
|
74
|
-
const nsILocalFile = Components.interfaces.nsILocalFile;
|
75
|
-
const nsIUpdateService = Components.interfaces.nsIUpdateService;
|
76
|
-
const nsIUpdateItem = Components.interfaces.nsIUpdateItem;
|
77
|
-
const nsIPrefLocalizedString = Components.interfaces.nsIPrefLocalizedString;
|
78
|
-
const nsIIncrementalDownload = Components.interfaces.nsIIncrementalDownload;
|
79
|
-
const nsIFileInputStream = Components.interfaces.nsIFileInputStream;
|
80
|
-
const nsIFileOutputStream = Components.interfaces.nsIFileOutputStream;
|
81
|
-
const nsICryptoHash = Components.interfaces.nsICryptoHash;
|
82
|
-
|
83
|
-
const Node = Components.interfaces.nsIDOMNode;
|
84
|
-
|
85
|
-
var gApp = null;
|
86
|
-
var gPref = null;
|
87
|
-
var gABI = null;
|
88
|
-
var gOSVersion = null;
|
89
|
-
var gConsole = null;
|
90
|
-
var gLogEnabled = { };
|
91
|
-
|
92
|
-
// shared code for suppressing bad cert dialogs
|
93
|
-
//@line 40 "/c/mozilla/toolkit/mozapps/update/src/../../shared/src/badCertHandler.js"
|
94
|
-
|
95
|
-
/**
|
96
|
-
* Only allow built-in certs for HTTPS connections. See bug 340198.
|
97
|
-
*/
|
98
|
-
function checkCert(channel) {
|
99
|
-
if (!channel.originalURI.schemeIs("https")) // bypass
|
100
|
-
return;
|
101
|
-
|
102
|
-
const Ci = Components.interfaces;
|
103
|
-
var cert =
|
104
|
-
channel.securityInfo.QueryInterface(Ci.nsISSLStatusProvider).
|
105
|
-
SSLStatus.QueryInterface(Ci.nsISSLStatus).serverCert;
|
106
|
-
|
107
|
-
var issuer = cert.issuer;
|
108
|
-
while (issuer && !cert.equals(issuer)) {
|
109
|
-
cert = issuer;
|
110
|
-
issuer = cert.issuer;
|
111
|
-
}
|
112
|
-
|
113
|
-
if (!issuer || issuer.tokenName != "Builtin Object Token")
|
114
|
-
throw "cert issuer is not built-in";
|
115
|
-
}
|
116
|
-
|
117
|
-
/**
|
118
|
-
* This class implements nsIBadCertListener. It's job is to prevent "bad cert"
|
119
|
-
* security dialogs from being shown to the user. It is better to simply fail
|
120
|
-
* if the certificate is bad. See bug 304286.
|
121
|
-
*/
|
122
|
-
function BadCertHandler() {
|
123
|
-
}
|
124
|
-
BadCertHandler.prototype = {
|
125
|
-
|
126
|
-
// nsIBadCertListener
|
127
|
-
confirmUnknownIssuer: function(socketInfo, cert, certAddType) {
|
128
|
-
LOG("EM BadCertHandler: Unknown issuer");
|
129
|
-
return false;
|
130
|
-
},
|
131
|
-
|
132
|
-
confirmMismatchDomain: function(socketInfo, targetURL, cert) {
|
133
|
-
LOG("EM BadCertHandler: Mismatched domain");
|
134
|
-
return false;
|
135
|
-
},
|
136
|
-
|
137
|
-
confirmCertExpired: function(socketInfo, cert) {
|
138
|
-
LOG("EM BadCertHandler: Expired certificate");
|
139
|
-
return false;
|
140
|
-
},
|
141
|
-
|
142
|
-
notifyCrlNextupdate: function(socketInfo, targetURL, cert) {
|
143
|
-
},
|
144
|
-
|
145
|
-
// nsIChannelEventSink
|
146
|
-
onChannelRedirect: function(oldChannel, newChannel, flags) {
|
147
|
-
// make sure the certificate of the old channel checks out before we follow
|
148
|
-
// a redirect from it. See bug 340198.
|
149
|
-
checkCert(oldChannel);
|
150
|
-
},
|
151
|
-
|
152
|
-
// nsIInterfaceRequestor
|
153
|
-
getInterface: function(iid) {
|
154
|
-
if (iid.equals(Components.interfaces.nsIBadCertListener) ||
|
155
|
-
iid.equals(Components.interfaces.nsIChannelEventSink))
|
156
|
-
return this;
|
157
|
-
|
158
|
-
Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
|
159
|
-
return null;
|
160
|
-
},
|
161
|
-
|
162
|
-
// nsISupports
|
163
|
-
QueryInterface: function(iid) {
|
164
|
-
if (!iid.equals(Components.interfaces.nsIBadCertListener) &&
|
165
|
-
!iid.equals(Components.interfaces.nsIChannelEventSink) &&
|
166
|
-
!iid.equals(Components.interfaces.nsIInterfaceRequestor) &&
|
167
|
-
!iid.equals(Components.interfaces.nsISupports))
|
168
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
169
|
-
return this;
|
170
|
-
}
|
171
|
-
};
|
172
|
-
//@line 134 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
173
|
-
|
174
|
-
/**
|
175
|
-
* Logs a string to the error console.
|
176
|
-
* @param string
|
177
|
-
* The string to write to the error console..
|
178
|
-
*/
|
179
|
-
function LOG(module, string) {
|
180
|
-
if (module in gLogEnabled) {
|
181
|
-
dump("*** " + module + ": " + string + "\n");
|
182
|
-
gConsole.logStringMessage(string);
|
183
|
-
}
|
184
|
-
}
|
185
|
-
|
186
|
-
/**
|
187
|
-
* Convert a string containing binary values to hex.
|
188
|
-
*/
|
189
|
-
function binaryToHex(input) {
|
190
|
-
var result = "";
|
191
|
-
for (var i = 0; i < input.length; ++i) {
|
192
|
-
var hex = input.charCodeAt(i).toString(16);
|
193
|
-
if (hex.length == 1)
|
194
|
-
hex = "0" + hex;
|
195
|
-
result += hex;
|
196
|
-
}
|
197
|
-
return result;
|
198
|
-
}
|
199
|
-
|
200
|
-
/**
|
201
|
-
* Gets a File URL spec for a nsIFile
|
202
|
-
* @param file
|
203
|
-
* The file to get a file URL spec to
|
204
|
-
* @returns The file URL spec to the file
|
205
|
-
*/
|
206
|
-
function getURLSpecFromFile(file) {
|
207
|
-
var ioServ = Components.classes["@mozilla.org/network/io-service;1"]
|
208
|
-
.getService(Components.interfaces.nsIIOService);
|
209
|
-
var fph = ioServ.getProtocolHandler("file")
|
210
|
-
.QueryInterface(Components.interfaces.nsIFileProtocolHandler);
|
211
|
-
return fph.getURLSpecFromFile(file);
|
212
|
-
}
|
213
|
-
|
214
|
-
/**
|
215
|
-
* Gets the specified directory at the specified hierarchy under a
|
216
|
-
* Directory Service key.
|
217
|
-
* @param key
|
218
|
-
* The Directory Service Key to start from
|
219
|
-
* @param pathArray
|
220
|
-
* An array of path components to locate beneath the directory
|
221
|
-
* specified by |key|
|
222
|
-
* @return nsIFile object for the location specified. If the directory
|
223
|
-
* requested does not exist, it is created, along with any
|
224
|
-
* parent directories that need to be created.
|
225
|
-
*/
|
226
|
-
function getDir(key, pathArray) {
|
227
|
-
return getDirInternal(key, pathArray, true, false);
|
228
|
-
}
|
229
|
-
|
230
|
-
/**
|
231
|
-
* Gets the specified directory at the speciifed hierarchy under a
|
232
|
-
* Directory Service key.
|
233
|
-
* @param key
|
234
|
-
* The Directory Service Key to start from
|
235
|
-
* @param pathArray
|
236
|
-
* An array of path components to locate beneath the directory
|
237
|
-
* specified by |key|
|
238
|
-
* @return nsIFile object for the location specified. If the directory
|
239
|
-
* requested does not exist, it is NOT created.
|
240
|
-
*/
|
241
|
-
function getDirNoCreate(key, pathArray) {
|
242
|
-
return getDirInternal(key, pathArray, false, false);
|
243
|
-
}
|
244
|
-
|
245
|
-
/**
|
246
|
-
* Gets the specified directory at the specified hierarchy under the
|
247
|
-
* update root directory.
|
248
|
-
* @param pathArray
|
249
|
-
* An array of path components to locate beneath the directory
|
250
|
-
* specified by |key|
|
251
|
-
* @return nsIFile object for the location specified. If the directory
|
252
|
-
* requested does not exist, it is created, along with any
|
253
|
-
* parent directories that need to be created.
|
254
|
-
*/
|
255
|
-
function getUpdateDir(pathArray) {
|
256
|
-
return getDirInternal(KEY_APPDIR, pathArray, true, true);
|
257
|
-
}
|
258
|
-
|
259
|
-
/**
|
260
|
-
* Gets the specified directory at the speciifed hierarchy under a
|
261
|
-
* Directory Service key.
|
262
|
-
* @param key
|
263
|
-
* The Directory Service Key to start from
|
264
|
-
* @param pathArray
|
265
|
-
* An array of path components to locate beneath the directory
|
266
|
-
* specified by |key|
|
267
|
-
* @param shouldCreate
|
268
|
-
* true if the directory hierarchy specified in |pathArray|
|
269
|
-
* should be created if it does not exist,
|
270
|
-
* false otherwise.
|
271
|
-
* @param update
|
272
|
-
* true if finding the update directory,
|
273
|
-
* false otherwise.
|
274
|
-
* @return nsIFile object for the location specified.
|
275
|
-
*/
|
276
|
-
function getDirInternal(key, pathArray, shouldCreate, update) {
|
277
|
-
var fileLocator = Components.classes["@mozilla.org/file/directory_service;1"]
|
278
|
-
.getService(Components.interfaces.nsIProperties);
|
279
|
-
var dir = fileLocator.get(key, Components.interfaces.nsIFile);
|
280
|
-
//@line 242 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
281
|
-
if (update) {
|
282
|
-
try {
|
283
|
-
dir = fileLocator.get(KEY_UPDROOT, Components.interfaces.nsIFile);
|
284
|
-
} catch (e) {
|
285
|
-
}
|
286
|
-
}
|
287
|
-
//@line 249 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
288
|
-
for (var i = 0; i < pathArray.length; ++i) {
|
289
|
-
dir.append(pathArray[i]);
|
290
|
-
if (shouldCreate && !dir.exists())
|
291
|
-
dir.create(nsILocalFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
|
292
|
-
}
|
293
|
-
return dir;
|
294
|
-
}
|
295
|
-
|
296
|
-
/**
|
297
|
-
* Gets the file at the speciifed hierarchy under a Directory Service key.
|
298
|
-
* @param key
|
299
|
-
* The Directory Service Key to start from
|
300
|
-
* @param pathArray
|
301
|
-
* An array of path components to locate beneath the directory
|
302
|
-
* specified by |key|. The last item in this array must be the
|
303
|
-
* leaf name of a file.
|
304
|
-
* @return nsIFile object for the file specified. The file is NOT created
|
305
|
-
* if it does not exist, however all required directories along
|
306
|
-
* the way are.
|
307
|
-
*/
|
308
|
-
function getFile(key, pathArray) {
|
309
|
-
var file = getDir(key, pathArray.slice(0, -1));
|
310
|
-
file.append(pathArray[pathArray.length - 1]);
|
311
|
-
return file;
|
312
|
-
}
|
313
|
-
|
314
|
-
/**
|
315
|
-
* Gets the file at the speciifed hierarchy under the update root directory.
|
316
|
-
* @param pathArray
|
317
|
-
* An array of path components to locate beneath the directory
|
318
|
-
* specified by |key|. The last item in this array must be the
|
319
|
-
* leaf name of a file.
|
320
|
-
* @return nsIFile object for the file specified. The file is NOT created
|
321
|
-
* if it does not exist, however all required directories along
|
322
|
-
* the way are.
|
323
|
-
*/
|
324
|
-
function getUpdateFile(pathArray) {
|
325
|
-
var file = getUpdateDir(pathArray.slice(0, -1));
|
326
|
-
file.append(pathArray[pathArray.length - 1]);
|
327
|
-
return file;
|
328
|
-
}
|
329
|
-
|
330
|
-
/**
|
331
|
-
* Closes a Safe Output Stream
|
332
|
-
* @param fos
|
333
|
-
* The Safe Output Stream to close
|
334
|
-
*/
|
335
|
-
function closeSafeOutputStream(fos) {
|
336
|
-
if (fos instanceof Components.interfaces.nsISafeOutputStream) {
|
337
|
-
try {
|
338
|
-
fos.finish();
|
339
|
-
}
|
340
|
-
catch (e) {
|
341
|
-
fos.close();
|
342
|
-
}
|
343
|
-
}
|
344
|
-
else
|
345
|
-
fos.close();
|
346
|
-
}
|
347
|
-
|
348
|
-
/**
|
349
|
-
* Returns human readable status text from the updates.properties bundle
|
350
|
-
* based on an error code
|
351
|
-
* @param code
|
352
|
-
* The error code to look up human readable status text for
|
353
|
-
* @param defaultCode
|
354
|
-
* The default code to look up should human readable status text
|
355
|
-
* not exist for |code|
|
356
|
-
* @returns A human readable status text string
|
357
|
-
*/
|
358
|
-
function getStatusTextFromCode(code, defaultCode) {
|
359
|
-
var sbs =
|
360
|
-
Components.classes["@mozilla.org/intl/stringbundle;1"].
|
361
|
-
getService(Components.interfaces.nsIStringBundleService);
|
362
|
-
var updateBundle = sbs.createBundle(URI_UPDATES_PROPERTIES);
|
363
|
-
var reason = updateBundle.GetStringFromName("checker_error-" + defaultCode);
|
364
|
-
try {
|
365
|
-
reason = updateBundle.GetStringFromName("checker_error-" + code);
|
366
|
-
LOG("General", "Transfer Error: " + reason + ", code: " + code);
|
367
|
-
}
|
368
|
-
catch (e) {
|
369
|
-
// Use the default reason
|
370
|
-
LOG("General", "Transfer Error: " + reason + ", code: " + defaultCode);
|
371
|
-
}
|
372
|
-
return reason;
|
373
|
-
}
|
374
|
-
|
375
|
-
/**
|
376
|
-
* Get the Active Updates directory
|
377
|
-
* @param key
|
378
|
-
* The Directory Service Key (optional).
|
379
|
-
* If used, don't search local appdata on Win32 and don't create dir.
|
380
|
-
* @returns The active updates directory, as a nsIFile object
|
381
|
-
*/
|
382
|
-
function getUpdatesDir(key) {
|
383
|
-
// Right now, we only support downloading one patch at a time, so we always
|
384
|
-
// use the same target directory.
|
385
|
-
var fileLocator =
|
386
|
-
Components.classes["@mozilla.org/file/directory_service;1"].
|
387
|
-
getService(Components.interfaces.nsIProperties);
|
388
|
-
var appDir;
|
389
|
-
if (key)
|
390
|
-
appDir = fileLocator.get(key, Components.interfaces.nsIFile);
|
391
|
-
else {
|
392
|
-
appDir = fileLocator.get(KEY_APPDIR, Components.interfaces.nsIFile);
|
393
|
-
//@line 355 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
394
|
-
try {
|
395
|
-
appDir = fileLocator.get(KEY_UPDROOT, Components.interfaces.nsIFile);
|
396
|
-
} catch (e) {
|
397
|
-
}
|
398
|
-
//@line 360 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
399
|
-
}
|
400
|
-
appDir.append(DIR_UPDATES);
|
401
|
-
appDir.append("0");
|
402
|
-
if (!appDir.exists() && !key)
|
403
|
-
appDir.create(nsILocalFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
|
404
|
-
return appDir;
|
405
|
-
}
|
406
|
-
|
407
|
-
/**
|
408
|
-
* Reads the update state from the update.status file in the specified
|
409
|
-
* directory.
|
410
|
-
* @param dir
|
411
|
-
* The dir to look for an update.status file in
|
412
|
-
* @returns The status value of the update.
|
413
|
-
*/
|
414
|
-
function readStatusFile(dir) {
|
415
|
-
var statusFile = dir.clone();
|
416
|
-
statusFile.append(FILE_UPDATE_STATUS);
|
417
|
-
LOG("General", "Reading Status File: " + statusFile.path);
|
418
|
-
return readStringFromFile(statusFile) || STATE_NONE;
|
419
|
-
}
|
420
|
-
|
421
|
-
/**
|
422
|
-
* Writes the current update operation/state to a file in the patch
|
423
|
-
* directory, indicating to the patching system that operations need
|
424
|
-
* to be performed.
|
425
|
-
* @param dir
|
426
|
-
* The patch directory where the update.status file should be
|
427
|
-
* written.
|
428
|
-
* @param state
|
429
|
-
* The state value to write.
|
430
|
-
*/
|
431
|
-
function writeStatusFile(dir, state) {
|
432
|
-
var statusFile = dir.clone();
|
433
|
-
statusFile.append(FILE_UPDATE_STATUS);
|
434
|
-
writeStringToFile(statusFile, state);
|
435
|
-
}
|
436
|
-
|
437
|
-
/**
|
438
|
-
* Removes the Updates Directory
|
439
|
-
* @param key
|
440
|
-
* The Directory Service Key under which update directory resides
|
441
|
-
* (optional).
|
442
|
-
*/
|
443
|
-
function cleanUpUpdatesDir(key) {
|
444
|
-
// Bail out if we don't have appropriate permissions
|
445
|
-
var updateDir;
|
446
|
-
try {
|
447
|
-
updateDir = getUpdatesDir(key);
|
448
|
-
}
|
449
|
-
catch (e) {
|
450
|
-
return;
|
451
|
-
}
|
452
|
-
|
453
|
-
var e = updateDir.directoryEntries;
|
454
|
-
while (e.hasMoreElements()) {
|
455
|
-
var f = e.getNext().QueryInterface(Components.interfaces.nsIFile);
|
456
|
-
// Preserve the last update log file for debugging purposes
|
457
|
-
if (f.leafName == FILE_UPDATE_LOG) {
|
458
|
-
try {
|
459
|
-
var dir = f.parent.parent;
|
460
|
-
var logFile = dir.clone();
|
461
|
-
logFile.append(FILE_LAST_LOG);
|
462
|
-
if (logFile.exists())
|
463
|
-
logFile.remove(false);
|
464
|
-
f.copyTo(dir, FILE_LAST_LOG);
|
465
|
-
}
|
466
|
-
catch (e) {
|
467
|
-
LOG("General", "Failed to copy file: " + f.path);
|
468
|
-
}
|
469
|
-
}
|
470
|
-
// Now, recursively remove this file. The recusive removal is really
|
471
|
-
// only needed on Mac OSX because this directory will contain a copy of
|
472
|
-
// updater.app, which is itself a directory.
|
473
|
-
try {
|
474
|
-
f.remove(true);
|
475
|
-
}
|
476
|
-
catch (e) {
|
477
|
-
LOG("General", "Failed to remove file: " + f.path);
|
478
|
-
}
|
479
|
-
}
|
480
|
-
try {
|
481
|
-
updateDir.remove(false);
|
482
|
-
} catch (e) {
|
483
|
-
LOG("General", "Failed to remove update directory: " + updateDir.path +
|
484
|
-
" - This is almost always bad. Exception = " + e);
|
485
|
-
throw e;
|
486
|
-
}
|
487
|
-
}
|
488
|
-
|
489
|
-
/**
|
490
|
-
* Clean up updates list and the updates directory.
|
491
|
-
* @param key
|
492
|
-
* The Directory Service Key under which update directory resides
|
493
|
-
* (optional).
|
494
|
-
*/
|
495
|
-
function cleanupActiveUpdate(key) {
|
496
|
-
// Move the update from the Active Update list into the Past Updates list.
|
497
|
-
var um =
|
498
|
-
Components.classes["@mozilla.org/updates/update-manager;1"].
|
499
|
-
getService(Components.interfaces.nsIUpdateManager);
|
500
|
-
um.activeUpdate = null;
|
501
|
-
um.saveUpdates();
|
502
|
-
|
503
|
-
// Now trash the updates directory, since we're done with it
|
504
|
-
cleanUpUpdatesDir(key);
|
505
|
-
}
|
506
|
-
|
507
|
-
/**
|
508
|
-
* Gets a preference value, handling the case where there is no default.
|
509
|
-
* @param func
|
510
|
-
* The name of the preference function to call, on nsIPrefBranch
|
511
|
-
* @param preference
|
512
|
-
* The name of the preference
|
513
|
-
* @param defaultValue
|
514
|
-
* The default value to return in the event the preference has
|
515
|
-
* no setting
|
516
|
-
* @returns The value of the preference, or undefined if there was no
|
517
|
-
* user or default value.
|
518
|
-
*/
|
519
|
-
function getPref(func, preference, defaultValue) {
|
520
|
-
try {
|
521
|
-
return gPref[func](preference);
|
522
|
-
}
|
523
|
-
catch (e) {
|
524
|
-
}
|
525
|
-
return defaultValue;
|
526
|
-
}
|
527
|
-
|
528
|
-
/**
|
529
|
-
* Gets the current value of the locale. It's possible for this preference to
|
530
|
-
* be localized, so we have to do a little extra work here. Similar code
|
531
|
-
* exists in nsHttpHandler.cpp when building the UA string.
|
532
|
-
*/
|
533
|
-
function getLocale() {
|
534
|
-
try {
|
535
|
-
return gPref.getComplexValue(PREF_GENERAL_USERAGENT_LOCALE,
|
536
|
-
nsIPrefLocalizedString).data;
|
537
|
-
} catch (e) {}
|
538
|
-
|
539
|
-
return gPref.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
|
540
|
-
}
|
541
|
-
|
542
|
-
/**
|
543
|
-
* Read the update channel from defaults only. We do this to ensure that
|
544
|
-
* the channel is tightly coupled with the application and does not apply
|
545
|
-
* to other instances of the application that may use the same profile.
|
546
|
-
*/
|
547
|
-
function getUpdateChannel() {
|
548
|
-
var channel = "default";
|
549
|
-
var prefName;
|
550
|
-
var prefValue;
|
551
|
-
|
552
|
-
var defaults =
|
553
|
-
gPref.QueryInterface(Components.interfaces.nsIPrefService).
|
554
|
-
getDefaultBranch(null);
|
555
|
-
try {
|
556
|
-
channel = defaults.getCharPref(PREF_APP_UPDATE_CHANNEL);
|
557
|
-
} catch (e) {
|
558
|
-
// use default when pref not found
|
559
|
-
}
|
560
|
-
|
561
|
-
try {
|
562
|
-
var partners = gPref.getChildList(PREF_PARTNER_BRANCH, { });
|
563
|
-
if (partners.length) {
|
564
|
-
channel += "-cck";
|
565
|
-
partners.sort();
|
566
|
-
|
567
|
-
for each (prefName in partners) {
|
568
|
-
prefValue = gPref.getCharPref(prefName);
|
569
|
-
channel += "-" + prefValue;
|
570
|
-
}
|
571
|
-
}
|
572
|
-
}
|
573
|
-
catch (e) {
|
574
|
-
Components.utils.reportError(e);
|
575
|
-
}
|
576
|
-
|
577
|
-
return channel;
|
578
|
-
}
|
579
|
-
|
580
|
-
/**
|
581
|
-
* An enumeration of items in a JS array.
|
582
|
-
* @constructor
|
583
|
-
*/
|
584
|
-
function ArrayEnumerator(aItems) {
|
585
|
-
this._index = 0;
|
586
|
-
if (aItems) {
|
587
|
-
for (var i = 0; i < aItems.length; ++i) {
|
588
|
-
if (!aItems[i])
|
589
|
-
aItems.splice(i, 1);
|
590
|
-
}
|
591
|
-
}
|
592
|
-
this._contents = aItems;
|
593
|
-
}
|
594
|
-
|
595
|
-
ArrayEnumerator.prototype = {
|
596
|
-
_index: 0,
|
597
|
-
_contents: [],
|
598
|
-
|
599
|
-
hasMoreElements: function() {
|
600
|
-
return this._index < this._contents.length;
|
601
|
-
},
|
602
|
-
|
603
|
-
getNext: function() {
|
604
|
-
return this._contents[this._index++];
|
605
|
-
}
|
606
|
-
};
|
607
|
-
|
608
|
-
/**
|
609
|
-
* Trims a prefix from a string.
|
610
|
-
* @param string
|
611
|
-
* The source string
|
612
|
-
* @param prefix
|
613
|
-
* The prefix to remove.
|
614
|
-
* @returns The suffix (string - prefix)
|
615
|
-
*/
|
616
|
-
function stripPrefix(string, prefix) {
|
617
|
-
return string.substr(prefix.length);
|
618
|
-
}
|
619
|
-
|
620
|
-
/**
|
621
|
-
* Writes a string of text to a file. A newline will be appended to the data
|
622
|
-
* written to the file. This function only works with ASCII text.
|
623
|
-
*/
|
624
|
-
function writeStringToFile(file, text) {
|
625
|
-
var fos =
|
626
|
-
Components.classes["@mozilla.org/network/safe-file-output-stream;1"].
|
627
|
-
createInstance(nsIFileOutputStream);
|
628
|
-
var modeFlags = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE;
|
629
|
-
if (!file.exists())
|
630
|
-
file.create(nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
|
631
|
-
fos.init(file, modeFlags, PERMS_FILE, 0);
|
632
|
-
text += "\n";
|
633
|
-
fos.write(text, text.length);
|
634
|
-
closeSafeOutputStream(fos);
|
635
|
-
}
|
636
|
-
|
637
|
-
/**
|
638
|
-
* Reads a string of text from a file. A trailing newline will be removed
|
639
|
-
* before the result is returned. This function only works with ASCII text.
|
640
|
-
*/
|
641
|
-
function readStringFromFile(file) {
|
642
|
-
var fis =
|
643
|
-
Components.classes["@mozilla.org/network/file-input-stream;1"].
|
644
|
-
createInstance(nsIFileInputStream);
|
645
|
-
var modeFlags = MODE_RDONLY;
|
646
|
-
if (!file.exists())
|
647
|
-
return null;
|
648
|
-
fis.init(file, modeFlags, PERMS_FILE, 0);
|
649
|
-
var sis =
|
650
|
-
Components.classes["@mozilla.org/scriptableinputstream;1"].
|
651
|
-
createInstance(Components.interfaces.nsIScriptableInputStream);
|
652
|
-
sis.init(fis);
|
653
|
-
var text = sis.read(sis.available());
|
654
|
-
sis.close();
|
655
|
-
if (text[text.length - 1] == "\n")
|
656
|
-
text = text.slice(0, -1);
|
657
|
-
return text;
|
658
|
-
}
|
659
|
-
|
660
|
-
function getObserverService()
|
661
|
-
{
|
662
|
-
return Components.classes["@mozilla.org/observer-service;1"]
|
663
|
-
.getService(Components.interfaces.nsIObserverService);
|
664
|
-
}
|
665
|
-
|
666
|
-
/**
|
667
|
-
* Update Patch
|
668
|
-
* @param patch
|
669
|
-
* A <patch> element to initialize this object with
|
670
|
-
* @throws if patch has a size of 0
|
671
|
-
* @constructor
|
672
|
-
*/
|
673
|
-
function UpdatePatch(patch) {
|
674
|
-
this._properties = {};
|
675
|
-
for (var i = 0; i < patch.attributes.length; ++i) {
|
676
|
-
var attr = patch.attributes.item(i);
|
677
|
-
attr.QueryInterface(Components.interfaces.nsIDOMAttr);
|
678
|
-
switch (attr.name) {
|
679
|
-
case "selected":
|
680
|
-
this.selected = attr.value == "true";
|
681
|
-
break;
|
682
|
-
case "size":
|
683
|
-
if (0 == parseInt(attr.value)) {
|
684
|
-
LOG("UpdatePatch", "0-sized patch!");
|
685
|
-
throw Components.results.NS_ERROR_ILLEGAL_VALUE;
|
686
|
-
}
|
687
|
-
default:
|
688
|
-
this[attr.name] = attr.value;
|
689
|
-
break;
|
690
|
-
};
|
691
|
-
}
|
692
|
-
}
|
693
|
-
UpdatePatch.prototype = {
|
694
|
-
/**
|
695
|
-
* See nsIUpdateService.idl
|
696
|
-
*/
|
697
|
-
serialize: function(updates) {
|
698
|
-
var patch = updates.createElementNS(URI_UPDATE_NS, "patch");
|
699
|
-
patch.setAttribute("type", this.type);
|
700
|
-
patch.setAttribute("URL", this.URL);
|
701
|
-
patch.setAttribute("hashFunction", this.hashFunction);
|
702
|
-
patch.setAttribute("hashValue", this.hashValue);
|
703
|
-
patch.setAttribute("size", this.size);
|
704
|
-
patch.setAttribute("selected", this.selected);
|
705
|
-
patch.setAttribute("state", this.state);
|
706
|
-
|
707
|
-
for (var p in this._properties) {
|
708
|
-
if (this._properties[p].present)
|
709
|
-
patch.setAttribute(p, this._properties[p].data);
|
710
|
-
}
|
711
|
-
|
712
|
-
return patch;
|
713
|
-
},
|
714
|
-
|
715
|
-
/**
|
716
|
-
* A hash of custom properties
|
717
|
-
*/
|
718
|
-
_properties: null,
|
719
|
-
|
720
|
-
/**
|
721
|
-
* See nsIWritablePropertyBag.idl
|
722
|
-
*/
|
723
|
-
setProperty: function(name, value) {
|
724
|
-
this._properties[name] = { data: value, present: true };
|
725
|
-
},
|
726
|
-
|
727
|
-
/**
|
728
|
-
* See nsIWritablePropertyBag.idl
|
729
|
-
*/
|
730
|
-
deleteProperty: function(name) {
|
731
|
-
if (name in this._properties)
|
732
|
-
this._properties[name].present = false;
|
733
|
-
else
|
734
|
-
throw Components.results.NS_ERROR_FAILURE;
|
735
|
-
},
|
736
|
-
|
737
|
-
/**
|
738
|
-
* See nsIPropertyBag.idl
|
739
|
-
*/
|
740
|
-
get enumerator() {
|
741
|
-
var properties = [];
|
742
|
-
for (var p in this._properties)
|
743
|
-
properties.push(this._properties[p].data);
|
744
|
-
return new ArrayEnumerator(properties);
|
745
|
-
},
|
746
|
-
|
747
|
-
/**
|
748
|
-
* See nsIPropertyBag.idl
|
749
|
-
*/
|
750
|
-
getProperty: function(name) {
|
751
|
-
if (name in this._properties &&
|
752
|
-
this._properties[name].present)
|
753
|
-
return this._properties[name].data;
|
754
|
-
throw Components.results.NS_ERROR_FAILURE;
|
755
|
-
},
|
756
|
-
|
757
|
-
/**
|
758
|
-
* Returns whether or not the update.status file for this patch exists at the
|
759
|
-
* appropriate location.
|
760
|
-
*/
|
761
|
-
get statusFileExists() {
|
762
|
-
var statusFile = getUpdatesDir();
|
763
|
-
statusFile.append(FILE_UPDATE_STATUS);
|
764
|
-
return statusFile.exists();
|
765
|
-
},
|
766
|
-
|
767
|
-
/**
|
768
|
-
* See nsIUpdateService.idl
|
769
|
-
*/
|
770
|
-
get state() {
|
771
|
-
if (!this.statusFileExists)
|
772
|
-
return STATE_NONE;
|
773
|
-
return this._properties.state;
|
774
|
-
},
|
775
|
-
set state(val) {
|
776
|
-
this._properties.state = val;
|
777
|
-
},
|
778
|
-
|
779
|
-
/**
|
780
|
-
* See nsISupports.idl
|
781
|
-
*/
|
782
|
-
QueryInterface: function(iid) {
|
783
|
-
if (!iid.equals(Components.interfaces.nsIUpdatePatch) &&
|
784
|
-
!iid.equals(Components.interfaces.nsIPropertyBag) &&
|
785
|
-
!iid.equals(Components.interfaces.nsIWritablePropertyBag) &&
|
786
|
-
!iid.equals(Components.interfaces.nsISupports))
|
787
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
788
|
-
return this;
|
789
|
-
}
|
790
|
-
};
|
791
|
-
|
792
|
-
/**
|
793
|
-
* Update
|
794
|
-
* Implements nsIUpdate
|
795
|
-
* @param update
|
796
|
-
* An <update> element to initialize this object with
|
797
|
-
* @throws if the update contains no patches
|
798
|
-
* @constructor
|
799
|
-
*/
|
800
|
-
function Update(update) {
|
801
|
-
this._properties = {};
|
802
|
-
this._patches = [];
|
803
|
-
this.installDate = 0;
|
804
|
-
this.isCompleteUpdate = false;
|
805
|
-
this.channel = "default";
|
806
|
-
|
807
|
-
// Null <update>, assume this is a message container and do no
|
808
|
-
// further initialization
|
809
|
-
if (!update)
|
810
|
-
return;
|
811
|
-
|
812
|
-
for (var i = 0; i < update.childNodes.length; ++i) {
|
813
|
-
var patchElement = update.childNodes.item(i);
|
814
|
-
if (patchElement.nodeType != Node.ELEMENT_NODE ||
|
815
|
-
patchElement.localName != "patch")
|
816
|
-
continue;
|
817
|
-
|
818
|
-
patchElement.QueryInterface(Components.interfaces.nsIDOMElement);
|
819
|
-
try {
|
820
|
-
var patch = new UpdatePatch(patchElement);
|
821
|
-
} catch (e) {
|
822
|
-
continue;
|
823
|
-
}
|
824
|
-
this._patches.push(patch);
|
825
|
-
}
|
826
|
-
|
827
|
-
if (0 == this._patches.length)
|
828
|
-
throw Components.results.NS_ERROR_ILLEGAL_VALUE;
|
829
|
-
|
830
|
-
for (var i = 0; i < update.attributes.length; ++i) {
|
831
|
-
var attr = update.attributes.item(i);
|
832
|
-
attr.QueryInterface(Components.interfaces.nsIDOMAttr);
|
833
|
-
if (attr.name == "installDate" && attr.value)
|
834
|
-
this.installDate = parseInt(attr.value);
|
835
|
-
else if (attr.name == "isCompleteUpdate")
|
836
|
-
this.isCompleteUpdate = attr.value == "true";
|
837
|
-
else if (attr.name == "isSecurityUpdate")
|
838
|
-
this.isSecurityUpdate = attr.value == "true";
|
839
|
-
else if (attr.name == "detailsURL")
|
840
|
-
this._detailsURL = attr.value;
|
841
|
-
else if (attr.name == "channel")
|
842
|
-
this.channel = attr.value;
|
843
|
-
else
|
844
|
-
this[attr.name] = attr.value;
|
845
|
-
}
|
846
|
-
|
847
|
-
// The Update Name is either the string provided by the <update> element, or
|
848
|
-
// the string: "<App Name> <Update App Version>"
|
849
|
-
var name = "";
|
850
|
-
if (update.hasAttribute("name"))
|
851
|
-
name = update.getAttribute("name");
|
852
|
-
else {
|
853
|
-
var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"]
|
854
|
-
.getService(Components.interfaces.nsIStringBundleService);
|
855
|
-
var brandBundle = sbs.createBundle(URI_BRAND_PROPERTIES);
|
856
|
-
var updateBundle = sbs.createBundle(URI_UPDATES_PROPERTIES);
|
857
|
-
var appName = brandBundle.GetStringFromName("brandShortName");
|
858
|
-
name = updateBundle.formatStringFromName("updateName",
|
859
|
-
[appName, this.version], 2);
|
860
|
-
}
|
861
|
-
this.name = name;
|
862
|
-
}
|
863
|
-
Update.prototype = {
|
864
|
-
/**
|
865
|
-
* See nsIUpdateService.idl
|
866
|
-
*/
|
867
|
-
get patchCount() {
|
868
|
-
return this._patches.length;
|
869
|
-
},
|
870
|
-
|
871
|
-
/**
|
872
|
-
* See nsIUpdateService.idl
|
873
|
-
*/
|
874
|
-
getPatchAt: function(index) {
|
875
|
-
return this._patches[index];
|
876
|
-
},
|
877
|
-
|
878
|
-
/**
|
879
|
-
* See nsIUpdateService.idl
|
880
|
-
*
|
881
|
-
* We use a copy of the state cached on this object in |_state| only when
|
882
|
-
* there is no selected patch, i.e. in the case when we could not load
|
883
|
-
* |.activeUpdate| from the update manager for some reason but still have
|
884
|
-
* the update.status file to work with.
|
885
|
-
*/
|
886
|
-
_state: "",
|
887
|
-
set state(state) {
|
888
|
-
if (this.selectedPatch)
|
889
|
-
this.selectedPatch.state = state;
|
890
|
-
this._state = state;
|
891
|
-
return state;
|
892
|
-
},
|
893
|
-
get state() {
|
894
|
-
if (this.selectedPatch)
|
895
|
-
return this.selectedPatch.state;
|
896
|
-
return this._state;
|
897
|
-
},
|
898
|
-
|
899
|
-
/**
|
900
|
-
* See nsIUpdateService.idl
|
901
|
-
*/
|
902
|
-
errorCode: 0,
|
903
|
-
|
904
|
-
/**
|
905
|
-
* See nsIUpdateService.idl
|
906
|
-
*/
|
907
|
-
get selectedPatch() {
|
908
|
-
for (var i = 0; i < this.patchCount; ++i) {
|
909
|
-
if (this._patches[i].selected)
|
910
|
-
return this._patches[i];
|
911
|
-
}
|
912
|
-
return null;
|
913
|
-
},
|
914
|
-
|
915
|
-
/**
|
916
|
-
* See nsIUpdateService.idl
|
917
|
-
*/
|
918
|
-
get detailsURL() {
|
919
|
-
if (!this._detailsURL) {
|
920
|
-
try {
|
921
|
-
// Try using a default details URL supplied by the distribution
|
922
|
-
// if the update XML does not supply one.
|
923
|
-
var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
|
924
|
-
.getService(Components.interfaces.nsIURLFormatter);
|
925
|
-
return formatter.formatURLPref(PREF_APP_UPDATE_URL_DETAILS);
|
926
|
-
}
|
927
|
-
catch (e) {
|
928
|
-
}
|
929
|
-
}
|
930
|
-
return this._detailsURL || "";
|
931
|
-
},
|
932
|
-
|
933
|
-
/**
|
934
|
-
* See nsIUpdateService.idl
|
935
|
-
*/
|
936
|
-
serialize: function(updates) {
|
937
|
-
var update = updates.createElementNS(URI_UPDATE_NS, "update");
|
938
|
-
update.setAttribute("type", this.type);
|
939
|
-
update.setAttribute("name", this.name);
|
940
|
-
update.setAttribute("version", this.version);
|
941
|
-
update.setAttribute("extensionVersion", this.extensionVersion);
|
942
|
-
update.setAttribute("detailsURL", this.detailsURL);
|
943
|
-
update.setAttribute("licenseURL", this.licenseURL);
|
944
|
-
update.setAttribute("serviceURL", this.serviceURL);
|
945
|
-
update.setAttribute("installDate", this.installDate);
|
946
|
-
update.setAttribute("statusText", this.statusText);
|
947
|
-
update.setAttribute("buildID", this.buildID);
|
948
|
-
update.setAttribute("isCompleteUpdate", this.isCompleteUpdate);
|
949
|
-
update.setAttribute("channel", this.channel);
|
950
|
-
updates.documentElement.appendChild(update);
|
951
|
-
|
952
|
-
for (var p in this._properties) {
|
953
|
-
if (this._properties[p].present)
|
954
|
-
update.setAttribute(p, this._properties[p].data);
|
955
|
-
}
|
956
|
-
|
957
|
-
for (var i = 0; i < this.patchCount; ++i)
|
958
|
-
update.appendChild(this.getPatchAt(i).serialize(updates));
|
959
|
-
|
960
|
-
return update;
|
961
|
-
},
|
962
|
-
|
963
|
-
/**
|
964
|
-
* A hash of custom properties
|
965
|
-
*/
|
966
|
-
_properties: null,
|
967
|
-
|
968
|
-
/**
|
969
|
-
* See nsIWritablePropertyBag.idl
|
970
|
-
*/
|
971
|
-
setProperty: function(name, value) {
|
972
|
-
this._properties[name] = { data: value, present: true };
|
973
|
-
},
|
974
|
-
|
975
|
-
/**
|
976
|
-
* See nsIWritablePropertyBag.idl
|
977
|
-
*/
|
978
|
-
deleteProperty: function(name) {
|
979
|
-
if (name in this._properties)
|
980
|
-
this._properties[name].present = false;
|
981
|
-
else
|
982
|
-
throw Components.results.NS_ERROR_FAILURE;
|
983
|
-
},
|
984
|
-
|
985
|
-
/**
|
986
|
-
* See nsIPropertyBag.idl
|
987
|
-
*/
|
988
|
-
get enumerator() {
|
989
|
-
var properties = [];
|
990
|
-
for (var p in this._properties)
|
991
|
-
properties.push(this._properties[p].data);
|
992
|
-
return new ArrayEnumerator(properties);
|
993
|
-
},
|
994
|
-
|
995
|
-
/**
|
996
|
-
* See nsIPropertyBag.idl
|
997
|
-
*/
|
998
|
-
getProperty: function(name) {
|
999
|
-
if (name in this._properties &&
|
1000
|
-
this._properties[name].present)
|
1001
|
-
return this._properties[name].data;
|
1002
|
-
throw Components.results.NS_ERROR_FAILURE;
|
1003
|
-
},
|
1004
|
-
|
1005
|
-
/**
|
1006
|
-
* See nsISupports.idl
|
1007
|
-
*/
|
1008
|
-
QueryInterface: function(iid) {
|
1009
|
-
if (!iid.equals(Components.interfaces.nsIUpdate_MOZILLA_1_8_BRANCH) &&
|
1010
|
-
!iid.equals(Components.interfaces.nsIUpdate) &&
|
1011
|
-
!iid.equals(Components.interfaces.nsIPropertyBag) &&
|
1012
|
-
!iid.equals(Components.interfaces.nsIWritablePropertyBag) &&
|
1013
|
-
!iid.equals(Components.interfaces.nsISupports))
|
1014
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
1015
|
-
return this;
|
1016
|
-
}
|
1017
|
-
};
|
1018
|
-
|
1019
|
-
/**
|
1020
|
-
* UpdateService
|
1021
|
-
* A Service for managing the discovery and installation of software updates.
|
1022
|
-
* @constructor
|
1023
|
-
*/
|
1024
|
-
function UpdateService() {
|
1025
|
-
gApp = Components.classes["@mozilla.org/xre/app-info;1"]
|
1026
|
-
.getService(Components.interfaces.nsIXULAppInfo)
|
1027
|
-
.QueryInterface(Components.interfaces.nsIXULRuntime);
|
1028
|
-
gPref = Components.classes["@mozilla.org/preferences-service;1"]
|
1029
|
-
.getService(Components.interfaces.nsIPrefBranch2);
|
1030
|
-
gConsole = Components.classes["@mozilla.org/consoleservice;1"]
|
1031
|
-
.getService(Components.interfaces.nsIConsoleService);
|
1032
|
-
|
1033
|
-
// Not all builds have a known ABI
|
1034
|
-
try {
|
1035
|
-
gABI = gApp.XPCOMABI;
|
1036
|
-
}
|
1037
|
-
catch (e) {
|
1038
|
-
LOG("UpdateService", "XPCOM ABI unknown: updates are not possible.");
|
1039
|
-
}
|
1040
|
-
|
1041
|
-
try {
|
1042
|
-
var sysInfo =
|
1043
|
-
Components.classes["@mozilla.org/system-info;1"]
|
1044
|
-
.getService(Components.interfaces.nsIPropertyBag2);
|
1045
|
-
|
1046
|
-
gOSVersion = encodeURIComponent(sysInfo.getProperty("name") + " " +
|
1047
|
-
sysInfo.getProperty("version"));
|
1048
|
-
}
|
1049
|
-
catch (e) {
|
1050
|
-
LOG("UpdateService", "OS Version unknown: updates are not possible.");
|
1051
|
-
}
|
1052
|
-
|
1053
|
-
//@line 1023 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
1054
|
-
|
1055
|
-
// Start the update timer only after a profile has been selected so that the
|
1056
|
-
// appropriate values for the update check are read from the user's profile.
|
1057
|
-
var os = getObserverService();
|
1058
|
-
|
1059
|
-
os.addObserver(this, "profile-after-change", false);
|
1060
|
-
|
1061
|
-
// Observe xpcom-shutdown to unhook pref branch observers above to avoid
|
1062
|
-
// shutdown leaks.
|
1063
|
-
os.addObserver(this, "xpcom-shutdown", false);
|
1064
|
-
}
|
1065
|
-
|
1066
|
-
UpdateService.prototype = {
|
1067
|
-
/**
|
1068
|
-
* The downloader we are using to download updates. There is only ever one of
|
1069
|
-
* these.
|
1070
|
-
*/
|
1071
|
-
_downloader: null,
|
1072
|
-
|
1073
|
-
/**
|
1074
|
-
* Handle Observer Service notifications
|
1075
|
-
* @param subject
|
1076
|
-
* The subject of the notification
|
1077
|
-
* @param topic
|
1078
|
-
* The notification name
|
1079
|
-
* @param data
|
1080
|
-
* Additional data
|
1081
|
-
*/
|
1082
|
-
observe: function(subject, topic, data) {
|
1083
|
-
var os = getObserverService();
|
1084
|
-
|
1085
|
-
switch (topic) {
|
1086
|
-
case "profile-after-change":
|
1087
|
-
os.removeObserver(this, "profile-after-change");
|
1088
|
-
this._start();
|
1089
|
-
break;
|
1090
|
-
case "xpcom-shutdown":
|
1091
|
-
os.removeObserver(this, "xpcom-shutdown");
|
1092
|
-
|
1093
|
-
// Release Services
|
1094
|
-
gApp = null;
|
1095
|
-
gPref = null;
|
1096
|
-
gConsole = null;
|
1097
|
-
break;
|
1098
|
-
}
|
1099
|
-
},
|
1100
|
-
|
1101
|
-
/**
|
1102
|
-
* Start the Update Service
|
1103
|
-
*/
|
1104
|
-
_start: function() {
|
1105
|
-
// Start logging
|
1106
|
-
this._initLoggingPrefs();
|
1107
|
-
|
1108
|
-
// Clean up any extant updates
|
1109
|
-
this._postUpdateProcessing();
|
1110
|
-
|
1111
|
-
// Register a background update check timer
|
1112
|
-
var tm =
|
1113
|
-
Components.classes["@mozilla.org/updates/timer-manager;1"]
|
1114
|
-
.getService(Components.interfaces.nsIUpdateTimerManager);
|
1115
|
-
var interval = getPref("getIntPref", PREF_APP_UPDATE_INTERVAL, 86400);
|
1116
|
-
tm.registerTimer("background-update-timer", this, interval);
|
1117
|
-
|
1118
|
-
// Resume fetching...
|
1119
|
-
var um = Components.classes["@mozilla.org/updates/update-manager;1"]
|
1120
|
-
.getService(Components.interfaces.nsIUpdateManager);
|
1121
|
-
var activeUpdate = um.activeUpdate;
|
1122
|
-
if (activeUpdate) {
|
1123
|
-
var status = this.downloadUpdate(activeUpdate, true);
|
1124
|
-
if (status == STATE_NONE)
|
1125
|
-
cleanupActiveUpdate();
|
1126
|
-
}
|
1127
|
-
},
|
1128
|
-
|
1129
|
-
/**
|
1130
|
-
* Perform post-processing on updates lingering in the updates directory
|
1131
|
-
* from a previous browser session - either report install failures (and
|
1132
|
-
* optionally attempt to fetch a different version if appropriate) or
|
1133
|
-
* notify the user of install success.
|
1134
|
-
*/
|
1135
|
-
_postUpdateProcessing: function() {
|
1136
|
-
// Detect installation failures and notify
|
1137
|
-
|
1138
|
-
// Bail out if we don't have appropriate permissions
|
1139
|
-
if (!this.canUpdate)
|
1140
|
-
return;
|
1141
|
-
|
1142
|
-
var status = readStatusFile(getUpdatesDir());
|
1143
|
-
|
1144
|
-
// Make sure to cleanup after an update that failed for an unknown reason
|
1145
|
-
if (status == "null")
|
1146
|
-
status = null;
|
1147
|
-
|
1148
|
-
var updRootKey = null;
|
1149
|
-
//@line 1119 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
1150
|
-
function findPreviousUpdate(key) {
|
1151
|
-
var updateDir = getUpdatesDir(key);
|
1152
|
-
if (updateDir.exists()) {
|
1153
|
-
status = readStatusFile(updateDir);
|
1154
|
-
// Previous download should succeed. Otherwise, we will not be here!
|
1155
|
-
if (status == STATE_SUCCEEDED)
|
1156
|
-
updRootKey = key;
|
1157
|
-
else
|
1158
|
-
status = null;
|
1159
|
-
}
|
1160
|
-
}
|
1161
|
-
|
1162
|
-
// required when updating from Fx 2.0.0.1 to 2.0.0.3 (or later)
|
1163
|
-
// on Windows Vista.
|
1164
|
-
if (status == null)
|
1165
|
-
findPreviousUpdate(KEY_UAPPDATA);
|
1166
|
-
|
1167
|
-
// required to migrate from older versions.
|
1168
|
-
if (status == null)
|
1169
|
-
findPreviousUpdate(KEY_APPDIR);
|
1170
|
-
//@line 1140 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
1171
|
-
|
1172
|
-
if (status == STATE_DOWNLOADING) {
|
1173
|
-
LOG("UpdateService", "_postUpdateProcessing: Downloading patch, resuming...");
|
1174
|
-
}
|
1175
|
-
else if (status != null) {
|
1176
|
-
// null status means the update.status file is not present, because either:
|
1177
|
-
// 1) no update was performed, and so there's no UI to show
|
1178
|
-
// 2) an update was attempted but failed during checking, transfer or
|
1179
|
-
// verification, and was cleaned up at that point, and UI notifying of
|
1180
|
-
// that error was shown at that stage.
|
1181
|
-
var um =
|
1182
|
-
Components.classes["@mozilla.org/updates/update-manager;1"].
|
1183
|
-
getService(Components.interfaces.nsIUpdateManager);
|
1184
|
-
var prompter =
|
1185
|
-
Components.classes["@mozilla.org/updates/update-prompt;1"].
|
1186
|
-
createInstance(Components.interfaces.nsIUpdatePrompt);
|
1187
|
-
|
1188
|
-
var shouldCleanup = true;
|
1189
|
-
var update = um.activeUpdate;
|
1190
|
-
if (!update) {
|
1191
|
-
update = new Update(null);
|
1192
|
-
}
|
1193
|
-
update.state = status;
|
1194
|
-
var sbs =
|
1195
|
-
Components.classes["@mozilla.org/intl/stringbundle;1"].
|
1196
|
-
getService(Components.interfaces.nsIStringBundleService);
|
1197
|
-
var bundle = sbs.createBundle(URI_UPDATES_PROPERTIES);
|
1198
|
-
if (status == STATE_SUCCEEDED) {
|
1199
|
-
update.statusText = bundle.GetStringFromName("installSuccess");
|
1200
|
-
|
1201
|
-
// Dig through the update history to find the patch that was just
|
1202
|
-
// installed and update its metadata.
|
1203
|
-
for (var i = 0; i < um.updateCount; ++i) {
|
1204
|
-
var umUpdate = um.getUpdateAt(i);
|
1205
|
-
if (umUpdate && umUpdate.version == update.version &&
|
1206
|
-
umUpdate.buildID == update.buildID) {
|
1207
|
-
umUpdate.statusText = update.statusText;
|
1208
|
-
break;
|
1209
|
-
}
|
1210
|
-
}
|
1211
|
-
|
1212
|
-
LOG("UpdateService", "_postUpdateProcessing: Install Succeeded, Showing UI");
|
1213
|
-
prompter.showUpdateInstalled(update);
|
1214
|
-
//@line 1187 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
1215
|
-
// Perform platform-specific post-update processing.
|
1216
|
-
if (POST_UPDATE_CONTRACTID in Components.classes) {
|
1217
|
-
Components.classes[POST_UPDATE_CONTRACTID].
|
1218
|
-
createInstance(Components.interfaces.nsIRunnable).run();
|
1219
|
-
}
|
1220
|
-
//@line 1193 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
1221
|
-
|
1222
|
-
// Done with this update. Clean it up.
|
1223
|
-
cleanupActiveUpdate(updRootKey);
|
1224
|
-
}
|
1225
|
-
else {
|
1226
|
-
// If we hit an error, then the error code will be included in the
|
1227
|
-
// status string following a colon. If we had an I/O error, then we
|
1228
|
-
// assume that the patch is not invalid, and we restage the patch so
|
1229
|
-
// that it can be attempted again the next time we restart.
|
1230
|
-
var ary = status.split(": ");
|
1231
|
-
update.state = ary[0];
|
1232
|
-
if (update.state == STATE_FAILED && ary[1]) {
|
1233
|
-
update.errorCode = ary[1];
|
1234
|
-
if (update.errorCode == WRITE_ERROR) {
|
1235
|
-
prompter.showUpdateError(update);
|
1236
|
-
writeStatusFile(getUpdatesDir(), update.state = STATE_PENDING);
|
1237
|
-
return;
|
1238
|
-
}
|
1239
|
-
}
|
1240
|
-
|
1241
|
-
// Something went wrong with the patch application process.
|
1242
|
-
cleanupActiveUpdate();
|
1243
|
-
|
1244
|
-
update.statusText = bundle.GetStringFromName("patchApplyFailure");
|
1245
|
-
var oldType = update.selectedPatch ? update.selectedPatch.type
|
1246
|
-
: "complete";
|
1247
|
-
if (update.selectedPatch && oldType == "partial") {
|
1248
|
-
// Partial patch application failed, try downloading the complete
|
1249
|
-
// update in the background instead.
|
1250
|
-
LOG("UpdateService", "_postUpdateProcessing: Install of Partial Patch " +
|
1251
|
-
"failed, downloading Complete Patch and maybe showing UI");
|
1252
|
-
var status = this.downloadUpdate(update, true);
|
1253
|
-
if (status == STATE_NONE)
|
1254
|
-
cleanupActiveUpdate();
|
1255
|
-
}
|
1256
|
-
else {
|
1257
|
-
LOG("UpdateService", "_postUpdateProcessing: Install of Complete or " +
|
1258
|
-
"only patch failed. Showing error.");
|
1259
|
-
}
|
1260
|
-
update.QueryInterface(Components.interfaces.nsIWritablePropertyBag);
|
1261
|
-
update.setProperty("patchingFailed", oldType);
|
1262
|
-
prompter.showUpdateError(update);
|
1263
|
-
}
|
1264
|
-
}
|
1265
|
-
else {
|
1266
|
-
LOG("UpdateService", "_postUpdateProcessing: No Status, No Update");
|
1267
|
-
}
|
1268
|
-
},
|
1269
|
-
|
1270
|
-
/**
|
1271
|
-
* Initialize Logging preferences, formatted like so:
|
1272
|
-
* app.update.log.<moduleName> = <true|false>
|
1273
|
-
*/
|
1274
|
-
_initLoggingPrefs: function() {
|
1275
|
-
try {
|
1276
|
-
var ps = Components.classes["@mozilla.org/preferences-service;1"]
|
1277
|
-
.getService(Components.interfaces.nsIPrefService);
|
1278
|
-
var logBranch = ps.getBranch(PREF_APP_UPDATE_LOG_BRANCH);
|
1279
|
-
var modules = logBranch.getChildList("", { value: 0 });
|
1280
|
-
|
1281
|
-
for (var i = 0; i < modules.length; ++i) {
|
1282
|
-
if (logBranch.prefHasUserValue(modules[i]))
|
1283
|
-
gLogEnabled[modules[i]] = logBranch.getBoolPref(modules[i]);
|
1284
|
-
}
|
1285
|
-
}
|
1286
|
-
catch (e) {
|
1287
|
-
}
|
1288
|
-
},
|
1289
|
-
|
1290
|
-
/**
|
1291
|
-
*
|
1292
|
-
*/
|
1293
|
-
_needsToPromptForUpdate: function(updates) {
|
1294
|
-
// First, check for Extension incompatibilities. These trump any preference
|
1295
|
-
// settings.
|
1296
|
-
var em = Components.classes["@mozilla.org/extensions/manager;1"]
|
1297
|
-
.getService(Components.interfaces.nsIExtensionManager);
|
1298
|
-
var incompatibleList = { };
|
1299
|
-
for (var i = 0; i < updates.length; ++i) {
|
1300
|
-
var count = {};
|
1301
|
-
em.getIncompatibleItemList(gApp.ID, updates[i].extensionVersion,
|
1302
|
-
nsIUpdateItem.TYPE_ADDON, false, count);
|
1303
|
-
if (count.value > 0)
|
1304
|
-
return true;
|
1305
|
-
}
|
1306
|
-
|
1307
|
-
// Now, inspect user preferences.
|
1308
|
-
|
1309
|
-
// No prompt necessary, silently update...
|
1310
|
-
return false;
|
1311
|
-
},
|
1312
|
-
|
1313
|
-
/**
|
1314
|
-
* Notified when a timer fires
|
1315
|
-
* @param timer
|
1316
|
-
* The timer that fired
|
1317
|
-
*/
|
1318
|
-
notify: function(timer) {
|
1319
|
-
// If a download is in progress, then do nothing.
|
1320
|
-
if (this.isDownloading || this._downloader && this._downloader.patchIsStaged)
|
1321
|
-
return;
|
1322
|
-
|
1323
|
-
var self = this;
|
1324
|
-
var listener = {
|
1325
|
-
/**
|
1326
|
-
* See nsIUpdateService.idl
|
1327
|
-
*/
|
1328
|
-
onProgress: function(request, position, totalSize) {
|
1329
|
-
},
|
1330
|
-
|
1331
|
-
/**
|
1332
|
-
* See nsIUpdateService.idl
|
1333
|
-
*/
|
1334
|
-
onCheckComplete: function(request, updates, updateCount) {
|
1335
|
-
self._selectAndInstallUpdate(updates);
|
1336
|
-
},
|
1337
|
-
|
1338
|
-
/**
|
1339
|
-
* See nsIUpdateService.idl
|
1340
|
-
*/
|
1341
|
-
onError: function(request, update) {
|
1342
|
-
LOG("Checker", "Error during background update: " + update.statusText);
|
1343
|
-
},
|
1344
|
-
}
|
1345
|
-
this.backgroundChecker.checkForUpdates(listener, false);
|
1346
|
-
},
|
1347
|
-
|
1348
|
-
/**
|
1349
|
-
* Determine whether or not an update requires user confirmation before it
|
1350
|
-
* can be installed.
|
1351
|
-
* @param update
|
1352
|
-
* The update to be installed
|
1353
|
-
* @returns true if a prompt UI should be shown asking the user if they want
|
1354
|
-
* to install the update, false if the update should just be
|
1355
|
-
* silently downloaded and installed.
|
1356
|
-
*/
|
1357
|
-
_shouldPrompt: function(update) {
|
1358
|
-
// There are two possible outcomes here:
|
1359
|
-
// 1. download and install the update automatically
|
1360
|
-
// 2. alert the user about the presence of an update before doing anything
|
1361
|
-
//
|
1362
|
-
// The outcome we follow is determined as follows:
|
1363
|
-
//
|
1364
|
-
// Note: all Major updates require notification and confirmation
|
1365
|
-
//
|
1366
|
-
// Update Type Mode Incompatible Outcome
|
1367
|
-
// Major 0 Yes or No Notify and Confirm
|
1368
|
-
// Major 1 No Notify and Confirm
|
1369
|
-
// Major 1 Yes Notify and Confirm
|
1370
|
-
// Major 2 Yes or No Notify and Confirm
|
1371
|
-
// Minor 0 Yes or No Auto Install
|
1372
|
-
// Minor 1 No Auto Install
|
1373
|
-
// Minor 1 Yes Notify and Confirm
|
1374
|
-
// Minor 2 No Auto Install
|
1375
|
-
// Minor 2 Yes Notify and Confirm
|
1376
|
-
//
|
1377
|
-
// In addition, if there is a license associated with an update, regardless
|
1378
|
-
// of type it must be agreed to.
|
1379
|
-
//
|
1380
|
-
// If app.update.enabled is set to false, an update check is not performed
|
1381
|
-
// at all, and so none of the decision making above is entered into.
|
1382
|
-
//
|
1383
|
-
if (update.type == "major") {
|
1384
|
-
LOG("Checker", "_shouldPrompt: Prompting because it is a major update");
|
1385
|
-
return true;
|
1386
|
-
}
|
1387
|
-
|
1388
|
-
update.QueryInterface(Components.interfaces.nsIPropertyBag);
|
1389
|
-
try {
|
1390
|
-
var licenseAccepted = update.getProperty("licenseAccepted") == "true";
|
1391
|
-
}
|
1392
|
-
catch (e) {
|
1393
|
-
licenseAccepted = false;
|
1394
|
-
}
|
1395
|
-
|
1396
|
-
var updateEnabled = getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true);
|
1397
|
-
if (!updateEnabled) {
|
1398
|
-
LOG("Checker", "_shouldPrompt: Not prompting because update is " +
|
1399
|
-
"disabled");
|
1400
|
-
return false;
|
1401
|
-
}
|
1402
|
-
|
1403
|
-
// User has turned off automatic download and install
|
1404
|
-
var autoEnabled = getPref("getBoolPref", PREF_APP_UPDATE_AUTO, true);
|
1405
|
-
if (!autoEnabled) {
|
1406
|
-
LOG("Checker", "_shouldPrompt: Prompting because auto install is disabled");
|
1407
|
-
return true;
|
1408
|
-
}
|
1409
|
-
|
1410
|
-
switch (getPref("getIntPref", PREF_APP_UPDATE_MODE, 1)) {
|
1411
|
-
case 1:
|
1412
|
-
// Mode 1 is do not prompt only if there are no incompatibilities
|
1413
|
-
// releases
|
1414
|
-
LOG("Checker", "_shouldPrompt: Prompting if there are incompatibilities");
|
1415
|
-
return !isCompatible(update);
|
1416
|
-
case 2:
|
1417
|
-
// Mode 2 is do not prompt only if there are no incompatibilities
|
1418
|
-
LOG("Checker", "_shouldPrompt: Prompting if there are incompatibilities");
|
1419
|
-
return !isCompatible(update);
|
1420
|
-
}
|
1421
|
-
// Mode 0 is do not prompt regardless of incompatibilities
|
1422
|
-
LOG("Checker", "_shouldPrompt: Not prompting the user - they choose to " +
|
1423
|
-
"ignore incompatibilities");
|
1424
|
-
return false;
|
1425
|
-
},
|
1426
|
-
|
1427
|
-
/**
|
1428
|
-
* Determine which of the specified updates should be installed.
|
1429
|
-
* @param updates
|
1430
|
-
* An array of available updates
|
1431
|
-
*/
|
1432
|
-
selectUpdate: function(updates) {
|
1433
|
-
if (updates.length == 0)
|
1434
|
-
return null;
|
1435
|
-
|
1436
|
-
// Choose the newest of the available minor and major updates.
|
1437
|
-
var majorUpdate = null, minorUpdate = null;
|
1438
|
-
var newestMinor = updates[0], newestMajor = updates[0];
|
1439
|
-
|
1440
|
-
var vc = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
|
1441
|
-
.getService(Components.interfaces.nsIVersionComparator);
|
1442
|
-
for (var i = 0; i < updates.length; ++i) {
|
1443
|
-
if (updates[i].type == "major" &&
|
1444
|
-
vc.compare(newestMajor.version, updates[i].version) <= 0)
|
1445
|
-
majorUpdate = newestMajor = updates[i];
|
1446
|
-
if (updates[i].type == "minor" &&
|
1447
|
-
vc.compare(newestMinor.version, updates[i].version) <= 0)
|
1448
|
-
minorUpdate = newestMinor = updates[i];
|
1449
|
-
}
|
1450
|
-
|
1451
|
-
// IMPORTANT
|
1452
|
-
// If there's a minor update, always try and fetch that one first,
|
1453
|
-
// otherwise use the newest major update.
|
1454
|
-
// selectUpdate() only returns one update.
|
1455
|
-
// if major were to trump minor, and we said "never" to the major
|
1456
|
-
// we'd never get the minor update, since selectUpdate()
|
1457
|
-
// would return the major update that the user said "never" to
|
1458
|
-
// (shadowing the important minor update with security fixes)
|
1459
|
-
return minorUpdate || majorUpdate;
|
1460
|
-
},
|
1461
|
-
|
1462
|
-
/**
|
1463
|
-
* Determine which of the specified updates should be installed and
|
1464
|
-
* begin the download/installation process, optionally prompting the
|
1465
|
-
* user for permission if required.
|
1466
|
-
* @param updates
|
1467
|
-
* An array of available updates
|
1468
|
-
*/
|
1469
|
-
_selectAndInstallUpdate: function(updates) {
|
1470
|
-
// Don't prompt if there's an active update - the user is already
|
1471
|
-
// aware and is downloading, or performed some user action to prevent
|
1472
|
-
// notification.
|
1473
|
-
var um = Components.classes["@mozilla.org/updates/update-manager;1"]
|
1474
|
-
.getService(Components.interfaces.nsIUpdateManager);
|
1475
|
-
if (um.activeUpdate)
|
1476
|
-
return;
|
1477
|
-
|
1478
|
-
var update = this.selectUpdate(updates, updates.length);
|
1479
|
-
if (!update)
|
1480
|
-
return;
|
1481
|
-
|
1482
|
-
// check if the user said "never" to this version
|
1483
|
-
// this check is done here, and not in selectUpdate() so that
|
1484
|
-
// the user can get an upgrade they said "never" to if they
|
1485
|
-
// manually do "Check for Updates..."
|
1486
|
-
// note, selectUpdate() only returns one update.
|
1487
|
-
// but in selectUpdate(), minor updates trump major updates
|
1488
|
-
// if major trumps minor, and we said "never" to the major
|
1489
|
-
// we'd never see the minor update.
|
1490
|
-
//
|
1491
|
-
// note, the never decision should only apply to major updates
|
1492
|
-
// see bug #350636 for a scenario where this could potentially
|
1493
|
-
// be an issue
|
1494
|
-
var neverPrefName = PREF_UPDATE_NEVER_BRANCH + update.version;
|
1495
|
-
var never = getPref("getBoolPref", neverPrefName, false);
|
1496
|
-
if (never && update.type == "major")
|
1497
|
-
return;
|
1498
|
-
|
1499
|
-
if (this._shouldPrompt(update))
|
1500
|
-
showPromptIfNoIncompatibilities(update);
|
1501
|
-
else {
|
1502
|
-
LOG("UpdateService", "_selectAndInstallUpdate: No need to show prompt, just download update");
|
1503
|
-
var status = this.downloadUpdate(update, true);
|
1504
|
-
if (status == STATE_NONE)
|
1505
|
-
cleanupActiveUpdate();
|
1506
|
-
}
|
1507
|
-
},
|
1508
|
-
|
1509
|
-
/**
|
1510
|
-
* The Checker used for background update checks.
|
1511
|
-
*/
|
1512
|
-
_backgroundChecker: null,
|
1513
|
-
|
1514
|
-
/**
|
1515
|
-
* See nsIUpdateService.idl
|
1516
|
-
*/
|
1517
|
-
get backgroundChecker() {
|
1518
|
-
if (!this._backgroundChecker)
|
1519
|
-
this._backgroundChecker = new Checker();
|
1520
|
-
return this._backgroundChecker;
|
1521
|
-
},
|
1522
|
-
|
1523
|
-
/**
|
1524
|
-
* See nsIUpdateService.idl
|
1525
|
-
*/
|
1526
|
-
get canUpdate() {
|
1527
|
-
try {
|
1528
|
-
var appDirFile = getUpdateFile([FILE_PERMS_TEST]);
|
1529
|
-
if (!appDirFile.exists()) {
|
1530
|
-
appDirFile.create(nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
|
1531
|
-
appDirFile.remove(false);
|
1532
|
-
}
|
1533
|
-
var updateDir = getUpdatesDir();
|
1534
|
-
var upDirFile = updateDir.clone();
|
1535
|
-
upDirFile.append(FILE_PERMS_TEST);
|
1536
|
-
if (!upDirFile.exists()) {
|
1537
|
-
upDirFile.create(nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
|
1538
|
-
upDirFile.remove(false);
|
1539
|
-
}
|
1540
|
-
}
|
1541
|
-
catch (e) {
|
1542
|
-
// No write privileges to install directory
|
1543
|
-
return false;
|
1544
|
-
}
|
1545
|
-
// If the administrator has locked the app update functionality
|
1546
|
-
// OFF - this is not just a user setting, so disable the manual
|
1547
|
-
// UI too.
|
1548
|
-
var enabled = getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true);
|
1549
|
-
if (!enabled && gPref.prefIsLocked(PREF_APP_UPDATE_ENABLED))
|
1550
|
-
return false;
|
1551
|
-
|
1552
|
-
// If we don't know the binary platform we're updating, we can't update.
|
1553
|
-
if (!gABI)
|
1554
|
-
return false;
|
1555
|
-
|
1556
|
-
// If we don't know the OS version we're updating, we can't update.
|
1557
|
-
if (!gOSVersion)
|
1558
|
-
return false;
|
1559
|
-
|
1560
|
-
return true;
|
1561
|
-
},
|
1562
|
-
|
1563
|
-
/**
|
1564
|
-
* See nsIUpdateService.idl
|
1565
|
-
*/
|
1566
|
-
addDownloadListener: function(listener) {
|
1567
|
-
if (!this._downloader) {
|
1568
|
-
LOG("UpdateService", "addDownloadListener: no downloader!\n");
|
1569
|
-
return;
|
1570
|
-
}
|
1571
|
-
this._downloader.addDownloadListener(listener);
|
1572
|
-
},
|
1573
|
-
|
1574
|
-
/**
|
1575
|
-
* See nsIUpdateService.idl
|
1576
|
-
*/
|
1577
|
-
removeDownloadListener: function(listener) {
|
1578
|
-
if (!this._downloader) {
|
1579
|
-
LOG("UpdateService", "removeDownloadListener: no downloader!\n");
|
1580
|
-
return;
|
1581
|
-
}
|
1582
|
-
this._downloader.removeDownloadListener(listener);
|
1583
|
-
},
|
1584
|
-
|
1585
|
-
/**
|
1586
|
-
* See nsIUpdateService.idl
|
1587
|
-
*/
|
1588
|
-
downloadUpdate: function(update, background) {
|
1589
|
-
if (!update)
|
1590
|
-
throw Components.results.NS_ERROR_NULL_POINTER;
|
1591
|
-
if (this.isDownloading) {
|
1592
|
-
if (update.isCompleteUpdate == this._downloader.isCompleteUpdate &&
|
1593
|
-
background == this._downloader.background) {
|
1594
|
-
LOG("UpdateService", "no support for downloading more than one update at a time");
|
1595
|
-
return readStatusFile(getUpdatesDir());
|
1596
|
-
}
|
1597
|
-
this._downloader.cancel();
|
1598
|
-
}
|
1599
|
-
this._downloader = new Downloader(background);
|
1600
|
-
return this._downloader.downloadUpdate(update);
|
1601
|
-
},
|
1602
|
-
|
1603
|
-
/**
|
1604
|
-
* See nsIUpdateService.idl
|
1605
|
-
*/
|
1606
|
-
pauseDownload: function() {
|
1607
|
-
if (this.isDownloading)
|
1608
|
-
this._downloader.cancel();
|
1609
|
-
},
|
1610
|
-
|
1611
|
-
/**
|
1612
|
-
* See nsIUpdateService.idl
|
1613
|
-
*/
|
1614
|
-
get isDownloading() {
|
1615
|
-
return this._downloader && this._downloader.isBusy;
|
1616
|
-
},
|
1617
|
-
|
1618
|
-
/**
|
1619
|
-
* See nsISupports.idl
|
1620
|
-
*/
|
1621
|
-
QueryInterface: function(iid) {
|
1622
|
-
if (!iid.equals(Components.interfaces.nsIApplicationUpdateService) &&
|
1623
|
-
!iid.equals(Components.interfaces.nsITimerCallback) &&
|
1624
|
-
!iid.equals(Components.interfaces.nsIObserver) &&
|
1625
|
-
!iid.equals(Components.interfaces.nsISupports))
|
1626
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
1627
|
-
return this;
|
1628
|
-
}
|
1629
|
-
};
|
1630
|
-
|
1631
|
-
/**
|
1632
|
-
* A service to manage active and past updates.
|
1633
|
-
* @constructor
|
1634
|
-
*/
|
1635
|
-
function UpdateManager() {
|
1636
|
-
// Ensure the Active Update file is loaded
|
1637
|
-
var updates = this._loadXMLFileIntoArray(getUpdateFile([FILE_UPDATE_ACTIVE]));
|
1638
|
-
if (updates.length > 0)
|
1639
|
-
this._activeUpdate = updates[0];
|
1640
|
-
}
|
1641
|
-
UpdateManager.prototype = {
|
1642
|
-
/**
|
1643
|
-
* All previously downloaded and installed updates, as an array of nsIUpdate
|
1644
|
-
* objects.
|
1645
|
-
*/
|
1646
|
-
_updates: null,
|
1647
|
-
|
1648
|
-
/**
|
1649
|
-
* The current actively downloading/installing update, as a nsIUpdate object.
|
1650
|
-
*/
|
1651
|
-
_activeUpdate: null,
|
1652
|
-
|
1653
|
-
/**
|
1654
|
-
* Loads an updates.xml formatted file into an array of nsIUpdate items.
|
1655
|
-
* @param file
|
1656
|
-
* A nsIFile for the updates.xml file
|
1657
|
-
* @returns The array of nsIUpdate items held in the file.
|
1658
|
-
*/
|
1659
|
-
_loadXMLFileIntoArray: function(file) {
|
1660
|
-
if (!file.exists()) {
|
1661
|
-
LOG("UpdateManager", "_loadXMLFileIntoArray: XML File does not exist");
|
1662
|
-
return [];
|
1663
|
-
}
|
1664
|
-
|
1665
|
-
var result = [];
|
1666
|
-
var fileStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
|
1667
|
-
.createInstance(Components.interfaces.nsIFileInputStream);
|
1668
|
-
fileStream.init(file, MODE_RDONLY, PERMS_FILE, 0);
|
1669
|
-
try {
|
1670
|
-
var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
|
1671
|
-
.createInstance(Components.interfaces.nsIDOMParser);
|
1672
|
-
var doc = parser.parseFromStream(fileStream, "UTF-8", fileStream.available(), "text/xml");
|
1673
|
-
|
1674
|
-
var updateCount = doc.documentElement.childNodes.length;
|
1675
|
-
for (var i = 0; i < updateCount; ++i) {
|
1676
|
-
var updateElement = doc.documentElement.childNodes.item(i);
|
1677
|
-
if (updateElement.nodeType != Node.ELEMENT_NODE ||
|
1678
|
-
updateElement.localName != "update")
|
1679
|
-
continue;
|
1680
|
-
|
1681
|
-
updateElement.QueryInterface(Components.interfaces.nsIDOMElement);
|
1682
|
-
try {
|
1683
|
-
var update = new Update(updateElement);
|
1684
|
-
} catch (e) {
|
1685
|
-
LOG("UpdateManager", "_loadXMLFileIntoArray: invalid update");
|
1686
|
-
continue;
|
1687
|
-
}
|
1688
|
-
result.push(new Update(updateElement));
|
1689
|
-
}
|
1690
|
-
}
|
1691
|
-
catch (e) {
|
1692
|
-
LOG("UpdateManager", "_loadXMLFileIntoArray: Error constructing update list " +
|
1693
|
-
e);
|
1694
|
-
}
|
1695
|
-
fileStream.close();
|
1696
|
-
return result;
|
1697
|
-
},
|
1698
|
-
|
1699
|
-
/**
|
1700
|
-
* Load the update manager, initializing state from state files.
|
1701
|
-
*/
|
1702
|
-
_ensureUpdates: function() {
|
1703
|
-
if (!this._updates) {
|
1704
|
-
this._updates = this._loadXMLFileIntoArray(getUpdateFile(
|
1705
|
-
[FILE_UPDATES_DB]));
|
1706
|
-
|
1707
|
-
// Make sure that any active update is part of our updates list
|
1708
|
-
var active = this.activeUpdate;
|
1709
|
-
if (active)
|
1710
|
-
this._addUpdate(active);
|
1711
|
-
}
|
1712
|
-
},
|
1713
|
-
|
1714
|
-
/**
|
1715
|
-
* See nsIUpdateService.idl
|
1716
|
-
*/
|
1717
|
-
getUpdateAt: function(index) {
|
1718
|
-
this._ensureUpdates();
|
1719
|
-
return this._updates[index];
|
1720
|
-
},
|
1721
|
-
|
1722
|
-
/**
|
1723
|
-
* See nsIUpdateService.idl
|
1724
|
-
*/
|
1725
|
-
get updateCount() {
|
1726
|
-
this._ensureUpdates();
|
1727
|
-
return this._updates.length;
|
1728
|
-
},
|
1729
|
-
|
1730
|
-
/**
|
1731
|
-
* See nsIUpdateService.idl
|
1732
|
-
*/
|
1733
|
-
get activeUpdate() {
|
1734
|
-
if (this._activeUpdate) {
|
1735
|
-
this._activeUpdate.QueryInterface(Components.interfaces.nsIUpdate_MOZILLA_1_8_BRANCH);
|
1736
|
-
if (this._activeUpdate.channel != getUpdateChannel()) {
|
1737
|
-
// User switched channels, clear out any old active updates and remove
|
1738
|
-
// partial downloads
|
1739
|
-
this._activeUpdate = null;
|
1740
|
-
|
1741
|
-
// Destroy the updates directory, since we're done with it.
|
1742
|
-
cleanUpUpdatesDir();
|
1743
|
-
}
|
1744
|
-
}
|
1745
|
-
return this._activeUpdate;
|
1746
|
-
},
|
1747
|
-
set activeUpdate(activeUpdate) {
|
1748
|
-
this._addUpdate(activeUpdate);
|
1749
|
-
this._activeUpdate = activeUpdate;
|
1750
|
-
if (!activeUpdate) {
|
1751
|
-
// If |activeUpdate| is null, we have updated both lists - the active list
|
1752
|
-
// and the history list, so we want to write both files.
|
1753
|
-
this.saveUpdates();
|
1754
|
-
}
|
1755
|
-
else
|
1756
|
-
this._writeUpdatesToXMLFile([this._activeUpdate],
|
1757
|
-
getUpdateFile([FILE_UPDATE_ACTIVE]));
|
1758
|
-
return activeUpdate;
|
1759
|
-
},
|
1760
|
-
|
1761
|
-
/**
|
1762
|
-
* Add an update to the Updates list. If the item already exists in the list,
|
1763
|
-
* replace the existing value with the new value.
|
1764
|
-
* @param update
|
1765
|
-
* The nsIUpdate object to add.
|
1766
|
-
*/
|
1767
|
-
_addUpdate: function(update) {
|
1768
|
-
if (!update)
|
1769
|
-
return;
|
1770
|
-
this._ensureUpdates();
|
1771
|
-
if (this._updates) {
|
1772
|
-
for (var i = 0; i < this._updates.length; ++i) {
|
1773
|
-
if (this._updates[i] &&
|
1774
|
-
this._updates[i].version == update.version &&
|
1775
|
-
this._updates[i].buildID == update.buildID) {
|
1776
|
-
// Replace the existing entry with the new value, updating
|
1777
|
-
// all metadata.
|
1778
|
-
this._updates[i] = update;
|
1779
|
-
return;
|
1780
|
-
}
|
1781
|
-
}
|
1782
|
-
}
|
1783
|
-
// Otherwise add it to the front of the list.
|
1784
|
-
if (update)
|
1785
|
-
this._updates = [update].concat(this._updates);
|
1786
|
-
},
|
1787
|
-
|
1788
|
-
/**
|
1789
|
-
* Serializes an array of updates to an XML file
|
1790
|
-
* @param updates
|
1791
|
-
* An array of nsIUpdate objects
|
1792
|
-
* @param file
|
1793
|
-
* The nsIFile object to serialize to
|
1794
|
-
*/
|
1795
|
-
_writeUpdatesToXMLFile: function(updates, file) {
|
1796
|
-
var fos = Components.classes["@mozilla.org/network/safe-file-output-stream;1"]
|
1797
|
-
.createInstance(Components.interfaces.nsIFileOutputStream);
|
1798
|
-
var modeFlags = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE;
|
1799
|
-
if (!file.exists())
|
1800
|
-
file.create(nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
|
1801
|
-
fos.init(file, modeFlags, PERMS_FILE, 0);
|
1802
|
-
|
1803
|
-
try {
|
1804
|
-
var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"]
|
1805
|
-
.createInstance(Components.interfaces.nsIDOMParser);
|
1806
|
-
const EMPTY_UPDATES_DOCUMENT = "<?xml version=\"1.0\"?><updates xmlns=\"http://www.mozilla.org/2005/app-update\"></updates>";
|
1807
|
-
var doc = parser.parseFromString(EMPTY_UPDATES_DOCUMENT, "text/xml");
|
1808
|
-
|
1809
|
-
for (var i = 0; i < updates.length; ++i) {
|
1810
|
-
if (updates[i])
|
1811
|
-
doc.documentElement.appendChild(updates[i].serialize(doc));
|
1812
|
-
}
|
1813
|
-
|
1814
|
-
var serializer = Components.classes["@mozilla.org/xmlextras/xmlserializer;1"]
|
1815
|
-
.createInstance(Components.interfaces.nsIDOMSerializer);
|
1816
|
-
serializer.serializeToStream(doc.documentElement, fos, null);
|
1817
|
-
}
|
1818
|
-
catch (e) {
|
1819
|
-
}
|
1820
|
-
|
1821
|
-
closeSafeOutputStream(fos);
|
1822
|
-
},
|
1823
|
-
|
1824
|
-
/**
|
1825
|
-
* See nsIUpdateService.idl
|
1826
|
-
*/
|
1827
|
-
saveUpdates: function() {
|
1828
|
-
this._writeUpdatesToXMLFile([this._activeUpdate],
|
1829
|
-
getUpdateFile([FILE_UPDATE_ACTIVE]));
|
1830
|
-
if (this._updates) {
|
1831
|
-
this._writeUpdatesToXMLFile(this._updates,
|
1832
|
-
getUpdateFile([FILE_UPDATES_DB]));
|
1833
|
-
}
|
1834
|
-
},
|
1835
|
-
|
1836
|
-
/**
|
1837
|
-
* See nsISupports.idl
|
1838
|
-
*/
|
1839
|
-
QueryInterface: function(iid) {
|
1840
|
-
if (!iid.equals(Components.interfaces.nsIUpdateManager) &&
|
1841
|
-
!iid.equals(Components.interfaces.nsISupports))
|
1842
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
1843
|
-
return this;
|
1844
|
-
}
|
1845
|
-
};
|
1846
|
-
|
1847
|
-
|
1848
|
-
/**
|
1849
|
-
* Checker
|
1850
|
-
* Checks for new Updates
|
1851
|
-
* @constructor
|
1852
|
-
*/
|
1853
|
-
function Checker() {
|
1854
|
-
}
|
1855
|
-
Checker.prototype = {
|
1856
|
-
/**
|
1857
|
-
* The XMLHttpRequest object that performs the connection.
|
1858
|
-
*/
|
1859
|
-
_request : null,
|
1860
|
-
|
1861
|
-
/**
|
1862
|
-
* The nsIUpdateCheckListener callback
|
1863
|
-
*/
|
1864
|
-
_callback : null,
|
1865
|
-
|
1866
|
-
/**
|
1867
|
-
* The URL of the update service XML file to connect to that contains details
|
1868
|
-
* about available updates.
|
1869
|
-
*/
|
1870
|
-
get updateURL() {
|
1871
|
-
var defaults =
|
1872
|
-
gPref.QueryInterface(Components.interfaces.nsIPrefService).
|
1873
|
-
getDefaultBranch(null);
|
1874
|
-
|
1875
|
-
// Use the override URL if specified.
|
1876
|
-
var url = getPref("getCharPref", PREF_APP_UPDATE_URL_OVERRIDE, null);
|
1877
|
-
|
1878
|
-
// Otherwise, construct the update URL from component parts.
|
1879
|
-
if (!url) {
|
1880
|
-
try {
|
1881
|
-
url = defaults.getCharPref(PREF_APP_UPDATE_URL);
|
1882
|
-
} catch (e) {
|
1883
|
-
}
|
1884
|
-
}
|
1885
|
-
|
1886
|
-
if (!url || url == "") {
|
1887
|
-
LOG("Checker", "Update URL not defined");
|
1888
|
-
return null;
|
1889
|
-
}
|
1890
|
-
|
1891
|
-
url = url.replace(/%PRODUCT%/g, gApp.name);
|
1892
|
-
url = url.replace(/%VERSION%/g, gApp.version);
|
1893
|
-
url = url.replace(/%BUILD_ID%/g, gApp.appBuildID);
|
1894
|
-
url = url.replace(/%BUILD_TARGET%/g, gApp.OS + "_" + gABI);
|
1895
|
-
url = url.replace(/%OS_VERSION%/g, gOSVersion);
|
1896
|
-
url = url.replace(/%LOCALE%/g, getLocale());
|
1897
|
-
url = url.replace(/%CHANNEL%/g, getUpdateChannel());
|
1898
|
-
url = url.replace(/\+/g, "%2B");
|
1899
|
-
|
1900
|
-
LOG("Checker", "update url: " + url);
|
1901
|
-
return url;
|
1902
|
-
},
|
1903
|
-
|
1904
|
-
/**
|
1905
|
-
* See nsIUpdateService.idl
|
1906
|
-
*/
|
1907
|
-
checkForUpdates: function(listener, force) {
|
1908
|
-
if (!listener)
|
1909
|
-
throw Components.results.NS_ERROR_NULL_POINTER;
|
1910
|
-
|
1911
|
-
if (!this.updateURL || (!this.enabled && !force))
|
1912
|
-
return;
|
1913
|
-
|
1914
|
-
this._request =
|
1915
|
-
Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].
|
1916
|
-
createInstance(Components.interfaces.nsIXMLHttpRequest);
|
1917
|
-
this._request.open("GET", this.updateURL, true);
|
1918
|
-
this._request.channel.notificationCallbacks = new BadCertHandler();
|
1919
|
-
this._request.overrideMimeType("text/xml");
|
1920
|
-
this._request.setRequestHeader("Cache-Control", "no-cache");
|
1921
|
-
|
1922
|
-
var self = this;
|
1923
|
-
this._request.onerror = function(event) { self.onError(event); };
|
1924
|
-
this._request.onload = function(event) { self.onLoad(event); };
|
1925
|
-
this._request.onprogress = function(event) { self.onProgress(event); };
|
1926
|
-
|
1927
|
-
LOG("Checker", "checkForUpdates: sending request to " + this.updateURL);
|
1928
|
-
this._request.send(null);
|
1929
|
-
|
1930
|
-
this._callback = listener;
|
1931
|
-
},
|
1932
|
-
|
1933
|
-
/**
|
1934
|
-
* When progress associated with the XMLHttpRequest is received.
|
1935
|
-
* @param event
|
1936
|
-
* The nsIDOMLSProgressEvent for the load.
|
1937
|
-
*/
|
1938
|
-
onProgress: function(event) {
|
1939
|
-
LOG("Checker", "onProgress: " + event.position + "/" + event.totalSize);
|
1940
|
-
this._callback.onProgress(event.target, event.position, event.totalSize);
|
1941
|
-
},
|
1942
|
-
|
1943
|
-
/**
|
1944
|
-
* Returns an array of nsIUpdate objects discovered by the update check.
|
1945
|
-
*/
|
1946
|
-
get _updates() {
|
1947
|
-
var updatesElement = this._request.responseXML.documentElement;
|
1948
|
-
if (!updatesElement) {
|
1949
|
-
LOG("Checker", "get_updates: empty updates document?!");
|
1950
|
-
return [];
|
1951
|
-
}
|
1952
|
-
|
1953
|
-
if (updatesElement.nodeName != "updates") {
|
1954
|
-
LOG("Checker", "get_updates: unexpected node name!");
|
1955
|
-
throw "";
|
1956
|
-
}
|
1957
|
-
|
1958
|
-
var updates = [];
|
1959
|
-
for (var i = 0; i < updatesElement.childNodes.length; ++i) {
|
1960
|
-
var updateElement = updatesElement.childNodes.item(i);
|
1961
|
-
if (updateElement.nodeType != Node.ELEMENT_NODE ||
|
1962
|
-
updateElement.localName != "update")
|
1963
|
-
continue;
|
1964
|
-
|
1965
|
-
updateElement.QueryInterface(Components.interfaces.nsIDOMElement);
|
1966
|
-
try {
|
1967
|
-
var update = new Update(updateElement);
|
1968
|
-
} catch (e) {
|
1969
|
-
LOG("Checker", "Invalid <update/>, ignoring...");
|
1970
|
-
continue;
|
1971
|
-
}
|
1972
|
-
update.serviceURL = this.updateURL;
|
1973
|
-
update.channel = getUpdateChannel();
|
1974
|
-
updates.push(update);
|
1975
|
-
}
|
1976
|
-
|
1977
|
-
return updates;
|
1978
|
-
},
|
1979
|
-
|
1980
|
-
/**
|
1981
|
-
* The XMLHttpRequest succeeded and the document was loaded.
|
1982
|
-
* @param event
|
1983
|
-
* The nsIDOMLSEvent for the load
|
1984
|
-
*/
|
1985
|
-
onLoad: function(event) {
|
1986
|
-
LOG("Checker", "onLoad: request completed downloading document");
|
1987
|
-
|
1988
|
-
try {
|
1989
|
-
checkCert(this._request.channel);
|
1990
|
-
|
1991
|
-
// Analyze the resulting DOM and determine the set of updates to install
|
1992
|
-
var updates = this._updates;
|
1993
|
-
|
1994
|
-
LOG("Checker", "Updates available: " + updates.length);
|
1995
|
-
|
1996
|
-
// ... and tell the Update Service about what we discovered.
|
1997
|
-
this._callback.onCheckComplete(event.target, updates, updates.length);
|
1998
|
-
}
|
1999
|
-
catch (e) {
|
2000
|
-
LOG("Checker", "There was a problem with the update service URL specified, " +
|
2001
|
-
"either the XML file was malformed or it does not exist at the location " +
|
2002
|
-
"specified. Exception: " + e);
|
2003
|
-
var update = new Update(null);
|
2004
|
-
update.statusText = getStatusTextFromCode(404, 404);
|
2005
|
-
this._callback.onError(event.target, update);
|
2006
|
-
}
|
2007
|
-
|
2008
|
-
this._request = null;
|
2009
|
-
},
|
2010
|
-
|
2011
|
-
/**
|
2012
|
-
* There was an error of some kind during the XMLHttpRequest
|
2013
|
-
* @param event
|
2014
|
-
* The nsIDOMLSEvent for the load
|
2015
|
-
*/
|
2016
|
-
onError: function(event) {
|
2017
|
-
LOG("Checker", "onError: error during load");
|
2018
|
-
|
2019
|
-
var request = event.target;
|
2020
|
-
try {
|
2021
|
-
var status = request.status;
|
2022
|
-
}
|
2023
|
-
catch (e) {
|
2024
|
-
var req = request.channel.QueryInterface(Components.interfaces.nsIRequest);
|
2025
|
-
status = req.status;
|
2026
|
-
}
|
2027
|
-
|
2028
|
-
// If we can't find an error string specific to this status code,
|
2029
|
-
// just use the 200 message from above, which means everything
|
2030
|
-
// "looks" fine but there was probably an XML error or a bogus file.
|
2031
|
-
var update = new Update(null);
|
2032
|
-
update.statusText = getStatusTextFromCode(status, 200);
|
2033
|
-
this._callback.onError(request, update);
|
2034
|
-
|
2035
|
-
this._request = null;
|
2036
|
-
},
|
2037
|
-
|
2038
|
-
/**
|
2039
|
-
* Whether or not we are allowed to do update checking.
|
2040
|
-
*/
|
2041
|
-
_enabled: true,
|
2042
|
-
|
2043
|
-
/**
|
2044
|
-
* See nsIUpdateService.idl
|
2045
|
-
*/
|
2046
|
-
get enabled() {
|
2047
|
-
var aus =
|
2048
|
-
Components.classes["@mozilla.org/updates/update-service;1"].
|
2049
|
-
getService(Components.interfaces.nsIApplicationUpdateService);
|
2050
|
-
var enabled = getPref("getBoolPref", PREF_APP_UPDATE_ENABLED, true) &&
|
2051
|
-
aus.canUpdate && this._enabled;
|
2052
|
-
return enabled;
|
2053
|
-
},
|
2054
|
-
|
2055
|
-
/**
|
2056
|
-
* See nsIUpdateService.idl
|
2057
|
-
*/
|
2058
|
-
stopChecking: function(duration) {
|
2059
|
-
// Always stop the current check
|
2060
|
-
if (this._request)
|
2061
|
-
this._request.abort();
|
2062
|
-
|
2063
|
-
const nsIUpdateChecker = Components.interfaces.nsIUpdateChecker;
|
2064
|
-
switch (duration) {
|
2065
|
-
case nsIUpdateChecker.CURRENT_SESSION:
|
2066
|
-
this._enabled = false;
|
2067
|
-
break;
|
2068
|
-
case nsIUpdateChecker.ANY_CHECKS:
|
2069
|
-
this._enabled = false;
|
2070
|
-
gPref.setBoolPref(PREF_APP_UPDATE_ENABLED, this._enabled);
|
2071
|
-
break;
|
2072
|
-
}
|
2073
|
-
},
|
2074
|
-
|
2075
|
-
/**
|
2076
|
-
* See nsISupports.idl
|
2077
|
-
*/
|
2078
|
-
QueryInterface: function(iid) {
|
2079
|
-
if (!iid.equals(Components.interfaces.nsIUpdateChecker) &&
|
2080
|
-
!iid.equals(Components.interfaces.nsISupports))
|
2081
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
2082
|
-
return this;
|
2083
|
-
}
|
2084
|
-
};
|
2085
|
-
|
2086
|
-
/**
|
2087
|
-
* Manages the download of updates
|
2088
|
-
* @param background
|
2089
|
-
* Whether or not this downloader is operating in background
|
2090
|
-
* update mode.
|
2091
|
-
* @constructor
|
2092
|
-
*/
|
2093
|
-
function Downloader(background) {
|
2094
|
-
this.background = background;
|
2095
|
-
}
|
2096
|
-
Downloader.prototype = {
|
2097
|
-
/**
|
2098
|
-
* The nsIUpdatePatch that we are downloading
|
2099
|
-
*/
|
2100
|
-
_patch: null,
|
2101
|
-
|
2102
|
-
/**
|
2103
|
-
* The nsIUpdate that we are downloading
|
2104
|
-
*/
|
2105
|
-
_update: null,
|
2106
|
-
|
2107
|
-
/**
|
2108
|
-
* The nsIIncrementalDownload object handling the download
|
2109
|
-
*/
|
2110
|
-
_request: null,
|
2111
|
-
|
2112
|
-
/**
|
2113
|
-
* Whether or not the update being downloaded is a complete replacement of
|
2114
|
-
* the user's existing installation or a patch representing the difference
|
2115
|
-
* between the new version and the previous version.
|
2116
|
-
*/
|
2117
|
-
isCompleteUpdate: null,
|
2118
|
-
|
2119
|
-
/**
|
2120
|
-
* Cancels the active download.
|
2121
|
-
*/
|
2122
|
-
cancel: function() {
|
2123
|
-
if (this._request &&
|
2124
|
-
this._request instanceof Components.interfaces.nsIRequest) {
|
2125
|
-
const NS_BINDING_ABORTED = 0x804b0002;
|
2126
|
-
this._request.cancel(NS_BINDING_ABORTED);
|
2127
|
-
}
|
2128
|
-
},
|
2129
|
-
|
2130
|
-
/**
|
2131
|
-
* Whether or not a patch has been downloaded and staged for installation.
|
2132
|
-
*/
|
2133
|
-
get patchIsStaged() {
|
2134
|
-
return readStatusFile(getUpdatesDir()) == STATE_PENDING;
|
2135
|
-
},
|
2136
|
-
|
2137
|
-
/**
|
2138
|
-
* Verify the downloaded file. We assume that the download is complete at
|
2139
|
-
* this point.
|
2140
|
-
*/
|
2141
|
-
_verifyDownload: function() {
|
2142
|
-
if (!this._request)
|
2143
|
-
return false;
|
2144
|
-
|
2145
|
-
var destination = this._request.destination;
|
2146
|
-
|
2147
|
-
// Ensure that the file size matches the expected file size.
|
2148
|
-
if (destination.fileSize != this._patch.size)
|
2149
|
-
return false;
|
2150
|
-
|
2151
|
-
var fileStream = Components.classes["@mozilla.org/network/file-input-stream;1"].
|
2152
|
-
createInstance(nsIFileInputStream);
|
2153
|
-
fileStream.init(destination, MODE_RDONLY, PERMS_FILE, 0);
|
2154
|
-
|
2155
|
-
try {
|
2156
|
-
var hash = Components.classes["@mozilla.org/security/hash;1"].
|
2157
|
-
createInstance(nsICryptoHash);
|
2158
|
-
var hashFunction = nsICryptoHash[this._patch.hashFunction.toUpperCase()];
|
2159
|
-
if (hashFunction == undefined)
|
2160
|
-
throw Components.results.NS_ERROR_UNEXPECTED;
|
2161
|
-
hash.init(hashFunction);
|
2162
|
-
hash.updateFromStream(fileStream, -1);
|
2163
|
-
// NOTE: For now, we assume that the format of _patch.hashValue is hex
|
2164
|
-
// encoded binary (such as what is typically output by programs like
|
2165
|
-
// sha1sum). In the future, this may change to base64 depending on how
|
2166
|
-
// we choose to compute these hashes.
|
2167
|
-
digest = binaryToHex(hash.finish(false));
|
2168
|
-
} catch (e) {
|
2169
|
-
LOG("Downloader", "failed to compute hash of downloaded update archive");
|
2170
|
-
digest = "";
|
2171
|
-
}
|
2172
|
-
|
2173
|
-
fileStream.close();
|
2174
|
-
|
2175
|
-
return digest == this._patch.hashValue.toLowerCase();
|
2176
|
-
},
|
2177
|
-
|
2178
|
-
/**
|
2179
|
-
* Select the patch to use given the current state of updateDir and the given
|
2180
|
-
* set of update patches.
|
2181
|
-
* @param update
|
2182
|
-
* A nsIUpdate object to select a patch from
|
2183
|
-
* @param updateDir
|
2184
|
-
* A nsIFile representing the update directory
|
2185
|
-
* @returns A nsIUpdatePatch object to download
|
2186
|
-
*/
|
2187
|
-
_selectPatch: function(update, updateDir) {
|
2188
|
-
// Given an update to download, we will always try to download the patch
|
2189
|
-
// for a partial update over the patch for a full update.
|
2190
|
-
|
2191
|
-
/**
|
2192
|
-
* Return the first UpdatePatch with the given type.
|
2193
|
-
* @param type
|
2194
|
-
* The type of the patch ("complete" or "partial")
|
2195
|
-
* @returns A nsIUpdatePatch object matching the type specified
|
2196
|
-
*/
|
2197
|
-
function getPatchOfType(type) {
|
2198
|
-
for (var i = 0; i < update.patchCount; ++i) {
|
2199
|
-
var patch = update.getPatchAt(i);
|
2200
|
-
if (patch && patch.type == type)
|
2201
|
-
return patch;
|
2202
|
-
}
|
2203
|
-
return null;
|
2204
|
-
}
|
2205
|
-
|
2206
|
-
// Look to see if any of the patches in the Update object has been
|
2207
|
-
// pre-selected for download, otherwise we must figure out which one
|
2208
|
-
// to select ourselves.
|
2209
|
-
var selectedPatch = update.selectedPatch;
|
2210
|
-
|
2211
|
-
var state = readStatusFile(updateDir)
|
2212
|
-
|
2213
|
-
// If this is a patch that we know about, then select it. If it is a patch
|
2214
|
-
// that we do not know about, then remove it and use our default logic.
|
2215
|
-
var useComplete = false;
|
2216
|
-
if (selectedPatch) {
|
2217
|
-
LOG("Downloader", "found existing patch [state="+state+"]");
|
2218
|
-
switch (state) {
|
2219
|
-
case STATE_DOWNLOADING:
|
2220
|
-
LOG("Downloader", "resuming download");
|
2221
|
-
return selectedPatch;
|
2222
|
-
case STATE_PENDING:
|
2223
|
-
LOG("Downloader", "already downloaded and staged");
|
2224
|
-
return null;
|
2225
|
-
default:
|
2226
|
-
// Something went wrong when we tried to apply the previous patch.
|
2227
|
-
// Try the complete patch next time.
|
2228
|
-
if (update && selectedPatch.type == "partial") {
|
2229
|
-
useComplete = true;
|
2230
|
-
} else {
|
2231
|
-
// This is a pretty fatal error. Just bail.
|
2232
|
-
LOG("Downloader", "failed to apply complete patch!");
|
2233
|
-
writeStatusFile(updateDir, STATE_NONE);
|
2234
|
-
return null;
|
2235
|
-
}
|
2236
|
-
}
|
2237
|
-
|
2238
|
-
selectedPatch = null;
|
2239
|
-
}
|
2240
|
-
|
2241
|
-
// If we were not able to discover an update from a previous download, we
|
2242
|
-
// select the best patch from the given set.
|
2243
|
-
var partialPatch = getPatchOfType("partial");
|
2244
|
-
if (!useComplete)
|
2245
|
-
selectedPatch = partialPatch;
|
2246
|
-
if (!selectedPatch) {
|
2247
|
-
if (partialPatch)
|
2248
|
-
partialPatch.selected = false;
|
2249
|
-
selectedPatch = getPatchOfType("complete");
|
2250
|
-
}
|
2251
|
-
|
2252
|
-
// Restore the updateDir since we may have deleted it.
|
2253
|
-
updateDir = getUpdatesDir();
|
2254
|
-
|
2255
|
-
// if update only contains a partial patch, selectedPatch == null here if
|
2256
|
-
// the partial patch has been attempted and fails and we're trying to get a
|
2257
|
-
// complete patch
|
2258
|
-
if (selectedPatch)
|
2259
|
-
selectedPatch.selected = true;
|
2260
|
-
|
2261
|
-
update.isCompleteUpdate = useComplete;
|
2262
|
-
|
2263
|
-
// Reset the Active Update object on the Update Manager and flush the
|
2264
|
-
// Active Update DB.
|
2265
|
-
var um = Components.classes["@mozilla.org/updates/update-manager;1"]
|
2266
|
-
.getService(Components.interfaces.nsIUpdateManager);
|
2267
|
-
um.activeUpdate = update;
|
2268
|
-
|
2269
|
-
return selectedPatch;
|
2270
|
-
},
|
2271
|
-
|
2272
|
-
/**
|
2273
|
-
* Whether or not we are currently downloading something.
|
2274
|
-
*/
|
2275
|
-
get isBusy() {
|
2276
|
-
return this._request != null;
|
2277
|
-
},
|
2278
|
-
|
2279
|
-
/**
|
2280
|
-
* Download and stage the given update.
|
2281
|
-
* @param update
|
2282
|
-
* A nsIUpdate object to download a patch for. Cannot be null.
|
2283
|
-
*/
|
2284
|
-
downloadUpdate: function(update) {
|
2285
|
-
if (!update)
|
2286
|
-
throw Components.results.NS_ERROR_NULL_POINTER;
|
2287
|
-
|
2288
|
-
var updateDir = getUpdatesDir();
|
2289
|
-
|
2290
|
-
this._update = update;
|
2291
|
-
|
2292
|
-
// This function may return null, which indicates that there are no patches
|
2293
|
-
// to download.
|
2294
|
-
this._patch = this._selectPatch(update, updateDir);
|
2295
|
-
if (!this._patch) {
|
2296
|
-
LOG("Downloader", "no patch to download");
|
2297
|
-
return readStatusFile(updateDir);
|
2298
|
-
}
|
2299
|
-
this.isCompleteUpdate = this._patch.type == "complete";
|
2300
|
-
|
2301
|
-
var patchFile = updateDir.clone();
|
2302
|
-
patchFile.append(FILE_UPDATE_ARCHIVE);
|
2303
|
-
|
2304
|
-
var ios = Components.classes["@mozilla.org/network/io-service;1"].
|
2305
|
-
getService(Components.interfaces.nsIIOService);
|
2306
|
-
var uri = ios.newURI(this._patch.URL, null, null);
|
2307
|
-
|
2308
|
-
this._request =
|
2309
|
-
Components.classes["@mozilla.org/network/incremental-download;1"].
|
2310
|
-
createInstance(nsIIncrementalDownload);
|
2311
|
-
|
2312
|
-
LOG("Downloader", "downloadUpdate: Downloading from " + uri.spec + " to " +
|
2313
|
-
patchFile.path);
|
2314
|
-
|
2315
|
-
var interval = this.background ? DOWNLOAD_BACKGROUND_INTERVAL
|
2316
|
-
: DOWNLOAD_FOREGROUND_INTERVAL;
|
2317
|
-
this._request.init(uri, patchFile, DOWNLOAD_CHUNK_SIZE, interval);
|
2318
|
-
this._request.start(this, null);
|
2319
|
-
|
2320
|
-
writeStatusFile(updateDir, STATE_DOWNLOADING);
|
2321
|
-
this._patch.QueryInterface(Components.interfaces.nsIWritablePropertyBag);
|
2322
|
-
this._patch.state = STATE_DOWNLOADING;
|
2323
|
-
var um = Components.classes["@mozilla.org/updates/update-manager;1"]
|
2324
|
-
.getService(Components.interfaces.nsIUpdateManager);
|
2325
|
-
um.saveUpdates();
|
2326
|
-
return STATE_DOWNLOADING;
|
2327
|
-
},
|
2328
|
-
|
2329
|
-
/**
|
2330
|
-
* An array of download listeners to notify when we receive
|
2331
|
-
* nsIRequestObserver or nsIProgressEventSink method calls.
|
2332
|
-
*/
|
2333
|
-
_listeners: [],
|
2334
|
-
|
2335
|
-
/**
|
2336
|
-
* Adds a listener to the download process
|
2337
|
-
* @param listener
|
2338
|
-
* A download listener, implementing nsIRequestObserver and
|
2339
|
-
* nsIProgressEventSink
|
2340
|
-
*/
|
2341
|
-
addDownloadListener: function(listener) {
|
2342
|
-
for (var i = 0; i < this._listeners.length; ++i) {
|
2343
|
-
if (this._listeners[i] == listener)
|
2344
|
-
return;
|
2345
|
-
}
|
2346
|
-
this._listeners.push(listener);
|
2347
|
-
},
|
2348
|
-
|
2349
|
-
/**
|
2350
|
-
* Removes a download listener
|
2351
|
-
* @param listener
|
2352
|
-
* The listener to remove.
|
2353
|
-
*/
|
2354
|
-
removeDownloadListener: function(listener) {
|
2355
|
-
for (var i = 0; i < this._listeners.length; ++i) {
|
2356
|
-
if (this._listeners[i] == listener) {
|
2357
|
-
this._listeners.splice(i, 1);
|
2358
|
-
return;
|
2359
|
-
}
|
2360
|
-
}
|
2361
|
-
},
|
2362
|
-
|
2363
|
-
/**
|
2364
|
-
* When the async request begins
|
2365
|
-
* @param request
|
2366
|
-
* The nsIRequest object for the transfer
|
2367
|
-
* @param context
|
2368
|
-
* Additional data
|
2369
|
-
*/
|
2370
|
-
onStartRequest: function(request, context) {
|
2371
|
-
request.QueryInterface(nsIIncrementalDownload);
|
2372
|
-
LOG("Downloader", "onStartRequest: " + request.URI.spec);
|
2373
|
-
|
2374
|
-
var listenerCount = this._listeners.length;
|
2375
|
-
for (var i = 0; i < listenerCount; ++i)
|
2376
|
-
this._listeners[i].onStartRequest(request, context);
|
2377
|
-
},
|
2378
|
-
|
2379
|
-
/**
|
2380
|
-
* When new data has been downloaded
|
2381
|
-
* @param request
|
2382
|
-
* The nsIRequest object for the transfer
|
2383
|
-
* @param context
|
2384
|
-
* Additional data
|
2385
|
-
* @param progress
|
2386
|
-
* The current number of bytes transferred
|
2387
|
-
* @param maxProgress
|
2388
|
-
* The total number of bytes that must be transferred
|
2389
|
-
*/
|
2390
|
-
onProgress: function(request, context, progress, maxProgress) {
|
2391
|
-
request.QueryInterface(nsIIncrementalDownload);
|
2392
|
-
LOG("Downloader.onProgress", "onProgress: " + request.URI.spec + ", " + progress + "/" + maxProgress);
|
2393
|
-
|
2394
|
-
var listenerCount = this._listeners.length;
|
2395
|
-
for (var i = 0; i < listenerCount; ++i) {
|
2396
|
-
var listener = this._listeners[i];
|
2397
|
-
if (listener instanceof Components.interfaces.nsIProgressEventSink)
|
2398
|
-
listener.onProgress(request, context, progress, maxProgress);
|
2399
|
-
}
|
2400
|
-
},
|
2401
|
-
|
2402
|
-
/**
|
2403
|
-
* When we have new status text
|
2404
|
-
* @param request
|
2405
|
-
* The nsIRequest object for the transfer
|
2406
|
-
* @param context
|
2407
|
-
* Additional data
|
2408
|
-
* @param status
|
2409
|
-
* A status code
|
2410
|
-
* @param statusText
|
2411
|
-
* Human readable version of |status|
|
2412
|
-
*/
|
2413
|
-
onStatus: function(request, context, status, statusText) {
|
2414
|
-
request.QueryInterface(nsIIncrementalDownload);
|
2415
|
-
LOG("Downloader", "onStatus: " + request.URI.spec + " status = " + status + ", text = " + statusText);
|
2416
|
-
var listenerCount = this._listeners.length;
|
2417
|
-
for (var i = 0; i < listenerCount; ++i) {
|
2418
|
-
var listener = this._listeners[i];
|
2419
|
-
if (listener instanceof Components.interfaces.nsIProgressEventSink)
|
2420
|
-
listener.onStatus(request, context, status, statusText);
|
2421
|
-
}
|
2422
|
-
},
|
2423
|
-
|
2424
|
-
/**
|
2425
|
-
* When data transfer ceases
|
2426
|
-
* @param request
|
2427
|
-
* The nsIRequest object for the transfer
|
2428
|
-
* @param context
|
2429
|
-
* Additional data
|
2430
|
-
* @param status
|
2431
|
-
* Status code containing the reason for the cessation.
|
2432
|
-
*/
|
2433
|
-
onStopRequest: function(request, context, status) {
|
2434
|
-
request.QueryInterface(nsIIncrementalDownload);
|
2435
|
-
LOG("Downloader", "onStopRequest: " + request.URI.spec + ", status = " + status);
|
2436
|
-
|
2437
|
-
var state = this._patch.state;
|
2438
|
-
var shouldShowPrompt = false;
|
2439
|
-
var deleteActiveUpdate = false;
|
2440
|
-
const NS_BINDING_ABORTED = 0x804b0002;
|
2441
|
-
const NS_ERROR_ABORT = 0x80004004;
|
2442
|
-
if (Components.isSuccessCode(status)) {
|
2443
|
-
var sbs =
|
2444
|
-
Components.classes["@mozilla.org/intl/stringbundle;1"].
|
2445
|
-
getService(Components.interfaces.nsIStringBundleService);
|
2446
|
-
var updateStrings = sbs.createBundle(URI_UPDATES_PROPERTIES);
|
2447
|
-
if (this._verifyDownload()) {
|
2448
|
-
state = STATE_PENDING;
|
2449
|
-
|
2450
|
-
// We only need to explicitly show the prompt if this is a backround
|
2451
|
-
// download, since otherwise some kind of UI is already visible and
|
2452
|
-
// that UI will notify.
|
2453
|
-
if (this.background)
|
2454
|
-
shouldShowPrompt = true;
|
2455
|
-
|
2456
|
-
// Tell the updater.exe we're ready to apply.
|
2457
|
-
writeStatusFile(getUpdatesDir(), state);
|
2458
|
-
this._update.installDate = (new Date()).getTime();
|
2459
|
-
this._update.statusText = updateStrings.
|
2460
|
-
GetStringFromName("installPending");
|
2461
|
-
} else {
|
2462
|
-
LOG("Downloader", "onStopRequest: download verification failed");
|
2463
|
-
state = STATE_DOWNLOAD_FAILED;
|
2464
|
-
|
2465
|
-
var brandStrings = sbs.createBundle(URI_BRAND_PROPERTIES);
|
2466
|
-
var brandShortName = brandStrings.GetStringFromName("brandShortName");
|
2467
|
-
this._update.statusText = updateStrings.
|
2468
|
-
formatStringFromName("verificationError", [brandShortName], 1);
|
2469
|
-
|
2470
|
-
// TODO: use more informative error code here
|
2471
|
-
status = Components.results.NS_ERROR_UNEXPECTED;
|
2472
|
-
|
2473
|
-
var message = getStatusTextFromCode("verification_failed",
|
2474
|
-
"verification_failed");
|
2475
|
-
this._update.statusText = message;
|
2476
|
-
|
2477
|
-
if (this._update.isCompleteUpdate)
|
2478
|
-
deleteActiveUpdate = true;
|
2479
|
-
|
2480
|
-
// Destroy the updates directory, since we're done with it.
|
2481
|
-
cleanUpUpdatesDir();
|
2482
|
-
}
|
2483
|
-
}
|
2484
|
-
else if (status != NS_BINDING_ABORTED &&
|
2485
|
-
status != NS_ERROR_ABORT) {
|
2486
|
-
LOG("Downloader", "onStopRequest: Non-verification failure");
|
2487
|
-
// Some sort of other failure, log this in the |statusText| property
|
2488
|
-
state = STATE_DOWNLOAD_FAILED;
|
2489
|
-
|
2490
|
-
// XXXben - if |request| (The Incremental Download) provided a means
|
2491
|
-
// for accessing the http channel we could do more here.
|
2492
|
-
|
2493
|
-
const NS_BINDING_FAILED = 2152398849;
|
2494
|
-
this._update.statusText = getStatusTextFromCode(status,
|
2495
|
-
NS_BINDING_FAILED);
|
2496
|
-
|
2497
|
-
// Destroy the updates directory, since we're done with it.
|
2498
|
-
cleanUpUpdatesDir();
|
2499
|
-
|
2500
|
-
deleteActiveUpdate = true;
|
2501
|
-
}
|
2502
|
-
LOG("Downloader", "Setting state to: " + state);
|
2503
|
-
this._patch.state = state;
|
2504
|
-
var um =
|
2505
|
-
Components.classes["@mozilla.org/updates/update-manager;1"].
|
2506
|
-
getService(Components.interfaces.nsIUpdateManager);
|
2507
|
-
if (deleteActiveUpdate) {
|
2508
|
-
this._update.installDate = (new Date()).getTime();
|
2509
|
-
um.activeUpdate = null;
|
2510
|
-
}
|
2511
|
-
um.saveUpdates();
|
2512
|
-
|
2513
|
-
var listenerCount = this._listeners.length;
|
2514
|
-
for (var i = 0; i < listenerCount; ++i)
|
2515
|
-
this._listeners[i].onStopRequest(request, context, status);
|
2516
|
-
|
2517
|
-
this._request = null;
|
2518
|
-
|
2519
|
-
if (state == STATE_DOWNLOAD_FAILED) {
|
2520
|
-
if (!this._update.isCompleteUpdate) {
|
2521
|
-
var allFailed = true;
|
2522
|
-
|
2523
|
-
// If we were downloading a patch and the patch verification phase
|
2524
|
-
// failed, log this and then commence downloading the complete update.
|
2525
|
-
LOG("Downloader", "onStopRequest: Verification of patch failed, downloading complete update");
|
2526
|
-
this._update.isCompleteUpdate = true;
|
2527
|
-
var status = this.downloadUpdate(this._update);
|
2528
|
-
|
2529
|
-
if (status == STATE_NONE) {
|
2530
|
-
cleanupActiveUpdate();
|
2531
|
-
} else {
|
2532
|
-
allFailed = false;
|
2533
|
-
}
|
2534
|
-
// This will reset the |.state| property on this._update if a new
|
2535
|
-
// download initiates.
|
2536
|
-
}
|
2537
|
-
|
2538
|
-
// if we still fail after trying a complete download, give up completely
|
2539
|
-
if (allFailed) {
|
2540
|
-
// In all other failure cases, i.e. we're S.O.L. - no more failing over
|
2541
|
-
// ...
|
2542
|
-
|
2543
|
-
// If this was ever a foreground download, and now there is no UI active
|
2544
|
-
// (e.g. because the user closed the download window) and there was an
|
2545
|
-
// error, we must notify now. Otherwise we can keep the failure to
|
2546
|
-
// ourselves since the user won't be expecting it.
|
2547
|
-
try {
|
2548
|
-
this._update.QueryInterface(Components.interfaces.nsIWritablePropertyBag);
|
2549
|
-
var fgdl = this._update.getProperty("foregroundDownload");
|
2550
|
-
}
|
2551
|
-
catch (e) {
|
2552
|
-
}
|
2553
|
-
|
2554
|
-
if (fgdl == "true") {
|
2555
|
-
var prompter =
|
2556
|
-
Components.classes["@mozilla.org/updates/update-prompt;1"].
|
2557
|
-
createInstance(Components.interfaces.nsIUpdatePrompt);
|
2558
|
-
this._update.QueryInterface(Components.interfaces.nsIWritablePropertyBag);
|
2559
|
-
this._update.setProperty("downloadFailed", "true");
|
2560
|
-
prompter.showUpdateError(this._update);
|
2561
|
-
}
|
2562
|
-
}
|
2563
|
-
|
2564
|
-
// the complete download succeeded or total failure was handled, so exit
|
2565
|
-
return;
|
2566
|
-
}
|
2567
|
-
|
2568
|
-
// Do this after *everything* else, since it will likely cause the app
|
2569
|
-
// to shut down.
|
2570
|
-
if (shouldShowPrompt) {
|
2571
|
-
// Notify the user that an update has been downloaded and is ready for
|
2572
|
-
// installation (i.e. that they should restart the application). We do
|
2573
|
-
// not notify on failed update attempts.
|
2574
|
-
var prompter =
|
2575
|
-
Components.classes["@mozilla.org/updates/update-prompt;1"].
|
2576
|
-
createInstance(Components.interfaces.nsIUpdatePrompt);
|
2577
|
-
prompter.showUpdateDownloaded(this._update);
|
2578
|
-
}
|
2579
|
-
},
|
2580
|
-
|
2581
|
-
/**
|
2582
|
-
* See nsIInterfaceRequestor.idl
|
2583
|
-
*/
|
2584
|
-
getInterface: function(iid) {
|
2585
|
-
// The network request may require proxy authentication, so provide the
|
2586
|
-
// default nsIAuthPrompt if requested.
|
2587
|
-
if (iid.equals(Components.interfaces.nsIAuthPrompt)) {
|
2588
|
-
var prompt =
|
2589
|
-
Components.classes["@mozilla.org/network/default-auth-prompt;1"].
|
2590
|
-
createInstance();
|
2591
|
-
return prompt.QueryInterface(iid);
|
2592
|
-
}
|
2593
|
-
Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
|
2594
|
-
return null;
|
2595
|
-
},
|
2596
|
-
|
2597
|
-
/**
|
2598
|
-
* See nsISupports.idl
|
2599
|
-
*/
|
2600
|
-
QueryInterface: function(iid) {
|
2601
|
-
if (!iid.equals(Components.interfaces.nsIRequestObserver) &&
|
2602
|
-
!iid.equals(Components.interfaces.nsIProgressEventSink) &&
|
2603
|
-
!iid.equals(Components.interfaces.nsIInterfaceRequestor) &&
|
2604
|
-
!iid.equals(Components.interfaces.nsISupports))
|
2605
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
2606
|
-
return this;
|
2607
|
-
}
|
2608
|
-
};
|
2609
|
-
|
2610
|
-
/**
|
2611
|
-
* A manager for update check timers. Manages timers that fire over long
|
2612
|
-
* periods of time (e.g. days, weeks).
|
2613
|
-
* @constructor
|
2614
|
-
*/
|
2615
|
-
function TimerManager() {
|
2616
|
-
getObserverService().addObserver(this, "xpcom-shutdown", false);
|
2617
|
-
|
2618
|
-
const nsITimer = Components.interfaces.nsITimer;
|
2619
|
-
this._timer = Components.classes["@mozilla.org/timer;1"]
|
2620
|
-
.createInstance(nsITimer);
|
2621
|
-
var timerInterval = getPref("getIntPref", PREF_APP_UPDATE_TIMER, 600000);
|
2622
|
-
this._timer.initWithCallback(this, timerInterval,
|
2623
|
-
nsITimer.TYPE_REPEATING_SLACK);
|
2624
|
-
}
|
2625
|
-
TimerManager.prototype = {
|
2626
|
-
/**
|
2627
|
-
* See nsIObserver.idl
|
2628
|
-
*/
|
2629
|
-
observe: function(subject, topic, data) {
|
2630
|
-
if (topic == "xpcom-shutdown") {
|
2631
|
-
getObserverService().removeObserver(this, "xpcom-shutdown");
|
2632
|
-
|
2633
|
-
// Release everything we hold onto.
|
2634
|
-
for (var timerID in this._timers)
|
2635
|
-
delete this._timers[timerID];
|
2636
|
-
this._timer = null;
|
2637
|
-
this._timers = null;
|
2638
|
-
}
|
2639
|
-
},
|
2640
|
-
|
2641
|
-
/**
|
2642
|
-
* The Checker Timer
|
2643
|
-
*/
|
2644
|
-
_timer: null,
|
2645
|
-
|
2646
|
-
/**
|
2647
|
-
* The set of registered timers.
|
2648
|
-
*/
|
2649
|
-
_timers: { },
|
2650
|
-
|
2651
|
-
/**
|
2652
|
-
* Called when the checking timer fires.
|
2653
|
-
* @param timer
|
2654
|
-
* The checking timer that fired.
|
2655
|
-
*/
|
2656
|
-
notify: function(timer) {
|
2657
|
-
for (var timerID in this._timers) {
|
2658
|
-
var timerData = this._timers[timerID];
|
2659
|
-
var lastUpdateTime = timerData.lastUpdateTime;
|
2660
|
-
var now = Math.round(Date.now() / 1000);
|
2661
|
-
|
2662
|
-
// Fudge the lastUpdateTime by some random increment of the update
|
2663
|
-
// check interval (e.g. some random slice of 10 minutes) so that when
|
2664
|
-
// the time comes to check, we offset each client request by a random
|
2665
|
-
// amount so they don't all hit at once. app.update.timer is in milliseconds,
|
2666
|
-
// whereas app.update.lastUpdateTime is in seconds
|
2667
|
-
var timerInterval = getPref("getIntPref", PREF_APP_UPDATE_TIMER, 600000);
|
2668
|
-
lastUpdateTime += Math.round(Math.random() * timerInterval / 1000);
|
2669
|
-
|
2670
|
-
if ((now - lastUpdateTime) > timerData.interval &&
|
2671
|
-
timerData.callback instanceof Components.interfaces.nsITimerCallback) {
|
2672
|
-
timerData.callback.notify(timer);
|
2673
|
-
timerData.lastUpdateTime = now;
|
2674
|
-
var preference = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, timerID);
|
2675
|
-
gPref.setIntPref(preference, now);
|
2676
|
-
}
|
2677
|
-
}
|
2678
|
-
},
|
2679
|
-
|
2680
|
-
/**
|
2681
|
-
* See nsIUpdateService.idl
|
2682
|
-
*/
|
2683
|
-
registerTimer: function(id, callback, interval) {
|
2684
|
-
var preference = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, id);
|
2685
|
-
var now = Math.round(Date.now() / 1000);
|
2686
|
-
var lastUpdateTime = null;
|
2687
|
-
if (gPref.prefHasUserValue(preference)) {
|
2688
|
-
lastUpdateTime = gPref.getIntPref(preference);
|
2689
|
-
} else {
|
2690
|
-
gPref.setIntPref(preference, now);
|
2691
|
-
lastUpdateTime = now;
|
2692
|
-
}
|
2693
|
-
this._timers[id] = { callback : callback,
|
2694
|
-
interval : interval,
|
2695
|
-
lastUpdateTime : lastUpdateTime };
|
2696
|
-
},
|
2697
|
-
|
2698
|
-
/**
|
2699
|
-
* See nsISupports.idl
|
2700
|
-
*/
|
2701
|
-
QueryInterface: function(iid) {
|
2702
|
-
if (!iid.equals(Components.interfaces.nsIUpdateTimerManager) &&
|
2703
|
-
!iid.equals(Components.interfaces.nsITimerCallback) &&
|
2704
|
-
!iid.equals(Components.interfaces.nsIObserver) &&
|
2705
|
-
!iid.equals(Components.interfaces.nsISupports))
|
2706
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
2707
|
-
return this;
|
2708
|
-
}
|
2709
|
-
};
|
2710
|
-
|
2711
|
-
//@line 2684 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
2712
|
-
/**
|
2713
|
-
* UpdatePrompt
|
2714
|
-
* An object which can prompt the user with information about updates, request
|
2715
|
-
* action, etc. Embedding clients can override this component with one that
|
2716
|
-
* invokes a native front end.
|
2717
|
-
* @constructor
|
2718
|
-
*/
|
2719
|
-
function UpdatePrompt() {
|
2720
|
-
}
|
2721
|
-
UpdatePrompt.prototype = {
|
2722
|
-
/**
|
2723
|
-
* See nsIUpdateService.idl
|
2724
|
-
*/
|
2725
|
-
checkForUpdates: function() {
|
2726
|
-
this._showUI(null, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
|
2727
|
-
null, null);
|
2728
|
-
},
|
2729
|
-
|
2730
|
-
/**
|
2731
|
-
* See nsIUpdateService.idl
|
2732
|
-
*/
|
2733
|
-
showUpdateAvailable: function(update) {
|
2734
|
-
if (this._enabled) {
|
2735
|
-
this._showUI(null, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
|
2736
|
-
"updatesavailable", update);
|
2737
|
-
}
|
2738
|
-
},
|
2739
|
-
|
2740
|
-
/**
|
2741
|
-
* See nsIUpdateService.idl
|
2742
|
-
*/
|
2743
|
-
showUpdateDownloaded: function(update) {
|
2744
|
-
if (this._enabled) {
|
2745
|
-
this._showUI(null, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
|
2746
|
-
"finishedBackground", update);
|
2747
|
-
}
|
2748
|
-
},
|
2749
|
-
|
2750
|
-
/**
|
2751
|
-
* See nsIUpdateService.idl
|
2752
|
-
*/
|
2753
|
-
showUpdateInstalled: function(update) {
|
2754
|
-
var showUpdateInstalledUI = getPref("getBoolPref",
|
2755
|
-
PREF_APP_UPDATE_SHOW_INSTALLED_UI, true);
|
2756
|
-
if (this._enabled && showUpdateInstalledUI) {
|
2757
|
-
this._showUI(null, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
|
2758
|
-
"installed", update);
|
2759
|
-
}
|
2760
|
-
},
|
2761
|
-
|
2762
|
-
/**
|
2763
|
-
* See nsIUpdateService.idl
|
2764
|
-
*/
|
2765
|
-
showUpdateError: function(update) {
|
2766
|
-
if (this._enabled) {
|
2767
|
-
// In some cases, we want to just show a simple alert dialog:
|
2768
|
-
if (update.state == STATE_FAILED && update.errorCode == WRITE_ERROR) {
|
2769
|
-
var sbs =
|
2770
|
-
Components.classes["@mozilla.org/intl/stringbundle;1"].
|
2771
|
-
getService(Components.interfaces.nsIStringBundleService);
|
2772
|
-
var updateBundle = sbs.createBundle(URI_UPDATES_PROPERTIES);
|
2773
|
-
var title = updateBundle.GetStringFromName("updaterIOErrorTitle");
|
2774
|
-
var text = updateBundle.formatStringFromName("updaterIOErrorText",
|
2775
|
-
[gApp.name], 1);
|
2776
|
-
var ww =
|
2777
|
-
Components.classes["@mozilla.org/embedcomp/window-watcher;1"].
|
2778
|
-
getService(Components.interfaces.nsIWindowWatcher);
|
2779
|
-
ww.getNewPrompter(null).alert(title, text);
|
2780
|
-
} else {
|
2781
|
-
this._showUI(null, URI_UPDATE_PROMPT_DIALOG, null, "Update:Wizard",
|
2782
|
-
"errors", update);
|
2783
|
-
}
|
2784
|
-
}
|
2785
|
-
},
|
2786
|
-
|
2787
|
-
/**
|
2788
|
-
* See nsIUpdateService.idl
|
2789
|
-
*/
|
2790
|
-
showUpdateHistory: function(parent) {
|
2791
|
-
this._showUI(parent, URI_UPDATE_HISTORY_DIALOG, "modal,dialog=yes", "Update:History",
|
2792
|
-
null, null);
|
2793
|
-
},
|
2794
|
-
|
2795
|
-
/**
|
2796
|
-
* Whether or not we are enabled (i.e. not in Silent mode)
|
2797
|
-
*/
|
2798
|
-
get _enabled() {
|
2799
|
-
return !getPref("getBoolPref", PREF_APP_UPDATE_SILENT, false);
|
2800
|
-
},
|
2801
|
-
|
2802
|
-
/**
|
2803
|
-
* Show the Update Checking UI
|
2804
|
-
* @param parent
|
2805
|
-
* A parent window, can be null
|
2806
|
-
* @param uri
|
2807
|
-
* The URI string of the dialog to show
|
2808
|
-
* @param name
|
2809
|
-
* The Window Name of the dialog to show, in case it is already open
|
2810
|
-
* and can merely be focused
|
2811
|
-
* @param page
|
2812
|
-
* The page of the wizard to be displayed, if one is already open.
|
2813
|
-
* @param update
|
2814
|
-
* An update to pass to the UI in the window arguments.
|
2815
|
-
* Can be null
|
2816
|
-
*/
|
2817
|
-
_showUI: function(parent, uri, features, name, page, update) {
|
2818
|
-
var ary = null;
|
2819
|
-
if (update) {
|
2820
|
-
ary = Components.classes["@mozilla.org/supports-array;1"]
|
2821
|
-
.createInstance(Components.interfaces.nsISupportsArray);
|
2822
|
-
ary.AppendElement(update);
|
2823
|
-
}
|
2824
|
-
|
2825
|
-
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
2826
|
-
.getService(Components.interfaces.nsIWindowMediator);
|
2827
|
-
var win = wm.getMostRecentWindow(name);
|
2828
|
-
if (win) {
|
2829
|
-
if (page && "setCurrentPage" in win)
|
2830
|
-
win.setCurrentPage(page);
|
2831
|
-
win.focus();
|
2832
|
-
}
|
2833
|
-
else {
|
2834
|
-
var openFeatures = "chrome,centerscreen,dialog=no,resizable=no,titlebar,toolbar=no";
|
2835
|
-
if (features)
|
2836
|
-
openFeatures += "," + features;
|
2837
|
-
var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
|
2838
|
-
.getService(Components.interfaces.nsIWindowWatcher);
|
2839
|
-
ww.openWindow(parent, uri, "", openFeatures, ary);
|
2840
|
-
}
|
2841
|
-
},
|
2842
|
-
|
2843
|
-
/**
|
2844
|
-
* See nsISupports.idl
|
2845
|
-
*/
|
2846
|
-
QueryInterface: function(iid) {
|
2847
|
-
if (!iid.equals(Components.interfaces.nsIUpdatePrompt) &&
|
2848
|
-
!iid.equals(Components.interfaces.nsISupports))
|
2849
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
2850
|
-
return this;
|
2851
|
-
}
|
2852
|
-
};
|
2853
|
-
//@line 2826 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
2854
|
-
|
2855
|
-
var gModule = {
|
2856
|
-
registerSelf: function(componentManager, fileSpec, location, type) {
|
2857
|
-
componentManager = componentManager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
2858
|
-
|
2859
|
-
for (var key in this._objects) {
|
2860
|
-
var obj = this._objects[key];
|
2861
|
-
componentManager.registerFactoryLocation(obj.CID, obj.className, obj.contractID,
|
2862
|
-
fileSpec, location, type);
|
2863
|
-
}
|
2864
|
-
|
2865
|
-
// Make the Update Service a startup observer
|
2866
|
-
var categoryManager = Components.classes["@mozilla.org/categorymanager;1"]
|
2867
|
-
.getService(Components.interfaces.nsICategoryManager);
|
2868
|
-
categoryManager.addCategoryEntry("app-startup", this._objects.service.className,
|
2869
|
-
"service," + this._objects.service.contractID,
|
2870
|
-
true, true, null);
|
2871
|
-
},
|
2872
|
-
|
2873
|
-
getClassObject: function(componentManager, cid, iid) {
|
2874
|
-
if (!iid.equals(Components.interfaces.nsIFactory))
|
2875
|
-
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
2876
|
-
|
2877
|
-
for (var key in this._objects) {
|
2878
|
-
if (cid.equals(this._objects[key].CID))
|
2879
|
-
return this._objects[key].factory;
|
2880
|
-
}
|
2881
|
-
|
2882
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
2883
|
-
},
|
2884
|
-
|
2885
|
-
_objects: {
|
2886
|
-
service: { CID : Components.ID("{B3C290A6-3943-4B89-8BBE-C01EB7B3B311}"),
|
2887
|
-
contractID : "@mozilla.org/updates/update-service;1",
|
2888
|
-
className : "Update Service",
|
2889
|
-
factory : makeFactory(UpdateService)
|
2890
|
-
},
|
2891
|
-
checker: { CID : Components.ID("{898CDC9B-E43F-422F-9CC4-2F6291B415A3}"),
|
2892
|
-
contractID : "@mozilla.org/updates/update-checker;1",
|
2893
|
-
className : "Update Checker",
|
2894
|
-
factory : makeFactory(Checker)
|
2895
|
-
},
|
2896
|
-
//@line 2869 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
2897
|
-
prompt: { CID : Components.ID("{27ABA825-35B5-4018-9FDD-F99250A0E722}"),
|
2898
|
-
contractID : "@mozilla.org/updates/update-prompt;1",
|
2899
|
-
className : "Update Prompt",
|
2900
|
-
factory : makeFactory(UpdatePrompt)
|
2901
|
-
},
|
2902
|
-
//@line 2875 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
2903
|
-
timers: { CID : Components.ID("{B322A5C0-A419-484E-96BA-D7182163899F}"),
|
2904
|
-
contractID : "@mozilla.org/updates/timer-manager;1",
|
2905
|
-
className : "Timer Manager",
|
2906
|
-
factory : makeFactory(TimerManager)
|
2907
|
-
},
|
2908
|
-
manager: { CID : Components.ID("{093C2356-4843-4C65-8709-D7DBCBBE7DFB}"),
|
2909
|
-
contractID : "@mozilla.org/updates/update-manager;1",
|
2910
|
-
className : "Update Manager",
|
2911
|
-
factory : makeFactory(UpdateManager)
|
2912
|
-
},
|
2913
|
-
},
|
2914
|
-
|
2915
|
-
canUnload: function(componentManager) {
|
2916
|
-
return true;
|
2917
|
-
}
|
2918
|
-
};
|
2919
|
-
|
2920
|
-
/**
|
2921
|
-
* Creates a factory for instances of an object created using the passed-in
|
2922
|
-
* constructor.
|
2923
|
-
*/
|
2924
|
-
function makeFactory(ctor) {
|
2925
|
-
function ci(outer, iid) {
|
2926
|
-
if (outer != null)
|
2927
|
-
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
2928
|
-
return (new ctor()).QueryInterface(iid);
|
2929
|
-
}
|
2930
|
-
return { createInstance: ci };
|
2931
|
-
}
|
2932
|
-
|
2933
|
-
function NSGetModule(compMgr, fileSpec) {
|
2934
|
-
return gModule;
|
2935
|
-
}
|
2936
|
-
|
2937
|
-
/**
|
2938
|
-
* Determines whether or there are installed addons which are incompatible
|
2939
|
-
* with this update.
|
2940
|
-
* @param update
|
2941
|
-
* The update to check compatibility against
|
2942
|
-
* @returns true if there are no addons installed that are incompatible with
|
2943
|
-
* the specified update, false otherwise.
|
2944
|
-
*/
|
2945
|
-
function isCompatible(update) {
|
2946
|
-
//@line 2919 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
2947
|
-
var em =
|
2948
|
-
Components.classes["@mozilla.org/extensions/manager;1"].
|
2949
|
-
getService(Components.interfaces.nsIExtensionManager);
|
2950
|
-
var items = em.getIncompatibleItemList("", update.extensionVersion,
|
2951
|
-
nsIUpdateItem.TYPE_ADDON, false, { });
|
2952
|
-
return items.length == 0;
|
2953
|
-
//@line 2928 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
2954
|
-
}
|
2955
|
-
|
2956
|
-
/**
|
2957
|
-
* Shows a prompt for an update, provided there are no incompatible addons.
|
2958
|
-
* If there are, kick off an update check and see if updates are available
|
2959
|
-
* that will resolve the incompatibilities.
|
2960
|
-
* @param update
|
2961
|
-
* The available update to show
|
2962
|
-
*/
|
2963
|
-
function showPromptIfNoIncompatibilities(update) {
|
2964
|
-
function showPrompt(update) {
|
2965
|
-
LOG("UpdateService", "_selectAndInstallUpdate: need to prompt user before continuing...");
|
2966
|
-
var prompter =
|
2967
|
-
Components.classes["@mozilla.org/updates/update-prompt;1"].
|
2968
|
-
createInstance(Components.interfaces.nsIUpdatePrompt);
|
2969
|
-
prompter.showUpdateAvailable(update);
|
2970
|
-
}
|
2971
|
-
|
2972
|
-
//@line 2947 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
2973
|
-
/**
|
2974
|
-
* Determines if an addon is compatible with a particular update.
|
2975
|
-
* @param addon
|
2976
|
-
* The addon to check
|
2977
|
-
* @param version
|
2978
|
-
* The extensionVersion of the update to check for compatibility
|
2979
|
-
* against.
|
2980
|
-
* @returns true if the addon is compatible, false otherwise
|
2981
|
-
*/
|
2982
|
-
function addonIsCompatible(addon, version) {
|
2983
|
-
var vc =
|
2984
|
-
Components.classes["@mozilla.org/xpcom/version-comparator;1"].
|
2985
|
-
getService(Components.interfaces.nsIVersionComparator);
|
2986
|
-
return (vc.compare(version, addon.minAppVersion) >= 0) &&
|
2987
|
-
(vc.compare(version, addon.maxAppVersion) <= 0);
|
2988
|
-
}
|
2989
|
-
|
2990
|
-
/**
|
2991
|
-
* An object implementing nsIAddonUpdateCheckListener that looks for
|
2992
|
-
* available updates to addons and if updates are found that will make the
|
2993
|
-
* user's installed addon set compatible with the update, suppresses the
|
2994
|
-
* prompt that would otherwise be shown.
|
2995
|
-
* @param addons
|
2996
|
-
* An array of incompatible addons that are installed.
|
2997
|
-
* @constructor
|
2998
|
-
*/
|
2999
|
-
function Listener(addons) {
|
3000
|
-
this._addons = addons;
|
3001
|
-
}
|
3002
|
-
Listener.prototype = {
|
3003
|
-
_addons: null,
|
3004
|
-
|
3005
|
-
/**
|
3006
|
-
* See nsIUpdateService.idl
|
3007
|
-
*/
|
3008
|
-
onUpdateStarted: function() {
|
3009
|
-
},
|
3010
|
-
onUpdateEnded: function() {
|
3011
|
-
// There are still incompatibilities, even after an extension update
|
3012
|
-
// check to see if there were newer, compatible versions available, so
|
3013
|
-
// we have to prompt.
|
3014
|
-
//
|
3015
|
-
// PREF_APP_UPDATE_INCOMPATIBLE_MODE controls the mode in which we
|
3016
|
-
// handle incompatibilities:
|
3017
|
-
// 0 We count both VersionInfo updates _and_ NewerVersion updates
|
3018
|
-
// against the list of incompatible addons installed - i.e. if
|
3019
|
-
// Foo 1.2 is installed and it is incompatible with the update, and
|
3020
|
-
// we find Foo 2.0 which is but which is not yet downloaded or
|
3021
|
-
// installed, then we do NOT prompt because the user can download
|
3022
|
-
// Foo 2.0 when they restart after the update during the mismatch
|
3023
|
-
// checking UI. This is the default, since it suppresses most
|
3024
|
-
// prompt dialogs.
|
3025
|
-
// 1 We count only VersionInfo updates against the list of
|
3026
|
-
// incompatible addons installed - i.e. if the situation above
|
3027
|
-
// with Foo 1.2 and available update to 2.0 applies, we DO show
|
3028
|
-
// the prompt since a download operation will be required after
|
3029
|
-
// the update. This is not the default and is supplied only as
|
3030
|
-
// a hidden option for those that want it.
|
3031
|
-
var mode = getPref("getIntPref", PREF_APP_UPDATE_INCOMPATIBLE_MODE,
|
3032
|
-
INCOMPATIBLE_MODE_NEWVERSIONS);
|
3033
|
-
if ((mode == 0 && this._addons.length) || !isCompatible(update))
|
3034
|
-
showPrompt(update);
|
3035
|
-
},
|
3036
|
-
onAddonUpdateStarted: function(addon) {
|
3037
|
-
},
|
3038
|
-
onAddonUpdateEnded: function(addon, status) {
|
3039
|
-
if (status == Components.interfaces.nsIAddonUpdateCheckListener.STATUS_UPDATE &&
|
3040
|
-
addonIsCompatible(addon, update.extensionVersion)) {
|
3041
|
-
for (var i = 0; i < this._addons.length; ++i) {
|
3042
|
-
if (this._addons[i] == addon) {
|
3043
|
-
this._addons.splice(i, 1);
|
3044
|
-
break;
|
3045
|
-
}
|
3046
|
-
}
|
3047
|
-
}
|
3048
|
-
},
|
3049
|
-
/**
|
3050
|
-
* See nsISupports.idl
|
3051
|
-
*/
|
3052
|
-
QueryInterface: function(iid) {
|
3053
|
-
if (!iid.equals(Components.interfaces.nsIAddonUpdateCheckListener) &&
|
3054
|
-
!iid.equals(Components.interfaces.nsISupports))
|
3055
|
-
throw Components.results.NS_ERROR_NO_INTERFACE;
|
3056
|
-
return this;
|
3057
|
-
}
|
3058
|
-
};
|
3059
|
-
|
3060
|
-
if (!isCompatible(update)) {
|
3061
|
-
var em =
|
3062
|
-
Components.classes["@mozilla.org/extensions/manager;1"].
|
3063
|
-
getService(Components.interfaces.nsIExtensionManager);
|
3064
|
-
var listener = new Listener(em.getIncompatibleItemList("",
|
3065
|
-
update.extensionVersion, nsIUpdateItem.TYPE_ADDON, false, { }));
|
3066
|
-
// See documentation on |mode| above.
|
3067
|
-
var mode = getPref("getIntPref", PREF_APP_UPDATE_INCOMPATIBLE_MODE,
|
3068
|
-
INCOMPATIBLE_MODE_NEWVERSIONS);
|
3069
|
-
em.update([], 0, mode != 0, listener);
|
3070
|
-
}
|
3071
|
-
else
|
3072
|
-
//@line 3047 "/c/mozilla/toolkit/mozapps/update/src/nsUpdateService.js.in"
|
3073
|
-
showPrompt(update);
|
3074
|
-
}
|