Moving JSCall to be a separate library from AspNetEdit. AspNetEdit will

be broken for an hour or so.

svn path=/trunk/aspeditor/; revision=62248
This commit is contained in:
Michael Hutchinson 2006-07-04 20:20:36 +00:00
Родитель 7634fd87c2
Коммит 586bfa5b84
11 изменённых файлов: 0 добавлений и 742 удалений

Просмотреть файл

@ -1,230 +0,0 @@
/*
* CommandManager.cs - The C# side of the JSCall Gecko#/C# glue layer
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
using System.Collections;
using Gecko;
using System.Text;
using System.Runtime.InteropServices;
namespace AspNetEdit.JSCall
{
public class CommandManager
{
[DllImport ("jscallglue.dll")]
static extern int PlaceFunctionCall (IntPtr embed,
[MarshalAs(UnmanagedType.LPWStr)] string call,
[MarshalAs(UnmanagedType.LPWStr)] string returnto,
[MarshalAs(UnmanagedType.LPWStr)] string args);
[DllImport ("jscallglue.dll")]
static extern int ExecuteScript (IntPtr embed,
[MarshalAs(UnmanagedType.LPWStr)] string script);
private Hashtable functions = new Hashtable ();
private WebControl webControl;
public CommandManager (WebControl control)
{
if (control == null)
throw new ArgumentNullException ("The Command Manager must be bound to a WebControl instance.", "control");
webControl = control;
webControl.TitleChange += new EventHandler (webControl_ECMAStatus);
}
private void webControl_ECMAStatus (object sender, EventArgs e)
{
if (!webControl.Title.StartsWith ("JSCall"))
return;
string[] call = webControl.Title.Split ((char)234);
if (call.Length < 2)
throw new Exception ("Too few parameters in call from JavaScript.");
string function = call[1];
string returnTo = call[2];
string[] args = (string[]) System.Array.CreateInstance (typeof(String), (call.Length - 3));
System.Array.Copy (call, 3, args, 0, (call.Length - 3));
if (!functions.Contains (function))
throw new Exception ("Unknown function name called from JavaScript.");
ClrCall clrCall = (ClrCall) functions[function];
if (returnTo.Length == 0)
{
clrCall (args);
}
else
{
string[] result = { clrCall (args) };
JSCall(returnTo, null, result);
}
}
public void JSEval (string script)
{
if ((script == null) || (script.Length < 1))
throw new ArgumentNullException ("A null or empty script cannot be executed.", "script");
int result = ExecuteScript (webControl.Handle, script);
string err;
switch (result)
{
case 0:
return;
case 1:
err = "Could not obtain IDOMDocument from GtkMozEmbed. Have you shown the window yet?";
break;
case 2:
err = "Could not create script element.";
break;
case 3:
err = "Could not cast script element to nsIDOMHTMLScriptElement.";
break;
case 4:
err = "Could not locate body element.";
break;
case 5:
err = "Could not append script element to body.";
break;
}
throw new Exception ("Glue function ExecuteScript: " + err);
}
public void JSCall (string function, string returnTo, params string[] args)
{
if ((function==null) || (function.Length < 1))
throw new ArgumentException ("A function name must be specified.", "function");
if (returnTo == null) returnTo = string.Empty;
string argsOut = String.Empty;
if (args != null) {
argsOut += args[0];
for (int i = 1; i <= args.Length - 1; i++) {
argsOut += (char)234 + args[i];
}
}
int result = PlaceFunctionCall (webControl.Handle, function, returnTo, argsOut);
string err;
switch (result)
{
case 0:
return;
case 1:
err = "Could not obtain IDOMDocument from GtkMozEmbed. Have you shown the window yet?";
break;
case 2:
err = "Error finding 'jscall' nodes.";
break;
case 3:
err = "Error getting number of 'jscall' nodes.";
break;
case 4:
err = "More or fewer than one 'jscall' node.";
break;
case 5:
err = "Error getting 'jscall' node.";
break;
case 6:
err = "Error adding 'infunction' node.";
break;
case 7:
err = "Error setting attributes on 'infunction' node.";
break;
case 8:
err = "Error getting nsIDOMNode interface on 'infunction' node.";
break;
case 9:
err = "Error appending 'infunction' node to 'jscall' node.";
break;
default:
err = "The glue wrapper returned an unknown error.";
break;
}
throw new Exception ("Glue function PlaceFunctionCall: "+err);
}
public void RegisterJSHandler (string name, ClrCall handler)
{
if (!functions.Contains (name))
{
functions.Add (name, handler);
}
else
{
throw new Exception ("A handler with this name already exists.");
}
}
public void UnregisterJSHandler (string name)
{
if (functions.Contains (name))
{
functions.Remove (name);
}
else
{
throw new IndexOutOfRangeException ("A function with this name has not been registered.");
}
}
}
public delegate string ClrCall (string[] args);
}

Просмотреть файл

@ -1,47 +0,0 @@
/*
* InvalidJSArgumentException.cs - The exception to be thrown when an argument from a call from JavaScript is invalid
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
using System;
namespace AspNetEdit.JSCall
{
public class InvalidJSArgumentException : Exception
{
public InvalidJSArgumentException (string function, int argument, Exception e)
:base ("Invalid argument " + argument.ToString () + " in JavaScript call to \"" + function + "\".", e)
{
}
public InvalidJSArgumentException (string function, int argument)
:base ("Invalid argument " + argument.ToString () + " in JavaScript call to \"" + function + "\".")
{
}
}
}

Просмотреть файл

@ -1,21 +0,0 @@
//
// AssemblyInfo.cs.in for jscall.dll in aspnetedit
//
// Authors:
// Michael Hutchinson <m.j.hutchinson@gmail.com>
//
using System.Reflection;
using System.Runtime.CompilerServices;
[assembly: AssemblyTitle ("AspNetEdit JSCall")]
[assembly: AssemblyDescription ("JSCall library for AspNetEdit Graphical ASP.NET Editor ")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AspNetEdit")]
[assembly: AssemblyCopyright ("Copyright © 2005 Michael Hutchinson")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyVersion("@VERSION@")]
[assembly: AssemblyFileVersion("@VERSION@")]

Просмотреть файл

@ -1,17 +0,0 @@
2006-06-24 Michael Hutchinson <m.j.hutchinson@gmail.com>
* jscallglue/jscallglue.cpp: Fix build on Gecko 1.8+ browsers. Not a
long-term solution -- need to re-work Mozilla string conversions to use
the new frozen interfaces, but that will break backwards compatibility.
2006-06-14 Michael Hutchinson <m.j.hutchinson@gmail.com>
* AspNetEdit.JSCall/CommandManager.cs: Null input checking to avoid
segfaults, general cleanup.
2006-06-14 Chris Howie <cdhowie@nerdshack.com>
* jscallglue/jscallglue.cpp,
AspNetEdit.JSCall/CommandManager.cs:
Add a method "JSEval" to execute arbitrary JavaScript in the browser.

Просмотреть файл

@ -1,29 +0,0 @@
SUBDIRS = jscallglue
ASSEMBLY_NAME = jscall
ASSEMBLY = $(top_builddir)/build/lib/$(ASSEMBLY_NAME).dll
TARGET = $(ASSEMBLY)
jscalldir=$(pkglibdir)
jscall_SCRIPTS = $(ASSEMBLY)
jscall_DATA = $(ASSEMBLY).mdb
JSCALL_CSFILES = \
$(srcdir)/AssemblyInfo.cs \
$(srcdir)/AspNetEdit.JSCall/CommandManager.cs \
$(srcdir)/AspNetEdit.JSCall/InvalidJSArgumentException.cs
JSCALL_REFERENCES = \
$(GTKSHARP_LIBS) \
$(GECKOSHARP_LIBS)
$(ASSEMBLY): $(JSCALL_CSFILES)
$(MCS) $(MCS_OPTIONS) $(JSCALL_REFERENCES) -debug -target:library -out:$@ $(JSCALL_CSFILES)
$(ASSEMBLY).mdb: $(ASSEMBLY)
all: $(ASSEMBLY)
EXTRA_DIST = $(JSCALL_CSFILES) $(srcdir)/README $(srcdir)/Resources/JSCall.js
CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb

Просмотреть файл

@ -1,25 +0,0 @@
INTRODUCTION
============
This is the AspNetEdit.JSGlue layer for calling C# functions from JavaScript in a Gecko# control, and vice versa. It should work with any .NET language but I've referrred to C# for simplicity. I don't expect many people to use this, so the documentation is little more than minimal; please contact me <m.j.hutchinson@gmail.com> if you need help working out how it works.
BUILDING
========
Use automake (./autogen.sh --prefix=/usr/local) at the application level.
USAGE
=====
On the CLR side of things, create an instance of AspNetEdit.JSGlue.CommandManager by passing the constructor the Gecko# control. This object has the following methods:
RegisterJSHandler(string name, ClrCall handler)
Register a ClrCall delegate as the handler when JS calls the named 'name' function.
UnregisterJSHandler(string name)
Unregister the 'name' function.
JSCall(string function, string returnTo, string[] args)
Call the 'function' JS function, with 'returnTo' as the callback for any return value. Arguments as a string array.
On the JS side, load the JSGlue.js file into your document and call JSGlueInit(). You then have the following functions available, mirroring the C# functions but a bit more "javascripty".
JSGluePlaceClrCall(fn, returnTo, args)
Call the 'fn' C# function, with 'returnTo' as the callback for any return value. Arguments as a string array.
JSGlueRegisterClrHandler(n, fn)
Register a the 'fn' function as the handler when C# calls the named 'n' function.
JSGlueUnregisterClrHandler()
Unregister the 'name' function.

Просмотреть файл

@ -1,122 +0,0 @@
/*
* JSCall.js - The JS side of the JSCall Gecko#/C# glue layer
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var JSCallFunctions;
var delimiter = unescape ("%ea");
function JSCallInit()
{
JSCallFunctions = Array();
if (document.getElementsByTagName("jscall").length == 0) {
el = document.createElement("jscall");
document.documentElement.appendChild(el);
}
if (document.getElementsByTagName("jscall").length != 1) {
throw "Error: the document already contains a <jscall> element";
}
el = document.getElementsByTagName("jscall")[0];
el.addEventListener( "DOMNodeInserted", JSCallHandler, false );
//JSCallRegisterClrHandler("Redo", Redo);
}
//function Redo()
//{
// alert("Yay!");
//}
function JSCallHandler(e)
{
if ( e.target.nodeName == "infunction" && e.target.nodeType == 1 ){
fn = e.target.attributes[0].value;
returnTo = e.target.attributes[1].value;
args = e.target.attributes[2].value.split(delimiter);
try {
if(JSCallFunctions[fn]) {
f = JSCallFunctions[fn];
result = f(args);
}
else {
throw "JSCall: The '"+fn+"' function has not been registered";
}
if (returnTo.length != 0) {
JSCallPlaceClrCall(returnTo, "", new Array(result));
}
}
catch(e) {
alert(e)
}
e.target.parentNode.removeChild(e.target);
}
}
function JSCallPlaceClrCall(fn, returnTo, args) {
str = "JSCall" + delimiter + fn + delimiter + returnTo + delimiter;
if (args && args.length > 0)
{
str += args.join(delimiter);
}
document.title= str;
}
function JSCallUnregisterClrHandler() {
if(JSCallFunctions[n]) {
delete JSCallFunctions[n];
}
else {
throw "Function with that name not registered";
}
}
function JSCallRegisterClrHandler(n, fn) {
if((typeof fn) != "function") {
throw "The fn argument must be a function";
}
if(JSCallFunctions[n]) {
throw "Function with that name already registered";
}
else {
JSCallFunctions[n] = fn;
}
}

Просмотреть файл

@ -1,47 +0,0 @@
<Project name="jscall" fileversion="2.0" newfilesearch="OnLoad" language="C#" clr-version="Net_1_1" ctype="DotNetProject">
<Configurations active="Debug">
<Configuration name="Debug" ctype="DotNetProjectConfiguration">
<Output directory="../../build/lib" assembly="jscall" />
<Build debugmode="True" target="Library" />
<Execution runwithwarnings="True" consolepause="True" runtime="MsNet" clr-version="Net_1_1" />
<CodeGeneration compiler="Csc" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" mainclass="" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
</Configuration>
<Configuration name="Release" ctype="DotNetProjectConfiguration">
<Output directory="../../build/lib" assembly="jscall" />
<Build debugmode="False" target="Library" />
<Execution runwithwarnings="True" consolepause="True" runtime="MsNet" clr-version="Net_1_1" />
<CodeGeneration compiler="Csc" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="True" mainclass="" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
</Configuration>
</Configurations>
<DeploymentInformation strategy="File">
<excludeFiles>
<ExcludeFile file="./AssemblyInfo.cs.in" />
<ExcludeFile file="./ChangeLog" />
<ExcludeFile file="./Resources/ChangeLog" />
<ExcludeFile file="./jscallglue/ChangeLog" />
<ExcludeFile file="./AspNetEdit.JSCall/ChangeLog" />
</excludeFiles>
</DeploymentInformation>
<Contents>
<File name="./AssemblyInfo.cs" subtype="Code" buildaction="Compile" />
<File name="./AssemblyInfo.cs.in" subtype="Code" buildaction="Exclude" />
<File name="./README" subtype="Code" buildaction="Exclude" />
<File name="./AspNetEdit.JSCall/CommandManager.cs" subtype="Code" buildaction="Compile" />
<File name="./AspNetEdit.JSCall/InvalidJSArgumentException.cs" subtype="Code" buildaction="Compile" />
<File name="./Resources/JSCall.js" subtype="Code" buildaction="Exclude" />
<File name="./jscallglue/README" subtype="Code" buildaction="Exclude" />
<File name="./jscallglue/jscallglue.cpp" subtype="Code" buildaction="Exclude" />
<File name="./ChangeLog" subtype="Code" buildaction="Exclude" />
<File name="./AspNetEdit.JSCall/ChangeLog" subtype="Code" buildaction="Exclude" />
<File name="./Resources/ChangeLog" subtype="Code" buildaction="Exclude" />
<File name="./jscallglue/ChangeLog" subtype="Code" buildaction="Exclude" />
</Contents>
<References>
<ProjectReference type="Gac" localcopy="True" refto="System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<ProjectReference type="Gac" localcopy="True" refto="gtk-sharp, Version=2.6.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<ProjectReference type="Gac" localcopy="True" refto="glib-sharp, Version=2.6.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.6.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<ProjectReference type="Gac" localcopy="True" refto="gecko-sharp, Version=2.0.0.0, Culture=neutral, PublicKeyToken=ccf7d78a55e9f021" />
<ProjectReference type="Gac" localcopy="True" refto="atk-sharp, Version=2.6.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
</References>
</Project>

Просмотреть файл

@ -1,16 +0,0 @@
jscallgluedir=$(pkglibdir)
dllfile = $(top_builddir)/build/lib/libjscallglue.dll.so
jscallglue_SCRIPTS = $(dllfile)
CXXFLAGS = -shared -g -fPIC -fno-rtti $(JSGLUEDEPS_CFLAGS)
LDFLAGS = $(JSGLUEDEPS_CFLAGS)
all: $(dllfile)
$(dllfile): jscallglue.cpp
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
CLEANFILES = $(dllfile)
EXTRA_DIST = README

Просмотреть файл

@ -1,22 +0,0 @@
The AspNetEdit XPCOM DOM Wrappers
=================================
A word of warning - this is a bit hacky, but will have to do until someone comes up with an XPConnect interface for Mono. The aim for now is to use a minimum of Gtk and XPCOM interop code to reuse existing components and simplify debugging.
We have two functions, PlaceFunctionCall and CollectFunctionCall. The document must contain a single node in the root called <aspnetcomm>, which contains the data to be communicated between C# and JavaScript, and these functions modify and read its contents.
The mechanism of invoking a C# method from JavaScript is as follows:
1. A JavaScript function representing the C# method is called. If it has a return value, it registers a callback function with a handler.
2. It calls a helper function that puts the data in the <aspnetcomm> node and sets the window 'status'. As Gecko# has no status bar this misuse doesn't adversely affect anything and is not visible to the user.
3. The modified Gecko# control catches the ECMAStatus event that is raised, reads and deletes the function call from the DOM using CollectFunctionCall, and calls the relevant C# method.
4. If there is a return value, a callback is placed in the reverse direction.
The reverse call is simple too:
1. A C# method of the modified Gecko# control representing a JavaScript function is called, and it writes to the DOM using PlaceFunctionCall. If it has a return value, it registers a callback delegate with a handler.
2. This raises the DOMNodeInserted event in JavaScript, which is caught by a handler.
3. The handler passes the arguments to the appropriate function.
4. If there is a return value, a callback is placed in the reverse direction.
Outbound (JS->C#) method calls are represented as a child of <aspnetcomm>, and are of the following form:
<outfunction call="functionName" args="encodedListOfArguments" >
Inbound calls are of the form:
<infunction call="functionName" args="encodedListOfArguments" >

Просмотреть файл

@ -1,166 +0,0 @@
/*
* jscallglue.cpp - XPCOM DOM interop for communication between JavaScript and Mono/Gecko#
*
* Authors:
* Michael Hutchinson <m.j.hutchinson@gmail.com>
*
* Copyright (C) 2005 Michael Hutchinson
*
* This sourcecode is licenced under The MIT License:
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit
* persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
* NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
//FIXME: uses internal string functions, so have to define this in newer Mozillas
//But we can only migrate to nsStringAPI.h in FF1.5/Mozilla 1.7+
#define MOZILLA_INTERNAL_API
#include <gtkmozembed.h>
#include <gtkmozembed_internal.h>
#include <nsCOMPtr.h>
#include <nsString.h>
#include <nsIWebBrowser.h>
#include <nsIDOMWindow.h>
#include <nsIDOMDocument.h>
#include <nsIDOMElement.h>
#include <nsIDOMNode.h>
#include <nsIDOMNodeList.h>
#include <nsIDOMHTMLScriptElement.h>
extern "C"
{
int PlaceFunctionCall(GtkMozEmbed *embed, const PRUnichar *call, const PRUnichar *returnto, const PRUnichar *args);
int ExecuteScript(GtkMozEmbed *embed, const PRUnichar *script);
}
/*
Gets the browser's IDomDocument.
*/
nsCOMPtr<nsIDOMDocument> GetIDOMDocument(GtkMozEmbed *embed)
{
//Get browser
nsCOMPtr<nsIWebBrowser> browser;
gtk_moz_embed_get_nsIWebBrowser(embed, getter_AddRefs(browser));
if(!browser) return NULL;
nsCOMPtr<nsIDOMWindow> domWindow;
browser->GetContentDOMWindow(getter_AddRefs(domWindow));
nsCOMPtr<nsIDOMDocument> domDocument;
domWindow->GetDocument(getter_AddRefs(domDocument));
return domDocument;
}
/*
Places a <outfunction call="..." args="..." returnto="..." />
function call element in the <jscall> element.
*/
int PlaceFunctionCall(GtkMozEmbed *embed, const PRUnichar *call, const PRUnichar *returnto, const PRUnichar *args)
{
nsresult result;
nsCOMPtr<nsIDOMDocument> doc = GetIDOMDocument(embed);
if(doc == NULL) return 1;
//get the "jscall" node
nsCOMPtr<nsIDOMNodeList> nodes;
result = doc->GetElementsByTagName(NS_ConvertUTF8toUTF16("jscall"), getter_AddRefs(nodes));
if(NS_FAILED(result) || !nodes) return 2;
PRUint32 length = 0;
result = nodes -> GetLength(&length);
if(NS_FAILED(result)) return 3;
if(length != 1) return 4;
nsCOMPtr<nsIDOMNode> jscall;
result = nodes->Item(0, getter_AddRefs(jscall));
if(NS_FAILED(result) || !jscall) return 5;
//add an "infunction" node
nsCOMPtr<nsIDOMElement> infunction;
result = doc->CreateElement(NS_ConvertUTF8toUTF16("infunction"), getter_AddRefs(infunction));
if(NS_FAILED(result) || !infunction) return 6;
//add the properties
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("call"), nsDependentString(call));
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("returnto"), nsDependentString(returnto));
result = infunction->SetAttribute(NS_ConvertUTF8toUTF16("args"), nsDependentString(args));
if(NS_FAILED(result)) return 7;
//append it to the jscall node
nsCOMPtr<nsIDOMNode> domNodeInfunction = do_QueryInterface(infunction);
if(!domNodeInfunction) return 8;
nsCOMPtr<nsIDOMNode> outchild;
result = jscall->AppendChild(domNodeInfunction, getter_AddRefs(outchild));
if(NS_FAILED(result) || !jscall) return 9;
return 0;
}
// Inspiration from
// http://kmeleon.cvs.sourceforge.net/kmeleon/k-meleon/BrowserViewUtils.cpp?revision=1.53&view=markup
int ExecuteScript(GtkMozEmbed *embed, const PRUnichar *script)
{
nsresult result;
nsCOMPtr<nsIDOMDocument> doc = GetIDOMDocument(embed);
if (doc == NULL)
return 1;
// Create the script node
nsCOMPtr<nsIDOMElement> scriptDOMElement;
result = doc->CreateElement(NS_ConvertUTF8toUTF16("script"), getter_AddRefs(scriptDOMElement));
if (NS_FAILED(result) || !scriptDOMElement)
return 2;
// and the content
nsCOMPtr<nsIDOMHTMLScriptElement> scriptE = do_QueryInterface(scriptDOMElement);
if (!scriptE)
return 3;
scriptE->SetText(nsDependentString(script));
scriptE->SetType(NS_ConvertUTF8toUTF16("text/javascript"));
// find the body node.
nsCOMPtr<nsIDOMElement> body;
result = doc->GetDocumentElement(getter_AddRefs(body));
if (NS_FAILED(result) || !body)
return 4;
// add the element to the body
nsCOMPtr<nsIDOMNode> unused;
result = body->AppendChild(scriptE, getter_AddRefs(unused));
if (NS_FAILED(result))
return 5;
// gecko has executed the element, we can remove it now
result = body->RemoveChild(scriptE, getter_AddRefs(unused));
return 0;
}