/* * Copyright 2022 The Android Open Source Project * * 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 androidx.javascriptengine; import android.content.res.AssetFileDescriptor; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresFeature; import androidx.concurrent.futures.CallbackToFutureAdapter; import com.google.common.util.concurrent.ListenableFuture; import org.chromium.android_webview.js_sandbox.common.IJsSandboxIsolate; import org.chromium.android_webview.js_sandbox.common.IJsSandboxIsolateCallback; import java.io.Closeable; import java.io.IOException; import java.io.OutputStream; import java.util.HashSet; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.concurrent.GuardedBy; /** * Environment within a {@link JavaScriptSandbox} where Javascript is executed. * * A single {@link JavaScriptSandbox} process can contain any number of {@link JavaScriptIsolate} * instances where JS can be evaluated independently and in parallel. *
* Each isolate has its own state and JS global object, * and cannot interact with any other isolate through JS APIs. There is only a moderate * security boundary between isolates in a single {@link JavaScriptSandbox}. If the code in one * {@link JavaScriptIsolate} is able to compromise the security of the JS engine then it may be * able to observe or manipulate other isolates, since they run in the same process. For strong * isolation multiple {@link JavaScriptSandbox} processes should be used, but it is not supported * at the moment. Please find the feature request here. *
* Each isolate object must only be used from one thread.
*/
public final class JavaScriptIsolate implements AutoCloseable {
private static final String TAG = "JavaScriptIsolate";
private final Object mSetLock = new Object();
@Nullable
private IJsSandboxIsolate mJsIsolateStub;
private CloseGuardHelper mGuard = CloseGuardHelper.create();
private final Executor mThreadPoolTaskExecutor =
Executors.newCachedThreadPool(new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "JavaScriptIsolate Thread #" + mCount.getAndIncrement());
}
});
private final JavaScriptSandbox mJsSandbox;
@Nullable
@GuardedBy("mSetLock")
private HashSet
*
* The environment uses a single JS global object for all the calls to {@link
* #evaluateJavaScriptAsync(String)} and {@link #provideNamedData(String, byte[])} methods.
* These calls are queued up and are run one at a time in sequence, using the single JS
* environment for the isolate. The global variables set by one evaluation are visible for
* later evaluations. This is similar to adding multiple {@code