mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add OnMediaAccessChange notification (fixes issue #3310)
This commit is contained in:
@@ -204,9 +204,10 @@ void CefBrowserHostBase::InitializeBrowser() {
|
||||
void CefBrowserHostBase::DestroyBrowser() {
|
||||
CEF_REQUIRE_UIT();
|
||||
|
||||
devtools_manager_.reset(nullptr);
|
||||
devtools_manager_.reset();
|
||||
media_stream_registrar_.reset();
|
||||
|
||||
platform_delegate_.reset(nullptr);
|
||||
platform_delegate_.reset();
|
||||
|
||||
contents_delegate_->RemoveObserver(this);
|
||||
contents_delegate_->ObserveWebContents(nullptr);
|
||||
@@ -972,6 +973,14 @@ content::BrowserContext* CefBrowserHostBase::GetBrowserContext() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CefMediaStreamRegistrar* CefBrowserHostBase::GetMediaStreamRegistrar() {
|
||||
CEF_REQUIRE_UIT();
|
||||
if (!media_stream_registrar_) {
|
||||
media_stream_registrar_ = std::make_unique<CefMediaStreamRegistrar>(this);
|
||||
}
|
||||
return media_stream_registrar_.get();
|
||||
}
|
||||
|
||||
views::Widget* CefBrowserHostBase::GetWindowWidget() const {
|
||||
CEF_REQUIRE_UIT();
|
||||
if (!platform_delegate_)
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "libcef/browser/devtools/devtools_manager.h"
|
||||
#include "libcef/browser/file_dialog_manager.h"
|
||||
#include "libcef/browser/frame_host_impl.h"
|
||||
#include "libcef/browser/media_stream_registrar.h"
|
||||
#include "libcef/browser/request_context_impl.h"
|
||||
|
||||
#include "base/observer_list.h"
|
||||
@@ -301,6 +302,7 @@ class CefBrowserHostBase : public CefBrowserHost,
|
||||
CefBrowserContentsDelegate* contents_delegate() const {
|
||||
return contents_delegate_.get();
|
||||
}
|
||||
CefMediaStreamRegistrar* GetMediaStreamRegistrar();
|
||||
|
||||
// Returns the Widget owner for the browser window. Only used with windowed
|
||||
// browsers.
|
||||
@@ -371,6 +373,8 @@ class CefBrowserHostBase : public CefBrowserHost,
|
||||
// Used for creating and managing DevTools instances.
|
||||
std::unique_ptr<CefDevToolsManager> devtools_manager_;
|
||||
|
||||
std::unique_ptr<CefMediaStreamRegistrar> media_stream_registrar_;
|
||||
|
||||
private:
|
||||
IMPLEMENT_REFCOUNTING(CefBrowserHostBase);
|
||||
};
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#include "include/cef_permission_handler.h"
|
||||
#include "libcef/browser/browser_host_base.h"
|
||||
#include "libcef/browser/media_capture_devices_dispatcher.h"
|
||||
#include "libcef/browser/media_stream_registrar.h"
|
||||
#include "libcef/common/cef_switches.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
@@ -20,13 +21,17 @@ class CefMediaAccessQuery {
|
||||
public:
|
||||
using CallbackType = content::MediaResponseCallback;
|
||||
|
||||
explicit CefMediaAccessQuery(const content::MediaStreamRequest& request,
|
||||
CallbackType&& callback)
|
||||
: request_(request), callback_(std::move(callback)) {}
|
||||
CefMediaAccessQuery(CefBrowserHostBase* const browser,
|
||||
const content::MediaStreamRequest& request,
|
||||
CallbackType&& callback)
|
||||
: browser_(browser), request_(request), callback_(std::move(callback)) {}
|
||||
|
||||
CefMediaAccessQuery(CefMediaAccessQuery&& query)
|
||||
: request_(query.request_), callback_(std::move(query.callback_)) {}
|
||||
: browser_(query.browser_),
|
||||
request_(query.request_),
|
||||
callback_(std::move(query.callback_)) {}
|
||||
CefMediaAccessQuery& operator=(CefMediaAccessQuery&& query) {
|
||||
browser_ = query.browser_;
|
||||
request_ = query.request_;
|
||||
callback_ = std::move(query.callback_);
|
||||
return *this;
|
||||
@@ -74,8 +79,20 @@ class CefMediaAccessQuery {
|
||||
: blink::mojom::MediaStreamRequestResult::OK;
|
||||
}
|
||||
|
||||
bool has_video = false;
|
||||
bool has_audio = false;
|
||||
if (!stream_devices_set->stream_devices.empty()) {
|
||||
blink::mojom::StreamDevices& devices =
|
||||
*stream_devices_set->stream_devices[0];
|
||||
has_video = devices.video_device.has_value();
|
||||
has_audio = devices.audio_device.has_value();
|
||||
}
|
||||
auto media_stream_ui =
|
||||
browser_->GetMediaStreamRegistrar()->MaybeCreateMediaStreamUI(
|
||||
has_video, has_audio);
|
||||
|
||||
std::move(callback_).Run(*stream_devices_set, result,
|
||||
std::unique_ptr<content::MediaStreamUI>());
|
||||
std::move(media_stream_ui));
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -205,6 +222,7 @@ class CefMediaAccessQuery {
|
||||
return stream_devices_set;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserHostBase> browser_;
|
||||
content::MediaStreamRequest request_;
|
||||
CallbackType callback_;
|
||||
};
|
||||
@@ -281,7 +299,7 @@ void RequestMediaAccessPermission(CefBrowserHostBase* browser,
|
||||
content::MediaResponseCallback callback) {
|
||||
CEF_REQUIRE_UIT();
|
||||
|
||||
CefMediaAccessQuery query(request, std::move(callback));
|
||||
CefMediaAccessQuery query(browser, request, std::move(callback));
|
||||
|
||||
if (CheckCommandLinePermission()) {
|
||||
// Allow all requested permissions.
|
||||
|
108
libcef/browser/media_stream_registrar.cc
Normal file
108
libcef/browser/media_stream_registrar.cc
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "libcef/browser/media_stream_registrar.h"
|
||||
|
||||
#include "libcef/browser/browser_host_base.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
class CefMediaStreamUI : public content::MediaStreamUI {
|
||||
public:
|
||||
CefMediaStreamUI(base::WeakPtr<CefMediaStreamRegistrar> registrar,
|
||||
bool has_video,
|
||||
bool has_audio)
|
||||
: registrar_(registrar), has_video_(has_video), has_audio_(has_audio) {}
|
||||
|
||||
~CefMediaStreamUI() override {
|
||||
if (registrar_) {
|
||||
registrar_->UnregisterMediaStream(label_);
|
||||
}
|
||||
}
|
||||
|
||||
CefMediaStreamUI(const CefMediaStreamUI&) = delete;
|
||||
CefMediaStreamUI& operator=(const CefMediaStreamUI&) = delete;
|
||||
|
||||
gfx::NativeViewId OnStarted(
|
||||
base::RepeatingClosure stop,
|
||||
SourceCallback source,
|
||||
const std::string& label,
|
||||
std::vector<content::DesktopMediaID> screen_capture_ids,
|
||||
StateChangeCallback state_change) override {
|
||||
if (registrar_) {
|
||||
label_ = label;
|
||||
registrar_->RegisterMediaStream(label, has_video_, has_audio_);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OnDeviceStoppedForSourceChange(
|
||||
const std::string& label,
|
||||
const content::DesktopMediaID& old_media_id,
|
||||
const content::DesktopMediaID& new_media_id) override {}
|
||||
|
||||
void OnDeviceStopped(const std::string& label,
|
||||
const content::DesktopMediaID& media_id) override {}
|
||||
|
||||
private:
|
||||
base::WeakPtr<CefMediaStreamRegistrar> registrar_;
|
||||
const bool has_video_;
|
||||
const bool has_audio_;
|
||||
std::string label_;
|
||||
};
|
||||
|
||||
CefMediaStreamRegistrar::CefMediaStreamRegistrar(CefBrowserHostBase* browser)
|
||||
: browser_(browser) {}
|
||||
|
||||
std::unique_ptr<content::MediaStreamUI>
|
||||
CefMediaStreamRegistrar::MaybeCreateMediaStreamUI(bool has_video,
|
||||
bool has_audio) const {
|
||||
// Only create the object if the callback will be executed.
|
||||
if (auto client = browser_->GetClient()) {
|
||||
if (auto handler = client->GetDisplayHandler()) {
|
||||
return std::make_unique<CefMediaStreamUI>(weak_ptr_factory_.GetWeakPtr(),
|
||||
has_video, has_audio);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CefMediaStreamRegistrar::RegisterMediaStream(const std::string& label,
|
||||
bool video,
|
||||
bool audio) {
|
||||
CEF_REQUIRE_UIT();
|
||||
MediaStreamInfo info = {video, audio};
|
||||
registered_streams_.insert(std::make_pair(label, info));
|
||||
NotifyMediaStreamChange();
|
||||
}
|
||||
|
||||
void CefMediaStreamRegistrar::UnregisterMediaStream(const std::string& label) {
|
||||
CEF_REQUIRE_UIT();
|
||||
registered_streams_.erase(label);
|
||||
NotifyMediaStreamChange();
|
||||
}
|
||||
|
||||
void CefMediaStreamRegistrar::NotifyMediaStreamChange() {
|
||||
bool video = false;
|
||||
bool audio = false;
|
||||
for (const auto& media_stream : registered_streams_) {
|
||||
const auto& info = media_stream.second;
|
||||
if (!video)
|
||||
video = info.video;
|
||||
if (!audio)
|
||||
audio = info.audio;
|
||||
}
|
||||
|
||||
if (audio == last_notified_info_.audio &&
|
||||
video == last_notified_info_.video) {
|
||||
return;
|
||||
}
|
||||
|
||||
last_notified_info_ = {video, audio};
|
||||
|
||||
if (auto client = browser_->GetClient()) {
|
||||
if (auto handler = client->GetDisplayHandler()) {
|
||||
handler->OnMediaAccessChange(browser_, video, audio);
|
||||
}
|
||||
}
|
||||
}
|
56
libcef/browser/media_stream_registrar.h
Normal file
56
libcef/browser/media_stream_registrar.h
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_MEDIA_STREAM_REGISTRAR_H_
|
||||
#define CEF_LIBCEF_BROWSER_MEDIA_STREAM_REGISTRAR_H_
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "content/public/browser/media_stream_request.h"
|
||||
|
||||
class CefBrowserHostBase;
|
||||
class CefMediaStreamUI;
|
||||
|
||||
class CefMediaStreamRegistrar {
|
||||
public:
|
||||
explicit CefMediaStreamRegistrar(CefBrowserHostBase* browser);
|
||||
|
||||
CefMediaStreamRegistrar(const CefMediaStreamRegistrar&) = delete;
|
||||
CefMediaStreamRegistrar& operator=(const CefMediaStreamRegistrar&) = delete;
|
||||
|
||||
std::unique_ptr<content::MediaStreamUI> MaybeCreateMediaStreamUI(
|
||||
bool has_video,
|
||||
bool has_audio) const;
|
||||
|
||||
private:
|
||||
friend class CefMediaStreamUI;
|
||||
|
||||
// Called from CefMediaStreamUI.
|
||||
void RegisterMediaStream(const std::string& label, bool video, bool audio);
|
||||
void UnregisterMediaStream(const std::string& label);
|
||||
|
||||
void NotifyMediaStreamChange();
|
||||
|
||||
// Guaranteed to outlive this object.
|
||||
CefBrowserHostBase* const browser_;
|
||||
|
||||
struct MediaStreamInfo {
|
||||
bool video;
|
||||
bool audio;
|
||||
};
|
||||
|
||||
// Current in use media streams.
|
||||
std::map<std::string, MediaStreamInfo> registered_streams_;
|
||||
|
||||
// Last notified media stream info.
|
||||
MediaStreamInfo last_notified_info_{};
|
||||
|
||||
base::WeakPtrFactory<CefMediaStreamRegistrar> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_MEDIA_STREAM_REGISTRAR_H_
|
Reference in New Issue
Block a user