Add floating console support
This commit is contained in:
@@ -1,37 +0,0 @@
|
||||
package com.stardust.autojs;
|
||||
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/1.
|
||||
*/
|
||||
|
||||
public class RunnableScriptExecution extends ScriptExecution.AbstarctScriptExecution implements ScriptExecution, Runnable {
|
||||
|
||||
private JavaScriptEngine mJavaScriptEngine;
|
||||
private ScriptRuntime mScriptRuntime;
|
||||
private ScriptEngineService mScriptEngineService;
|
||||
|
||||
public RunnableScriptExecution(ScriptEngineService service, ScriptExecutionTask task) {
|
||||
super(task);
|
||||
mScriptEngineService = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mJavaScriptEngine = mScriptEngineService.createScriptEngine();
|
||||
mScriptRuntime = mScriptEngineService.createScriptRuntime();
|
||||
mScriptExecutionTask.execute(mScriptRuntime, mJavaScriptEngine);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaScriptEngine getEngine() {
|
||||
return mJavaScriptEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptRuntime getRuntime() {
|
||||
return mScriptRuntime;
|
||||
}
|
||||
}
|
||||
@@ -6,12 +6,19 @@ import android.util.Log;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.engine.JavaScriptEngineManager;
|
||||
import com.stardust.autojs.engine.ScriptExecuteActivity;
|
||||
import com.stardust.autojs.runtime.ScriptInterrupptedException;
|
||||
import com.stardust.autojs.execution.ExecutionConfig;
|
||||
import com.stardust.autojs.execution.RunnableScriptExecution;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.execution.ScriptExecutionListener;
|
||||
import com.stardust.autojs.execution.ScriptExecutionObserver;
|
||||
import com.stardust.autojs.execution.ScriptExecutionTask;
|
||||
import com.stardust.autojs.execution.SimpleScriptExecutionListener;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
import com.stardust.autojs.runtime.api.Console;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
import com.stardust.lang.ThreadCompat;
|
||||
import com.stardust.util.Supplier;
|
||||
import com.stardust.util.UiHandler;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
@@ -21,7 +28,10 @@ import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL;
|
||||
|
||||
import static com.stardust.autojs.runtime.ScriptInterruptedException.causedByInterrupted;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/23.
|
||||
@@ -31,15 +41,18 @@ public class ScriptEngineService {
|
||||
|
||||
private static final String LOG_TAG = "ScriptEngineService";
|
||||
private static final EventBus EVENT_BUS = new EventBus();
|
||||
private static final ScriptExecutionListener DEFAULT_LISTENER = new SimpleScriptExecutionListener() {
|
||||
private static final ScriptExecutionListener GLOBAL_LISTENER = new SimpleScriptExecutionListener() {
|
||||
@Override
|
||||
public void onStart(JavaScriptEngine engine, ScriptSource source) {
|
||||
EVENT_BUS.post(new ScriptExecutionEvent(ScriptExecutionEvent.ON_START, source.toString()));
|
||||
public void onStart(ScriptExecution execution) {
|
||||
execution.getRuntime().console.setTitle(execution.getSource().getName());
|
||||
EVENT_BUS.post(new ScriptExecutionEvent(ScriptExecutionEvent.ON_START, execution.getSource().toString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(JavaScriptEngine engine, ScriptSource source, Exception e) {
|
||||
public void onException(ScriptExecution execution, Exception e) {
|
||||
e.printStackTrace();
|
||||
if (!causedByInterrupted(e)) {
|
||||
execution.getRuntime().console.error(e.getMessage());
|
||||
EVENT_BUS.post(new ScriptExecutionEvent(ScriptExecutionEvent.ON_EXCEPTION, e.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -48,19 +61,20 @@ public class ScriptEngineService {
|
||||
|
||||
private final Supplier<ScriptRuntime> mRuntimeSupplier;
|
||||
private final Context mContext;
|
||||
private ScriptRuntime mGlobalScriptRuntime;
|
||||
private UiHandler mUiHandler;
|
||||
private final Console mGlobalConsole;
|
||||
private final JavaScriptEngineManager mJavaScriptEngineManager;
|
||||
private final EngineLifecycleObserver mEngineLifecycleObserver = new EngineLifecycleObserver();
|
||||
private ScriptExecutionListener mDefaultScriptExecutionListener = DEFAULT_LISTENER;
|
||||
private ScriptExecutionObserver mScriptExecutionObserver = new ScriptExecutionObserver();
|
||||
|
||||
ScriptEngineService(ScriptEngineServiceBuilder builder) {
|
||||
mRuntimeSupplier = builder.mRuntimeSupplier;
|
||||
mContext = builder.mContext;
|
||||
mUiHandler = builder.mUiHandler;
|
||||
mContext = mUiHandler.getContext();
|
||||
mJavaScriptEngineManager = builder.mJavaScriptEngineManager;
|
||||
mGlobalScriptRuntime = mRuntimeSupplier.get();
|
||||
mGlobalConsole = mGlobalScriptRuntime.console;
|
||||
mGlobalConsole = builder.mGlobalConsole;
|
||||
mJavaScriptEngineManager.setEngineLifecycleCallback(mEngineLifecycleObserver);
|
||||
mScriptExecutionObserver.registerScriptExecutionListener(GLOBAL_LISTENER);
|
||||
EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
@@ -68,17 +82,8 @@ public class ScriptEngineService {
|
||||
return mGlobalConsole;
|
||||
}
|
||||
|
||||
public ScriptExecutionListener getDefaultScriptExecutionListener() {
|
||||
return mDefaultScriptExecutionListener;
|
||||
}
|
||||
|
||||
public void setDefaultScriptExecutionListener(ScriptExecutionListener defaultScriptExecutionListener) {
|
||||
mDefaultScriptExecutionListener = defaultScriptExecutionListener;
|
||||
}
|
||||
|
||||
public JavaScriptEngine createScriptEngine() {
|
||||
JavaScriptEngine engine = mJavaScriptEngineManager.createEngine();
|
||||
Log.d(LOG_TAG, Arrays.toString(Thread.currentThread().getStackTrace()));
|
||||
return engine;
|
||||
}
|
||||
|
||||
@@ -94,12 +99,20 @@ public class ScriptEngineService {
|
||||
mEngineLifecycleObserver.unregisterCallback(engineLifecycleCallback);
|
||||
}
|
||||
|
||||
public static boolean causedByInterrupted(Throwable e) {
|
||||
return e instanceof ScriptInterrupptedException || e.getCause() instanceof ScriptInterrupptedException;
|
||||
public boolean registerGlobalScriptExecutionListener(ScriptExecutionListener listener) {
|
||||
return mScriptExecutionObserver.registerScriptExecutionListener(listener);
|
||||
}
|
||||
|
||||
public boolean unregisterGlobalScriptExecutionListener(ScriptExecutionListener listener) {
|
||||
return mScriptExecutionObserver.removeScriptExecutionListener(listener);
|
||||
}
|
||||
|
||||
public ScriptExecution execute(ScriptExecutionTask task) {
|
||||
task.setDefaultListenerIfNeeded(mDefaultScriptExecutionListener);
|
||||
if (task.getListener() != null) {
|
||||
task.setExecutionListener(new ScriptExecutionObserver.Wrapper(mScriptExecutionObserver, task.getListener()));
|
||||
} else {
|
||||
task.setExecutionListener(mScriptExecutionObserver);
|
||||
}
|
||||
if (isUiMode(task)) {
|
||||
return ScriptExecuteActivity.execute(mContext, this, task);
|
||||
} else {
|
||||
@@ -128,7 +141,7 @@ public class ScriptEngineService {
|
||||
}
|
||||
|
||||
public ScriptExecution execute(ScriptSource source) {
|
||||
return execute(source, mDefaultScriptExecutionListener, ExecutionConfig.getDefault());
|
||||
return execute(source, null, ExecutionConfig.getDefault());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -136,7 +149,7 @@ public class ScriptEngineService {
|
||||
if (event.getCode() == ScriptExecutionEvent.ON_START) {
|
||||
mGlobalConsole.verbose(DateFormat.getTimeInstance().format(new Date()) + " " + mContext.getString(R.string.text_start_running) + " " + event.getMessage());
|
||||
} else if (event.getCode() == ScriptExecutionEvent.ON_EXCEPTION) {
|
||||
mGlobalScriptRuntime.toast(mContext.getString(R.string.text_error) + ": " + event.getMessage());
|
||||
mUiHandler.toast(mContext.getString(R.string.text_error) + ": " + event.getMessage());
|
||||
mGlobalConsole.error(event.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -149,9 +162,9 @@ public class ScriptEngineService {
|
||||
public void stopAllAndToast() {
|
||||
int n = stopAll();
|
||||
if (n > 0)
|
||||
mGlobalScriptRuntime.toast(String.format(mContext.getString(R.string.text_already_stop_n_scripts), n));
|
||||
mUiHandler.toast(String.format(mContext.getString(R.string.text_already_stop_n_scripts), n));
|
||||
else
|
||||
mGlobalScriptRuntime.toast(mContext.getString(R.string.text_no_running_script));
|
||||
mUiHandler.toast(mContext.getString(R.string.text_no_running_script));
|
||||
}
|
||||
|
||||
public String[] getGlobalFunctions() {
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.stardust.autojs.engine.JavaScriptEngineManager;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
import com.stardust.autojs.runtime.api.Console;
|
||||
import com.stardust.util.Supplier;
|
||||
import com.stardust.util.UiHandler;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
@@ -14,8 +15,9 @@ import com.stardust.util.Supplier;
|
||||
public class ScriptEngineServiceBuilder {
|
||||
|
||||
Supplier<ScriptRuntime> mRuntimeSupplier;
|
||||
Context mContext;
|
||||
JavaScriptEngineManager mJavaScriptEngineManager;
|
||||
Console mGlobalConsole;
|
||||
UiHandler mUiHandler;
|
||||
|
||||
public ScriptEngineServiceBuilder() {
|
||||
|
||||
@@ -26,8 +28,8 @@ public class ScriptEngineServiceBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScriptEngineServiceBuilder context(Context context) {
|
||||
mContext = context;
|
||||
public ScriptEngineServiceBuilder uiHandler(UiHandler uiHandler) {
|
||||
mUiHandler = uiHandler;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -36,6 +38,11 @@ public class ScriptEngineServiceBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScriptEngineServiceBuilder globalConsole(Console console) {
|
||||
mGlobalConsole = console;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScriptEngineService build() {
|
||||
return new ScriptEngineService(this);
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.stardust.autojs;
|
||||
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
|
||||
public interface ScriptExecutionListener extends Serializable {
|
||||
|
||||
void onStart(JavaScriptEngine engine, ScriptSource source);
|
||||
|
||||
void onSuccess(JavaScriptEngine engine, ScriptSource source, Object result);
|
||||
|
||||
void onException(JavaScriptEngine engine, ScriptSource source, Exception e);
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package com.stardust.autojs;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
|
||||
public class ScriptExecutionTask implements Serializable {
|
||||
|
||||
private static final String TAG = "ScriptExecutionTask";
|
||||
|
||||
private ScriptSource mScriptSource;
|
||||
private ScriptExecutionListener mExecutionListener;
|
||||
private ExecutionConfig mExecutionConfig;
|
||||
|
||||
public ScriptExecutionTask(ScriptSource source, ScriptExecutionListener listener, ExecutionConfig config) {
|
||||
mScriptSource = source;
|
||||
mExecutionListener = listener;
|
||||
mExecutionConfig = config;
|
||||
}
|
||||
|
||||
public ScriptSource getSource() {
|
||||
return mScriptSource;
|
||||
}
|
||||
|
||||
public ScriptExecutionListener getListener() {
|
||||
return mExecutionListener;
|
||||
}
|
||||
|
||||
public ExecutionConfig getConfig() {
|
||||
return mExecutionConfig;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void execute(ScriptRuntime runtime, JavaScriptEngine engine) {
|
||||
try {
|
||||
prepare(runtime, engine);
|
||||
doExecution(engine);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
mExecutionListener.onException(engine, mScriptSource, e);
|
||||
} finally {
|
||||
Log.d(TAG, "Engine destroy");
|
||||
engine.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void prepare(ScriptRuntime runtime, JavaScriptEngine engine) {
|
||||
if ((mScriptSource.getExecutionMode() & ScriptSource.EXECUTION_MODE_AUTO) != 0) {
|
||||
runtime.ensureAccessibilityServiceEnabled();
|
||||
}
|
||||
engine.put("__runtime__", runtime);
|
||||
engine.init();
|
||||
}
|
||||
|
||||
private void doExecution(JavaScriptEngine engine) {
|
||||
engine.setTag("script", mScriptSource);
|
||||
mExecutionListener.onStart(engine, mScriptSource);
|
||||
mExecutionListener.onSuccess(engine, mScriptSource, engine.execute(mScriptSource));
|
||||
}
|
||||
|
||||
public ScriptExecutionListener getExecutionListenerOrDefault(ScriptExecutionListener defaultListener) {
|
||||
if (mExecutionListener == null)
|
||||
return defaultListener;
|
||||
return mExecutionListener;
|
||||
}
|
||||
|
||||
public void setDefaultListenerIfNeeded(ScriptExecutionListener defaultScriptExecutionListener) {
|
||||
if (mExecutionListener == null) {
|
||||
mExecutionListener = defaultScriptExecutionListener;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.stardust.autojs;
|
||||
|
||||
import com.stardust.autojs.ScriptExecutionListener;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
|
||||
public class SimpleScriptExecutionListener implements ScriptExecutionListener {
|
||||
@Override
|
||||
public void onStart(JavaScriptEngine engine, ScriptSource source) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(JavaScriptEngine engine, ScriptSource source, Object result) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(JavaScriptEngine engine, ScriptSource source, Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,6 @@ public abstract class JavaScriptEngineManager {
|
||||
for (JavaScriptEngine engine : mEngines) {
|
||||
engine.forceStop();
|
||||
}
|
||||
mEngines.clear();
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package com.stardust.autojs.engine;
|
||||
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.autojs.rhino_android.AndroidContextFactory;
|
||||
import com.stardust.autojs.rhino_android.RhinoAndroidHelper;
|
||||
import com.stardust.autojs.runtime.ScriptInterrupptedException;
|
||||
import com.stardust.autojs.runtime.ScriptStopException;
|
||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
@@ -17,11 +14,9 @@ import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
@@ -31,12 +26,13 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
|
||||
|
||||
private static final String LOG_TAG = "RhinoJavaScriptEngine";
|
||||
|
||||
private static int contextCount = 0;
|
||||
|
||||
private Context mContext;
|
||||
private Scriptable mScriptable;
|
||||
private Thread mThread;
|
||||
private RhinoJavaScriptEngineManager mEngineManager;
|
||||
private Map<String, Object> mTags = new Hashtable<>();
|
||||
private boolean mDestroyed = false;
|
||||
private Map<String, Object> mTags = new ConcurrentHashMap<>();
|
||||
|
||||
public RhinoJavaScriptEngine(RhinoJavaScriptEngineManager engineManager) {
|
||||
mEngineManager = engineManager;
|
||||
@@ -69,6 +65,8 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
|
||||
public synchronized void destroy() {
|
||||
Log.d(LOG_TAG, "on destroy");
|
||||
Context.exit();
|
||||
contextCount--;
|
||||
Log.d(LOG_TAG, "contextCount = " + contextCount);
|
||||
mEngineManager.removeEngine(this);
|
||||
}
|
||||
|
||||
@@ -108,8 +106,9 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
|
||||
ContextFactory.initGlobal(new InterruptibleAndroidContextFactory(new File(mEngineManager.getContext().getCacheDir(), "classes")));
|
||||
}
|
||||
Context context = new RhinoAndroidHelper(mEngineManager.getContext()).enterContext();
|
||||
contextCount++;
|
||||
context.setOptimizationLevel(-1);
|
||||
context.setLanguageVersion(Context.VERSION_1_7);
|
||||
context.setLanguageVersion(Context.VERSION_ES6);
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -122,8 +121,7 @@ public class RhinoJavaScriptEngine implements JavaScriptEngine {
|
||||
@Override
|
||||
protected void observeInstructionCount(Context cx, int instructionCount) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
Context.exit();
|
||||
throw new ScriptInterrupptedException();
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,10 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.stardust.autojs.ExecutionConfig;
|
||||
import com.stardust.autojs.ScriptEngineService;
|
||||
import com.stardust.autojs.ScriptExecution;
|
||||
import com.stardust.autojs.ScriptExecutionListener;
|
||||
import com.stardust.autojs.ScriptExecutionTask;
|
||||
import com.stardust.autojs.execution.ScriptExecution;
|
||||
import com.stardust.autojs.execution.ScriptExecutionListener;
|
||||
import com.stardust.autojs.execution.ScriptExecutionTask;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
|
||||
@@ -50,14 +49,14 @@ public class ScriptExecuteActivity extends Activity {
|
||||
prepare();
|
||||
doExecution();
|
||||
} catch (Exception e) {
|
||||
mExecutionListener.onException(mJavaScriptEngine, mScriptSource, e);
|
||||
mExecutionListener.onException(execution, e);
|
||||
super.finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void doExecution() {
|
||||
mJavaScriptEngine.setTag("script", mScriptSource);
|
||||
mExecutionListener.onStart(mJavaScriptEngine, mScriptSource);
|
||||
mExecutionListener.onStart(execution);
|
||||
mResult = mJavaScriptEngine.execute(mScriptSource);
|
||||
}
|
||||
|
||||
@@ -69,7 +68,7 @@ public class ScriptExecuteActivity extends Activity {
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
mExecutionListener.onSuccess(mJavaScriptEngine, mScriptSource, mResult);
|
||||
mExecutionListener.onSuccess(execution, mResult);
|
||||
super.finish();
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ public class ScriptExecuteActivity extends Activity {
|
||||
execution = null;
|
||||
}
|
||||
|
||||
private static class ActivityScriptExecution extends ScriptExecution.AbstarctScriptExecution {
|
||||
private static class ActivityScriptExecution extends ScriptExecution.AbstractScriptExecution {
|
||||
|
||||
private JavaScriptEngine mJavaScriptEngine;
|
||||
private ScriptRuntime mScriptRuntime;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.stardust.autojs;
|
||||
package com.stardust.autojs.execution;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.stardust.autojs.execution;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.autojs.ScriptEngineService;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/1.
|
||||
*/
|
||||
|
||||
public class RunnableScriptExecution extends ScriptExecution.AbstractScriptExecution implements ScriptExecution, Runnable {
|
||||
|
||||
private static final String TAG = "RunnableScriptExecution";
|
||||
private JavaScriptEngine mJavaScriptEngine;
|
||||
private ScriptRuntime mScriptRuntime;
|
||||
private ScriptEngineService mScriptEngineService;
|
||||
|
||||
public RunnableScriptExecution(ScriptEngineService service, ScriptExecutionTask task) {
|
||||
super(task);
|
||||
mScriptEngineService = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mJavaScriptEngine = mScriptEngineService.createScriptEngine();
|
||||
mScriptRuntime = mScriptEngineService.createScriptRuntime();
|
||||
execute(mScriptRuntime, mJavaScriptEngine);
|
||||
}
|
||||
|
||||
private void execute(ScriptRuntime runtime, JavaScriptEngine engine) {
|
||||
try {
|
||||
prepare(runtime, engine);
|
||||
doExecution(engine);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
getListener().onException(this, e);
|
||||
} finally {
|
||||
Log.d(TAG, "Engine destroy");
|
||||
engine.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private void prepare(ScriptRuntime runtime, JavaScriptEngine engine) {
|
||||
if ((getSource().getExecutionMode() & ScriptSource.EXECUTION_MODE_AUTO) != 0) {
|
||||
runtime.ensureAccessibilityServiceEnabled();
|
||||
}
|
||||
engine.put("__runtime__", runtime);
|
||||
engine.init();
|
||||
}
|
||||
|
||||
private void doExecution(JavaScriptEngine engine) {
|
||||
engine.setTag("script", getSource());
|
||||
getListener().onStart(this);
|
||||
getListener().onSuccess(this, engine.execute(getSource()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaScriptEngine getEngine() {
|
||||
return mJavaScriptEngine;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptRuntime getRuntime() {
|
||||
return mScriptRuntime;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.stardust.autojs;
|
||||
package com.stardust.autojs.execution;
|
||||
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
import com.stardust.autojs.runtime.ScriptRuntime;
|
||||
@@ -20,11 +20,11 @@ public interface ScriptExecution {
|
||||
|
||||
ExecutionConfig getConfig();
|
||||
|
||||
abstract class AbstarctScriptExecution implements ScriptExecution {
|
||||
abstract class AbstractScriptExecution implements ScriptExecution {
|
||||
|
||||
protected ScriptExecutionTask mScriptExecutionTask;
|
||||
|
||||
public AbstarctScriptExecution(ScriptExecutionTask task) {
|
||||
public AbstractScriptExecution(ScriptExecutionTask task) {
|
||||
mScriptExecutionTask = task;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.stardust.autojs.execution;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
|
||||
public interface ScriptExecutionListener extends Serializable {
|
||||
|
||||
void onStart(ScriptExecution execution);
|
||||
|
||||
void onSuccess(ScriptExecution execution, Object result);
|
||||
|
||||
void onException(ScriptExecution execution, Exception e);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.stardust.autojs.execution;
|
||||
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/5/3.
|
||||
*/
|
||||
|
||||
public class ScriptExecutionObserver implements ScriptExecutionListener {
|
||||
private CopyOnWriteArraySet<ScriptExecutionListener> mScriptExecutionListeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
@Override
|
||||
public void onStart(ScriptExecution execution) {
|
||||
for (ScriptExecutionListener listener : mScriptExecutionListeners) {
|
||||
listener.onStart(execution);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(ScriptExecution execution, Object result) {
|
||||
for (ScriptExecutionListener listener : mScriptExecutionListeners) {
|
||||
listener.onSuccess(execution, result);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(ScriptExecution execution, Exception e) {
|
||||
for (ScriptExecutionListener listener : mScriptExecutionListeners) {
|
||||
listener.onException(execution, e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean registerScriptExecutionListener(ScriptExecutionListener listener) {
|
||||
return mScriptExecutionListeners.add(listener);
|
||||
}
|
||||
|
||||
public boolean removeScriptExecutionListener(ScriptExecutionListener listener) {
|
||||
return mScriptExecutionListeners.remove(listener);
|
||||
}
|
||||
|
||||
public static class Wrapper implements ScriptExecutionListener {
|
||||
|
||||
private final ScriptExecutionObserver mScriptExecutionObserver;
|
||||
private final ScriptExecutionListener mScriptExecutionListener;
|
||||
|
||||
public Wrapper(ScriptExecutionObserver scriptExecutionObserver, ScriptExecutionListener scriptExecutionListener) {
|
||||
mScriptExecutionObserver = scriptExecutionObserver;
|
||||
mScriptExecutionListener = scriptExecutionListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(ScriptExecution execution) {
|
||||
mScriptExecutionListener.onStart(execution);
|
||||
mScriptExecutionObserver.onStart(execution);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(ScriptExecution execution, Object result) {
|
||||
mScriptExecutionListener.onSuccess(execution, result);
|
||||
mScriptExecutionObserver.onSuccess(execution, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(ScriptExecution execution, Exception e) {
|
||||
mScriptExecutionListener.onException(execution, e);
|
||||
mScriptExecutionObserver.onException(execution, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.stardust.autojs.execution;
|
||||
|
||||
import com.stardust.autojs.script.ScriptSource;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
|
||||
public class ScriptExecutionTask implements Serializable {
|
||||
|
||||
private ScriptSource mScriptSource;
|
||||
private ScriptExecutionListener mExecutionListener;
|
||||
private ExecutionConfig mExecutionConfig;
|
||||
|
||||
public ScriptExecutionTask(ScriptSource source, ScriptExecutionListener listener, ExecutionConfig config) {
|
||||
mScriptSource = source;
|
||||
mExecutionListener = listener;
|
||||
mExecutionConfig = config;
|
||||
}
|
||||
|
||||
public ScriptSource getSource() {
|
||||
return mScriptSource;
|
||||
}
|
||||
|
||||
public ScriptExecutionListener getListener() {
|
||||
return mExecutionListener;
|
||||
}
|
||||
|
||||
public ExecutionConfig getConfig() {
|
||||
return mExecutionConfig;
|
||||
}
|
||||
|
||||
public void setExecutionListener(ScriptExecutionListener executionListener) {
|
||||
mExecutionListener = executionListener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.stardust.autojs.execution;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
*/
|
||||
|
||||
public class SimpleScriptExecutionListener implements ScriptExecutionListener {
|
||||
|
||||
@Override
|
||||
public void onStart(ScriptExecution execution) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(ScriptExecution execution, Object result) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onException(ScriptExecution execution, Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
package com.stardust.autojs.rhino_android;
|
||||
|
||||
|
||||
import com.stardust.autojs.runtime.ScriptInterrupptedException;
|
||||
import com.stardust.autojs.runtime.ScriptStopException;
|
||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
@@ -40,7 +39,7 @@ public class AndroidContextFactory extends ContextFactory {
|
||||
@Override
|
||||
protected void observeInstructionCount(Context cx, int instructionCount) {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new ScriptInterrupptedException();
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.stardust.autojs.runtime;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.autojs.runtime.api.Console;
|
||||
|
||||
@@ -12,10 +11,8 @@ import com.stardust.autojs.runtime.api.Console;
|
||||
|
||||
public abstract class AbstractConsole implements Console {
|
||||
|
||||
protected abstract void log(int level, CharSequence charSequence);
|
||||
|
||||
public void println(int level, @Nullable Object data, Object... options) {
|
||||
log(level, format(data, options));
|
||||
public void printf(int level, @Nullable Object data, Object... options) {
|
||||
println(level, format(data, options));
|
||||
}
|
||||
|
||||
public CharSequence format(@Nullable Object data, Object... options) {
|
||||
@@ -29,33 +26,33 @@ public abstract class AbstractConsole implements Console {
|
||||
|
||||
@Override
|
||||
public void verbose(@Nullable Object data, Object... options) {
|
||||
println(Log.VERBOSE, data, options);
|
||||
printf(Log.VERBOSE, data, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(@Nullable Object data, Object... options) {
|
||||
println(Log.DEBUG, data, options);
|
||||
printf(Log.DEBUG, data, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@Nullable Object data, Object... options) {
|
||||
println(Log.INFO, data, options);
|
||||
printf(Log.INFO, data, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(@Nullable Object data, Object... options) {
|
||||
println(Log.WARN, data, options);
|
||||
printf(Log.WARN, data, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(@Nullable Object data, Object... options) {
|
||||
println(Log.ERROR, data, options);
|
||||
printf(Log.ERROR, data, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertTrue(boolean value, @Nullable Object data, Object... options) {
|
||||
if (!value) {
|
||||
println(Log.ASSERT, data, options);
|
||||
printf(Log.ASSERT, data, options);
|
||||
throw new ScriptStopException(new AssertionError(format(data, options)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.stardust.autojs.runtime;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/30.
|
||||
*/
|
||||
|
||||
public class ScriptInterrupptedException extends ScriptStopException {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.stardust.autojs.runtime;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/30.
|
||||
*/
|
||||
|
||||
public class ScriptInterruptedException extends ScriptStopException {
|
||||
|
||||
public static boolean causedByInterrupted(Throwable e) {
|
||||
return e instanceof ScriptInterruptedException || e.getCause() instanceof ScriptInterruptedException;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,6 @@
|
||||
package com.stardust.autojs.runtime;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.autojs.R;
|
||||
import com.stardust.autojs.engine.JavaScriptEngine;
|
||||
@@ -18,8 +15,8 @@ import com.stardust.pio.UncheckedIOException;
|
||||
import com.stardust.util.ClipboardUtil;
|
||||
import com.stardust.util.SdkVersionUtil;
|
||||
import com.stardust.util.Shell;
|
||||
import com.stardust.util.UiHandler;
|
||||
import com.stardust.view.accessibility.AccessibilityInfoProvider;
|
||||
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
|
||||
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
|
||||
@@ -35,8 +32,7 @@ public class ScriptRuntime {
|
||||
|
||||
private static final String TAG = "ScriptRuntime";
|
||||
|
||||
private Handler mUIHandler;
|
||||
private Context mContext;
|
||||
private UiHandler mUiHandler;
|
||||
private AccessibilityBridge mAccessibilityBridge;
|
||||
|
||||
@JavascriptField
|
||||
@@ -53,11 +49,10 @@ public class ScriptRuntime {
|
||||
|
||||
private AbstractShell mRootShell;
|
||||
|
||||
public ScriptRuntime(Context context, Handler uiHandler, Console console, AccessibilityBridge accessibilityBridge) {
|
||||
mContext = context;
|
||||
public ScriptRuntime(UiHandler uiHandler, Console console, AccessibilityBridge accessibilityBridge) {
|
||||
mAccessibilityBridge = accessibilityBridge;
|
||||
mUIHandler = uiHandler;
|
||||
app = new AppUtils(context);
|
||||
mUiHandler = uiHandler;
|
||||
app = new AppUtils(uiHandler.getContext());
|
||||
info = accessibilityBridge.getInfoProvider();
|
||||
this.console = console;
|
||||
automator = new SimpleActionAutomator(accessibilityBridge, this);
|
||||
@@ -65,12 +60,7 @@ public class ScriptRuntime {
|
||||
|
||||
@JavascriptInterface
|
||||
public void toast(final String text) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(mContext, text, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
mUiHandler.toast(text);
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
@@ -78,16 +68,16 @@ public class ScriptRuntime {
|
||||
try {
|
||||
Thread.sleep(millis);
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptInterrupptedException();
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public void setClip(final String text) {
|
||||
mUIHandler.post(new Runnable() {
|
||||
mUiHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ClipboardUtil.setClip(mContext, text);
|
||||
ClipboardUtil.setClip(mUiHandler.getContext(), text);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -119,7 +109,7 @@ public class ScriptRuntime {
|
||||
@JavascriptInterface
|
||||
public void requiresApi(int i) {
|
||||
if (Build.VERSION.SDK_INT < i) {
|
||||
throw new ScriptStopException(mContext.getString(R.string.text_requires_sdk_version_to_run_the_script) + SdkVersionUtil.sdkIntToString(i));
|
||||
throw new ScriptStopException(mUiHandler.getContext().getString(R.string.text_requires_sdk_version_to_run_the_script) + SdkVersionUtil.sdkIntToString(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,4 +36,8 @@ public interface Console {
|
||||
|
||||
@JavascriptInterface
|
||||
void hide();
|
||||
|
||||
void println(int level, CharSequence charSequence);
|
||||
|
||||
void setTitle(CharSequence title);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,7 @@ import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
||||
|
||||
import com.stardust.autojs.runtime.ScriptInterrupptedException;
|
||||
import com.stardust.autojs.runtime.ScriptStopException;
|
||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
@@ -108,7 +107,7 @@ public class InjectableWebClient extends WebViewClient {
|
||||
try {
|
||||
ScriptBridge.this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptInterrupptedException();
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
@@ -132,7 +131,7 @@ public class InjectableWebClient extends WebViewClient {
|
||||
try {
|
||||
this.wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new ScriptInterrupptedException();
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -8,7 +8,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import com.stardust.autojs.runtime.AccessibilityBridge;
|
||||
import com.stardust.autojs.runtime.JavascriptInterface;
|
||||
import com.stardust.autojs.runtime.ScriptInterrupptedException;
|
||||
import com.stardust.autojs.runtime.ScriptInterruptedException;
|
||||
import com.stardust.automator.AccessibilityEventCommandHost;
|
||||
import com.stardust.automator.ActionArgument;
|
||||
import com.stardust.automator.UiGlobalSelector;
|
||||
@@ -118,7 +118,7 @@ public class UiSelector extends UiGlobalSelector {
|
||||
do {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
Log.d(TAG, "Thread isInterrupted");
|
||||
throw new ScriptInterrupptedException();
|
||||
throw new ScriptInterruptedException();
|
||||
}
|
||||
uiObjectCollection = find();
|
||||
} while (uiObjectCollection == null || uiObjectCollection.size() == 0);
|
||||
|
||||
@@ -29,8 +29,8 @@ public class JsBeautifier {
|
||||
|
||||
private Executor mExecutor = Executors.newSingleThreadExecutor();
|
||||
private Context mContext;
|
||||
private org.mozilla.javascript.Context mScriptContext;
|
||||
private Function mJsBeautifyFunction;
|
||||
private org.mozilla.javascript.Context mScriptContext;
|
||||
private Scriptable mScriptable;
|
||||
private final String mBeautifyJsPath;
|
||||
|
||||
@@ -45,16 +45,33 @@ public class JsBeautifier {
|
||||
public void run() {
|
||||
try {
|
||||
prepareIfNeeded();
|
||||
enterContext();
|
||||
Object beautifiedCode = mJsBeautifyFunction.call(mScriptContext, mScriptable, mScriptable, new Object[]{code});
|
||||
callback.onSuccess(beautifiedCode.toString());
|
||||
} catch (Exception e) {
|
||||
callback.onException(e);
|
||||
} finally {
|
||||
exitContext();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void exitContext() {
|
||||
if (mScriptContext != null) {
|
||||
org.mozilla.javascript.Context.exit();
|
||||
mScriptContext = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void enterContext() {
|
||||
if (mScriptContext == null) {
|
||||
mScriptContext = org.mozilla.javascript.Context.enter();
|
||||
mScriptContext.setOptimizationLevel(-1);
|
||||
}
|
||||
}
|
||||
|
||||
public void prepare() {
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
@@ -71,19 +88,20 @@ public class JsBeautifier {
|
||||
|
||||
|
||||
private void prepareIfNeeded() {
|
||||
if (mScriptContext != null)
|
||||
if (mJsBeautifyFunction != null)
|
||||
return;
|
||||
RhinoAndroidHelper helper = new RhinoAndroidHelper(mContext);
|
||||
mScriptContext = helper.enterContext();
|
||||
compile();
|
||||
}
|
||||
|
||||
private void compile() {
|
||||
try {
|
||||
enterContext();
|
||||
InputStream is = mContext.getAssets().open(mBeautifyJsPath);
|
||||
mScriptable = mScriptContext.initSafeStandardObjects();
|
||||
if (mScriptable == null)
|
||||
mScriptable = mScriptContext.initSafeStandardObjects();
|
||||
mJsBeautifyFunction = mScriptContext.compileFunction(mScriptable, PFile.read(is), "<js_beautify>", 1, null);
|
||||
} catch (IOException e) {
|
||||
exitContext();
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user