/**
   * Accepts a command reply, and retrieves the next command to run.
   *
   * @param commandResult - the reply from the previous command, or null
   * @param incomingFrameAddress - frame from which the reply came
   * @param uniqueId
   * @param justLoaded
   * @param jsWindowNameVars
   * @return - the next command to run
   */
  public RemoteCommand handleCommandResult(
      String commandResult,
      FrameAddress incomingFrameAddress,
      String uniqueId,
      boolean justLoaded,
      List<?> jsWindowNameVars) {
    CommandQueue queue = getCommandQueue(uniqueId);
    queue.setFrameAddress(incomingFrameAddress);
    if (jsWindowNameVars != null) {
      for (Object jsWindowNameVar : jsWindowNameVars) {
        queue.addJsWindowNameVar((String) jsWindowNameVar);
      }
    }

    if (justLoaded) {
      markWhetherJustLoaded(uniqueId, true);
      commandResult = null;
    }

    if (WindowClosedException.WINDOW_CLOSED_ERROR.equals(commandResult)) {
      queue.declareClosed();
      return new DefaultRemoteCommand("testComplete", "", "");
    }

    return queue.handleCommandResult(commandResult);
  }
 private void setCurrentFrameAddress(String uniqueId) {
   assert uniqueId != null;
   FrameAddress frameAddress = uniqueIdToCommandQueue.get(uniqueId).getFrameAddress();
   this.currentUniqueId = uniqueId;
   this.currentFrameAddress = frameAddress;
   this.currentSeleniumWindowName = frameAddress.getWindowName();
   this.currentLocalFrameAddress = frameAddress.getLocalFrameAddress();
   markWhetherJustLoaded(uniqueId, false);
   if (LOGGER.isDebugEnabled()) {
     LOGGER.debug("Current uniqueId set to " + uniqueId + ", frameAddress = " + frameAddress);
   }
 }
  private String waitForLoad(
      String waitingForThisWindowName, String waitingForThisLocalFrame, int timeoutInSeconds)
      throws RemoteCommandException {

    for (String matchingFrameAddress = null; timeoutInSeconds >= 0; timeoutInSeconds--) {
      dataLock.lock();
      try {
        LOGGER.debug(
            "waiting for window '"
                + waitingForThisWindowName
                + "' local frame '"
                + waitingForThisLocalFrame
                + "' for "
                + timeoutInSeconds
                + " more secs");

        matchingFrameAddress =
            findMatchingFrameAddress(
                frameAddressToJustLoaded.keySet(),
                waitingForThisWindowName,
                waitingForThisLocalFrame);
        if (null != matchingFrameAddress) {
          LOGGER.debug(
              "wait is over: window '"
                  + waitingForThisWindowName
                  + "' was seen at last ("
                  + matchingFrameAddress
                  + ")");
          /*
           * Remove it from the list of matching frame addresses
           * since it just loaded. Mark whether just loaded
           * to aid debugging.
           */
          markWhetherJustLoaded(matchingFrameAddress, false);
          return matchingFrameAddress;
        }

        waitUntilSignalOrNumSecondsPassed(resultArrivedOnAnyQueue, 1);
      } finally {
        dataLock.unlock();
      }
    }
    String result = "timed out waiting for window '" + waitingForThisWindowName + "' to appear";
    throw new RemoteCommandException(result, result);
  }
 /**
  * Does uniqueId point at a window that matches 'windowName'/'localFrame'?
  *
  * @param uniqueId
  * @param windowName
  * @param localFrame
  * @return True if the frame addressed by uniqueId is addressable by window name 'windowName' and
  *     local frame address 'localFrame'.
  */
 private boolean matchesFrameAddress(String uniqueId, String windowName, String localFrame) {
   // it's an odd selenium convention: "null" maps to the initial, main window:
   if (windowName == null || windowName.equals("null")) {
     windowName = DEFAULT_SELENIUM_WINDOW_NAME;
   }
   if (localFrame == null) {
     localFrame = "top";
   }
   CommandQueue queue = uniqueIdToCommandQueue.get(uniqueId);
   if (queue.isClosed()) {
     return false;
   }
   boolean windowJustLoaded = justLoaded(uniqueId);
   FrameAddress frameAddress = queue.getFrameAddress();
   if (!frameAddress.getLocalFrameAddress().equals(localFrame)) {
     return false;
   }
   // DGF Windows that have just loaded may not know their true identity
   if (windowJustLoaded) {
     String title;
     try {
       title = getRemoteWindowTitle(queue);
     } catch (WindowClosedException e) {
       return false;
     }
     markWhetherJustLoaded(uniqueId, true);
     if (title.equals(windowName)) {
       return true;
     }
   }
   String actualWindowName = frameAddress.getWindowName();
   if (windowName.equals(actualWindowName)) {
     return true;
   }
   if (windowName.equals("_blank") && actualWindowName.startsWith("selenium_blank")) {
     // DGF the API automatically changed target="_blank" to target="selenium_blank12345"
     return true;
   }
   return uniqueIdToCommandQueue.get(uniqueId).isWindowPointedToByJsVariable(windowName);
 }
  /**
   * Schedules the specified command to be retrieved by the next call to handle command result, and
   * returns the result of that command.
   *
   * @param command - the remote command verb
   * @param arg - the first remote argument (meaning depends on the verb)
   * @param value - the second remote argument
   * @return - the command result, defined by the remote JavaScript. "getX" style commands may
   *     return data from the browser; other "doX" style commands may just return "OK" or an error
   *     message.
   * @throws RemoteCommandException if a waitForLoad failed.
   */
  public String doCommand(String command, String arg, String value) throws RemoteCommandException {
    if (proxyInjectionMode) {
      if (command.equals("selectFrame")) {
        if ("".equals(arg)) {
          arg = "top";
        }
        boolean newFrameFound = false;
        // DGF iterate in lexical order for testability
        Set<String> idSet = uniqueIdToCommandQueue.keySet();
        String[] ids = idSet.toArray(new String[0]);
        Arrays.sort(ids);
        for (String uniqueId : ids) {
          CommandQueue frameQ = uniqueIdToCommandQueue.get(uniqueId);
          if (frameQ.isClosed()) {
            continue;
          }
          FrameAddress frameAddress = frameQ.getFrameAddress();
          if (frameAddress.getWindowName().equals(currentSeleniumWindowName)) {
            if (queueMatchesFrameAddress(frameQ, currentLocalFrameAddress, arg)) {
              setCurrentFrameAddress(uniqueId);
              newFrameFound = true;
              break;
            }
          }
        }
        if (!newFrameFound) {
          return "ERROR: starting from frame "
              + currentFrameAddress
              + ", could not find frame "
              + arg;
        }
        return "OK";
      }
      if (command.equals("selectWindow")) {
        return selectWindow(arg);
      }
      if (command.equals("waitForPopUp")) {
        String waitingForThisWindowName = arg;
        long timeoutInMilliseconds = Long.parseLong(value);
        String uniqueId;
        try {
          // Wait for the popup window to load, if it throws
          // an exception then we should simply return the
          // command result
          uniqueId =
              waitForLoad(waitingForThisWindowName, "top", (int) (timeoutInMilliseconds / 1000l));

          // if (!result.equals("OK")) {
          // 	return result;
          // }
        } catch (RemoteCommandException ex) {
          return ex.getResult();
        }

        // Return the result of selecting the frame address, not the window name
        setCurrentFrameAddress(uniqueId);
        return "OK";
      }
      if (command.equals("waitForPageToLoad")) {
        return waitForLoad(arg);
      }
      if (command.equals("waitForFrameToLoad")) {
        String waitingForThisFrameName = arg;
        long timeoutInMilliseconds = Long.parseLong(value);
        String currentWindowName = getCommandQueue().getFrameAddress().getWindowName();
        String result;
        try {
          result =
              waitForLoad(
                  currentWindowName,
                  waitingForThisFrameName,
                  (int) (timeoutInMilliseconds / 1000l));
        } catch (RemoteCommandException e) {
          return e.getMessage();
        }
        setCurrentFrameAddress(result);
        return "OK";
      }

      if (command.equals("setTimeout")) {
        try {
          pageLoadTimeoutInMilliseconds = Integer.parseInt(arg);
        } catch (NumberFormatException e) {
          return "ERROR: setTimeout arg is not a number: " + arg;
        }
        return "OK";
      }

      if (command.equals("getAllWindowNames")) {
        return getAttributeFromAllWindows("name");
      }
      if (command.equals("getAllWindowTitles")) {
        return getAttributeFromAllWindows("document.title");
      }
      if (command.equals("getAllWindowIds")) {
        return getAttributeFromAllWindows("id");
      }
      if (command.equals("getAttributeFromAllWindows")) {
        return getAttributeFromAllWindows(arg);
      }

      // handle closed queue (the earlier commands don't care about closed queues)
      CommandQueue queue = getCommandQueue();
      if (queue.isClosed()) {
        try {
          String uniqueId = waitForLoad(currentSeleniumWindowName, currentLocalFrameAddress, 1);
          setCurrentFrameAddress(uniqueId);
        } catch (RemoteCommandException e) {
          return WindowClosedException.WINDOW_CLOSED_ERROR;
        }
      }

      if (command.equals("open")) {
        markWhetherJustLoaded(currentUniqueId, false);
        String t = getCommandQueue().doCommand(command, arg, value);
        if (!"OK".equals(t)) {
          return t;
        }
        return waitForLoad(pageLoadTimeoutInMilliseconds);
      }
      // strip off AndWait - in PI mode we handle this in the server rather than in core...
      if (command.endsWith("AndWait")) {
        markWhetherJustLoaded(currentUniqueId, false);
        command = command.substring(0, command.length() - "AndWait".length());
        String t = getCommandQueue().doCommand(command, arg, value);
        if (!t.startsWith("OK")) {
          return t;
        }
        return waitForLoad(pageLoadTimeoutInMilliseconds);
      }
    } // if (proxyInjectionMode)
    markWhetherJustLoaded(currentUniqueId, false);
    return getCommandQueue().doCommand(command, arg, value);
  }