/*
* Copyright (C) 2012 Sony Mobile Communications AB
*
* This file is part of ApkAnalyser.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package analyser.gui;
import gui.AbstractMainFrame;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import mereflect.CorruptBytecodeException;
import mereflect.MEClass;
import mereflect.MEField;
import mereflect.MEMethod;
import mereflect.UnknownMethod;
import mereflect.UnknownResSpec;
import org.jf.dexlib.Code.Instruction;
import analyser.gui.actions.AboutAction;
import analyser.gui.actions.AnalyseAction;
import analyser.gui.actions.AnalyseMidletAction;
import analyser.gui.actions.ExamineClassAction;
import analyser.gui.actions.ExitAction;
import analyser.gui.actions.SetPathsAction;
import analyser.gui.actions.SettingsAction;
import analyser.gui.actions.ShowBytecodeAction;
import analyser.gui.actions.bytecodemod.FieldAction;
import analyser.gui.actions.bytecodemod.GraphMarkAction;
import analyser.gui.actions.bytecodemod.MethodEntryAction;
import analyser.gui.actions.bytecodemod.MethodExitAction;
import analyser.gui.actions.bytecodemod.MethodFlowAction;
import analyser.gui.actions.bytecodemod.MethodOffsetAction;
import analyser.gui.actions.bytecodemod.MethodOffsetCurThreadAction;
import analyser.gui.actions.bytecodemod.PerformAction;
import analyser.gui.actions.bytecodemod.ReferenceCallsAction;
import analyser.gui.actions.bytecodemod.UnregisterAction;
import analyser.gui.actions.lookup.FindFieldAccessAction;
import analyser.gui.actions.lookup.FindMonitorsAction;
import analyser.gui.actions.lookup.FindNativeCallsAction;
import analyser.gui.actions.lookup.LocalLookUpCallersAction;
import analyser.gui.actions.lookup.LocalLookUpCallsAction;
import analyser.gui.actions.lookup.LookUpAction;
import analyser.gui.actions.lookup.OpenCallGraphAction;
import analyser.gui.actions.lookup.OpenCallerGraphAction;
import analyser.logic.RefAndroidManifest;
import analyser.logic.RefClass;
import analyser.logic.RefContext;
import analyser.logic.RefField;
import analyser.logic.RefFieldAccess;
import analyser.logic.RefFolder;
import analyser.logic.RefInvokation;
import analyser.logic.RefMethod;
import analyser.logic.RefPackage;
import analyser.logic.RefResReference;
import analyser.logic.RefResSpec;
import analyser.logic.RefXml;
import analyser.logic.Reference;
import analyser.logic.Resolver;
import andreflect.ApkClassContext;
import andreflect.DexField;
import andreflect.DexMethod;
import andreflect.DexReferenceCache;
import andreflect.gui.action.AdbOpenAction;
import andreflect.gui.action.ApkExamineOdexDependencyAction;
import andreflect.gui.action.ApkInstallAndStartAction;
import andreflect.gui.action.ApkResignAction;
import andreflect.gui.action.ApkResignInstallAndStartAction;
import andreflect.gui.action.ApkUninstallAction;
import andreflect.gui.action.DalvikFindFieldAccessAction;
import andreflect.gui.action.XmlFindLabelAction;
import andreflect.gui.action.XmlResourceAction;
import andreflect.gui.action.XmlResourceIdAction;
import andreflect.gui.action.XmlSystemReferenceAction;
import andreflect.gui.action.XmlUnusedFileAction;
import andreflect.gui.action.XmlUnusedResourceAction;
import andreflect.gui.action.XmlVerifyResourceAction;
import andreflect.gui.action.injection.DalvikMethodEntryAction;
import andreflect.gui.action.injection.DalvikMethodEntryParamAction;
import andreflect.gui.action.injection.DalvikMethodExitAction;
import andreflect.gui.action.injection.DalvikMethodExitValueAction;
import andreflect.gui.action.injection.DalvikMethodFieldReadAction;
import andreflect.gui.action.injection.DalvikMethodFieldWriteAction;
import andreflect.gui.action.injection.DalvikMethodLocalReadAction;
import andreflect.gui.action.injection.DalvikMethodLocalWriteAction;
import andreflect.gui.action.injection.DalvikMethodOffsetCurThreadAction;
import andreflect.gui.action.injection.DalvikMethodOffsetCustomLogAction;
import andreflect.gui.action.injection.DalvikMethodOffsetExCatchAction;
import andreflect.gui.action.injection.DalvikMethodOffsetExThrowAction;
import andreflect.gui.action.injection.DalvikMethodOffsetGCAction;
import andreflect.gui.action.injection.DalvikMethodOffsetInstanceFinalizeAction;
import andreflect.gui.action.injection.DalvikMethodOffsetInstanceNewAction;
import andreflect.gui.action.injection.DalvikMethodOffsetInstanceNewInnerAction;
import andreflect.gui.action.injection.DalvikMethodOffsetPrintStackTraceAction;
import andreflect.gui.action.injection.DalvikMethodOffsetSyncEntryAction;
import andreflect.gui.action.injection.DalvikMethodOffsetSyncExitAction;
import andreflect.gui.action.injection.DalvikReferenceCallsParamAction;
import andreflect.gui.action.injection.DalvikReferenceCallsReturnAction;
import andreflect.gui.chart.GraphPanel;
import andreflect.gui.chart.GraphToolBar;
import andreflect.gui.linebuilder.DalvikByteCodeLineBuilder;
import andreflect.gui.linebuilder.XmlLineFormatter;
import andreflect.xml.XmlParser;
import andreflect.xml.XmlParser.XmlLine;
import brut.androlib.res.data.ResResSpec;
/**
* TODO on MidletAnalyser
* C look for jad file and modify accordingly (size and jar name)
* C generic bytecode modifiction using reflection
* - invoke a special class instead of doing system.out.println
* - modify and compile that class in MidletAnalyser
* - being able to review bytecode changes
* - rescanning bytecode changes when showing bytecodes
*/
public class MainFrame extends AbstractMainFrame implements WindowListener
{
private static final long serialVersionUID = 3267840509615224745L;
protected static MainFrame m_inst = null;
protected JSplitPane m_splitContent;
protected JSplitPane m_splitTree;
protected ClassTree m_resourceTree;
protected ClassTree m_midletTree;
protected Resolver m_resolver;
protected JPopupMenu m_popup;
protected ClassTree m_selectedTree;
protected List<MAButton> m_buttons = new ArrayList<MAButton>();
protected List<JMenuItem> m_contextMenuItems = new ArrayList<JMenuItem>();
protected List<JMenuItem> m_apkMenuItems = new ArrayList<JMenuItem>();
protected TextBuilder m_contentTextBuilder;
protected GraphToolBar m_toolBar;
protected JScrollPane m_contentScrollPane;
protected GraphPanel m_contentViewPane;
protected JSplitPane m_splitToolBar;
public ClassTree getSelectedTree()
{
return m_selectedTree;
}
public ClassTree getOppositeSelectedTree()
{
if (m_selectedTree == null) {
return null;
}
return m_selectedTree == getResourceTree() ?
getMidletTree() :
getResourceTree();
}
public ClassTree getResourceTree()
{
return m_resourceTree;
}
public ClassTree getMidletTree()
{
return m_midletTree;
}
public void setResolver(Resolver resolver)
{
m_resolver = resolver;
}
public Resolver getResolver()
{
return m_resolver;
}
protected void lookUpOppositeInvokations(ClassTree tree, Reference mRef)
{
Object[] source = { tree, mRef };
LookUpAction.getInstance(this).actionPerformed(new ActionEvent(source, 0, null));
}
// Common
public static MainFrame getInstance()
{
if (m_inst == null)
{
m_inst = new MainFrame();
}
return m_inst;
}
@Override
protected void setupGui(Container pane, int width, int height)
{
// Popups
JPopupMenu midletPopup = new JPopupMenu();
midletPopup.add(AnalyseMidletAction.getInstance(this));
JPopupMenu packagePopup = new JPopupMenu();
packagePopup.add(LookUpAction.getInstance(this));
packagePopup.addSeparator();
packagePopup.add(ReferenceCallsAction.getInstance(this));
packagePopup.add(DalvikReferenceCallsParamAction.getInstance(this));
packagePopup.add(DalvikReferenceCallsReturnAction.getInstance(this));
JPopupMenu classPopup = new JPopupMenu();
classPopup.add(LookUpAction.getInstance(this));
classPopup.add(ExamineClassAction.getInstance(this));
//classPopup.add(RenameAction.getInstance(this));
classPopup.add(FindMonitorsAction.getInstance(this));
classPopup.addSeparator();
classPopup.add(ReferenceCallsAction.getInstance(this));
// classPopup.add(GenericModificationAction.getInstance(this));
classPopup.add(DalvikReferenceCallsParamAction.getInstance(this));
classPopup.add(DalvikReferenceCallsReturnAction.getInstance(this));
JPopupMenu resourcePopup = new JPopupMenu();
resourcePopup.add(LookUpAction.getInstance(this));
//resourcePopup.add(RemoveResourceAction.getInstance(this));
resourcePopup.add(FindMonitorsAction.getInstance(this));
resourcePopup.addSeparator();
resourcePopup.add(ReferenceCallsAction.getInstance(this));
resourcePopup.add(DalvikReferenceCallsParamAction.getInstance(this));
resourcePopup.add(DalvikReferenceCallsReturnAction.getInstance(this));
JPopupMenu midletMethodPopup = new JPopupMenu();
midletMethodPopup.add(LookUpAction.getInstance(this));
midletMethodPopup.add(LocalLookUpCallsAction.getInstance(this));
midletMethodPopup.add(LocalLookUpCallersAction.getInstance(this));
midletMethodPopup.add(OpenCallGraphAction.getInstance(this));
midletMethodPopup.add(OpenCallerGraphAction.getInstance(this));
midletMethodPopup.addSeparator();
midletMethodPopup.add(ShowBytecodeAction.getInstance(this));
midletMethodPopup.add(MethodEntryAction.getInstance(this));
midletMethodPopup.add(MethodExitAction.getInstance(this));
// midletMethodPopup.add(GenericModificationAction.getInstance(this));
midletMethodPopup.addSeparator();
midletMethodPopup.add(FindNativeCallsAction.getInstance(this));
midletMethodPopup.add(FindMonitorsAction.getInstance(this));
//midletMethodPopup.add(RenameAction.getInstance(this));
JPopupMenu resourceMethodPopup = new JPopupMenu();
resourceMethodPopup.add(LookUpAction.getInstance(this));
resourceMethodPopup.add(ShowBytecodeAction.getInstance(this));
resourceMethodPopup.add(FindNativeCallsAction.getInstance(this));
resourceMethodPopup.addSeparator();
resourceMethodPopup.add(ReferenceCallsAction.getInstance(this));
resourceMethodPopup.add(DalvikReferenceCallsParamAction.getInstance(this));
resourceMethodPopup.add(DalvikReferenceCallsReturnAction.getInstance(this));
JPopupMenu resourceFieldPopup = new JPopupMenu();
resourceFieldPopup.add(DalvikFindFieldAccessAction.getInstance(this));
resourceFieldPopup.add(DalvikMethodFieldReadAction.getInstanceOneField(this));
resourceFieldPopup.add(DalvikMethodFieldWriteAction.getInstanceOneField(this));
JPopupMenu invPopup = new JPopupMenu();
invPopup.add(LookUpAction.getInstance(this));
JPopupMenu bytecodePopup = new JPopupMenu();
bytecodePopup.add(MethodOffsetAction.getInstance(this));
bytecodePopup.add(MethodOffsetCurThreadAction.getInstance(this));
bytecodePopup.add(FieldAction.getInstance(this));
bytecodePopup.add(MethodFlowAction.getInstance(this));
JPopupMenu methodBytecodePopup = new JPopupMenu();
methodBytecodePopup.add(MethodFlowAction.getInstance(this));
JPopupMenu fieldPopup = new JPopupMenu();
fieldPopup.add(FindFieldAccessAction.getInstance(this));
// Popup text dialog registration
TextDialog.registerPopup(LineBuilderFormatter.BytecodeOffset.class, bytecodePopup);
TextDialog.registerPopup(LineBuilderFormatter.Return.class, bytecodePopup);
TextDialog.registerPopup(LineBuilderFormatter.Return.class, bytecodePopup);
TextDialog.registerPopup(LineBuilderFormatter.Finally.class, methodBytecodePopup);
TextDialog.registerPopup(LineBuilderFormatter.Label.class, methodBytecodePopup);
TextDialog.registerPopup(LineBuilderFormatter.TryStart.class, methodBytecodePopup);
TextDialog.registerPopup(LineBuilderFormatter.TryEnd.class, methodBytecodePopup);
TextDialog.registerPopup(LineBuilderFormatter.Catch.class, methodBytecodePopup);
TextDialog.registerPopup(MEField.class, fieldPopup);
// Popup tree registration
m_resourceTree = new ClassTree();
ToolTipManager.sharedInstance().registerComponent(m_resourceTree);
m_resourceTree.setCellRenderer(new ClassTreeRenderer(true));
m_resourceTree.setModel(null);
m_resourceTree.addMouseListener(new ClassTreeMouseListener(m_resourceTree));
m_resourceTree.setRootVisible(false);
m_resourceTree.setShowsRootHandles(true);
m_resourceTree.registerPopup(RefContext.class, resourcePopup);
m_resourceTree.registerPopup(RefPackage.class, packagePopup);
m_resourceTree.registerPopup(RefClass.class, classPopup);
m_resourceTree.registerPopup(RefMethod.class, resourceMethodPopup);
m_resourceTree.registerPopup(RefInvokation.class, invPopup);
m_resourceTree.registerPopup(RefField.class, resourceFieldPopup);
m_resourceTree.registerPopup(RefFieldAccess.class, invPopup);
m_resourceTree.registerPopup(RefFolder.class, invPopup);
m_resourceTree.registerPopup(RefResSpec.class, invPopup);
m_resourceTree.registerPopup(RefResReference.class, invPopup);
m_midletTree = new ClassTree();
ToolTipManager.sharedInstance().registerComponent(m_midletTree);
m_midletTree.setCellRenderer(new ClassTreeRenderer(false));
m_midletTree.setModel(null);
m_midletTree.addMouseListener(new ClassTreeMouseListener(m_midletTree));
m_midletTree.setRootVisible(false);
m_midletTree.setShowsRootHandles(true);
m_midletTree.registerPopup(RefContext.class, resourcePopup);
m_midletTree.registerPopup(RefPackage.class, packagePopup);
m_midletTree.registerPopup(RefClass.class, classPopup);
m_midletTree.registerPopup(RefMethod.class, midletMethodPopup);
m_midletTree.registerPopup(RefInvokation.class, invPopup);
m_midletTree.registerPopup(void.class, midletPopup);
m_resourceTree.registerApkPopup(RefContext.class, resourcePopup);
m_resourceTree.registerApkPopup(RefPackage.class, packagePopup);
m_resourceTree.registerApkPopup(RefClass.class, classPopup);
m_resourceTree.registerApkPopup(RefMethod.class, resourceMethodPopup);
m_resourceTree.registerApkPopup(RefInvokation.class, invPopup);
m_resourceTree.registerApkPopup(RefField.class, resourceFieldPopup);
m_resourceTree.registerApkPopup(RefFieldAccess.class, invPopup);
m_resourceTree.registerApkPopup(RefFolder.class, invPopup);
m_resourceTree.registerApkPopup(RefResSpec.class, invPopup);
m_resourceTree.registerApkPopup(RefResReference.class, invPopup);
registerApkPopups();
m_contentTextBuilder = new TextBuilder("");
m_contentScrollPane = new JScrollPane(m_contentTextBuilder.getTextPane());
m_contentTextBuilder.setScrollPane(m_contentScrollPane);
m_contentViewPane = new GraphPanel(this);
m_toolBar = new GraphToolBar(m_contentViewPane, "Preview");
m_splitTree = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(m_resourceTree), new JScrollPane(
m_midletTree));
m_splitToolBar = new JSplitPane(JSplitPane.VERTICAL_SPLIT, m_toolBar, m_contentViewPane);
m_splitToolBar.setDividerSize(0);
m_splitToolBar.setEnabled(false);
m_splitToolBar.setBorder(null);
m_splitContent = new JSplitPane(JSplitPane.VERTICAL_SPLIT, m_splitTree, m_splitToolBar);
// Other
pane.add(m_splitContent, BorderLayout.CENTER);
// Set divider settings
int divTree = width / 2;
if (Settings.getMainFrameTreesDiv() > 0) {
divTree = Settings.getMainFrameTreesDiv();
}
m_splitTree.setDividerLocation(divTree);
int divContent = height / 2;
if (Settings.getMainFrameContentDiv() > 0) {
divContent = Settings.getMainFrameContentDiv();
}
m_splitContent.setDividerLocation(divContent);
}
protected void registerApkPopups() {
// Popups
JPopupMenu midletPopup = new JPopupMenu();
midletPopup.add(AnalyseMidletAction.getInstance(this));
JPopupMenu packagePopup = new JPopupMenu();
packagePopup.add(LookUpAction.getInstanceInternal(this));
packagePopup.add(LookUpAction.getInstance(this));
packagePopup.add(FindMonitorsAction.getInstance(this));
//packagePopup.add(ReferenceCallsAction.getInstance(this));
packagePopup.addSeparator();
packagePopup.add(DalvikMethodEntryAction.getInstance(this));
packagePopup.add(DalvikMethodEntryParamAction.getInstance(this));
packagePopup.add(DalvikMethodExitAction.getInstance(this));
packagePopup.add(DalvikMethodExitValueAction.getInstance(this));
packagePopup.addSeparator();
packagePopup.add(DalvikMethodOffsetCurThreadAction.getInstance(this));
packagePopup.add(DalvikMethodOffsetGCAction.getInstance(this));
packagePopup.add(DalvikMethodOffsetPrintStackTraceAction.getInstance(this));
packagePopup.add(DalvikMethodOffsetInstanceNewAction.getInstance(this));
packagePopup.addSeparator();
packagePopup.add(DalvikMethodOffsetInstanceNewInnerAction.getInstance(this));
packagePopup.add(DalvikMethodOffsetInstanceFinalizeAction.getInstance(this));
packagePopup.addSeparator();
packagePopup.add(DalvikMethodFieldReadAction.getInstance(this));
packagePopup.add(DalvikMethodFieldWriteAction.getInstance(this));
packagePopup.addSeparator();
packagePopup.add(DalvikMethodLocalReadAction.getInstance(this));
packagePopup.add(DalvikMethodLocalWriteAction.getInstance(this));
packagePopup.addSeparator();
packagePopup.add(DalvikMethodOffsetExThrowAction.getInstance(this));
packagePopup.add(DalvikMethodOffsetExCatchAction.getInstance(this));
packagePopup.addSeparator();
packagePopup.add(DalvikMethodOffsetSyncEntryAction.getInstance(this));
packagePopup.add(DalvikMethodOffsetSyncExitAction.getInstance(this));
JPopupMenu classPopup = new JPopupMenu();
classPopup.add(LookUpAction.getInstanceInternal(this));
classPopup.add(LookUpAction.getInstance(this));
classPopup.add(ExamineClassAction.getInstance(this));
//classPopup.add(RenameAction.getInstance(this));
classPopup.add(FindMonitorsAction.getInstance(this));
//classPopup.add(ReferenceCallsAction.getInstance(this));
//classPopup.add(GenericModificationAction.getInstance(this));
classPopup.addSeparator();
classPopup.add(DalvikMethodEntryAction.getInstance(this));
classPopup.add(DalvikMethodEntryParamAction.getInstance(this));
classPopup.add(DalvikMethodExitAction.getInstance(this));
classPopup.add(DalvikMethodExitValueAction.getInstance(this));
classPopup.addSeparator();
classPopup.add(DalvikMethodOffsetCurThreadAction.getInstance(this));
classPopup.add(DalvikMethodOffsetGCAction.getInstance(this));
classPopup.add(DalvikMethodOffsetPrintStackTraceAction.getInstance(this));
classPopup.add(DalvikMethodOffsetInstanceNewAction.getInstance(this));
classPopup.addSeparator();
classPopup.add(DalvikMethodOffsetInstanceNewInnerAction.getInstanceOneClass(this));
classPopup.add(DalvikMethodOffsetInstanceFinalizeAction.getInstanceOneClass(this));
classPopup.addSeparator();
classPopup.add(DalvikMethodFieldReadAction.getInstance(this));
classPopup.add(DalvikMethodFieldWriteAction.getInstance(this));
classPopup.addSeparator();
classPopup.add(DalvikMethodLocalReadAction.getInstance(this));
classPopup.add(DalvikMethodLocalWriteAction.getInstance(this));
classPopup.addSeparator();
classPopup.add(DalvikMethodOffsetExThrowAction.getInstance(this));
classPopup.add(DalvikMethodOffsetExCatchAction.getInstance(this));
classPopup.addSeparator();
classPopup.add(DalvikMethodOffsetSyncEntryAction.getInstance(this));
classPopup.add(DalvikMethodOffsetSyncExitAction.getInstance(this));
JPopupMenu resourcePopup = new JPopupMenu();
JMenu popDensity = new JMenu("Verify xml resources");
popDensity.add(XmlVerifyResourceAction.getInstance(this, "nodpi"));
popDensity.add(XmlVerifyResourceAction.getInstance(this, "ldpi"));
popDensity.add(XmlVerifyResourceAction.getInstance(this, "mdpi"));
popDensity.add(XmlVerifyResourceAction.getInstance(this, "hdpi"));
popDensity.add(XmlVerifyResourceAction.getInstance(this, "xhdpi"));
resourcePopup.add(LookUpAction.getInstance(this));
resourcePopup.add(FindMonitorsAction.getInstance(this));
//resourcePopup.add(RemoveResourceAction.getInstance(this));
//resourcePopup.add(ReferenceCallsAction.getInstance(this));
resourcePopup.addSeparator();
resourcePopup.add(ApkInstallAndStartAction.getInstance(this));
resourcePopup.add(ApkResignInstallAndStartAction.getInstance(this));
resourcePopup.add(ApkResignAction.getInstance(this));
resourcePopup.add(ApkUninstallAction.getInstance(this));
resourcePopup.add(ApkExamineOdexDependencyAction.getInstance(this));
resourcePopup.addSeparator();
resourcePopup.add(XmlResourceAction.getInstance(this));
resourcePopup.add(XmlResourceIdAction.getInstance(this));
resourcePopup.add(XmlUnusedResourceAction.getInstance(this));
resourcePopup.add(XmlUnusedFileAction.getInstance(this));
resourcePopup.add(XmlSystemReferenceAction.getInstance(this));
resourcePopup.add(XmlFindLabelAction.getInstance(this));
resourcePopup.add(popDensity);
resourcePopup.addSeparator();
resourcePopup.add(DalvikMethodEntryAction.getInstance(this));
resourcePopup.add(DalvikMethodEntryParamAction.getInstance(this));
resourcePopup.add(DalvikMethodExitAction.getInstance(this));
resourcePopup.add(DalvikMethodExitValueAction.getInstance(this));
resourcePopup.addSeparator();
resourcePopup.add(DalvikMethodOffsetCurThreadAction.getInstance(this));
resourcePopup.add(DalvikMethodOffsetGCAction.getInstance(this));
resourcePopup.add(DalvikMethodOffsetPrintStackTraceAction.getInstance(this));
resourcePopup.add(DalvikMethodOffsetInstanceNewAction.getInstance(this));
resourcePopup.addSeparator();
resourcePopup.add(DalvikMethodOffsetInstanceNewInnerAction.getInstance(this));
resourcePopup.add(DalvikMethodOffsetInstanceFinalizeAction.getInstance(this));
resourcePopup.addSeparator();
resourcePopup.add(DalvikMethodFieldReadAction.getInstance(this));
resourcePopup.add(DalvikMethodFieldWriteAction.getInstance(this));
resourcePopup.addSeparator();
resourcePopup.add(DalvikMethodLocalReadAction.getInstance(this));
resourcePopup.add(DalvikMethodLocalWriteAction.getInstance(this));
resourcePopup.addSeparator();
resourcePopup.add(DalvikMethodOffsetExThrowAction.getInstance(this));
resourcePopup.add(DalvikMethodOffsetExCatchAction.getInstance(this));
resourcePopup.addSeparator();
resourcePopup.add(DalvikMethodOffsetSyncEntryAction.getInstance(this));
resourcePopup.add(DalvikMethodOffsetSyncExitAction.getInstance(this));
JPopupMenu midletMethodPopup = new JPopupMenu();
midletMethodPopup.add(LookUpAction.getInstance(this));
midletMethodPopup.add(FindMonitorsAction.getInstance(this));
midletMethodPopup.add(FindNativeCallsAction.getInstance(this));
midletMethodPopup.add(LocalLookUpCallsAction.getInstance(this));
midletMethodPopup.add(LocalLookUpCallersAction.getInstance(this));
midletMethodPopup.add(OpenCallGraphAction.getInstance(this));
midletMethodPopup.add(OpenCallerGraphAction.getInstance(this));
midletMethodPopup.addSeparator();
midletMethodPopup.add(ShowBytecodeAction.getInstance(this));
//midletMethodPopup.add(GenericModificationAction.getInstance(this));
midletMethodPopup.addSeparator();
//midletMethodPopup.add(RenameAction.getInstance(this));
midletMethodPopup.add(DalvikMethodEntryAction.getInstance(this));
midletMethodPopup.add(DalvikMethodEntryParamAction.getInstance(this));
midletMethodPopup.add(DalvikMethodExitAction.getInstance(this));
midletMethodPopup.add(DalvikMethodExitValueAction.getInstance(this));
midletMethodPopup.addSeparator();
midletMethodPopup.add(DalvikMethodOffsetCurThreadAction.getInstance(this));
midletMethodPopup.add(DalvikMethodOffsetGCAction.getInstance(this));
midletMethodPopup.add(DalvikMethodOffsetPrintStackTraceAction.getInstance(this));
midletMethodPopup.add(DalvikMethodOffsetInstanceNewAction.getInstance(this));
midletMethodPopup.addSeparator();
midletMethodPopup.add(DalvikMethodFieldReadAction.getInstance(this));
midletMethodPopup.add(DalvikMethodFieldWriteAction.getInstance(this));
midletMethodPopup.addSeparator();
midletMethodPopup.add(DalvikMethodLocalReadAction.getInstance(this));
midletMethodPopup.add(DalvikMethodLocalWriteAction.getInstance(this));
midletMethodPopup.addSeparator();
midletMethodPopup.add(DalvikMethodOffsetExThrowAction.getInstance(this));
midletMethodPopup.add(DalvikMethodOffsetExCatchAction.getInstance(this));
midletMethodPopup.addSeparator();
midletMethodPopup.add(DalvikMethodOffsetSyncEntryAction.getInstance(this));
midletMethodPopup.add(DalvikMethodOffsetSyncExitAction.getInstance(this));
JPopupMenu invPopup = new JPopupMenu();
invPopup.add(LookUpAction.getInstanceInternal(this));
invPopup.add(LookUpAction.getInstance(this));
JPopupMenu bytecodePopup = new JPopupMenu();
bytecodePopup.add(DalvikMethodOffsetCustomLogAction.getInstance(this));
bytecodePopup.add(DalvikMethodOffsetCurThreadAction.getInstanceOffset(this));
bytecodePopup.add(DalvikMethodOffsetGCAction.getInstanceOffset(this));
bytecodePopup.add(DalvikMethodOffsetPrintStackTraceAction.getInstanceOffset(this));
JPopupMenu fieldPopup = new JPopupMenu();
fieldPopup.add(LookUpAction.getInstanceInternal(this));
fieldPopup.addSeparator();
fieldPopup.add(DalvikFindFieldAccessAction.getInstance(this));
fieldPopup.add(DalvikMethodFieldReadAction.getInstanceOneField(this));
fieldPopup.add(DalvikMethodFieldWriteAction.getInstanceOneField(this));
// Popup text dialog registration
TextDialog.registerPopup(DalvikByteCodeLineBuilder.DalvikBytecodeOffset.class, bytecodePopup);
TextDialog.registerPopup(DexField.class, fieldPopup);
m_midletTree.registerApkPopup(RefContext.class, resourcePopup);
m_midletTree.registerApkPopup(RefPackage.class, packagePopup);
m_midletTree.registerApkPopup(RefClass.class, classPopup);
m_midletTree.registerApkPopup(RefMethod.class, midletMethodPopup);
m_midletTree.registerApkPopup(RefInvokation.class, invPopup);
m_midletTree.registerApkPopup(void.class, midletPopup);
m_midletTree.registerApkPopup(RefField.class, fieldPopup);
m_midletTree.registerApkPopup(RefFieldAccess.class, invPopup);
m_midletTree.registerApkPopup(RefFolder.class, invPopup);
m_midletTree.registerApkPopup(RefResSpec.class, invPopup);
m_midletTree.registerApkPopup(RefResReference.class, invPopup);
m_midletTree.registerApkPopup(RefXml.class, invPopup);
m_midletTree.registerApkPopup(RefAndroidManifest.class, invPopup);
}
@Override
protected JMenuBar createMenuBar()
{
JMenuBar menuBar = new JMenuBar();
// File menu
JMenu menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menuBar.add(menu);
menu.add(AnalyseAction.getInstance(this));
menu.add(new JSeparator());
menu.add(SetPathsAction.getInstance(this));
menu.add(SettingsAction.getInstance(this));
menu.add(new JSeparator());
menu.add(ExitAction.getInstance());
// View menu
menu = new JMenu("View");
menu.setMnemonic(KeyEvent.VK_V);
menuBar.add(menu);
m_contextMenuItems.add(menu.add(ExamineClassAction.getInstance(this)));
m_contextMenuItems.add(menu.add(ShowBytecodeAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(OpenCallGraphAction.getInstance(this)));
m_contextMenuItems.add(menu.add(OpenCallerGraphAction.getInstance(this)));
// Lookup menu
menu = new JMenu("Lookup");
menu.setMnemonic(KeyEvent.VK_L);
menuBar.add(menu);
m_apkMenuItems.add(menu.add(XmlFindLabelAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(LookUpAction.getInstanceInternal(this)));
m_contextMenuItems.add(menu.add(LookUpAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(LocalLookUpCallsAction.getInstance(this)));
m_contextMenuItems.add(menu.add(LocalLookUpCallersAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(FindMonitorsAction.getInstance(this)));
m_contextMenuItems.add(menu.add(FindNativeCallsAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(DalvikFindFieldAccessAction.getInstance(this)));
// Bytecode mod menu
menu = new JMenu("Modifications");
menu.setMnemonic(KeyEvent.VK_M);
menuBar.add(menu);
menu.add(UnregisterAction.getInstance(this));
menu.add(PerformAction.getInstance(this));
menu.addSeparator();
m_contextMenuItems.add(menu.add(DalvikMethodEntryAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodEntryParamAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodExitAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodExitValueAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(DalvikMethodOffsetCurThreadAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetGCAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetPrintStackTraceAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetInstanceNewAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(DalvikMethodOffsetInstanceNewInnerAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetInstanceFinalizeAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetInstanceNewInnerAction.getInstanceOneClass(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetInstanceFinalizeAction.getInstanceOneClass(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(DalvikMethodFieldReadAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodFieldWriteAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodFieldReadAction.getInstanceOneField(this)));
m_contextMenuItems.add(menu.add(DalvikMethodFieldWriteAction.getInstanceOneField(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(DalvikMethodLocalReadAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodLocalWriteAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(DalvikMethodOffsetExThrowAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetExCatchAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(DalvikMethodOffsetSyncEntryAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetSyncExitAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(DalvikMethodOffsetCustomLogAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetCurThreadAction.getInstanceOffset(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetGCAction.getInstanceOffset(this)));
m_contextMenuItems.add(menu.add(DalvikMethodOffsetPrintStackTraceAction.getInstanceOffset(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(ReferenceCallsAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikReferenceCallsParamAction.getInstance(this)));
m_contextMenuItems.add(menu.add(DalvikReferenceCallsReturnAction.getInstance(this)));
menu.addSeparator();
m_contextMenuItems.add(menu.add(GraphMarkAction.getInstance(this)));
// Resource menu
menu = new JMenu("Resource");
menu.setMnemonic(KeyEvent.VK_R);
menuBar.add(menu);
JMenu popDensity = new JMenu("Verify xml resources");
m_apkMenuItems.add(popDensity.add(XmlVerifyResourceAction.getInstance(this, "nodpi")));
m_apkMenuItems.add(popDensity.add(XmlVerifyResourceAction.getInstance(this, "ldpi")));
m_apkMenuItems.add(popDensity.add(XmlVerifyResourceAction.getInstance(this, "mdpi")));
m_apkMenuItems.add(popDensity.add(XmlVerifyResourceAction.getInstance(this, "hdpi")));
m_apkMenuItems.add(popDensity.add(XmlVerifyResourceAction.getInstance(this, "xhdpi")));
m_apkMenuItems.add(menu.add(XmlResourceAction.getInstance(this)));
m_apkMenuItems.add(menu.add(XmlResourceIdAction.getInstance(this)));
menu.addSeparator();
m_apkMenuItems.add(menu.add(XmlUnusedResourceAction.getInstance(this)));
m_apkMenuItems.add(menu.add(XmlUnusedFileAction.getInstance(this)));
m_apkMenuItems.add(menu.add(XmlSystemReferenceAction.getInstance(this)));
menu.addSeparator();
m_apkMenuItems.add(menu.add(popDensity));
// Device menu
menu = new JMenu("Device");
menu.setMnemonic(KeyEvent.VK_D);
menuBar.add(menu);
m_apkMenuItems.add(menu.add(ApkInstallAndStartAction.getInstance(this)));
m_apkMenuItems.add(menu.add(ApkResignInstallAndStartAction.getInstance(this)));
m_apkMenuItems.add(menu.add(ApkResignAction.getInstance(this)));
m_apkMenuItems.add(menu.add(ApkUninstallAction.getInstance(this)));
menu.addSeparator();
m_apkMenuItems.add(menu.add(ApkExamineOdexDependencyAction.getInstance(this)));
menu.addSeparator();
//menu.add(EjavaOpenAction.getInstance(this));
menu.add(AdbOpenAction.getInstance(this));
// About menu
menu = new JMenu("Help");
menu.setMnemonic(KeyEvent.VK_H);
menuBar.add(menu);
menu.add(AboutAction.getInstance(this));
for (JMenuItem item : m_contextMenuItems) {
if (!(item instanceof JMenu)) {
item.setEnabled(false);
}
}
for (JMenuItem item : m_apkMenuItems) {
if (!(item instanceof JMenu)) {
item.setEnabled(false);
}
}
return menuBar;
}
@Override
protected JPanel createButtonBar() {
JPanel p = new JPanel();
p.setLayout(new FlowLayout(FlowLayout.LEFT));
MAButton butt;
// Analyse
butt = new MAButton(AnalyseAction.getInstance(this), FlagIcon.createImageIcon("b_analyse.png"), null,
"Load midlets and resolve against classpaths");
p.add(butt);
m_buttons.add(butt);
// Resolve
Class<?>[] luRelevance = { RefContext.class, RefPackage.class, RefInvokation.class, RefMethod.class, RefClass.class };
butt = new MAButton(LookUpAction.getInstance(this), FlagIcon.createImageIcon("b_lookup.png"), luRelevance,
"Find references to selected element in opposite tree");
p.add(butt);
m_buttons.add(butt);
// Examine = {Examine class, View bytecodes}
Class<?>[] examineRelevance = { RefMethod.class, RefClass.class };
butt = new MAButton(new AbstractAction() {
private static final long serialVersionUID = -723730167439372591L;
@Override
public void actionPerformed(ActionEvent e)
{
Object mRef = Selection.getSelectedObject();
if (mRef instanceof RefClass)
{
ExamineClassAction.getInstance(MainFrame.this).actionPerformed(e);
}
else if (mRef instanceof RefMethod)
{
ShowBytecodeAction.getInstance(MainFrame.this).actionPerformed(e);
}
}
}, FlagIcon.createImageIcon("b_examine.png"), examineRelevance, "Show detailed information, class definition or bytecodes");
p.add(butt);
m_buttons.add(butt);
p.add(new JLabel(" ")); // beautiful!!
// Add printout to method entry
Class<?>[] bytecodeModRelevance = { RefMethod.class, RefClass.class, RefPackage.class, RefContext.class };
butt = new MAButton(new AbstractAction() {
private static final long serialVersionUID = 2505914358357543450L;
@Override
public void actionPerformed(ActionEvent e)
{
RefContext ref = Selection.getRefContextOfSeletedObject();
if (ref != null) {
if (ref.getContext() instanceof ApkClassContext) {
DalvikMethodEntryAction.getInstance(MainFrame.this).actionPerformed(e);
} else {
MethodEntryAction.getInstance(MainFrame.this).actionPerformed(e);
}
}
}
}, FlagIcon.createImageIcon("b_bmpome.png"), bytecodeModRelevance, "Bytecode modify, add printout at method entry");
p.add(butt);
m_buttons.add(butt);
// Add printout to method exit
butt = new MAButton(new AbstractAction() {
private static final long serialVersionUID = -3216711373704635316L;
@Override
public void actionPerformed(ActionEvent e)
{
RefContext ref = Selection.getRefContextOfSeletedObject();
if (ref != null) {
if (ref.getContext() instanceof ApkClassContext) {
DalvikMethodExitAction.getInstance(MainFrame.this).actionPerformed(e);
} else {
MethodExitAction.getInstance(MainFrame.this).actionPerformed(e);
}
}
}
}, FlagIcon.createImageIcon("b_bmpomx.png"), bytecodeModRelevance, "Bytecode modify, add printout at method exits");
p.add(butt);
m_buttons.add(butt);
// Add printout to exceptionhandler
/*butt = new MAButton(new AbstractAction() {
private static final long serialVersionUID = 7363575542575354414L;
@Override
public void actionPerformed(ActionEvent e)
{
RefContext ref = Selection.getRefContextOfSeletedObject();
if (ref != null) {
if (ref.getContext() instanceof ApkClassContext) {
DalvikMethodOffsetExCatchAction.getInstance(MainFrame.this).actionPerformed(e);
} else {
ExceptionHandlerAction.getInstance(MainFrame.this).actionPerformed(e);
}
}
}
}, FlagIcon.createImageIcon("b_bmpexhand.png"), bytecodeModRelevance, "Bytecode modify, add printout in exception handlers");
p.add(butt);
m_buttons.add(butt);*/
p.add(new JLabel(" ")); // beautiful!!
// Remove registered bytecode modifications
butt = new MAButton(UnregisterAction.getInstance(this), FlagIcon.createImageIcon("b_bmunreg.png"), null, "Unregister bytecode modifications");
p.add(butt);
m_buttons.add(butt);
// Save byte code modifications
butt = new MAButton(PerformAction.getInstance(this), FlagIcon.createImageIcon("b_bmperform.png"), null, "Performs all registered bytecode modifications");
p.add(butt);
m_buttons.add(butt);
for (int i = 0; i < m_buttons.size(); i++)
{
butt = m_buttons.get(i);
butt.activate(null);
}
return p;
}
@Override
protected void saveSettingsOnClose() throws IOException
{
Settings.setMainFrameTreesDiv(m_splitTree.getDividerLocation());
Settings.setMainFrameContentDiv(m_splitContent.getDividerLocation());
}
class ClassTreeMouseListener extends MouseAdapter
{
protected ClassTree m_tree;
public ClassTreeMouseListener(ClassTree tree)
{
m_tree = tree;
}
@Override
public void mousePressed(MouseEvent e)
{
m_selectedTree = null;
if (m_popup != null)
{
m_popup.setVisible(false);
m_popup = null;
}
int selRow = m_tree.getRowForLocation(e.getX(), e.getY());
TreePath selPath = m_tree.getPathForLocation(e.getX(), e.getY());
DefaultMutableTreeNode node = null;
if (selRow > -1)
{
node =
((DefaultMutableTreeNode) selPath.getLastPathComponent());
}
if (node == null) {
return;
}
Selection.setSelectedObject(m_tree, node.getUserObject());
m_selectedTree = m_tree;
m_tree.setSelected(true);
getOppositeSelectedTree().setSelected(false);
if (SwingUtilities.isLeftMouseButton(e))
{
Object o = node != null ? node.getUserObject() : null;
showContent(o);
if ((e.getModifiers() & MouseEvent.ALT_MASK) != 0)
{
markUsedResources(node);
}
}
m_popup = m_tree.getPopup(node);
if (SwingUtilities.isRightMouseButton(e))
{
if (m_popup != null)
{
m_tree.setSelectionPath(selPath);
m_popup.show(e.getComponent(), e.getX(), e.getY());
}
}
for (int i = 0; i < m_buttons.size(); i++)
{
MAButton butt = m_buttons.get(i);
butt.activate(node.getUserObject().getClass());
}
for (int i = 0; i < m_contextMenuItems.size(); i++) {
m_contextMenuItems.get(i).setEnabled(false);
}
if (m_popup != null)
{
int itemCount = m_popup.getComponentCount();
for (int j = 0; j < itemCount; j++) {
if (m_popup.getComponent(j) instanceof JMenuItem) {
for (int i = 0; i < m_contextMenuItems.size(); i++) {
if (m_contextMenuItems.get(i).getAction() == ((JMenuItem) m_popup.getComponent(j)).getAction()) {
m_contextMenuItems.get(i).setEnabled(true);
break;
}
}
}
}
}
boolean apkActionEnabled = false;
RefContext ref = Selection.getRefContextOfSeletedObject();
if (ref != null
&& ref.getContext() instanceof ApkClassContext
&& ref.getContext().isMidlet()) {
apkActionEnabled = true;
}
for (JMenuItem item : m_apkMenuItems) {
item.setEnabled(apkActionEnabled);
}
}
}
@SuppressWarnings("unchecked")
private void markUsedResources(DefaultMutableTreeNode node)
{
if (getSelectedTree() == m_midletTree)
{
Object o = node != null ? node.getUserObject() : null;
if (o != null
&& o instanceof Reference)
{
LookUpAction lua = LookUpAction.getInstance(this);
lua.setRunning(true);
Reference[] invs = lua.getInvokations((Reference) o, false);
ClassTree tree = getOppositeSelectedTree();
lua.selectPathsInTree(tree, invs, RefPackage.class, RefFolder.class);
lua.setRunning(false);
}
}
}
private void switchContentPanel(JComponent jp) {
if (m_splitToolBar.getRightComponent().equals(jp)) {
return;
}
m_splitToolBar.setRightComponent(jp);
m_toolBar.setZoom(jp == m_contentViewPane);
}
public void showContent(Object o) {
if (o == null) {
return;
}
if (o instanceof RefContext) {
RefContext ctx = (RefContext) o;
m_toolBar.setText(ctx.getName(), ClassTreeRenderer.ICON_APK);
m_contentViewPane.loadContext(ctx);
switchContentPanel(m_contentViewPane);
} else if (o instanceof RefPackage) {
RefPackage pack = (RefPackage) o;
m_toolBar.setText(pack.getName(), ClassTreeRenderer.ICON_PACKAGE);
m_contentViewPane.loadContext(pack);
switchContentPanel(m_contentViewPane);
} else if (o instanceof RefClass) {
RefClass refClass = (RefClass) o;
MEClass c = refClass.getMEClass();
m_toolBar.setText(c.getName(), ClassTreeRenderer.ICON_CLASS);
m_contentViewPane.loadContext(refClass);
switchContentPanel(m_contentViewPane);
} else if (o instanceof RefMethod) {
RefMethod refMethod = (RefMethod) o;
int pc = Selection.getPc();
Instruction instruction = Selection.getDalvikInstruction();
showBytecodeContent(refMethod.getMethod(), instruction, pc);
switchContentPanel(m_contentScrollPane);
} else if (o instanceof RefAndroidManifest) {
RefAndroidManifest refManifest = (RefAndroidManifest) o;
XmlLineFormatter xmllb = refManifest.getContext().getXmlParser().getXmlLineBuilder(XmlParser.MANIFEST, -1, -1, false);
LineBuilder lb = null;
if (xmllb != null
&& (lb = xmllb.getLineBuilder()) != null) {
m_contentTextBuilder.init(lb);
m_toolBar.setText(XmlParser.MANIFEST, ClassTreeRenderer.ICON_ANDROID);
switchContentPanel(m_contentScrollPane);
}
} else if (o instanceof RefResSpec) {
RefResSpec refSpec = (RefResSpec) o;
ApkClassContext apkCtx = refSpec.getRefContext();
if (!(refSpec.getDexSpec().getResSpec() instanceof UnknownResSpec)) {
LineBuilder lb = apkCtx.getXmlParser().getResourceChecker().showSpecDetail(refSpec.getDexSpec().getResSpec(), this, refSpec.getRefContext());
if (lb != null) {
m_contentTextBuilder.init(lb);
m_toolBar.setText(refSpec.getDexSpec().getResSpec().getFullName(), ClassTreeRenderer.ICON_ANDROID);
switchContentPanel(m_contentScrollPane);
}
}
} else if (o instanceof RefInvokation) {
RefInvokation refInvo = (RefInvokation) o;
if (refInvo.isLocal() == false
&& refInvo.getContext().isMidlet() == false) {
refInvo = refInvo.getOppositeInvokation();
}
showBytecodeContent(refInvo.getMethod(), refInvo.getInvokation().offsetIns, refInvo.getInvokation().bytecodePc);
switchContentPanel(m_contentScrollPane);
} else if (o instanceof RefFieldAccess) {
DexReferenceCache.FieldAccess access = ((RefFieldAccess) o).getAccess();
showBytecodeContent(access.method, access.instruction, access.pc);
switchContentPanel(m_contentScrollPane);
} else if (o instanceof RefResReference) {
RefResReference refResReference = (RefResReference) o;
ApkClassContext apkCtx = refResReference.getRefContext();
if (refResReference.isRes()) {
LineBuilder lb = apkCtx.getXmlParser().getResourceChecker().showSpecDetail((ResResSpec) refResReference.getReferred(), this, refResReference.getRefContext());
if (lb != null) {
m_contentTextBuilder.init(lb);
m_toolBar.setText(((ResResSpec) refResReference.getReferred()).getFullName(), ClassTreeRenderer.ICON_ANDROID);
switchContentPanel(m_contentScrollPane);
}
} else if (refResReference.isXml()) {
XmlLine xmlLine = (XmlLine) refResReference.getReferred();
XmlLineFormatter xmllb = apkCtx.getXmlParser().getXmlLineBuilder(xmlLine.entry.getName(), xmlLine.line, xmlLine.id, false);
LineBuilder lb = null;
if (xmllb != null
&& (lb = xmllb.getLineBuilder()) != null) {
m_contentTextBuilder.init(lb);
if (xmllb.getCaret() != -1) {
m_contentTextBuilder.setCaretPosition(xmllb.getCaret());
}
m_toolBar.setText(xmlLine.entry.getName(), ClassTreeRenderer.ICON_XML);
switchContentPanel(m_contentScrollPane);
}
} else if (refResReference.isCode()) {
DexReferenceCache.LoadConstRes dexSpec = (DexReferenceCache.LoadConstRes) refResReference.getReferred();
showBytecodeContent(dexSpec.method, dexSpec.instruction, dexSpec.pc);
switchContentPanel(m_contentScrollPane);
}
} else if (o instanceof RefXml) {
RefXml ref = (RefXml) o;
ApkClassContext apkCtx = ref.getRefContext();
XmlLineFormatter xmllb = apkCtx.getXmlParser().getXmlLineBuilder(ref.getXml().getName(), -1, -1, false);
LineBuilder lb = null;
if (xmllb != null
&& (lb = xmllb.getLineBuilder()) != null) {
m_contentTextBuilder.init(lb);
m_toolBar.setText(ref.getXml().getName(), ClassTreeRenderer.ICON_XML);
switchContentPanel(m_contentScrollPane);
}
}
}
private void showBytecodeContent(MEMethod method, Instruction instruction, int pc) {
final String PREFIX = " ";
LineBuilder result = null;
if (method == null) {
return;
}
m_contentTextBuilder.setOwnerData(method);
MEClass clazz = method.getMEClass();
String methodName = method.getName();
if (methodName.equals("<init>")) {
methodName = "Constructor";
} else if (methodName.equals("<cinit>")) {
methodName = "Static constructor";
}
m_toolBar.setText(methodName + " method of " + clazz.getName(), ClassTreeRenderer.ICON_JAVAFILE);
if (method instanceof UnknownMethod) {
LineBuilder classLines = new LineBuilder();
m_contentTextBuilder.init(classLines);
return;
}
LineBuilder classLines = LineBuilderFormatter.makeOutline(clazz);
classLines.blendLines(0xffffff, 50);
int lineNbr = classLines.getLine(method);
try {
LineBuilder codeLines;
if (method instanceof DexMethod) {
codeLines = DalvikByteCodeLineBuilder.getByteCodeAssembler((DexMethod) method, PREFIX);
} else {
codeLines = LineBuilderFormatter.getByteCodeAssembler(method, PREFIX);
}
if (lineNbr >= 0) {
classLines.insertAfter(lineNbr, codeLines);
classLines.insertLineAfter(lineNbr + codeLines.lineCount());
result = classLines;
} else {
result = codeLines;
}
} catch (CorruptBytecodeException cbe) {
return;
}
if (result != null) {
m_contentTextBuilder.init(result);
if (instruction == null
&& pc < 0
&& method instanceof DexMethod
&& !method.isAbstract()) {
DexMethod dexMethod = (DexMethod) method;
instruction = dexMethod.getInstructionAtCodeAddress(0);
}
if (instruction != null) {
LineBuilder lb = m_contentTextBuilder.getLineBuilder();
for (int i = 0; i < lb.lineCount(); i++) {
Object ref = lb.getReference(i);
if (ref instanceof DalvikByteCodeLineBuilder.DalvikBytecodeOffset
&& ((DalvikByteCodeLineBuilder.DalvikBytecodeOffset) ref).instruction == instruction) {
lb.gotoLine(i);
m_contentTextBuilder.findNext(lb.currentLineString());
}
}
} else if (pc >= 0) {
int line = -1;
LineBuilder lb = m_contentTextBuilder.getLineBuilder();
for (int i = 0; i < lb.lineCount(); i++) {
Object ref = lb.getReference(i);
if (ref instanceof LineBuilderFormatter.BytecodeOffset) {
line = i;
break;
} else if (ref instanceof DalvikByteCodeLineBuilder.DalvikBytecodeOffset) {
line = i;
break;
}
}
if (line >= 0) {
m_contentTextBuilder.findNext(PREFIX + Integer.toHexString(pc) + ' '); // TODO fix up this sordid stuff
}
}
}
}
}