Refactors initDisplayDelay function for readability
[platform/framework/web/wrtjs.git] / wrt_app / src / web_application.ts
index 430a593..e6cc16c 100644 (file)
@@ -37,6 +37,7 @@ export class WebApplication {
   backgroundSupport = wrt.getBackgroundSupport();
   debugPort = 0;
   firstRendered = false;
+  contentSrc = '';
   inspectorSrc = '';
   loadFinished = false;
   pendingCallbacks: Map<number, any> = new Map();
@@ -69,12 +70,12 @@ export class WebApplication {
     this.setupEventListener(options);
 
     this.mainWindow = new WRTWindow(this.getWindowOption(options));
-    this.initDisplayDelay(true);
+    this.initDisplayDelay();
     this.setupMainWindowEventListener();
   }
 
   private setupEventListener(options: RuntimeOption) {
-    app.on('browser-window-created', (event, window) => {
+    app.on('browser-window-created', (event: any, window: any) => {
       if (this.windowList.length > 0)
         this.windowList[this.windowList.length - 1].hide();
       this.windowList.push(window);
@@ -88,12 +89,14 @@ export class WebApplication {
           this.windowList[this.windowList.length - 1].show();
       });
     });
-    app.on('web-contents-created', (event, webContents) => {
+
+    app.on('web-contents-created', (event: any, webContents: any) => {
       webContents.on('crashed', function() {
         console.error('webContents crashed');
         app.exit(100);
       });
-      webContents.session.setPermissionRequestHandler((webContents, permission, callback) => {
+
+      webContents.session.setPermissionRequestHandler((webContents: any, permission: string, callback: any) => {
         console.log(`handlePermissionRequests for ${permission}`);
         if (permission === 'notifications') {
           if (!this.notificationPermissionMap)
@@ -127,7 +130,8 @@ export class WebApplication {
         }
       });
     });
-    app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
+
+    app.on('certificate-error', (event: any, webContents: any, url: string, error: string, certificate: any, callback: any) => {
       console.log('A certificate error has occurred');
       event.preventDefault();
       if (certificate.data) {
@@ -140,7 +144,8 @@ export class WebApplication {
         callback(false);
       }
     });
-    app.on('login', (event, webContents, request, authInfo, callback) => {
+
+    app.on('login', (event: any, webContents: any, request: any, authInfo: any, callback: any) => {
       console.log(`Login info is required, isproxy: ${authInfo.isProxy}`);
       event.preventDefault();
       let usrname = '';
@@ -165,9 +170,10 @@ export class WebApplication {
         wrt.handleAuthRequest(id, webContents);
       }
     });
+
     if (this.accessiblePath) {
       console.log(`accessiblePath: ${this.accessiblePath}`);
-      protocol.interceptFileProtocol('file', (request, callback) => {
+      protocol.interceptFileProtocol('file', (request: any, callback: any) => {
         if (request.url) {
           let parsed_info = new URL(request.url);
           let access_path = parsed_info.host + decodeURI(parsed_info.pathname);
@@ -190,11 +196,12 @@ export class WebApplication {
           console.log('request url is empty');
           (callback as any)(403);
         }
-      }, (error) => {
+      }, (error: Error) => {
         console.log(error);
       });
     }
-    wrt.on('permission-response', (event, id, result) => {
+
+    wrt.on('permission-response', (event: any, id: number, result: boolean) => {
       console.log(`permission-response for ${id} is ${result}`);
       let callback = this.pendingCallbacks.get(id);
       if (typeof callback === 'function') {
@@ -203,7 +210,8 @@ export class WebApplication {
         this.pendingCallbacks.delete(id);
       }
     });
-    wrt.on('auth-response', (event, id, submit, user, password) => {
+
+    wrt.on('auth-response', (event: any, id: number, submit: boolean, user: string, password: string) => {
       let callback = this.pendingCallbacks.get(id);
       if (typeof callback === 'function') {
         console.log('calling auth response callback');
@@ -214,7 +222,8 @@ export class WebApplication {
         this.pendingCallbacks.delete(id);
       }
     });
-    wrt.on('app-status-changed', (event, status) => {
+
+    wrt.on('app-status-changed', (event: any, status: string) => {
       console.log(`runningStatus: ${status}, ${this.loadFinished}`);
       if (!wrt.tv)
         return;
@@ -238,7 +247,8 @@ export class WebApplication {
       show: false,
       webPreferences: {
         nodeIntegration: options.isAddonAvailable,
-        nodeIntegrationInWorker: false
+        nodeIntegrationInWorker: false,
+        nativeWindowOpen: true,
       },
       webContents: WRTWebContents.create(),
     };
@@ -258,10 +268,12 @@ export class WebApplication {
       }
       this.show();
     });
+
     this.mainWindow.webContents.on('did-start-loading', () => {
       console.log('webContents did-start-loading');
       this.loadFinished = false;
     });
+
     this.mainWindow.webContents.on('did-finish-load', () => {
       console.log('webContents did-finish-load');
       this.loadFinished = true;
@@ -278,35 +290,30 @@ export class WebApplication {
     });
   }
 
-  private initDisplayDelay(firstLaunch: boolean) {
-    // TODO: On 6.0, this causes a black screen on relaunch
-    if (firstLaunch)
-      this.firstRendered = false;
+  private enableWindow() {
     this.suspended = false;
+    // TODO: On 6.0, this causes a black screen on relaunch
     if (this.showTimer)
       clearTimeout(this.showTimer);
-    let splashShown = firstLaunch && wrt.showSplashScreen();
-    if (!splashShown && !wrt.tv) {
-      this.showTimer = setTimeout(() => {
-        if (!this.suspended) {
-          console.log('FrameRendered not obtained from engine. To show window, timer fired');
-          this.mainWindow.emit('ready-to-show');
-        }
-      }, 2000);
-    }
-    if (!firstLaunch && !this.backgroundRunnable())
+    if (!this.backgroundRunnable())
       this.mainWindow.setEnabled(true);
   }
 
-  private backgroundRunnable(): boolean {
-    return this.backgroundSupport || this.backgroundExecution;
+  private initDisplayDelay() {
+    let splashShown = this.preloadStatus !== 'preload' && wrt.showSplashScreen();
+    if (splashShown || wrt.tv)
+      return;
+
+    this.showTimer = setTimeout(() => {
+      if (!this.suspended) {
+        console.log('FrameRendered not obtained from engine. To show window, timer fired');
+        this.mainWindow.emit('ready-to-show');
+      }
+    }, 2000);
   }
 
-  handleAppControlReload(url: string) {
-    console.log('WebApplication : handleAppControlReload');
-    this.closeWindows();
-    this.initDisplayDelay(false);
-    this.mainWindow.loadURL(url);
+  private backgroundRunnable(): boolean {
+    return this.backgroundSupport || this.backgroundExecution;
   }
 
   private suspendByStatus() {
@@ -344,6 +351,58 @@ Then you can get profile log from the initial loading.`;
     }
   }
 
+  handleAppControlEvent(appControl: any) {
+    let launchMode = appControl.getData('http://samsung.com/appcontrol/data/launch_mode');
+    this.handlePreloadState(launchMode);
+
+    let skipReload = appControl.getData('SkipReload');
+    if (skipReload == 'Yes') {
+      console.log('skipping reload');
+      // TODO : Need to care this situation and decide to pass the addon event emitter to resume()
+      this.resume();
+      return;
+    }
+
+    let loadInfo = appControl.getLoadInfo();
+    let src = loadInfo.getSrc();
+    let reload = loadInfo.getReload() || this.needReload(src);
+    // handle http://tizen.org/appcontrol/operation/main operation specially.
+    // only menu-screen app can send launch request with main operation.
+    // in this case, web app should have to resume web app not reset.
+    if (reload && appControl.getOperation() == 'http://tizen.org/appcontrol/operation/main')
+      reload = false;
+    if (reload)
+      this.handleAppControlReload(src);
+    else
+      this.sendAppControlEvent();
+  }
+
+  private launchInspectorIfNeeded(appControl: NativeWRTjs.AppControl) {
+    console.log('launchInspectorIfNeeded');
+    let inspectorEnabledByVconf = wrt.tv ? wrt.tv.needUseInspector() : false;
+    if (inspectorEnabledByVconf && !this.backgroundExecution) {
+      this.inspectorSrc = this.contentSrc;
+      this.contentSrc = 'about:blank';
+    }
+    let hasAulDebug = (appControl.getData('__AUL_DEBUG__') === '1');
+    if (hasAulDebug || inspectorEnabledByVconf) {
+      let debugPort = wrt.startInspectorServer();
+      let data = { "port": [debugPort.toString()] };
+      this.debugPort = debugPort;
+      appControl.reply(data);
+    }
+  }
+
+  loadUrl(appControl: NativeWRTjs.AppControl) {
+    this.contentSrc = appControl.getLoadInfo().getSrc();
+    this.launchInspectorIfNeeded(appControl);
+    this.mainWindow.loadURL(this.contentSrc);
+    this.prelaunch(this.contentSrc);
+    if (wrt.da) {
+      this.mainWindow.emit('ready-to-show');
+    }
+  }
+
   suspend() {
     if (this.suspended || this.inQuit)
       return;
@@ -379,8 +438,8 @@ Then you can get profile log from the initial loading.`;
     this.windowList[this.windowList.length - 1].show();
   }
 
-  finalize() {
-    console.log('WebApplication : finalize');
+  quit() {
+    console.log('WebApplication : quit');
     this.flushData();
     this.windowList.forEach((window) => window.removeAllListeners());
     this.inQuit = false;
@@ -388,8 +447,8 @@ Then you can get profile log from the initial loading.`;
       this.suspend();
   }
 
-  quit() {
-    console.log('WebApplication : quit');
+  beforeQuit() {
+    console.log('WebApplication : beforeQuit');
     addonManager.emit('lcQuit', this.mainWindow.id);
     if (wrt.tv) {
       this.inspectorSrc = '';
@@ -403,6 +462,48 @@ Then you can get profile log from the initial loading.`;
     this.inQuit = true;
   }
 
+  private needReload(src: string) {
+    if (this.isAlwaysReload) {
+      return true;
+    }
+    let reload = false;
+    let originalUrl = this.mainWindow.webContents.getURL();
+    if (wrt.tv) {
+      console.log(`appcontrol src = ${src}, original url = ${originalUrl}`);
+      if (src && originalUrl) {
+        let appcontrolUrl = (new URL(src)).href;
+        let oldUrl = (new URL(originalUrl)).href;
+        console.log(`appcontrolUrl = ${appcontrolUrl}, oldUrl = ${oldUrl}`);
+        // FIXME(dh81.song)
+        // Below case it must be distinguishable for known cases
+        //   from 'file:///index.htmlx' to 'file:///index.html'
+        if (appcontrolUrl !== oldUrl.substr(0, appcontrolUrl.length))
+          reload = true;
+      } else {
+        reload = true;
+      }
+    } else if (src !== originalUrl) {
+      reload = true;
+    }
+    return reload;
+  }
+
+  private handleAppControlReload(url: string) {
+    console.log('WebApplication : handleAppControlReload');
+    this.closeWindows();
+    this.enableWindow();
+    this.mainWindow.loadURL(url);
+  }
+
+  private handlePreloadState(launchMode: string) {
+    if (this.preloadStatus == 'readyToShow') {
+      this.show();
+    } else {
+      if (launchMode != 'backgroundAtStartup')
+        this.preloadStatus = 'none';
+    }
+  }
+
   private flushData() {
     console.log('WebApplication : FlushData');
     this.windowList.forEach((window) => window.webContents.session.flushStorageData());