| Index: plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/wip/WipScriptManager.java
|
| diff --git a/plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/wip/WipScriptManager.java b/plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/wip/WipScriptManager.java
|
| deleted file mode 100644
|
| index c17a86e53ac8c28b26cd344bc7865aecde0994b6..0000000000000000000000000000000000000000
|
| --- a/plugins/org.chromium.sdk.wipbackend.wk118685/src/org/chromium/sdk/internal/wip/WipScriptManager.java
|
| +++ /dev/null
|
| @@ -1,376 +0,0 @@
|
| -// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -package org.chromium.sdk.internal.wip;
|
| -
|
| -import static org.chromium.sdk.util.BasicUtil.containsKeySafe;
|
| -import static org.chromium.sdk.util.BasicUtil.getSafe;
|
| -
|
| -import java.util.ArrayDeque;
|
| -import java.util.ArrayList;
|
| -import java.util.Collection;
|
| -import java.util.HashMap;
|
| -import java.util.List;
|
| -import java.util.Map;
|
| -import java.util.Queue;
|
| -import java.util.Set;
|
| -
|
| -import org.chromium.sdk.DebugEventListener;
|
| -import org.chromium.sdk.JavascriptVm;
|
| -import org.chromium.sdk.RelayOk;
|
| -import org.chromium.sdk.Script;
|
| -import org.chromium.sdk.SyncCallback;
|
| -import org.chromium.sdk.internal.ScriptBase;
|
| -import org.chromium.sdk.internal.wip.protocol.input.debugger.GetScriptSourceData;
|
| -import org.chromium.sdk.internal.wip.protocol.input.debugger.ScriptParsedEventData;
|
| -import org.chromium.sdk.internal.wip.protocol.output.debugger.GetScriptSourceParams;
|
| -import org.chromium.sdk.util.AsyncFuture;
|
| -import org.chromium.sdk.util.AsyncFuture.Callback;
|
| -import org.chromium.sdk.util.AsyncFutureMerger;
|
| -import org.chromium.sdk.util.AsyncFutureRef;
|
| -import org.chromium.sdk.util.GenericCallback;
|
| -import org.chromium.sdk.util.RelaySyncCallback;
|
| -
|
| -/**
|
| - * Keeps all current scripts for the debug session and handles script source loading.
|
| - */
|
| -class WipScriptManager {
|
| - private final WipTabImpl tabImpl;
|
| - // Access must be synchronized.
|
| - private final Map<String, ScriptData> scriptIdToData = new HashMap<String, ScriptData>();
|
| -
|
| - /**
|
| - * A future for script pre-load operation. User may call {@link #getScripts} at any time,
|
| - * but we return result only once we have loaded all pre-existing scripts.
|
| - */
|
| - private final AsyncFutureRef<Void> scriptsPreloaded;
|
| -
|
| - /** Accessed from Dispatch thread only. */
|
| - private ScriptPopulateMode populateMode = new ScriptPopulateMode();
|
| -
|
| - WipScriptManager(WipTabImpl tabImpl) {
|
| - this.tabImpl = tabImpl;
|
| - this.scriptsPreloaded = populateMode.createAndInitMasterFuture();
|
| - }
|
| -
|
| - WipTabImpl getTabImpl() {
|
| - return tabImpl;
|
| - }
|
| -
|
| - // Run command in dispatch thread so that no scripts event could happen in the meantime.
|
| - // TODO: make sure we do not return those scripts that are reported compiled but not loaded yet.
|
| - RelayOk getScripts(final GenericCallback<Collection<Script>> callback,
|
| - SyncCallback syncCallback) {
|
| -
|
| - // Async command chain here, wrap syncCallback to guaranteed calling.
|
| - RelaySyncCallback relay = new RelaySyncCallback(syncCallback);
|
| -
|
| - // Guard for the step one.
|
| - final RelaySyncCallback.Guard guardOne = relay.newGuard();
|
| -
|
| - // Chain commands are in the reverse order.
|
| -
|
| - // Wait for script pre-load operation and return scripts.
|
| - final AsyncFuture.Callback<Void> futureCallback = new AsyncFuture.Callback<Void>() {
|
| - @Override
|
| - public void done(Void res) {
|
| - if (callback != null) {
|
| - callback.success(getCurrentScripts());
|
| - }
|
| - }
|
| - };
|
| -
|
| - // Start everything in dispatch thread (otherwise user may be called from this thread).
|
| - Runnable mainRunnable = new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - RelayOk relayOk =
|
| - scriptsPreloaded.getAsync(futureCallback, guardOne.getRelay().getUserSyncCallback());
|
| - guardOne.discharge(relayOk);
|
| - }
|
| - };
|
| -
|
| - return tabImpl.getCommandProcessor().runInDispatchThread(mainRunnable,
|
| - guardOne.asSyncCallback());
|
| - }
|
| -
|
| - Script getScript(String scriptId) {
|
| - ScriptData data;
|
| - synchronized (scriptIdToData) {
|
| - data = getSafe(scriptIdToData, scriptId);
|
| - }
|
| - if (data == null) {
|
| - return null;
|
| - }
|
| - if (!data.sourceLoadedFuture.isDone()) {
|
| - return null;
|
| - }
|
| - return data.scriptImpl;
|
| - }
|
| -
|
| -
|
| - private Collection<Script> getCurrentScripts() {
|
| - synchronized (scriptIdToData) {
|
| - List<Script> list = new ArrayList<Script>(scriptIdToData.size());
|
| - for (ScriptData data : scriptIdToData.values()) {
|
| - if (data.sourceLoadedFuture.isDone()) {
|
| - list.add(data.scriptImpl);
|
| - }
|
| - }
|
| - return list;
|
| - }
|
| - }
|
| -
|
| - public void scriptIsReportedParsed(ScriptParsedEventData data) {
|
| - final String sourceID = data.scriptId();
|
| -
|
| - String url = data.url();
|
| - if (url.isEmpty()) {
|
| - url = null;
|
| - }
|
| -
|
| - ScriptBase.Descriptor<String> descriptor = new ScriptBase.Descriptor<String>(Script.Type.NORMAL,
|
| - sourceID, url, (int) data.startLine(), (int) data.startColumn(), -1);
|
| - final WipScriptImpl script = new WipScriptImpl(this, descriptor);
|
| - final ScriptData scriptData = new ScriptData(script);
|
| -
|
| - synchronized (scriptIdToData) {
|
| - if (containsKeySafe(scriptIdToData, sourceID)) {
|
| - throw new IllegalStateException("Already has script with id " + sourceID);
|
| - }
|
| - scriptIdToData.put(sourceID, scriptData);
|
| - }
|
| -
|
| - scriptData.sourceLoadedFuture.initializeRunning(new SourceLoadOperation(script, sourceID));
|
| -
|
| - final ScriptPopulateMode populateModeSaved = populateMode;
|
| -
|
| - AsyncFuture.Callback<Boolean> callback;
|
| - SyncCallback syncCallback;
|
| -
|
| - if (populateModeSaved == null) {
|
| - callback = new AsyncFuture.Callback<Boolean>() {
|
| - @Override
|
| - public void done(Boolean res) {
|
| - tabImpl.getTabListener().getDebugEventListener().scriptLoaded(script);
|
| - }
|
| - };
|
| - syncCallback = null;
|
| - } else {
|
| - populateModeSaved.anotherSourceToWait();
|
| -
|
| - callback = new AsyncFuture.Callback<Boolean>() {
|
| - @Override
|
| - public void done(Boolean res) {
|
| - populateModeSaved.sourceLoaded(res);
|
| - }
|
| - };
|
| - syncCallback = new SyncCallback() {
|
| - @Override
|
| - public void callbackDone(RuntimeException e) {
|
| - populateModeSaved.sourceLoadedSync(e);
|
| - }
|
| - };
|
| - }
|
| -
|
| - scriptData.sourceLoadedFuture.getAsync(callback, syncCallback);
|
| - }
|
| -
|
| - /**
|
| - * Asynchronously loads script source.
|
| - */
|
| - private final class SourceLoadOperation implements AsyncFuture.Operation<Boolean> {
|
| - private final WipScriptImpl script;
|
| - private final String sourceID;
|
| -
|
| - private SourceLoadOperation(WipScriptImpl script, String sourceID) {
|
| - this.script = script;
|
| - this.sourceID = sourceID;
|
| - }
|
| -
|
| - @Override
|
| - public RelayOk start(final Callback<Boolean> operationCallback, SyncCallback syncCallback) {
|
| - GenericCallback<GetScriptSourceData> commandCallback =
|
| - new GenericCallback<GetScriptSourceData>() {
|
| - @Override
|
| - public void success(GetScriptSourceData data) {
|
| - String source = data.scriptSource();
|
| - script.setSource(source);
|
| - operationCallback.done(true);
|
| - }
|
| - @Override
|
| - public void failure(Exception exception) {
|
| - throw new RuntimeException(exception);
|
| - }
|
| - };
|
| - GetScriptSourceParams params = new GetScriptSourceParams(sourceID);
|
| - return tabImpl.getCommandProcessor().send(params, commandCallback, syncCallback);
|
| - }
|
| - }
|
| -
|
| - private class ScriptData {
|
| - final WipScriptImpl scriptImpl;
|
| - final AsyncFutureRef<Boolean> sourceLoadedFuture = new AsyncFutureRef<Boolean>();
|
| -
|
| - ScriptData(WipScriptImpl scriptImpl) {
|
| - this.scriptImpl = scriptImpl;
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Asynchronously loads all script sources that will be referenced from a new debug context
|
| - * (from its stack frames).
|
| - * Must be called from Dispatch thread.
|
| - */
|
| - RelayOk loadScriptSourcesAsync(Set<String> ids, ScriptSourceLoadCallback callback,
|
| - SyncCallback syncCallback) {
|
| - Queue<ScriptData> scripts = new ArrayDeque<ScriptData>(ids.size());
|
| - Map<String, WipScriptImpl> result = new HashMap<String, WipScriptImpl>(ids.size());
|
| - synchronized (scriptIdToData) {
|
| - for (String id : ids) {
|
| - ScriptData data = getSafe(scriptIdToData, id);
|
| - if (data == null) {
|
| - // We probably got id of internal script (usually happens when we suspend on breakpoint
|
| - // thrown from internals).
|
| - result.put(id, null);
|
| - continue;
|
| - }
|
| - result.put(id, data.scriptImpl);
|
| - if (!data.sourceLoadedFuture.isDone()) {
|
| - scripts.add(data);
|
| - }
|
| - }
|
| - }
|
| -
|
| - // Start a chain of asynchronous operations.
|
| - // Make sure we call this sync callback sooner or later.
|
| - RelaySyncCallback relay = new RelaySyncCallback(syncCallback);
|
| -
|
| - return loadNextScript(scripts, result, callback, relay);
|
| - }
|
| -
|
| - interface ScriptSourceLoadCallback {
|
| - void done(Map<String, WipScriptImpl> loadedScripts);
|
| - }
|
| -
|
| - static String convertAlienSourceId(Object sourceIdObj) {
|
| - if (sourceIdObj instanceof String == false) {
|
| - throw new IllegalArgumentException("Script id must be string");
|
| - }
|
| - return (String) sourceIdObj;
|
| - }
|
| -
|
| - // TODO: scripts are loaded in-series; make load parallel instead (to wait less).
|
| - private RelayOk loadNextScript(final Queue<ScriptData> scripts,
|
| - final Map<String, WipScriptImpl> result, final ScriptSourceLoadCallback callback,
|
| - final RelaySyncCallback relay) {
|
| - final ScriptData data = scripts.poll();
|
| - if (data == null) {
|
| - // Terminate the chain of asynchronous loads and pass a result to the callback.
|
| - RelayOk relayOk;
|
| - if (callback != null) {
|
| - callback.done(result);
|
| - }
|
| - return relay.finish();
|
| - }
|
| -
|
| - // Create a guard for the case that we fail before issuing next #loadNextScript() call.
|
| - final RelaySyncCallback.Guard guard = relay.newGuard();
|
| -
|
| - AsyncFuture.Callback<Boolean> futureCallback = new AsyncFuture.Callback<Boolean>() {
|
| - @Override
|
| - public void done(Boolean res) {
|
| - RelayOk relayOk = loadNextScript(scripts, result, callback, relay);
|
| - // We successfully relayed responsibility for operationDestructable to next async call,
|
| - // discharge guard.
|
| - guard.discharge(relayOk);
|
| - }
|
| - };
|
| -
|
| - // The async operation will call a guard even if something failed within the AsyncFuture.
|
| - return data.sourceLoadedFuture.getAsync(futureCallback, guard.asSyncCallback());
|
| - }
|
| -
|
| - public void pageReloaded() {
|
| - synchronized (scriptIdToData) {
|
| - scriptIdToData.clear();
|
| - }
|
| - }
|
| -
|
| - void endPopulateScriptMode() {
|
| - populateMode.endMode();
|
| - populateMode = null;
|
| - }
|
| -
|
| - /**
|
| - * Right after initialization we come into 'populate scripts' mode, when back-end
|
| - * reports about all pre-existing scripts as if they have just been parsed.
|
| - * <p>
|
| - * We treat this notifications differently: all these scripts must be returned from
|
| - * {@link JavascriptVm#getScripts} from the beginning and only truly new scripts get
|
| - * reported via {@link DebugEventListener#scriptLoaded}.
|
| - * <p>
|
| - * This means that until 'populate mode' ends (and all sources are loaded),
|
| - * {@link JavascriptVm#getScripts} call blocks.
|
| - */
|
| - private static class ScriptPopulateMode {
|
| - /**
|
| - * Future for script preload operation. It completes when all pre-exising scripts
|
| - * are fully loaded (with sources). The operation result value is an array of
|
| - * source loading success/failure flags.
|
| - */
|
| - private final AsyncFutureMerger<Boolean> populateAndLoadSourcesFuture =
|
| - new AsyncFutureMerger<Boolean>();
|
| -
|
| - /**
|
| - * Reports that 'populate script' mode is finished. However we may still be waiting for
|
| - * the corresponding script sources.
|
| - */
|
| - void endMode() {
|
| - populateAndLoadSourcesFuture.subOperationDone(null);
|
| - populateAndLoadSourcesFuture.subOperationDoneSync(null);
|
| - }
|
| -
|
| - /**
|
| - * We learned about another pre-existing script. Now we have to wait for its source.
|
| - */
|
| - void anotherSourceToWait() {
|
| - populateAndLoadSourcesFuture.addSubOperation();
|
| - }
|
| -
|
| - void sourceLoaded(Boolean result) {
|
| - populateAndLoadSourcesFuture.subOperationDone(result);
|
| - }
|
| -
|
| - /**
|
| - * Additional method that completes {@link #sourceLoaded} and used to be compatible with
|
| - * {@link SyncCallback} paradigm.
|
| - */
|
| - void sourceLoadedSync(RuntimeException e) {
|
| - populateAndLoadSourcesFuture.subOperationDoneSync(e);
|
| - }
|
| -
|
| - /**
|
| - * Creates a 'master operation' future that hides the complex result value
|
| - * of {@link #populateAndLoadSourcesFuture}. It hides it from Java GC also,
|
| - * so the {@link ArrayList} gets collected once operation is finished.
|
| - */
|
| - AsyncFutureRef<Void> createAndInitMasterFuture() {
|
| - AsyncFutureRef<Void> asyncFutureRef = new AsyncFutureRef<Void>();
|
| - asyncFutureRef.initializeRunning(new AsyncFuture.Operation<Void>() {
|
| - @Override
|
| - public RelayOk start(final Callback<Void> callback, SyncCallback syncCallback) {
|
| - AsyncFuture<?> innerFuture = populateAndLoadSourcesFuture.getFuture();
|
| - return innerFuture.getAsync(new Callback<Object>() {
|
| - @Override
|
| - public void done(Object res) {
|
| - callback.done(null);
|
| - }
|
| - }, syncCallback);
|
| - }
|
| - });
|
| - return asyncFutureRef;
|
| - }
|
| - }
|
| -}
|
|
|