1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955
  1. /*
  2. * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  3. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4. */
  5. /**
  6. The Java Deployment Toolkit is a utility to deploy Java content in
  7. the browser as applets or applications using the right version of Java.
  8. If needed it can initiate an upgrade of user's system to install required
  9. components of Java platform.
  10. <p>
  11. Note that some of the Deployment Toolkit methods may not be fully operational if
  12. used before web page body is loaded (because DT native plugins could not be instantiated).
  13. If you intend to use it before web page DOM tree is ready then dtjava.js
  14. needs to be loaded inside the body element of the page and before use of other DT APIs.
  15. @module java/deployment_toolkit
  16. */
  17. var dtjava = function() {
  18. function notNull(o) {
  19. return (o != undefined && o != null);
  20. }
  21. function isDef(fn) {
  22. return (fn != null && typeof fn != "undefined");
  23. }
  24. //return true if any of patterns from query list is found in the given string
  25. function containsAny(lst, str) {
  26. for (var q = 0; q < lst.length; q++) {
  27. if (str.indexOf(lst[q]) != -1) {
  28. return true;
  29. }
  30. }
  31. return false;
  32. }
  33. /* Location of static web content - images, javascript files. */
  34. var jscodebase = (function () {
  35. // <script> elements are added to the DOM and run synchronously,
  36. // the currently running script will also be the last element in the array
  37. var scripts = document.getElementsByTagName("script");
  38. var src = scripts[scripts.length - 1].getAttribute("src");
  39. return src ? src.substring(0, src.lastIndexOf('/') + 1) : "";
  40. })();
  41. //set to true to disable FX auto install (before release)
  42. var noFXAutoInstall = false;
  43. // page has no body yet, postpone plugin installation
  44. postponeNativePluginInstallation = false;
  45. // JRE version we start to have JRE and FX true co-bundle
  46. var minJRECobundleVersion = "1.7.0_06";
  47. //aliases
  48. var d = document;
  49. var w = window;
  50. var cbDone = false; //done with onload callbacks
  51. var domInternalCb = []; //list of internal callbacks
  52. var domCb = []; //list of callbacks
  53. var ua = null;
  54. // Add internal function to be called on DOM ready event.
  55. // These functions will be called before functions added by addOnDomReady().
  56. // Used to do internal initialization (installing native plug-in) to avoid
  57. // race condition with user requests.
  58. function addOnDomReadyInternal(fn) {
  59. if (cbDone) {
  60. fn();
  61. } else {
  62. domInternalCb[domInternalCb.length] = fn;
  63. }
  64. }
  65. // add function to be called on DOM ready event
  66. function addOnDomReady(fn) {
  67. if (cbDone) {
  68. fn();
  69. } else {
  70. domCb[domCb.length] = fn;
  71. }
  72. }
  73. //invoke pending onload callbacks
  74. function invokeCallbacks() {
  75. if (!cbDone) {
  76. //swfoject.js tests whether DOM is actually ready first
  77. // in order to not fire too early. Use same heuristic
  78. try {
  79. var t = d.getElementsByTagName("body")[0].appendChild(
  80. d.createElement("div"));
  81. t.parentNode.removeChild(t);
  82. } catch (e) {
  83. return;
  84. }
  85. cbDone = true;
  86. for (var i = 0; i < domInternalCb.length; i++) {
  87. domInternalCb[i]();
  88. }
  89. for (var i = 0; i < domCb.length; i++) {
  90. domCb[i]();
  91. }
  92. }
  93. }
  94. //cross browser onload support.
  95. //Derived from swfobject.js
  96. function addOnload(fn) {
  97. if (isDef(w.addEventListener)) {
  98. w.addEventListener("load", fn, false);
  99. } else if (isDef(d.addEventListener)) {
  100. d.addEventListener("load", fn, false);
  101. } else if (isDef(w.attachEvent)) {
  102. w.attachEvent("onload", fn);
  103. //TODO: swfobject also keeps references to the listeners to detach them on onload
  104. // to avoid memory leaks ...
  105. } else if (typeof w.onload == "function") {
  106. var fnOld = w.onload;
  107. w.onload = function() {
  108. fnOld();
  109. fn();
  110. };
  111. } else {
  112. w.onload = fn;
  113. }
  114. }
  115. function detectEnv() {
  116. var dom = isDef(d.getElementById) && isDef(d.getElementsByTagName) && isDef(d.createElement);
  117. var u = navigator.userAgent.toLowerCase(),
  118. p = navigator.platform.toLowerCase();
  119. //NB: may need to be refined as some user agent may contain strings related to other browsers
  120. // (e.g. Chrome has both Safari and mozilla, Safari also has mozilla
  121. var windows = p ? /win/.test(p) : /win/.test(u),
  122. mac = p ? /mac/.test(p) : /mac/.test(u),
  123. linux = p ? /linux/.test(p) : /linux/.test(u),
  124. chrome = /chrome/.test(u),
  125. // get webkit version or false if not webkit
  126. webkit = !chrome && /webkit/.test(u) ?
  127. parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false,
  128. opera = /opera/.test(u),
  129. cputype = null,
  130. osVersion = null;
  131. var ie = false;
  132. try {
  133. //Used to be using trick from
  134. // http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
  135. //ie = !+"\v1",
  136. //but it does not work with IE9 in standards mode
  137. //Reverting to alternative - use execScript
  138. ie = isDef(window.execScript);
  139. // IE 11 does not support execScript any more and no exception is thrown, so lets use more naive test.
  140. // http://msdn.microsoft.com/en-us/library/ie/bg182625(v=vs.85).aspx
  141. if (!ie) { // We do not want to overwrite if ie was detected above.
  142. ie = (navigator.userAgent.match(/Trident/i) != null);
  143. }
  144. } catch (ee) {
  145. //if javafx app is in the iframe and content of main window is coming from other domain
  146. // then some browsers may restrict access to outer window properties,
  147. // e.g. FF can throw exception for top.execScript (see RT-17885)
  148. //We could revert to more naive test, e.g. test user agent for "MSIE " string
  149. // but so far IE does not seem to throw exception => if we get here it is not IE anyways
  150. ie = false;
  151. }
  152. var edge = false;
  153. var noActiveX = false;
  154. edge = (navigator.userAgent.match(/Edge/i) != null);
  155. // If IE and Windows 8 or Windows 8.1 then check for Metro mode
  156. if(ie && navigator.userAgent.match(/Windows NT 6\.[23]/i) != null) {
  157. try {
  158. // try to create a known ActiveX object
  159. new ActiveXObject("htmlfile");
  160. } catch(e) {
  161. // ActiveX is disabled or not supported.
  162. noActiveX = true;
  163. }
  164. }
  165. if(edge || noActiveX) {
  166. ie = false;
  167. }
  168. var noPluginWebBrowser = edge || chrome || noActiveX;
  169. //we are not required to detect everything and can leave values null as
  170. // long as we later treat them accordingly.
  171. //We use "cputype" to detect if given hardware is supported,
  172. // e.g. we do not support PPC or iPhone/iPad despite they are running Mac OS
  173. //We use "osVersion" to detect if Java/JavaFX can be installed on this OS
  174. // e.g. Oracle Java for Mac requires 10.7.3
  175. if (mac) {
  176. if ((p && /intel/.test(p)) || /intel/.test(u)) {
  177. cputype = "intel";
  178. }
  179. //looking for things like 10_7, 10_6_8, 10.4 in the user agent
  180. var t = u.match(/mac os x (10[0-9_\.]+)/);
  181. //normalize to "." separators
  182. osVersion = notNull(t) ? t[0].replace("mac os x ","").replace(/_/g, ".") : null;
  183. }
  184. // trim() is not supported by IE10 and before
  185. if(typeof String.prototype.trim !== 'function') {
  186. String.prototype.trim = function() {
  187. return this.replace(/^\s+|\s+$/g, '');
  188. }
  189. }
  190. // startsWith() is not supported by IE
  191. if(typeof String.prototype.startsWith !== 'function') {
  192. String.prototype.startsWith = function(searchString, position) {
  193. position = position || 0;
  194. return this.indexOf(searchString, position) === position;
  195. }
  196. }
  197. // Check mime types. Works with netscape family browsers and checks latest installed plugin only
  198. var mm = navigator.mimeTypes;
  199. var jre = null;
  200. var deploy = null;
  201. var fx = null;
  202. var override = false;
  203. if (typeof __dtjavaTestHook__ !== 'undefined' &&
  204. __dtjavaTestHook__ != null &&
  205. __dtjavaTestHook__.jre != null &&
  206. __dtjavaTestHook__.jfx != null &&
  207. __dtjavaTestHook__.deploy != null) {
  208. jre = __dtjavaTestHook__.jre;
  209. deploy = __dtjavaTestHook__.deploy;
  210. fx = __dtjavaTestHook__.jfx;
  211. override = true;
  212. }
  213. else {
  214. //Cache configuration from plugin mimetypes
  215. //It is only available for NPAPI browsers
  216. for (var t = 0; t < mm.length; t++) {
  217. // The jpi-version is the JRE version.
  218. var m = navigator.mimeTypes[t].type;
  219. if (m.indexOf("application/x-java-applet;version") != -1 && m.indexOf('=') != -1) {
  220. var v = m.substring(m.indexOf('=') + 1);
  221. // Use the existing version comparison mechanism to ensure that
  222. // the latest JRE is selected ( "versionA"<="VersionB" equals to
  223. // versionCheck("versionA+","versionB") returns "true")
  224. if(jre == null || versionCheck(jre + "+", v)){
  225. jre = v;
  226. }
  227. }
  228. //Supported for 7u6 or later
  229. if (m.indexOf("application/x-java-applet;deploy") != -1 && m.indexOf('=') != -1) {
  230. deploy = m.substring(m.indexOf('=') + 1);
  231. }
  232. //javafx version for cobundled javafx (7u6+)
  233. if (m.indexOf("application/x-java-applet;javafx") != -1 && m.indexOf('=') != -1) {
  234. fx = m.substring(m.indexOf('=') + 1);
  235. }
  236. }
  237. }
  238. return {haveDom:dom, wk:webkit, ie:ie, win:windows,
  239. linux:linux, mac:mac, op: opera, chrome:chrome, edge:edge,
  240. jre:jre, deploy:deploy, fx:fx, noPluginWebBrowser:noPluginWebBrowser,
  241. cputype: cputype, osVersion: osVersion, override: override};
  242. }
  243. function showMessageBox() {
  244. var message = 'Java Plug-in is not supported by this browser. <a href="https://java.com/dt-redirect">More info</a>';
  245. var mbStyle = 'background-color: #ffffce;text-align: left;border: solid 1px #f0c000; padding: 1.65em 1.65em .75em 0.5em; font-family: Helvetica, Arial, sans-serif; font-size: 75%; bottom:0; left:0; right:0; position:fixed; margin:auto; opacity:0.9; width:400px;';
  246. var messageStyle = "border: .85px; margin:-2.2em 0 0.55em 2.5em;";
  247. var closeButtonStyle = "margin-left:10px;font-weight:bold;float:right;font-size:22px;line-height:20px;cursor:pointer;color:red;"
  248. var messageBox = '<span style="'+ closeButtonStyle +'" onclick="this.parentElement.style.display=\'none\';">&times;</span><img src="https://java.com/js/alert_16.png"><div style="'+ messageStyle +'"><p>'+ message + '</p>';
  249. var divTag = document.createElement("div");
  250. divTag.id = "messagebox";
  251. divTag.setAttribute('style', mbStyle);
  252. divTag.innerHTML = messageBox;
  253. document.body.appendChild(divTag);
  254. }
  255. //partially derived from swfobject.js
  256. var initDone = false;
  257. function init() {
  258. if (typeof __dtjavaTestHook__ !== 'undefined') {
  259. jre = null;
  260. jfx = null;
  261. deploy = null;
  262. if ((__dtjavaTestHook__ != null) && (__dtjavaTestHook__.args != null)) {
  263. jre = __dtjavaTestHook__.args.jre;
  264. jfx = __dtjavaTestHook__.args.jfx;
  265. deploy = __dtjavaTestHook__.args.deploy;
  266. }
  267. if ((window.location.href.indexOf('http://localhost') == 0) ||
  268. (window.location.href.indexOf('file:///') == 0)) {
  269. __dtjavaTestHook__ = {
  270. detectEnv: detectEnv,
  271. Version: Version,
  272. checkFXSupport: checkFXSupport,
  273. versionCheck: versionCheck,
  274. versionCheckFX: versionCheckFX,
  275. jre: jre,
  276. jfx: jfx,
  277. deploy: deploy
  278. };
  279. }
  280. }
  281. if (initDone) return;
  282. ua = detectEnv();
  283. if (!ua.haveDom) {
  284. return;
  285. }
  286. //NB: dtjava.js can be added dynamically and init() can be called after
  287. // document onload event is fired
  288. if (( isDef(d.readyState) && d.readyState == "complete") ||
  289. (!isDef(d.readyState) &&
  290. (d.getElementsByTagName("body")[0] || d.body))) {
  291. invokeCallbacks();
  292. }
  293. if (!cbDone) {
  294. if (isDef(d.addEventListener)) {
  295. d.addEventListener("DOMContentLoaded",
  296. invokeCallbacks, false);
  297. }
  298. if (ua.ie && ua.win) {
  299. // http://msdn.microsoft.com/en-us/library/ie/ms536343(v=vs.85).aspx
  300. // attachEvent is not supported by IE 11.
  301. if (isDef(d.addEventListener)) {
  302. d.addEventListener("onreadystatechange", function() {
  303. if (d.readyState == "complete") {
  304. d.removeEventListener("onreadystatechange", arguments.callee, false);
  305. invokeCallbacks();
  306. }
  307. }, false);
  308. } else {
  309. d.attachEvent("onreadystatechange", function() {
  310. if (d.readyState == "complete") {
  311. d.detachEvent("onreadystatechange", arguments.callee);
  312. invokeCallbacks();
  313. }
  314. });
  315. }
  316. if (w == top) { // if not inside an iframe
  317. (function() {
  318. if (cbDone) {
  319. return;
  320. }
  321. //AI: what for??
  322. try {
  323. d.documentElement.doScroll("left");
  324. } catch(e) {
  325. setTimeout(arguments.callee, 0);
  326. return;
  327. }
  328. invokeCallbacks();
  329. })();
  330. }
  331. }
  332. if (ua.wk) {
  333. (function() {
  334. if (cbDone) {
  335. return;
  336. }
  337. if (!/loaded|complete/.test(d.readyState)) {
  338. setTimeout(arguments.callee, 0);
  339. return;
  340. }
  341. invokeCallbacks();
  342. })();
  343. }
  344. addOnload(invokeCallbacks);
  345. }
  346. //only try to install native plugin if we do not have DTLite
  347. //Practically this means we are running NPAPI browser on Windows
  348. //(Chrome or FF) and recent JRE (7u4+?)
  349. if (!haveDTLite()) {
  350. installNativePlugin();
  351. }
  352. }
  353. function getAbsoluteUrl(jnlp){
  354. var absoluteUrl;
  355. if(isAbsoluteUrl(jnlp)) {
  356. absoluteUrl = jnlp;
  357. } else {
  358. var location = window.location.href;
  359. var pos = location.lastIndexOf('/');
  360. var docbase = pos > -1 ? location.substring(0, pos + 1) : location + '/';
  361. absoluteUrl = docbase + jnlp;
  362. }
  363. return absoluteUrl;
  364. }
  365. function launchWithJnlpProtocol(jnlp) {
  366. document.location="jnlp:"+ getAbsoluteUrl(jnlp);
  367. }
  368. function isAbsoluteUrl(url){
  369. var protocols = ["http://", "https://", "file://"];
  370. for (var i=0; i < protocols.length; i++){
  371. if(url.toLowerCase().startsWith(protocols[i])){
  372. return true;;
  373. }
  374. }
  375. return false;
  376. }
  377. /**
  378. This class provides details on why current platform does not meet
  379. application platform requirements. Note that severe problems are
  380. reported immediately and therefore full check may be not performed and
  381. some (unrelated to fatal problem)
  382. methods may provide false positive answers.
  383. <p>
  384. If multiple components do not match then worst status is reported.
  385. Application need to repeat checks on each individual component
  386. if it want to find out all details.
  387. @class PlatformMismatchEvent
  388. @for dtjava
  389. */
  390. function PlatformMismatchEvent(a) {
  391. //expect to get all parameters needed
  392. for (var p in a) {
  393. this[p] = a[p];
  394. }
  395. /**
  396. * @method toString
  397. * @return {string}
  398. * Returns string replesentation of event. Useful for debugging.
  399. */
  400. this.toString = function() {
  401. return "MISMATCH [os=" + this.os + ", browser=" + this.browser
  402. + ", jre=" + this.jre + ", fx=" + this.fx
  403. + ", relaunch=" + this.relaunch + ", platform="
  404. + this.platform + "]";
  405. };
  406. /**
  407. @method isUnsupportedPlatform
  408. @return {boolean}
  409. Returns true if this platform (OS/hardware) is not supported in a way
  410. to satisfy all platfrom requirements.
  411. (E.g. page is viewed on iPhone or JavaFX 2.0 application on Solaris.)
  412. <p>
  413. Note that this does not include browser match data.
  414. If platform is unsupported then application can not be
  415. launched and user need to use another platform to view it.
  416. */
  417. this.isUnsupportedPlatform = function() {
  418. return this.os;
  419. };
  420. /**
  421. @method isUnsupportedBrowser
  422. @return {boolean}
  423. Returns true if error is because current browser is not supported.
  424. <p>
  425. If true is returned and isRelaunchNeeded() returns true too then
  426. there are known supported browsers browsers for this platform.
  427. (but they are not necessary installed on end user system)
  428. */
  429. this.isUnsupportedBrowser = function() {
  430. return this.browser;
  431. };
  432. /**
  433. @method jreStatus
  434. @return {string}
  435. Returns "ok" if error was not due to missing JRE.
  436. Otherwise return error code characterizing the problem:
  437. <ul>
  438. <li> none - no JRE were detected on the system
  439. <li> old - some version of JRE was detected but it does not match platform requirements
  440. <li> oldplugin - matching JRE found but it is configured to use deprecated Java plugin that
  441. does not support Java applets
  442. <ul>
  443. <p>
  444. canAutoInstall() and isRelaunchNeeded() can be used to
  445. get more details on how seamless user' install experience will be.
  446. */
  447. this.jreStatus = function() {
  448. return this.jre;
  449. };
  450. /**
  451. * @method jreInstallerURL
  452. * @param {string} locale (optional) Locale to be used for installation web page
  453. * @return {string}
  454. *
  455. * Return URL of page to visit to install required version of Java.
  456. * If matching java runtime is already installed or not officially supported
  457. * then return value is null.
  458. */
  459. this.jreInstallerURL = function(locale) {
  460. if (!this.os && (this.jre == "old" || this.jre == "none")) {
  461. return getJreUrl(locale);
  462. }
  463. return null;
  464. };
  465. /**
  466. @method javafxStatus
  467. @return {string}
  468. Returns "ok" if error was not due to missing JavaFX.
  469. Otherwise return error code characterizing the problem:
  470. <ul>
  471. <li> none - no JavaFX runtime is detected on the system
  472. <li> old - some version of JavaFX runtime iss detected but it does not match platform requirements
  473. <li> disabled - matching JavaFX is detected but it is disabled
  474. <li> unsupported - JavaFX is not supported on this platform
  475. <ul>
  476. <p>
  477. canAutoInstall() and isRelaunchNeeded() can be used to
  478. get more details on how seamless user' install experience will be.
  479. */
  480. this.javafxStatus = function() {
  481. return this.fx;
  482. };
  483. /**
  484. * @method javafxInstallerURL
  485. * @param {string} locale (optional) Locale to be used for installation web page
  486. * @return {string}
  487. *
  488. * Return URL of page to visit to install required version of JavaFX.
  489. * If matching JavaFX runtime is already installed or not officially supported
  490. * then return value is null.
  491. */
  492. this.javafxInstallerURL = function(locale) {
  493. if (!this.os && (this.fx == "old" || this.fx == "none")) {
  494. return getFxUrl(locale);
  495. }
  496. return null;
  497. };
  498. /**
  499. @method canAutoInstall
  500. @return {boolean}
  501. Returns true if installation of missing components can be
  502. triggered automatically. In particular, ture is returned
  503. if there are no missing components too.
  504. <p>
  505. If any of missing components need to be installed manually
  506. (i.e. click through additional web pages) then false is returned.
  507. */
  508. this.canAutoInstall = function() {
  509. return isAutoInstallEnabled(this.platform, this.jre, this.fx);
  510. };
  511. /**
  512. @method isRelaunchNeeded
  513. @return {boolean}
  514. Returns true if browser relaunch is needed before application can be loaded.
  515. This often is true in conjuction with need to perform installation.
  516. <p>
  517. Other typical case - use of unsupported browser when
  518. it is known that there are supported browser for this pltaform.
  519. Then both isUnsupportedBrowser() and isRelaunchNeeded() return true.
  520. */
  521. this.isRelaunchNeeded = function() {
  522. return this.relaunch;
  523. };
  524. }
  525. //returns version of instaled JavaFX runtime matching requested version
  526. //or null otherwise
  527. function getInstalledFXVersion(requestedVersion) {
  528. //NPAPI browser and JRE with cobundle
  529. if (ua.fx != null && versionCheckFX(requestedVersion, ua.fx)) {
  530. return ua.fx;
  531. }
  532. //try to use DT
  533. var p = getPlugin();
  534. if (notNull(p)) {
  535. try {
  536. return p.getInstalledFXVersion(requestedVersion);
  537. } catch(e) {}
  538. }
  539. return null;
  540. }
  541. //concatenate list with space as separator
  542. function listToString(lst) {
  543. if (lst != null) {
  544. return lst.join(" ");
  545. } else {
  546. return null;
  547. }
  548. }
  549. function addArgToList(lst, arg) {
  550. if (notNull(lst)) {
  551. lst.push(arg);
  552. return lst;
  553. } else {
  554. var res = [arg];
  555. return res;
  556. }
  557. }
  558. function doLaunch(ld, platform, cb) {
  559. var app = normalizeApp(ld, true);
  560. if(ua.noPluginWebBrowser){
  561. launchWithJnlpProtocol(app.url);
  562. return;
  563. }
  564. //required argument is missing
  565. if (!(notNull(app) && notNull(app.url))) {
  566. throw "Required attribute missing! (application url need to be specified)";
  567. }
  568. //if we got array we need to copy over!
  569. platform = new dtjava.Platform(platform);
  570. //normalize handlers
  571. cb = new dtjava.Callbacks(cb);
  572. var launchFunc = function() {
  573. //prepare jvm arguments
  574. var jvmArgs = notNull(platform.jvmargs) ? platform.jvmargs : null;
  575. if (notNull(platform.javafx)) {
  576. //if FX is needed we know it is available or
  577. // we will not get here
  578. var v = getInstalledFXVersion(platform.javafx);
  579. //add hint that we need FX toolkit to avoid relaunch
  580. // if JNLP is not embedded
  581. jvmArgs = addArgToList(jvmArgs, " -Djnlp.fx=" + v);
  582. //for swing applications embedding FX we do not want this property as it will
  583. // trigger FX toolkit and lead to app failure!
  584. //But for JavaFX application it saves us relaunch as otherwise we wil launch with AWT toolkit ...
  585. if (!notNull(ld.toolkit) || ld.toolkit == "fx") {
  586. jvmArgs = addArgToList(jvmArgs, " -Djnlp.tk=jfx");
  587. }
  588. }
  589. //if we on 7u6+ we can use DTLite plugin in the NPAPI browsers
  590. //Caveat: as of 7u6 it does not work with Chrome on Linux because Chrome expects
  591. // DTLite plugin to implement xembed (or claim to support xembed)
  592. if (haveDTLite() && !(ua.linux && ua.chrome)) {
  593. if (doLaunchUsingDTLite(app, jvmArgs, cb)) {
  594. return;
  595. }
  596. }
  597. //Did not launch yet? Try DT plugin (7u2+)
  598. var p = getPlugin();
  599. if (notNull(p)) {
  600. try {
  601. try {
  602. //check if new DT APIs are available
  603. if (versionCheck("10.6+", ua.deploy, false)) {
  604. // obj.launchApp({"url" : "http://somewhere/my.jnlp",
  605. // "jnlp_content" : "... BASE 64 ...",
  606. // "vmargs" : [ "-ea -Djnlp.foo=bar"
  607. // "appargs" : [ "first arg, second arg" ]
  608. // "params" : {"p1" : "aaa", "p2" : "bbb"}});
  609. var callArgs = {"url":app.url};
  610. if (notNull(jvmArgs)) {
  611. callArgs["vmargs"] = jvmArgs;
  612. }
  613. //Only use HTML parameters, they are supposed to overwrite values in the JNLP
  614. //In the future we want to pass arguments too but this needs also be exposed for
  615. // embedded deployment
  616. if (notNull(app.params)) {
  617. //copy over and ensure all values are strings
  618. // (native code will ignore them otherwise)
  619. var ptmp = {};
  620. for (var k in app.params) {
  621. ptmp[k] = String(app.params[k]);
  622. }
  623. callArgs["params"] = ptmp;
  624. }
  625. if (notNull(app.jnlp_content)) {
  626. callArgs["jnlp_content"] = app.jnlp_content;
  627. }
  628. var err = p.launchApp(callArgs);
  629. if (err == 0) { //0 - error
  630. if (isDef(cb.onRuntimeError)) {
  631. cb.onRuntimeError(app.id);
  632. }
  633. }
  634. } else { //revert to old DT APIs
  635. //older DT APIs expects vmargs as a single string
  636. if (!p.launchApp(app.url, app.jnlp_content, listToString(jvmArgs))) {
  637. if (isDef(cb.onRuntimeError)) {
  638. cb.onRuntimeError(app.id);
  639. }
  640. }
  641. }
  642. return;
  643. } catch (ee) { //temp support for older build of DT
  644. if (!p.launchApp(app.url, app.jnlp_content)) {
  645. if (isDef(cb.onRuntimeError)) {
  646. cb.onRuntimeError(app.id);
  647. }
  648. }
  649. return;
  650. }
  651. } catch (e) {
  652. //old DT
  653. }
  654. } //old Java (pre DTLite)? not Windows? or old DT
  655. //use old way to launch it using java plugin
  656. var o = getWebstartObject(app.url);
  657. if (notNull(d.body)) {
  658. d.body.appendChild(o);
  659. } else {
  660. //should never happen
  661. d.write(o.innerHTML);
  662. }
  663. }
  664. var r = doValidateRelaxed(platform);
  665. //can not launch, try to fix
  666. if (r != null) {
  667. resolveAndLaunch(app, platform, r, cb, launchFunc);
  668. } else {
  669. launchFunc();
  670. }
  671. }
  672. //process unhandled platform error - convert to code and call callback
  673. function reportPlatformError(app, r, cb) {
  674. if (isDef(cb.onDeployError)) {
  675. cb.onDeployError(app, r);
  676. }
  677. }
  678. function isDTInitialized(p) {
  679. //if plugin is blocked then p.version will be undefined
  680. return p != null && isDef(p.version);
  681. }
  682. //Wait until DT plugin is initialized and then run the code
  683. //Currently we only use it for embeded apps and Chrome on Windows
  684. function runUsingDT(label, f) {
  685. // Possible situations:
  686. // a) plugin is live and we can simply run code
  687. // - just run the code
  688. // b) plugin is in the DOM tree but it is not initialized yet (e.g. Chrome blocking)
  689. // and there is live timer (pendingCount > 0)
  690. // - there could be another request. We will APPEND to it
  691. // (this is different from dtlite as in this case we can not have multiple clicks)
  692. // - renew timer life counter (do not want new timer)
  693. // c) plugin is in the DOM tree and it is not fully initialized yet but timer is stopped
  694. // - overwrite old request
  695. // - restart timer
  696. //
  697. // Problem we are solving:
  698. // when plugin is ready to serve request? How do we schedule call to happen when plugin is initialized?
  699. // Caveat:
  700. // Chrome can popup dialog asking user to grant permissions to load the plugin.
  701. // There is no API to detect dialog is shown and when user grants or declines permissions
  702. //
  703. // Note:
  704. // If we set property on plugin object before it is unblocked then they seem to be lost
  705. // and are not propagated to the final object once it is instantiated.
  706. //
  707. // Workaround we use:
  708. // Once plugin is added we will be checking if it is initialized and once we detect it we will execute code.
  709. // We will stop checking after some time.
  710. var p = getPlugin();
  711. if (p == null) {
  712. return; //NO DT
  713. }
  714. if (isDTInitialized(p)) {
  715. f(p);
  716. } else {
  717. // see if we need new timer
  718. var waitAndUse = null;
  719. if (!isDef(dtjava.dtPendingCnt) || dtjava.dtPendingCnt == 0) {
  720. waitAndUse = function () {
  721. if (isDTInitialized(p)) {
  722. if (notNull(dtjava.dtPending)) {
  723. for (var i in dtjava.dtPending) {
  724. dtjava.dtPending[i]();
  725. }
  726. }
  727. return;
  728. }
  729. if (dtjava.dtPendingCnt > 0) {
  730. dtjava.dtPendingCnt--;
  731. setTimeout(waitAndUse, 500);
  732. }
  733. }
  734. }
  735. //add new task in queue
  736. if (!notNull(dtjava.dtPending) || dtjava.dtPendingCnt == 0) {
  737. dtjava.dtPending = {};
  738. }
  739. dtjava.dtPending[label] = f; //use map to ensure repitative actions are not queued (e.g. multiple click to launch webstart)
  740. //reset the timer counter
  741. dtjava.dtPendingCnt = 1000; //timer is gone after 500s
  742. //start timer if needed
  743. if (waitAndUse != null) waitAndUse();
  744. }
  745. }
  746. //returns same mismatch event if not resolved, null if resolved
  747. function resolveAndLaunch(app, platform, v, cb, launchFunction) {
  748. var p = getPlugin();
  749. if( p == null && ua.noPluginWebBrowser){
  750. var readyStateCheck = setInterval(function() {
  751. if(document.readyState == "complete"){
  752. clearInterval(readyStateCheck);
  753. showMessageBox();
  754. }
  755. }, 15);
  756. return;
  757. }
  758. //Special case: Chrome/Windows
  759. // (Note: IE may also block activeX control but then it will block attempts to use it too)
  760. if (ua.chrome && ua.win && p != null && !isDTInitialized(p)) {
  761. //this likely means DT plugin is blocked by Chrome
  762. //tell user to grant permissions and retry
  763. var actionLabel;
  764. if (notNull(app.placeholder)) {
  765. var onClickFunc = function() {w.open("https://www.java.com/en/download/faq/chrome.xml"); return false;};
  766. var msg1 = "Please give Java permission to run on this browser web page.";
  767. var msg2 = "Click for more information.";
  768. var altText = "";
  769. doShowMessageInTheArea(app, msg1, msg2, altText, "javafx-chrome.png", onClickFunc);
  770. actionLabel = app.id + "-embed";
  771. } else {
  772. v.jre = "blocked";
  773. reportPlatformError(app, v, cb);
  774. actionLabel = "launch"; //we only queue ONE webstart launch.
  775. //Do not want to try to queue different apps - bad UE
  776. // (once user enable multiple things can spawn)
  777. //Note: what if multiple webstart apps are set to launch on page load (suer do not need to click)?
  778. // Guess do not worry for now
  779. //Note: app.id may be null in case of webstart app.
  780. }
  781. //now we need to start waiter. Once DT is initialized we can proceeed
  782. var retryFunc = function() {
  783. var vnew = doValidateRelaxed(platform);
  784. if (vnew == null) { //no problems with env
  785. launchFunction();
  786. } else {
  787. resolveAndLaunch(app, platform, vnew, cb, launchFunction);
  788. }
  789. };
  790. runUsingDT(actionLabel, retryFunc);
  791. return;
  792. }
  793. if (!v.isUnsupportedPlatform() && !v.isUnsupportedBrowser()) { //otherwise fatal, at least until restart of browser
  794. if (isMissingComponent(v) && isDef(cb.onInstallNeeded)) {
  795. var resolveFunc= function() {
  796. //once install is over we need to revalidate
  797. var vnew = doValidateRelaxed(platform);
  798. if (vnew == null) { //if no problems found - can launch
  799. launchFunction();
  800. } else { //TODO: what happens if we installed everything but relaunch is needed??
  801. //We can not get here if component install was not offered for any or missing componens
  802. //(if auto install was possible, see doInstall() implementation)
  803. //Hence, it is safe to assume we failed to meet requirements
  804. reportPlatformError(app, vnew, cb);
  805. //TODO: may be should call itself again but
  806. // then it easy can become infinite loop
  807. //e.g. user installs but we fail to detect it because DT
  808. // is not FX aware and retry, etc.
  809. //TODO: think it through
  810. }
  811. };
  812. cb.onInstallNeeded(app, platform, cb,
  813. v.canAutoInstall(), v.isRelaunchNeeded(), resolveFunc);
  814. return;
  815. }
  816. }
  817. reportPlatformError(app, v, cb);
  818. }
  819. function haveDTLite() {
  820. // IE does not support DTLite
  821. if (ua.deploy != null && !ua.ie) {
  822. return versionCheck("10.6+", ua.deploy, false);
  823. }
  824. return false;
  825. }
  826. function isDTLiteInitialized(p) {
  827. //if plugin is blocked then p.version will be undefined
  828. return p != null && isDef(p.version);
  829. }
  830. function getDTLitePlugin() {
  831. return document.getElementById("dtlite");
  832. }
  833. function doInjectDTLite() {
  834. //do not want more than one plugin
  835. if (getDTLitePlugin() != null) return;
  836. var p = document.createElement('embed');
  837. p.width = '10px';
  838. p.height = '10px';
  839. p.id = "dtlite";
  840. p.type = "application/x-java-applet"; //means we get latest
  841. var div = document.createElement("div");
  842. div.style.position = "relative";
  843. div.style.left = "-10000px";
  844. div.appendChild(p);
  845. var e = document.getElementsByTagName("body");
  846. e[0].appendChild(div);
  847. }
  848. function runUsingDTLite(f) {
  849. // Possible situations:
  850. // a) first request, plugin is not in the DOM tree yet
  851. // - add plugin
  852. // - setup wait mechanism and run f() once plugin is ready
  853. // b) plugin is live and we can simply run code
  854. // - just run the code
  855. // c) plugin is in the DOM tree but it is not initialized yet (e.g. Chrome blocking)
  856. // and there is live timer (pendingCount > 0)
  857. // - there could be another request. We will override it (e.g. user clicked multiple times)
  858. // - renew timer life counter (do not want new timer)
  859. // d) plugin is in the DOM tree and it is not fully initialized yet but timer is stopped
  860. // - overwrite old request
  861. // - restart timer
  862. //
  863. // Problem:
  864. // when plugin is ready to serve request? How do we schedule call to happen when plugin is initialized?
  865. // Caveat:
  866. // Chrome can popup dialog asking user to grant permissions to load the plugin.
  867. // There is no API to detect dialog is shown and when user grants or declines permissions
  868. //
  869. // Note:
  870. // If we set property on plugin object before it is unblocked then they seem to be lost
  871. // and are not propagated to the final object once it is instantiated.
  872. //
  873. // Workaround we use:
  874. // Once plugin is added we will be checking if it is initialized and once we detect it we will execute code.
  875. // We will stop checking after some time.
  876. var p = getDTLitePlugin();
  877. if (p == null) {
  878. doInjectDTLite();
  879. p = getDTLitePlugin();
  880. }
  881. if (isDTLiteInitialized(p)) {
  882. f(p);
  883. } else {
  884. // see if we need new timer
  885. var waitAndUse = null;
  886. if (!isDef(dtjava.dtlitePendingCnt) || dtjava.dtlitePendingCnt == 0) {
  887. waitAndUse = function () {
  888. if (isDef(p.version)) {
  889. if (dtjava.pendingLaunch != null) {
  890. dtjava.pendingLaunch(p);
  891. }
  892. dtjava.pendingLaunch = null;
  893. return;
  894. }
  895. if (dtjava.dtlitePendingCnt > 0) {
  896. dtjava.dtlitePendingCnt--;
  897. setTimeout(waitAndUse, 500);
  898. }
  899. }
  900. }
  901. //add new task in queue
  902. dtjava.pendingLaunch = f;
  903. //reset the timer counter
  904. dtjava.dtlitePendingCnt = 1000; //timer is gone after 500s
  905. //start timer if needed
  906. if (waitAndUse != null) {
  907. waitAndUse();
  908. }
  909. }
  910. }
  911. function doLaunchUsingDTLite(app, jvmargs, cb) {
  912. var launchIt = function() {
  913. var pp = getDTLitePlugin();
  914. if (pp == null) {
  915. //should not be possible as we guard before enter this function
  916. if (isDef(cb.onRuntimeError)) {
  917. cb.onRuntimeError(app.id);
  918. }
  919. }
  920. //DTLite only support new invocation API
  921. // obj.launchApp({"url" : "http://somewhere/my.jnlp",
  922. // "jnlp_content" : "... BASE 64 ...",
  923. // "vmargs" : [ "-ea -Djnlp.foo=bar"
  924. // "appargs" : [ "first arg, second arg" ]
  925. // "params" : {"p1" : "aaa", "p2" : "bbb"}});
  926. var callArgs = {"url" : app.url};
  927. if (notNull(jvmargs)) {
  928. callArgs["vmargs"] = jvmargs;
  929. }
  930. //Only use HTML parameters, they are supposed to overwrite values in the JNLP
  931. //In the future we want to pass arguments too but this needs also be exposed for
  932. // embedded deployment
  933. if (notNull(app.params)) {
  934. //copy over and ensure all values are stings
  935. // (native code will ignore them otherwise)
  936. var ptmp = {};
  937. for (var k in app.params) {
  938. ptmp[k] = String(app.params[k]);
  939. }
  940. callArgs["params"] = ptmp;
  941. }
  942. if (notNull(app.jnlp_content)) {
  943. callArgs["jnlp_content"] = app.jnlp_content;
  944. }
  945. var err = pp.launchApp(callArgs);
  946. if (err == 0) { //0 - error
  947. if (isDef(cb.onRuntimeError)) {
  948. cb.onRuntimeError(app.id);
  949. }
  950. }
  951. };
  952. if (versionCheck("10.4+", ua.deploy, false)) { //only for NPAPI browsers
  953. runUsingDTLite(launchIt);
  954. return true;
  955. }
  956. return false;
  957. }
  958. function getWebstartObject(jnlp) {
  959. var wo = null;
  960. if (ua.ie) { //TODO: attempt to use object in FF 3.6 lead to hang. Revert to embed for now
  961. //TODO: Should Chrome use object?
  962. //object tag itself
  963. wo = d.createElement('object');
  964. wo.width = '1px'; //zero size reports invalid argument in IE!
  965. wo.height = '1px'; //TODO: make it less distruptive to page layout? hide div?
  966. var p = d.createElement('param');
  967. p.name = 'launchjnlp';
  968. p.value = jnlp;
  969. wo.appendChild(p);
  970. p = d.createElement('param');
  971. p.name = 'docbase';
  972. p.value = notNull(d.documentURI) ? d.documentURI : d.URL;
  973. wo.appendChild(p);
  974. if (!ua.ie) {
  975. //NB:do not need to use exact version in mime type as generic should be mapped to latest?
  976. wo.type = "application/x-java-applet;version=1.7";
  977. } else {
  978. wo.classid = "clsid:8AD9C840-044E-11D1-B3E9-00805F499D93";
  979. }
  980. } else { //TODO: else part should go away once we figure out what is going on with FF
  981. wo = d.createElement('embed');
  982. wo.width = '0px';
  983. wo.height = '0px';
  984. //NB: dot notation did not work for custom attributes??? revert to setAttribute
  985. wo.setAttribute('launchjnlp', jnlp);
  986. wo.setAttribute('docbase', (notNull(d.documentURI) ? d.documentURI : d.URL));
  987. //NB:do not need to use exact version in mime type as generic should be mapped to latest?
  988. wo.type = "application/x-java-applet;version=1.7";
  989. }
  990. var div = d.createElement("div");
  991. div.style.position = "relative";
  992. div.style.left = "-10000px";
  993. div.appendChild(wo);
  994. return div;
  995. }
  996. // Version class. The argument VersionString is a valid version string and
  997. // UpgradeFromOldJavaVersion is optional true/false.
  998. var Match = {
  999. Exact: {value: 0}, // exact version
  1000. Family: {value: 1}, // Example: 1.7* only matches 1.7.X family
  1001. Above: {value: 2} // Example: 1.7+ matches 1.7 and above
  1002. };
  1003. var Token = {
  1004. Uninitialized: {value: -2},
  1005. Unknown: {value: -1},
  1006. Identifier: {value: 0},
  1007. Alpha: {value: 1},
  1008. Digits: {value: 2},
  1009. Plus: {value: 3},
  1010. Minus: {value: 4},
  1011. Underbar: {value: 5},
  1012. Star: {value: 6},
  1013. Dot: {value: 7},
  1014. End: {value: 8}
  1015. };
  1016. var Version = function(VersionString, UpgradeFromOldJavaVersion) {
  1017. if (typeof UpgradeFromOldJavaVersion === 'undefined') {
  1018. var UpgradeFromOldJavaVersion = true;
  1019. }
  1020. // Constants
  1021. var MAX_DIGITS = 4;
  1022. // Private
  1023. var FVersionString = null;
  1024. var FOld = false;
  1025. var FVersion = null;
  1026. var FBuild = null;
  1027. var FPre = null;
  1028. var FMatch = null;
  1029. var FMajor = null;
  1030. var FMinor = null;
  1031. var FSecurity = null;
  1032. var FPatch = null;
  1033. // Class constructor
  1034. if (!VersionString) {
  1035. return null;
  1036. }
  1037. else {
  1038. FVersionString = VersionString;
  1039. var v = parseAndSplitVersionString(VersionString, UpgradeFromOldJavaVersion)
  1040. FOld = v.old;
  1041. FVersion = v.version;
  1042. FBuild = v.build;
  1043. FMatch = v.match;
  1044. FPre = v.pre;
  1045. var parts = splitVersion(v.version);
  1046. FMajor = parts.major;
  1047. FMinor = parts.minor;
  1048. FSecurity = parts.security;
  1049. FPatch = parts.patch;
  1050. }
  1051. // Public
  1052. return {
  1053. VersionString: VersionString,
  1054. old: FOld,
  1055. major: FMajor,
  1056. minor: FMinor,
  1057. security: FSecurity,
  1058. patch: FPatch,
  1059. version: FVersion,
  1060. build: FBuild,
  1061. pre: FPre,
  1062. match: FMatch,
  1063. check: function(query) {
  1064. return check(query, this);
  1065. },
  1066. equals: function(query) {
  1067. return equals(query, this);
  1068. }
  1069. };
  1070. // Private
  1071. function splitVersion(version) {
  1072. var lmajor = null;
  1073. var lminor = null;
  1074. var lsecurity = null;
  1075. var lpatch = null;
  1076. if (version.length >= 1) {
  1077. lmajor = version[0];
  1078. }
  1079. if (version.length >= 2) {
  1080. lminor = version[1];
  1081. }
  1082. if (version.length >= 3) {
  1083. lsecurity = version[2];
  1084. }
  1085. if (version.length >= 4) {
  1086. lpatch = version[3];
  1087. }
  1088. return {
  1089. major: lmajor,
  1090. minor: lminor,
  1091. security: lsecurity,
  1092. patch: lpatch
  1093. };
  1094. }
  1095. function VersionStringTokenizer(versionString) {
  1096. // Convert the version string to lower case and strip all whitespace
  1097. // from the beginning and end of the string.
  1098. var FVersionString = versionString.toLowerCase().trim();
  1099. var FIndex;
  1100. var FCurrentToken = null;
  1101. var FStack = Array();
  1102. function isDigit(c) {
  1103. var result = false;
  1104. switch(c) {
  1105. case '0':
  1106. case '1':
  1107. case '2':
  1108. case '3':
  1109. case '4':
  1110. case '5':
  1111. case '6':
  1112. case '7':
  1113. case '8':
  1114. case '9':
  1115. result = true;
  1116. break;
  1117. }
  1118. return result;
  1119. }
  1120. function isLetter(c) {
  1121. //return c.match("^[a-zA-Z]");
  1122. var result = false;
  1123. var lowerBoundLower = "a".charCodeAt(0);
  1124. var upperBoundLower = "z".charCodeAt(0);
  1125. var bound = c.charCodeAt(0);
  1126. if (lowerBoundLower <= bound && bound <= upperBoundLower) {
  1127. result = true;
  1128. }
  1129. return result;
  1130. }
  1131. function start() {
  1132. FIndex = 0;
  1133. }
  1134. function currentToken() {
  1135. return FCurrentToken;
  1136. }
  1137. function pushToken(Token) {
  1138. if (FCurrentToken != null) {
  1139. FStack.unshift(FCurrentToken);
  1140. }
  1141. FCurrentToken = Token;
  1142. }
  1143. function nextToken() {
  1144. var tokenID = Token.Uninitialized;
  1145. var token = '';
  1146. if (FStack.length > 0) {
  1147. tokenID = FStack[0].tokenID;
  1148. token = FStack[0].token;
  1149. FStack.shift();
  1150. }
  1151. else {
  1152. if (FIndex >= FVersionString.length) {
  1153. tokenID = Token.End;
  1154. }
  1155. else {
  1156. while (FIndex < FVersionString.length) {
  1157. var c = FVersionString.charAt(FIndex);
  1158. if ((tokenID == Token.Uninitialized || tokenID == Token.Alpha) &&
  1159. isLetter(c) == true) {
  1160. tokenID = Token.Alpha;
  1161. FIndex++;
  1162. token += c;
  1163. }
  1164. else if ((tokenID == Token.Uninitialized || tokenID == Token.Digits) &&
  1165. isDigit(c) == true) {
  1166. if (parseInt(c) == 0 && parseInt(token) == 0) {
  1167. tokenID = Token.Unknown;
  1168. token += c;
  1169. FIndex++;
  1170. break;
  1171. }
  1172. else {
  1173. tokenID = Token.Digits;
  1174. token += c;
  1175. FIndex++;
  1176. }
  1177. }
  1178. else if ((tokenID == Token.Alpha || tokenID == Token.Identifier) &&
  1179. isDigit(c) == true &&
  1180. isLetter(c) == false) {
  1181. tokenID = Token.Identifier;
  1182. FIndex++;
  1183. token += c;
  1184. }
  1185. else if (tokenID == Token.Uninitialized) {
  1186. switch(c) {
  1187. case '-':
  1188. tokenID = Token.Minus;
  1189. FIndex++;
  1190. token = c;
  1191. break;
  1192. case '+':
  1193. tokenID = Token.Plus;
  1194. FIndex++;
  1195. token = c;
  1196. break;
  1197. case '*':
  1198. tokenID = Token.Star;
  1199. FIndex++;
  1200. token = c;
  1201. break;
  1202. case '.':
  1203. tokenID = Token.Dot;
  1204. FIndex++;
  1205. token = c;
  1206. break;
  1207. case '_':
  1208. tokenID = Token.Underbar;
  1209. FIndex++;
  1210. token = c;
  1211. break;
  1212. default:
  1213. tokenID = Token.Unknown;
  1214. FIndex++;
  1215. break;
  1216. }
  1217. break;
  1218. }
  1219. else {
  1220. break;
  1221. }
  1222. }
  1223. }
  1224. }
  1225. FCurrentToken = {
  1226. token: token,
  1227. tokenID: tokenID
  1228. }
  1229. return FCurrentToken;
  1230. }
  1231. return {
  1232. start: start,
  1233. nextToken: nextToken,
  1234. pushToken: pushToken,
  1235. currentToken: currentToken,
  1236. isDigit: isDigit,
  1237. isLetter: isLetter
  1238. }
  1239. }
  1240. function VersionStringParser() {
  1241. function readDigits(Tokenizer) {
  1242. var result = new Array();
  1243. var token = Tokenizer.currentToken();
  1244. if (token.tokenID == Token.Digits) {
  1245. result.push(parseInt(token.token));
  1246. token = Tokenizer.nextToken();
  1247. // Read up to 3 more digits.
  1248. for (var index = 0; index < (MAX_DIGITS - 1); index++) {
  1249. if (token.tokenID == Token.Dot) {
  1250. token = Tokenizer.nextToken();
  1251. if (token.tokenID == Token.Digits) {
  1252. result.push(parseInt(token.token));
  1253. token = Tokenizer.nextToken();
  1254. }
  1255. else if (token.tokenID == Token.Star ||
  1256. token.tokenID == Token.Plus) {
  1257. break;
  1258. }
  1259. else {
  1260. result = null;
  1261. break;
  1262. }
  1263. }
  1264. else if (token.tokenID == Token.Star ||
  1265. token.tokenID == Token.Plus ||
  1266. token.tokenID == Token.End ||
  1267. token.tokenID == Token.Minus ||
  1268. token.tokenID == Token.Underbar ||
  1269. token.tokenID == Token.Identifier ||
  1270. (token.tokenID == Token.Alpha && token.token == 'u')) {
  1271. break;
  1272. }
  1273. else {
  1274. result = null;
  1275. break;
  1276. }
  1277. }
  1278. }
  1279. return result;
  1280. }
  1281. function readMatch(Tokenizer, Old) {
  1282. var result = Match.Exact;
  1283. var token = Tokenizer.currentToken();
  1284. if (token.tokenID == Token.Dot) {
  1285. token = Tokenizer.nextToken();
  1286. if (token.tokenID == Token.Star) {
  1287. result = Match.Family;
  1288. Tokenizer.nextToken();
  1289. }
  1290. else if (token.tokenID == Token.Plus) {
  1291. result = Match.Above;
  1292. Tokenizer.nextToken();
  1293. }
  1294. }
  1295. else if (token.tokenID == Token.Star) {
  1296. result = Match.Family;
  1297. Tokenizer.nextToken();
  1298. }
  1299. else if (token.tokenID == Token.Plus) {
  1300. result = Match.Above;
  1301. Tokenizer.nextToken();
  1302. }
  1303. return result;
  1304. }
  1305. function readPre(Tokenizer) {
  1306. var result = null;
  1307. var token = Tokenizer.currentToken();
  1308. if (token.tokenID == Token.Minus) {
  1309. var savedToken = token;
  1310. var token = Tokenizer.nextToken();
  1311. if (token.tokenID == Token.Alpha) {
  1312. result = token.token;
  1313. Tokenizer.nextToken();
  1314. }
  1315. else {
  1316. Tokenizer.pushToken(savedToken);
  1317. }
  1318. }
  1319. return result;
  1320. }
  1321. function readBuild(Tokenizer, Old) {
  1322. var result = null;
  1323. var token = Tokenizer.currentToken();
  1324. if (token.tokenID == Token.Plus) {
  1325. // The new version spec has build number prepended with a "+":
  1326. // RegEx: +([1-9][0-9]*)
  1327. var savedToken = token;
  1328. var token = Tokenizer.nextToken();
  1329. if (token.tokenID == Token.Digits) {
  1330. result = parseInt(token.token);
  1331. Tokenizer.nextToken();
  1332. }
  1333. else {
  1334. Tokenizer.pushToken(savedToken);
  1335. }
  1336. }
  1337. else if (Old == true) {
  1338. // The old version spec has build number prepended with a "-b"
  1339. // RegEx: -b([1-9][0-9]*)
  1340. if (token.tokenID == Token.Minus || token.tokenID == Token.Underbar) {
  1341. var savedToken = token;
  1342. token = Tokenizer.nextToken();
  1343. if (token.tokenID == Token.Identifier && token.token[0] == 'b') {
  1344. var builderNumber = parseInt(token.token.substr(1));
  1345. if (builderNumber != null && isNaN(builderNumber) == false) {
  1346. Tokenizer.nextToken();
  1347. result = builderNumber;
  1348. }
  1349. }
  1350. else {
  1351. Tokenizer.pushToken(savedToken);
  1352. }
  1353. }
  1354. }
  1355. return result;
  1356. }
  1357. // isOldUpdate determines if the version string is in the old
  1358. // short format. For Example: 8u60
  1359. function isOldUpdate(version, token) {
  1360. var result = false;
  1361. if (version.length == 1 &&
  1362. parseInt(version[0]) <= 8 &&
  1363. token.tokenID == Token.Identifier &&
  1364. token.token.length > 0 &&
  1365. token.token.charAt(0) == "u") {
  1366. result = true;
  1367. }
  1368. return result;
  1369. }
  1370. // Only call this function if isOldUpdate() returns true.
  1371. function readOldUpdate(Tokenizer) {
  1372. var result = null;
  1373. var token = Tokenizer.currentToken();
  1374. if (token.tokenID == Token.Identifier) {
  1375. result = parseInt(token.token.substr(1));
  1376. Tokenizer.nextToken();
  1377. }
  1378. else if (token.tokenID == Token.Star) {
  1379. lmatch = Match.Family;
  1380. Tokenizer.nextToken();
  1381. }
  1382. else if (token.tokenID == Token.Plus) {
  1383. lmatch = Match.Above;
  1384. Tokenizer.nextToken();
  1385. }
  1386. return result;
  1387. }
  1388. function readOpt(Tokenizer) {
  1389. var result = null;
  1390. var token = Tokenizer.currentToken();
  1391. if (token.tokenID == Token.Alpha) {
  1392. result = token.token;
  1393. Tokenizer.nextToken();
  1394. }
  1395. return result;
  1396. }
  1397. function parse(Tokenizer) {
  1398. var result = null;
  1399. var success = false;
  1400. var lold = false;
  1401. var lversion = null;
  1402. var lbuild = null;
  1403. var lmatch = Match.Exact;
  1404. var lpre = false;
  1405. var lopt = null;
  1406. Tokenizer.start();
  1407. var token = Tokenizer.nextToken();
  1408. if (token.tokenID == Token.Digits) {
  1409. lversion = readDigits(Tokenizer);
  1410. if (lversion != null && lversion.length > 0) {
  1411. token = Tokenizer.currentToken();
  1412. if (lversion[0] == 1) {
  1413. if (lversion.length >= 2 && lversion[1] == 9) {
  1414. return null;
  1415. }
  1416. lold = true;
  1417. }
  1418. else if (token.token == "u") {
  1419. // Special case. For Example: 8u*
  1420. token = Tokenizer.nextToken();
  1421. }
  1422. if (isOldUpdate(lversion, token) == true) {
  1423. lold = true;
  1424. var value = readOldUpdate(Tokenizer);
  1425. if (value != null) {
  1426. token = Tokenizer.currentToken();
  1427. lversion.push(parseInt(value));
  1428. lold = true;
  1429. if (token.tokenID == Token.End) {
  1430. success = true;
  1431. }
  1432. else {
  1433. lmatch = readMatch(Tokenizer);
  1434. token = Tokenizer.currentToken();
  1435. if (token.tokenID == Token.End) {
  1436. success = true;
  1437. }
  1438. }
  1439. }
  1440. }
  1441. else {
  1442. token = Tokenizer.currentToken();
  1443. if (lold == true && token.tokenID == Token.Underbar) {
  1444. token = Tokenizer.nextToken();
  1445. if (token.tokenID == Token.Digits && lversion.length < MAX_DIGITS) {
  1446. lversion.push(parseInt(token.token));
  1447. Tokenizer.nextToken();
  1448. }
  1449. }
  1450. lpre = readPre(Tokenizer);
  1451. token = Tokenizer.currentToken();
  1452. lbuild = readBuild(Tokenizer, lold);
  1453. lopt = readOpt(Tokenizer);
  1454. lmatch = readMatch(Tokenizer, lold);
  1455. token = Tokenizer.currentToken();
  1456. if (token.tokenID == Token.End) {
  1457. success = true;
  1458. }
  1459. }
  1460. if (success == true) {
  1461. result = {
  1462. old: lold,
  1463. version: lversion,
  1464. build: lbuild,
  1465. match: lmatch,
  1466. pre: lpre,
  1467. opt: lopt
  1468. };
  1469. }
  1470. }
  1471. }
  1472. return result;
  1473. }
  1474. return {
  1475. parse: parse
  1476. }
  1477. }
  1478. function parseAndSplitVersionString(versionString, UpgradeFromOldJavaVersion) {
  1479. var lold = false;
  1480. var lversion = new Array;
  1481. var lbuild = null;
  1482. var lmatch = null;
  1483. var lpre = false;
  1484. var lopt = null;
  1485. // Corner case inputs.
  1486. if (versionString == null || versionString.length == 0) {
  1487. lversion = [0, 0, 0, 0];
  1488. }
  1489. else {
  1490. var tokenizer = VersionStringTokenizer(versionString);
  1491. var parser = VersionStringParser();
  1492. var result = parser.parse(tokenizer);
  1493. if (result != null) {
  1494. if (UpgradeFromOldJavaVersion == true &&
  1495. result.old == true) {
  1496. if (result.version.length > 0 &&
  1497. result.version[0] == 1) {
  1498. lversion = result.version.splice(1, result.version.length - 1);
  1499. }
  1500. else {
  1501. lversion = result.version;
  1502. }
  1503. lold = true;
  1504. }
  1505. else {
  1506. lversion = result.version;
  1507. }
  1508. lbuild = result.build;
  1509. lmatch = result.match;
  1510. lpre = result.pre;
  1511. }
  1512. }
  1513. return {
  1514. old: lold,
  1515. version: lversion,
  1516. build: lbuild,
  1517. match: lmatch,
  1518. pre: lpre,
  1519. opt: lopt
  1520. };
  1521. }
  1522. function sameVersion(query, version) {
  1523. var result = false;
  1524. var lquery = query;
  1525. if (lquery == null)
  1526. lquery = 0;
  1527. if (parseInt(lquery) == parseInt(version)) {
  1528. result = true;
  1529. }
  1530. return result;
  1531. }
  1532. // compareVersionExact comparison returns true only if query and version are
  1533. // exact matches.
  1534. function compareVersionExact(query, version) {
  1535. var result = false;
  1536. if ((query.major != null) &&
  1537. (version.major != null) &&
  1538. sameVersion(query.major, version.major) &&
  1539. sameVersion(query.minor, version.minor) &&
  1540. sameVersion(query.security, version.security) &&
  1541. sameVersion(query.patch, version.patch) &&
  1542. (query.old == version.old) &&
  1543. (query.pre == version.pre) &&
  1544. ((parseInt(query.build) == parseInt(version.build)) || (query.build == null && version.build == null))) {
  1545. result = true;
  1546. }
  1547. return result;
  1548. }
  1549. // compareVersionFamily comparison is for the * wild card for the current query
  1550. // version and anything above within the current version. For Example:
  1551. // 1.7* will match 1.7.8.9 but not 1.8.
  1552. function compareVersionFamily(query, version) {
  1553. var result = false;
  1554. // There is a subtle corner case comparison when comparing:
  1555. // 1.* to 1.8 (success)
  1556. // 1.* to 9.0 (fail)
  1557. // In this case, if both strings are old that means we have a 1s, so
  1558. // since the query string is all 0s, or empty, we have a match.
  1559. if (query.old == true && query.version.length == 0 && version.old == true) {
  1560. result = true;
  1561. }
  1562. else {
  1563. // All elements must match on the query version array.
  1564. for (index = 0 ;index < query.version.length && index < version.version.length;
  1565. index++) {
  1566. var q = query.version[index];
  1567. var v = version.version[index];
  1568. if (parseInt(q) == parseInt(v)) {
  1569. result = true;
  1570. }
  1571. else {
  1572. result = false;
  1573. break;
  1574. }
  1575. }
  1576. }
  1577. return result;
  1578. }
  1579. // compareVersionAbove comparison is for the + wild card for the current query
  1580. // version and anything above returning true.
  1581. function compareVersionAbove(query, version) {
  1582. var result = false;
  1583. if (query.old == true && query.version.length == 0) {
  1584. result = true;
  1585. }
  1586. else if (query.old == true && version.old == false) {
  1587. result = true;
  1588. }
  1589. else if (query.major == 0) {
  1590. result = true;
  1591. }
  1592. else if ((query.major != null) &&
  1593. (version.major != null) &&
  1594. ((parseInt(query.build) == parseInt(version.build)) || (query.build == null && version.build == null))) {
  1595. for (var index = 0; index < query.version.length; index++) {
  1596. var q = query.version[index];
  1597. var v = version.version[index];
  1598. if (parseInt(q) == parseInt(v)) {
  1599. result = true;
  1600. }
  1601. else if (parseInt(q) < parseInt(v)) {
  1602. if ((query.old == true && version.old == true) ||
  1603. (query.old == false && version.old == false)) {
  1604. result = true;
  1605. }
  1606. break;
  1607. }
  1608. else {
  1609. result = false;
  1610. break;
  1611. }
  1612. }
  1613. }
  1614. return result;
  1615. }
  1616. // cloneAndCompleteVersionInfo is an internal method. It makes a copy of the
  1617. // version structure and completes the version array to contain four elements.
  1618. function cloneAndCompleteVersionInfo(version) {
  1619. var clone_version = version.version.slice(0);
  1620. // The source version string must be a complete version string (four digits).
  1621. // Example: 9.0.0.0
  1622. for (var index = clone_version.length; index < 4 ; index++) {
  1623. clone_version.push(0);
  1624. }
  1625. var parts = splitVersion(clone_version);
  1626. return {
  1627. old: version.old,
  1628. major: parts.major,
  1629. minor: parts.minor,
  1630. security: parts.security,
  1631. patch: parts.patch,
  1632. version: clone_version,
  1633. build: version.build,
  1634. pre: version.pre
  1635. };
  1636. }
  1637. // Check performs a deploy pattern match comparison and returns
  1638. // true if the comparing version matches false if not.
  1639. function check(query, version) {
  1640. var result = false;
  1641. if (query.VersionString == null || query.VersionString.length == 0) {
  1642. result = true;
  1643. }
  1644. else {
  1645. if (query.build == null && version.build == null) {
  1646. var lversion = cloneAndCompleteVersionInfo(version);
  1647. if (query.match == Match.Exact) {
  1648. result = compareVersionExact(query, lversion);
  1649. }
  1650. else if (query.match == Match.Family) {
  1651. result = compareVersionFamily(query, lversion);
  1652. }
  1653. else if (query.match == Match.Above) {
  1654. result = compareVersionAbove(query, lversion);
  1655. }
  1656. }
  1657. }
  1658. return result;
  1659. }
  1660. // Performs a comparison on the two version string arguments and returns
  1661. // true if the comparing version matches false if not.
  1662. function equals(value, version) {
  1663. var result = false;
  1664. if (query.VersionString == null || query.VersionString.length == 0) {
  1665. result = true;
  1666. }
  1667. else {
  1668. var lversion = cloneAndCompleteVersionInfo(version);
  1669. var lquery = cloneAndCompleteVersionInfo(query);
  1670. result = compareVersionExact(lquery, lversion);
  1671. }
  1672. return result;
  1673. }
  1674. };
  1675. // Compares two version strings: query and version, matching query against version. query
  1676. // is allowed to have wild cards + and * version is not. The argument UpgradeFromOldJavaVersion
  1677. // is optional. This will remove the 1 prefix if present and mark the old field in the structure
  1678. // that is passed around.
  1679. function versionCheck(query, version, UpgradeFromOldJavaVersion) {
  1680. var q = new Version(query, UpgradeFromOldJavaVersion);
  1681. var v = new Version(version, UpgradeFromOldJavaVersion);
  1682. return v.check(q);
  1683. }
  1684. // This is similar to version check rules except there is a range
  1685. // over versions (3-7) that are not valid.
  1686. //
  1687. // JavaFX version requirements are always treated as "not earlier than this update".
  1688. // I.e. we expect
  1689. // 2.2.0 to match 2.2*, 2.2+, 2.1+, 2.1*, 2.0 and 1+
  1690. // but not match 2.2.1+, 2.2.1*, 2.3*, 2.3+ or 1*
  1691. function versionCheckFX(query, version) {
  1692. var q = new Version(query, false);
  1693. if (parseInt(q.major) >= 3 && parseInt(q.major) <= 7 && query.substr(-1) !== "+") {
  1694. return false;
  1695. }
  1696. if (q.match == Match.Exact) {
  1697. q = new Version(query + "+", false);
  1698. }
  1699. var v = new Version(version, false);
  1700. return v.check(q);
  1701. }
  1702. //as JavaFX comes with own plugin binaries then check based on mime types, etc.
  1703. // may be false positive as it only checks for plugin version, not real JRE
  1704. //Here we check that DT plugin is aware of JRE installations
  1705. //Note that:
  1706. // - if DT is not available we will return false but we only do this i
  1707. // ready to launch => DT must be found
  1708. // - we do not want to check in jreCheck() as we want to avoid loading
  1709. // DT plugin if we can (as old DT may make it not possible to autostart)
  1710. function doublecheckJrePresence() {
  1711. if (!haveDTLite()) { //basically IE on windows or Old JRE on windows
  1712. if (postponeNativePluginInstallation && notNull(d.body)) {
  1713. // Native Plugin installation was postponed, as the page didn't have
  1714. // body at that time. Try to install the plugin now.
  1715. installNativePlugin();
  1716. postponeNativePluginInstallation = false;
  1717. }
  1718. var p = getPlugin();
  1719. if (p != null) {
  1720. return true;
  1721. //WORKAROUND: bug in native DT!!! TODO: What version? bypass for it only
  1722. //return (p.jvms.getLength() > 0);
  1723. }
  1724. return false;
  1725. }
  1726. //if we are not using native DT plugin (i.e. using DTLite) then no way we can do sanity check
  1727. // => assume first check is accurate
  1728. return true;
  1729. }
  1730. function jreCheck(jre) {
  1731. // Check if latest JRE is exposed in mimetype and if it is good enough (only for NPAPI browsers)
  1732. if (ua.jre != null) {
  1733. if (versionCheck(jre, ua.jre)) {
  1734. return "ok";
  1735. }
  1736. //Note: if we have JRE but it is not match that means we may need an upgrade message
  1737. // but we still could be able to get more accurate answer with native DT plugin
  1738. }
  1739. //try to use DT plugin
  1740. var p = getPlugin();
  1741. if (p != null) {
  1742. var VMs = p.jvms;
  1743. for (var i = 0; VMs != null && i < VMs.getLength(); i++) {
  1744. if (versionCheck(jre, VMs.get(i).version)) {
  1745. if (!ua.ie && notNull(navigator.mimeTypes)) {
  1746. //if mime types are available but plugin is not there =>
  1747. // it is disabled
  1748. if (!notNull(navigator.mimeTypes["application/x-java-applet"])) {
  1749. return "disabled";
  1750. }
  1751. }
  1752. return "ok";
  1753. }
  1754. }
  1755. //do not need to try other ways if used DT
  1756. return "none";
  1757. }
  1758. //No full DT => On Windows we can not launch FX anyways
  1759. // but may have old JRE
  1760. //And we might be able to launch on Mac/Linux
  1761. //This is only IE on Windows. This gives no update version. only e.g. 1.6.0
  1762. //and also cause java plugin to be loaded => browser will need to be restarted
  1763. //if new JRE is installed.
  1764. //However, if we got here than DT is not available and autoinstall is not possible
  1765. if (ua.ie) {
  1766. var lst = ["1.8.0", "1.7.0", "1.6.0", "1.5.0"];
  1767. for (var v = 0; v < lst.length; v++) {
  1768. if (versionCheck(jre, lst[v])) {
  1769. try {
  1770. //TODO: FIXME: This does not seem to work in my testing in IE7?
  1771. var axo = new ActiveXObject("JavaWebStart.isInstalled." + lst[v] + ".0");
  1772. // This is not hit if the above throws an exception.
  1773. return "ok";
  1774. } catch (ignored) {
  1775. }
  1776. }
  1777. }
  1778. }
  1779. return "none";
  1780. }
  1781. function checkJRESupport() {
  1782. //Negative test. New platforms will not be rejected
  1783. var osProblem = ['iPhone', 'iPod'];
  1784. var os = containsAny(osProblem, navigator.userAgent);
  1785. //Do not support Chrome/Mac as Chrome is 32 bit only
  1786. var browser = (ua.mac && ua.chrome && ua.cputype == "intel");
  1787. //autoinstall possible if native plugin is detected or OS is fine
  1788. auto = os || (getPlugin() != null);
  1789. //false is no problem found
  1790. return {os: os, browser: browser, auto: auto};
  1791. }
  1792. //it is not clear if we can work in IE6
  1793. // but it is hard to test and JRE7 does not even support it
  1794. // mark as unsupported for now
  1795. function isUnsupportedVersionOfIE() {
  1796. if (ua.ie) {
  1797. try {
  1798. //these functions are defined in IE only
  1799. var v = 10*ScriptEngineMajorVersion() + ScriptEngineMinorVersion();
  1800. if (v < 57) return true; //IE7 will have 57
  1801. } catch (err) {
  1802. //really old IE?
  1803. return true;
  1804. }
  1805. }
  1806. return false;
  1807. }
  1808. function checkFXSupport() {
  1809. var browser;
  1810. if (ua.win) {
  1811. //do not support Opera and Safari
  1812. // (not really tested, may be it works but known to have problems with DT detection)
  1813. browser = ua.op || ua.wk || isUnsupportedVersionOfIE();
  1814. //false is no problem found
  1815. return {os: false, browser: browser};
  1816. } else if (ua.mac && ua.cputype == "intel") { //do not support PPC/iphone/ipad ...
  1817. var os = !versionCheck("10.7.3+", ua.osVersion, false); //10.7.3 or later!
  1818. browser = ua.op ||
  1819. (ua.mac && ua.chrome); //Opera is not supported
  1820. //Chrome on Mac is 32 bit => plugin only work in 64 bit ...
  1821. //TODO: How do we detect FF running in 32 bit mode?
  1822. //false is no problem found
  1823. return {os: os, browser: browser};
  1824. } else if (ua.linux) {
  1825. browser = ua.op; //Opera unsupported
  1826. //false is no problem found
  1827. return {os: false, browser: browser};
  1828. } else {
  1829. //unknown unsupported OS
  1830. return {os: true, browser: false};
  1831. }
  1832. }
  1833. function relaxVersion(v) {
  1834. if (notNull(v) && v.length > 0) {
  1835. var c = v.charAt(v.length - 1);
  1836. if (c == '*') {
  1837. v = v.substring(0, v.length - 1)+"+";
  1838. } else if (c != '+') { //exact version (e.g. 1.6)
  1839. v = v + "+";
  1840. }
  1841. }
  1842. return v;
  1843. }
  1844. //we relax validation rules where we try to embed or launch app
  1845. // in order to deal with requests for OLDER jres at the java level
  1846. //Basically we convert request for version in JRE family to request for any future JRE
  1847. //We do NOT do same for JavaFX right now. There is no real need before 3.0 and it is not clear if it is good thing
  1848. //
  1849. //Note we keep validation strict for install and validate-only scenarios.
  1850. // This allows to query accurate details from javascript
  1851. function doValidateRelaxed(platform) {
  1852. var p = new dtjava.Platform(platform);
  1853. p.jvm = relaxVersion(p.jvm);
  1854. //p.javafx = relaxVersion(p.javafx);
  1855. return doValidate(p);
  1856. }
  1857. function doValidate(platform, noPluginWebBrowser) {
  1858. //ensure some platform is set (we could get array too!)
  1859. platform = new dtjava.Platform(platform);
  1860. //problem markers
  1861. var fx = "ok", jre = "ok", restart = false, os = false, browser = false,
  1862. p, details;
  1863. //check JRE
  1864. if (notNull(platform.jvm) && jreCheck(platform.jvm) != "ok") { //matching JRE not found
  1865. var res = jreCheck("1+");
  1866. if (res == "ok") {
  1867. jre = "old";
  1868. } else {
  1869. jre = res; //"none" or "disabled"
  1870. }
  1871. details = checkJRESupport();
  1872. if (details.os) {
  1873. jre = "unsupported";
  1874. os = true;
  1875. } else if(noPluginWebBrowser) {
  1876. jre = "ok";
  1877. } else {
  1878. browser = details.browser;
  1879. }
  1880. }
  1881. //check FX
  1882. if (notNull(platform.javafx)) {
  1883. details = checkFXSupport();
  1884. if (details.os) { //FX is not supported,
  1885. //do not even try
  1886. fx = "unsupported";
  1887. os = os || details.os;
  1888. } else if(noPluginWebBrowser) {
  1889. fx = "ok";
  1890. } else if( details.browser) {
  1891. browser = browser || details.browser;
  1892. } else {
  1893. //on non windows platforms automated install is not possible
  1894. // (if it is needed on windows and possible we will set it to false later)
  1895. if (ua.fx != null) {
  1896. //found cobundled JavaFX on 7u6+ (and it is NPAPI-based browser)
  1897. if (versionCheckFX(platform.javafx, ua.fx)) {
  1898. fx = "ok";
  1899. } else if (versionCheckFX("2.0+", ua.fx)) {
  1900. fx = "old";
  1901. }
  1902. } else if (ua.win) { //could be 7u6(cobundle)/IE or JRE6/FX
  1903. try {
  1904. p = getPlugin();
  1905. //typeof did not work in IE
  1906. var v = p.getInstalledFXVersion(platform.javafx);
  1907. // If not found then try for the latest family (e.g. if the requested FX version is "2.2" and "8.0.5" is installed
  1908. // we should not report that FX is old or does not exist. Instead we should continue with "8.0.5" and than either relaunch
  1909. // with the requested JRE or offer the user to launch the app using the latest JRE installed).
  1910. if (v == "" || v == null) {
  1911. v = p.getInstalledFXVersion(platform.javafx + '+');
  1912. }
  1913. //if found we should get version string, otherwise empty string or null. If found then fx=false!
  1914. if (v == "" || v == null) {
  1915. v = p.getInstalledFXVersion("2.0+"); //check for any FX version
  1916. if (v == null || v == "") {
  1917. fx = "none";
  1918. } else {
  1919. fx = "old";
  1920. }
  1921. }
  1922. } catch(err) {
  1923. //If we got here then environment is supported but
  1924. //this is non FX aware JRE => no FX and can only offer manual install
  1925. // (restart needed as toolkit is already loaded)
  1926. fx = "none";
  1927. }
  1928. } else if (ua.mac || ua.linux) {
  1929. fx = "none";
  1930. }
  1931. }
  1932. }
  1933. //recommend relaunch if OS is ok but browser is not supported
  1934. restart = restart || (!os && browser);
  1935. //TODO: need a way to find out if java plugin is loaded => will need to relaunch
  1936. //we need to return null if everything is ok. Check for problems.
  1937. if (fx != "ok" || jre != "ok" || restart || os || browser) {
  1938. return new PlatformMismatchEvent(
  1939. {fx: fx, jre: jre, relaunch: restart, os: os, browser: browser,
  1940. platform: platform});
  1941. } else {
  1942. //if all looks good check JRE again, it could be false positive
  1943. if (ua.override == false && !noPluginWebBrowser && !doublecheckJrePresence()) {
  1944. return new PlatformMismatchEvent(
  1945. {fx: fx, jre: "none", relaunch: restart, os: os,
  1946. browser: browser, platform: platform});
  1947. }
  1948. }
  1949. return null;
  1950. }
  1951. //TODO: does it make sense to have a way to explicitly request locale?
  1952. function guessLocale() {
  1953. var loc = null;
  1954. loc = navigator.userLanguage;
  1955. if (loc == null)
  1956. loc = navigator.systemLanguage;
  1957. if (loc == null)
  1958. loc = navigator.language;
  1959. if (loc != null) {
  1960. loc = loc.replace("-", "_")
  1961. }
  1962. return loc;
  1963. }
  1964. function getJreUrl(loc) {
  1965. if (!notNull(loc)) {
  1966. loc = guessLocale();
  1967. }
  1968. return 'https://java.com/dt-redirect?' +
  1969. ((notNull(window.location) && notNull(window.location.href)) ?
  1970. ('&returnPage=' + window.location.href) : '') +
  1971. (notNull(loc) ? ('&locale=' + loc) : '');
  1972. //NB: brand parameter is not supported for now
  1973. }
  1974. function getFxUrl(locale) {
  1975. return "http://www.oracle.com/technetwork/java/javafx/downloads/index.html";
  1976. }
  1977. //return true if mismatch event suggest to perform installation
  1978. function isMissingComponent(v) {
  1979. if (v != null) {
  1980. var jre = v.jreStatus();
  1981. var fx = v.javafxStatus();
  1982. //if anything is disabled then this need to be resolved before any further installs
  1983. return (jre == "none" || fx == "none" || jre == "old" || fx == "old")
  1984. && (fx != "disabled" && jre != "disabled");
  1985. }
  1986. return false;
  1987. }
  1988. function showClickToInstall(ld, isJRE, isUpgrade, isAutoinstall, isRelaunchNeeded, actionFunc) {
  1989. //what product?
  1990. var productName, productLabel;
  1991. if (isJRE) {
  1992. productName = "Java";
  1993. productLabel = "java";
  1994. } else {
  1995. productName = "JavaFX";
  1996. productLabel = "javafx";
  1997. }
  1998. var msg1, msg2, imgName;
  1999. if (isUpgrade) {
  2000. msg1 = "A newer version of " + productName + "is required to view the content on this page.";
  2001. msg2 = "Please click here to update " + productName;
  2002. imgName = "upgrade_"+productLabel+".png";
  2003. } else {
  2004. msg1 = "View the content on this page.";
  2005. msg2 = "Please click here to install " + productName;
  2006. imgName = "get_"+productLabel+".png";
  2007. }
  2008. var altText = "Click to install "+productName;
  2009. doShowMessageInTheArea(ld, msg1, msg2, altText, imgName, actionFunc);
  2010. }
  2011. function doShowMessageInTheArea(ld, msg1, msg2, altText, imgName, actionFunc) {
  2012. //if image will fit (size 238x155)
  2013. var r = d.createElement("div");
  2014. r.width = normalizeDimension(ld.width);
  2015. r.height = normalizeDimension(ld.height);
  2016. var lnk = d.createElement("a");
  2017. lnk.href="";
  2018. lnk.onclick = function() {actionFunc(); return false;};
  2019. if (ld.width < 250 || ld.height < 160) { //if relative size this will fail =>
  2020. // will choose image
  2021. r.appendChild(
  2022. d.createElement("p").appendChild(
  2023. d.createTextNode(msg1)));
  2024. lnk.appendChild(d.createTextNode(msg2));
  2025. r.appendChild(lnk);
  2026. } else {
  2027. var img = d.createElement("img");
  2028. img.src = jscodebase + imgName;
  2029. img.alt = altText;
  2030. img.style.borderWidth="0px";
  2031. img.style.borderStyle="none";
  2032. //FIXME: centering image does not work (in a way it also work with relative dimensions ...)
  2033. // lnk.style.top="50%";
  2034. // lnk.style.left="50%";
  2035. // lnk.style.marginTop = -119; // 238/2
  2036. // lnk.style.marginLeft = -77; //155/2
  2037. lnk.appendChild(img);
  2038. r.appendChild(lnk);
  2039. }
  2040. wipe(ld.placeholder);
  2041. ld.placeholder.appendChild(r);
  2042. }
  2043. function canJavaFXCoBundleSatisfy(platform) {
  2044. // check if latest co-bundle can satisfy
  2045. if (versionCheck(platform.jvm, minJRECobundleVersion, false) &&
  2046. versionCheckFX(platform.javafx, "2.2.0")) {
  2047. return true;
  2048. }
  2049. return false;
  2050. }
  2051. function defaultInstallHandler(app, platform, cb,
  2052. isAutoinstall, needRelaunch, launchFunc) {
  2053. var installFunc = function() {
  2054. doInstall(app, platform, cb, launchFunc);
  2055. };
  2056. var s = doValidate(platform);
  2057. if (!notNull(s)) { //platform match => nothing to install
  2058. if (notNull(launchFunc)) {
  2059. launchFunc();
  2060. }
  2061. }
  2062. var isUpgrade = notNull(s) && (s.javafxStatus() == "old" || s.jreStatus() == "old");
  2063. if (notNull(app.placeholder)) { //embedded
  2064. if (canJavaFXCoBundleSatisfy(platform)) { //if both JRE and FX are missing we will start install from JRE
  2065. //it is only JRE that needs to be updated
  2066. showClickToInstall(app, true, isUpgrade, isAutoinstall, needRelaunch, installFunc);
  2067. } else {
  2068. showClickToInstall(app, (s.jreStatus() != "ok"), isUpgrade, isAutoinstall, needRelaunch, installFunc);
  2069. }
  2070. } else { //webstart
  2071. var r = isAutoinstall;
  2072. var msg = null;
  2073. if (!r) {
  2074. if (canJavaFXCoBundleSatisfy(platform)) { //if both JRE and FX are missing we will start install from JRE
  2075. //it is only JRE that needs to be updated
  2076. if (isUpgrade) {
  2077. msg = "A newer version of Java is required to view the content on this page. Please click here to update Java.";
  2078. } else {
  2079. msg = "To view the content on this page, please click here to install Java.";
  2080. }
  2081. r = confirm(msg);
  2082. } else {
  2083. if (isUpgrade) {
  2084. msg = "A newer version of JavaFX is required to view the content on this page. Please click here to update JavaFX.";
  2085. } else {
  2086. msg = "To view the content on this page, please click here to install JavaFX.";
  2087. }
  2088. r = confirm(msg);
  2089. }
  2090. }
  2091. if (r)
  2092. installFunc();
  2093. }
  2094. }
  2095. /**
  2096. * returns true if we can enable DT plugin auto-install without chance of
  2097. * deadlock on cert mismatch dialog
  2098. *
  2099. * requestedJREVersion param is optional - if null, it will be
  2100. * treated as installing any JRE version
  2101. *
  2102. * DT plugin for 6uX only knows about JRE installer signed by SUN cert.
  2103. * If it encounter Oracle signed JRE installer, it will have chance of
  2104. * deadlock when running with IE. This function is to guard against this.
  2105. */
  2106. function enableWithoutCertMisMatchWorkaround(requestedJREVersion) {
  2107. // Non-IE browser are okay
  2108. if (!ua.ie) return true;
  2109. // if DT plugin is 10.0.0 or above, return true
  2110. // This is because they are aware of both SUN and Oracle signature and
  2111. // will not show cert mismatch dialog that might cause deadlock
  2112. if (versionCheck("10.0.0+", getPlugin().version, false)) {
  2113. return true;
  2114. }
  2115. // If we got there, DT plugin is 6uX
  2116. if (requestedJREVersion == null) {
  2117. // if requestedJREVersion is not defined - it means ANY.
  2118. // can not guarantee it is safe to install ANY version because 6uX
  2119. // DT does not know about Oracle certificates and may deadlock
  2120. return false;
  2121. }
  2122. // 6u32 or earlier JRE installer used Sun certificate
  2123. // 6u33+ uses Oracle's certificate
  2124. // DT in JRE6 does not know about Oracle certificate => can only
  2125. // install 6u32 or earlier without risk of deadlock
  2126. return !versionCheck("1.6.0_33+", requestedJREVersion);
  2127. }
  2128. // return true if we can auto-install to satisfy the platform requirement
  2129. // return false otherwise
  2130. //
  2131. // We can auto-install if all below is true:
  2132. // - windows platform
  2133. // - native DT plugin available
  2134. // - if JRE install is required, JRE exe is signed by compatible
  2135. // certificate
  2136. // - if FX install is required, JRE co-bundle can satisfy the
  2137. // requirement or DT plugin supports FX auto-install
  2138. function isAutoInstallEnabled(platform, jre, fx) {
  2139. // auto-install is windows only
  2140. if (!ua.win) return false;
  2141. // if no DT plugin, return false
  2142. // if DT plugin is there but not operational (e.g. blocked)
  2143. // then pretend there is no autoinstall
  2144. var p = getPlugin();
  2145. if (p == null || !isDef(p.version)) return false;
  2146. if (jre != "ok") {
  2147. // need JRE install
  2148. if (!enableWithoutCertMisMatchWorkaround(platform.jvm)) {
  2149. return false;
  2150. }
  2151. }
  2152. if (fx != "ok") {
  2153. if (!canJavaFXCoBundleSatisfy(platform)) {
  2154. // no cobundle, check if there is standalone FX auto-install
  2155. // DT from Java 7 or later should be ok
  2156. if (!versionCheck("10.0.0+", getPlugin().version, false)) {
  2157. return false;
  2158. }
  2159. } else {
  2160. // we are going to install co-bundle JRE - check if we can do
  2161. // that
  2162. if (!enableWithoutCertMisMatchWorkaround(minJRECobundleVersion)) {
  2163. return false;
  2164. }
  2165. }
  2166. }
  2167. return true;
  2168. }
  2169. function doInstall(app, platform, cb, postInstallFunc) {
  2170. var s = doValidate(platform);
  2171. cb = new dtjava.Callbacks(cb);
  2172. if (notNull(s) && s.isUnsupportedPlatform()) {
  2173. reportPlatformError(app, s, cb);
  2174. return false; //no install
  2175. }
  2176. var placeholder = (app != null) ? app.placeholder : null;
  2177. var codes, status;
  2178. if (isMissingComponent(s)) { //otherwise nothing to install
  2179. if (s.jre != "ok") {
  2180. if (isDef(cb.onInstallStarted)) {
  2181. cb.onInstallStarted(placeholder, "Java",
  2182. false, getPlugin() != null);
  2183. }
  2184. startManualJREInstall();
  2185. } else { //what it could be??
  2186. reportPlatformError(app, s, cb);
  2187. }
  2188. } else {
  2189. //nothing to install
  2190. if (postInstallFunc != null) {
  2191. postInstallFunc();
  2192. }
  2193. return true;
  2194. }
  2195. //no install initiated
  2196. return false;
  2197. }
  2198. //just open download URL in new window
  2199. function startManualJREInstall() {
  2200. w.open(getJreUrl());
  2201. }
  2202. //just open download URL in new window
  2203. function startManualFXInstall() {
  2204. w.open(javafxURL);
  2205. }
  2206. function defaultGetSplashHandler(ld) {
  2207. if (ld.placeholder != null) {
  2208. var _w = ld.width, _h = ld.height;
  2209. //prepare image
  2210. //if width and height are relative then comparison with int will be false
  2211. // and we will end up using large image. This is on purpose
  2212. // as it is unlikely that relative dimensions are used for tiny applet areas
  2213. var isBig = !(_w < 100 && _h < 100);
  2214. var iU = isBig ? 'javafx-loading-100x100.gif' : 'javafx-loading-25x25.gif';
  2215. var iW = isBig ? 80 : 25;
  2216. var iH = isBig ? 80 : 25;
  2217. var img = d.createElement("img");
  2218. img.src = jscodebase + iU;
  2219. img.alt = "";
  2220. //position in the center of the container
  2221. img.style.position = "relative";
  2222. img.style.top = "50%";
  2223. img.style.left = "50%";
  2224. img.style.marginTop = normalizeDimension(-iH/2);
  2225. img.style.marginLeft = normalizeDimension(-iW/2);
  2226. return img;
  2227. } else {
  2228. //webstart or install case
  2229. //TODO: show some html splash for webstart? how to hide it?
  2230. return null;
  2231. }
  2232. }
  2233. function defaultGetNoPluginMessageHandler(app) {
  2234. if (app.placeholder != null) {
  2235. var p = d.createElement("p");
  2236. p.appendChild(d.createTextNode("FIXME - add real message!"));
  2237. return p;
  2238. } //no op if not embedded content
  2239. return null;
  2240. }
  2241. //remove all child elements for given node
  2242. function wipe(c) {
  2243. while(c.hasChildNodes()) c.removeChild(c.firstChild);
  2244. }
  2245. function defaultInstallStartedHandler(placeholder, component, isAuto, restartNeeded) {
  2246. if (placeholder != null) {
  2247. var code = null;
  2248. if (isAuto) {
  2249. code = (component == "JavaFX") ?
  2250. "install:inprogress:javafx": "install:inprogress:jre";
  2251. } else {
  2252. code = (component == "JavaFX") ?
  2253. "install:inprogress:javafx:manual" : "install:inprogress:jre:manual";
  2254. }
  2255. appletInfoMsg(code);
  2256. }
  2257. }
  2258. function defaultInstallFinishedHandler(placeholder, component, status, relaunch) {
  2259. var t;
  2260. if (status != "success") {
  2261. var msg = null;
  2262. if (component == "javafx") {
  2263. if (!doublecheckJrePresence()) { //guess if we failed due to no JRE
  2264. //need to request to install JRE first
  2265. msg = "install:fx:error:nojre";
  2266. } else {
  2267. msg = "install:fx:"+status;
  2268. }
  2269. } else { //must be JRE error
  2270. msg = "install:jre:"+status;
  2271. }
  2272. if (placeholder != null) {
  2273. t = appletErrorMsg(msg, null);
  2274. //Instead of hiding splash and applet we simply clear the container
  2275. //We are not going to show neither splash nor applet anyways ...
  2276. wipe(placeholder);
  2277. placeholder.appendChild(t);
  2278. } else {
  2279. w.alert(webstartErrorMsg(msg));
  2280. }
  2281. } else { //success
  2282. if (relaunch) {
  2283. t = appletInfoMsg("install:fx:restart");
  2284. //Instead of hiding splash and applet we simply clear the container
  2285. //We are not going to show neither splash nor applet anyways ...
  2286. wipe(placeholder);
  2287. placeholder.appendChild(t);
  2288. }
  2289. }
  2290. }
  2291. function defaultDeployErrorHandler(app, r) {
  2292. if (r == null) {
  2293. code = "success";
  2294. } else if (r.isUnsupportedBrowser()) {
  2295. code = "browser";
  2296. } else if (r.jreStatus() != "ok") {
  2297. code = "jre:" + r.jreStatus();
  2298. } else if (r.javafxStatus() != "ok") {
  2299. code = "javafx:" + r.javafxStatus();
  2300. } else if (r.isRelaunchNeeded()) {
  2301. code = "relaunch";
  2302. } else {
  2303. code = "unknown " + r.toString();
  2304. }
  2305. if (app.placeholder != null) {//embedded app
  2306. showAppletError(app.id, code, null);
  2307. } else { //webstart or install case
  2308. w.alert(webstartErrorMsg(code));
  2309. }
  2310. }
  2311. function defaultRuntimeErrorHandler(id) {
  2312. var el_applet = findAppletDiv(id);
  2313. if (getErrorDiv(id) != null) {
  2314. showAppletError(id, "launch:fx:generic:embedded",
  2315. function() {showHideApplet(findAppletDiv(id), false); return false;});
  2316. } else {
  2317. w.alert(webstartErrorMsg("launch:fx:generic"));
  2318. }
  2319. }
  2320. //TODO: Does availability of object mean initialization is completed (or even started?)
  2321. //Can we expect that any subsequent call to this object will actually work?
  2322. //Perhaps it is false alarm
  2323. function getPlugin() {
  2324. var result = null;
  2325. if (ua.override == false) {
  2326. navigator.plugins.refresh(false);
  2327. result = document.getElementById('dtjavaPlugin');
  2328. }
  2329. return result;
  2330. }
  2331. function installNativePlugin() {
  2332. //already installed?
  2333. if (getPlugin() != null) return;
  2334. //can not install plugin now as page has no body yet, postpone
  2335. //NB: use cbDone here to avoid infinite recursion (corner case)
  2336. if (!notNull(d.body) && !cbDone) {
  2337. addOnDomReadyInternal(function() {
  2338. installNativePlugin();
  2339. });
  2340. postponeNativePluginInstallation = true;
  2341. return;
  2342. }
  2343. var p = null;
  2344. if (ua.ie) {
  2345. p = d.createElement('object');
  2346. //TODO: zero size does not work?? How we can make it less intrusive for layout?
  2347. p.width = '1px';
  2348. p.height = '1px';
  2349. //new CLSID, one with 0000-0000 had been kill bit
  2350. p.classid = 'clsid:CAFEEFAC-DEC7-0000-0001-ABCDEFFEDCBA';
  2351. } else {
  2352. // Safari and Opera browsers find the plugin but it
  2353. // doesn't work, so until we can get it to work - don't use it.
  2354. if (!ua.wk && !ua.op && navigator.mimeTypes != null) {
  2355. // mime-type of the DeployToolkit plugin object
  2356. // (do not care about old DT plugin anymore)
  2357. var mimeType = 'application/java-deployment-toolkit';
  2358. var newDT = false;
  2359. for (var i = 0; i < navigator.mimeTypes.length; i++) {
  2360. var mt = navigator.mimeTypes[i];
  2361. newDT = newDT || ((mt.type == mimeType) && mt.enabledPlugin);
  2362. }
  2363. if (newDT) {
  2364. p = d.createElement('embed');
  2365. p.setAttribute('type', newDT ? mimeType : oldMimeType);
  2366. p.setAttribute('hidden', 'true');
  2367. }
  2368. }
  2369. }
  2370. if (p != null) {
  2371. p.setAttribute('id', 'dtjavaPlugin');
  2372. d.body.appendChild(p);
  2373. // Update internal versions from plug-in if needed
  2374. if (ua.deploy == null && isDef(p.version)) {
  2375. ua.deploy = p.version;
  2376. }
  2377. }
  2378. }
  2379. var appletCounter = 0;
  2380. function prepareAppletID(ld) {
  2381. if (notNull(ld.id)) {
  2382. return ld.id;
  2383. } else {
  2384. appletCounter++;
  2385. return ("dtjava-app-" + appletCounter);
  2386. }
  2387. }
  2388. //returns object that represents an applet/object tag
  2389. function getAppletSnippet(ld, platform, cb) {
  2390. //we use wrapper div here as changing style on applet tag
  2391. // cause liveconnect to be initialized and slows down startup
  2392. var wrapper = d.createElement("div");
  2393. wrapper.width = normalizeDimension(ld.width);
  2394. wrapper.height = normalizeDimension(ld.height);
  2395. wrapper.id = ld.id + "-app";
  2396. //without this it splash will not work in Chrome
  2397. wrapper.style.position = "relative";
  2398. var r = d.createElement("applet"); //TODO: use object!
  2399. r.code = "dummy.class";
  2400. r.id = ld.id;
  2401. r.width = normalizeDimension(ld.width);
  2402. r.height = normalizeDimension(ld.height);
  2403. //things added unconditionally
  2404. var sparams = {"jnlp_href" : ld.url,
  2405. "java_status_events" : true,
  2406. "type" : "application/x-java-applet"};
  2407. if (notNull(ld.jnlp_content)) {
  2408. sparams['jnlp_embedded'] = ld.jnlp_content;
  2409. }
  2410. if (notNull(platform.javafx)) {
  2411. //for swing applications embedding FX we do not want this property as it will
  2412. // trigger FX toolkit and lead to app failure!
  2413. if (!notNull(ld.toolkit) || ld.toolkit == "fx") {
  2414. sparams["javafx_version"] = ((platform.javafx == "*") ? "2.0+" : platform.javafx);
  2415. }
  2416. //FX requires new VM per applet, do it unconditionally
  2417. sparams["separate_jvm"] = true;
  2418. sparams["javafx_applet_id"] = r.id;
  2419. //enable scripting for FX unconditionally for now
  2420. sparams["scriptable"] = true;
  2421. } else {
  2422. if (ld.scriptable) {
  2423. sparams["scriptable"] = true;
  2424. }
  2425. if (ld.sharedjvm) {
  2426. sparams["separate_jvm"] = true;
  2427. }
  2428. }
  2429. if (notNull(platform.jvmargs)) {
  2430. sparams["java_arguments"] = platform.jvmargs;
  2431. }
  2432. //prepare parameters first
  2433. var key, p;
  2434. for (key in ld.params) {
  2435. //do not let to override system parameters
  2436. if (!notNull(sparams[key])) {
  2437. p = d.createElement("param");
  2438. p.name = key;
  2439. p.value = ld.params[key];
  2440. r.appendChild(p);
  2441. }
  2442. }
  2443. for (key in sparams) {
  2444. p = d.createElement("param");
  2445. p.name = key;
  2446. p.value = sparams[key];
  2447. r.appendChild(p);
  2448. }
  2449. if (isDef(cb.onGetNoPluginMessage)) {
  2450. p = d.createElement("noapplet");
  2451. var t = cb.onGetNoPluginMessage(ld);
  2452. p.appendChild(t);
  2453. //TODO: FIXME: following line fails for me in IE7??
  2454. //r.appendChild(p);
  2455. }
  2456. wrapper.appendChild(r);
  2457. return wrapper;
  2458. }
  2459. function findAppletDiv(id) {
  2460. //TODO: FIXME: in static deployment scenario this seem to cause restart of plugin (in FF)
  2461. //Weird but similar code works in the deployJava.js ...
  2462. //TODO: reinvestigate
  2463. var el = d.getElementById(id + "-app");
  2464. if (el == null) { //wrapping div for applet is not required
  2465. el = d.getElementById(id);
  2466. }
  2467. return el;
  2468. }
  2469. //IMPORTANT: whilst we can update style on the applet element itself
  2470. // this is not best idea as this may also cause wait till liveconnect
  2471. // is initialized and slow startup.
  2472. function showHideApplet(div, hide) {
  2473. if (!notNull(div)) return;
  2474. if (hide) {
  2475. div.style.left = -10000;
  2476. } else {
  2477. div.style.left = "0px";
  2478. }
  2479. }
  2480. function showHideDiv(div, hide) {
  2481. if (!notNull(div)) return;
  2482. if (hide) {
  2483. div.style.visibility = "hidden";
  2484. } else {
  2485. div.style.visibility = "visible";
  2486. }
  2487. }
  2488. function doHideSplash(id) {
  2489. try {
  2490. var errPane = getErrorDiv(id);
  2491. if (errPane != null && errPane.style != null && errPane.style.visibility == "visible") {
  2492. //if we have error pane shown then ignore this request
  2493. // (could be race condition and applet is asking to hide splash to show error too)
  2494. return;
  2495. }
  2496. var el = findAppletDiv(id);
  2497. showHideApplet(el, false);
  2498. //show applet first and then hide splash to avoid blinking
  2499. showHideDiv(d.getElementById(id + "-splash"), true);
  2500. } catch(err) {}
  2501. }
  2502. var javafxURL = "https://java.com/javafx";
  2503. //TODO: validate ALL messages are shown as expected and when expected (for applet/webstart/install)
  2504. var errorMessages = {
  2505. "launch:fx:generic" : ["JavaFX application could not launch due to system configuration.",
  2506. " See ", "a", "https://java.com/javafx", "java.com/javafx",
  2507. " for troubleshooting information."],
  2508. "launch:fx:generic:embedded" : ["JavaFX application could not launch due to system configuration ",
  2509. "(", "onclick", "show error details", ").",
  2510. " See ", "a", "https://java.com/javafx", "java.com/javafx",
  2511. " for troubleshooting information."],
  2512. "install:fx:restart" : ["Restart your browser to complete the JavaFX installation,",
  2513. " then return to this page."],
  2514. "install:fx:error:generic" : ["JavaFX install not completed.",
  2515. " See ", "a", "https://java.com/javafx", "java.com/javafx",
  2516. " for troubleshooting information."],
  2517. "install:fx:error:download" : ["JavaFX install could not start because of a download error.",
  2518. " See ", "a", "https://java.com/javafx", "java.com/javafx",
  2519. " for troubleshooting information."],
  2520. "install:fx:error:cancelled" : ["JavaFX install was cancelled.",
  2521. " Reload the page and click on the download button to try again."],
  2522. "install:jre:error:cancelled" : ["Java install was cancelled.",
  2523. " Reload the page and click on the download button to try again."],
  2524. "install:jre:error:generic" : ["Java install not completed.",
  2525. " See ", "a", "https://java.com/", "java.com",
  2526. " for troubleshooting information."],
  2527. "install:jre:error:download" : ["Java install could not start because of a download error.",
  2528. " See ", "a", "https://java.com/", "java.com/",
  2529. " for troubleshooting information."],
  2530. "install:inprogress:jre" : ["Java install in progress."],
  2531. "install:inprogress:javafx" : ["JavaFX install in progress."],
  2532. "install:inprogress:javafx:manual" : ["Please download and run JavaFX Setup from ",
  2533. "a", getFxUrl(null), "java.com/javafx",
  2534. ". When complete, restart your browser to finish the installation,",
  2535. " then return to this page."],
  2536. "install:inprogress:jre:manual" : ["Please download and run Java Setup from ",
  2537. "a", getJreUrl(), "java.com/download",
  2538. ". When complete, reload the page."],
  2539. "install:fx:error:nojre" : ["b", "Installation failed.", "br",
  2540. "Java Runtime is required to install JavaFX and view this content. ",
  2541. "a", getJreUrl(), "Download Java Runtime",
  2542. " and run the installer. Then reload the page to install JavaFX."],
  2543. "browser": [ 'Content can not be displayed using your Web browser. Please open this page using another browser.'],
  2544. "jre:none": [ 'JavaFX application requires a recent Java runtime. Please download and install the latest JRE from ',
  2545. 'a', 'https://java.com', "java.com", '.'],
  2546. "jre:old" : [ 'JavaFX application requires a recent Java runtime. Please download and install the latest JRE from ',
  2547. 'a', 'https://java.com', "java.com", '.'],
  2548. "jre:plugin": ['b', "A Java plugin is required to view this content.", 'br',
  2549. "Make sure that ", "a", 'https://java.com', "a recent Java runtime",
  2550. " is installed, and the Java plugin is enabled."],
  2551. "jre:blocked": ["Please give Java permission to run. This will allow Java to present content provided on this page."],
  2552. "jre:unsupported": ["b", "Java is required to view this content but Java is currently unsupported on this platform.",
  2553. "br", "Please consult ", "a", "https://java.com", "the Java documentation",
  2554. " for list of supported platforms."],
  2555. "jre:browser" : ["b", "Java plugin is required to view this content but Java plugin is currently unsupported in this browser.",
  2556. "br", "Please try to launch this application using other browser. Please consult ",
  2557. "a", "https://java.com", "the Java documentation",
  2558. " for list of supported browsers for your OS."],
  2559. "javafx:unsupported" : ["b", "JavaFX 2.0 is required to view this content but JavaFX is currently unsupported on this platform.",
  2560. "br", "Please consult ", "a", javafxURL, "the JavaFX documentation",
  2561. " for list of supported platforms."],
  2562. "javafx:old" : [ 'This application requires newer version of JavaFX runtime. ',
  2563. 'Please download and install the latest JavaFX Runtime from ',
  2564. 'a', javafxURL, "java.com/javafx", '.'],
  2565. "javafx:none" : ["b", "JavaFX 2.0 is required to view this content.",
  2566. "br", "a", javafxURL, "Get the JavaFX runtime from java.com/javafx",
  2567. " and run the installer. Then restart the browser."],
  2568. "javafx:disabled" : ["JavaFX is disabled. Please open Java Control Panel, switch to Advanced tab and enable it. ",
  2569. "Then restart the browser."],
  2570. "jre:oldplugin" : ["New generation Java plugin is required to view this content." +
  2571. " Please open Java Control Panel and enable New Generation Java Plugin."],
  2572. "jre:disabled" : ["Java plugin appear to be disabled in your browser. ",
  2573. " Please enable Java in the browser options."]
  2574. };
  2575. //assume we get list of (tag, param, text) where both param and tag are optional
  2576. // Supported tags:
  2577. // ("a", href value, link text)
  2578. // ("b", text)
  2579. // ("br")
  2580. // (text) //text can not be the same as any of tag names
  2581. function msgAsDOM(lst, extra, onClickFunc) {
  2582. var i = 0;
  2583. var root = d.createElement("p");
  2584. if (extra != null) {
  2585. root.appendChild(extra);
  2586. }
  2587. var el;
  2588. while (i < lst.length) {
  2589. switch (lst[i]) {
  2590. case "a":
  2591. el = d.createElement(lst[i]);
  2592. el.href = lst[i + 1];
  2593. el.appendChild(d.createTextNode(lst[i + 2]));
  2594. i = i + 2;
  2595. break;
  2596. case "br":
  2597. el = d.createElement(lst[i]);
  2598. break;
  2599. case "b":
  2600. el = d.createElement(lst[i]);
  2601. el.appendChild(d.createTextNode(lst[i + 1]));
  2602. i++;
  2603. break;
  2604. case "onclick":
  2605. el = d.createElement("a");
  2606. el.href = "";
  2607. if (onClickFunc == null) {
  2608. onClickFunc = function() {return false;}
  2609. }
  2610. el.onclick = onClickFunc;
  2611. el.appendChild(d.createTextNode(lst[i + 1]));
  2612. i = i + 1;
  2613. break;
  2614. default:
  2615. el = d.createTextNode(lst[i]);
  2616. break;
  2617. }
  2618. root.appendChild(el);
  2619. i++;
  2620. }
  2621. return root;
  2622. }
  2623. function webstartErrorMsg(code) {
  2624. var m = "";
  2625. var lst = errorMessages[code];
  2626. var i = 0;
  2627. if (notNull(lst)) {
  2628. while (i < lst.length) {
  2629. if (lst[i] != 'a' && lst[i] != 'br' && lst[i] != 'b') {
  2630. m += lst[i];
  2631. } else if (lst[i] == 'a') { //next element is link => skip it
  2632. i++;
  2633. }
  2634. i++;
  2635. }
  2636. } else {
  2637. m = "Unknown error: ["+code+"]";
  2638. }
  2639. return m;
  2640. }
  2641. function getErrorDiv(id) {
  2642. return d.getElementById(id + "-error");
  2643. }
  2644. function showAppletError(id, code, onclickFunc) {
  2645. var pane = getErrorDiv(id);
  2646. if (!notNull(pane)) { //should not be possible, we add error pane right a way and then add it again before we add splash/app
  2647. return;
  2648. }
  2649. //remove old content in the ERROR PANE only (if any)
  2650. wipe(pane);
  2651. //populate and show pane
  2652. pane.appendChild(appletErrorMsg(code, onclickFunc));
  2653. pane.style.visibility = "visible";
  2654. //hide splash and applet
  2655. showHideDiv(d.getElementById(id+"-splash"), true);
  2656. showHideApplet(findAppletDiv(id), true);
  2657. }
  2658. //returns DOM subtree
  2659. function appletErrorMsg(code, onclickFunc) {
  2660. var out = d.createElement("div");
  2661. var img = d.createElement("img");
  2662. img.src = jscodebase + 'error.png';
  2663. img.width = '16px';
  2664. img.height = '16px';
  2665. img.alt = "";
  2666. img.style.cssFloat = "left";
  2667. img.style.styleFloat = "left"; //IE way
  2668. img.style.margin = "0px 10px 60px 10px";
  2669. img.style.verticalAlign="text-top";
  2670. var m = errorMessages[code];
  2671. //error message is missing => show code as fallback
  2672. if (!notNull(m)) {
  2673. m = [code];
  2674. }
  2675. var hideFunc = null;
  2676. if (isDef(onclickFunc)) {
  2677. hideFunc = function() {
  2678. if (notNull(out.parentNode)) {
  2679. out.parentNode.removeChild(out);
  2680. }
  2681. try {
  2682. onclickFunc();
  2683. } catch (e) {}
  2684. return false;
  2685. }
  2686. }
  2687. out.appendChild(msgAsDOM(m, img, hideFunc));
  2688. return out;
  2689. }
  2690. //returns DOM subtree
  2691. function appletInfoMsg(code) {
  2692. var out = d.createElement("div");
  2693. var m = errorMessages[code];
  2694. //error message is missing => show code as fallback
  2695. if (!notNull(m)) {
  2696. m = [code];
  2697. }
  2698. out.appendChild(msgAsDOM(m, null, null));
  2699. return out;
  2700. }
  2701. function normalizeApp(ld, acceptString) {
  2702. var app = null;
  2703. //normalize launch descriptor
  2704. if (notNull(ld)) {
  2705. //could be either url or set of parameters
  2706. if (acceptString && typeof ld === 'string') {
  2707. app = new dtjava.App(ld, null);
  2708. } else if (ld instanceof dtjava.App) {
  2709. app = ld;
  2710. } else {
  2711. app = new dtjava.App(ld.url, ld);
  2712. }
  2713. }
  2714. return app;
  2715. }
  2716. function setupAppletCallbacks(platform, callbacks) {
  2717. //set default callbacks
  2718. var cb = new dtjava.Callbacks(callbacks);
  2719. //disable splash if it is was not requested explicitly and
  2720. // it is not JavaFX app
  2721. if (platform.javafx == null && cb.onGetSplash === defaultGetSplashHandler) {
  2722. cb.onGetSplash = null;
  2723. }
  2724. return cb;
  2725. }
  2726. //width and height in styles need to have unit type explicitly referenced
  2727. // or they will not conform to strict doctypes
  2728. //On other hand we can have relative dimensions, e.g. 100% and these are fine without units
  2729. //
  2730. //This method will add unit type to numeric dimension specifications. E.g.
  2731. // 400 => 400px
  2732. // -10 => -10px
  2733. // 50% => 50%
  2734. function normalizeDimension(v) {
  2735. if (isFinite(v)) {
  2736. return v + 'px';
  2737. } else {
  2738. return v;
  2739. }
  2740. }
  2741. //wrap given node s in the div
  2742. function wrapInDiv(ld, s, suffix) {
  2743. var sid = ld.id + "-" + suffix;
  2744. var div = d.createElement("div");
  2745. div.id = sid;
  2746. div.style.width = normalizeDimension(ld.width);
  2747. //this does not work well for different browsers
  2748. //if height is relative ...
  2749. //For firefox it becomes better if 100% is hardcode
  2750. // but then image is off in Chrome and it does not work in IE too ...
  2751. div.style.height = normalizeDimension(ld.height);
  2752. div.style.position = "absolute";
  2753. //TODO: provide way to specify bgcolor
  2754. // Perhaps app.style.bgcolor, app.style.splash-image, ... ?
  2755. // What was the param name supported by regular applet?
  2756. div.style.backgroundColor = "white";
  2757. if (s != null) {
  2758. div.appendChild(s);
  2759. }
  2760. return div;
  2761. }
  2762. var pendingCallbacks = {};
  2763. function doInstallCallbacks(id, cb) {
  2764. if (cb == null) {
  2765. cb = pendingCallbacks[id];
  2766. if (notNull(cb)) {
  2767. pendingCallbacks[id] = null;
  2768. } else {
  2769. return;
  2770. }
  2771. }
  2772. var a = document.getElementById(id);
  2773. if (!notNull(a)) return;
  2774. if (isDef(cb.onJavascriptReady)) {
  2775. var onReady = cb.onJavascriptReady;
  2776. if (a.status < 2) { //not READY yet
  2777. a.onLoad = function() {
  2778. onReady(id);
  2779. a.onLoad = null; //workaround bug in plugin for IE in JRE7
  2780. }
  2781. }
  2782. }
  2783. if (isDef(cb.onRuntimeError)) {
  2784. if (a.status < 3) { //not ERROR or READY yet
  2785. a.onError = function() {
  2786. cb.onRuntimeError(id);
  2787. //This used to be added as
  2788. // "workaround bug in plugin for IE in JRE7"
  2789. //I do not have recollection what the bug was
  2790. // and can not reproduce it now
  2791. //(perhaps multiple calls into callback?)
  2792. //With FX 2.0 it cause restart of the applet in IE
  2793. // for reason that is not completely clear
  2794. //Disable it for now
  2795. /* a.onError = null; */
  2796. }
  2797. } else if (a.status == 3) { //already failed, call handler in place
  2798. cb.onRuntimeError(id);
  2799. }
  2800. }
  2801. }
  2802. //we can not install applet callbacks until applet is instantiated as
  2803. //hook entry points are not defined and we do not control when applet is
  2804. //instantiated as developer may not add it to the DOM tree for a while.
  2805. //
  2806. //Therefore what we do is we insert <script> element AFTER applet tag
  2807. //to initiate install after applet tag is parsed
  2808. //
  2809. //However, we can not
  2810. //
  2811. function getSnippetToInstallCallbacks(id, cb) {
  2812. if (!notNull(cb) || !(isDef(cb.onDeployError) || isDef(cb.onJavascriptReady))) {
  2813. return null;
  2814. }
  2815. var s = d.createElement("script");
  2816. pendingCallbacks[id] = cb;
  2817. s.text = "dtjava.installCallbacks('"+id+"')";
  2818. return s;
  2819. }
  2820. function getErrorPaneSnippet(app) {
  2821. var paneDiv = wrapInDiv(app, null, "error");
  2822. paneDiv.style.visibility = "hidden";
  2823. return paneDiv;
  2824. }
  2825. function doEmbed(ld, platform, callbacks) {
  2826. var app = normalizeApp(ld, false);
  2827. //required argument is missing
  2828. if (!(notNull(app) && notNull(app.url) &&
  2829. notNull(app.width) && notNull(app.height) && notNull(app.placeholder))) {
  2830. //deployment error, not runtime => exception is ok
  2831. throw "Required attributes are missing! (url, width, height and placeholder are required)";
  2832. }
  2833. app.id = prepareAppletID(app);
  2834. //if placeholder is passed as id => find DOM node
  2835. if ((typeof app.placeholder == "string")) {
  2836. var p = d.getElementById(app.placeholder);
  2837. if (p == null) {
  2838. throw "Application placeholder [id="+app.placeholder+"] not found.";
  2839. }
  2840. app.placeholder = p;
  2841. }
  2842. //we may fail before we even try to add splash. E.g. because it is unsupported platform
  2843. //make sure we have error pane in place to show error
  2844. app.placeholder.appendChild(getErrorPaneSnippet(app));
  2845. //if we got array we need to copy over!
  2846. platform = new dtjava.Platform(platform);
  2847. var cb = setupAppletCallbacks(platform, callbacks);
  2848. //allow family match to match next family
  2849. //Once we get to java layer we will deal with it there
  2850. var v = doValidateRelaxed(platform);
  2851. var launchFunction = function() {
  2852. var appSnippet = getAppletSnippet(app, platform, cb);
  2853. var splashSnippet = (cb.onGetSplash == null) ? null : cb.onGetSplash(ld);
  2854. //what we try to do:
  2855. // placeholder need to have relative positioning (then splash will pe position relative to it)
  2856. // if splash is present it needs to have position "absolute", then it will not occupy space
  2857. // and can be placed on top of applet
  2858. app.placeholder.style.position = "relative";
  2859. if (splashSnippet != null) {
  2860. //position splash on top of applet area and hide applet temporarily
  2861. var ss = wrapInDiv(app, splashSnippet, "splash");
  2862. showHideDiv(ss, false);
  2863. showHideApplet(appSnippet, true);
  2864. wipe(app.placeholder);
  2865. app.placeholder.appendChild(getErrorPaneSnippet(app));
  2866. app.placeholder.appendChild(ss);
  2867. app.placeholder.appendChild(appSnippet);
  2868. } else {
  2869. wipe(app.placeholder);
  2870. app.placeholder.appendChild(getErrorPaneSnippet(app));
  2871. app.placeholder.appendChild(appSnippet);
  2872. }
  2873. //Note: this is not needed as we use setTimeout for the same
  2874. //var cbSnippet = getSnippetToInstallCallbacks(app.id, cb);
  2875. //if (cbSnippet != null) {
  2876. // app.placeholder.appendChild(cbSnippet);
  2877. //}
  2878. setTimeout(function() {doInstallCallbacks(app.id, cb)}, 0);
  2879. };
  2880. //can not launch yet
  2881. if (v != null) {
  2882. resolveAndLaunch(app, platform, v, cb, launchFunction);
  2883. } else {
  2884. launchFunction();
  2885. }
  2886. }
  2887. function extractApp(e) {
  2888. if (notNull(e)) {
  2889. var w = e.width; //TODO: do we need to extract number? e.g. if it was 400px? or 100%?
  2890. var h = e.height;
  2891. var jnlp = "dummy"; //Can find it from list of parameters but it is not really needed in
  2892. //static deployment scenario
  2893. return new dtjava.App(jnlp, {
  2894. id: e.id,
  2895. width: w,
  2896. height: h,
  2897. placeholder: e.parentNode
  2898. });
  2899. } else {
  2900. throw "Can not find applet with null id";
  2901. }
  2902. }
  2903. function processStaticObject(id, platform, callbacks) {
  2904. var a = d.getElementById(id); //TODO: use findAppletDiv??
  2905. var app = extractApp(a);
  2906. var cb = setupAppletCallbacks(platform, callbacks);
  2907. //Ensure some platform is set
  2908. platform = new dtjava.Platform(platform);
  2909. var launchFunc = function() {
  2910. //add error pane
  2911. app.placeholder.insertBefore(getErrorPaneSnippet(app), a);
  2912. if (cb.onGetSplash != null) {
  2913. //TODO: show splash if it was not hidden yet!
  2914. var splashSnippet = cb.onGetSplash(app);
  2915. if (notNull(splashSnippet)) {
  2916. var ss = wrapInDiv(app, splashSnippet, "splash");
  2917. if (notNull(ss)) {
  2918. app.placeholder.style.position = "relative";
  2919. app.placeholder.insertBefore(ss, a);
  2920. showHideApplet(a, true);
  2921. }
  2922. }
  2923. }
  2924. //TODO: install applet callbacks if they are provided
  2925. //Note - in theory we need to check if callbacks are supported too
  2926. // but if detection was not possible then it is hard to do
  2927. //they always wotk for FX or jre 7+ but how validate this?
  2928. //otherwise attempt to set them will block js and then trigger exception ...
  2929. }
  2930. var v = doValidateRelaxed(platform);
  2931. if (v != null) {
  2932. //TODO: Problem
  2933. // if FX missing and static deployment
  2934. // then JRE will try to autoinstall itself - this will cause popup
  2935. // Then DT will detect problem and also initiate install too
  2936. // a) double install
  2937. // b) if popup is canceled then we still offer to install again but it will not help applet to launch
  2938. // c) popup is unconditional and really ugly ...
  2939. //But popup comes from JRE7 - can not fix it, on other hand 6 will go manual install route
  2940. resolveAndLaunch(app, platform, v, cb, launchFunc);
  2941. } else {
  2942. launchFunc();
  2943. }
  2944. }
  2945. function doRegister(id, platform, cb) {
  2946. //we will record static object and process it once onload is done
  2947. addOnDomReady(function() {
  2948. processStaticObject(id, platform, cb);
  2949. });
  2950. }
  2951. //perform basic (lightweight) initialization
  2952. init();
  2953. /**
  2954. The Java Deployment Toolkit is utility to deploy Java content in
  2955. the browser as applets or applications using right version of Java.
  2956. If needed it can initiate upgrade of user's system to install required
  2957. components of Java platform.
  2958. <p>
  2959. Note that some of Deployment Toolkit methods may not be fully operational if
  2960. used before web page body is loaded (because DT native plugins could not be instantiated).
  2961. If you intend to use it before web page DOM tree is ready then dtjava.js needs to be loaded inside the
  2962. body element of the page and before use of other DT APIs.
  2963. @class dtjava
  2964. @static */
  2965. return {
  2966. /**
  2967. Version of Javascript part of Deployment Toolkit.
  2968. Increasing date lexicographically.
  2969. @property version
  2970. @type string
  2971. */
  2972. version: "20150817",
  2973. /**
  2974. Validate that platform requirements are met.
  2975. @param platform {Platform}
  2976. (Optional) set of platform requirements.
  2977. <p>
  2978. Default settings are
  2979. <ul>
  2980. <li>platform.jvm : "1.6+"
  2981. <li>platform.javafx : null
  2982. <li>platform.plugin : "*"
  2983. </ul>
  2984. @return {PlatformMismatchEvent}
  2985. Returns null if all requirements are met.
  2986. Return PlatformMismatchEvent describing the problem otherwise.
  2987. */
  2988. validate: function(platform) {
  2989. return doValidate(platform, ua.noPluginWebBrowser);
  2990. },
  2991. /**
  2992. Perform install of missing components based on given
  2993. platform requirements. By default if automated install is
  2994. not possible then manual install will be offered.
  2995. @method install
  2996. @param platform {Platform}
  2997. Description of platform requirements.
  2998. @param callbacks {Callbacks}
  2999. Optional set of callbacks to customize install experience.
  3000. @return {boolean}
  3001. Returns true if install was initiated.
  3002. */
  3003. install: function(platform, callbacks) {
  3004. return doInstall(null, platform, callbacks, null);
  3005. },
  3006. // (TODO: AI: what are limitations on "connect back to origin host?"
  3007. // can someone provide us fake JNLP url to get access to other host?
  3008. // Perhaps we should support this for relative URLs only?)
  3009. /**
  3010. Launch application (not embedded into browser) based on given
  3011. application descriptor. If launch requirements are not met
  3012. then autoinstall may be initiated if requested and supported.
  3013. By default autoinstall is disabled.
  3014. @method launch
  3015. @param ld {App | string | array}
  3016. Application launch descriptor. Could be defined as one of following:
  3017. <ul>
  3018. <li>instance of App object,
  3019. <li>string with URL of application JNLP file
  3020. <li>or array (where URL attribute is required)
  3021. </ul>
  3022. At least link to JNLP file must be provided (could be full URL or relative to
  3023. document location).
  3024. <p>
  3025. Note that passing parameters through the Apps object is not supported by this method.
  3026. Any parameters specified will be ignored.
  3027. @param platform {Platform}
  3028. Optional platform requirements (such as JRE and JavaFX versions).
  3029. @param callbacks {Callbacks | array}
  3030. Optional set of callbacks. See Callbacks for details.
  3031. */
  3032. //this will not use jvargs either but we do not necessary need to document it
  3033. launch: function(ld, platform, callbacks) {
  3034. return doLaunch(ld, platform, callbacks);
  3035. },
  3036. /**
  3037. Embeds application into browser based on given application descriptor
  3038. (required elements: url of JNLP file, width and height, id or reference to placeholder node).
  3039. <p>
  3040. If JRE or JavaFX installation is required then default handler is to return "click to install" html snippet.
  3041. To enable autoinstall custom onDeployError handler need to be used.
  3042. <p>
  3043. If applet can not be launched because platform requirements are not met
  3044. (e.g. DT plugin is not available or mandatory parameters are missing)
  3045. return value will be null.
  3046. <p>
  3047. Set applet identifier in the launch descriptor if you want to name your
  3048. applet in the DOM tree (e.g. to use it from javascript later).
  3049. @method embed
  3050. @param ld {App | string | array}
  3051. Application launch descriptor. Could be defined as one of following:
  3052. <ul>
  3053. <li>instance of App object,
  3054. <li>array (where attribute names are same as in App object)
  3055. </ul>
  3056. At least link to JNLP file, width and height must be provided.
  3057. @param platform {Platform}
  3058. Optional platform requirements (such as JRE and JavaFX versions).
  3059. @param cb {Callbacks | array}
  3060. Optional set of callbacks. See Callbacks for details.
  3061. @return {void}
  3062. */
  3063. embed: function(ld, platform, cb) {
  3064. return doEmbed(ld, platform, cb);
  3065. },
  3066. /**
  3067. Registers statically deployed Java applet to customize loading experience
  3068. if Javascript is enabled.
  3069. <p>
  3070. Note that launch of statically deployed applet will be initiated
  3071. before this this function will get control. Hence platform
  3072. requirements listed here will NOT be validated prior to launch
  3073. and will be used if applet launch can not be initiated otherwise.
  3074. @method register
  3075. @param id
  3076. Identifier of application.
  3077. @param platform {Platform}
  3078. Optional platform requirements (such as JRE and JavaFX versions).
  3079. @param cb {Callbacks | array}
  3080. Optional set of callbacks. See Callbacks for details.
  3081. */
  3082. register: function(id, platform, callbacks) {
  3083. return doRegister(id, platform, callbacks);
  3084. },
  3085. /**
  3086. * Hides html splash panel for applet with given id.
  3087. * If splash panel does not exist this method has no effect.
  3088. * For JavaFX applications this method will be called automatically once application is ready.
  3089. * For Swing/AWT applets application code need to call into this method explicitly if they were deployed
  3090. * with custom splash handler.
  3091. *
  3092. * @method hideSplash
  3093. * @param id Identifier of applet whose splash panel need to be hidden
  3094. */
  3095. hideSplash: function(id) {
  3096. return doHideSplash(id);
  3097. },
  3098. /**
  3099. Helper function: cross-browser onLoad support
  3100. <p>
  3101. This will call fn() once document is loaded.
  3102. If page is already loaded when this method is
  3103. called then fn() is called immediately.
  3104. <p>
  3105. If strictMode is true then fn() is called once page
  3106. and all its assets are loaded (i.e. when document
  3107. ready state will be 'complete').
  3108. Otherwise fn() is called after DOM tree is fully created
  3109. (but some assets may not yet be loaded).
  3110. <p>
  3111. It is ok to call this function multiple times. It will append
  3112. to existing chain of events (and do not replace them).
  3113. @method addOnloadCallback
  3114. @param {function} fn
  3115. (required) function to call
  3116. @param strictMode {boolean} Flag indicating whether page assets need to
  3117. be loaded before launch (default is false).
  3118. */
  3119. addOnloadCallback: function(fn, strictMode) {
  3120. //WORKAROUND for RT-21574
  3121. // avoid using onDomReady because it leads to deadlocks
  3122. if (strictMode || (ua.chrome && !ua.win)) {
  3123. addOnload(fn);
  3124. } else {
  3125. addOnDomReady(fn);
  3126. }
  3127. },
  3128. /**
  3129. * Add onJavascriptReady and onDeployError callbacks
  3130. * to the existing Java applet or JavaFX application.
  3131. * Application need to be alive in the browser DOM tree for this to work
  3132. *
  3133. * @param id {string} applet id
  3134. * @param cb {array} Set of callbacks. If null then pending callbacks are installed (if any for this applet).
  3135. * @private
  3136. */
  3137. installCallbacks: function(id, cb) {
  3138. doInstallCallbacks(id, cb);
  3139. },
  3140. /** Platform requirements for application launch.
  3141. <p><br>
  3142. The version pattern strings are of the form #[.#[.#[_#]]][+|*],
  3143. which includes strings such as "1.6", * "2.0*", and "1.6.0_18+".
  3144. <p>
  3145. A star (*) means "any version within this family" where family is defined
  3146. by prefix and a plus (+) means "any version greater or equal to the specified version".
  3147. For example "1.6.0*" matches 1.6.0_25 but not 1.7.0_01,
  3148. whereas "1.6.0+" or "1.*" match both.
  3149. <p>
  3150. If the version pattern does not include all four version components
  3151. but does not end with a star or plus, it will be treated as if it
  3152. ended with a star. "2.0" is exactly equivalent to "2.0*", and will
  3153. match any version number beginning with "2.0".
  3154. <p>
  3155. Null version string is treated as "there is no requirement to have it installed".
  3156. Validation will pass whether this component is installed or not.
  3157. <p>
  3158. Both "+" and "*" will match any installed version of component. However if component is not
  3159. installed then validation will fail.
  3160. @class Platform
  3161. @for dtjava
  3162. @constructor
  3163. @param r {array}
  3164. Array describing platform requirements. Element names should match
  3165. Platform properties.
  3166. */
  3167. Platform: function(r) {
  3168. //init with defaults
  3169. /**
  3170. JRE/JVM version.
  3171. @property jvm
  3172. @type version pattern string
  3173. @default "1.6+"
  3174. */
  3175. this.jvm = "1.6+";
  3176. /**
  3177. Minimum JavaFX version.
  3178. @property javafx
  3179. @type version pattern string
  3180. @default null
  3181. */
  3182. this.javafx = null;
  3183. /**
  3184. Java Plugin version.
  3185. If set to null then browser plugin support for embedded content is not validated.
  3186. @property plugin
  3187. @type version pattern string
  3188. @default "*"
  3189. */
  3190. this.plugin = "*";
  3191. /**
  3192. List of requested JVM arguments.
  3193. @property jvmargs
  3194. @type string
  3195. @default null
  3196. */
  3197. this.jvmargs = null;
  3198. //copy over
  3199. for (var v in r) {
  3200. this[v] = r[v];
  3201. //we expect jvmargs to come as array. if not - convert to array
  3202. if (this["jvmargs"] != null && typeof this.jvmargs == "string") {
  3203. this["jvmargs"] = this["jvmargs"].split(" ");
  3204. }
  3205. }
  3206. /**
  3207. * @method toString
  3208. * @return {string}
  3209. * Returns string replesentation of platform spec. Useful for debugging.
  3210. */
  3211. this.toString = function() {
  3212. return "Platform [jvm=" + this.jvm + ", javafx=" + this.javafx
  3213. + ", plugin=" + this.plugin + ", jvmargs=" + this.jvmargs + "]";
  3214. };
  3215. },
  3216. /**
  3217. Application launch descriptor.
  3218. @class App
  3219. @for dtjava
  3220. @constructor
  3221. @param url {string}
  3222. (Required) location of JNLP file. Could be full URL or partial
  3223. relative to document base.
  3224. @param details {array}
  3225. (Optional) set of values for other object properties.
  3226. Name should match documented object properties.
  3227. */
  3228. App: function(url, details) {
  3229. /**
  3230. Location of application's JNLP file. Can not be null or undefined.
  3231. @property url
  3232. @type string
  3233. */
  3234. this.url = url;
  3235. //default behavior
  3236. this.scriptable = true;
  3237. this.sharedjvm = true;
  3238. if (details != undefined && details != null) {
  3239. /**
  3240. Identifier of this App. Expected to be unique on this page.
  3241. If null then it is autogenerated.
  3242. @property id
  3243. @type string
  3244. */
  3245. this.id = details.id;
  3246. /**
  3247. Base64 encoded content of JNLP file.
  3248. @property jnlp_content
  3249. @type string
  3250. */
  3251. this.jnlp_content = details.jnlp_content;
  3252. /**
  3253. Applet width. Could be absolute or relative (e.g. 50 or 50%)
  3254. @property width
  3255. @type string
  3256. */
  3257. this.width = details.width;
  3258. /**
  3259. Applet height. Could be absolute or relative (e.g. 50 or 50%)
  3260. @property height
  3261. @type int
  3262. */
  3263. this.height = details.height;
  3264. /**
  3265. Set of named parameters to pass to application.
  3266. @property params
  3267. @type array
  3268. */
  3269. this.params = details.params;
  3270. /**
  3271. If set to true then Javascript to Java bridge will be initialized.
  3272. Note that some platform requirements imply Javascript bridge is initialized anyways.
  3273. If set to false the Java to Javascript calls are still possible.
  3274. //TODO: AI: will it affect applet callbacks?
  3275. @property scriptable
  3276. @type boolean
  3277. @default true
  3278. */
  3279. this.scriptable = details.scriptable;
  3280. /**
  3281. True if application does not need JVM instance to be dedicated to this application.
  3282. Some of platform requirements may imply exclusive use of JVM.
  3283. <p>
  3284. Note that even if sharing is enabled java plugin may choose to run applets in different JVM
  3285. instances. There is no way to force java plugin to reuse same JVM.
  3286. @property sharedjvm
  3287. @type boolean
  3288. @default true
  3289. */
  3290. this.sharedjvm = details.sharedjvm;
  3291. /**
  3292. Reference to DOM node to embed application into.
  3293. If not provided by the user and application is embedded then will be allocated dynamically.
  3294. <p>
  3295. Note that element may be not inserted into the DOM tree yet.
  3296. <p>
  3297. User may also provide identifier of the existing DOM node to be used as placeholder.
  3298. @property placeholder
  3299. @type {DOM node | DOM node id}
  3300. @default null
  3301. */
  3302. this.placeholder = details.placeholder;
  3303. /**
  3304. Tookit used by the application.
  3305. By default it is "fx" (and null is treated as JavaFX too).
  3306. Swing applications embedding JavaFX components need to pass "swing"
  3307. */
  3308. this.toolkit = details.toolkit;
  3309. }
  3310. /**
  3311. * Returns string representation of this object.
  3312. *
  3313. * @return {string}
  3314. */
  3315. this.toString = function() {
  3316. var pstr = "null";
  3317. var first = true;
  3318. if (notNull(this.params)) {
  3319. pstr = "{";
  3320. for (p in this.params) {
  3321. pstr += ((first) ? "" : ", ") + p + " => " + this.params[p];
  3322. first = false;
  3323. }
  3324. pstr += "}";
  3325. }
  3326. return "dtjava.App: [url=" + this.url + ", id=" + this.id + ", dimensions=(" + this.width + "," + this.height + ")"
  3327. + ", toolkit=" + this.toolkit
  3328. + ", embedded_jnlp=" + (notNull(this.jnlp_content) ? (this.jnlp_content.length + " bytes") : "NO")
  3329. + ", params=" + pstr + "]";
  3330. }
  3331. },
  3332. /**
  3333. Set of callbacks to be used to customize user experience.
  3334. @class Callbacks
  3335. @for dtjava
  3336. @constructor
  3337. @param cb {list of callbacks}
  3338. set of callbacks to set
  3339. */
  3340. Callbacks: function(cb) {
  3341. /**
  3342. Callback to be called to obtain content of the splash panel. Gets application
  3343. launch descriptor as an input. If null is returned then splash is disabled.
  3344. Non-null return value is expected to be html snippet to be added into splash overlay.
  3345. Only applicable to embed().
  3346. <p>
  3347. Note that autohiding splash is not supported by all platforms. Splash will be hidden by default
  3348. for JavaFX application but not for Swing/AWT applets. In later case if use of splash is desirable
  3349. then app need to call dtjava.hideSplash() explicitly to initiate hiding splash.
  3350. @property onGetSplash
  3351. @type function(app)
  3352. @default Default splash panel for JavaFX applications embedded into web page, null otherwise.
  3353. */
  3354. this.onGetSplash = defaultGetSplashHandler;
  3355. /**
  3356. Called if embedding or launching application need
  3357. additional components to be installed. This callback is
  3358. responsible for handling such situation, e.g. reporting
  3359. need to install something to the user,
  3360. initiating installation using install() and
  3361. hiding splash panel for embedded apps (if needed).
  3362. After installation is complete callback implementation may
  3363. retry attempt to launch application using provided launch function.
  3364. <p>
  3365. This method is NOT called if platform requirement could not be met
  3366. (e.g. if platfrom is not supported or if installation
  3367. is not possible).
  3368. <p>Default handler provides "click to install" solution for
  3369. embedded application and attempt to perform installation without
  3370. additional questions for apps started using launch().
  3371. <p>
  3372. If handler is null then it is treated as no op handler.
  3373. <p>
  3374. Parameters:
  3375. <ul>
  3376. <li> <b>app</b> - application launch descriptor.
  3377. For embedded applications app.placeholder will refer to
  3378. the root of the applet area in the DOM tree (to be used for
  3379. visual feedback)
  3380. <li> <b>platform</b> - application platform requirements
  3381. <li> <b>cb</b> - set of callbacks to be used during
  3382. installation process
  3383. <li> <b>isAutoinstall</b> - true if install can be launched
  3384. automatically
  3385. <li> <b>needRestart</b> - true if browser restart will be required
  3386. once installation is complete
  3387. <li> <b>launchFunction</b> - function to be executed to
  3388. retry launching the application once installation is finished
  3389. </ul>
  3390. @property onInstallNeeded
  3391. @type function(app, platform, cb, isAutoinstall, needRelaunch, launchFunc)
  3392. @default Default implementation shows "click to install" banner
  3393. for embedded applications or initiates installation immediately
  3394. for applications launched from web page.
  3395. */
  3396. this.onInstallNeeded = defaultInstallHandler;
  3397. /**
  3398. Called before installation of required component is triggered.
  3399. For manual install scenario it is called before installation
  3400. page is opened.
  3401. <p>
  3402. This method can be used to provide visual feedback to the user
  3403. during the installation. Placeholder
  3404. points to the area that can be used for visualization,
  3405. for embedded applications it will be applet area.
  3406. If null then callee need to find place for visualization on its own.
  3407. <p>
  3408. In case of automatic launch of installation onInstallFinished will be called
  3409. once installation is complete (succesfully or not).
  3410. <p>
  3411. If handler is null then it is treated as no-op handler.
  3412. Parameters:
  3413. <ul>
  3414. <li> <b>placeholder</b> - DOM element to insert visual feedback into.
  3415. If null then callee need to add visual feedback to the document on its own
  3416. (e.g. placeholder will be null if installation is not happening in context of embedding application into
  3417. web page).
  3418. <li> <b>component</b> - String "Java", "JavaFX" or "Java bundle"
  3419. <li> <b>isAutoInstall</b> - true if installer will be launched
  3420. automatically
  3421. <li> <b>restartNeeded</b> - boolean to specify whether browser restart will be required
  3422. </ul>
  3423. @property onInstallStarted
  3424. @type function(placeholder, component, isAuto, restartNeeded)
  3425. @default No-op
  3426. */
  3427. this.onInstallStarted = defaultInstallStartedHandler;
  3428. /**
  3429. Called once installation of required component
  3430. is completed. This method will NOT be called if installation is
  3431. performed in manual mode.
  3432. Parameters:
  3433. <ul>
  3434. <li> <b>placeholder</b> - DOM element that was passed to
  3435. onInstallStarted to insert visual feedback into.
  3436. <li> <b>component</b> - String "jre" or "javafx"
  3437. <li> <b>status</b> - status code is string categorizing the status of install.
  3438. ("success", "error:generic", "error:download" or "error:canceled")
  3439. <li> <b>relaunchNeeded</b> - boolean to specify
  3440. whether browser restart is required to complete the installation
  3441. </ul>
  3442. @property onInstallFinished
  3443. @type function(placeholder, component, status, relaunchNeeded)
  3444. @default no op
  3445. */
  3446. this.onInstallFinished = defaultInstallFinishedHandler;
  3447. /**
  3448. This function is called if application can not be deployed because
  3449. current platform does not match given platform requirements.
  3450. It is also called if request to install missing components can not be
  3451. completed due to platform.
  3452. <p>
  3453. Problem can be fatal error or transient issue (e.g. relaunch needed). Further
  3454. details can be extracted from provided mismatchEvent. Here are some typical combinations:
  3455. <ul>
  3456. <li><em>Current browser is not supported by Java</em> - (r.isUnsupportedBrowser())
  3457. <li><em>Browser need to be restarted before application can be launched</em> - (r.isRelaunchNeeded())
  3458. <li>JRE specific codes
  3459. <ul>
  3460. <li><em>JRE is not supported on this platform</em> - (r.jreStatus() == "unsupported")
  3461. <li><em>JRE is not detected and need to be installed</em> - (r.jreStatus() == "none")
  3462. <li><em>Installed version of JRE does not match requirements</em> - (r.jreStatus() == "old")
  3463. <li><em>Matching JRE is detected but deprecated Java plugin is used and
  3464. it does not support JNLP applets</em> - (r.jreStatus() == "oldplugin")
  3465. </ul>
  3466. <li> JavaFX specific codes
  3467. <ul>
  3468. <li><em>JavaFX is not supported on this platform</em> - (r.javafxStatus() == "unsupported")
  3469. <li><em>JavaFX Runtime is missing and need to be installed manually</em> - (r.javafxStatus() == "none")
  3470. <li><em>Installed version of JavaFX Runtime does not match requirements</em> - (r.javafxStatus() == "old")
  3471. <li><em>JavaFX Runtime is installed but currently disabled</em> - (r.javafxStatus() == "disabled")
  3472. </ul>
  3473. </ul>
  3474. Default error handler handles both application launch errors and embedded content.
  3475. @property onDeployError
  3476. @type function(app, mismatchEvent)
  3477. */
  3478. this.onDeployError = defaultDeployErrorHandler;
  3479. /**
  3480. * Called to get content to be shown in the applet area if Java plugin is not installed
  3481. * and none of callbacks helped to resolve this.
  3482. *
  3483. * @property onGetNoPluginMessage
  3484. * @type function(app)
  3485. * @return DOM Element object representing content to be shown in the applet area if
  3486. * java plugin is not detected by browser.
  3487. */
  3488. this.onGetNoPluginMessage = defaultGetNoPluginMessageHandler;
  3489. /**
  3490. Called once applet is ready to accept Javascript calls.
  3491. Only supported for plugin version 10.0.0 or later
  3492. @property onJavascriptReady
  3493. @type function(id)
  3494. @default null
  3495. */
  3496. this.onJavascriptReady = null;
  3497. /**
  3498. Called if application failed to launch.
  3499. Only supported for plugin version 10.0.0 or later.
  3500. @property onRuntimeError
  3501. @type function(id)
  3502. @default no op
  3503. */
  3504. this.onRuntimeError = defaultRuntimeErrorHandler;
  3505. //overwrite with provided parameters
  3506. for (c in cb) {
  3507. this[c] = cb[c];
  3508. }
  3509. }
  3510. };
  3511. }();