summaryrefslogtreecommitdiff
path: root/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs
diff options
context:
space:
mode:
Diffstat (limited to 'BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs')
-rw-r--r--BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs375
1 files changed, 0 insertions, 375 deletions
diff --git a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs b/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs
deleted file mode 100644
index 0fa4a884..00000000
--- a/BCT/BytecodeTranslator/Phone/PhoneNavigationTraverser.cs
+++ /dev/null
@@ -1,375 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Microsoft.Cci;
-using Microsoft.Cci.MutableCodeModel;
-using TranslationPlugins;
-
-namespace BytecodeTranslator.Phone {
- public class PhoneNavigationCodeTraverser : CodeTraverser {
- private MetadataReaderHost host;
- private ITypeReference navigationSvcType;
- private ITypeReference cancelEventArgsType;
- private ITypeReference typeTraversed;
- private IMethodDefinition methodTraversed;
- private static HashSet<IMethodDefinition> navCallers= new HashSet<IMethodDefinition>();
- public static IEnumerable<IMethodDefinition> NavCallers { get { return navCallers; } }
-
- private HashSet<IMethodReference> navigationCallers;
- public IEnumerable<IMethodReference> NavigationCallers { get { return NavigationCallers; } }
-
- public PhoneNavigationCodeTraverser(MetadataReaderHost host, IEnumerable<IAssemblyReference> assemblies) : base() {
- this.host = host;
- List<IAssembly> assembliesTraversed = new List<IAssembly>();
- foreach (IAssemblyReference asmRef in assemblies) {
- assembliesTraversed.Add(asmRef.ResolvedAssembly);
- }
-
- Microsoft.Cci.Immutable.PlatformType platform = host.PlatformType as Microsoft.Cci.Immutable.PlatformType;
-
- // TODO obtain version, culture and signature data dynamically
- IAssemblyReference assembly= PhoneTypeHelper.getPhoneAssemblyReference(host);
- // TODO determine the needed types dynamically
- navigationSvcType = platform.CreateReference(assembly, "System", "Windows", "Navigation", "NavigationService");
-
- assembly = PhoneTypeHelper.getSystemAssemblyReference(host);
- cancelEventArgsType = platform.CreateReference(assembly, "System", "ComponentModel", "CancelEventArgs");
- navigationCallers = new HashSet<IMethodReference>();
- }
-
- public override void TraverseChildren(ITypeDefinition typeDef) {
- this.typeTraversed = typeDef;
- base.TraverseChildren(typeDef);
- }
-
- public override void TraverseChildren(IMethodDefinition method) {
- this.methodTraversed = method;
- if (method.IsConstructor && PhoneTypeHelper.isPhoneApplicationClass(typeTraversed, host)) {
- navigationCallers.Add(method);
- string mainPageUri = PhoneCodeHelper.instance().PhonePlugin.getMainPageXAML();
- SourceMethodBody sourceBody = method.Body as SourceMethodBody;
- if (sourceBody != null) {
- BlockStatement bodyBlock = sourceBody.Block as BlockStatement;
- if (bodyBlock != null) {
- Assignment uriInitAssign = new Assignment() {
- Source = new CompileTimeConstant() {
- Type = host.PlatformType.SystemString,
- Value = UriHelper.getURIBase(mainPageUri),
- },
- Type = host.PlatformType.SystemString,
- Target = new TargetExpression() {
- Type = host.PlatformType.SystemString,
- // TODO unify code for current uri fieldreference
- Definition = new FieldReference() {
- ContainingType = PhoneCodeHelper.instance().getMainAppTypeReference(),
- IsStatic=true,
- Type=host.PlatformType.SystemString,
- Name=host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
- InternFactory= host.InternFactory,
- },
- },
- };
- Statement uriInitStmt= new ExpressionStatement() {
- Expression= uriInitAssign,
- };
- bodyBlock.Statements.Insert(0, uriInitStmt);
- }
- }
- }
- base.TraverseChildren(method);
- }
-
-
- private bool navCallFound=false;
- private bool navCallIsStatic = false;
- private bool navCallIsBack = false;
- private StaticURIMode currentStaticMode= StaticURIMode.NOT_STATIC;
- private string unpurifiedFoundURI="";
-
- public override void TraverseChildren(IBlockStatement block) {
- IList<Tuple<IStatement,StaticURIMode,string>> staticNavStmts = new List<Tuple<IStatement,StaticURIMode,string>>();
- IList<IStatement> nonStaticNavStmts = new List<IStatement>();
- foreach (IStatement statement in block.Statements) {
- navCallFound = false;
- navCallIsStatic = false;
- navCallIsBack = false;
- this.Traverse(statement);
- if (navCallFound) {
- navCallers.Add(methodTraversed);
- if (navCallIsStatic) {
- staticNavStmts.Add(new Tuple<IStatement, StaticURIMode, string>(statement, currentStaticMode, unpurifiedFoundURI));
- } else if (!navCallIsBack) {
- nonStaticNavStmts.Add(statement);
- }
- }
- }
-
- injectNavigationUpdateCode(block, staticNavStmts, nonStaticNavStmts);
- }
-
- private bool isNavigationOnBackKeyPressHandler(IMethodCall call, out string target) {
- target = null;
- if (!PhoneCodeHelper.instance().isBackKeyPressOverride(methodTraversed.ResolvedMethod))
- return false;
-
- if (!call.MethodToCall.ContainingType.isNavigationServiceClass(host))
- return false;
-
- if (!PhoneCodeHelper.NAV_CALLS.Contains(call.MethodToCall.Name.Value) || call.MethodToCall.Name.Value == "GoBack") // back is actually ok
- return false;
-
- if (call.MethodToCall.Name.Value == "Navigate") {
- try {
- IExpression expr = call.Arguments.First();
- bool isStatic = UriHelper.isArgumentURILocallyCreatedStatic(expr, host, out target) ||
- UriHelper.isArgumentURILocallyCreatedStaticRoot(expr, host, out target);
- if (!isStatic)
- target = "--Other non inferrable target--";
- else
- target = UriHelper.getURIBase(target);
- } catch (InvalidOperationException) {
- }
- }
-
- return true;
- }
-
- private bool isCancelOnBackKeyPressHandler(IMethodCall call) {
- if (!PhoneCodeHelper.instance().isBackKeyPressOverride(methodTraversed.ResolvedMethod))
- return false;
-
- return isEventCancellationMethodCall(call);
- }
-
- private bool isEventCancellationMethodCall(IMethodCall call) {
- if (!call.MethodToCall.Name.Value.StartsWith("set_Cancel"))
- return false;
-
- if (call.Arguments.Count() != 1 || call.Arguments.ToList()[0].Type != host.PlatformType.SystemBoolean)
- return false;
-
- if (call.ThisArgument == null || !call.ThisArgument.Type.isCancelEventArgsClass(host))
- return false;
-
- ICompileTimeConstant constant = call.Arguments.ToList()[0] as ICompileTimeConstant;
- if (constant != null && constant.Value != null) {
- CompileTimeConstant falseConstant = new CompileTimeConstant() {
- Type = host.PlatformType.SystemBoolean,
- Value = false,
- };
- if (constant.Value == falseConstant.Value)
- return false;
- }
-
- return true;
- }
-
- public override void TraverseChildren(IMethodCall methodCall) {
- string target;
- if (isNavigationOnBackKeyPressHandler(methodCall, out target)) {
- ICollection<Tuple<IMethodReference,string>> targets;
- try {
- targets= PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed];
- } catch (KeyNotFoundException) {
- targets = new HashSet<Tuple<IMethodReference,string>>();
- }
- targets.Add(Tuple.Create<IMethodReference,string>(methodTraversed, "\"" + target + "\""));
- PhoneCodeHelper.instance().BackKeyNavigatingOffenders[typeTraversed]= targets;
- } else if (isCancelOnBackKeyPressHandler(methodCall)) {
- PhoneCodeHelper.instance().BackKeyCancellingOffenders.Add(Tuple.Create<ITypeReference, string>(typeTraversed,""));
- }
-
- // re-check whether it is an event cancellation call
- if (isEventCancellationMethodCall(methodCall)) {
- PhoneCodeHelper.instance().KnownEventCancellingMethods.Add(methodTraversed);
- }
-
- // check whether it is a NavigationService call
- IMethodReference methodToCall= methodCall.MethodToCall;
- ITypeReference callType= methodToCall.ContainingType;
- if (!callType.ResolvedType.Equals(navigationSvcType.ResolvedType))
- return;
-
- string methodToCallName= methodToCall.Name.Value;
- if (!PhoneCodeHelper.NAV_CALLS.Contains(methodToCallName))
- return;
-
- navCallFound = true;
- // TODO check what to do with these
- if (methodToCallName == "GoForward" || methodToCallName == "StopLoading") {
- // TODO forward navigation is not supported by the phone
- // TODO StopLoading is very async, I don't think we may verify this behaviour
- // TODO possibly log
- return;
- } else {
- currentStaticMode = StaticURIMode.NOT_STATIC;
- if (methodToCallName == "GoBack") {
- navCallIsStatic = false;
- navCallIsBack = true;
- } else { // Navigate()
- navCallIsBack = false;
-
- // check for different static patterns that we may be able to verify
- IExpression uriArg = methodCall.Arguments.First();
- if (UriHelper.isArgumentURILocallyCreatedStatic(uriArg, host, out unpurifiedFoundURI)) {
- navCallIsStatic = true;
- currentStaticMode = StaticURIMode.STATIC_URI_CREATION_ONSITE;
- } else if (UriHelper.isArgumentURILocallyCreatedStaticRoot(uriArg, host, out unpurifiedFoundURI)) {
- navCallIsStatic = true;
- currentStaticMode = StaticURIMode.STATIC_URI_ROOT_CREATION_ONSITE;
- } else {
- // get reason
- //ICreateObjectInstance creationSite = methodCall.Arguments.First() as ICreateObjectInstance;
- //if (creationSite == null)
- // notStaticReason = "URI not created at call site";
- //else
- // notStaticReason = "URI not initialized as a static string";
- }
- }
-
- if (navCallFound && !navCallIsBack) {
- // check this method as a navigation method
- PhoneCodeHelper.instance().KnownNavigatingMethods.Add(methodTraversed);
- }
-
- //Console.Write("Page navigation event found. Target is static? " + (isStatic ? "YES" : "NO"));
- //if (!isStatic) {
- // Console.WriteLine(" -- Reason: " + notStaticReason);
- //} else {
- // Console.WriteLine("");
- //}
- }
- }
-
- private void injectNavigationUpdateCode(IBlockStatement block, IEnumerable<Tuple<IStatement,StaticURIMode, string>> staticStmts, IEnumerable<IStatement> nonStaticStmts) {
- // TODO Here there is the STRONG assumption that a given method will only navigate at most once per method call
- // TODO (or at most will re-navigate to the same page). Quick "page flipping" on the same method
- // TODO would not be captured correctly
- Microsoft.Cci.MutableCodeModel.BlockStatement mutableBlock = block as Microsoft.Cci.MutableCodeModel.BlockStatement;
-
- foreach (IStatement stmt in nonStaticStmts) {
- int ndx = mutableBlock.Statements.ToList().IndexOf(stmt);
- if (ndx == -1) {
- // can't be
- throw new IndexOutOfRangeException("Statement must exist in original block");
- }
-
- Assignment currentURIAssign = new Assignment() {
- Source = new CompileTimeConstant() {
- Type = host.PlatformType.SystemString,
- Value = PhoneCodeHelper.BOOGIE_DO_HAVOC_CURRENTURI,
- },
- Type = host.PlatformType.SystemString,
- Target = new TargetExpression() {
- Type = host.PlatformType.SystemString,
- // TODO unify code for current uri fieldreference
- Definition = new FieldReference() {
- ContainingType = PhoneCodeHelper.instance().getMainAppTypeReference(),
- IsStatic= true,
- Type = host.PlatformType.SystemString,
- Name = host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
- InternFactory=host.InternFactory,
- },
- },
- };
- Statement uriInitStmt = new ExpressionStatement() {
- Expression = currentURIAssign,
- };
- mutableBlock.Statements.Insert(ndx + 1, uriInitStmt);
- }
-
-
- foreach (Tuple<IStatement, StaticURIMode, string> entry in staticStmts) {
- int ndx= mutableBlock.Statements.ToList().IndexOf(entry.Item1);
- if (ndx == -1) {
- // can't be
- throw new IndexOutOfRangeException("Statement must exist in original block");
- }
-
- Assignment currentURIAssign = new Assignment() {
- Source = new CompileTimeConstant() {
- Type = host.PlatformType.SystemString,
- Value = UriHelper.getURIBase(entry.Item3).ToLower(),
- },
- Type = host.PlatformType.SystemString,
- Target = new TargetExpression() {
- Type = host.PlatformType.SystemString,
- // TODO unify code for current uri fieldreference
- Definition = new FieldReference() {
- ContainingType = PhoneCodeHelper.instance().getMainAppTypeReference(),
- IsStatic= true,
- Type = host.PlatformType.SystemString,
- Name = host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
- InternFactory=host.InternFactory,
- },
- },
- };
- Statement uriInitStmt = new ExpressionStatement() {
- Expression = currentURIAssign,
- };
- mutableBlock.Statements.Insert(ndx+1, uriInitStmt);
- }
- }
- }
-
- /// <summary>
- /// Traverse metadata looking only for PhoneApplicationPage's constructors
- /// </summary>
- public class PhoneNavigationMetadataTraverser : MetadataTraverser {
- private MetadataReaderHost host;
- private ITypeDefinition typeBeingTraversed;
- private PhoneNavigationCodeTraverser codeTraverser;
-
- public PhoneNavigationMetadataTraverser(MetadataReaderHost host)
- : base() {
- this.host = host;
- }
-
- public override void TraverseChildren(IModule module) {
- codeTraverser = new PhoneNavigationCodeTraverser(host, module.AssemblyReferences);
- base.Traverse(module.AssemblyReferences);
- base.TraverseChildren(module);
- }
-
-
- // TODO can we avoid visiting every type? Are there only a few, identifiable, types that may perform navigation?
- public override void TraverseChildren(ITypeDefinition typeDefinition) {
- typeBeingTraversed = typeDefinition;
- if (typeDefinition.isPhoneApplicationClass(host)) {
- NamespaceTypeDefinition mutableTypeDef = typeDefinition as NamespaceTypeDefinition;
- if (mutableTypeDef != null) {
- // TODO unify code for current uri fieldreference
- FieldDefinition fieldDef = new FieldDefinition() {
- ContainingTypeDefinition= mutableTypeDef,
- InternFactory= host.InternFactory,
- IsStatic= true,
- Name= host.NameTable.GetNameFor(PhoneCodeHelper.IL_CURRENT_NAVIGATION_URI_VARIABLE),
- Type= host.PlatformType.SystemString,
- Visibility= TypeMemberVisibility.Public,
- };
- PhoneCodeHelper.CurrentURIFieldDefinition = fieldDef;
- mutableTypeDef.Fields.Add(fieldDef);
- }
- }
-
- codeTraverser.Traverse(typeDefinition);
- base.TraverseChildren(typeDefinition);
- }
-
- // TODO same here. Are there specific methods (and ways to identfy those) that can perform navigation?
- public override void TraverseChildren(IMethodDefinition method) {
- if (PhoneCodeHelper.instance().isBackKeyPressOverride(method)) {
- PhoneCodeHelper.instance().KnownBackKeyHandlers.Add(method);
- PhoneCodeHelper.instance().OnBackKeyPressOverriden = true;
- }
- base.TraverseChildren(method);
- }
-
- public void InjectPhoneCodeAssemblies(IEnumerable<IUnit> assemblies) {
- foreach (var a in assemblies) {
- this.Traverse((IAssembly)a);
- }
- }
- }
-}