Package org.openqa.selenium.firefox

Source Code of org.openqa.selenium.firefox.FirefoxDriver$LazyCommandExecutor

/*
Copyright 2007-2009 WebDriver committers
Copyright 2007-2009 Google Inc.
Portions copyright 2007 ThoughtWorks, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package org.openqa.selenium.firefox;

import static org.openqa.selenium.OutputType.FILE;
import static org.openqa.selenium.browserlaunchers.CapabilityType.PROXY;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.openqa.selenium.Alert;
import org.openqa.selenium.Capabilities;
import org.openqa.selenium.NoAlertPresentException;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.Platform;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.UnhandledAlertException;
import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.browserlaunchers.Proxies;
import org.openqa.selenium.firefox.internal.Lock;
import org.openqa.selenium.firefox.internal.NewProfileExtensionConnection;
import org.openqa.selenium.firefox.internal.ProfilesIni;
import org.openqa.selenium.firefox.internal.SocketLock;
import org.openqa.selenium.internal.FileHandler;
import org.openqa.selenium.internal.FindsByCssSelector;
import org.openqa.selenium.remote.Command;
import org.openqa.selenium.remote.CommandExecutor;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.DriverCommand;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.RemoteWebElement;
import org.openqa.selenium.remote.Response;

import com.google.common.collect.ImmutableMap;
import org.openqa.selenium.remote.internal.JsonToWebElementConverter;


/**
* An implementation of the {#link WebDriver} interface that drives Firefox. This works through a firefox extension,
* which gets installed automatically if necessary. Important system variables are:
* <ul>
* <li><b>webdriver.firefox.bin</b> - Which firefox binary to use (normally "firefox" on the PATH).</li>
* <li><b>webdriver.firefox.profile</b> - The name of the profile to use (normally "WebDriver").</li>
* </ul>
* <p/>
* When the driver starts, it will make a copy of the profile it is using, rather than using that profile directly.
* This allows multiple instances of firefox to be started.
*/
public class FirefoxDriver extends RemoteWebDriver implements TakesScreenshot, FindsByCssSelector {
  public static final String BINARY = "firefox_binary";
  public static final String PROFILE = "firefox_profile";

  public static final int DEFAULT_PORT = 7055;
  // For now, only enable native events on Windows
  public static final boolean DEFAULT_ENABLE_NATIVE_EVENTS =
      Platform.getCurrent()
          .is(Platform.WINDOWS);
  // Accept untrusted SSL certificates.
  public static final boolean ACCEPT_UNTRUSTED_CERTIFICATES = true;
  // Assume that the untrusted certificates will come from untrusted issuers
  // or will be self signed.
  public static final boolean ASSUME_UNTRUSTED_ISSUER = true;

  // Commands we can execute with needing to dismiss an active alert
  private final Set<String> alertWhiteListedCommands = new HashSet<String>() {{
    add(DriverCommand.DISMISS_ALERT);
  }};

  private FirefoxAlert currentAlert;

  protected FirefoxBinary binary;
  protected FirefoxProfile profile;

  public FirefoxDriver() {
    this(new FirefoxBinary(), null);
  }

  public FirefoxDriver(FirefoxProfile profile) {
    this(new FirefoxBinary(), profile);
  }

  public FirefoxDriver(Capabilities capabilities) {
    this(getBinary(capabilities), extractProfile(capabilities));
  }

  private static FirefoxProfile extractProfile(Capabilities capabilities) {
    FirefoxProfile profile = new FirefoxProfile();

    if (capabilities.getCapability(PROFILE) != null) {
      Object raw = capabilities.getCapability(PROFILE);
      if (raw instanceof FirefoxProfile) {
        profile = (FirefoxProfile) raw;
      } else if (raw instanceof String) {
        try {
          profile = FirefoxProfile.fromJson((String) raw);
        } catch (IOException e) {
          throw new WebDriverException(e);
        }
      }
    }

    if (capabilities.getCapability(PROXY) != null) {
      Proxy proxy = Proxies.extractProxy(capabilities);
      profile.setProxyPreferences(proxy);
    }

    return profile;
  }

  private static FirefoxBinary getBinary(Capabilities capabilities) {
    if (capabilities.getCapability(BINARY) != null) {
      File file = new File((String) capabilities.getCapability(BINARY));
      new FirefoxBinary(file);
    }
    return new FirefoxBinary();
  }

  public FirefoxDriver(FirefoxBinary binary, FirefoxProfile profile) {
    super(new LazyCommandExecutor(binary, profile), DesiredCapabilities.firefox());
    this.binary = binary;
    this.profile = profile;
    setElementConverter(new JsonToWebElementConverter(this) {
      @Override
      protected RemoteWebElement newRemoteWebElement() {
        return new FirefoxWebElement(FirefoxDriver.this);
      }
    });
  }

  @Override
  protected void startClient() {
    LazyCommandExecutor exe = (LazyCommandExecutor) getCommandExecutor();
    FirefoxProfile profileToUse = getProfile(exe.profile);
    profileToUse.addWebDriverExtensionIfNeeded(false);

    // TODO(simon): Make this not sinfully ugly
    ExtensionConnection connection = connectTo(exe.binary, profileToUse, "localhost");
    exe.setConnection(connection);

    try {
      connection.start();
    } catch (IOException e) {
      throw new WebDriverException("An error occurred while connecting to Firefox", e);
    }
  }

  private FirefoxProfile getProfile(FirefoxProfile profile) {
    FirefoxProfile profileToUse = profile;
    String suggestedProfile = System.getProperty("webdriver.firefox.profile");
    if (profileToUse == null && suggestedProfile != null) {
      profileToUse = new ProfilesIni().getProfile(suggestedProfile);
    } else if (profileToUse == null) {
      profileToUse = new FirefoxProfile();
    }
    return profileToUse;
  }

  protected ExtensionConnection connectTo(FirefoxBinary binary, FirefoxProfile profile,
                                          String host) {
    int profilePort = profile.getPort() == 0 ? DEFAULT_PORT : profile.getPort();
    Lock lock = new SocketLock(profilePort - 1);
    try {
      FirefoxBinary bin = binary == null ? new FirefoxBinary() : binary;
     

      return new NewProfileExtensionConnection(lock, bin, profile, host);
    } catch (Exception e) {
      throw new WebDriverException(e);
    } finally {
      lock.unlock();
    }
  }

  @Override
  protected void stopClient() {
    ((LazyCommandExecutor) this.getCommandExecutor()).quit();
  }

  @Override
  protected FirefoxWebElement newRemoteWebElement() {
    return new FirefoxWebElement(this);
  }

  public WebElement findElementByCssSelector(String using) {
    if (using == null) {
      throw new IllegalArgumentException("Cannot find elements when the css selector is null.");
    }

    return findElement("css selector", using);
  }

  public List<WebElement> findElementsByCssSelector(String using) {
    if (using == null) {
      throw new IllegalArgumentException("Cannot find elements when the css selector is null.");
    }

    return findElements("css selector", using);
  }

  @Override
  public TargetLocator switchTo() {
    return new FirefoxTargetLocator();
  }

  @Override
  protected Response execute(String driverCommand, Map<String, ?> parameters) {
    if (currentAlert != null) {
      if (!alertWhiteListedCommands.contains(driverCommand)) {
        ((FirefoxTargetLocator) switchTo()).alert()
            .dismiss();
        throw new UnhandledAlertException(driverCommand.toString());
      }
    }

    Response response = super.execute(driverCommand, parameters);

    Object rawResponse = response.getValue();
    if (rawResponse instanceof Map) {
      Map map = (Map) rawResponse;
      if (map.containsKey("__webdriverType")) {
        // Looks like have an alert. construct it
        currentAlert = new FirefoxAlert((String) map.get("text"));
        response.setValue(null);
      }
    }

    return response;
  }

  @Override
  public boolean isJavascriptEnabled() {
    return true;
  }

  private class FirefoxTargetLocator extends RemoteTargetLocator {
    // TODO: this needs to be on an interface

    public Alert alert() {
      if (currentAlert != null) {
        return currentAlert;
      }

      throw new NoAlertPresentException();
    }
  }

  public <X> X getScreenshotAs(OutputType<X> target) {
    // Get the screenshot as base64.
    String base64 = execute(DriverCommand.SCREENSHOT).getValue().toString();
    // ... and convert it.
    return target.convertFromBase64Png(base64);
  }

  /**
   * Saves a screenshot of the current page into the given file.
   *
   * @deprecated Use getScreenshotAs(file), which returns a temporary file.
   */
  @Deprecated
  public void saveScreenshot(File pngFile) {
    if (pngFile == null) {
      throw new IllegalArgumentException("Method parameter pngFile must not be null");
    }

    File tmpfile = getScreenshotAs(FILE);

    File dir = pngFile.getParentFile();
    if (dir != null && !dir.exists() && !dir.mkdirs()) {
      throw new WebDriverException("Could not create directory " + dir.getAbsolutePath());
    }

    try {
      FileHandler.copy(tmpfile, pngFile);
    } catch (IOException e) {
      throw new WebDriverException(e);
    }
  }

  private class FirefoxAlert implements Alert {
    private String text;

    public FirefoxAlert(String text) {
      this.text = text;
    }

    public void dismiss() {
      execute(DriverCommand.DISMISS_ALERT, ImmutableMap.of("text", text));
      currentAlert = null;
    }

    public void accept() {
    }

    public String getText() {
      return text;
    }
  }

  private static class LazyCommandExecutor implements CommandExecutor {
    private ExtensionConnection connection;
    private final FirefoxBinary binary;
    private final FirefoxProfile profile;

    private LazyCommandExecutor(FirefoxBinary binary, FirefoxProfile profile) {
      this.binary = binary;
      this.profile = profile;
    }

    public void setConnection(ExtensionConnection connection) {
      this.connection = connection;
    }

    public void quit() {
      connection.quit();
    }

    public Response execute(Command command) throws Exception {
      return connection.execute(command);
    }
  }
}
TOP

Related Classes of org.openqa.selenium.firefox.FirefoxDriver$LazyCommandExecutor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.