mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-21 15:56:42 +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>,
|
class GstWebView2Item : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
|
||||||
FtmBase, IFrameArrivedHandler,
|
FtmBase, IFrameArrivedHandler,
|
||||||
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler,
|
ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler,
|
||||||
ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler>
|
ICoreWebView2CreateCoreWebView2CompositionControllerCompletedHandler,
|
||||||
|
ICoreWebView2NavigationCompletedEventHandler,
|
||||||
|
ICoreWebView2ExecuteScriptCompletedHandler>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static LRESULT CALLBACK
|
static LRESULT CALLBACK
|
||||||
|
@ -238,6 +240,9 @@ public:
|
||||||
hr = ctrl_->get_CoreWebView2 (&webview_);
|
hr = ctrl_->get_CoreWebView2 (&webview_);
|
||||||
CHECK_HR_AND_RETURN (hr, get_CoreWebView2);
|
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;
|
ComPtr<ICoreWebView2_8> webview8;
|
||||||
hr = webview_.As (&webview8);
|
hr = webview_.As (&webview8);
|
||||||
if (SUCCEEDED (hr))
|
if (SUCCEEDED (hr))
|
||||||
|
@ -251,6 +256,26 @@ public:
|
||||||
return S_OK;
|
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
|
HRESULT
|
||||||
startCapture ()
|
startCapture ()
|
||||||
{
|
{
|
||||||
|
@ -367,11 +392,16 @@ public:
|
||||||
comp_ = nullptr;
|
comp_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Navigate (LPCWSTR location)
|
HRESULT Navigate (LPCWSTR location, LPCWSTR script)
|
||||||
{
|
{
|
||||||
if (!webview_ || !location)
|
if (!webview_ || !location)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
|
if (script)
|
||||||
|
script_ = script;
|
||||||
|
else
|
||||||
|
script_.clear ();
|
||||||
|
|
||||||
return webview_->Navigate (location);
|
return webview_->Navigate (location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,6 +533,8 @@ private:
|
||||||
ComPtr<ICoreWebView2Controller3> ctrl_;
|
ComPtr<ICoreWebView2Controller3> ctrl_;
|
||||||
ComPtr<ICoreWebView2CompositionController > comp_ctrl_;
|
ComPtr<ICoreWebView2CompositionController > comp_ctrl_;
|
||||||
ComPtr<ICoreWebView2 > webview_;
|
ComPtr<ICoreWebView2 > webview_;
|
||||||
|
EventRegistrationToken navigation_compl_token_ = { };
|
||||||
|
std::wstring script_;
|
||||||
|
|
||||||
ComPtr<IGraphicsCaptureItem> item_;
|
ComPtr<IGraphicsCaptureItem> item_;
|
||||||
SizeInt32 frame_size_ = { };
|
SizeInt32 frame_size_ = { };
|
||||||
|
@ -576,18 +608,23 @@ class UpdateLocationHandler : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
STDMETHODIMP
|
STDMETHODIMP
|
||||||
RuntimeClassInitialize (GstWebView2Item * item, const std::string & location)
|
RuntimeClassInitialize (GstWebView2Item * item, const std::string & location,
|
||||||
|
const std::string & script)
|
||||||
{
|
{
|
||||||
item_ = item;
|
item_ = item;
|
||||||
location_wide_ = g_utf8_to_utf16 (location.c_str (),
|
location_wide_ = g_utf8_to_utf16 (location.c_str (),
|
||||||
-1, nullptr, nullptr, nullptr);
|
-1, nullptr, nullptr, nullptr);
|
||||||
|
if (!script.empty ()) {
|
||||||
|
script_wide_ = g_utf8_to_utf16 (script.c_str (),
|
||||||
|
-1, nullptr, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
IFACEMETHOD(Invoke) (void)
|
IFACEMETHOD(Invoke) (void)
|
||||||
{
|
{
|
||||||
item_->Navigate ((LPCWSTR) location_wide_);
|
item_->Navigate ((LPCWSTR) location_wide_, (LPCWSTR) script_wide_);
|
||||||
item_ = nullptr;
|
item_ = nullptr;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -596,11 +633,13 @@ public:
|
||||||
~UpdateLocationHandler ()
|
~UpdateLocationHandler ()
|
||||||
{
|
{
|
||||||
g_free (location_wide_);
|
g_free (location_wide_);
|
||||||
|
g_free (script_wide_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ComPtr<GstWebView2Item> item_;
|
ComPtr<GstWebView2Item> item_;
|
||||||
gunichar2 *location_wide_ = nullptr;
|
gunichar2 *location_wide_ = nullptr;
|
||||||
|
gunichar2 *script_wide_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AsyncWaiter : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
|
class AsyncWaiter : public RuntimeClass<RuntimeClassFlags<ClassicCom>,
|
||||||
|
@ -932,7 +971,7 @@ gst_webview2_object_new (GstD3D11Device * device)
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
gst_webview2_object_set_location (GstWebView2Object * object,
|
gst_webview2_object_set_location (GstWebView2Object * object,
|
||||||
const std::string & location)
|
const std::string & location, const std::string & script)
|
||||||
{
|
{
|
||||||
auto priv = object->priv;
|
auto priv = object->priv;
|
||||||
std::lock_guard < std::mutex > lk (priv->lock);
|
std::lock_guard < std::mutex > lk (priv->lock);
|
||||||
|
@ -941,7 +980,7 @@ gst_webview2_object_set_location (GstWebView2Object * object,
|
||||||
|
|
||||||
ComPtr < UpdateLocationHandler > handler;
|
ComPtr < UpdateLocationHandler > handler;
|
||||||
auto hr = MakeAndInitialize < UpdateLocationHandler > (&handler,
|
auto hr = MakeAndInitialize < UpdateLocationHandler > (&handler,
|
||||||
priv->item.Get (), location);
|
priv->item.Get (), location, script);
|
||||||
if (FAILED (hr))
|
if (FAILED (hr))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,12 @@ G_DECLARE_FINAL_TYPE (GstWebView2Object, gst_webview2_object,
|
||||||
GstWebView2Object * gst_webview2_object_new (GstD3D11Device * device);
|
GstWebView2Object * gst_webview2_object_new (GstD3D11Device * device);
|
||||||
|
|
||||||
gboolean gst_webview2_object_set_location (GstWebView2Object * client,
|
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,
|
gboolean gst_webview_object_update_size (GstWebView2Object * client,
|
||||||
guint width, guint height);
|
guint width,
|
||||||
|
guint height);
|
||||||
|
|
||||||
void gst_webview2_object_send_event (GstWebView2Object * client,
|
void gst_webview2_object_send_event (GstWebView2Object * client,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
|
|
|
@ -57,6 +57,7 @@ enum
|
||||||
PROP_ADAPTER,
|
PROP_ADAPTER,
|
||||||
PROP_LOCATION,
|
PROP_LOCATION,
|
||||||
PROP_PROCESSING_DEADLINE,
|
PROP_PROCESSING_DEADLINE,
|
||||||
|
PROP_JAVASCRIPT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_LOCATION "about:blank"
|
#define DEFAULT_LOCATION "about:blank"
|
||||||
|
@ -80,6 +81,7 @@ struct GstWebView2SrcPrivate
|
||||||
gint adapter_index = DEFAULT_ADAPTER;
|
gint adapter_index = DEFAULT_ADAPTER;
|
||||||
std::string location = DEFAULT_LOCATION;
|
std::string location = DEFAULT_LOCATION;
|
||||||
GstClockTime processing_deadline = DEFAULT_PROCESSING_DEADLINE;
|
GstClockTime processing_deadline = DEFAULT_PROCESSING_DEADLINE;
|
||||||
|
std::string script;
|
||||||
};
|
};
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
@ -138,7 +140,7 @@ gst_webview2_src_class_init (GstWebView2SrcClass * klass)
|
||||||
G_PARAM_STATIC_STRINGS)));
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
g_object_class_install_property (object_class, PROP_LOCATION,
|
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",
|
"The URL to display",
|
||||||
nullptr, (GParamFlags) (G_PARAM_READWRITE |
|
nullptr, (GParamFlags) (G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_PLAYING)));
|
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 |
|
DEFAULT_PROCESSING_DEADLINE, (GParamFlags) (G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS | GST_PARAM_MUTABLE_PLAYING)));
|
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,
|
gst_element_class_set_static_metadata (element_class,
|
||||||
"WebView2 Source", "Source/Video",
|
"WebView2 Source", "Source/Video",
|
||||||
"Creates a video stream rendered by WebView2",
|
"Creates a video stream rendered by WebView2",
|
||||||
|
@ -208,8 +216,10 @@ gst_webview2_src_set_location (GstWebView2Src * self, const gchar * location)
|
||||||
else
|
else
|
||||||
priv->location = DEFAULT_LOCATION;
|
priv->location = DEFAULT_LOCATION;
|
||||||
|
|
||||||
if (priv->object)
|
if (priv->object) {
|
||||||
gst_webview2_object_set_location (priv->object, priv->location);
|
gst_webview2_object_set_location (priv->object,
|
||||||
|
priv->location, priv->script);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -242,6 +252,20 @@ gst_webview2_src_set_property (GObject * object, guint prop_id,
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -266,6 +290,9 @@ gst_win32_video_src_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_PROCESSING_DEADLINE:
|
case PROP_PROCESSING_DEADLINE:
|
||||||
g_value_set_uint64 (value, priv->processing_deadline);
|
g_value_set_uint64 (value, priv->processing_deadline);
|
||||||
break;
|
break;
|
||||||
|
case PROP_JAVASCRIPT:
|
||||||
|
g_value_set_string (value, priv->script.c_str ());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -311,7 +338,7 @@ gst_webview2_src_start (GstBaseSrc * src)
|
||||||
return FALSE;
|
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;
|
priv->last_frame_no = -1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue