NEW 214811
[GTK] Web process crash during user media permission request calling gst_v4l2_open()
https://bugs.webkit.org/show_bug.cgi?id=214811
Summary [GTK] Web process crash during user media permission request calling gst_v4l2...
Michael Catanzaro
Reported 2020-07-26 13:32:10 PDT
I'm going to try and see if I can figure out how to reproduce this. I think it occurred testing a bluejeans.com call. (Maybe it occurs when my webcam is in use elsewhere?) Obviously (from the backtrace) it's related to the user media permission request. Note frame 5 of the backtrace: #5 0x00007f37a0438b09 in gst_v4l2_open (v4l2object=v4l2object@entry=0x2b54690) at v4l2_calls.c:621 __txt = 0x2b55610 "Could not open device '/dev/video1' for reading and writing." __dbg = 0x2b55510 "system error: Permission denied" st = {st_dev = 5, st_ino = 602862, st_nlink = 0, st_mode = 8192, st_uid = 65534, st_gid = 65534, __pad0 = 0, st_rdev = 20737, st_size = 0, st_blksize = 4096, st_blocks = 0, st_atim = {tv_sec = 1595793989, tv_nsec = 230543748}, st_mtim = {tv_sec = 1595793989, tv_nsec = 230543748}, st_ctim = {tv_sec = 1595794051, tv_nsec = 425020882}, __glibc_reserved = {0, 0, 0}} libv4l2_fd = -1 __func__ = "gst_v4l2_open" I'm skeptical that gst_v4l2_open() should be called in the UI process, especially since this is unsandboxed. #0 g_logv (log_domain=0x7f502aa81960 <g_log_domain_gstreamer> "GStreamer", log_level=G_LOG_LEVEL_CRITICAL, format=<optimized out>, args=<optimized out>) at ../glib/gmessages.c:1377 domain = 0x0 data = 0x0 depth = 0 log_func = 0x7f502a9d15e0 <debug_log_handler> domain_fatal_mask = <optimized out> masquerade_fatal = <optimized out> test_level = <optimized out> was_fatal = <optimized out> was_recursion = <optimized out> msg = 0x2b555a0 "gst_element_message_full_with_details: assertion 'GST_IS_ELEMENT (element)' failed" msg_alloc = 0x2b555a0 "gst_element_message_full_with_details: assertion 'GST_IS_ELEMENT (element)' failed" i = 3 #1 0x00007f502a0e7233 in g_log (log_domain=<optimized out>, log_level=log_level@entry=G_LOG_LEVEL_CRITICAL, format=format@entry=0x7f502a1396ff "%s: assertion '%s' failed") at ../glib/gmessages.c:1415 args = {{gp_offset = 40, fp_offset = 48, overflow_arg_area = 0x7ffdd3d9fe60, reg_save_area = 0x7ffdd3d9fda0}} #2 0x00007f502a0e7a2d in g_return_if_fail_warning (log_domain=<optimized out>, pretty_function=pretty_function@entry=0x7f502aa8cac0 <__func__.24665> "gst_element_message_full_with_details", expression=<optimized out>) at ../glib/gmessages.c:2771 #3 0x00007f502aa02c08 in gst_element_message_full_with_details (element=<optimized out>, type=type@entry=GST_MESSAGE_ERROR, domain=3135, code=code@entry=7, text=text@entry=0x2b55610 "Could not open device '/dev/video1' for reading and writing.", debug=debug@entry=0x2b55510 "system error: Permission denied", file=0x7f37a04464e9 "v4l2_calls.c", function=0x7f37a0447360 <__func__.29605> "gst_v4l2_open", line=621, structure=0x0) at gstelement.c:2112 gerror = 0x0 name = <optimized out> sent_text = <optimized out> sent_debug = <optimized out> has_debug = 1 message = 0x0 __PRETTY_FUNCTION__ = "gst_element_message_full_with_details" __func__ = "gst_element_message_full_with_details" #4 0x00007f502aa02c4c in gst_element_message_full (element=<optimized out>, type=type@entry=GST_MESSAGE_ERROR, domain=<optimized out>, code=code@entry=7, text=text@entry=0x2b55610 "Could not open device '/dev/video1' for reading and writing.", debug=debug@entry=0x2b55510 "system error: Permission denied", file=0x7f37a04464e9 "v4l2_calls.c", function=0x7f37a0447360 <__func__.29605> "gst_v4l2_open", line=621) at gstelement.c:2204 #5 0x00007f37a0438b09 in gst_v4l2_open (v4l2object=v4l2object@entry=0x2b54690) at v4l2_calls.c:621 __txt = 0x2b55610 "Could not open device '/dev/video1' for reading and writing." __dbg = 0x2b55510 "system error: Permission denied" st = {st_dev = 5, st_ino = 602862, st_nlink = 0, st_mode = 8192, st_uid = 65534, st_gid = 65534, __pad0 = 0, st_rdev = 20737, st_size = 0, st_blksize = 4096, st_blocks = 0, st_atim = {tv_sec = 1595793989, tv_nsec = 230543748}, st_mtim = {tv_sec = 1595793989, tv_nsec = 230543748}, st_ctim = {tv_sec = 1595794051, tv_nsec = 425020882}, __glibc_reserved = {0, 0, 0}} libv4l2_fd = -1 __func__ = "gst_v4l2_open" #6 0x00007f37a0414dfb in gst_v4l2_device_provider_probe_device (device_name=0x0, props=0x1016860, device_path=0x2b4df10 "/dev/video1", provider=0x2b39b90 [GstV4l2DeviceProvider|--Type <RET> for more, q to quit, c to continue without paging--c v4l2deviceprovider0]) at gstv4l2deviceprovider.c:119 v4l2obj = 0x2b54690 device = 0x0 [GstV4l2Device] type = GST_V4L2_DEVICE_TYPE_INVALID caps = <optimized out> st = {st_dev = 5, st_ino = 602862, st_nlink = 0, st_mode = 8192, st_uid = 65534, st_gid = 65534, __pad0 = 0, st_rdev = 20737, st_size = 0, st_blksize = 4096, st_blocks = 0, st_atim = {tv_sec = 1595793989, tv_nsec = 230543748}, st_mtim = {tv_sec = 1595793989, tv_nsec = 230543748}, st_ctim = {tv_sec = 1595794051, tv_nsec = 425020882}, __glibc_reserved = {0, 0, 0}} __func__ = "gst_v4l2_device_provider_probe_device" props = 0x1016860 device = <optimized out> self = 0x2b39b90 [GstV4l2DeviceProvider|v4l2deviceprovider0] it = 0x2b54100 devices = 0x0 #7 gst_v4l2_device_provider_probe (provider=0x2b39b90 [GstV4l2DeviceProvider|v4l2deviceprovider0]) at gstv4l2deviceprovider.c:213 props = 0x1016860 device = <optimized out> self = 0x2b39b90 [GstV4l2DeviceProvider|v4l2deviceprovider0] it = 0x2b54100 devices = 0x0 #8 0x00007f502a9fbc0d in gst_device_provider_get_devices (provider=provider@entry=0x2b39b90 [GstV4l2DeviceProvider|v4l2deviceprovider0]) at gstdeviceprovider.c:420 klass = 0x2b58af0 devices = 0x0 started = <optimized out> item = <optimized out> __func__ = "gst_device_provider_get_devices" #9 0x00007f502a9fa40d in gst_device_monitor_get_devices (monitor=0x2afa2b0 [GstDeviceMonitor|devicemonitor1]) at gstdevicemonitor.c:393 tmpdev = <optimized out> provider = 0x2b39b90 [GstV4l2DeviceProvider|v4l2deviceprovider0] item = <optimized out> devices = 0x0 hidden = 0x0 i = 0 cookie = 1 __func__ = "gst_device_monitor_get_devices" __PRETTY_FUNCTION__ = "gst_device_monitor_get_devices" #10 0x00007f5032b697b5 in WebCore::GStreamerCaptureDeviceManager::refreshCaptureDevices() (this=0x7f5034126740 <WebCore::GStreamerVideoCaptureDeviceManager::singleton()::manager>) at DerivedSources/ForwardingHeaders/wtf/glib/GRefPtr.h:105 __FUNCTION__ = "refreshCaptureDevices" devices = <optimized out> #11 0x00007f5032b6996a in WebCore::GStreamerCaptureDeviceManager::captureDevices() (this=this@entry=0x7f5034126740 <WebCore::GStreamerVideoCaptureDeviceManager::singleton()::manager>) at ../../Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.cpp:84 #12 0x00007f5032b699eb in WebCore::GStreamerCaptureDeviceManager::gstreamerDeviceWithUID(WTF::String const&) (this=0x7f5034126740 <WebCore::GStreamerVideoCaptureDeviceManager::singleton()::manager>, deviceID=...) at ../../Source/WebCore/platform/mediastream/gstreamer/GStreamerCaptureDeviceManager.cpp:71 #13 0x00007f5032b6b89e in WebCore::GStreamerVideoCaptureSource::create(WTF::String&&, WTF::String&&, WebCore::MediaConstraints const*) (deviceID=..., hashSalt=..., constraints=0x7f379bc039c8) at ../../Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoCaptureSource.cpp:101 device = {<WTF::Optional_base<WebCore::GStreamerCaptureDevice>> = {init_ = true, storage_ = {dummy_ = 0 '\000', value_ = {<WebCore::CaptureDevice> = {m_persistentId = {static MaxLength = 2147483647, m_impl = {static isRefPtr = <optimized out>, m_ptr = 0x0}}, m_type = WebCore::CaptureDevice::DeviceType::Microphone, m_label = {static MaxLength = 2147483647, m_impl = {static isRefPtr = <optimized out>, m_ptr = 0x0}}, m_groupId = {static MaxLength = 2147483647, m_impl = {static isRefPtr = <optimized out>, m_ptr = 0x0}}, m_enabled = true}, m_device = {m_ptr = 0x2afa350 [GstPulseDevice|pulsedevice2]}}}}, <No data fields>} source = <optimized out> #14 0x00007f5032b6cc4f in WebCore::GStreamerVideoCaptureSourceFactory::createVideoCaptureSource(WebCore::CaptureDevice const&, WTF::String&&, WebCore::MediaConstraints const*) (this=<optimized out>, device=..., hashSalt=..., constraints=<optimized out>) at DerivedSources/ForwardingHeaders/wtf/text/StringImpl.h:1107 #15 0x00007f50323b4c39 in WebCore::RealtimeMediaSourceCenter::createMediaStream(WTF::Ref<WTF::Logger const, WTF::DumbPtrTraits<WTF::Logger const> >&&, WTF::Function<void (std::experimental::fundamentals_v3::expected<WTF::Ref<WebCore::MediaStreamPrivate, WTF::DumbPtrTraits<WebCore::MediaStreamPrivate> >, WTF::String>&&)>&&, WTF::String&&, WebCore::CaptureDevice&&, WebCore::CaptureDevice&&, WebCore::MediaStreamRequest const&) (this=this@entry=0x7f503411d4c0 <WebCore::RealtimeMediaSourceCenter::singleton()::center>, logger=..., completionHandler=..., hashSalt=..., audioDevice=..., videoDevice=..., request=...) at ../../Source/WebCore/platform/mediastream/CaptureDevice.h:65 source = {captureSource = {static isRefPtr = <optimized out>, m_ptr = 0x0}, errorMessage = {static MaxLength = 2147483647, m_impl = {static isRefPtr = <optimized out>, m_ptr = 0x0}}} invalidConstraint = {static MaxLength = 2147483647, m_impl = {static isRefPtr = <optimized out>, m_ptr = 0x0}} audioSource = <optimized out> videoSource = {static isRefPtr = <optimized out>, m_ptr = 0x0} #16 0x00007f50318ccd8e in operator() (__closure=0x7f379aa8d8f8) at /usr/include/c++/10/bits/atomic_base.h:325 <truncated by mcatanzaro> #17 WTF::Detail::CallableWrapper<WebCore::UserMediaRequest::allow(WebCore::CaptureDevice&&, WebCore::CaptureDevice&&, WTF::String&&, WTF::CompletionHandler<void()>&&)::<lambda()>, void>::call(void) (this=0x7f379aa8d8f0) at DerivedSources/ForwardingHeaders/wtf/Function.h:52 #18 0x00007f5031c97482 in WTF::Function<void ()>::operator()() const (this=<optimized out>) at /usr/include/c++/10/bits/unique_ptr.h:420 group = <optimized out> task = std::unique_ptr<class WebCore::EventLoopTask> = {get() = 0x7f379296e000} __for_range = <synthetic pointer>: <optimized out> __for_begin = 0x7f37979b2780 __for_end = 0x7f37979b2788 remainingTasks = {<WTF::VectorBuffer<std::unique_ptr<WebCore::EventLoopTask, std::default_delete<WebCore::EventLoopTask> >, 0, WTF::FastMalloc>> = {<WTF::VectorBufferBase<std::unique_ptr<WebCore::EventLoopTask, std::default_delete<WebCore::EventLoopTask> >, WTF::FastMalloc>> = {m_buffer = 0x0, m_capacity = 0, m_size = 0}, <No data fields>}, <No data fields>} didPerformMicrotaskCheckpoint = false #19 WebCore::EventLoopFunctionDispatchTask::execute() (this=<optimized out>) at ../../Source/WebCore/dom/EventLoop.cpp:134 group = <optimized out> task = std::unique_ptr<class WebCore::EventLoopTask> = {get() = 0x7f379296e000} __for_range = <synthetic pointer>: <optimized out> __for_begin = 0x7f37979b2780 __for_end = 0x7f37979b2788 remainingTasks = {<WTF::VectorBuffer<std::unique_ptr<WebCore::EventLoopTask, std::default_delete<WebCore::EventLoopTask> >, 0, WTF::FastMalloc>> = {<WTF::VectorBufferBase<std::unique_ptr<WebCore::EventLoopTask, std::default_delete<WebCore::EventLoopTask> >, WTF::FastMalloc>> = {m_buffer = 0x0, m_capacity = 0, m_size = 0}, <No data fields>}, <No data fields>} didPerformMicrotaskCheckpoint = false #20 WebCore::EventLoop::run() (this=this@entry=0x7f501906c190) at ../../Source/WebCore/dom/EventLoop.cpp:98 group = <optimized out> task = std::unique_ptr<class WebCore::EventLoopTask> = {get() = 0x7f379296e000} __for_range = <synthetic pointer>: <optimized out> __for_begin = 0x7f37979b2780 __for_end = 0x7f37979b2788 remainingTasks = {<WTF::VectorBuffer<std::unique_ptr<WebCore::EventLoopTask, std::default_delete<WebCore::EventLoopTask> >, 0, WTF::FastMalloc>> = {<WTF::VectorBufferBase<std::unique_ptr<WebCore::EventLoopTask, std::default_delete<WebCore::EventLoopTask> >, WTF::FastMalloc>> = {m_buffer = 0x0, m_capacity = 0, m_size = 0}, <No data fields>}, <No data fields>} didPerformMicrotaskCheckpoint = false #21 0x00007f5031d1808d in WebCore::WindowEventLoop::didReachTimeToRun() (this=0x7f501906c190) at ../../Source/WebCore/dom/WindowEventLoop.cpp:120 protectedThis = {static isRef = <optimized out>, m_ptr = 0x7f501906c190} #22 0x00007f50322b2a04 in WebCore::ThreadTimers::sharedTimerFiredInternal() (this=0x7f5019093de8) at ../../Source/WebCore/platform/ThreadTimers.h:106 item = {static isRef = <optimized out>, m_ptr = 0x7f37a199b150} timer = <optimized out> interval = <optimized out> timeToQuit = <optimized out> #23 WebCore::ThreadTimers::sharedTimerFiredInternal() (this=0x7f5019093de8) at ../../Source/WebCore/platform/ThreadTimers.cpp:99 #24 0x00007f502e499a9d in operator() (__closure=0x0, userData=0x7f503411c750 <WebCore::MainThreadSharedTimer::singleton()::instance+16>) at ../../Source/WTF/wtf/glib/RunLoopGLib.cpp:147 timer = 0x7f503411c750 <WebCore::MainThreadSharedTimer::singleton()::instance+16> source = 0x12f0c10 #25 _FUN(gpointer) () at ../../Source/WTF/wtf/glib/RunLoopGLib.cpp:150 #26 0x00007f502a0df78f in g_main_dispatch (context=0xe6eac0) at ../glib/gmain.c:3309 dispatch = <optimized out> prev_source = 0x0 was_in_call = <optimized out> user_data = 0x7f503411c750 <WebCore::MainThreadSharedTimer::singleton()::instance+16> callback = 0x7f502e499a10 <_FUN(gpointer)> cb_funcs = 0x7f502a1b5280 <g_source_callback_funcs> cb_data = 0x12f0cb0 need_destroy = <optimized out> source = 0x12f0c10 current = 0xe76830 i = 1 __func__ = "g_main_dispatch" #27 g_main_context_dispatch (context=0xe6eac0) at ../glib/gmain.c:3974 #28 0x00007f502a0dfb18 in g_main_context_iterate (context=0xe6eac0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4047 max_priority = 100 timeout = 0 some_ready = 1 nfds = <optimized out> allocated_nfds = <optimized out> fds = 0xfc8990 #29 0x00007f502a0dfe33 in g_main_loop_run (loop=loop@entry=0xf97630) at ../glib/gmain.c:4241 __func__ = "g_main_loop_run" #30 0x00007f502e499c80 in WTF::RunLoop::run() () at ../../Source/WTF/wtf/glib/RunLoopGLib.cpp:96 runLoop = @0x7f50190f9000: {<WTF::FunctionDispatcher> = {<WTF::ThreadSafeRefCounted<WTF::FunctionDispatcher, (WTF::DestructionThread)0>> = {<WTF::ThreadSafeRefCountedBase> = {m_refCount = {<std::__atomic_base<unsigned int>> = {static _S_alignment = 4, _M_i = 33}, static is_always_lock_free = true}}, <No data fields>}, _vptr.FunctionDispatcher = 0x7f502e7cd158 <vtable for WTF::RunLoop+16>}, m_currentIteration = {m_start = 1, m_end = 1, m_buffer = {<WTF::VectorBufferBase<WTF::Function<void()>, WTF::FastMalloc>> = {m_buffer = 0x7f501904a000, m_capacity = 16, m_size = 0}, <No data fields>}}, m_nextIterationLock = {static isHeldBit = 1 '\001', static hasParkedBit = 2 '\002', m_byte = {value = {<std::__atomic_base<unsigned char>> = {static _S_alignment = 1, _M_i = 0 '\000'}, static is_always_lock_free = true}}}, m_nextIteration = {m_start = 0, m_end = 1, m_buffer = {<WTF::VectorBufferBase<WTF::Function<void()>, WTF::FastMalloc>> = {m_buffer = 0x7f501904a080, m_capacity = 16, m_size = 0}, <No data fields>}}, m_isFunctionDispatchSuspended = false, m_hasSuspendedFunctions = false, m_mainContext = {m_ptr = 0xe6eac0}, m_mainLoops = {<WTF::VectorBuffer<WTF::GRefPtr<_GMainLoop>, 0, WTF::FastMalloc>> = {<WTF::VectorBufferBase<WTF::GRefPtr<_GMainLoop>, WTF::FastMalloc>> = {m_buffer = 0x7f50190f9080, m_capacity = 16, m_size = 1}, <No data fields>}, <No data fields>}, m_source = {m_ptr = 0xf18970}} mainContext = 0xe6eac0 innermostLoop = 0xf97630 nestedMainLoop = <optimized out> #31 0x00007f503101e01f in WebKit::AuxiliaryProcessMain<WebKit::WebProcess, WebKit::WebProcessMainGtk>(int, char**) (argc=3, argv=<optimized out>) at ../../Source/WebKit/Shared/AuxiliaryProcessMain.h:49 auxiliaryMain = {<WebKit::AuxiliaryProcessMainBase> = {_vptr.AuxiliaryProcessMainBase = 0x7f5033dafa10 <vtable for WebKit::WebProcessMainGtk+16>, m_parameters = {uiProcessName = {static MaxLength = 2147483647, m_impl = {static isRefPtr = <optimized out>, m_ptr = 0x0}}, clientIdentifier = {static MaxLength = 2147483647, m_impl = {static isRefPtr = <optimized out>, m_ptr = 0x0}}, processIdentifier = {<WTF::constexpr_Optional_base<WTF::ObjectIdentifier<WebCore::ProcessIdentifierType> >> = {init_ = true, storage_ = {dummy_ = 68 'D', value_ = {<WTF::ObjectIdentifierBase> = {<No data fields>}, m_identifier = 68, static m_generationProtected = false}}}, <No data fields>}, connectionIdentifier = 65, extraInitializationData = {m_impl = {static smallMaxLoadNumerator = <optimized out>, static smallMaxLoadDenominator = <optimized out>, static largeMaxLoadNumerator = <optimized out>, static largeMaxLoadDenominator = <optimized out>, static maxSmallTableCapacity = <optimized out>, static minLoad = <optimized out>, static tableSizeOffset = <optimized out>, static tableSizeMaskOffset = <optimized out>, static keyCountOffset = <optimized out>, static deletedCountOffset = <optimized out>, static metadataSize = <optimized out>, m_table = 0x0}}, processType = 64}}, <No data fields>} #32 0x00007f5028a99042 in __libc_start_main (main=0x400b20 <main(int, char**)>, argc=3, argv=0x7ffdd3da0878, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffdd3da0868) at ../csu/libc-start.c:308 result = <optimized out> unwind_buf = {cancel_jmp_buf = {{jmp_buf = {0, -5900587206844801872, 4197248, 0, 0, 0, 5901756234023640240, 5817725899212266672}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x3, 0x7ffdd3da0878}, data = {prev = 0x0, cleanup = 0x0, canceltype = 3}}} not_first_call = <optimized out> #33 0x0000000000400bae in _start ()
Attachments
Michael Catanzaro
Comment 1 2020-07-26 13:45:44 PDT
(In reply to Michael Catanzaro from comment #0) > I'm going to try and see if I can figure out how to reproduce this. I think > it occurred testing a bluejeans.com call. (Maybe it occurs when my webcam is > in use elsewhere?) Obviously (from the backtrace) it's related to the user > media permission request. Note frame 5 of the backtrace: Apologies, this is actually a web process crash. I got confused because I have two backtraces that look almost the same, and the other one is a UI process crash. I have separately reported bug #214812 for the UI process crash since using GStreamer in the UI process requires special scrutiny. Finally, note this is a G_DEBUG=fatal-criticals crash, I use that in my jhbuild environment to crash as early as possible for the best backtrace.
Víctor M. Jáquez L.
Comment 2 2020-08-05 08:48:16 PDT
Since right now it is expected to access the camera from WebProcess, is this a bug? or a missing rule in the sandbox?
Michael Catanzaro
Comment 3 2020-08-05 10:09:53 PDT
Well it's definitely a bug. Even if there's no permission to access /dev/video1, WebKit shouldn't crash. That's happening because of this critical: assertion 'GST_IS_ELEMENT (element)' failed. So that's the first issue to fix. Now, as to why the permission error is occurring... I think you were correct to guess a sandbox problem. I would actually never have thought of that, but that must be it. There's actually sandbox rule to bind /dev/video1 in bindV4l in BubblewrapLauncher.cpp. But it can only be bound if it already exists at the time the web process is launched! Testing now, /dev/video0 and /dev/video1 are only created when I actually plug in my webcam, which I usually do long after the web process is already running. The sandbox will never be able to allow access to files that don't already exist at the time the web process is launched, so using /dev/video0 and /dev/video1 from the web process cannot be made to work. I'm pretty sure pipewire is designed to avoid this problem, right? (We're going to need to hook up to pipewire to make desktop sharing work anyway. Maybe we should have a separate bug for pipewire integration?)
Víctor M. Jáquez L.
Comment 4 2020-08-06 03:38:59 PDT
(In reply to Michael Catanzaro from comment #3) > Well it's definitely a bug. Even if there's no permission to access > /dev/video1, WebKit shouldn't crash. That's happening because of this > critical: assertion 'GST_IS_ELEMENT (element)' failed. So that's the first > issue to fix. Did you compile WebKit with Flatpak? If so, I guess I get why it is happening: We need to compile gstv4l2 without udev support, because flatpak can't handle it, and gstv4l2 fallbacks to traversing a hard-coded list of possible devices, where probing is opening try-and-error. Then this probing is done without an element associated, raising the precondition check. > > Now, as to why the permission error is occurring... I think you were correct > to guess a sandbox problem. I would actually never have thought of that, but > that must be it. There's actually sandbox rule to bind /dev/video1 in > bindV4l in BubblewrapLauncher.cpp. But it can only be bound if it already > exists at the time the web process is launched! Testing now, /dev/video0 and > /dev/video1 are only created when I actually plug in my webcam, which I > usually do long after the web process is already running. The sandbox will > never be able to allow access to files that don't already exist at the time > the web process is launched, so using /dev/video0 and /dev/video1 from the > web process cannot be made to work. I'm pretty sure pipewire is designed to > avoid this problem, right? (We're going to need to hook up to pipewire to > make desktop sharing work anyway. Maybe we should have a separate bug for > pipewire integration?) AFAIK, pipewire takes care of the available devices, so yes. But -- again, afaik -- we need to upgrade pipewire to work in flatpak
Michael Catanzaro
Comment 6 2020-08-06 07:02:43 PDT
(In reply to Víctor M. Jáquez L. from comment #4) > Did you compile WebKit with Flatpak? No, I used GNOME jhbuild. And I probably did not compile GStreamer, so it's probably using system GStreamer. > AFAIK, pipewire takes care of the available devices, so yes. But -- again, afaik -- we need to upgrade pipewire to work in flatpak We need to upgrade pipewire? (In reply to Víctor M. Jáquez L. from comment #5) > https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/ > 694 Cool! (But note I'm not using fatal-warnings -- in fact, a warning might be appropriate if a GStreamer element is missing -- only fatal-criticals, which indicate programmer error.)
Philippe Normand
Comment 7 2020-08-11 01:49:21 PDT
(In reply to Michael Catanzaro from comment #6) > (In reply to Víctor M. Jáquez L. from comment #4) > > Did you compile WebKit with Flatpak? > > No, I used GNOME jhbuild. And I probably did not compile GStreamer, so it's > probably using system GStreamer. > > > AFAIK, pipewire takes care of the available devices, so yes. But -- again, afaik -- we need to upgrade pipewire to work in flatpak > > We need to upgrade pipewire? > Clarifying a bit here... The FDO SDK we depend on currently (19.08) doesn't provide a functional Pipewire. However I think it works correctly in the upcoming 20.08 branch. So whenever this is released the work on Pipewire support could start, there's https://bugs.webkit.org/show_bug.cgi?id=210926 open for screen sharing. Another bug could be open for camera devices access through pipewire, although I suspect it will just work out of the box.
Michael Catanzaro
Comment 8 2020-08-11 07:50:11 PDT
Well you don't need to wait, you can pin to 20.08beta.6 like GNOME and Tech Preview are using. We upgrade it regularly.
Philippe Normand
Comment 9 2020-08-11 09:11:55 PDT
(In reply to Michael Catanzaro from comment #8) > Well you don't need to wait, you can pin to 20.08beta.6 like GNOME and Tech > Preview are using. We upgrade it regularly. With the limited resources we have currently, we can't afford to update to every single beta of the FDO SDK.
Note You need to log in before you can comment on or make changes to this bug.