PageSourceSearch

https://cdn4.hola.org/www/hola/pub/app_checker.js

js hola.org collected 2026-09-24 10:18:36 UTC 11,297 bytes, 350 lines download raw bytes

1// LICENSE_CODE ZON
2'use strict'; /*jslint node:true, browser:true*/
3var define;
4var is_node = typeof module=='object' && module.exports;
5if (is_node)
6    define = require('../../../util/require_node.js').define(module, '..');
7else
8    define = self.define;
9define(['/util/user_agent.js', '/util/etask.js', 'svc_versions',
10    '/util/version_util.js', '/www/hola/pub/lib/model.ts', '/svc/hola/pub/svc_ipc.js',
11    '/www/hola/pub/config.js', '/util/url.js', '/svc/vpn/pub/util.js'],
12    function(user_agent, etask, versions, version_util, hola_model,
13    svc_ipc, config, zurl, svc_vpn_util)
14    {
15var b = user_agent.guess_browser();
16var g = user_agent.guess();
17var is_ext_inited, is_svc_inited, is_reg_inited;
18var ext_etask, svc_etask, reg_etask;
19
20// XXX pavlo: not working for MP use case now
21function msg_post_recv(opt){
22    var msg = opt.msg, on_msg;
23    return etask([function(){
24        on_msg = function(e){
25            if (e.source!=top || e.data.src==msg.src || e.data.id!=msg.id)
26                return;
27            this.continue(e.data);
28        }.bind(this);
29        try {
30            // will init exception on cross origin frame access
31            top.addEventListener('message', on_msg);
32        } catch(e){
33            this.continue();
34            return;
35        }
36        top.postMessage(msg, '*');
37        return this.wait(opt.timeout||5000);
38    }, function finally$(){
39        // will init exception on cross origin frame access
40        try { top.removeEventListener('message', on_msg); } catch(e){}
41    }]);
42}
43
44function check_ext(opt){
45    opt = opt||{};
46    return msg_post_recv({timeout: opt.timeout||2000,
47        msg: {src: 'hola_ccgi', id: 'callback'}});
48}
49
50function lean_check_ext(){ return svc_ipc.ext.lean_ping(); }
51
52function is_plugin(exe){ return /\bhola_plugin/.test(exe); }
53
54function check_svc(){
55    return etask([function(){
56        return svc_ipc.ajax('callback.json');
57    }, function catch$(ret){
58        throw {status: ret};
59    }, function(ret){
60        var data = ret.ret;
61        var xhr = ret.xhr;
62        return {data: data, status: xhr.statusText};
63    }]);
64}
65
66function get_registry(attrib){
67    return etask([function(){
68        return svc_ipc.ajax({cmd: 'get_registry.json',
69            data: {attrib: attrib}});
70    }, function(ret){
71        var data = ret.ret||{};
72        return data.value;
73    }]);
74}
75
76var info_model = new hola_model.Model({
77    on_svc_detected: [],
78    reset: function(){
79        is_ext_inited = is_svc_inited = is_reg_inited = false;
80        ext_etask = svc_etask = reg_etask = undefined;
81        config.set_hola_extension_info(undefined);
82        this.set('ext_info', undefined);
83        this.set('svc_info', undefined);
84        this.set('agree_ts', undefined);
85    },
86    is_latest_ext: function(){
87        var _this = this;
88        return etask([function(){
89            return _this.get_ext_info();
90        }, function(info){
91            if (!info || !info.build_info)
92                return false;
93            return version_util.cmp(info.ver,
94                versions[info.build_info.browser_build])>=0;
95        }]);
96    },
97    get_ext_info: function(){
98        var _this = this;
99        return etask([function(){
100            if (is_ext_inited)
101                return;
102            return _this._check_ext();
103        }, function(){
104            is_ext_inited = true;
105            return _this.get('ext_info');
106        }]);
107    },
108    get_svc_info: function(){
109        var _this = this;
110        return etask([function(){
111            if (is_svc_inited)
112                return;
113            return _this._check_svc();
114        }, function(){
115            is_svc_inited = true;
116            return _this.get('svc_info');
117        }]);
118    },
119    get_registry_info: function(){
120        // XXX sergeir: don't use agree_ts; use object for all keys
121        var _this = this;
122        return etask([function(){
123            if (is_reg_inited)
124                return;
125            return _this._check_registry();
126        }, function(){
127            is_reg_inited = true;
128            return {agree_ts: _this.get('agree_ts')};
129        }]);
130    },
131    is_ext: function(){
132        var _this = this;
133        return etask([function(){
134            return _this.get_ext_info();
135        }, function(info){
136            return !!info;
137        }]);
138    },
139    is_svc: function(){
140        var _this = this;
141        return etask([function(){
142            return _this.get_svc_info();
143        }, function(info){
144            return !!info && !info.err;
145        }]);
146    },
147    is_latest_svc: function(){
148        var _this = this;
149        return etask([function(){
150            return _this.get_svc_info();
151        }, function(info){
152            if (!info)
153                return false;
154            var v_os = g.os=='macos' ? versions.mac_svc :
155                svc_vpn_util.pick_version(versions,
156                svc_vpn_util.get_product(info.appid), 'windows');
157            return version_util.cmp(info.ver, v_os)>=0;
158        }]);
159    },
160    /**
161     * Waits for svc.
162     *
163     * @param {number} [timeout] Timeout in seconds.
164     * @returns {etask} Etask with svc info.
165     */
166    wait_for_svc: function(timeout){
167        var _this = this;
168        var spent = 0;
169        return etask.for(null, function(){ return etask.sleep(1000); },
170        [function try_catch$(){
171            spent++;
172            // _check_svc() will not work if we are currently using 'https', so
173            // call both, _check_ext() can provide svc info too.
174            this.spawn(_this._check_ext());
175            this.spawn(_this._check_svc());
176            this.spawn(_this._check_registry());
177            return this.wait_child('any');
178        }, function(){
179            return _this.get_svc_info();
180        }, function(info){
181            if (info || timeout && spent==timeout)
182                return this.break(info);
183        }]);
184    },
185    /**
186     * Waits for latest svc.
187     *
188     * @returns {etask} Etask with svc info.
189     */
190    wait_for_new_svc: function(){
191        var _this = this;
192        return etask.for(null, function(){ return etask.sleep(1000); },
193        [function try_catch$(){
194            // _check_svc() will not work if we are currently using 'https', so
195            // call both, _check_ext() can provide svc info too.
196            return etask.all({ext: _this._check_ext(), svc: _this
197            ._check_svc()});
198        }, function(){
199            return _this.is_latest_svc();
200        }, function(is_latest){
201            if (is_latest)
202                return this.break(_this.get('svc_info'));
203        }]);
204    },
205    /**
206     * Waits for latest extension.
207     *
208     * @param {boolean} [lean=false] Whether we should check using image
209     * {@link svc/hola/pub/svc_ipc.js:ext.lean_ping()}.
210     * @returns {etask} Etask with extension info.
211     */
212    wait_for_new_ext: function(lean){
213        var _this = this;
214        var previous_init_ts = (_this.get('ext_info')||{}).init_ts;
215        return etask.for(null, function(){ return etask.sleep(1000); },
216        [function try_catch$(){
217            if (lean)
218                return lean_check_ext();
219            return _this._check_ext();
220        }, function(e){
221            if (lean)
222            {
223                if (!this.error)
224                    return this.break();
225                return;
226            }
227            var new_info = !this.error && e;
228            if (!new_info)
229                return;
230            // in chrome, chrome.webstore.install will succeed if extension is
231            // already the the latest version, but the extension will not be
232            // reinstalled (so init_ts will not change).
233            if (b.browser=='chrome' && new_info.init_ts)
234                return this.break();
235            if (previous_init_ts==new_info.init_ts)
236                return;
237            return this.break(new_info);
238        }]);
239    },
240    _set_ext_info: function(info){
241        if (!info)
242            return;
243        this.set('ext_info', info);
244        if (info.svc_info && !info.svc_info.plugin)
245            this.set('svc_info', info.svc_info.raw);
246    },
247    _check_ext: function(){
248        var _this = this;
249        if (ext_etask)
250            return ext_etask;
251        this._set_ext_info(config.get_hola_extension_info());
252        ext_etask = etask([function try_catch$(){
253            return check_ext();
254        }, function(e){
255            ext_etask = null;
256            if (this.error || !e || !e.data)
257                return;
258            _this._set_ext_info(e.data);
259            return e.data;
260        }]);
261        return ext_etask;
262    },
263    _check_svc: function(){
264        var _this = this;
265        if (svc_etask)
266            return svc_etask;
267        if (window && window.no_svc_check)
268        {
269            _this.set('svc_info', undefined);
270            return;
271        }
272        if (window && window.location)
273        {
274            var qs = zurl.qs_parse(window.location.search.substr(1),
275                {safe: true});
276            if (qs.debug_svc=='off')
277            {
278                _this.set('svc_info', undefined);
279                return;
280            }
281            else if (qs.debug_svc)
282            {
283                var svc_i_json;
284                try {
285                    svc_i_json = JSON.parse(qs.debug_svc);
286                } catch(e){
287                    svc_i_json = {appid: qs.debug_svc};
288                }
289                console.log('detect debug svc info');
290                setTimeout(function(){
291                    console.log('set debug svc info');
292                    _this.set('svc_info', svc_i_json);
293                    if (svc_i_json && svc_i_json.uuid)
294                        _this.perr({id: 'www_detect_svc', info: svc_i_json});
295                }, 1000);
296                return;
297            }
298        }
299        svc_etask = etask([function try_catch$(){
300            return check_svc();
301        }, function(e){
302            svc_etask = null;
303            if (this.error || !e || !e.data)
304                return;
305            var info = e.data;
306            var v_os = g.os=='macos' ? versions.mac_svc :
307                svc_vpn_util.pick_version(versions,
308                svc_vpn_util.get_product(info.appid), 'windows');
309            info.is_latest_svc = version_util.cmp(info.ver, v_os)>=0;
310            if (is_plugin(info.exe))
311                return;
312            _this.set('svc_info', info);
313            if (info && info.uuid)
314            {
315                _this.perr({id: 'www_detect_svc', info: info});
316                try {
317                    _this.on_svc_detected.forEach(function(fn){
318                        fn({info: info});
319                    });
320                } catch(e){}
321            }
322        }]);
323        return svc_etask;
324    },
325    _check_registry: function(){
326        var _this = this;
327        if (g.os!='windows')
328            return;
329        if (reg_etask)
330            return reg_etask;
331        return reg_etask = etask([function try_catch$(){
332            return get_registry('agree_ts');
333        }, function(e){
334            reg_etask = null;
335            if (this.error || !e)
336                return;
337            _this.set('agree_ts', e);
338        }]);
339    },
340    perr: function(){
341        console.warn('not implemented');
342    },
343    set_perr_fn: function(fn){
344        this.perr = fn;
345    }
346});
347
348// Singleton.
349return info_model;
350});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.