// Copyright (c) 2009 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.v8native; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.chromium.sdk.JsEvaluateContext; import org.chromium.sdk.JsVariable; import org.chromium.sdk.RelayOk; import org.chromium.sdk.SyncCallback; import org.chromium.sdk.internal.JsEvaluateContextBase; import org.chromium.sdk.internal.protocolparser.JsonProtocolParseException; import org.chromium.sdk.internal.v8native.InternalContext.ContextDismissedCheckedException; import org.chromium.sdk.internal.v8native.protocol.input.SuccessCommandResponse; import org.chromium.sdk.internal.v8native.protocol.input.data.ValueHandle; import org.chromium.sdk.internal.v8native.protocol.output.DebuggerMessage; import org.chromium.sdk.internal.v8native.protocol.output.DebuggerMessageFactory; import org.chromium.sdk.internal.v8native.value.JsObjectBase; import org.chromium.sdk.internal.v8native.value.JsVariableImpl; import org.chromium.sdk.internal.v8native.value.ValueMirror; import org.chromium.sdk.util.RelaySyncCallback; /** * Generic implementation of {@link JsEvaluateContext}. The abstract class leaves unspecified * stack frame identifier (possibly null) and reference to {@link InternalContext}. */ abstract class JsEvaluateContextImpl extends JsEvaluateContextBase { public RelayOk evaluateAsyncImpl(final String expression, Map<String, String> additionalContext, final EvaluateCallback callback, SyncCallback syncCallback) throws ContextDismissedCheckedException { Integer frameIdentifier = getFrameIdentifier(); Boolean isGlobal = frameIdentifier == null ? Boolean.TRUE : null; List<Map.Entry<String, Integer>> internalAdditionalContext = convertAdditionalContextList(additionalContext); DebuggerMessage message = DebuggerMessageFactory.evaluate(expression, frameIdentifier, isGlobal, Boolean.TRUE, internalAdditionalContext); V8CommandProcessor.V8HandlerCallback commandCallback = callback == null ? null : new V8CommandCallbackBase() { @Override public void success(SuccessCommandResponse successResponse) { ValueHandle body; try { body = successResponse.body().asEvaluateBody(); } catch (JsonProtocolParseException e) { throw new RuntimeException(e); } InternalContext internalContext = getInternalContext(); ValueMirror mirror = internalContext.getValueLoader().addDataToMap(body); JsVariable variable = new JsVariableImpl(internalContext.getValueLoader(), mirror, expression); callback.success(variable); } @Override public void failure(String message) { callback.failure(message); } }; return getInternalContext().sendV8CommandAsync(message, true, commandCallback, syncCallback); } @Override public RelayOk evaluateAsync(final String expression, Map<String, String> additionalContext, final EvaluateCallback callback, SyncCallback syncCallback) { try { return evaluateAsyncImpl(expression, additionalContext, callback, syncCallback); } catch (ContextDismissedCheckedException e) { maybeRethrowContextException(e); // or callback.failure(e.getMessage()); return RelaySyncCallback.finish(syncCallback); } } private void maybeRethrowContextException(ContextDismissedCheckedException ex) { getInternalContext().getDebugSession().maybeRethrowContextException(ex); } private static List<Map.Entry<String, Integer>> convertAdditionalContextList( Map<String, String> source) { if (source == null) { return null; } final List<Map.Entry<String, Integer>> dataList = new ArrayList<Map.Entry<String,Integer>>(source.size()); for (final Map.Entry<String, String> en : source.entrySet()) { final int refValue = JsObjectBase.parseRefId(en.getValue()); Map.Entry<String, Integer> convertedEntry = new Map.Entry<String, Integer>() { public String getKey() { return en.getKey(); } public Integer getValue() { return refValue; } public Integer setValue(Integer value) { throw new UnsupportedOperationException(); } }; dataList.add(convertedEntry); } return dataList; } /** * @return frame identifier or null if the context is not frame-related */ protected abstract Integer getFrameIdentifier(); protected abstract InternalContext getInternalContext(); }