/**
  * Ends a browser session.
  *
  * @param sessionId the id of the session to be ended
  * @param configuration Remote Control configuration. Cannot be null.
  * @param ensureClean if clean sessions (e.g. no leftover cookies) are required.
  */
 protected void endBrowserSession(
     boolean forceClose,
     String sessionId,
     RemoteControlConfiguration configuration,
     boolean ensureClean) {
   BrowserSessionInfo sessionInfo = lookupInfoBySessionId(sessionId, activeSessions);
   if (null != sessionInfo) {
     activeSessions.remove(sessionInfo);
     try {
       if (forceClose || !configuration.reuseBrowserSessions()) {
         shutdownBrowserAndClearSessionData(sessionInfo);
       } else {
         if (null != sessionInfo.session) { // optional field
           sessionInfo.session.reset(sessionInfo.baseUrl);
         }
         // mark what time this session was ended
         sessionInfo.lastClosedAt = System.currentTimeMillis();
         availableSessions.add(sessionInfo);
       }
     } finally {
       LoggingManager.perSessionLogHandler().removeSessionLogs(new SessionId(sessionId));
       if (ensureClean) {
         // need to add this to the launcher API.
         // sessionInfo.launcher.restoreOriginalSessionData();
       }
     }
   } else {
     // look for it in the available sessions.
     sessionInfo = lookupInfoBySessionId(sessionId, availableSessions);
     if (null != sessionInfo && (forceClose || !configuration.reuseBrowserSessions())) {
       try {
         availableSessions.remove(sessionInfo);
         shutdownBrowserAndClearSessionData(sessionInfo);
       } finally {
         LoggingManager.perSessionLogHandler().removeSessionLogs(new SessionId(sessionId));
         if (ensureClean) {
           // sessionInfo.launcher.restoreOriginalSessionData();
         }
       }
     }
   }
 }
  /**
   * Creates and tries to open a new session.
   *
   * @param browserString
   * @param startURL
   * @param extensionJs
   * @param configuration Remote Control configuration. Cannot be null.
   * @param ensureClean if a clean session is required
   * @return the BrowserSessionInfo of the new session.
   * @throws RemoteCommandException if the browser failed to launch and request work in the required
   *     amount of time.
   */
  protected BrowserSessionInfo createNewRemoteSession(
      String browserString,
      String startURL,
      String extensionJs,
      Capabilities browserConfiguration,
      boolean ensureClean,
      RemoteControlConfiguration configuration)
      throws RemoteCommandException {

    final FrameGroupCommandQueueSet queueSet;
    final BrowserSessionInfo sessionInfo;
    final BrowserLauncher launcher;
    String sessionId;

    sessionId = UUID.randomUUID().toString().replace("-", "");
    if ("*webdriver".equals(browserString) && browserConfiguration != null) {
      Object id = browserConfiguration.getCapability("webdriver.remote.sessionid");
      if (id != null && id instanceof String) {
        sessionId = (String) id;
      }
    }

    queueSet = makeQueueSet(sessionId, configuration.getPortDriversShouldContact(), configuration);
    queueSet.setExtensionJs(extensionJs);

    try {
      launcher =
          browserLauncherFactory.getBrowserLauncher(
              browserString, sessionId, configuration, browserConfiguration);
    } catch (InvalidBrowserExecutableException e) {
      throw new RemoteCommandException(e.getMessage(), "");
    }

    sessionInfo = new BrowserSessionInfo(sessionId, browserString, startURL, launcher, queueSet);
    SessionIdTracker.setLastSessionId(sessionId);
    log.info("Allocated session " + sessionId + " for " + startURL + ", launching...");

    final PerSessionLogHandler perSessionLogHandler = LoggingManager.perSessionLogHandler();
    perSessionLogHandler.attachToCurrentThread(new SessionId(sessionId));
    try {
      launcher.launchRemoteSession(startURL);
      queueSet.waitForLoad(configuration.getTimeoutInSeconds() * 1000l);

      // TODO DGF log4j only
      // NDC.push("sessionId="+sessionId);
      FrameGroupCommandQueueSet queue = getQueueSet(sessionId);
      queue.doCommand("setContext", sessionId, "");

      activeSessions.add(sessionInfo);
      return sessionInfo;
    } catch (Exception e) {
      /*
       * At this point the session might not have been added to neither available nor active
       * sessions. This session is unlikely to be of any practical use so we need to make sure we
       * close the browser and clear all session data.
       */
      log.log(
          Level.SEVERE,
          "Failed to start new browser session, shutdown browser and clear all session data",
          e);
      shutdownBrowserAndClearSessionData(sessionInfo);
      throw new RemoteCommandException("Error while launching browser", "", e);
    } finally {
      perSessionLogHandler.detachFromCurrentThread();
    }
  }