mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-10 11:29:55 +00:00
webview2: Add support for javascript injection
Allow javascript injection for various custom use cases. For example, scrollbars and scrolling can be disabled via gst-launch-1.0 webview2src location=https://gstreamer.freedesktop.org \ javascript="document.querySelector('body').style.overflow='hidden'" ! ... Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6487>
This commit is contained in:
parent
85d422f7c6
commit
f7bdf91ad7
3 changed files with 80 additions and 12 deletions
|
@ -119,7 +119,9 @@ GstGetActivationFactory (InterfaceType ** factory)
|
|||
class GstWebView2Item : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
|
||||
FtmBase, IFrameArrivedHandler,
|
||||
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler,
|
||||
ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler>
|
||||
ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler,
|
||||
ICoreWebView2NavigationCompletedEventHandler,
|
||||
ICoreWebView2ExecuteScriptCompletedHandler>
|
||||
{
|
||||
public:
|
||||
static LRESULT CALLBACK
|
||||
|
@ -238,6 +240,9 @@ public:
|
|||
hr = ctrl_->get_CoreWebView2 (&webview_);
|
||||
CHECK_HR_AND_RETURN (hr, get_CoreWebView2);
|
||||
|
||||
hr = webview_->add_NavigationCompleted (this, &navigation_compl_token_);
|
||||
CHECK_HR_AND_RETURN (hr, get_CoreWebView2);
|
||||
|
||||
ComPtr<ICoreWebView2_8> webview8;
|
||||
hr = webview_.As (&webview8);
|
||||
if (SUCCEEDED (hr))
|
||||
|
@ -251,6 +256,26 @@ public:
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHOD(Invoke) (HRESULT hr, LPCWSTR result_json)
|
||||
{
|
||||
GST_DEBUG_OBJECT (obj_, "Executing script result 0x%x", (guint) hr);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHOD(Invoke) (ICoreWebView2 * sender,
|
||||
ICoreWebView2NavigationCompletedEventArgs * arg)
|
||||
{
|
||||
GST_DEBUG_OBJECT (obj_, "Navigation completed");
|
||||
|
||||
if (!script_.empty ()) {
|
||||
GST_DEBUG_OBJECT (obj_, "Executing script");
|
||||
sender->ExecuteScript (script_.c_str (), this);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
startCapture ()
|
||||
{
|
||||
|
@ -367,11 +392,16 @@ public:
|
|||
comp_ = nullptr;
|
||||
}
|
||||
|
||||
HRESULT Navigate (LPCWSTR location)
|
||||
HRESULT Navigate (LPCWSTR location, LPCWSTR script)
|
||||
{
|
||||
if (!webview_ || !location)
|
||||
return E_FAIL;
|
||||
|
||||
if (script)
|
||||
script_ = script;
|
||||
else
|
||||
script_.clear ();
|
||||
|
||||
return webview_->Navigate (location);
|
||||
}
|
||||
|
||||
|
@ -503,6 +533,8 @@ private:
|
|||
ComPtr<ICoreWebView2Controller3> ctrl_;
|
||||
ComPtr<ICoreWebView2CompositionController > comp_ctrl_;
|
||||
ComPtr<ICoreWebView2 > webview_;
|
||||
EventRegistrationToken navigation_compl_token_ = { };
|
||||
std::wstring script_;
|
||||
|
||||
ComPtr<IGraphicsCaptureItem> item_;
|
||||
SizeInt32 frame_size_ = { };
|
||||
|
@ -576,18 +608,23 @@ class UpdateLocationHandler : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
|
|||
{
|
||||
public:
|
||||
STDMETHODIMP
|
||||
RuntimeClassInitialize (GstWebView2Item * item, const std::string & location)
|
||||
RuntimeClassInitialize (GstWebView2Item * item, const std::string & location,
|
||||
const std::string & script)
|
||||
{
|
||||
item_ = item;
|
||||
location_wide_ = g_utf8_to_utf16 (location.c_str (),
|
||||
-1, nullptr, nullptr, nullptr);
|
||||
if (!script.empty ()) {
|
||||
script_wide_ = g_utf8_to_utf16 (script.c_str (),
|
||||
-1, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHOD(Invoke) (void)
|
||||
{
|
||||
item_->Navigate ((LPCWSTR) location_wide_);
|
||||
item_->Navigate ((LPCWSTR) location_wide_, (LPCWSTR) script_wide_);
|
||||
item_ = nullptr;
|
||||
|
||||
return S_OK;
|
||||
|
@ -596,11 +633,13 @@ public:
|
|||
~UpdateLocationHandler ()
|
||||
{
|
||||
g_free (location_wide_);
|
||||
g_free (script_wide_);
|
||||
}
|
||||
|
||||
private:
|
||||
ComPtr<GstWebView2Item> item_;
|
||||
gunichar2 *location_wide_ = nullptr;
|
||||
gunichar2 *script_wide_ = nullptr;
|
||||
};
|
||||
|
||||
class AsyncWaiter : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
|
||||
|
@ -932,7 +971,7 @@ gst_webview2_object_new (GstD3D11Device * device)
|
|||
|
||||
gboolean
|
||||
gst_webview2_object_set_location (GstWebView2Object * object,
|
||||
const std::string & location)
|
||||
const std::string & location, const std::string & script)
|
||||
{
|
||||
auto priv = object->priv;
|
||||
std::lock_guard < std::mutex > lk (priv->lock);
|
||||
|
@ -941,7 +980,7 @@ gst_webview2_object_set_location (GstWebView2Object * object,
|
|||
|
||||
ComPtr < UpdateLocationHandler > handler;
|
||||
auto hr = MakeAndInitialize < UpdateLocationHandler > (&handler,
|
||||
priv->item.Get (), location);
|
||||
priv->item.Get (), location, script);
|
||||
if (FAILED (hr))
|
||||
return FALSE;
|
||||
|
||||
|
|
|
@ -33,10 +33,12 @@ G_DECLARE_FINAL_TYPE (GstWebView2Object, gst_webview2_object,
|
|||
GstWebView2Object * gst_webview2_object_new (GstD3D11Device * device);
|
||||
|
||||
gboolean gst_webview2_object_set_location (GstWebView2Object * client,
|
||||
const std::string & location);
|
||||
const std::string & location,
|
||||
const std::string & script);
|
||||
|
||||
gboolean gst_webview_object_update_size (GstWebView2Object * client,
|
||||
guint width, guint height);
|
||||
guint width,
|
||||
guint height);
|
||||
|
||||
void gst_webview2_object_send_event (GstWebView2Object * client,
|
||||
GstEvent * event);
|
||||
|
|
|
@ -57,6 +57,7 @@ enum
|
|||
PROP_ADAPTER,
|
||||
PROP_LOCATION,
|
||||
PROP_PROCESSING_DEADLINE,
|
||||
PROP_JAVASCRIPT,
|
||||
};
|
||||
|
||||
#define DEFAULT_LOCATION "about:blank"
|
||||
|
@ -80,6 +81,7 @@ struct GstWebView2SrcPrivate
|
|||
gint adapter_index = DEFAULT_ADAPTER;
|
||||
std::string location = DEFAULT_LOCATION;
|
||||
GstClockTime processing_deadline = DEFAULT_PROCESSING_DEADLINE;
|
||||
std::string script;
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
@ -138,7 +140,7 @@ gst_webview2_src_class_init (GstWebView2SrcClass * klass)
|
|||
G_PARAM_STATIC_STRINGS)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_LOCATION,
|
||||
g_param_spec_string ("location", "location",
|
||||
g_param_spec_string ("location", "Location",
|
||||
"The URL to display",
|
||||
nullptr, (GParamFlags) (G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_PLAYING)));
|
||||
|
@ -149,6 +151,12 @@ gst_webview2_src_class_init (GstWebView2SrcClass * klass)
|
|||
DEFAULT_PROCESSING_DEADLINE, (GParamFlags) (G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_PLAYING)));
|
||||
|
||||
g_object_class_install_property (object_class, PROP_JAVASCRIPT,
|
||||
g_param_spec_string ("javascript", "Javascript",
|
||||
"Javascript to run on nevigation completed",
|
||||
nullptr, (GParamFlags) (G_PARAM_READWRITE |
|
||||
G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_PLAYING)));
|
||||
|
||||
gst_element_class_set_static_metadata (element_class,
|
||||
"WebView2 Source", "Source/Video",
|
||||
"Creates a video stream rendered by WebView2",
|
||||
|
@ -208,8 +216,10 @@ gst_webview2_src_set_location (GstWebView2Src * self, const gchar * location)
|
|||
else
|
||||
priv->location = DEFAULT_LOCATION;
|
||||
|
||||
if (priv->object)
|
||||
gst_webview2_object_set_location (priv->object, priv->location);
|
||||
if (priv->object) {
|
||||
gst_webview2_object_set_location (priv->object,
|
||||
priv->location, priv->script);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -242,6 +252,20 @@ gst_webview2_src_set_property (GObject * object, guint prop_id,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case PROP_JAVASCRIPT:
|
||||
{
|
||||
auto script = g_value_get_string (value);
|
||||
if (script)
|
||||
priv->script = script;
|
||||
else
|
||||
priv->script.clear ();
|
||||
|
||||
if (priv->object) {
|
||||
gst_webview2_object_set_location (priv->object, priv->location,
|
||||
priv->script);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -266,6 +290,9 @@ gst_win32_video_src_get_property (GObject * object, guint prop_id,
|
|||
case PROP_PROCESSING_DEADLINE:
|
||||
g_value_set_uint64 (value, priv->processing_deadline);
|
||||
break;
|
||||
case PROP_JAVASCRIPT:
|
||||
g_value_set_string (value, priv->script.c_str ());
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -311,7 +338,7 @@ gst_webview2_src_start (GstBaseSrc * src)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
gst_webview2_object_set_location (priv->object, priv->location);
|
||||
gst_webview2_object_set_location (priv->object, priv->location, priv->script);
|
||||
|
||||
priv->last_frame_no = -1;
|
||||
|
||||
|
|
Loading…
Reference in a new issue