Access JavaScript functions in WebGadget on Linux
Posted: Sat Jan 10, 2009 3:27 am
After many hours digging through XPCOM, C++ function mangling and blasphemously undocumented Mozilla functions - I finally have a working ExecuteJavaScript() hack for the Linux WebGadget. Although it doesn't use XPCOM or any magic, or for that matter even play with the gtk_moz_embed_*_() API functions. In theory it could be completely cross platform, in practice the win32 IWebBrowser2 object doesn't get the change to the document title until after a return to the programs event loop. Somebody let me know if it works on Mac?
Identical interface as Freak's win32 library, except this one adds an optional timeout value in case the function never returns. This is necessary to prevent lock-ups if an unforseen error occurs and the title never changes.
Actually, the example given is a prompt() function, which happens to be one of the only things that doesn't work well (modal dialogs.)
Cheers.
Identical interface as Freak's win32 library, except this one adds an optional timeout value in case the function never returns. This is necessary to prevent lock-ups if an unforseen error occurs and the title never changes.
Code: Select all
; Linux PB 4.30
; Tested on Slackware 11
Prototype.s ProtoExecuteJavaScript(gadget, Function$, Arguments$, Separator$, timeout=5000)
JSMutex = CreateMutex()
Procedure.s JavaScriptQuote(code.s)
code = ReplaceString(code, "\", "\\")
code = ReplaceString(code, Chr(34), "\"+Chr(34))
ProcedureReturn Chr(34)+code+Chr(34)
EndProcedure
Procedure.l JavaScriptResetTitle(gadget.l)
Shared JSMutex
LockMutex(JSMutex)
SetGadgetText(gadget, "javascript:void(function(){document.title='';})();")
UnlockMutex(JSMutex)
EndProcedure
Procedure JavaScriptExamineThread(gadget.l)
title.s = ""
Repeat
title = GetGadgetItemText(gadget, #PB_Web_PageTitle)
If title = ""
Delay(100)
EndIf
Until title > ""
EndProcedure
Procedure.s ProcExecuteJavaScript(gadget, Function$, Arguments$, Separator$, timeout)
Shared JSMutex
If GadgetType(gadget) <> #PB_GadgetType_Web
ProcedureReturn ""
EndIf
code.s = ""
If Trim(Arguments$) = ""
code = ""
ElseIf Seperator$ = ""
code = JavaScriptQuote(Arguments$)
Else
Count = CountString(Arguments$, Separator$)+1
For i = 1 To Count
code = code + JavaScriptQuote(StringField(Arguments$, i, Separator$))
If i <> Count
code = code + ","
EndIf
Next i
EndIf
code = Function$+"("+code+");"
JavaScriptResetTitle(gadget)
LockMutex(JSMutex)
code = JavaScriptQuote(code)
js.s = "javascript:void(function(){document.title='';try{var ret = eval("+code
js = js + ");document.title=ret;}catch(e){document.title='exception: '+e;}})();"
SetGadgetText(gadget, js)
thread = CreateThread(@JavaScriptExamineThread(), gadget)
If thread <> 0
WaitThread(thread, timeout)
EndIf
UnlockMutex(JSMutex)
title.s = GetGadgetItemText(gadget, #PB_Web_PageTitle)
ProcedureReturn title
EndProcedure
ExecuteJavaScript.ProtoExecuteJavaScript = @ProcExecuteJavaScript()
#URL = "file:////somewhere.html"
Enumeration
#Gadget_Web
#Gadget_Command
#Gadget_Args
#Gadget_Text
#Gadget_Button
EndEnumeration
Procedure Resize()
Width = WindowWidth(0)
Height = WindowHeight(0)
ResizeGadget(#Gadget_Web, 5, 5, Width-10, Height-60)
ResizeGadget(#Gadget_Command, 5, Height-50, (Width-105)/4, 20)
ResizeGadget(#Gadget_Args, 10+(Width-105)/4, Height-50, ((Width-105)*3)/4, 20)
ResizeGadget(#Gadget_Text, 5, Height-25, Width-10, 20)
ResizeGadget(#Gadget_Button, Width-90, Height-50, 85, 20)
EndProcedure
If OpenWindow(0, 0, 0, 800, 600, "Javascript test", #PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_MaximizeGadget|#PB_Window_MinimizeGadget)
WebGadget(#Gadget_Web, 0, 0, 0, 0, #URL)
StringGadget(#Gadget_Command, 0, 0, 0, 0, "prompt")
StringGadget(#Gadget_Args, 0, 0, 0, 0, "So what will it be?,2 Beers")
TextGadget(#Gadget_Text, 0, 0, 0, 0, "Type commandname into the first, and arguments into the second box. Do not include ()", #PB_Text_Border)
ButtonGadget(#Gadget_Button, 0, 0, 0, 0, "Execute")
Resize()
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_SizeWindow
Resize()
ElseIf Event = #PB_Event_Gadget And EventGadget() = #Gadget_Button
Command$ = GetGadgetText(#Gadget_Command)
Arguments$ = GetGadgetText(#Gadget_Args)
Result$ = ExecuteJavaScript(#Gadget_Web, Command$, Arguments$, ",")
SetGadgetText(#Gadget_Text, "Result: "+Result$)
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
End
Cheers.