Make same function name with its event name
[platform/framework/web/wrtjs.git] / wrt_app / src / runtime.ts
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16
17 'use strict';
18
19 import { wrt } from '../browser/wrt';  // Load first for log
20 import { addonManager } from './addon_manager';
21 import { app } from 'electron';
22 import { WebApplication } from './web_application';
23
24 class Runtime {
25   webApplication?: WebApplication = undefined;
26   isLaunched = false;
27   inspectorEnabledByVconf = false;
28
29   constructor() {
30     app.on('before-quit', (event: any) => {
31       console.log('before-quit');
32       this.webApplication?.beforeQuit();
33     });
34
35     app.on('will-quit', (event: any) => {
36       console.log('will-quit');
37       addonManager.deactivateAll();
38     });
39
40     app.on('quit', (event: any) => {
41       console.log('quit');
42       if (this.webApplication) {
43         this.webApplication.quit();
44         this.webApplication = undefined;
45       }
46     });
47
48     app.on('browser-window-created', () => {
49       console.log('browser-window-created');
50       if (!this.isLaunched) {
51         addonManager.activateAll();
52         this.isLaunched = true;
53       }
54     });
55
56     app.on('window-all-closed', () => {
57       console.log('window-all-closed');
58       app.quit();
59     });
60
61     app.on('web-contents-created', (event: any, webContents: any) => {
62       console.log('web-contents-created');
63       webContents.on('before-input-event', (event: any, input: any) => {
64         if (this.isLaunched && this.webApplication)
65           this.handleKeyEvents(input.key);
66       });
67     });
68
69     app.once('ready', (event: any) => {
70       console.log('ready');
71       let addonAvailable = addonManager.build();
72       console.log("addonBuild : " + addonAvailable);
73       if (addonAvailable) {
74         const XWalkExtension = require('../common/wrt_xwalk_extension');
75         XWalkExtension.initialize();
76         XWalkExtension.preventCleanup();
77       }
78       wrt.tv?.importCertificate('');
79     });
80
81     wrt.on('app-control', (event: any, appControl: any) => {
82       console.log('app-control');
83       let loadInfo = appControl.getLoadInfo();
84       let src = loadInfo.getSrc();
85
86       if (wrt.isElectronApp()) {
87         console.log('Electron App launch');
88         const Module = require('module');
89         Module.globalPaths.push(wrt.getAppPath());
90         let filePath = src[7] === '/' ? src.substr(8) : src.substr(7); // strip "file://"
91         let pkgJson = require(filePath);
92         let pos = filePath.lastIndexOf('/');
93
94         let mainJsPath = (pos !== -1 ? filePath.substr(0, pos + 1) : '') +
95                             (pkgJson.main || 'index.js');
96         console.log('loading path:', mainJsPath);
97         Module._load(mainJsPath, Module, true);
98         app.emit('ready');
99       } else {
100         console.log('Tizen Web App launch');
101         let launchMode = appControl.getData('http://samsung.com/appcontrol/data/launch_mode');
102         if (!this.webApplication) {
103           console.log('Creating WebApplication');
104           let options: RuntimeOption = {
105             isAddonAvailable: addonManager.isAddonAvailable(),
106             launchMode: launchMode
107           }
108           this.webApplication = new WebApplication(options);
109           if (wrt.tv) {
110             this.inspectorEnabledByVconf = wrt.tv.needUseInspector();
111             if (this.inspectorEnabledByVconf && launchMode != 'backgroundExecution') {
112               this.webApplication.inspectorSrc = src;
113               src = "about:blank";
114             }
115             let useDiskCache = appControl.getData('USE_DISKCACHE');
116             let halfWindowOption = appControl.getData('http://samsung.com/appcontrol/data/half_window_support');
117             wrt.tv.setDiskCache(useDiskCache);
118             wrt.tv.handleAppControlData(launchMode, halfWindowOption);
119           }
120           this.webApplication.mainWindow.loadURL(src);
121           this.webApplication.prelaunch(src);
122           if (wrt.da) {
123             this.webApplication.mainWindow.emit('ready-to-show');
124           }
125         } else {
126           console.log('Handling app-control event');
127           if (this.webApplication.preloadStatus == 'readyToShow') {
128             this.webApplication.show();
129           } else {
130             if (launchMode != 'backgroundAtStartup')
131               this.webApplication.preloadStatus = 'none';
132           }
133
134           let skipReload = appControl.getData('SkipReload');
135           if (skipReload == 'Yes') {
136             console.log('skipping reload');
137             // TODO : Need to care this situation and decide to pass the addon event emitter to resume()
138             this.webApplication.resume();
139             return;
140           }
141
142           let reload = loadInfo.getReload() || this.webApplication.isAlwaysReload;
143           if (!reload) {
144             let originalUrl = this.webApplication.mainWindow.webContents.getURL();
145             if (wrt.tv) {
146               console.log(`appcontrol src = ${src}, original url = ${originalUrl}`);
147               if (src && originalUrl) {
148                 let appcontrolUrl = (new URL(src)).href;
149                 let oldUrl = (new URL(originalUrl)).href;
150                 console.log(`appcontrolUrl = ${appcontrolUrl}, oldUrl = ${oldUrl}`);
151                 // FIXME(dh81.song)
152                 // Below case it must be distinguishable for known cases
153                 //   from 'file:///index.htmlx' to 'file:///index.html'
154                 if (appcontrolUrl !== oldUrl.substr(0, appcontrolUrl.length))
155                   reload = true;
156               } else {
157                 reload = true;
158               }
159             } else if (src !== originalUrl) {
160               reload = true;
161             }
162           }
163           // handle http://tizen.org/appcontrol/operation/main operation specially.
164           // only menu-screen app can send launch request with main operation.
165           // in this case, web app should have to resume web app not reset.
166           if (reload && appControl.getOperation() == 'http://tizen.org/appcontrol/operation/main')
167             reload = false;
168           if (reload)
169             this.webApplication.handleAppControlReload(src);
170           else
171             this.webApplication.sendAppControlEvent();
172         }
173       }
174       this.launchInspector(appControl);
175     });
176
177     wrt.on('suspend', () => {
178       console.log('suspend');
179       this.webApplication?.suspend();
180     });
181
182     wrt.on('resume', () => {
183       console.log('resume');
184       this.webApplication?.resume();
185     });
186
187     wrt.on('low-memory', () => {
188       console.log('low-memory');
189       this.webApplication?.lowMemory();
190     });
191
192     wrt.on('message', (event: any, type: string, params: string[]) => {
193       console.log('message type(' + type + ') params : ' + params);
194       const app_id = params[0];
195       if (type === 'startService') {
196         require('../common/service_manager').startService(app_id, params[1]);
197         event.preventDefault();
198       } else if (type === 'stopService') {
199         require('../common/service_manager').stopService(app_id);
200         event.preventDefault();
201       }
202     });
203
204     wrt.on('ambient-tick', () => {
205       this.webApplication?.ambientTick();
206     });
207
208     wrt.on('ambient-changed', (event: any, ambient_mode: boolean) => {
209       console.log('ambient-changed , ambient_mode:' + ambient_mode);
210       this.webApplication?.ambientChanged(ambient_mode);
211     });
212
213     wrt.on('addon-installed', (event: any, path: string) => {
214       console.log('addon-installed at ' + path);
215       addonManager.checkAddon(path);
216     });
217
218     wrt.on('addon-uninstalled', (event: any, id: string) => {
219       console.log('addon-unistalled named ' + id);
220     });
221
222     wrt.on('wgt-checking-done', (event: any) => {
223       console.log('wgt-checking-done');
224       addonManager.updateDB();
225     });
226
227     /* FIXME: will uncheck after chromium-efl released */
228     if (wrt.getPlatformType() !== "product_tv")
229       wrt.getInstalledPkg();
230   }
231
232   private launchInspector(appControl: NativeWRTjs.AppControl) {
233     this.launchInspector = (param) => {}; // call once
234     console.log('launchInspector');
235
236     // AUL public key/Vconf - To support inspector
237     if (this.checkInspectorCondition(appControl)) {
238       let debugPort = wrt.startInspectorServer();
239       let data = { "port" :  [ debugPort.toString() ] };
240       if (this.webApplication)
241         this.webApplication.debugPort = debugPort;
242       appControl.reply(data);
243     }
244   }
245
246   private checkInspectorCondition(appControl: NativeWRTjs.AppControl) {
247     let bundleDebug = (appControl.getData('__AUL_DEBUG__') === "1");
248     return (bundleDebug || this.inspectorEnabledByVconf);
249   }
250
251   private handleKeyEvents(key: string) {
252     let valid = false;
253     console.log(key + ' is pressed');
254     switch(key) {
255       case "ArrowUp":
256       case "Up":
257       case "ArrowDown":
258       case "Down":
259         valid = true;
260         break;
261       default:
262         console.log('No handler for the key ' + key);
263         break;
264     }
265     if (valid)
266       this.webApplication?.keyEvent(key);
267   }
268 }
269
270 new Runtime();