Domanda

I have a webbrowser made using webkit running in mono c#. I would like to allow pages to call a function in the browser and then the browser perform actions based on the parameters passed. I cant seem to be able to do it.

The html page is the next one

<html>
<head>
<title>ola</title>
</head>
<body>
<button onclick="window.external.Test('called from script code');">test</button>
</body>
</html>

The webkit.cs

using System;
using System.Collections;
using System.Runtime.InteropServices;
using Gtk;
using GLib;

namespace WebKit
{
 class DOMDocument : GLib.Object
 {
  public DOMDocument (IntPtr raw) : base (raw) {}

  [DllImport ("webkit-1.0")]
  private static extern IntPtr webkit_dom_document_get_elements_by_tag_name (IntPtr raw, IntPtr str1ng);

  public DOMNodeList get_elements_by_tag_name (string tag)
  {
   IntPtr intPtr = Marshaller.StringToPtrGStrdup (tag);
   IntPtr result = webkit_dom_document_get_elements_by_tag_name(base.Handle, intPtr);
   Marshaller.Free (intPtr);
   return new DOMNodeList(result);
  }
 }

 // http://www.opensource.apple.com/source/WebKit/WebKit-7533.16/gtk/tests/testdomdocument.c
 class DOMNodeList: GLib.Object, IEnumerable
 {
  public DOMNodeList (IntPtr raw) : base (raw) {}

  [DllImport ("webkit-1.0")]
  private static extern IntPtr webkit_dom_node_list_item (IntPtr raw, int element);

  [DllImport ("webkit-1.0")]
  private static extern int webkit_dom_node_list_get_length (IntPtr raw);

  public IEnumerator GetEnumerator ()
  {
   for (int i = 0; i < webkit_dom_node_list_get_length(base.Handle); i++) {
    yield return new DOMNode(webkit_dom_node_list_item(base.Handle, i));
   }
  }
 }

 class DOMNode : GLib.Object
 {
  public DOMNode (IntPtr raw) : base (raw) {}


 }

 class DOMElement : GLib.Object
 {
  public DOMElement (IntPtr raw) : base (raw) {}


 }

 class DOMHTMLElement : GLib.Object
 {
  public DOMHTMLElement (IntPtr raw) : base (raw) {}

  [DllImport ("webkit-1.0")]
  private static extern IntPtr webkit_dom_html_element_get_inner_text(IntPtr raw);

  public string get_inner_text ()
  {
   IntPtr data = webkit_dom_html_element_get_inner_text(base.Handle);
   return Marshaller.PtrToStringGFree(data);
  }
 }

 class ExtendedWebSettings : WebKit.WebSettings {
  public void g_object_set(string name, GLib.Value value) {
   SetProperty(name, value);
  }

  public GLib.Value g_object_get(string name) {
   return GetProperty(name);
  }
 }

 class ExtendedWebView : WebKit.WebView {
  [DllImport ("webkit-1.0")]
  private static extern IntPtr webkit_web_view_get_dom_document (IntPtr raw);

  public DOMDocument get_dom_document()
  {
   return new DOMDocument(webkit_web_view_get_dom_document(base.Handle));
  }

  public event CreateWebViewHandler CreateWebView
  {
   add
   {
    Signal signal = Signal.Lookup (this, "create-web-view", typeof(CreateWebViewArgs));
    signal.AddDelegate (value);
   }
   remove
   {
    Signal signal = Signal.Lookup (this, "create-web-view", typeof(CreateWebViewArgs));
    signal.RemoveDelegate (value);
   }
  }

  public event WebViewReadyHandler WebViewReady
  {
   add
   {
    Signal signal = Signal.Lookup (this, "web-view-ready", typeof(WebViewReadyArgs));
    signal.AddDelegate (value);
   }
   remove
   {
    Signal signal = Signal.Lookup (this, "web-view-ready", typeof(WebViewReadyArgs));
    signal.RemoveDelegate (value);
   }
  }

  public event NewWindowPolicyDecisionRequestedHandler NewWindowPolicyDecisionRequested
  {
   add
   {
    Signal signal = Signal.Lookup (this, "new-window-policy-decision-requested", typeof(NewWindowPolicyDecisionRequestedArgs));
    signal.AddDelegate (value);
   }
   remove
   {
    Signal signal = Signal.Lookup (this, "new-window-policy-decision-requested", typeof(NewWindowPolicyDecisionRequestedArgs));
    signal.RemoveDelegate (value);
   }
  }

  [DefaultSignalHandler (Type = typeof(WebView), ConnectionMethod = "OverrideCreateWebView")]
  protected virtual WebView OnCreateWebView (WebFrame frame)
  {
   ExtendedWebView webView = new ExtendedWebView();
   Value empty = Value.Empty;
   ValueArray valueArray = new ValueArray (2u);
   Value[] array = new Value[2];
   array [0] = new Value (this);
   valueArray.Append (array [0]);
   array [1] = new Value (frame);
   valueArray.Append (array [1]);
   GLib.Object.g_signal_chain_from_overridden (valueArray.ArrayPtr, ref empty);
   Value[] array2 = array;
   for (int i = 0; i < array2.Length; i++)
   {
    Value value = array2 [i];
    value.Dispose ();
   }
   return webView;
  }

  [DefaultSignalHandler (Type = typeof(WebView), ConnectionMethod = "OverrideNewWindowPolicyDecisionRequested")]
  protected virtual int OnNewWindowPolicyDecisionRequested (WebFrame frame, NetworkRequest request, WebNavigationAction navigation_action, WebPolicyDecision policy_decision)
  {
   Value val = new Value (GType.Int);
   ValueArray valueArray = new ValueArray (3u);
   Value[] array = new Value[5];
   array [0] = new Value (this);
   valueArray.Append (array [0]);
   array [1] = new Value (frame);
   valueArray.Append (array [1]);
   array [2] = new Value (request);
   valueArray.Append (array [2]);
   array [3] = new Value (navigation_action);
   valueArray.Append (array [3]);
   array [4] = new Value (policy_decision);
   valueArray.Append (array [4]);
   GLib.Object.g_signal_chain_from_overridden (valueArray.ArrayPtr, ref val);
   Value[] array2 = array;
   for (int i = 0; i < array2.Length; i++)
   {
    Value value = array2 [i];
    value.Dispose ();
   }
   int result = (int)val;
   val.Dispose ();
   return result;
  }

  [DefaultSignalHandler (Type = typeof(WebView), ConnectionMethod = "OverrideWebViewReady")]
  protected virtual bool OnWebViewReady (WebFrame frame)
  {
   Value empty = Value.Empty;
   ValueArray valueArray = new ValueArray (2u);
   Value[] array = new Value[2];
   array [0] = new Value (this);
   valueArray.Append (array [0]);
   array [1] = new Value (frame);
   valueArray.Append (array [1]);
   GLib.Object.g_signal_chain_from_overridden (valueArray.ArrayPtr, ref empty);
   Value[] array2 = array;
   for (int i = 0; i < array2.Length; i++)
   {
    Value value = array2 [i];
    value.Dispose ();
   }
   return true;
  }
 }

 public delegate void WebViewReadyHandler (object o, WebViewReadyArgs args);

 public class WebViewReadyArgs : SignalArgs
 {
  //
  // Properties
  //

  public WebFrame Frame
  {
   get
   {
    return (WebFrame)base.Args [0];
   }
  }
 }

 public delegate void CreateWebViewHandler (object o, CreateWebViewArgs args);

 public class CreateWebViewArgs : SignalArgs
 {
  //
  // Properties
  //

  public WebFrame Frame
  {
   get
   {
    return (WebFrame)base.Args [0];
   }
  }
 }

 public delegate void NewWindowPolicyDecisionRequestedHandler (object o, NewWindowPolicyDecisionRequestedArgs args);

 public class NewWindowPolicyDecisionRequestedArgs : SignalArgs
 {
  //
  // Properties
  //

  public WebFrame Frame
  {
   get
   {
    return (WebFrame)base.Args [0];
   }
  }

  public NetworkRequest Request
  {
   get
   {
    return (NetworkRequest)base.Args [1];
   }
  }

  public WebNavigationAction NavigationAction
  {
   get
   {
    return (WebNavigationAction)base.Args [2];
   }
  }

  public WebPolicyDecision PolicyDecision
  {
   get
   {
    return (WebPolicyDecision)base.Args [3];
   }
  }
 }

}

and the Main.cs

using System;
using Gtk;
using GLib;
using WebKit;
using System.Timers;
//using Notifications;
using System.Text.RegularExpressions;

public partial class MainWindow: Gtk.Window
{
  private Timer notifications = new Timer(2000);
  private ExtendedWebView webView;
  private bool recent_notification = false;

  public MainWindow (string url): base (Gtk.WindowType.Toplevel)
  {
    Build ();
    url ="http://127.0.0.1/csharp/";
    webView = new ExtendedWebView ();
    ExtendedWebSettings settings = new ExtendedWebSettings ();
    settings.g_object_set ("user-agent", new GLib.Value ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:24.0) Gecko/20100101 Firefox/24.0"));
    settings.g_object_set ("enable-spell-checking", new GLib.Value (true));
    webView.TitleChanged += HandleTitleChanged;
    webView.Settings = settings;
    webView.NewWindowPolicyDecisionRequested += HandleNewWindowPolicyDecisionRequested;
    webView.CreateWebView += HandleCreateWebView;
    webView.Open(url);
    webView.LoadFinished += new LoadFinishedHandler (OnLoadFinished);
    VBox vbox1 = new VBox();
    vbox1.PackStart(webView);
    this.Add(vbox1);
    this.ShowAll();
  }

  private void OnLoadFinished (object o, LoadFinishedArgs args)
  {
    String testVar = "[ { \"id\" : \"4578\" },{ \"id\" : \"4579\" }]";
    Console.WriteLine("Executei isto por aqui....");
    webView.ExecuteScript("scriptTeste(" + testVar + ");");
    Console.WriteLine("Executei isto por aqui....");
  }


  void HandleCreateWebView (object o, CreateWebViewArgs args)
  {
    Window info = new Window("");
    info.DefaultWidth = 1000;
    info.DefaultHeight = 700;
    VBox vbox2 = new VBox();
    WebView child = new WebView();
    child.NavigationRequested += HandleNavigationRequested1;
    vbox2.PackStart(child);
    info.Add (vbox2);
    info.ShowAll();
    args.RetVal = child;
  }

  void HandleNavigationRequested1 (object o, NavigationRequestedArgs args)
  {
    // Destroy the window if it was already opened in the browser
    if (args.Request.Uri.Contains ("&URL=")) {
      WebView self = (WebView)o;
      VBox container = (VBox)self.Parent;
      Window parent = (Window)container.Parent;
      parent.Destroy();
      args.RetVal = 1;
    }
  }

  void HandleNewWindowPolicyDecisionRequested (object o, NewWindowPolicyDecisionRequestedArgs args)
  {
    string URL = System.Web.HttpUtility.UrlDecode(Regex.Split(args.Request.Uri, "&URL=")[1]);
    System.Diagnostics.Process.Start(URL);
  }

  void HandleElapsed (object sender, ElapsedEventArgs e)
  {
    if (recent_notification) {
      notifications.Interval = 5000;
      recent_notification = false;
    }
  /*  if (!recent_notification && webView.SearchText ("Reminders", true, true, true)) {
      Notification notify = new Notification ("Outlook Notification", "");
      notify.Urgency = Urgency.Normal;
      notify.Show ();
      recent_notification = true;
      notifications.Interval = 30000;

    }*/
  }

  void HandleTitleChanged (object o, TitleChangedArgs args)
  {
    this.Title = args.Title;
  }


  protected void OnDeleteEvent (object sender, DeleteEventArgs a)
  {
    Application.Quit ();
    a.RetVal = true;
  }
}

If you want the c# project it is here https://github.com/dmulder/owa_browse/

Thanks in advance.

È stato utile?

Soluzione

You need to derive a new webview class from your old one, and override:

public class MyDerived: WebView
{
...

    public const string COM_COMMAND_INIT = "http://mypresetcommand/?";
    protected override void OnResourceRequestStarting(WebKit.WebFrame web_frame, WebKit.WebResource web_resource, WebKit.NetworkRequest request, WebKit.NetworkResponse response)
    {
        // check if this is a command
        if (request.Uri.ToLower().StartsWith(COM_COMMAND_INIT))
        {
            // this is a com command. Responding with responce.
            string cmnd = web_resource.Uri.Substring(COM_COMMAND_INIT.Length);
            // HANDLE COMMAND HERE.
            return;
        }
        base.OnResourceRequestStarting(web_frame, web_resource, request, response);
    }
}

Once you have done this, you can simply do an ajax call to the C# application from within the webpage. Replace "myresetcommand/?" with your own unreacheable url. You can respond via ExecuteScript in the WebView.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top