/**
   * Rewrites the given browser string based on server settings.
   *
   * @param inputString the input browser string
   * @return a possibly-modified browser string.
   * @throws IllegalArgumentException if inputString is null.
   */
  private String validateBrowserString(String inputString, RemoteControlConfiguration configuration)
      throws IllegalArgumentException {
    String browserString = inputString;
    if (configuration.getForcedBrowserMode() != null) {
      browserString = configuration.getForcedBrowserMode();
      log.info("overriding browser mode w/ forced browser mode setting: " + browserString);
    }
    if (configuration.getProxyInjectionModeArg() && browserString.equals("*iexplore")) {
      log.warning(
          "running in proxy injection mode, but you used a *iexplore browser string; this is "
              + "almost surely inappropriate, so I'm changing it to *piiexplore...");
      browserString = "*piiexplore";
    } else if (configuration.getProxyInjectionModeArg()
        && (browserString.equals("*firefox")
            || browserString.equals("*firefox2")
            || browserString.equals("*firefox3"))) {
      log.warning(
          "running in proxy injection mode, but you used a "
              + browserString
              + " browser string; this is "
              + "almost surely inappropriate, so I'm changing it to *pifirefox...");
      browserString = "*pifirefox";
    }

    if (null == browserString) {
      throw new IllegalArgumentException("browser string may not be null");
    }
    return browserString;
  }
  public FrameGroupCommandQueueSet(
      String sessionId, int portDriversShouldContact, RemoteControlConfiguration configuration) {

    this.sessionId = sessionId;
    this.portDriversShouldContact = portDriversShouldContact;
    this.configuration = configuration;
    this.extensionJs = "";
    proxyInjectionMode = configuration.getProxyInjectionModeArg();

    /*
     * Initialize delay, using the static CommandQueue getSpeed
     * in order to imitate previous behavior, wherein that static
     * field would control the speed for all sessions.  The
     * speed for a frame group's queues will only be changed if
     * they're changed via this class's setSpeed().
     */
    millisecondDelayBetweenOperations = new AtomicInteger(CommandQueue.getSpeed());
  }
  /**
   * Gets a new browser session
   *
   * @param browserString
   * @param startURL
   * @param extensionJs per-session user extension Javascript
   * @param configuration Remote Control configuration. Cannot be null.
   * @param useCached if a cached session should be used if one is available
   * @param ensureClean if a clean session (e.g. no previous cookies) is required.
   * @return the BrowserSessionInfo for the new browser session.
   * @throws RemoteCommandException
   */
  protected BrowserSessionInfo getNewBrowserSession(
      String browserString,
      String startURL,
      String extensionJs,
      Capabilities browserConfigurations,
      boolean useCached,
      boolean ensureClean,
      RemoteControlConfiguration configuration)
      throws RemoteCommandException {

    BrowserSessionInfo sessionInfo = null;
    browserString = validateBrowserString(browserString, configuration);

    if (configuration.getProxyInjectionModeArg()) {
      InjectionHelper.setBrowserSideLogEnabled(configuration.isBrowserSideLogEnabled());
      InjectionHelper.init();
    }

    if (useCached) {
      log.info("grabbing available session...");
      sessionInfo = grabAvailableSession(browserString, startURL);
    }

    // couldn't find one in the cache, or not reusing sessions.
    if (null == sessionInfo) {
      log.info("creating new remote session");
      sessionInfo =
          createNewRemoteSession(
              browserString,
              startURL,
              extensionJs,
              browserConfigurations,
              ensureClean,
              configuration);
    }

    assert null != sessionInfo;
    if (false /* ensureClean */) {
      // need to add this to the launcher API.
      // sessionInfo.launcher.hideCurrentSessionData();
    }
    return sessionInfo;
  }