Java tutorial
/* * Copyright 2012 ios-driver 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 Licence 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.uiautomation.ios.wkrdp.internal; import com.google.common.collect.ImmutableMap; import org.json.JSONException; import org.json.JSONObject; import org.openqa.selenium.WebDriverException; import org.uiautomation.ios.utils.PlistManager; import org.uiautomation.ios.wkrdp.MessageHandler; import org.uiautomation.ios.wkrdp.MessageListener; import org.uiautomation.ios.wkrdp.RemoteExceptionException; import org.uiautomation.ios.wkrdp.ResponseFinder; import java.util.Map; import java.util.UUID; import java.util.logging.Logger; /** * Communication logic for the WKRDP to connect to an app, and to a specific webview inside that * app. * * @see WebKitRemoteDebugProtocol#sendWebkitCommand(org.json.JSONObject, int) to use the protocol * itself. */ public abstract class WebKitRemoteDebugProtocol { private static final Logger log = Logger.getLogger(WebKitRemoteDebugProtocol.class.getName()); protected final MessageHandler handler; private Thread listen; private String connectionId; private String bundleId; private final PlistManager plist = new PlistManager(); private final static String senderBase = "E0F4C128-F4FF-4D45-A538-BA382CD660"; private int commandId = 0; private volatile boolean keepGoing = true; private volatile boolean readyToBeStopped = true; public abstract void start(); public abstract void stop(); protected abstract void read() throws Exception; protected abstract void sendMessage(String message); protected void startListenerThread() { listen = new Thread(new Runnable() { @Override public void run() { try { readyToBeStopped = false; keepGoing = true; while (keepGoing) { read(); sleepTight(50); } } catch (Exception e) { //e.printStackTrace(); } finally { readyToBeStopped = true; } } }); listen.start(); } public WebKitRemoteDebugProtocol(MessageListener listener, ResponseFinder... finders) { this.handler = new DefaultMessageHandler(listener, finders); } public void addListener(MessageListener listener) { handler.addListener(listener); } public void register() { if (connectionId != null) { throw new WebDriverException("Session already created."); } connectionId = UUID.randomUUID().toString(); Map<String, String> var = ImmutableMap.of("$WIRConnectionIdentifierKey", connectionId); sendSystemCommand(PlistManager.SET_CONNECTION_KEY, var); } public void connect(String bundleId) { if (connectionId == null) { throw new WebDriverException("Cannot connect to app " + bundleId + ".Call register first."); } Map<String, String> var = ImmutableMap.of("$WIRConnectionIdentifierKey", this.connectionId, "$bundleId", bundleId); sendSystemCommand(PlistManager.CONNECT_TO_APP, var); this.bundleId = bundleId; } public void attachToPage(int pageId) { String senderKey = generateSenderString(pageId); if (connectionId == null || bundleId == null) { throw new WebDriverException("You need to call register and connect first."); } Map<String, String> var = ImmutableMap.of("$WIRConnectionIdentifierKey", connectionId, "$bundleId", bundleId, "$WIRSenderKey", senderKey, "$WIRPageIdentifierKey", "" + pageId); sendSystemCommand(PlistManager.SET_SENDER_KEY, var); } private void sendSystemCommand(String templateName, Map<String, String> variables) { String xml = plist.loadFromTemplate(templateName); for (String key : variables.keySet()) { xml = xml.replace(key, variables.get(key)); } sendMessage(xml); } public synchronized JSONObject sendWebkitCommand(JSONObject command, int pageId) { String sender = generateSenderString(pageId); try { commandId++; command.put("id", commandId); long start = System.currentTimeMillis(); String xml = plist.JSONCommand(command); Map<String, String> var = ImmutableMap.of("$WIRConnectionIdentifierKey", connectionId, "$bundleId", bundleId, "$WIRSenderKey", sender, "$WIRPageIdentifierKey", "" + pageId); for (String key : var.keySet()) { xml = xml.replace(key, var.get(key)); } sendMessage(xml); JSONObject response = handler.getResponse(command.getInt("id")); JSONObject error = response.optJSONObject("error"); if (error != null) { throw new RemoteExceptionException(error, command); } else if (response.optBoolean("wasThrown", false)) { throw new WebDriverException("remote JS exception " + response.toString(2)); } else { log.fine(System.currentTimeMillis() + "\t\t" + (System.currentTimeMillis() - start) + "ms\t" + command.getString("method") + " " + command); JSONObject res = response.getJSONObject("result"); if (res == null) { System.err.println("GOT a null result from " + response.toString(2)); } return res; } } catch (JSONException e) { throw new WebDriverException(e); } } private String generateSenderString(int pageIdentifierKey) { if (pageIdentifierKey < 10) { return senderBase + "0" + pageIdentifierKey; } else { return senderBase + pageIdentifierKey; } } public void stopListenerThread() { if (handler != null) { handler.stop(); } keepGoing = false; if (listen != null) { listen.interrupt(); } while (!readyToBeStopped) { sleepTight(50); } } private static void sleepTight(int ms) { try { Thread.sleep(ms); } catch (InterruptedException ignore) { Thread.currentThread().interrupt(); } } }