view class doc
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833/// FOURJS_START_COPYRIGHT(D,2015)
/// Property of Four Js*
/// (c) Copyright Four Js 2015, 2022. All Rights Reserved.
/// * Trademark of Four Js Development Tools Europe Ltd
///   in the United States and elsewhere
///
/// This file can be modified by licensees according to the
/// product manual.
/// FOURJS_END_COPYRIGHT

"use strict";

modulum("VMSession", ["EventListener", "VMSessionTabbedContainerMode", "VMSessionBrowserMultiPageMode"],
  function(context, cls) {
    /**
     * A VM driven Session
     * @class VMSession
     * @memberOf classes
     * @extends classes.EventListener
     * @publicdoc Base
     */
    cls.VMSession = context.oo.Class(cls.EventListener, function($super) {
      return /** @lends classes.VMSession.prototype */ {
        __name: "VMSession",
        /**
         * @type {?string}
         */
        _identifier: null,
        /**
         * @type {?string}
         */
        _sessionId: null,
        /**
         * @type {classes.VMApplication[]}
         */
        _applications: null,

        /**
         * app id bootstrapped by the GAS
         * if not 0, is is loaded as a new tab/window in browser
         * @type {number}
         */
        _htmlHostPageAppId: 0,

        _baseInfos: null,
        _closeHandler: null,
        _restartHandler: null,
        /**
         * @type {classes.SessionWidget}
         */
        _widget: null,
        _bookmarkWidget: null,
        _applicationIdentifier: 0,
        _applicationQueue: null,

        _waitingNewTasks: 0,
        _showEnding: false,
        _flushingApplications: false,
        _flushingApplicationsListener: false,
        _unloadListener: false,
        _flushableApplications: null,
        /** @type {?string} */
        _logPromptUrl: null,
        /** @type Window */
        _logPromptWindow: null,
        /** @type classes.SessionLogPromptWidget */
        _logPromptWidget: null,
        /** @type string[] */
        _serverFeatures: null,
        /** @type {?string} */
        _endUrl: null,

        _sessionMode: null,

        /** @type {classes.VMSessionNavigationManager} */
        _navigationManager: null,

        /**
         * @inheritDoc
         * @constructs
         * @param {?string} identifier session identifier
         */
        constructor: function(identifier) {
          $super.constructor.call(this);
          this._navigationManager = new cls.VMSessionNavigationManager(this);
          this._htmlHostPageAppId = context.bootstrapInfo.subAppInfo;
          this._widget = cls.WidgetFactory.createWidget("Session", {
            appHash: gbc.systemAppId,
            session: this
          });
          this._widget.when(context.constants.widgetEvents.titleChanged,
            (title) => context.HostService.setDocumentTitle());
          context.HostService.getApplicationHostWidget().addChildWidget(this._widget);
          context.HostLeftSidebarService.addSession(this);
          this._identifier = identifier;
          this._applications = [];
          this._applicationQueue = [];
          this._closeHandler = this._widget.getEndWidget().when(context.constants.widgetEvents.close, () => this.destroy());
          this._restartHandler = this._widget.getEndWidget().when(context.constants.widgetEvents.restart, () => this._onRestart());

          this._flushableApplications = [];
          context.HostLeftSidebarService.setTitle(i18next.t("gwc.main.sidebar.title"));
          // if context.bootstrapInfo.subAppInfo > 0, we are in a child window
          if (this._htmlHostPageAppId) {
            this.activateBrowserMultiPageMode();
          }
          this._flushingApplicationsListener = context.InitService.when(
            gbc.constants.widgetEvents.onBeforeUnload, () => this._flushWaitingApplications());
          this._unloadListener = context.InitService.when(
            gbc.constants.widgetEvents.onUnload, () => this._destroyChildrenWindows());
          this._serverFeatures = [];
        },
        _onRestart: function() {
          if (context.bootstrapInfo.reloadOnRestart === "true") {
            window.location.reload(true);
            return;
          }
          var info = this._baseInfos;
          this.destroy(true);
          context.SessionService.startApplication(info.appId, info.urlParameters);
        },
        getWidget: function() {
          return this._widget;
        },
        getIdentifier: function() {
          return this._identifier;
        },

        getApplicationIdentifier: function() {
          return this._applicationIdentifier++;
        },

        destroy: function(restarting) {
          context.SessionService.remove(this, true === restarting);
          if (this._sessionMode) {
            this._sessionMode.destroy();
            this._sessionMode = null;
          }
          this._closeHandler();
          this._restartHandler();

          //context.HostLeftSidebarService.removeSession(this); //No need

          if (this._navigationManager) {
            this._navigationManager.destroy();
            this._navigationManager = null;
          }
          this._widget.destroy();
          this._widget = null;
          this._applications.length = 0;
          this._applicationQueue.length = 0;
          this._flushingApplicationsListener();
          this._destroyChildrenWindows();
          $super.destroy.call(this);
        },
        getConnector: function() {
          return this._baseInfos.connector;
        },
        /**
         * Get the session ID
         * @return {string} the session ID
         * @publicdoc
         */
        getSessionId: function() {
          return this._sessionId;
        },

        setSessionId: function(id) {
          if (!this._sessionId) {
            this._sessionId = id;
            context.SessionService.updateSessionId(this, id);
          } else if (id !== this._sessionId) {
            this.error("Session Id Changed");
          }
        },
        getAppId: function() {
          return this._baseInfos.appId;
        },
        error: function(msg) {

        },

        /**
         * @returns {classes.VMSessionNavigationManager}
         */
        getNavigationManager: function() {
          return this._navigationManager;
        },

        /**
         *
         * @param {classes.VMApplication} application
         */
        add: function(application) {
          let queueSize = this._applicationQueue.length;
          this._applications.push(application);

          if (queueSize === 0 || this._applicationQueue[queueSize - 1] !== application) {
            this._applicationQueue.push(application);
          }

          application.__idleChangedSessionHook = application.dvm.onIdleChanged(
            () => this._onIdleChanged(application));
          this.emit(context.constants.baseEvents.applicationAdded, application);
        },
        /**
         *
         * @param {classes.VMApplication} application
         */
        remove: function(application) {
          application.__idleChangedSessionHook();
          this._navigationManager.removeApplication(application);
          this._applications.remove(application);
          this._applicationQueue.remove(application);
          this._applicationEnding = application.info().ending;
          var pos = 0;

          while (pos < this._applicationQueue.length) {
            if (this._applicationQueue[pos] === this._applicationQueue[pos + 1]) {
              this._applicationQueue.splice(pos, 1);
            } else {
              pos++;
            }
          }

          this.emit(context.constants.baseEvents.applicationRemoved, application);
          var currentApp = this.getNewApplication(application);

          if (currentApp) {
            this.setCurrentApplication(currentApp);
            var currentWindow = currentApp.getVMWindow();
            if (currentWindow) {
              var appWidget = currentApp.getUI().getWidget(),
                winWidget = currentWindow.getController().getWidget();

              this.getNavigationManager().setLastActiveWindow(currentApp, currentWindow.getId());
              winWidget.domAttributesMutator(() => appWidget.removeClass("inactiveWindow"));

              this._widget.setCurrentWidget(appWidget);
              context.HostService.setDisplayedWindowNode(currentWindow);
            }
          }

          this._showEnding = true;
          this._updateDisplayEnd();
        },

        _updateDisplayEnd: function() {
          if (this._showEnding && !this._applications.length) {
            if (!this._destroyed) {
              this.getWidget().showWaitingEnd();
            }
            context.HostService.unsetDisplayedWindowNode();

            var delay = 0;

            if (context.BrowserWindowsService.isRootWindow() && this.isInBrowserMultiPageMode()) {
              delay = 1000;
            }

            this._registerTimeout(() => {
              if (!(
                  (context.BrowserWindowsService.isRootWindow() &&
                    context.BrowserWindowsService.countChildWindows(
                      (w) => (!/monitor=true/.test(window._multiWindowData.directChildren[0].location.search)))) ||
                  (this.isInBrowserMultiPageMode() && this._waitingNewTasks > 0))) {
                if (this._waitingNewTasks === 0 && !this._destroyed) {
                  context.HostLeftSidebarService.setContent();
                  if (this.isInTabbedContainerMode()) {
                    this._sessionMode.freeIdleHook();
                  }
                  this.displayEnd();
                }
                this.displayEnd();
              }
            }, delay);
          }
        },
        _autoclose: function() {
          this._registerTimeout(() => {
            var can = !this._flushableApplications || !this._flushableApplications.length;
            if (can) {
              cls.WindowHelper.closeWindow();
            } else {
              this._autoclose();
            }
          }, 200);
        },

        /**
         * Terminate the session
         * (This is always called by window.onunload with forceServer=true)
         * @param {boolean} [forceServer] true to send a session close (/ua/close) to the server (if supported)
         * @publicdoc
         */
        closeSession: function(forceServer) {
          // if forceServer and is not child of an other tab (stantdalone or browserMultiPage activated),
          // send session /ua/close if has feature
          if (forceServer && this.isMasterBrowserPage() && this.hasServerFeature("close-session")) {
            if (this._applications && this._applications[0]) {
              this._applications[0].protocolInterface.closeSession();
            }
            // if forceServer and is child of an other tab (browserMultiPage activated)
            // try to send app /ua/close (will free parent app processing if RUN was called)
          } else if (forceServer && !this.isMasterBrowserPage() && this._applications[0]) {
            this._applications[0].close();
          } else {
            while (this._applications.length) {
              this._applications[0].stop();
            }
          }
        },

        setEndUrl: function(url) {
          this._endUrl = url;
        },

        displayEnd: function() {
          if (!this.isMasterBrowserPage()) {
            this._autoclose();
            return;
          }
          this.emit(context.constants.baseEvents.displayEnd, this._baseInfos.session);
          if (this.getWidget()) {
            this.getWidget().getEndWidget().setHeader(i18next.t("gwc.app.ending.title"));
            // disable sidebar on session end
            context.HostLeftSidebarService.enableSidebar(false);
            if (this._baseInfos.session) {
              this.getWidget().getEndWidget().showSessionActions();
              this.getWidget().getEndWidget().setSessionLinks(this._baseInfos.customUA || this._baseInfos.connector || "",
                this._baseInfos.session);
              //cls.AuiApplicationService.linkDownload();
              this.getWidget().getEndWidget().setSessionID(this._baseInfos.session);
            }
            if (this._baseInfos.mode === "ua") {
              this.getWidget().getEndWidget().showUAActions();
            }
            if (!this._applicationEnding.normal) {

              switch (this._applicationEnding.flag) {
                case "notFound":
                  this.getWidget().getEndWidget().setHeader(i18next.t("gwc.app.notFound.title"));
                  this.getWidget().getEndWidget().setMessage(i18next.t("gwc.app.notFound.message", {
                    appId: "<strong>\"" + this._baseInfos.appId + "\"</strong>"
                  }));
                  break;
                case "notok":
                  this.getWidget().getEndWidget().setMessage(
                    "<p data-details='notok'>" + i18next.t("gwc.app.error.message") + ".</p><p>" + this._applicationEnding
                    .message +
                    "</p>");
                  break;
                case "forbidden":
                  this.getWidget().getEndWidget().setMessage(
                    "<p data-details='forbidden'>" + i18next.t("gwc.app.forbidden.message") + ".</p><p>" + this._applicationEnding
                    .message + "</p>");
                  break;
                case "autoLogout":
                  this.getWidget().getEndWidget().setMessage(
                    "<p data-details='autoLogout'>" + i18next.t("gwc.app.autologout.message") + ".</p>");
                  break;
                case "uaProxy":
                  this.getWidget().getEndWidget().setMessage(
                    "<p data-details='uaProxy'>" + i18next.t("gwc.app.uaProxy.message") + ".</p><p>" + this._applicationEnding
                    .message +
                    "</p>");
                  break;
              }
            }
            if (this._endUrl) {
              this.getWidget().showRedirectEnd();
              window.location.href = this._endUrl;
            } else if (this._applicationEnding.flag !== "hidden") {
              this.getWidget().showEnd();
            }
          }
          this.displayLogPrompt();
          context.HostService.unsetDisplayedWindowNode();
        },

        displayLogPrompt: function(promptUrl) {
          var latePromptHandling = !this._logPromptUrl && Boolean(promptUrl);
          if (!latePromptHandling) {
            this._trackPromptEnding();
          }
          if (this._logPromptUrl !== promptUrl) {
            this._logPromptUrl = promptUrl;
            if (!this._logPromptUrl) {
              document.body.removeClass("logPrompting");
              if (this._logPromptWindow) {
                this._logPromptWindow.close();
                this._logPromptWindow = null;
              }
              if (this._logPromptWidgetHandle) {
                this._logPromptWidgetHandle();
              }
              if (this._logPromptWidget) {
                this._logPromptWidget.destroy();
                this._logPromptWidget = null;
              }
            } else {
              if (latePromptHandling) {
                this._trackPromptEnding();
              }
              if (!this._logPromptWidget) {
                this._logPromptWidget = cls.WidgetFactory.createWidget("SessionLogPrompt", {
                  appHash: gbc.systemAppId
                });
                this._logPromptWidgetHandle = this._logPromptWidget.when(context.constants.widgetEvents.click, function() {
                  if (this.isMasterBrowserPage()) {
                    this._displayLogPopup();
                  } else {
                    var opener = window.opener,
                      openerSession = opener && opener.gbc && opener.gbc.SessionService.getCurrent();
                    if (openerSession) {
                      openerSession._displayLogPopup();
                    }
                  }
                }.bind(this));
                document.body.appendChild(this._logPromptWidget.getElement());
              }
              if (this.isMasterBrowserPage()) {
                if (!this._logPromptWindow) {
                  document.body.addClass("logPrompting");
                } else {
                  this._logPromptWindow.location.href = this._logPromptUrl;
                }
              }
            }
          }
        },
        _displayLogPopup: function() {
          if (!this._logPromptWindow || this._logPromptWindow.closed) {
            this._logPromptWindow = window.open(this._logPromptUrl, "",
              "resizable,scrollbars,status,width=" + window.innerWidth + ",height=" + window.innerHeight +
              ",top=" + window.screenTop + ",left=" + window.screenLeft);
          } else if (this._logPromptWindow) {
            this._logPromptWindow.focus();
          }
        },

        _trackPromptEnding: function() {
          if (this._logPromptUrl) {
            var hasOnlyIdle = true,
              protocolInterface = this.getApplications()[0] && this.getApplications()[0].protocolInterface,
              protocolAlive = protocolInterface && protocolInterface.isAlive();
            this.getApplications().forEach(function(app) {
              hasOnlyIdle = hasOnlyIdle && app.isIdle();
            });
            if (hasOnlyIdle && protocolAlive) {
              protocolInterface.trackPrompt();
            }
          }
        },

        /**
         *
         * @param {string[]} features
         */
        addServerFeatures: function(features) {
          for (var i = 0; i < features.length; i++) {
            var feature = features[i].trim();
            if (this._serverFeatures.indexOf(feature) < 0) {
              this._serverFeatures.push(feature);
            }
          }
        },
        /**
         *
         * @param {string} feature
         * @return {boolean}
         */
        hasServerFeature: function(feature) {
          return Boolean(this._serverFeatures) && this._serverFeatures.indexOf(feature) >= 0;
        },
        /**
         *
         * @returns {boolean}
         */
        isEmpty: function() {
          return !this._applications.length;
        },

        start: function(appName, params) {
          var info = new cls.VMApplicationInfo({
            appId: appName,
            urlParameters: params || (
              context.bootstrapInfo.queryString ?
              new cls.QueryString(context.bootstrapInfo.queryString).copyContentsObject() :
              context.UrlService.currentUrl().getQueryStringObject()
            )
          });
          info.connector = info.urlParameters.connector || context.bootstrapInfo.connectorUri || "";
          info.customUA = info.urlParameters.customUA || null;
          info.mode = info.urlParameters.mode || "ua";
          info.inNewWindow = !this.isMasterBrowserPage();
          if (info.inNewWindow) {
            info.session = this._sessionId = context.bootstrapInfo.sessionId;
            context.HostLeftSidebarService.setTitle(i18next.t("gwc.main.sidebar.multitab_title"));
          }
          this._baseInfos = info;
          var application = new cls.VMApplication(info, this);
          var appWidget = application.getUI().getWidget();
          this.add(application);
          this._widget.setCurrentWidget(appWidget);
          application.start();
          this._registerNewTask(application.protocolInterface);
          return application;
        },

        startSubTask: function(taskId, taskProcIdParent = null, taskWaiting = null, callback = () => {}) {
          let info = {
            ...(this._baseInfos || {})
          };
          info.connectionInfo = {};
          info.urlParameters = {
            ...(this._baseInfos.urlParameters || {})
          };
          info.inNewWindow = this.isInBrowserMultiPageMode() || (!this.isMasterBrowserPage() && (this._htmlHostPageAppId !== taskId));

          if (info.inNewWindow) {
            info.urlParameters = context.bootstrapInfo.queryString ?
              new cls.QueryString(context.bootstrapInfo.queryString).copyContentsObject() :
              context.UrlService.currentUrl().getQueryStringObject();
            info.connector = info.urlParameters.connector || context.bootstrapInfo.connectorUri || "";
            info.customUA = info.urlParameters.customUA || null;
            info.mode = info.urlParameters.mode || "ua";
          }
          if (!this.isMasterBrowserPage()) {
            context.HostLeftSidebarService.setTitle(i18next.t("gwc.main.sidebar.multitab_title"));
            this._sessionId = context.bootstrapInfo.sessionId;
            info.session = this._sessionId;
          }

          info.task = true;
          info.page = 2;
          info.app = taskId;
          info.taskProcIdParent = taskProcIdParent;
          info.taskWaiting = taskWaiting;

          let hostingWindow = taskWaiting && window._multiWindowData.findWindowBy((w) => {
            const session = w && w.gbc && w.gbc.SessionService.getCurrent();
            if (session) {
              return session.getApplications().find(
                (app) => app.info() && app.info().connectionInfo.procId === taskProcIdParent);
            }
            return null;
          });
          info.inNewWindow = info.inNewWindow && !hostingWindow;
          if (!info.inNewWindow) {
            const session = hostingWindow ? hostingWindow.gbc.SessionService.getCurrent() : this;
            session._startSubTaskLocally(info, callback);
          } else {
            let application = new cls.VMApplication(new cls.VMApplicationInfo(info), this);
            application.waitForApplicationInNewWindow(() => {
              this.waitedForNewTask();
              callback(application);
            }, () => {});
          }
        },

        _startSubTaskLocally: function(info, callback) {
          let application = new cls.VMApplication(new cls.VMApplicationInfo(info), this);
          var appWidget = application.getUI().getWidget();
          this._widget.setCurrentWidget(appWidget);
          this.add(application);
          application.start();
          this.waitedForNewTask();
          callback(application);
        },

        /**
         *
         * @param {window.gbcWrapper} wrapper
         * @param {Object<string, *>} headers
         */
        startDirect: function(wrapper, readyData) {
          context.HostLeftSidebarService.enableSidebar(true);
          let meta = cls.AuiProtocolReader.translate(readyData.meta)[0];
          var info = new cls.VMApplicationInfo({
            pingTimeout: 1000,
            connectionInfo: meta.attributes,
            procId: meta.attributes.procId,
            page: 1,
            auiOrder: 0,
            mode: "direct",
            nativeResourcePrefix: readyData.nativeResourcePrefix.replace(/\/$/, "") + "/__dvm__/"
          });
          if (readyData.headers) {
            var headersKeys = Object.keys(context.constants.network.startHeaders);
            for (var i = 0; i < headersKeys.length; i++) {
              var key = headersKeys[i];
              var value = context.constants.network.startHeaders[key];
              info[value.prop || key] = readyData.headers[context.constants.network.headers[key]];
            }
          }

          gbc.classes.EncodingHelper.setVMEncoding(meta.attributes.encoding.toLowerCase());

          info.wrapper = wrapper;
          this._baseInfos = info;
          var application = new cls.VMApplication(info, this);
          application.setProcessing();
          application.procId = info.procId;
          var appWidget = application.getUI().getWidget();
          this._widget.setCurrentWidget(appWidget);
          this.add(application);
          this._navigationManager.updateApplicationInformation(application);
          application.start();
        },
        onApplicationAdded: function(hook) {
          return this.when(context.constants.baseEvents.applicationAdded, hook);
        },
        onApplicationRemoved: function(hook, once) {
          return this.when(context.constants.baseEvents.applicationRemoved, hook, once);
        },

        info: function() {
          return this._baseInfos;
        },

        /**
         * Get all running applications
         * @returns {classes.VMApplication[]} an array of applications or null
         * @publicdoc
         */
        getApplications: function() {
          return this._applications;
        },

        /**
         * Get the current application
         * @returns {classes.VMApplication}
         */
        getCurrentApplication: function() {
          if (this._applications.length && this._applications[this._applications.length - 1]) {
            return this._applications[this._applications.length - 1];
          }
          return null;
        },

        /**
         *
         * @returns {classes.VMApplication}
         */
        getApplicationByHash: function(hash) {
          return this._applications && this._applications.filter(function(item) {
            return item.applicationHash === hash;
          })[0];
        },
        getApplicationByProcId: function(procId) {
          return this._applications && this._applications.filter(function(item) {
            return item.procId === procId || (item.info() && item.info().procId === procId);
          })[0];
        },
        setCurrentApplication: function(application) {
          var index = this._applications.indexOf(application);
          if (index !== -1) {
            this._applications.splice(index, 1);
            this._applications.push(application);
          }
        },
        _onIdleChanged: function(application) {
          this.emit(context.constants.baseEvents.idleChanged, application);
        },
        whenIdleChanged: function(hook) {
          return this.when(context.constants.baseEvents.idleChanged, hook);
        },
        isCurrentIdle: function() {
          var app = this.getCurrentApplication();
          return !app || app.dvm.processed && app.dvm.idle && app.layout.isIdle() && app.typeahead.hasFinished();
        },

        _addWaitingApplication: function(application) {
          this._flushableApplications.push(application);
        },
        _removeWaitingApplication: function(application) {
          this._flushableApplications.remove(application);
        },
        _flushWaitingApplications: function() {
          this._flushingApplications = true;
          while (this._flushableApplications && this._flushableApplications.length) {
            cls.WindowHelper.openWindow(cls.UANetwork.newApp(this._flushableApplications.shift(), null, null, {
              noQueryString: true
            }), true);
          }
        },
        _registerNewTask: function(protocolInterface) {
          this._storedProtocol = protocolInterface;
        },
        newTask: function() {
          if (this._storedProtocol) {
            this._storedProtocol.newTask();
          }
        },
        _registerChildWindow: function(win) {
          if (win) {
            window._emergencyClose = window._emergencyClose || {};
            win.addEventListener("load", function() {
              window._emergencyClose[win.gbc.uid] = [];
              win.addEventListener("unload", function() {
                if (window.browserInfo.isFirefox) {
                  var emergencyCloses = window._emergencyClose[win.gbc.uid];
                  for (var i = 0; i < emergencyCloses.length; i++) {
                    var closeInfo = emergencyCloses[i];
                    cls.UANetwork.querySend("close", null, closeInfo, function() {}, null, null);
                  }
                }
                if (win.location.href !== "about:blank") { // thank you firefox
                  this._updateDisplayEnd();
                }
              }.bind(this));
            }.bind(this));
          }
        },
        _destroyChildrenWindows: function() {
          context.BrowserWindowsService.closeAllChildren();
        },
        waitingForNewTask: function() {
          this._waitingNewTasks++;
        },

        waitedForNewTask: function() {
          if (this._waitingNewTasks > 0) {
            this._waitingNewTasks--;
          }
          this._updateDisplayEnd();
        },

        isInBrowserMultiPageMode: function() {
          return this._sessionMode && this._sessionMode.isInstanceOf(cls.VMSessionBrowserMultiPageMode);
        },

        isMasterBrowserPage: function() {
          return !this._htmlHostPageAppId;
        },

        isInTabbedContainerMode: function() {
          return this._sessionMode && this._sessionMode.isInstanceOf(cls.VMSessionTabbedContainerMode);
        },

        displayChanged: function() {
          let app = null;
          if (this.isInTabbedContainerMode()) {
            app = this._sessionMode.triggerDisplayChanged();
          }
          return app;
        },

        /**
         *
         * @param {classes.WindowNode} windowNode
         */
        activateTabbedContainerMode: function(windowNode) {
          if (!this._sessionMode && windowNode) {
            this._sessionMode = new cls.VMSessionTabbedContainerMode(this);
            this._sessionMode.activate(windowNode);
            context.HostLeftSidebarService.setApplicationListVisibility(true);
            context.HostLeftSidebarService.setTabbedContainerMode(true);
          }
        },

        getHostApplication: function() {
          return this.isInTabbedContainerMode() && this._sessionMode.getHostApplication();
        },

        activateBrowserMultiPageMode: function() {
          if (!this._sessionMode && (this.getApplications().length === 1)) {
            this._sessionMode = new cls.VMSessionBrowserMultiPageMode(this);
            context.HostLeftSidebarService.setTitle(i18next.t("gwc.main.sidebar.multitab_title"));
          }
        },

        /**
         * '
         * @param {classes.VMApplication} app
         * @param {classes.ApplicationWidget} appWidget
         */
        addApplicationWidget: function(app, appWidget) {
          if (this.isInTabbedContainerMode()) {
            this._sessionMode.addApplicationWidget(app, appWidget);
          } else {
            this.getWidget().addChildWidget(appWidget);
          }
        },

        manageStartMenu: function(startMenuNode, widget) {
          if (this.isInTabbedContainerMode() && this._sessionMode.willManageStartMenu()) {
            this._sessionMode.manageStartMenu(startMenuNode, widget);
          } else {
            startMenuNode.getAncestor("UserInterface").getController().getWidget().addStartMenu(widget);
          }
        },

        /**
         * Get the running application corresponding to the remove application
         * @param removedApplication
         * @return {classes.VMApplication}
         */
        getNewApplication: function(removedApplication) {
          let parentProcId = removedApplication.getParentProcId();

          if (!parentProcId || this._applicationQueue.length === 1) {
            return this._applicationQueue[this._applicationQueue.length - 1];
          }

          let app = null;
          let childApp = null;
          let procId = parentProcId;
          //Search the running child
          do {
            app = this._navigationManager.getApplicationByProcId(procId);
            childApp = app && this._navigationManager.getChildApplication(app);
            procId = childApp && childApp.getProcId();
          } while (app && app.isProcessing() && childApp);

          return app;
        },

        /**
         * Get the application with identifier = applicationIdentifier
         * @param {number} applicationIdentifier
         * @return {classes.VMApplication|undefined}
         */
        getApplicationByIdentifier: function(applicationIdentifier) {
          return this._applications.find((app) => {
            return app.applicationHash === applicationIdentifier;
          });
        }
      };
    });
  });