Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright 2012 selendroid committers.
   * 
   * 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 io.selendroid.server.model;
 
 import  io.selendroid.util.SelendroidLogger;
 
 import java.util.List;
 import java.util.Map;
 
 
 
 public class SelendroidWebDriver {
   private static final String ELEMENT_KEY = "ELEMENT";
   private static final long FOCUS_TIMEOUT = 1000L;
   private static final long LOADING_TIMEOUT = 30000L;
   private static final long POLLING_INTERVAL = 50L;
   private static final long START_LOADING_TIMEOUT = 700L;
   static final long UI_TIMEOUT = 3000L;
   private volatile boolean pageDoneLoading;
   private volatile boolean pageStartedLoading;
   private volatile String result;
   private volatile WebView webview = null;
   private static final String WINDOW_KEY = "WINDOW";
   private volatile boolean editAreaHasFocus;
   private final Object syncObject = new Object();
   private boolean done = false;
 
   public SelendroidWebDriver(ServerInstrumentation serverInstrumentation) {
     this. = serverInstrumentation;
     init();
   }
 
   private static String escapeAndQuote(final String toWrap) {
     StringBuilder toReturn = new StringBuilder("\"");
     for (int i = 0; i < toWrap.length(); i++) {
       char c = toWrap.charAt(i);
       if (c == '\"') {
         toReturn.append("\\\"");
       } else if (c == '\\') {
         toReturn.append("\\\\");
       } else {
         toReturn.append(c);
       }
     }
     toReturn.append("\"");
     return toReturn.toString();
   }
 
   @SuppressWarnings("unchecked")
   private String convertToJsArgs(JSONArray argsthrows JSONException {
     StringBuilder toReturn = new StringBuilder();
 
     int length = args.length();
     for (int i = 0; i < lengthi++) {
       toReturn.append((i > 0) ? "," : "");
       toReturn.append(convertToJsArgs(args.get(i)));
     }
     SelendroidLogger.log("convertToJsArgs: " + toReturn.toString());
     return toReturn.toString();
   }
 
   private String convertToJsArgs(Object obj) {
     StringBuilder toReturn = new StringBuilder();
     if (obj instanceof List<?>) {
       toReturn.append("[");
       List<ObjectaList = (List<Object>) obj;
       for (int j = 0; j < aList.size(); j++) {
         String comma = ((j == 0) ? "" : ",");
         toReturn.append(comma + convertToJsArgs(aList.get(j)));
       }
       toReturn.append("]");
     } else if (obj instanceof Map<?, ?>) {
       Map<ObjectObjectaMap = (Map<ObjectObject>) obj;
       String toAdd = "{";
      for (Object key : aMap.keySet()) {
        toAdd += key + ":" + convertToJsArgs(aMap.get(key)) + ",";
      }
      toReturn.append(toAdd.substring(0, toAdd.length() - 1) + "}");
    } else if (obj instanceof AndroidWebElement) {
      // A WebElement is represented in JavaScript by an Object as
      // follow: {"ELEMENT":"id"} where "id" refers to the id
      // of the HTML element in the javascript cache that can
      // be accessed throught bot.inject.cache.getCache_()
      toReturn.append("{\"" +  + "\":\"" + ((AndroidWebElementobj).getId() + "\"}");
    } else if (obj instanceof DomWindow) {
      // A DomWindow is represented in JavaScript by an Object as
      // follow {"WINDOW":"id"} where "id" refers to the id of the
      // DOM window in the cache.
      toReturn.append("{\"" +  + "\":\"" + ((DomWindowobj).getKey() + "\"}");
    } else if (obj instanceof Number || obj instanceof Boolean) {
      toReturn.append(String.valueOf(obj));
    } else if (obj instanceof String) {
      toReturn.append(escapeAndQuote((Stringobj));
    }
    SelendroidLogger.log("convertToJsArgs: " + toReturn.toString());
    return toReturn.toString();
  }
  public Object executeAtom(AndroidAtoms atomObject... args) {
    JSONArray array = new JSONArray();
    for (int i = 0; i < args.lengthi++) {
      array.put(args[i]);
    }
    try {
      return executeAtom(atomarray);
    } catch (JSONException je) {
      je.printStackTrace();
      throw new RuntimeException(je);
    }
  }
  public Object executeAtom(AndroidAtoms atomJSONArray argsthrows JSONException {
    final String myScript = atom.getValue();
    String scriptInWindow =
        "(function(){ " + " var win; try{win=window;}catch(e){win=window;}" + "with(win){return ("
            + myScript + ")(" + convertToJsArgs(args) + ")}})()";
    String jsResult = executeJavascriptInWebView("alert('selendroid:'+" + scriptInWindow + ")");
    SelendroidLogger.log("jsResult: " + jsResult);
    if (jsResult == null || "undefined".equals(jsResult)) {
      return null;
    }
    try {
      JSONObject json = new JSONObject(jsResult);
      if (0 != json.optInt("status")) {
        Object value = json.get("value");
        if ((value instanceof String && value.equals("Element does not exist in cache"))
            || (value instanceof JSONObject && ((JSONObjectvalue).getString("message").equals(
                "Element does not exist in cache"))) {
          throw new StaleElementReferenceException(json.optString("value"));
        }
        throw new SelendroidException(json.optString("value"));
      }
      if (json.isNull("value")) {
        return null;
      } else {
        return json.get("value");
      }
    } catch (JSONException e) {
      throw new SelendroidException(e);
    }
  }
  private String executeJavascriptInWebView(final String script) {
     = null;
    ServerInstrumentation.getInstance().runOnUiThread(new Runnable() {
      public void run() {
        if (.getUrl() == null) {
          return;
        }
        .loadUrl("javascript:" + script);
      }
    });
    long timeout = System.currentTimeMillis() + 60000; /*
                                                        * how long to wait to allow the script to
                                                        * run? This could be arbitrarily high for
                                                        * some users... setting extremely high for
                                                        * now (1 min)
                                                        */
    synchronized () {
      while ( == null && (System.currentTimeMillis() < timeout)) {
        try {
          .wait(2000);
        } catch (InterruptedException e) {
          throw new SelendroidException(e);
        }
      }
      return ;
    }
  }
  public Object executeScript(String script) {
    try {
      return injectJavascript(scriptfalsenew JSONArray());
    } catch (JSONException je) {
      je.printStackTrace();
      throw new RuntimeException(je);
    }
  }
  public Object executeScript(String scriptJSONArray args) {
    try {
      return injectJavascript(scriptfalseargs);
    } catch (JSONException je) {
      je.printStackTrace();
      throw new RuntimeException(je);
    }
  }
  public Object executeScript(String scriptObject args) {
    try {
      return injectJavascript(scriptfalseargs);
    } catch (JSONException je) {
      je.printStackTrace();
      throw new RuntimeException(je);
    }
  }
  public String getCurrentUrl() {
    if ( == null) {
      throw new SelendroidException("No open web view.");
    }
    long end = System.currentTimeMillis() + ;
    final String[] url = new String[1];
     = false;
    Runnable r = new Runnable() {
      public void run() {
        url[0] = .getUrl();
        synchronized (this) {
          this.notify();
        }
      }
    };
    return url[0];
  }
  public void get(final String url) {
      public void run() {
        .loadUrl(url);
      }
    });
  }
  public Object getWindowSource() throws JSONException {
    JSONObject source =
        new JSONObject(
            (StringexecuteScript("return (new XMLSerializer()).serializeToString(document.documentElement);"));
    return source.getString("value");
  }
  protected void init() {
    ..println("Selendroid webdriver init");
    long start = System.currentTimeMillis();
     = ViewHierarchyAnalyzer.getDefaultInstance().findWebView();
    while ( == null
        && (System.currentTimeMillis() - start <= ServerInstrumentation.getInstance()
            .getAndroidWait().getTimeoutInMillis())) {
      DefaultSelendroidDriver.sleepQuietly(500);
       = ViewHierarchyAnalyzer.getDefaultInstance().findWebView();
    }
    if ( == null) {
      throw new SelendroidException("No webview found on current activity.");
    }
  }
  private void configureWebView(final WebView view) {
    ServerInstrumentation.getInstance().runOnUiThread(new Runnable() {
      @Override
      public void run() {
        try {
          view.clearCache(true);
          view.clearFormData();
          view.clearHistory();
          view.setFocusable(true);
          view.setFocusableInTouchMode(true);
          view.setNetworkAvailable(true);
          view.setWebChromeClient(new MyWebChromeClient());
          WebSettings settings = view.getSettings();
          settings.setJavaScriptCanOpenWindowsAutomatically(true);
          settings.setSupportMultipleWindows(true);
          settings.setBuiltInZoomControls(true);
          settings.setJavaScriptEnabled(true);
          settings.setAppCacheEnabled(true);
          settings.setAppCacheMaxSize(10 * 1024 * 1024);
          settings.setAppCachePath("");
          settings.setDatabaseEnabled(true);
          settings.setDomStorageEnabled(true);
          settings.setGeolocationEnabled(true);
          settings.setSaveFormData(false);
          settings.setSavePassword(false);
          settings.setRenderPriority(..);
          // Flash settings
          settings.setPluginState(..);
          // Geo location settings
          settings.setGeolocationEnabled(true);
          settings.setGeolocationDatabasePath("/data/data/selendroid");
        } catch (Exception e) {
          SelendroidLogger.log("An error occured while configuring the web view"e);
        }
      }
    });
  }
  Object injectJavascript(String toExecuteboolean isAsyncObject argsthrows JSONException {
    String executeScript = ..getValue();
    String window = "window;";
    toExecute =
        "var win_context; try{win_context= " + window + "}catch(e){"
            + "win_context=window;}with(win_context){" + toExecute + "}";
    String wrappedScript =
        "(function(){" + "var win; try{win=" + window + "}catch(e){win=window}"
            + "with(win){return (" + executeScript + ")(" + escapeAndQuote(toExecute) + ", [";
    if (args instanceof JSONArray) {
      wrappedScript += convertToJsArgs((JSONArrayargs);
    } else {
      wrappedScript += convertToJsArgs(args);
    }
    wrappedScript += "], true)}})()";
    return executeJavascriptInWebView("alert('selendroid:'+" + wrappedScript + ")");
  }
  void resetPageIsLoading() {
     = false;
     = false;
  }
  void setEditAreaHasFocus(boolean focused) {
     = focused;
  }
  void waitForPageToLoad() {
    synchronized () {
      long timeout = System.currentTimeMillis() + ;
      while (! && (System.currentTimeMillis() < timeout)) {
        try {
          .wait();
        } catch (InterruptedException e) {
          throw new RuntimeException();
        }
      }
      long end = System.currentTimeMillis() + ;
      while (! &&  && (System.currentTimeMillis() < end)) {
        try {
          .wait();
        } catch (InterruptedException e) {
          throw new RuntimeException(e);
        }
      }
    }
  }
    long timeout = System.currentTimeMillis() + ;
    while (! && (System.currentTimeMillis() < timeout)) {
      try {
        Thread.sleep();
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
    }
  }
  public class MyWebChromeClient extends WebChromeClient {

    
Unconventional way of adding a Javascript interface but the main reason why I took this way is that it is working stable compared to the webview.addJavascriptInterface way.
    @Override
    public boolean onJsAlert(WebView viewString urlString messageJsResult jsResult) {
      if (message != null && message.startsWith("selendroid:")) {
        jsResult.confirm();
        synchronized () {
           = message.replaceFirst("selendroid:""");
          .notify();
        }
        return true;
      } else {
        return super.onJsAlert(viewurlmessagejsResult);
      }
    }
  }
  public String getTitle() {
    if ( == null) {
      throw new SelendroidException("No open web view.");
    }
    long end = System.currentTimeMillis() + ;
    final String[] title = new String[1];
     = false;
      public void run() {
        synchronized () {
          title[0] = .getTitle();
           = true;
          .notify();
        }
      }
    });
    waitForDone(end"Failed to get title");
    return title[0];
  }
  private void waitForDone(long endlong timeoutString error) {
    synchronized () {
      while (! && System.currentTimeMillis() < end) {
        try {
          .wait(timeout);
        } catch (InterruptedException e) {
          throw new SelendroidException(errore);
        }
      }
    }
  }
  private void runSynchronously(Runnable rlong timeout) {
    synchronized (r) {
      try {
        r.wait(timeout);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
  public WebView getWebview() {
    return ;
  }
New to GrepCode? Check out our FAQ X