I display user HTML content in the webgadget (cross platform). For this, I cover it into some iframe. There I want to use sandbox feature to disable JavaScript (for security). But I need to open links from within this document to be opened by myself (I want to open the system web-browser with clicked target to allow links to be displayed independent of me).
Then I did this test code, puzzled together mainly from forum posts (eg from Shardik, Wilbert and others). It loads some document and iframe from my website. Containing only links to PureBasic website. You can see directly here.
Code: Select all
; PureBasic 5.46 LTS / Unicode
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
; ----------------------
; -- WINDOWS SPECIFIC --
;{----------------------
Procedure EnsureJSforWebGadget(WebgadgetID.i)
; not needed on Windows
EndProcedure
Procedure SetNavigationCallback(WebGadget.i, *CallBackFunction)
; Somehow works by default on Windows
SetGadgetAttribute(WebGadget.i, #PB_Web_NavigationCallback,
*CallBackFunction)
EndProcedure
;}
CompilerCase #PB_OS_Linux
; --------------------
; -- LINUX SPECIFIC --
;{--------------------
#G_TYPE_INT = 6 << 2
ImportC ""
g_object_get_property(*Object.GObject, PropertyName.P-UTF8,
*PropertyValue)
EndImport
ImportC "-lwebkitgtk-3.0"
webkit_web_view_get_settings(*WebView)
webkit_web_view_set_settings(*WebView, *WebkitSettings)
webkit_web_navigation_action_get_original_uri(*NavigationAction)
webkit_web_policy_decision_ignore(*PolicyDecision)
webkit_web_policy_decision_use(*PolicyDecision)
EndImport
ImportC "-lgobject-2.0"
g_signal_connect_data(*Instance, Signal.P-UTF8, *Callback, *UserData,
*ClosureNotify, ConnectFlags.I)
EndImport
ProcedureC linNavigationCallback(*WebView, *Frame, *Request,
*NavigationAction, *PolicyDecision, *UserCallback)
Protected URL.s = PeekS(webkit_web_navigation_action_get_original_uri(*NavigationAction),
-1, #PB_UTF8)
CallFunctionFast(*UserCallback, 0, @URL.s)
; webkit_web_policy_decision_ignore(*PolicyDecision)
webkit_web_policy_decision_use(*PolicyDecision)
EndProcedure
Procedure EnsureJSforWebGadget(WebgadgetID.i)
; Enable JavaScript support in GTK3 WebGadgets
; (dont know why it is off by default?)
Protected WebkitSettings.i = webkit_web_view_get_settings(GadgetID(WebgadgetID.i))
Protected Value.GValue
If WebkitSettings
Value\g_type = #G_TYPE_INT
g_object_get_property(WebkitSettings, "enable-scripts", @Value)
If g_value_get_int_(@Value) = 0
g_value_set_int_(@Value, 1)
g_object_set_property_(WebkitSettings, "enable-scripts", @Value)
webkit_web_view_set_settings(GadgetID(WebgadgetID.i), WebkitSettings)
EndIf
EndIf
EndProcedure
Procedure SetNavigationCallback(WebGadget.i, *CallBackFunction)
g_signal_connect_data(GadgetID(0), "navigation-policy-decision-requested",
@linNavigationCallback(), *CallBackFunction, 0, 0)
EndProcedure
;}
CompilerCase #PB_OS_MacOS
; ----------------------
; -- MAC OSX SPECIFIC --
;{----------------------
Global AppDelegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
Global DelegateClass = CocoaMessage(0, AppDelegate, "class")
Global *macCallbackFunction
ProcedureC macPolicyDecisionMaker(Object.I, Selector.I, WebView.I,
ActionInformation.I, Request.I, *FrameName, Listener.I)
Protected *URL = CocoaMessage(0, Request, "URL")
Protected URL.s = PeekS(CocoaMessage(0,
CocoaMessage(0, *URL, "absoluteString"), "UTF8String"), -1, #PB_UTF8)
Debug URL.s
CallFunctionFast(*macCallbackFunction, 0, @URL.s)
; CocoaMessage(0, Listener, "ignore")
CocoaMessage(0, Listener, "use")
EndProcedure
class_addMethod_(DelegateClass, sel_registerName_("webView:" +
"decidePolicyForNavigationAction:request:frame:decisionListener:"),
@macPolicyDecisionMaker(), "v@:@@@@@")
Procedure EnsureJSforWebGadget(WebgadgetID.i)
; not needed on MacOS
EndProcedure
Procedure SetNavigationCallback(WebGadget.i, *CallBackFunction)
; Somehow works by default on Linux
*macCallbackFunction = *CallBackFunction
CocoaMessage(0, GadgetID(WebGadget.i), "setPolicyDelegate:", AppDelegate)
EndProcedure
;}
CompilerEndSelect
; ---------------
; -- TEST CODE --
;{---------------
Procedure NavigationCallback(Gadget.i, Url.s)
Debug "Detected URL: [" + Url.s + "]"
; IMPORTANT: Gadget.i is only returned on Windows! Linux and Mac is 0.
ProcedureReturn #True
EndProcedure
If OpenWindow(0, 0, 0, 600, 300, "WebGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
WebGadget(0, 10, 10, 580, 280, "http://x-beliebig.info/Download/iframetest.html")
EnsureJSforWebGadget(0)
SetNavigationCallback(0, @NavigationCallback())
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
;}
Windows main frame:
I get only target="_self" navigation callbacks.
target="_blank" does not fire callbacks, but opens new web-browser!
Windows iframe:
I get only target="_self" navigation callbacks.
target="_blank" does nothing
Linux main frame:
I get only target="_self" navigation callbacks.
target="_blank" does nothing
Linux iframe:
I get no navigation callbacks at all.
MacOS main frame:
I get only target="_self" navigation callbacks.
target="_blank" does nothing
MacOS iframe:
I get no navigation callbacks at all.
I wish I was able to get ALL navigation events. I also really need to get the events from inside the iframe, too.
Do you see any idea about how to get and handle ALL navigation events of all target="n" variants? I'm also able to reqrite all target="_blank" to be target="_self" if this helps a little. On Windows this will work, but not on MacOS or Linux (not getting any event at all).
JavaScript is not an option, because the sandbox iframe will stop all execution of JS by the code in the iframe (this is what I finally want). I also considered removing all script code from the HTML, but it is impossible. There are soooo many ways to enbed JS (urls, events, tags etc). It is also to slow for big documents.