title: Partial Trust JavaScript Object Access in XBAP via HostScript: SecurityException in Callbacks
body: <p>I've encountered a problem with the XBAP Script Interop feature that was added in WPF 4. It involves a combination of the following:</p>
  
  <ol>
  <li>Accessing members of a script object from .NET</li>
  <li>Running .NET code in a callback invoked from JavaScript</li>
  <li>Running in Partial trust</li>
  </ol>
  
  <p>This seems to be a "pick any two" scenario... If I try and do all three of those things, I get a <code>SecurityException</code>.</p>
  
  <p>For example, combining 1 and 3 is easy. I can put this into my hosting web page's script:</p>
  
  <pre><code>function ReturnSomething()
  {
      return { Foo: "Hello", Bar: 42 };
  }
  </code></pre>
  
  <p>And then in, say, a button click handler in my WPF code behind, I can do this:</p>
  
  <pre><code>dynamic script = BrowserInteropHelper.HostScript;
  if (script != null)
  {
      dynamic result = script.ReturnSomething();
      string foo = result.Foo;
      int bar = result.Bar;
      // go on to do something useful with foo and bar...
  }
  </code></pre>
  
  <p>That works fine, even in a partial trust deployment. (I'm using the default ClickOnce security settings offered by the WPF Browser Application template in Visual Studio 2010, which debugs the XBAP as though it were running in the Internet zone.) So far, so good.</p>
  
  <p>I can also combine 2 and 3. To make my .NET method callable from JavaScript, sadly we can't just pass a delegate, we have to do this:</p>
  
  <pre><code>[ComVisible(true)]
  public class CallbackClass
  {
      public string MyMethod(int arg)
      {
          return "Value: " + arg;
      }
  }
  </code></pre>
  
  <p>and then I can declare a JavaScript method that looks like this:</p>
  
  <pre><code>function CallMethod(obj)
  {
      var result = obj.MyMethod(42);
      var myElement = document.getElementById("myElement");
      myElement.innerText = "Result: " + result;
  }
  </code></pre>
  
  <p>and now in, say, a WPF button click handler, I can do this:</p>
  
  <pre><code>script.CallMethod(new CallbackClass());
  </code></pre>
  
  <p>So my WPF code calls (via <code>BrowserInteropHelper.HostScript</code>) my JavaScript <code>CallMethod</code> function, which in turn calls my .NET code back - specifically, it calls the <code>MyMethod</code> method exposed by my CallbackClass. (Or I could mark the callback method as a default method with a <code>[DispId(0)]</code> attribute, which would let me simplify the JavaScript code - the script could treat the argument itself as a method. Either approach yields the same results.)</p>
  
  <p>The <code>MyMethod</code> callback is successfully called. I can see in the debugger that the argument passed from JavaScript (42) is getting through correctly (having been properly coerced to an int). And when my method returns, the string that it returns ends up in my HTML UI thanks to the rest of the <code>CallMethod</code> function.</p>
  
  <p>Great - so we can do 2 and 3.</p>
  
  <p>But what about combining all three? I want to modify my callback class so that it can work with script objects just like the one returned by my first snippet, the <code>ReturnSomething</code> function. We know that it's perfectly possible to work with such objects because that first example succeded. So you'd think I could do this:</p>
  
  <pre><code>[ComVisible(true)]
  public class CallbackClass
  {
      public string MyMethod(dynamic arg)
      {
          return "Foo: " + arg.Foo + ", Bar: " + arg.Bar;
      }
  }
  </code></pre>
  
  <p>and then modify my JavaScript to look like this:</p>
  
  <pre><code>function CallMethod(obj)
  {
      var result = obj.MyMethod({ Foo: "Hello", Bar: 42 });
      var myElement = document.getElementById("myElement");
      myElement.innerText = "Result: " + result;
  }
  </code></pre>
  
  <p>and then call the method from my WPF button click handler as before:</p>
  
  <pre><code>script.CallMethod(new CallbackClass());
  </code></pre>
  
  <p>this successfully calls the JavaScript <code>CallMethod</code> function, which successfully calls back the <code>MyMethod</code> C# method, but when that method attempts to retrieve the <code>arg.Foo</code> property, I get a <code>SecurityException</code> with a message of <code>RequestFailed</code>. Here's the call stack:</p>
  
  <pre><code>at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark&amp; stackMark, Boolean isPermSet)
  at System.Security.CodeAccessSecurityEngine.Check(PermissionSet permSet, StackCrawlMark&amp; stackMark)
  at System.Security.PermissionSet.Demand()
  at System.Dynamic.ComBinder.TryBindGetMember(GetMemberBinder binder, DynamicMetaObject instance, DynamicMetaObject&amp; result, Boolean delayInvocation)
  at Microsoft.CSharp.RuntimeBinder.CSharpGetMemberBinder.FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
  at System.Dynamic.DynamicMetaObject.BindGetMember(GetMemberBinder binder)
  at System.Dynamic.GetMemberBinder.Bind(DynamicMetaObject target, DynamicMetaObject[] args)
  at System.Dynamic.DynamicMetaObjectBinder.Bind(Object[] args, ReadOnlyCollection`1 parameters, LabelTarget returnLabel)
  at System.Runtime.CompilerServices.CallSiteBinder.BindCore[T](CallSite`1 site, Object[] args)
  at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
  at XBapDemo.CallbackClass.MyMethod(Object arg)
  </code></pre>
  
  <p>That's the whole trace as reported by the exception. And above <code>CallbackClass.MyMethod</code>, Visual Studio is showing two lots of [Native to Managed Transition] and an [AppDomain Transition] - so that's the whole of the stack. (Apparently we're on a different thread now. This callback is happening on what the Threads panel describes as a Worker Thread - I can see that the Main Thread is still sat inside my WPF button click handler, waiting for the call to the JavaScript <code>CallMethod</code> function to return.)</p>
  
  <p>Apparently the problem is that the DLR has ended up wrapping the JavaScript object in the <code>ComBinder</code> which demands full trust. But in the earlier case where I called a JavaScript method via <code>HostScript</code> and it returned me an object, the <code>HostScript</code> wrapped it in a <code>System.Windows.Interop.DynamicScriptObject</code> for me.</p>
  
  <p>The <code>DynamicScriptObject</code> class is specific to WPFs XBAP script interop - it's not part of the usual DLR types, and it's defined in <code>PresentationFramework.dll</code>. As far as I can tell, one of the jobs it does is to make it possible to use C#'s <code>dynamic</code> keyword to access JavaScript properties without needing full trust, even though those properties are being accessed through COM interop (which usually requires full trust) under the covers.</p>
  
  <p>As far as I can tell, the problem is that you only get these <code>DynamicScriptObject</code> wrappers for objects that are returned from other <code>DynamicScriptObject</code> instances (such as <code>HostScript</code>). With callbacks, that wrapping doesn't seem to occur. In my callback, I'm getting the sort of dynamic wrapper C# would normally give me in plain old COM interop scenarios, at which point, it demands that I have full trust.</p>
  
  <p>Running it with full trust works fine - that would be the "1 and 2" combination from the list above. But I don't want to have full trust. (I want 1, 2, <em>and</em> 3.) And outside of callback situations, I can access JavaScript object members just fine. It seems inconsistent that I can access a JavaScript object just fine most of the time, but accessing an identical object in a callback is forbidden.</p>
  
  <p>Is there a way around this? Or am I doomed to run my code in full trust if I want to do anything interesting in a callback?</p>