You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2016/04/22 21:30:07 UTC
[45/52] [abbrv] [partial] git commit: [flex-falcon]
[refs/heads/feature/maven-migration-test] - move stuff to where I think Maven
wants it
http://git-wip-us.apache.org/repos/asf/flex-falcon/blob/07f5a7de/debugger/src/flash/tools/debugger/concrete/PlayerSession.java
----------------------------------------------------------------------
diff --git a/debugger/src/flash/tools/debugger/concrete/PlayerSession.java b/debugger/src/flash/tools/debugger/concrete/PlayerSession.java
deleted file mode 100644
index f41ed19..0000000
--- a/debugger/src/flash/tools/debugger/concrete/PlayerSession.java
+++ /dev/null
@@ -1,3069 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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 flash.tools.debugger.concrete;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import flash.tools.debugger.AIRLaunchInfo;
-import flash.tools.debugger.Frame;
-import flash.tools.debugger.IDebuggerCallbacks;
-import flash.tools.debugger.ILauncher;
-import flash.tools.debugger.InProgressException;
-import flash.tools.debugger.Isolate;
-import flash.tools.debugger.IsolateController;
-import flash.tools.debugger.IsolateSession;
-import flash.tools.debugger.Location;
-import flash.tools.debugger.NoResponseException;
-import flash.tools.debugger.NotConnectedException;
-import flash.tools.debugger.NotSupportedException;
-import flash.tools.debugger.NotSuspendedException;
-import flash.tools.debugger.PlayerDebugException;
-import flash.tools.debugger.Session;
-import flash.tools.debugger.SessionManager;
-import flash.tools.debugger.SourceFile;
-import flash.tools.debugger.SourceLocator;
-import flash.tools.debugger.SuspendedException;
-import flash.tools.debugger.SwfInfo;
-import flash.tools.debugger.Value;
-import flash.tools.debugger.ValueAttribute;
-import flash.tools.debugger.Variable;
-import flash.tools.debugger.VariableAttribute;
-import flash.tools.debugger.VariableType;
-import flash.tools.debugger.VersionException;
-import flash.tools.debugger.Watch;
-import flash.tools.debugger.concrete.DProtocol.ListenerIndex;
-import flash.tools.debugger.events.DebugEvent;
-import flash.tools.debugger.events.ExceptionFault;
-import flash.tools.debugger.events.FaultEvent;
-import flash.tools.debugger.expression.ECMA;
-import flash.tools.debugger.expression.PlayerFaultException;
-import flash.util.Trace;
-
-
-public class PlayerSession implements Session, DProtocolNotifierIF, Runnable, IsolateController
-{
- public static final int MAX_STACK_DEPTH = 256;
- public static final long MAX_TERMINATE_WAIT_MILLIS = 10000;
-
- private Socket m_socket;
- private DProtocol m_protocol;
- private DManager m_manager;
- private IDebuggerCallbacks m_debuggerCallbacks;
- private Process m_process;
- private Map<String, Object> m_prefs; // WARNING -- accessed from multiple threads
- private static final String s_newline = System.getProperty("line.separator"); //$NON-NLS-1$
-
- private volatile boolean m_isConnected; // WARNING -- accessed from multiple threads
- private volatile boolean m_isHalted; // WARNING -- accessed from multiple threads
- private volatile boolean m_incoming; // WARNING -- accessed from multiple threads
- private volatile boolean m_lastResponse; // whether there was a reponse from the last message to the Player
- private volatile HashMap<Integer, PlayerSessionIsolateStatus> m_isolateStatus = new HashMap<Integer, PlayerSessionIsolateStatus>();
-
- private int m_watchTransactionTag;
- private Boolean m_playerCanCallFunctions;
- private Boolean m_playerSupportsWatchpoints;
- private Boolean m_playerCanBreakOnAllExceptions;
- private Boolean m_playerSupportsConcurrency;
- private Boolean m_playerSupportsWideLine;
-
- private ILauncher launcher;
-
- /**
- * The URL that was launched, or <code>null</code> if not known. Note:
- * This is NOT the value returned by getURI(). getURI() returns the
- * URL that came from the Player, and is therefore probably the URI of
- * the SWF; but m_launchedUrl contains the URL that we tried to launch,
- * which might be an HTML wrapper, e.g. http://localhost/myapp.html
- */
- private String m_launchUrl;
-
- private AIRLaunchInfo m_airLaunchInfo; // null if this is not an AIR app
-
- static volatile boolean m_debugMsgOn; // debug ONLY; turned on with "set $debug_messages = 1"
- volatile int m_debugMsgSize; // debug ONLY; controlled with "set $debug_message_size = NNN"
- static volatile boolean m_debugMsgFileOn; // debug ONLY for file dump; turned on with "set $debug_message_file = 1"
- volatile int m_debugMsgFileSize; // debug ONLY for file dump; controlled with "set $debug_message_file_size = NNN"
-
- //FIXME: Make this concurrency aware
- /**
- * A simple cache of previous "is" and "instanceof" queries, in order to
- * avoid having to send redundant messages to the player.
- */
- private Map<String, Boolean> m_evalIsAndInstanceofCache = new HashMap<String, Boolean>();
-
- private volatile int m_lastPreIsolate = Isolate.DEFAULT_ID;
-
- private final Map<Integer, IsolateSession> m_isolateSessions;
-
- private static final String DEBUG_MESSAGES = "$debug_messages"; //$NON-NLS-1$
- private static final String DEBUG_MESSAGE_SIZE = "$debug_message_size"; //$NON-NLS-1$
- private static final String DEBUG_MESSAGE_FILE = "$debug_message_file"; //$NON-NLS-1$
- private static final String DEBUG_MESSAGE_FILE_SIZE = "$debug_message_file_size"; //$NON-NLS-1$
-
- private static final String CONSOLE_ERRORS = "$console_errors"; //$NON-NLS-1$
-
- private static final String FLASH_PREFIX = "$flash_"; //$NON-NLS-1$
-
- PlayerSession(Socket s, DProtocol proto, DManager manager, IDebuggerCallbacks debuggerCallbacks)
- {
- m_isConnected = false;
- m_isHalted = false;
- m_socket = s;
- m_protocol = proto;
- m_manager = manager;
- m_prefs = Collections.synchronizedMap(new HashMap<String, Object>());
- m_incoming = false;
- m_debugMsgOn = false;
- m_debugMsgSize = 16;
- m_debugMsgFileOn = false;
- m_debugMsgFileSize = 128;
- m_watchTransactionTag = 1; // number that is sent for each watch transaction that occurs
- m_playerCanCallFunctions = null;
- m_debuggerCallbacks = debuggerCallbacks;
- m_isolateSessions = Collections.synchronizedMap(new HashMap<Integer, IsolateSession>());
- }
-
- private static PlayerSession createFromSocketHelper(Socket s, IDebuggerCallbacks debuggerCallbacks, DProtocol proto) throws IOException
- {
- // let the manager hear incoming messages
- DManager manager = new DManager();
-
- PlayerSession session = new PlayerSession(s, proto, manager, debuggerCallbacks);
- return session;
- }
-
- /**
- * @deprecated Use createFromSocketWithOptions
- * @param s
- * @param debuggerCallbacks
- * @return
- * @throws IOException
- */
- public static PlayerSession createFromSocket(Socket s, IDebuggerCallbacks debuggerCallbacks) throws IOException
- {
- DProtocol proto = DProtocol.createFromSocket(s);
-
- return createFromSocketHelper(s, debuggerCallbacks, proto);
- }
-
- /**
- * Creates a session from the socket. Sets session specific
- * socket settings and stores the callback object.
- * @param s
- * @param debuggerCallbacks
- * @param sessionManager
- * @return
- * @throws IOException
- */
- public static PlayerSession createFromSocketWithOptions(Socket s, IDebuggerCallbacks debuggerCallbacks, SessionManager sessionManager) throws IOException
- {
- DProtocol proto = DProtocol.createFromSocket(s, sessionManager);
-
- return createFromSocketHelper(s, debuggerCallbacks, proto);
- }
-
- /* getter */
- public DMessageCounter getMessageCounter() { return m_protocol.getMessageCounter(); }
- public String getURI() { return m_manager.getURI(); }
- public boolean playerSupportsGet() { return m_manager.isGetSupported(); }
- public int playerVersion() { return m_manager.getVersion(); }
- public SourceLocator getSourceLocator() { return m_manager.getSourceLocator(); }
-
- /*
- * @see flash.tools.debugger.Session#setSourceLocator(flash.tools.debugger.SourceLocator)
- */
- public void setSourceLocator(SourceLocator sourceLocator)
- {
- m_manager.setSourceLocator(sourceLocator);
- }
-
- /**
- * If the manager started the process for us, then note it here. We will attempt to kill
- * it when we go down
- */
- void setProcess(Process proc)
- {
- m_process = proc;
- }
-
- /*
- * @see flash.tools.debugger.Session#getLaunchProcess()
- */
- public Process getLaunchProcess()
- {
- return m_process;
- }
-
- /**
- * Set preference
- * If an invalid preference is passed, it will be silently ignored.
- */
- public void setPreferences(Map<String, ? extends Object> map) { m_prefs.putAll(map); mapBack(); }
- public Set<String> keySet() { return m_prefs.keySet(); }
- public Object getPreferenceAsObject(String pref) { return m_prefs.get(pref); }
-
- /**
- * Set a property. Special logic for debug message boolean
- */
- public void setPreference(String pref, int value)
- {
- m_prefs.put(pref, new Integer(value));
- mapBack();
-
- // change in console messages?
- if (pref.equals(CONSOLE_ERRORS))
- sendConsoleErrorsAsTrace(value == 1);
-
- // generic message for flash player wherein "$flash_xxx" causes "xxx" to be sent
- if (pref.startsWith(FLASH_PREFIX))
- sendOptionMessage(pref.substring(FLASH_PREFIX.length()), Integer.toString(value));
- }
-
- // helper for mapBack()
- private int mapBackOnePreference(String preferenceName, int defaultValue)
- {
- Object prefValue = getPreferenceAsObject(preferenceName);
- if (prefValue != null)
- return ((Integer)prefValue).intValue();
- else
- return defaultValue;
- }
-
- // helper for mapBack()
- private boolean mapBackOnePreference(String preferenceName, boolean defaultValue)
- {
- Object prefValue = getPreferenceAsObject(preferenceName);
- if (prefValue != null)
- return ((Integer)prefValue).intValue() != 0 ? true : false;
- else
- return defaultValue;
- }
-
- // look for preferences, that map back to variables
- private void mapBack()
- {
- m_debugMsgOn = mapBackOnePreference(DEBUG_MESSAGES, m_debugMsgOn);
- m_debugMsgSize = mapBackOnePreference(DEBUG_MESSAGE_SIZE, m_debugMsgSize);
-
- m_debugMsgFileOn = mapBackOnePreference(DEBUG_MESSAGE_FILE, m_debugMsgFileOn);
- m_debugMsgFileSize = mapBackOnePreference(DEBUG_MESSAGE_FILE_SIZE, m_debugMsgFileSize);
- }
-
- public int getPreference(String pref)
- {
- int val = 0;
- Integer i = (Integer)m_prefs.get(pref);
- if (i == null)
- throw new NullPointerException();
- else
- val = i.intValue();
- return val;
- }
-
-
- /*
- * @see flash.tools.debugger.Session#isConnected()
- */
- public boolean isConnected()
- {
- return m_isConnected;
- }
-
- /*
- * @see flash.tools.debugger.Session#isSuspended()
- */
- public boolean isSuspended() throws NotConnectedException
- {
- if (!isConnected())
- throw new NotConnectedException();
-
- return m_isHalted;
- }
-
- /*
- * @see flash.tools.debugger.Session#isIsolateSuspended()
- */
- public boolean isWorkerSuspended(int isolateId) throws NotConnectedException
- {
- if (isolateId == Isolate.DEFAULT_ID)
- return isSuspended();
-
- if (!isConnected())
- throw new NotConnectedException();
-
- if (m_isolateStatus.containsKey(isolateId)) {
- return m_isolateStatus.get(isolateId).m_isHalted;
- }
-
- return false;
- }
-
- /**
- * Start up the session listening for incoming messages on the socket
- */
- public boolean bind() throws VersionException
- {
- boolean bound = false;
-
- if (m_isConnected)
- return false;
-
- // mark that we are connected
- m_isConnected = true;
-
- // attach us to the pipe (we are last to ensure that DManager and msg counter
- // get updated first
- m_protocol.addListener(ListenerIndex.PlayerSession, this);
-
- // start up the receiving thread
- bound = m_protocol.bind();
-
- // transmit our first few adjustment messages
- sendStopWarning();
- sendStopOnFault();
- sendEnumerateOverride();
- sendFailureNotify();
- sendInvokeSetters();
- sendSwfloadNotify();
- sendGetterTimeout();
- sendSetterTimeout();
- boolean responded = sendSquelch(true, Isolate.DEFAULT_ID);
-
- // now note in our preferences whether get is working or not.
- setPreference(SessionManager.PLAYER_SUPPORTS_GET, playerSupportsGet() ? 1 : 0);
- if (supportsConcurrency()) {
- sendConcurrentDebugger();
- }
-
- if (supportsWideLineNumbers()) {
- sendWideLineDebugger();
- }
-
- // Spawn a background thread which fetches the SWF and SWD
- // from the Player and uses them to build function name tables
- // for each source file
- Thread t = new Thread(this, "SWF/SWD reader"); //$NON-NLS-1$
- t.setDaemon(true);
- t.start();
-
- // we're probably using a bad version
- if (!responded)
- throw new VersionException();
-
- return bound;
- }
-
- /**
- * Permanently stops the debugging session and breaks the
- * connection to the Player
- */
- public void unbind()
- {
- unbind(false);
- }
-
- /**
- * @param requestTerminate
- * if true, and if the player to which we are attached is capable
- * of terminating itself (e.g. Adobe AIR), then the player will
- * be told to terminate.
- * @return true if the player is capable of terminating itself and has been
- * told to do so
- */
- private boolean unbind(boolean requestTerminate)
- {
- // If the caller asked us to terminate the player, then we first check
- // whether the player to which we are connected is capable of that.
- // (The web-based players are not; Adobe AIR is.)
- requestTerminate = requestTerminate && playerCanTerminate();
- DMessage dm = DMessageCache.alloc(1);
- dm.setType(DMessage.OutExit);
- dm.putByte((byte)(requestTerminate ? 1 : 0));
- sendMessage(dm);
-
- // unbind from the socket, so that we don't receive any more messages
- m_protocol.unbind();
-
- // kill the socket
- try { m_socket.close(); } catch(IOException io) {}
-
- m_isConnected = false;
- m_isHalted = false;
-
- return requestTerminate; // true if player was told to terminate
- }
-
- /**
- * Execute the specified AppleScript by passing it to /usr/bin/osascript.
- *
- * @param appleScript
- * the AppleScript to execute, as a series of lines
- * @param argv
- * any arguments; these can be accessed from within your
- * AppleScript via "item 1 or argv", "item 2 of argv", etc.
- * @return any text which was sent to stdout by /usr/bin/osascript, with the
- * trailing \n already removed
- */
- private String executeAppleScript(String[] appleScript, String[] argv)
- {
- StringBuilder retval = new StringBuilder();
- try
- {
- List<String> execArgs = new LinkedList<String>();
- // "osascript" is the command-line way of executing AppleScript.
- execArgs.add("/usr/bin/osascript"); //$NON-NLS-1$
- execArgs.add("-"); //$NON-NLS-1$
- if (argv != null)
- {
- for (int i=0; i<argv.length; ++i)
- execArgs.add(argv[i]);
- }
- Process osascript = Runtime.getRuntime().exec(execArgs.toArray(new String[execArgs.size()]));
- // feed our AppleScript code to osascript's stdin
- OutputStream outputStream = osascript.getOutputStream();
- PrintWriter writer = new PrintWriter(outputStream, true);
- writer.println("on run argv"); //$NON-NLS-1$ // this gives the name "argv" to the command-line args
- for (int i=0; i<appleScript.length; ++i)
- writer.println(appleScript[i]);
- writer.println("end run"); //$NON-NLS-1$
- writer.close();
- InputStreamReader reader = new InputStreamReader(osascript.getInputStream());
- int ch;
- while ( (ch=reader.read()) != -1 )
- retval.append((char)ch);
- }
- catch (IOException e)
- {
- // ignore
- }
- return retval.toString().replaceAll("\n$", ""); //$NON-NLS-1$ //$NON-NLS-2$
- }
-
- /**
- * Execute the specified AppleScript by passing it to /usr/bin/osascript.
- *
- * @param appleScriptFilename
- * The name of the file containing AppleScript to execute. This
- * must be relative to PlayerSession.java.
- * @param argv
- * any arguments; these can be accessed from within your
- * AppleScript via "item 1 or argv", "item 2 of argv", etc.
- * @return any text which was sent to stdout by /usr/bin/osascript, with the
- * trailing \n already removed
- * @throws IOException
- */
- private String executeAppleScript(String appleScriptFilename, String[] argv) throws IOException
- {
- InputStream stm = null;
- try {
- stm = PlayerSession.class.getResourceAsStream(appleScriptFilename);
- BufferedReader reader = new BufferedReader(new InputStreamReader(stm));
- String line;
- List<String> appleScriptLines = new ArrayList<String>();
- while ( (line=reader.readLine()) != null )
- appleScriptLines.add(line);
- String[] lines = appleScriptLines.toArray(new String[appleScriptLines.size()]);
- return executeAppleScript(lines, argv);
- } finally {
- if (stm != null) {
- stm.close();
- }
- }
- }
-
- /**
- * Checks whether the specified Macintosh web browser is currently
- * running. You should only call this function if you have already
- * checked that you are running on a Mac.
- *
- * @param browserName a name, e.g. "Safari", "Firefox", "Camino"
- * @return true if currently running
- */
- private Set<String> runningApplications()
- {
- String running = executeAppleScript(
- new String[]
- {
- "tell application \"System Events\"", //$NON-NLS-1$
- " name of processes", //$NON-NLS-1$
- "end tell" //$NON-NLS-1$
- },
- null
- );
- String[] apps = running.split(", "); //$NON-NLS-1$
- Set<String> retval = new HashSet<String>();
- for (int i=0; i<apps.length; ++i)
- retval.add(apps[i]);
- return retval;
- }
-
- /**
- * Destroys all objects related to the connection
- * including the process that was tied to this
- * session via SessionManager.launch(), if it
- * exists.
- */
- public void terminate()
- {
- boolean playerWillTerminateItself = false;
-
- // unbind first
- try
- {
- // Tell player to end session. Note that this is just a hint, and will often
- // do nothing. For example, the Flash player running in a browser will
- // currently never terminate when you tell it to, but the AIR player will
- // terminate.
- playerWillTerminateItself = unbind(true);
- } catch(Exception e)
- {
- }
-
- if (!playerWillTerminateItself)
- {
- if (System.getProperty("os.name").toLowerCase().startsWith("mac os x")) //$NON-NLS-1$ //$NON-NLS-2$
- {
- if (m_airLaunchInfo != null)
- {
- // nothing we need to do -- Process.destroy() will kill the AIR app
- }
- else if (m_launchUrl != null && m_launchUrl.length() > 0)
- {
- boolean closedAnyWindows = false;
- Set<String> runningApps = runningApplications();
-
- if (!closedAnyWindows && runningApps.contains("Safari")) //$NON-NLS-1$
- {
- try {
- String url = m_launchUrl.replaceAll(" ", "%20"); //$NON-NLS-1$ //$NON-NLS-2$
- String safariClosedAnyWindows = executeAppleScript("appleScriptCloseSafariWindow.txt", new String[] { url }); //$NON-NLS-1$
- if ("true".equals(safariClosedAnyWindows)) { //$NON-NLS-1$
- closedAnyWindows = true;
- }
- else if ( "appquit".equals(safariClosedAnyWindows) ) { //$NON-NLS-1$
- closedAnyWindows = true;
- //we closed Safari, verify safari was closed
- runningApps = waitForMacAppQuit("Safari"); //$NON-NLS-1$
- }
- } catch (IOException e) {
- // ignore
- }
- }
-
- if (!closedAnyWindows && runningApps.contains("Camino")) //$NON-NLS-1$
- {
- // For local file: URLs, Camino uses "file://localhost/..." instead of "file:///..."
- String url = m_launchUrl.replaceFirst("^file:///", "file://localhost/"); //$NON-NLS-1$ //$NON-NLS-2$
- try {
- String caminoClosedAnyWindows = executeAppleScript("appleScriptCloseCaminoWindow.txt", new String[] { url }); //$NON-NLS-1$
- if ("true".equals(caminoClosedAnyWindows)) { //$NON-NLS-1$
- closedAnyWindows = true;
- }
- else if ( "appquit".equals(caminoClosedAnyWindows) ) { //$NON-NLS-1$
- closedAnyWindows = true;
- //we closed camino, verify camino was closed
- runningApps = waitForMacAppQuit("Camino"); //$NON-NLS-1$
- }
-
- } catch (IOException e) {
- // ignore
- }
- }
-
- // The standalone player on the Mac has gone through several name changes,
- // so we have to look for all of these.
- String[] macStandalonePlayerNames =
- {
- "Flash Player Debugger", // New name as of Player 10.1 //$NON-NLS-1$
- "Flash Player", // New name as of 12/4/06 //$NON-NLS-1$
- "SAFlashPlayer", // An older name //$NON-NLS-1$
- "standalone" // Another older name //$NON-NLS-1$
- };
-
- for (int i=0; !closedAnyWindows && i<macStandalonePlayerNames.length; ++i)
- {
- if (runningApps.contains(macStandalonePlayerNames[i]))
- {
- executeAppleScript(new String[] { "tell application \"" + macStandalonePlayerNames[i] + "\" to quit" }, null); //$NON-NLS-1$ //$NON-NLS-2$
- waitForMacAppQuit(macStandalonePlayerNames[i]);
- closedAnyWindows = true;
- }
- }
- }
- }
-
- // if we have a process pop it
- if (m_process != null)
- {
- try
- {
- //if a launcher is set for handling the launcher operations then use it.
- if(null != launcher)
- {
- m_debuggerCallbacks.terminateDebugTarget(m_process,launcher);
- }
- else
- {
- m_debuggerCallbacks.terminateDebugTarget(m_process);
- }
- }
- catch (IOException e)
- {
- // ignore
- }
- }
- }
- else if (m_process != null) {
- try {
- m_process.waitFor();
- }
- catch (Exception e) {
- }
- }
-
- // now clear it all
- m_isConnected = false;
- m_isHalted = false;
- }
-
- /**
- * Utility function to wait for a mac application to quit.
- * This waits for a maximum of MAX_TERMINATE_WAIT_MILLIS.
- *
- * Waiting is important because applescript "quit" is not
- * synchronous and launching a URL while the browser is
- * quitting is not good. (See FB-21879)
- * @return Set<String> of running applications.
- */
- private Set<String> waitForMacAppQuit(String browser) {
- Set<String> runningApps;
- boolean appClosed = true;
- final long startMillis = System.currentTimeMillis();
- final long waitMillis = 100;
- do {
- runningApps = runningApplications();
- if ( runningApps.contains(browser) ) {
- appClosed = false;
-
- try {
- Thread.sleep(waitMillis);
- } catch (InterruptedException e) {
- return runningApps;
- }
-
- long currentMillis = System.currentTimeMillis();
-
- if ( currentMillis - startMillis >= MAX_TERMINATE_WAIT_MILLIS )
- break;
- }
- else {
- appClosed = true;
- }
- }
- while ( !appClosed );
- return runningApps;
- }
-
- /*
- * @see flash.tools.debugger.Session#resume()
- */
- public void resume() throws NotSuspendedException, NotConnectedException, NoResponseException
- {
- resumeWorker(Isolate.DEFAULT_ID);
- }
-
- /*
- * @see flash.tools.debugger.Session#suspend()
- */
- public void suspend() throws SuspendedException, NotConnectedException, NoResponseException
- {
- suspendWorker(Isolate.DEFAULT_ID);
- }
-
- /**
- * Obtain all the suspend information
- */
- public DSuspendInfo getSuspendInfo()
- {
- return getSuspendInfoIsolate(Isolate.DEFAULT_ID);
- }
-
- /**
- * Return the reason that the player has suspended itself.
- */
- public int suspendReason()
- {
- DSuspendInfo info = getSuspendInfo();
- return info.getReason();
- }
-
- /**
- * Return the offset in which the player has suspended itself. The BreakReason
- * message contains both reason and offset.
- */
- public int getSuspendOffset()
- {
- DSuspendInfo info = getSuspendInfo();
- return info.getOffset();
- }
-
- /**
- * Return the offset in which the player has suspended itself. The BreakReason
- * message contains both reason and offset.
- */
- public int getSuspendActionIndex()
- {
- DSuspendInfo info = getSuspendInfo();
- return info.getActionIndex();
- }
-
- /**
- * Obtain information about the various SWF(s) that have been
- * loaded into the Player, for this session.
- *
- * Note: As SWFs are loaded by the Player a SwfLoadedEvent is
- * fired. At this point, a call to getSwfInfo() will provide
- * updated information.
- *
- * @return array of records describing the SWFs
- */
- public SwfInfo[] getSwfs() throws NoResponseException
- {
- return getSwfsWorker(Isolate.DEFAULT_ID);
- }
-
- /**
- * Request information on a particular swf, used by DSwfInfo
- * to fill itself correctly
- */
- public void requestSwfInfo(int at, int isolateId) throws NoResponseException
- {
- // nope don't have it...might as well go out and ask for all of them.
- DMessage dm = DMessageCache.alloc(4);
- dm.setType( DMessage.OutSwfInfo );
- dm.setTargetIsolate(isolateId);
- dm.putWord(at);
- dm.putWord(0); // rserved
-
- int to = getPreference(SessionManager.PREF_CONTEXT_RESPONSE_TIMEOUT);
-
- if (!simpleRequestResponseMessage(dm, DMessage.InSwfInfo, to))
- throw new NoResponseException(to);
- }
-
- /**
- * Request a set of actions from the player
- */
- public byte[] getActions(int which, int at, int len) throws NoResponseException
- {
- byte[] actions = null;
-
- // send a actions message
- DMessage dm = DMessageCache.alloc(12);
- dm.setType( DMessage.OutGetActions );
- dm.putWord(which);
- dm.putWord(0); // rsrvd
- dm.putDWord(at);
- dm.putDWord(len);
-
- // request action bytes
- int to = getPreference(SessionManager.PREF_CONTEXT_RESPONSE_TIMEOUT);
- if (simpleRequestResponseMessage(dm, DMessage.InGetActions, to))
- actions = m_manager.getActions();
- else
- throw new NoResponseException(to);
-
- return actions;
- }
-
- /*
- * @see flash.tools.debugger.Session#stepInto()
- */
- public void stepInto() throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- stepIntoWorker(Isolate.DEFAULT_ID);
- }
-
- /*
- * @see flash.tools.debugger.Session#stepOut()
- */
- public void stepOut() throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- stepOutWorker(Isolate.DEFAULT_ID);
- }
-
- /*
- * @see flash.tools.debugger.Session#stepOver()
- */
- public void stepOver() throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- stepOverWorker(Isolate.DEFAULT_ID);
- }
-
- /*
- * @see flash.tools.debugger.Session#stepContinue()
- */
- public void stepContinue() throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- if (!isSuspended())
- throw new NotSuspendedException();
-
- // send a step-continue message and then wait for the Flash player to tell us that is has
- // resumed execution
- if (!simpleRequestResponseMessage(DMessage.OutStepContinue, DMessage.InContinue))
- throw new NoResponseException(getPreference(SessionManager.PREF_RESPONSE_TIMEOUT));
- }
-
- /**
- * Sends a request to the player to obtain function names.
- * The resultant message end up populating the function name array
- * for the given DModule.
- *
- * @param moduleId
- * @param lineNbr
- * @return
- */
- public void requestFunctionNames(int moduleId, int lineNbr, int isolateId) throws VersionException, NoResponseException
- {
- // only player 9 supports this message
- if (m_manager.getVersion() >= 9)
- {
- DMessage dm = DMessageCache.alloc(8);
- dm.setType(DMessage.OutGetFncNames);
- dm.setTargetIsolate(isolateId);
- dm.putDWord(moduleId);
- dm.putDWord(lineNbr);
-
- if (!simpleRequestResponseMessage(dm, DMessage.InGetFncNames))
- throw new NoResponseException(0);
- }
- else
- {
- throw new VersionException();
- }
- }
-
- /**
- * From a given file identifier return a source file object
- */
- public SourceFile getFile(int fileId, int isolateId)
- {
- return m_manager.getSource(fileId, isolateId);
- }
-
- /**
- * Get a list of breakpoints
- */
- public Location[] getBreakpointList()
- {
- return m_manager.getBreakpoints(Isolate.DEFAULT_ID);
- }
-
- /*
- * @see flash.tools.debugger.Session#setBreakpoint(int, int)
- */
- public Location setBreakpoint(int fileId, int lineNum) throws NoResponseException, NotConnectedException
- {
- return setBreakpointWorker(fileId, lineNum, Isolate.DEFAULT_ID);
- }
-
- /*
- * @see flash.tools.debugger.Session#clearBreakpoint(flash.tools.debugger.Location)
- */
- public Location clearBreakpoint(Location local)
- {
- /* first find it */
- SourceFile source = local.getFile();
- int fileId = source.getId();
- int lineNum = local.getLine();
- int bp = DLocation.encodeId(fileId, lineNum);
- int isolateId = local.getIsolateId();
- Location l = null;
- l = m_manager.getBreakpoint(bp, isolateId);
-
- if (l != null)
- {
- /* send the message */
- int wideLineSize = 0;
- if (supportsWideLineNumbers())
- wideLineSize = 4;
- DMessage dm = DMessageCache.alloc(8 + wideLineSize);
- dm.setType(DMessage.OutRemoveBreakpoints);
- dm.setTargetIsolate(isolateId);
- dm.putDWord(1);
- if (!supportsWideLineNumbers())
- dm.putDWord(bp);
- else {
- dm.putDWord(fileId);
- dm.putDWord(lineNum);
- }
- sendMessage(dm);
-
- /* no callback from the player so we remove it ourselves */
- m_manager.removeBreakpoint(bp, isolateId);
- }
- return l;
- }
-
- /*
- * @see flash.tools.debugger.Session#getWatchList()
- */
- public Watch[] getWatchList() throws NoResponseException, NotConnectedException
- {
- return getWatchListWorker(Isolate.DEFAULT_ID);
- }
-
- /*
- * @see flash.tools.debugger.Session#getWatchList()
- */
- public Watch[] getWatchListWorker(int isolateId) throws NoResponseException, NotConnectedException
- {
- return m_manager.getWatchpoints(isolateId);
- }
-
- private Watch setWatch(long varId, String memberName, int kind, int isolateId) throws NoResponseException, NotConnectedException, NotSupportedException
- {
- // we really have two cases here, one where we add a completely new
- // watchpoint and the other where we modify an existing one.
- // In either case the DManager logic is such that the last watchpoint
- // in the list will contain our id if successful.
- Watch w = null;
- int tag = m_watchTransactionTag++;
-
- if (addWatch(varId, memberName, kind, tag, isolateId))
- {
- // good that we got a response now let's check that
- // it actually worked.
- int count = m_manager.getWatchpointCount(isolateId);
- if (count > 0)
- {
- DWatch lastWatch = m_manager.getWatchpoint(count-1, isolateId);
- if (lastWatch.getTag() == tag)
- w = lastWatch;
- }
- }
- return w;
- }
-
- /*
- * @see flash.tools.debugger.Session#setWatch(flash.tools.debugger.Variable, java.lang.String, int)
- */
- public Watch setWatch(Value v, String memberName, int kind) throws NoResponseException, NotConnectedException, NotSupportedException
- {
- return setWatch(v.getId(), memberName, kind, v.getIsolateId());
- }
-
- public Watch setWatch(Watch watch) throws NoResponseException, NotConnectedException, NotSupportedException
- {
- return setWatch(watch.getValueId(), watch.getMemberName(), watch.getKind(), watch.getIsolateId());
- }
-
- /*
- * @see flash.tools.debugger.Session#clearWatch(flash.tools.debugger.Watch)
- */
- public Watch clearWatch(Watch watch) throws NoResponseException, NotConnectedException
- {
- Watch[] list = getWatchListWorker(watch.getIsolateId());
- Watch w = null;
- if ( removeWatch(watch.getValueId(), watch.getMemberName(), watch.getIsolateId()) )
- {
- // now let's first check the size of the list, it
- // should now be one less
- if (m_manager.getWatchpointCount(watch.getIsolateId()) < list.length)
- {
- // ok we made a change. So let's compare list and see which
- // one went away
- Watch[] newList = getWatchListWorker(watch.getIsolateId());
- for(int i=0; i<newList.length; i++)
- {
- // where they differ is the missing one
- if (list[i] != newList[i])
- {
- w = list[i];
- break;
- }
- }
-
- // might be the last one...
- if (w == null)
- w = list[list.length-1];
- }
- }
- return w;
- }
-
- /*
- * @see flash.tools.debugger.Session#getVariableList()
- */
- public Variable[] getVariableList() throws NotSuspendedException, NoResponseException, NotConnectedException, VersionException
- {
- return getVariableListWorker(Isolate.DEFAULT_ID);
- }
-
- public Variable[] getVariableListWorker(int isolateId) throws NotSuspendedException, NoResponseException, NotConnectedException, VersionException
- {
- // make sure the player has stopped and send our message awaiting a response
- if (!isWorkerSuspended(isolateId))
- throw new NotSuspendedException();
-
- requestFrame(0, isolateId); // our 0th frame gets our local context
-
- // now let's request all of the special variables too
- getValueWorker(Value.GLOBAL_ID, isolateId);
- getValueWorker(Value.THIS_ID, isolateId);
- getValueWorker(Value.ROOT_ID, isolateId);
-
- // request as many levels as we can get
- int i = 0;
- Value v = null;
- do
- {
- v = getValueWorker(Value.LEVEL_ID-i, isolateId);
- }
- while( i++ < 128 && v != null);
-
- // now that we've primed the DManager we can request the base variable whose
- // children are the variables that are available
- v = m_manager.getValue(Value.BASE_ID, isolateId);
- if (v == null)
- throw new VersionException();
- return v.getMembers(this);
- }
-
- /*
- * @see flash.tools.debugger.Session#getFrames()
- */
- public Frame[] getFrames() throws NotConnectedException
- {
- return m_manager.getFrames(Isolate.DEFAULT_ID);
- }
-
- /**
- * Asks the player to return information regarding our current context which includes
- * this pointer, arguments for current frame, locals, etc.
- */
- public void requestFrame(int depth, int isolateId) throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- if (playerSupportsGet())
- {
- if (!isWorkerSuspended(isolateId))
- throw new NotSuspendedException();
-
- int timeout = getPreference(SessionManager.PREF_CONTEXT_RESPONSE_TIMEOUT);
-
- DMessage dm = DMessageCache.alloc(4);
- dm.setType(DMessage.OutGetFrame);
- dm.setTargetIsolate(isolateId);
- dm.putDWord(depth); // depth of zero
- if (!simpleRequestResponseMessage(dm, DMessage.InFrame, timeout)) {
- throw new NoResponseException(timeout);
- }
-
- pullUpActivationObjectVariables(depth, isolateId);
- }
- }
-
- /**
- * The compiler sometimes creates special local variables called
- * "activation objects." When it decides to do this (e.g. if the
- * current function contains any anonymous functions, try/catch
- * blocks, complicated E4X expressions, or "with" clauses), then
- * all locals and arguments are actually stored as children of
- * this activation object, rather than the usual way.
- *
- * We need to hide this implementation detail from the user. So,
- * if we find any activation objects among the locals of the current
- * function, then we will "pull up" its members, and represent them
- * as if they were actually args/locals of the function itself.
- *
- * @param depth the depth of the stackframe we are fixing; 0 is topmost
- */
- private void pullUpActivationObjectVariables(int depth, int isolateId) throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- DValue frame = m_manager.getValue(Value.BASE_ID-depth, isolateId);
- if (frame == null)
- return;
- DStackContext context = m_manager.getFrame(depth, isolateId);
- DVariable[] frameVars = (DVariable[]) frame.getMembers(this);
- Map<String, DVariable> varmap = new LinkedHashMap<String, DVariable>(frameVars.length); // preserves order
- List<DVariable> activationObjects = new ArrayList<DVariable>();
- Pattern activationObjectNamePattern = Pattern.compile("^.*\\$\\d+$"); //$NON-NLS-1$
-
- // loop through all frame variables, and separate them into two
- // groups: activation objects, and all others (locals and arguments)
- for (int i=0; i<frameVars.length; ++i)
- {
- DVariable member = frameVars[i];
- Matcher matcher = activationObjectNamePattern.matcher(member.getName());
- if (matcher.matches())
- activationObjects.add(member);
- else
- varmap.put(member.getName(), member);
- }
-
- // If there are no activation objects, then we don't need to do anything
- if (activationObjects.size() == 0)
- return;
-
- // overwrite existing args and locals with ones pulled from the activation objects
- for (int i=0; i<activationObjects.size(); ++i)
- {
- DVariable activationObject = activationObjects.get(i);
- DVariable[] activationMembers = (DVariable[]) activationObject.getValue().getMembers(this);
- for (int j=0; j<activationMembers.length; ++j)
- {
- DVariable member = activationMembers[j];
- int attributes = member.getAttributes();
-
- // For some odd reason, the activation object often contains a whole bunch of
- // other variables that we shouldn't be displaying. I don't know what they
- // are, but I do know that they are all marked "static".
- if ((attributes & VariableAttribute.IS_STATIC) != 0)
- continue;
-
- // No matter what the activation object member's scope is, we want all locals
- // and arguments to be considered "public"
- attributes &= ~(VariableAttribute.PRIVATE_SCOPE | VariableAttribute.PROTECTED_SCOPE | VariableAttribute.NAMESPACE_SCOPE);
- attributes |= VariableAttribute.PUBLIC_SCOPE;
- member.setAttributes(attributes);
-
- String name = member.getName();
- DVariable oldvar = varmap.get(name);
- int vartype;
- if (oldvar != null)
- vartype = oldvar.getAttributes() & (VariableAttribute.IS_ARGUMENT | VariableAttribute.IS_LOCAL);
- else
- vartype = VariableAttribute.IS_LOCAL;
- member.setAttributes(member.getAttributes() | vartype);
- varmap.put(name, member);
- }
-
- context.convertLocalToActivationObject(activationObject);
- }
-
- for (DVariable var: varmap.values())
- {
- frame.addMember(var);
- if (var.isAttributeSet(VariableAttribute.IS_LOCAL))
- {
- context.addLocal(var);
- }
- else if (var.isAttributeSet(VariableAttribute.IS_ARGUMENT))
- {
- if (var.getName().equals("this")) //$NON-NLS-1$
- context.setThis(var);
- else
- context.addArgument(var);
- }
- }
- }
-
- /*
- * @see flash.tools.debugger.Session#getValue(int)
- */
- public Value getValue(long valueId) throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- return getValueWorker(valueId, Isolate.DEFAULT_ID);
- }
-
- public Value getValueWorker(long valueId, int isolateId) throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- DValue val = null;
-
- if (!isWorkerSuspended(isolateId))
- throw new NotSuspendedException();
-
- // get it from cache if we can
- val = m_manager.getValue(valueId, isolateId);
-
- if (val == null)
- {
- // if a special variable, then we need to trigger a local frame call, otherwise just use id to get it
- if (valueId < Value.UNKNOWN_ID)
- {
- requestFrame(0, isolateId); // force our current frame to get populated, BASE_ID will be available
- }
- else if (valueId > Value.UNKNOWN_ID)
- {
- requestVariable(valueId, null, isolateId);
- }
-
- // after all this we should have our variable cache'd so try again if it wasn't there the first time
- val = m_manager.getValue(valueId, isolateId);
- }
-
- return val;
- }
-
- /**
- * Returns the current value object for the given id; never requests it from the player.
- */
- public Value getRawValue(long valueId, int isolateId)
- {
- return m_manager.getValue(valueId, isolateId);
- }
-
- /**
- * Returns the previous value object for the given id -- that is, the value that that
- * object had the last time the player was suspended. Never requests it from the
- * player (because it can't, of course). Returns <code>null</code> if we don't have
- * a value for that id.
- */
- public Value getPreviousValue(long valueId, int isolateId)
- {
- return m_manager.getPreviousValue(valueId, isolateId);
- }
-
- /**
- * Launches a request to obtain all the members of the specified variable, and
- * store them in the variable which would be returned by
- * {@link DManager#getVariable(long)}.
- *
- * @param valueId id of variable whose members we want; underlying Variable must
- * already be known by the PlayerSessionManager.
- *
- * @throws NoResponseException
- * @throws NotConnectedException
- * @throws NotSuspendedException
- */
- void obtainMembers(long valueId, int isolateId) throws NoResponseException, NotConnectedException, NotSuspendedException
- {
- if (!isWorkerSuspended(isolateId))
- throw new NotSuspendedException();
-
- // Get it from cache. Normally, this should never fail; however, in
- // the case of Flex Builder, which is multithreaded, it is possible
- // that a thread has called this even after a different thread has
- // single-stepped, so that the original variable is no longer valid.
- // So, we'll check for a null return value.
- DValue v = m_manager.getValue(valueId, isolateId);
-
- if (v != null && !v.membersObtained())
- {
- requestVariable(valueId, null, false, true, isolateId);
- }
- }
-
- public Value getGlobal(String name) throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- return getGlobalWorker(name, Isolate.DEFAULT_ID);
- }
-
- public Value getGlobalWorker(String name, int isolateId) throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- Value v = getValue(0, name, isolateId);
-
- if (v==null || v.getType() == VariableType.UNDEFINED)
- return null;
- else
- return v;
- }
-
- /**
- * Get the value of the variable named 'name' using varId
- * as the context id for the Variable.
- *
- * This call is used to fire getters, where the id must
- * be that of the original object and not the object id
- * of where the getter actually lives. For example
- * a getter a() may live under o.__proto__.__proto__
- * but you must use the id of o and the name of 'a'
- * in order for the getter to fire correctly. [Note: This
- * paragraph was written for AS2; __proto__ doesn't exist
- * in AS3. TODO: revise this paragraph]
- */
- public Value getValue(long varId, String name, int isolateId) throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- Value v = null;
- if (isWorkerSuspended(isolateId))
- {
- int fireGetter = getPreference(SessionManager.PREF_INVOKE_GETTERS);
-
- // disable children attaching to parent variables and clear our
- // most recently seen variable
- m_manager.clearLastVariable(isolateId);
- m_manager.enableChildAttach(false, isolateId);
-
- try
- {
- requestVariable(varId, name, (fireGetter != 0), false, isolateId);
-
- DVariable lastVariable = m_manager.lastVariable(isolateId);
- if (lastVariable != null)
- v = lastVariable.getValue();
- else
- v = DValue.forPrimitive(Value.UNDEFINED, isolateId);
- }
- catch (NoResponseException e)
- {
- if (fireGetter != 0)
- {
- // We fired a getter -- most likely, what happened is that that getter
- // (which is actual code in the user's movie) just took too long to
- // calculate its value. So rather than throwing an exception, we store
- // some error text for the value of the variable itself.
- //
- // TODO [mmorearty 4/20/06] Even though I wrote the below code, I now
- // am wondering if it is incorrect that I am calling addVariableMember(),
- // because in every other case, this function does not add members to
- // existing objects. Need to revisit this.
- v = new DValue(VariableType.STRING, "String", "String", ValueAttribute.IS_EXCEPTION, //$NON-NLS-1$ //$NON-NLS-2$
- e.getLocalizedMessage(), isolateId);
- if (varId != 0) {
- DVariable var = new DVariable(name, (DValue)v, isolateId);
- m_manager.enableChildAttach(true, isolateId);
- m_manager.addVariableMember(varId, var, isolateId);
- }
- }
- else
- {
- throw e; // re-throw
- }
- }
- finally
- {
- // reset our attach flag, so that children attach to parent variables.
- m_manager.enableChildAttach(true, isolateId);
- }
- }
- else
- throw new NotSuspendedException();
-
- return v;
- }
-
- private void requestVariable(long id, String name, int isolateId) throws NoResponseException, NotConnectedException, NotSuspendedException
- {
- requestVariable(id, name, false, false, isolateId);
- }
-
- /**
- * @param thisValue the value of the "this" pointer; meaningless if isConstructor is true
- * @param isConstructor whether we're calling a constructor as opposed to a regular function
- * @param funcname the name of the function to call (or class whose constructor we're calling)
- * @param args the args to the function
- * @return the return value of the function
- */
- private Value callFunction(Value thisValue, boolean isConstructor, String funcname, Value[] args, int isolateId) throws PlayerDebugException
- {
- if (!isWorkerSuspended(isolateId))
- throw new NotSuspendedException();
-
- if (!playerCanCallFunctions(isolateId))
- throw new NotSupportedException(PlayerSessionManager.getLocalizationManager().getLocalizedTextString("functionCallsNotSupported")); //$NON-NLS-1$
-
- // name = getRawMemberName(id, name);
-
- m_manager.clearLastFunctionCall(isolateId);
-
- DMessage dm = buildCallFunctionMessage(isConstructor, thisValue, funcname, args);
-
- dm.setTargetIsolate(isolateId);
-
- // make sure any exception during the setter gets held onto
- m_manager.beginPlayerCodeExecution(isolateId);
-
- // TODO wrong timeout
- int timeout = getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
- timeout += 500; // give the player enough time to raise its timeout exception
-
- boolean result = simpleRequestResponseMessage(dm, DMessage.InCallFunction, timeout);
-
- // tell manager we're done; ignore returned FaultEvent
- m_manager.endPlayerCodeExecution(isolateId);
-
- if (!result)
- throw new NoResponseException(timeout);
-
- DVariable lastFunctionCall = m_manager.lastFunctionCall(isolateId);
- if (lastFunctionCall != null)
- return lastFunctionCall.getValue();
- else
- return DValue.forPrimitive(Value.UNDEFINED, isolateId);
- }
-
- /*
- * @see flash.tools.debugger.Session#callFunction(flash.tools.debugger.Value, java.lang.String, flash.tools.debugger.Value[])
- */
- public Value callFunction(Value thisValue, String funcname, Value[] args) throws PlayerDebugException
- {
- return callFunctionWorker(thisValue, funcname, args, Isolate.DEFAULT_ID);
- }
-
- public Value callFunctionWorker(Value thisValue, String funcname, Value[] args, int isolateId) throws PlayerDebugException
- {
- Value retval = callPseudoFunction(thisValue, funcname, args, isolateId);
- if (retval != null) {
- return retval;
- }
-
- return callFunction(thisValue, false, funcname, args, isolateId);
- }
-
- /**
- * Checks to see if the function being called is a debugger pseudofunction such as
- * $obj(), and if so, handles that directly rather than calling the player. Returns
- * null if the function being called is not a pseudofunction.
- */
- private Value callPseudoFunction(Value thisValue, String funcname, Value[] args, int isolateId) throws PlayerDebugException{
- if (thisValue.getType() == VariableType.UNDEFINED || thisValue.getType() == VariableType.NULL) {
- if ("$obj".equals(funcname)) { //$NON-NLS-1$
- return callObjPseudoFunction(args, isolateId);
- }
- }
-
- return null;
- }
-
- /**
- * Handles a call to the debugger pseudofunction $obj() -- e.g. $obj(1234) returns
- * a pointer to the object with id 1234.
- */
- private Value callObjPseudoFunction(Value[] args, int isolateId) throws PlayerDebugException {
- if (args.length != 1) {
- return DValue.forPrimitive(DValue.UNDEFINED, isolateId);
- }
- double arg = ECMA.toNumber(this, args[0]);
- long id = (long) arg;
- if (id != arg) {
- return DValue.forPrimitive(DValue.UNDEFINED, isolateId);
- }
- DValue value = m_manager.getValue(id, isolateId);
- if (value == null) {
- return DValue.forPrimitive(DValue.UNDEFINED, isolateId);
- }
- return value;
- }
-
- public Value callConstructor(String funcname, Value[] args) throws PlayerDebugException
- {
- return callConstructorWorker(funcname, args, Isolate.DEFAULT_ID);
- }
-
- public Value callConstructorWorker(String funcname, Value[] args, int isolateId) throws PlayerDebugException
- {
- return callFunction(DValue.forPrimitive(null, isolateId), true, funcname, args, isolateId);
- }
-
- private DMessage buildCallFunctionMessage(boolean isConstructor, Value thisValue, String funcname, Value[] args)
- {
- funcname = (funcname == null) ? "" : funcname; //$NON-NLS-1$
-
- int messageSize = 8; // DWORD representing flags + DWORD representing frame
- String thisType = DVariable.typeNameFor(thisValue.getType());
- String thisValueString = thisValue.getValueAsString();
- messageSize += DMessage.getStringLength(thisType)+1;
- messageSize += DMessage.getStringLength(thisValueString)+1;
- messageSize += DMessage.getStringLength(funcname)+1;
- messageSize += 4; // DWORD representing the number of args
- String[] argTypes = new String[args.length];
- String[] argValues = new String[args.length];
- for (int i=0; i<args.length; ++i)
- {
- argTypes[i] = DVariable.typeNameFor(args[i].getType());
- argValues[i] = args[i].getValueAsString();
- messageSize += DMessage.getStringLength(argValues[i])+1;
- messageSize += DMessage.getStringLength(argTypes[i])+1;
- }
-
- DMessage dm = DMessageCache.alloc(messageSize);
- dm.setType(DMessage.OutCallFunction);
- try
- {
- dm.putDWord(isConstructor ? 1 : 0);
- dm.putDWord(0); // TODO: the currently active frame number
- dm.putString(thisType);
- dm.putString(thisValueString);
- dm.putString(funcname);
- dm.putDWord(args.length);
- for (int i=0; i<args.length; ++i)
- {
- dm.putString(argTypes[i]);
- dm.putString(argValues[i]);
- }
- }
- catch(UnsupportedEncodingException uee)
- {
- // couldn't write out the string, so just terminate it and complete anyway
- dm.putByte((byte)'\0');
- }
-
- return dm;
- }
-
- private void requestVariable(long id, String name, boolean fireGetter, boolean alsoGetChildren, int isolateId) throws NoResponseException, NotConnectedException, NotSuspendedException
- {
- if (!isWorkerSuspended(isolateId))
- throw new NotSuspendedException();
-
- name = getRawMemberName(id, name, isolateId);
-
- DMessage dm = buildOutGetMessage(id, name, fireGetter, alsoGetChildren);
-
- dm.setTargetIsolate(isolateId);
-
- // make sure any exception during the setter gets held onto
- m_manager.beginPlayerCodeExecution(isolateId);
-
- int timeout = getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
- timeout += 500; // give the player enough time to raise its timeout exception
-
- boolean result = simpleRequestResponseMessage(dm, DMessage.InGetVariable, timeout);
-
- // tell manager we're done; ignore returned FaultEvent
- m_manager.endPlayerCodeExecution(isolateId);
-
- if (!result)
- throw new NoResponseException(timeout);
- }
-
- private DMessage buildOutGetMessage(long id, String name, boolean fireGetter, boolean alsoGetChildren)
- {
- final int FLAGS_SIZE = 4;
- name = (name == null) ? "" : name; //$NON-NLS-1$
-
- DMessage dm = DMessageCache.alloc(DMessage.getSizeofPtr() + DMessage.getStringLength(name)+1 + FLAGS_SIZE);
- dm.setType( (!fireGetter) ? DMessage.OutGetVariable : DMessage.OutGetVariableWhichInvokesGetter );
- dm.putPtr(id);
- try
- {
- dm.putString(name);
- }
- catch(UnsupportedEncodingException uee)
- {
- // couldn't write out the string, so just terminate it and complete anyway
- dm.putByte((byte)'\0');
- }
-
- // as an optimization, newer player builds allow us to tell them not to
- // send all the children of an object along with the object, because
- // frequently we don't care about the children
- int flags = GetVariableFlag.DONT_GET_FUNCTIONS; // we never want functions
- if (fireGetter)
- flags |= GetVariableFlag.INVOKE_GETTER;
- if (alsoGetChildren)
- flags |= GetVariableFlag.ALSO_GET_CHILDREN | GetVariableFlag.GET_CLASS_HIERARCHY;
- dm.putDWord(flags);
-
- return dm;
- }
-
- public FaultEvent setScalarMember(long varId, String memberName, int type, String value, int isolateId) throws NotSuspendedException, NoResponseException, NotConnectedException
- {
- if (!isWorkerSuspended(isolateId))
- throw new NotSuspendedException();
-
- // If the varId is that of a stack frame, then we need to check whether that
- // stack frame has an "activation object". If it does, then all of the
- // arguments and locals are actually kept as members of that activation
- // object, and so we need to change varId to be the ID of that activation
- // object -- that way, the player will modify the member of the activation
- // object rather than modifying the "regular" argument or local. See bug
- // 155031.
- if (varId <= Value.BASE_ID && varId > Value.LEVEL_ID)
- {
- int depth = (int) (Value.BASE_ID - varId);
- DStackContext context = m_manager.getFrame(depth,isolateId);
- DVariable activationObject = context.getActivationObject();
- if (activationObject != null)
- varId = activationObject.getValue().getId();
- }
-
- memberName = getRawMemberName(varId, memberName, isolateId);
-
- // see if it is our any of our special variables
- FaultEvent faultEvent = requestSetVariable( isPseudoVarId(varId) ? 0 : varId, memberName, type, value, isolateId);
-
- // now that we sent it out, we need to clear our variable cache
- // if it is our special context then mark the frame as stale.
- if (isPseudoVarId(varId) && m_manager.getFrameCount(isolateId) > 0)
- {
- m_manager.getFrame(0, isolateId).markStale();
- }
- else
- {
- DValue parent = m_manager.getValue(varId,isolateId);
- if (parent != null)
- parent.removeAllMembers();
- }
-
- return faultEvent;
- }
-
- /**
- * Returns whether a variable ID is "real" or not. For example,
- * Value.THIS_ID is a "pseudo" varId, as are all the other special
- * hard-coded varIds in the Value class.
- */
- private boolean isPseudoVarId(long varId)
- {
- /*
- * Unfortunately, this is actually just taking a guess. The old code
- * used "varId < 0"; however, the Linux player sometimes has real
- * variable IDs which are less than zero.
- */
- return (varId < 0 && varId > -65535);
- }
-
- /**
- * <code>memberName</code> might be just <code>"varname"</code>, or it
- * might be <code>"namespace::varname"</code>, or it might be
- * <code>"namespace@hexaddr::varname"</code>. In the third case, it is
- * fully resolved, and there is nothing we need to do. But in the first
- * and second cases, we may need to fully resolve it so that the Player
- * will recognize it.
- */
- private String getRawMemberName(long parentValueId, String memberName, int isolateId)
- {
- if (memberName != null)
- {
- DValue parent = m_manager.getValue(parentValueId, isolateId);
- if (parent != null)
- {
- int doubleColon = memberName.indexOf("::"); //$NON-NLS-1$
- String shortName = (doubleColon==-1) ? memberName : memberName.substring(doubleColon+2);
- DVariable member = parent.findMember(shortName);
- if (member != null)
- memberName = member.getRawName();
- }
- }
- return memberName;
- }
-
- /**
- * @return null for success, or fault event if a setter in the player threw an exception
- */
- private FaultEvent requestSetVariable(long id, String name, int t, String value, int isolateId) throws NoResponseException
- {
- // convert type to typeName
- String type = DVariable.typeNameFor(t);
- DMessage dm = buildOutSetMessage(id, name, type, value);
- dm.setTargetIsolate(isolateId);
- FaultEvent faultEvent = null;
-// System.out.println("setmsg id="+id+",name="+name+",t="+type+",value="+value);
-
- // make sure any exception during the setter gets held onto
- m_manager.beginPlayerCodeExecution(isolateId);
-
- // turn off squelch so we can hear the response
- sendSquelch(false, isolateId);
-
- int timeout = getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
-
- if (!simpleRequestResponseMessage(dm, (t == VariableType.STRING) ? DMessage.InSetVariable : DMessage.InSetVariable2, timeout))
- throw new NoResponseException(getPreference(SessionManager.PREF_RESPONSE_TIMEOUT));
-
- // turn it back on
- sendSquelch(true, isolateId);
-
- // tell manager we're done, and get exception if any
- faultEvent = m_manager.endPlayerCodeExecution(isolateId);
-
- // hammer the variable cache and context array
- m_manager.freeValueCache(isolateId);
- return faultEvent;
- }
-
- private DMessage buildOutSetMessage(long id, String name, String type, String v)
- {
- DMessage dm = DMessageCache.alloc(DMessage.getSizeofPtr()+
- DMessage.getStringLength(name)+
- DMessage.getStringLength(type)+
- DMessage.getStringLength(v)+
- 3);
- dm.setType(DMessage.OutSetVariable);
- dm.putPtr(id);
- try { dm.putString(name); } catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
- try { dm.putString(type); } catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
- try { dm.putString(v); } catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
- return dm;
- }
-
- /*
- * @see flash.tools.debugger.Session#waitForEvent()
- */
- public void waitForEvent() throws NotConnectedException, InterruptedException
- {
- Object eventNotifier = m_manager.getEventNotifier();
- synchronized (eventNotifier)
- {
- while (getEventCount() == 0 && isConnected())
- {
- eventNotifier.wait();
- }
- }
-
- // We should NOT call isConnected() to test for a broken connection! That
- // is because we may have received one or more events AND lost the connection,
- // almost simultaneously. If there are any messages available for the
- // caller to process, we should not throw an exception.
- if (getEventCount() == 0 && !isConnected())
- throw new NotConnectedException();
- }
-
- /*
- * @see flash.tools.debugger.Session#getEventCount()
- */
- public int getEventCount()
- {
- return m_manager.getEventCount();
- }
-
- /*
- * @see flash.tools.debugger.Session#nextEvent()
- */
- public DebugEvent nextEvent()
- {
- return m_manager.nextEvent();
- }
-
- /**
- * Adds a watchpoint on the given expression
- * @throws NotConnectedException
- * @throws NoResponseException
- * @throws NotSupportedException
- * @throws NotSuspendedException
- */
- public boolean addWatch(long varId, String varName, int type, int tag, int isolateId) throws NoResponseException, NotConnectedException, NotSupportedException
- {
- // TODO check for NoResponse, NotConnected
-
- if (!supportsWatchpoints(isolateId))
- throw new NotSupportedException(PlayerSessionManager.getLocalizationManager().getLocalizedTextString("watchpointsNotSupported")); //$NON-NLS-1$
-
- varName = getRawMemberName(varId, varName, isolateId);
- DMessage dm = DMessageCache.alloc(4+DMessage.getSizeofPtr()+DMessage.getStringLength(varName)+1);
- dm.setType(DMessage.OutAddWatch2);
- dm.setTargetIsolate(isolateId);
- dm.putPtr(varId);
- try { dm.putString(varName); } catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
- dm.putWord(type);
- dm.putWord(tag);
-
- int timeout = getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
- boolean result = simpleRequestResponseMessage(dm, DMessage.InWatch2, timeout);
- return result;
- }
-
- /**
- * Removes a watchpoint on the given expression
- * @throws NotConnectedException
- * @throws NoResponseException
- * @throws NotSuspendedException
- */
- public boolean removeWatch(long varId, String memberName, int isolateId) throws NoResponseException, NotConnectedException
- {
- memberName = getRawMemberName(varId, memberName, isolateId);
- DMessage dm = DMessageCache.alloc(DMessage.getSizeofPtr()+DMessage.getStringLength(memberName)+1);
- dm.setType(DMessage.OutRemoveWatch2);
- dm.putPtr(varId);
- try { dm.putString(memberName); } catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
-
- int timeout = getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT);
- boolean result = simpleRequestResponseMessage(dm, DMessage.InWatch2, timeout);
- return result;
- }
-
- /**
- * Send a message that contains no data
- */
- void sendMessage(int message)
- {
- DMessage dm = DMessageCache.alloc(0);
- dm.setType(message);
- sendMessage(dm);
- }
-
- /**
- * Send a message that contains no data
- */
- void sendMessageIsolate(int message, int isolateId)
- {
- DMessage dm = DMessageCache.alloc(0);
- dm.setTargetIsolate(isolateId);
- dm.setType(message);
- sendMessage(dm);
- }
-
- /**
- * Send a fully formed message and release it when done
- */
- synchronized void sendMessage(DMessage dm)
- {
- try
- {
- if (dm.getType() != DMessage.OutSetActiveIsolate) {
- int isolate = dm.getTargetIsolate();
- if (isolate != getActiveIsolate().getId()) {
- DMessage dm1 = DMessageCache.alloc(4);
- dm1.setTargetIsolate(isolate);
- dm1.setType(DMessage.OutSetActiveIsolate);
- dm1.putDWord(isolate);
-
- /* Use sendMessage here to avoid waiting for a response.
- * The assumption is that once the message is sent, subsequent
- * messages are for that isolate regardless of the player confirming
- * it. With this change, performance has improved considerably; player
- * debugger has not gone out of sync since the ProcessTag messages
- * flood issue was resolved. */
- sendMessage(dm1);
-
- m_manager.setActiveIsolate(m_manager.getIsolate(isolate));
-
- }
- }
- m_protocol.txMessage(dm);
-
- if (m_debugMsgOn || m_debugMsgFileOn)
- trace(dm, false);
- }
- catch(IOException io)
- {
- if (Trace.error)
- {
- Trace.trace("Attempt to send message "+dm.outToString()+" failed"); //$NON-NLS-1$ //$NON-NLS-2$
- io.printStackTrace();
- }
- }
- DMessageCache.free(dm);
- }
-
- /**
- * Tell the player to shut-up
- */
- boolean sendSquelch(boolean on, int isolateId)
- {
- boolean responded;
- DMessage dm = DMessageCache.alloc(4);
- dm.setType(DMessage.OutSetSquelch);
- dm.setTargetIsolate(isolateId);
- dm.putDWord( on ? 1 : 0);
- responded = simpleRequestResponseMessage(dm, DMessage.InSquelch);
- return responded;
- }
-
- void sendStopWarning()
- {
- // Currently, "disable_script_stuck_dialog" only works for AS2, not for AS3.
- String option = "disable_script_stuck_dialog"; //$NON-NLS-1$
- String value = "on"; //$NON-NLS-1$
-
- sendOptionMessage(option, value);
-
- // HACK: Completely disable the script-stuck notifications, so that we can
- // get AS3 debugging working.
- option = "disable_script_stuck"; //$NON-NLS-1$
- value = "on"; //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- }
-
- void sendStopOnFault()
- {
- String option = "break_on_fault"; //$NON-NLS-1$
- String value = "on"; //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- }
-
- void sendEnumerateOverride()
- {
- String option = "enumerate_override"; //$NON-NLS-1$
- String value = "on"; //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- }
-
- void sendFailureNotify()
- {
- String option = "notify_on_failure"; //$NON-NLS-1$
- String value = "on"; //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- }
-
- void sendInvokeSetters()
- {
- String option = "invoke_setters"; //$NON-NLS-1$
- String value = "on"; //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- }
-
- void sendSwfloadNotify()
- {
- String option = "swf_load_messages"; //$NON-NLS-1$
- String value = "on"; //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- }
-
- void sendConsoleErrorsAsTrace(boolean on)
- {
- String option = "console_errors"; //$NON-NLS-1$
- String value = (on) ? "on" : "off"; //$NON-NLS-1$ //$NON-NLS-2$
-
- sendOptionMessage(option, value);
- }
-
- void sendGetterTimeout()
- {
- String option = "getter_timeout"; //$NON-NLS-1$
- String value = "" + getPreference(SessionManager.PREF_GETVAR_RESPONSE_TIMEOUT); //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- }
-
- void sendSetterTimeout()
- {
- String option = "setter_timeout"; //$NON-NLS-1$
- String value = "" + getPreference(SessionManager.PREF_SETVAR_RESPONSE_TIMEOUT); //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- }
-
- void sendConcurrentDebugger()
- {
- String option = "concurrent_debugger"; //$NON-NLS-1$
- String value = "on"; //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- }
-
- void sendWideLineDebugger()
- {
- String option = "wide_line_debugger"; //$NON-NLS-1$
- String value = "on"; //$NON-NLS-1$
-
- sendOptionMessage(option, value);
- m_manager.setWideLines(true);
- }
-
- void sendOptionMessage(String option, String value)
- {
- int msgSize = DMessage.getStringLength(option)+DMessage.getStringLength(value)+2; // add 2 for trailing nulls of each string
-
- DMessage dm = DMessageCache.alloc(msgSize);
- dm.setType(DMessage.OutSetOption);
- try { dm.putString(option); } catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
- try { dm.putString(value); } catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
- simpleRequestResponseMessage(dm, DMessage.InOption);
- }
-
- public boolean supportsWatchpoints()
- {
- return supportsWatchpoints(Isolate.DEFAULT_ID);
- }
-
- public boolean supportsWatchpoints(int isolateId)
- {
- if (m_playerSupportsWatchpoints == null)
- m_playerSupportsWatchpoints = new Boolean(getOption("can_set_watchpoints", false, isolateId)); //$NON-NLS-1$
- return m_playerSupportsWatchpoints.booleanValue();
- }
-
- public boolean playerCanBreakOnAllExceptions()
- {
- return playerCanBreakOnAllExceptions(Isolate.DEFAULT_ID);
- }
-
- public boolean playerCanBreakOnAllExceptions(int isolateId)
- {
- if (m_playerCanBreakOnAllExceptions == null)
- m_playerCanBreakOnAllExceptions = new Boolean(getOption("can_break_on_all_exceptions", false, isolateId)); //$NON-NLS-1$
- return m_playerCanBreakOnAllExceptions.booleanValue();
- }
-
- public boolean supportsConcurrency(int isolateId)
- {
- if (m_playerSupportsConcurrency == null)
- m_playerSupportsConcurrency = new Boolean(getOption("concurrent_player", false, isolateId)); //$NON-NLS-1$
- return m_playerSupportsConcurrency.booleanValue();
- }
-
- public boolean supportsConcurrency()
- {
- return supportsConcurrency(Isolate.DEFAULT_ID);
- }
-
- public boolean supportsWideLineNumbers()
- {
- return supportsWideLineNumbers(Isolate.DEFAULT_ID);
- }
-
- public boolean supportsWideLineNumbers(int isolateId)
- {
- if (m_playerSupportsWideLine == null)
- m_playerSupportsWideLine = new Boolean(getOption("wide_line_player", false, isolateId)); //$NON-NLS-1$
- return m_playerSupportsWideLine.booleanValue();
- }
-
- public boolean playerCanTerminate()
- {
- return getOption("can_terminate", false, Isolate.DEFAULT_ID); //$NON-NLS-1$
- }
-
- public boolean playerCanCallFunctions()
- {
- return playerCanCallFunctions(Isolate.DEFAULT_ID);
- }
-
- public boolean playerCanCallFunctions(int isolateId)
- {
- if (m_playerCanCallFunctions == null)
- m_playerCanCallFunctions = new Boolean(getOption("can_call_functions", false, isolateId)); //$NON-NLS-1$
- return m_playerCanCallFunctions.booleanValue();
- }
-
- /**
- * Returns the value of a Flash Player boolean option that was requested by
- * OutGetOption and returned by InOption.
- *
- * @param optionName
- * the name of the option
- * @return its value, or null
- */
- public boolean getOption(String optionName, boolean defaultValue, int isolateId)
- {
- boolean retval = defaultValue;
- String optionValue = getOption(optionName, null, isolateId);
-
- if (optionValue != null)
- retval = Boolean.valueOf(optionValue).booleanValue();
-
- return retval;
- }
-
- /**
- * Returns the value of a Flash Player string option that was requested by
- * OutGetOption and returned by InOption.
- *
- * @param optionName
- * the name of the option
- * @return its value, or null
- */
- public String getOption(String optionName, String defaultValue, int isolateId)
- {
- String optionValue = defaultValue;
-
- int msgSize = DMessage.getStringLength(optionName)+1; // add 1 for trailing null of string
-
- DMessage dm = DMessageCache.alloc(msgSize);
- dm.setTargetIsolate(isolateId);
- dm.setType(DMessage.OutGetOption);
- try { dm.putString(optionName); } catch(UnsupportedEncodingException uee) { dm.putByte((byte)'\0'); }
- if (simpleRequestResponseMessage(dm, DMessage.InOption))
- optionValue = m_manager.getOption(optionName);
- return optionValue;
- }
-
- long getMessageInCount(DMessageCounter counter, long isolate, int msgType) {
- if (isolate == Isolate.DEFAULT_ID) {
- return counter.getInCount(msgType);
- }
- else {
- return counter.getIsolateInCount(isolate, msgType);
- }
- }
-
- Object getMessageInLock(DMessageCounter counter, long isolate) {
- if (isolate == Isolate.DEFAULT_ID) {
- return counter.getInLock();
- }
- else {
- return counter.getIsolateInLock(isolate);
- }
- }
-
- /**
- * Send our message and assume that the next response that is received is
- * ours. Primitive but there is no use in setting up a full request / response
- * pattern since the player doesn't follow it.
- *
- * @return false is no response.
- */
- boolean simpleRequestResponseMessage(DMessage msg, int msgType, int timeout)
- {
- boolean response = false;
-
- //FIXME: Check if timeout needs to adjust to the isolate switching
- // delay
- // use default or user supplied timeout
- timeout = (timeout > 0) ? timeout : getPreference(SessionManager.PREF_RESPONSE_TIMEOUT);
-
- // note the number of messages of this type before our send
- DMessageCounter msgCounter = getMessageCounter();
- int isolate = msg.getTargetIsolate();
- long num = getMessageInCount(msgCounter, isolate, msgType);
- long expect = num+1;
-
- // send the message
- sendMessage(msg);
-
- long startTime = System.currentTimeMillis();
-// System.out.println("sending- "+DMessage.outTypeName(msg.getType())+",timeout="+timeout+",start="+start);
-
- // now wait till we see a message come in
- m_incoming = false;
- synchronized (getMessageInLock(msgCounter, isolate))
- {
- while( (expect > getMessageInCount(msgCounter, isolate, msgType)) &&
- System.currentTimeMillis() < startTime + timeout &&
- isConnected())
- {
- // block until the message counter tells us that some message has been received
- try
- {
- getMessageInLock(msgCounter, isolate).wait(timeout);
- }
- catch (InterruptedException e)
- {
- // this should never happen
- e.printStackTrace();
- //FIXME: Will resetting the interrupted status here
- //cause any problems?
-// Thread.currentThread().interrupt();
- }
-
- // if we see incoming messages, then we should reset our timeout
- synchronized (this)
- {
- if (m_incoming)
- {
- startTime = System.currentTimeMillis();
- m_incoming = false;
- }
- }
- }
- }
-
- if (getMessageInCount(msgCounter, isolate, msgType) >= expect)
- response = true;
- else if (timeout <= 0 && Trace.error)
- Trace.trace("Timed-out waiting for "+DMessage.inTypeName(msgType)+" response to message "+msg.outToString()); //$NON-NLS-1$ //$NON-NLS-2$
-
-// long endTime = System.currentTimeMillis();
-// System.out.println(" response- "+response+",timeout="+timeout+",elapsed="+(endTime-startTime));
- m_lastResponse = response;
- return response;
- }
-
- // use default timeout
- boolean simpleRequestResponseMessage(DMessage msg, int msgType) { return simpleRequestResponseMessage(msg, msgType, -1); }
-
- boolean simpleRequestResponseMessageIsolate(DMessage msg, int msgType, int isolateId) {
- return simpleRequestResponseMessageIsolate(msg, msgType, -1, isolateId);
- }
-
- boolean simpleRequestResponseMessageIsolate(DMessage msg, int msgType, int timeout, int isolateId)
- {
- msg.setTargetIsolate(isolateId);
- return simpleRequestResponseMessage(msg, msgType, timeout);
- }
-
- boolean simpleRequestResponseMessage(int msg, int msgType) { return simpleRequestResponseMessage(msg, msgType, -1); }
-
- boolean simpleRequestResponseMessageIsolate(int msg, int msgType, int isolateId) {
- return simpleRequestResponseMessageIsolate(msg, msgType, -1, isolateId);
- }
-
- boolean simpleRequestResponseMessageIsolate(int msg, int msgType, int timeout, int isolateId)
- {
- DMessage dm = DMessageCache.alloc(0);
- dm.setType(msg);
- dm.setTargetIsolate(isolateId);
- return simpleRequestResponseMessage(dm, msgType, timeout);
- }
-
- // Convenience function
- boolean simpleRequestResponseMessage(int msg, int msgType, int timeout)
- {
- DMessage dm = DMessageCache.alloc(0);
- dm.setType(msg);
- return simpleRequestResponseMessage(dm, msgType, timeout);
- }
-
- /**
- * We register ourself as a listener to DMessages from the pipe for the
- * sole purpose of monitoring the state of the debugger. All other
- * object management occurs with DManager
- */
- /**
- * Issued when the socket connection to the player is cut
- */
- public void disconnected()
- {
- m_isHalted = false;
- m_isConnected = false;
- m_manager.disconnected();
- }
-
- /**
- * This is the core routine for decoding incoming messages and deciding what should be
- * done with them. We have registered ourself with DProtocol to be notified when any
- * incoming messages have been received.
- *
- * It is important to note that we should not rely on the contents of the message
- * since it may be reused after we exit this method.
- */
- public void messageArrived(DMessage msg, DProtocol which)
- {
- preMessageArrived(msg, which);
- msg.reset(); // allow the message to be re-parsed
- m_manager.messageArrived(msg, which);
- msg.reset(); // allow the message to be re-parsed
- postMessageArrived(msg, which);
- }
-
- /**
- * Processes the message before it is passed to the DManager.
- */
- private void preMessageArrived(DMessage msg, DProtocol which)
- {
- switch (msg.getType())
- {
- case DMessage.InIsolate:
-
- m_lastPreIsolate = (int)msg.getDWord();
-
- break;
-
- case DMessage.InAskBreakpoints:
- case DMessage.InBreakAt:
- case DMessage.InBreakAtExt:
- {
- // We need to set m_isHalted to true before the DManager processes
- // the message, because the DManager may add a BreakEvent to the
- // event queue, which the host debugger may immediately process;
- // if the debugger calls back to the Session, the Session must be
- // correctly marked as halted.
- if (m_lastPreIsolate == Isolate.DEFAULT_ID)
- m_isHalted = true;
- else
- updateHaltIsolateStatus(m_lastPreIsolate, true);
- break;
- }
- }
- }
-
- /**
- * Processes the message after it has been passed to the DManager.
- */
- private void postMessageArrived(DMessage msg, DProtocol which)
- {
- if (m_debugMsgOn || m_debugMsgFileOn)
- trace(msg, true);
-
- /* at this point we just open up a big switch statement and walk through all possible cases */
- int type = msg.getType();
- switch(type)
- {
- case DMessage.InExit:
- {
- m_isConnected = false;
- break;
- }
-
- case DMessage.InProcessTag:
- {
- // need to send a response to this message to keep the player going
- sendMessageIsolate(DMessage.OutProcessedTag, msg.getTargetIsolate());
- break;
- }
-
- case DMessage.InContinue:
- {
- if (msg.getTargetIsolate() == Isolate.DEFAULT_ID)
- m_isHalted = false;
- else {
- updateHaltIsolateStatus(msg.getTargetIsolate(), false);
- }
- break;
- }
-
- case DMessage.InOption:
- {
- //workers inherit options, so only store options
- //from main thread.
- if (msg.getTargetIsolate() == Isolate.DEFAULT_ID) {
- String s = msg.getString();
- String v = msg.getString();
-
- // add it to our properties, for DEBUG purposes only
- m_prefs.put(s, v);
- }
- break;
- }
-
- case DMessage.InSwfInfo:
- case DMessage.InScript:
- case DMessage.InRemoveScript:
- {
- //FIXME: Clear this cache only for affected
- //workers. Right now, the key contains worker
- //id, so we are safe. But we unnecessarily flush
- //the queue.
- m_evalIsAndInstanceofCache.clear();
-
- m_incoming = true;
- break;
- }
-
- default:
- {
- /**
- * Simple indicator that we have received a message. We
- * put this indicator in default so that InProcessTag msgs
- * wouldn't generate false triggers. Mainly, we want to
- * reset our timeout counter when we receive trace messages.
- */
- m_incoming = true;
- break;
- }
- }
-
- // something came in so assume that we can now talk
- // to the player
- m_lastResponse = true;
- }
-
- private void updateHaltIsolateStatus(int targetIsolate, boolean value) {
- if (!m_isolateStatus.containsKey(targetIsolate)) {
- PlayerSessionIsolateStatus status = new PlayerSessionIsolateStatus();
- status.m_isHalted = value;
- m_isolateStatus.put(targetIsolate, status);
- }
- else {
- m_isolateStatus.get(targetIsolate).m_isHalted = value;
- }
- }
-
- /**
- * A background thread which wakes up periodically and fetches the SWF and SWD
- * from the Player for new movies that have loaded. It then uses these to create
- * an instance of MovieMetaData (a class shared with the Profiler) from which
- * fdb can cull function names.
- * This work is done on a background thread because it can take several
- * seconds, and we want the fdb user to be able to execute other commands
- * while it is happening.
- */
- public void run()
- {
- long last = 0;
- while(isConnected())
- {
- // try every 250ms
- try { Thread.sleep(250); } catch(InterruptedException ie) {}
-
- try
- {
- // let's make sure that the traffic level is low before
- // we do our requests.
- long current = m_protocol.messagesReceived();
- long delta = last - current;
- last = current;
-
- // if the last message that went out was not responded to
- // or we are not suspended and have high traffic
- // then wait for later.
- if (!m_lastResponse || (!isSuspended() && delta > 5))
- throw new NotSuspendedException();
-
- // we are either suspended or low enough traffic
-
- // get the list of swfs we have
- for (Isolate isolate : m_manager.getIsolates()) {
- int isolateId = isolate.getId();
- if (isolateId != Isolate.DEFAULT_ID && !isWorkerSuspended(isolateId) && delta > 5) {
- throw new NotSuspendedException();
- }
- int count = m_manager.getSwfInfoCount(isolateId);
- for(int i=0; i<count; i++)
- {
- DSwfInfo info = m_manager.getSwfInfo(i, isolateId);
-
- // no need to process if it's been removed
- if (info == null || info.isUnloaded() || info.isPopulated() || (info.getVmVersion() > 0) )
- continue;
-
- // see if the swd has been loaded, throws exception if unable to load it.
- // Also triggers a callback into the info object to freshen its contents
- // if successful
- //FIXME: remove sysout
- info.getSwdSize(this);
- // check since our vm version info could get updated in between.
- if (info.getVmVersion() > 0)
- {
- // mark it populated if we haven't already done so
- info.setPopulated();
- continue;
- }
-
- // so by this point we know that we've got good swd data,
- // or we've made too many attempts and gave up.
- if (!info.isSwdLoading() && !info.isUnloaded())
- {
- // now load the swf, if we haven't already got it
- if (info.getSwf() == null && !info.isUnloaded())
- info.setSwf(requestSwf(i));
-
- // only get the swd if we haven't got it
- if (info.getSwd() == null && !info.isUnloaded())
- info.setSwd(requestSwd(i));
-
- try
- {
- // now go populate the functions tables...
- if (!info.isUnloaded())
- info.parseSwfSwd(m_manager);
- }
- catch(Throwable e)
- {
- // oh this is not good and means that we should probably
- // give up.
- if (Trace.error)
- {
- Trace.trace("Error while parsing swf/swd '"+info.getUrl()+"'. Giving up and marking it processed"); //$NON-NLS-1$ //$NON-NLS-2$
- e.printStackTrace();
- }
-
- info.setPopulated();
- }
- }
- }
- }
- }
- catch(InProgressException ipe)
- {
- // swd is still loading so give us a bit of
- // time and then come back and try again
- }
- catch(NoResponseException nre)
- {
- // timed out on one of our requests so don't bother
- // continuing right now, try again later
- }
- catch(NotSuspendedException nse)
- {
- // probably want to wait until we are halted before
- // doing this heavy action
- }
- catch(Exception e)
- {
- // maybe not good
- if (Trace.error)
- {
- Trace.trace("Exception in background swf/swd processing thread"); //$NON-NLS-1$
- e.printStackTrace();
- }
- }
- }
- }
-
- byte[] requestSwf(int index) throws NoResponseException
- {
- /* send the message */
- int to = getPreference(SessionManager.PREF_SWFSWD_LOAD_TIMEOUT);
- byte[] swf = null;
-
- // the query
- DMessage dm = DMessageCache.alloc(2);
- dm.setType(DMessage.OutGetSwf);
- dm.putWord(index);
-
- if (simpleRequestResponseMessage(dm, DMessage.InGetSwf, to))
- swf = m_manager.getSWF();
- else
- throw new NoResponseException(to);
-
- return swf;
- }
-
- byte[] requestSwd(int index) throws NoResponseException
- {
- /* send the message */
- int to = getPreference(SessionManager.PREF_SWFSWD_LOAD_TIMEOUT);
- byte[] swd = null;
-
- // the query
- DMessage dm = DMessageCache.alloc(2);
- dm.setType(DMessage.OutGetSwd);
- dm.putWord(index);
-
- if (simpleRequestResponseMessage(dm, DMessage.InGetSwd, to))
- swd = m_manager.getSWD();
- else
- throw new NoResponseException(to);
-
- return swd;
- }
-
- //
- // Debug purposes only. Dump contents of our messages to the screen
- // and/or file.
- //
- synchronized void trace(DMessage dm, boolean in)
- {
- try
- {
- if (m_debugMsgOn) {
- System.out.println( (in) ? dm.inToString(m_debugMsgSize) : dm.outToString(m_debugMsgSize) );
- }
-
- if (m_debugMsgFileOn)
- {
- traceFile().write( (in) ? dm.inToString(m_debugMsgFileSize) : dm.outToString(m_debugMsgFileSize) );
- m_trace.write(s_newline);
- m_trace.flush();
- }
- }
- catch(Exception e) {}
- }
-
- // i/o for tracing
- java.io.Writer m_trace;
-
-
- java.io.Writer traceFile() throws IOException
- {
- if (m_trace == null)
- {
- m_trace = new java.io.FileWriter("mm_debug_api_trace.txt"); //$NON-NLS-1$
- try { m_trace.write(new java.util.Date().toString()); } catch(Exception e) { m_trace.write("Date unknown"); } //$NON-NLS-1$
- try
- {
- m_trace.write(s_newline);
-
- // java properties dump
- java.util.Properties props = System.getProperties();
- props.list(new java.io.PrintWriter(m_trace));
-
- m_trace.write(s_newline);
-
- // property dump
- for (String key: m_prefs.keySet())
- {
- Object value = m_prefs.get(key);
- m_trace.write(key);
- m_trace.write(" = "); //$NON-NLS-1$
- m_trace.write(value.toString());
- m_trace.write(s_newline);
- }
- }
- catch(Exception e) { if (Trace.error) e.printStackTrace(); }
- m_trace.write(s_newline);
- }
- return m_trace;
- }
-
- public void setLaunchUrl(String url)
- {
- if (url.startsWith("/")) { //$NON-NLS-1$
- url = "file://" + url; //$NON-NLS-1$
- }
- m_launchUrl = url;
- }
-
- public void setAIRLaunchInfo(AIRLaunchInfo airLaunchInfo)
- {
- m_airLaunchInfo = airLaunchInfo;
- }
-
- public void breakOnCaughtExceptions(boolean b) throws NotSupportedException, NoResponseException {
- breakOnCaughtExceptions(b, Isolate.DEFAULT_ID);
- }
-
- public void breakOnCaughtExceptions(boolean b, int isolateId) throws NotSupportedException, NoResponseException {
- if (!playerCanBreakOnAllExceptions(isolateId))
- throw new NotSupportedException(PlayerSessionManager.getLocalizationManager().getLocalizedTextString("exceptionBreakpointsNotSupported")); //$NON-NLS-1$
-
- DMessage dm = DMessageCache.alloc(1);
- dm.setType(DMessage.OutPassAllExceptionsToDebugger);
- dm.putByte((byte)(b ? 1 : 0));
- dm.setTargetIsolate(isolateId);
- /* TODO: Verify that sendMessage below is a bug */
-// sendMessage(dm);
- if (!simpleRequestResponseMessage(dm, DMessage.InPassAllExceptionsToDebugger))
- throw new NoResponseException(getPreference(SessionManager.PREF_RESPONSE_TIMEOUT));
- }
-
-
- public boolean evalIs(Value value, Value type) throws PlayerDebugException, PlayerFaultException
- {
- return evalIsOrInstanceof(BinaryOp.Is, value, type, Isolate.DEFAULT_ID);
- }
-
- public boolean evalIs(Value value, String type) throws PlayerDebugException, PlayerFaultException
- {
- return evalIsOrInstanceof(BinaryOp.Is, value, type, Isolate.DEFAULT_ID);
- }
-
- public boolean evalInstanceof(Value value, Value type) throws PlayerDebugException, PlayerFaultException
- {
- return evalIsOrInstanceof(BinaryOp.Instanceof, value, type, Isolate.DEFAULT_ID);
- }
-
- public boolean evalInstanceof(Value value, String type) throws PlayerDebugException, PlayerFaultException
- {
- return evalIsOrInstanceof(BinaryOp.Instanceof, value, type, Isolate.DEFAULT_ID);
- }
-
- // isolate version
-
- public boolean evalIsWorker(Value value, Value type, int isolateId) throws PlayerDebugException, PlayerFaultException
- {
- return evalIsOrInstanceof(BinaryOp.Is, value, type, isolateId);
- }
-
- public boolean evalIsWorker(Value value, String type, int isolateId) throws PlayerDebugException, PlayerFaultException
- {
- return evalIsOrInstanceof(BinaryOp.Is, value, type, isolateId);
- }
-
- public boolean evalInstanceofWorker(Value value, Value type, int isolateId) throws PlayerDebugException, PlayerFaultException
- {
- return evalIsOrInstanceof(BinaryOp.Instanceof, value, type, isolateId);
- }
-
- public boolean evalInstanceofWorker(Value value, String type, int isolateId) throws PlayerDebugException, PlayerFaultException
- {
- return evalIsOrInstanceof(BinaryOp.Instanceof, value, type, isolateId);
- }
-
- private boolean evalIsOrInstanceof(BinaryOp op, Value value, Value type, int isolateId) throws PlayerDebugException, PlayerFaultException
- {
- String key = value.getTypeName() + " " + op + " " + type.getTypeName() + " " + String.valueOf(isolateId); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- Boolean retval = m_evalIsAndInstanceofCache.get(key);
- if (retval == null)
- {
- retval = new Boolean(ECMA.toBoolean(evalBinaryOp(op, value, type, isolateId)));
- m_evalIsAndInstanceofCache.put(key, retval);
- }
-
- return retval.booleanValue();
- }
-
- private boolean evalIsOrInstanceof(BinaryOp op, Value value, String type, int isolateId) throws PlayerDebugException, PlayerFaultException
- {
- String key = value.getTypeName() + " " + op + " " + type + " " + String.valueOf(isolateId); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- Boolean retval = m_evalIsAndInstanceofCache.get(key);
- if (retval == null)
- {
- Value typeval = getGlobalWorker(type, isolateId);
- if (typeval == null)
- retval = Boolean.FALSE;
- else
- retval = new
<TRUNCATED>