All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openqa.selenium.firefox.Preferences Maven / Gradle / Ivy

Go to download

Selenium automates browsers. That's it! What you do with that power is entirely up to you.

There is a newer version: 4.19.1
Show newest version
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you 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 com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.openqa.selenium.json.Json.MAP_TYPE;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.io.CharStreams;
import com.google.common.io.Closeables;
import com.google.common.io.LineReader;

import org.openqa.selenium.WebDriverException;
import org.openqa.selenium.json.Json;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

class Preferences {

  /**
   * The maximum amount of time scripts should be permitted to run. The user may increase this
   * timeout, but may not set it below the default value.
   */
  private static final String MAX_SCRIPT_RUN_TIME_KEY = "dom.max_script_run_time";
  private static final int DEFAULT_MAX_SCRIPT_RUN_TIME = 30;

  /**
   * This pattern is used to parse preferences in user.js. It is intended to match all preference
   * lines in the format generated by Firefox; it won't necessarily match all possible lines that
   * Firefox will parse.
   *
   * e.g. if you have a line with extra spaces after the end-of-line semicolon, this pattern will
   * not match that line because Firefox never generates lines like that.
   */
  private static final Pattern PREFERENCE_PATTERN =
      Pattern.compile("user_pref\\(\"([^\"]+)\", (\"?.+?\"?)\\);");

  private Map immutablePrefs = new HashMap<>();
  private Map allPrefs = new HashMap<>();

  public Preferences(Reader defaults) {
    readDefaultPreferences(defaults);
  }

  public Preferences(Reader defaults, File userPrefs) {
    readDefaultPreferences(defaults);
    try (FileReader reader = new FileReader(userPrefs)) {
      readPreferences(reader);
    } catch (IOException e) {
      throw new WebDriverException(e);
    }
  }

  @VisibleForTesting
  public Preferences(Reader defaults, Reader reader) {
    readDefaultPreferences(defaults);
    try {
      readPreferences(reader);
    } catch (IOException e) {
      throw new WebDriverException(e);
    } finally {
      try {
        Closeables.close(reader, true);
      } catch (IOException ignored) {
      }
    }
  }

  private void readDefaultPreferences(Reader defaultsReader) {
    try {
      String rawJson = CharStreams.toString(defaultsReader);
      Map map = new Json().toType(rawJson, MAP_TYPE);

      Map frozen = (Map) map.get("frozen");
      for (Map.Entry entry : frozen.entrySet()) {
        String key = entry.getKey();
        Object value = entry.getValue();
        if (value instanceof Long) {
          value = new Integer(((Long)value).intValue());
        }
        setPreference(key, value);
        immutablePrefs.put(key, value);
      }

      Map mutable = (Map) map.get("mutable");
      for (Map.Entry entry : mutable.entrySet()) {
        Object value = entry.getValue();
        if (value instanceof Long) {
          value = new Integer(((Long)value).intValue());
        }
        setPreference(entry.getKey(), value);
      }
    } catch (IOException e) {
      throw new WebDriverException(e);
    }
  }

  private void setPreference(String key, Object value) {
    if (value instanceof String) {
      setPreference(key, (String) value);
    } else if (value instanceof Boolean) {
      setPreference(key, ((Boolean) value).booleanValue());
    } else {
      setPreference(key, ((Number) value).intValue());
    }
  }

  private void readPreferences(Reader reader) throws IOException {
    LineReader allLines = new LineReader(reader);
    String line = allLines.readLine();
    while (line != null) {
      Matcher matcher = PREFERENCE_PATTERN.matcher(line);
      if (matcher.matches()) {
        allPrefs.put(matcher.group(1), preferenceAsValue(matcher.group(2)));
      }
      line = allLines.readLine();
    }
  }

  public void setPreference(String key, String value) {
    checkPreference(key, value);
    if (isStringified(value)) {
      throw new IllegalArgumentException(
          String.format("Preference values must be plain strings: %s: %s",
              key, value));
    }
    allPrefs.put(key, value);
  }

  public void setPreference(String key, boolean value) {
    checkPreference(key, value);
    allPrefs.put(key, value);
  }

  public void setPreference(String key, int value) {
    checkPreference(key, value);
    allPrefs.put(key, value);
  }

  public void addTo(Preferences prefs) {
    // TODO(simon): Stop being lazy
    prefs.allPrefs.putAll(allPrefs);
  }

  public void addTo(FirefoxProfile profile) {
    profile.getAdditionalPreferences().allPrefs.putAll(allPrefs);
  }

  public void writeTo(Writer writer) throws IOException {
    for (Map.Entry pref : allPrefs.entrySet()) {
      writer.append("user_pref(\"").append(pref.getKey()).append("\", ");
      writer.append(valueAsPreference(pref.getValue()));
      writer.append(");\n");
    }
  }

  private String valueAsPreference(Object value) {
    if (value instanceof String) {
      return "\"" + escapeValueAsPreference((String) value) + "\"";
    }
    return escapeValueAsPreference(String.valueOf(value));
  }

  private String escapeValueAsPreference(String value) {
    return value.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\"");
  }

  private Object preferenceAsValue(String toConvert) {
    if (toConvert.startsWith("\"") && toConvert.endsWith("\"")) {
      return toConvert.substring(1, toConvert.length() - 1).replaceAll("\\\\\\\\", "\\\\");
    }

    if ("false".equals(toConvert) || "true".equals(toConvert)) {
      return Boolean.parseBoolean(toConvert);
    }

    try {
      return Integer.parseInt(toConvert);
    } catch (NumberFormatException e) {
      throw new WebDriverException(e);
    }
  }

  @VisibleForTesting
  protected Object getPreference(String key) {
    return allPrefs.get(key);
  }

  private boolean isStringified(String value) {
    // Assume we a string is stringified (i.e. wrapped in " ") when
    // the first character == " and the last character == "
    return value.startsWith("\"") && value.endsWith("\"");
  }

  public void putAll(Map frozenPreferences) {
    allPrefs.putAll(frozenPreferences);
  }

  private void checkPreference(String key, Object value) {
    checkNotNull(value);
    checkArgument(!immutablePrefs.containsKey(key) ||
                  (immutablePrefs.containsKey(key) && value.equals(immutablePrefs.get(key))),
                  "Preference %s may not be overridden: frozen value=%s, requested value=%s",
                  key, immutablePrefs.get(key), value);
    if (MAX_SCRIPT_RUN_TIME_KEY.equals(key)) {
      int n;
      if (value instanceof String) {
        n = Integer.parseInt((String) value);
      } else if (value instanceof Integer) {
        n = (Integer) value;
      } else {
        throw new IllegalArgumentException(String.format(
            "%s value must be a number: %s", MAX_SCRIPT_RUN_TIME_KEY, value.getClass().getName()));
      }
      checkArgument(n == 0 || n >= DEFAULT_MAX_SCRIPT_RUN_TIME,
                    "%s must be == 0 || >= %s",
                    MAX_SCRIPT_RUN_TIME_KEY,
                    DEFAULT_MAX_SCRIPT_RUN_TIME);
    }
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy