Cannot load html from localhost in Awesomium.Net + XNA

845 views Asked by At

I am writing a game in XNA which is using Awesomium webviews as the UI. The webviews are rendered to Texture2D using this class.

It works great using local html files, but I also need to use some XML and Awesomium does not seem to allow for this (setting FileAccessFromFileURL and WebSecurity to false does nothing). My solution was to host my HTML/XML UI on a local web server, used this class for the server.

The web server is running fine and accessible from my browser but I get blank windows when I set my webview sources to http://localhost:8023/myindex.html. I do not get this output when I access localhost using the Awesomium WPF control, nor do I get it when I host the html remotely. This makes me think the issue is caused by how my class is handling URI's.

    public struct AwesomiumMenu
{
    public WebView webView;
    public Microsoft.Xna.Framework.Rectangle Rectangle;

    public AwesomiumMenu(string Source, Microsoft.Xna.Framework.Rectangle rectangle)
    {
        // WebPreferences to disable same-origin policy so we can load local XML + remove scrollbars
        const string SCROLLBAR_CSS = "::-webkit-scrollbar { visibility: hidden; }";
        WebSession session = WebCore.CreateWebSession(new WebPreferences()
        {
            CustomCSS = SCROLLBAR_CSS,
            UniversalAccessFromFileURL = true,
            FileAccessFromFileURL = true,
            WebSecurity = false
        });

        //// CSS styling
        //const string SCROLLBAR_CSS = "::-webkit-scrollbar { visibility: hidden; }";
        //WebCore.Initialize(new WebConfig()
        //{
        //    CustomCSS = SCROLLBAR_CSS
        //});

        webView = WebCore.CreateWebView(rectangle.Width, rectangle.Height, session);
        webView.Source = Source.ToUri();
        Console.WriteLine(webView.Source);
        webView.IsTransparent = true;

        while (webView.IsLoading)
            WebCore.Update();
2

There are 2 answers

0
voytek On

I use mongoose as my local server - very easy to use. I did simplest test application I could, and it works for me. Here is the entire code:

public partial class Form1 : Form
{
    private Awesomium.Windows.Forms.WebControl webControl1;

    public Form1()
    {
        if (!WebCore.IsInitialized)
        {
            WebCore.Initialize(new WebConfig(), true);
        }

        InitializeComponent();

        this.webControl1.Dock = System.Windows.Forms.DockStyle.Fill;
        this.webControl1.Location = new System.Drawing.Point(0, 0);
        this.webControl1.Size = new System.Drawing.Size(1134, 681);
        this.webControl1.TabIndex = 0;

        this.webControl1.WebSession = WebCore.CreateWebSession("%APPDATA%\\Test", new WebPreferences
        {
            CustomCSS = "body { overflow:hidden; }",
            WebSecurity = false,
            DefaultEncoding = "UTF-8",
        });

        this.webControl1.Source = new Uri("http://localhost:8080/Test/test.html");
    }
}
2
Not Important On

Since you are doing an XNA game, why don't embed your interface as resources in a DLL files? this is what i've done for my game and it works fine

In my game I've an interface loaded from a DLL and by design i prevent url navigation outside of my context (no external url navigation).

To achieve this, I've implemented a DataSource class that on the OnRequest call, load the resource from the dll, here it is (a bit optimized and right extracted from my project, but you should understand it)

class SampleDataSource : DataSource {
     Assembly InterfaceAssembly;
     string[] names;

     public SampleDataSource() {
        InterfaceAssembly = typeof(Interface.HTMLInterface).Assembly;

        // Get the names of all the resources in the assembly
        names = InterfaceAssembly.GetManifestResourceNames();
        Array.Sort(names, CaseInsensitiveComparer.Default);
     }

     protected override void OnRequest(DataSourceRequest request) {
        var response = new DataSourceResponse();

        string[] parts = request.Path.Replace("\\", "/").Split('/');

        for (int i = 0; i < parts.Length - 1; i++) {
           parts[i] = parts[i].Replace(".", "_").Replace("-", "_");
        }

        string resourcePath = "Interface.html." + request.Path
           //.Replace(".", "_")
           .Replace("/", ".")
           .Replace("\\", ".");

        resourcePath = "Interface.html." + String.Join(".", parts);


        // Find the image in the names array
        int pos = Array.BinarySearch(names, resourcePath, CaseInsensitiveComparer.Default);

        if (pos > -1) {
           resourcePath = names[pos];
        }

        byte[] data = null;
        using (Stream stream = InterfaceAssembly.GetManifestResourceStream(resourcePath)) {
           data = new byte[stream.Length];
           stream.Read(data, 0, data.Length);
        }

        IntPtr unmanagedPointer = IntPtr.Zero;
        try {
           unmanagedPointer = Marshal.AllocHGlobal(data.Length);
           Marshal.Copy(data, 0, unmanagedPointer, data.Length);

           response.Buffer = unmanagedPointer;

           switch (System.IO.Path.GetExtension(request.Path).ToLower()) {
              case ".html":
              case ".htm":
                 response.MimeType = "text/html";
                 break;
              case ".js":
                 response.MimeType = "application/javascript";
                 break;
              case ".css":
                 response.MimeType = "text/css";
                 break;
              case ".png":
                 response.MimeType = "image/png";
                 break;
              case ".jpeg":
              case ".jpg":
                 response.MimeType = "image/jpeg";
                 break;
              default:
                 response.MimeType = "text/html";
                 break;
           }

           response.Size = (uint)data.Length;
           SendResponse(request, response);
        }
        catch (Exception e) {
           throw e;
        }
        finally {
           Marshal.FreeHGlobal(unmanagedPointer);
        }
     }
  }

you can find informations about DataSource on the official documentation docs.awesomium.net

anyway this is how i link the datasource to my webview:

WebView.WebSession.AddDataSource("sample", new SampleDataSource());