chrome: Add support for OnRequestMediaAccessPermission callback (see issue #2582)

This commit is contained in:
Marshall Greenblatt 2022-07-08 07:40:35 +00:00
parent d9a7422346
commit 64a5754959
10 changed files with 282 additions and 99 deletions

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=5a39566f586c012271d96c7d42337a30bf98e6b8$
// $hash=e902fe011f8667b64989e57ad9e72aec74b22015$
//
#ifndef CEF_INCLUDE_CAPI_CEF_PERMISSION_HANDLER_CAPI_H_
@ -106,9 +106,11 @@ typedef struct _cef_permission_handler_t {
// combination of values from cef_media_access_permission_types_t that
// represent the requested permissions. Return true (1) and call
// cef_media_access_callback_t functions either in this function or at a later
// time to continue or cancel the request. Return false (0) to cancel the
// request immediately. This function will not be called if the "--enable-
// media-stream" command-line switch is used to grant all permissions.
// time to continue or cancel the request. Return false (0) to proceed with
// default handling. With the Chrome runtime, default handling will display
// the permission request UI. With the Alloy runtime, default handling will
// deny the request. This function will not be called if the "--enable-media-
// stream" command-line switch is used to grant all permissions.
///
int(CEF_CALLBACK* on_request_media_access_permission)(
struct _cef_permission_handler_t* self,

View File

@ -92,8 +92,10 @@ class CefPermissionHandler : public virtual CefBaseRefCounted {
// combination of values from cef_media_access_permission_types_t that
// represent the requested permissions. Return true and call
// CefMediaAccessCallback methods either in this method or at a later time to
// continue or cancel the request. Return false to cancel the request
// immediately. This method will not be called if the "--enable-media-stream"
// continue or cancel the request. Return false to proceed with default
// handling. With the Chrome runtime, default handling will display the
// permission request UI. With the Alloy runtime, default handling will deny
// the request. This method will not be called if the "--enable-media-stream"
// command-line switch is used to grant all permissions.
///
/*--cef()--*/

View File

@ -1298,8 +1298,10 @@ void AlloyBrowserHostImpl::RequestMediaAccessPermission(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
media_access_query::RequestMediaAccessPermission(this, request,
std::move(callback));
auto returned_callback = media_access_query::RequestMediaAccessPermission(
this, request, std::move(callback), /*default_disallow=*/true);
// Callback should not be returned.
DCHECK(returned_callback.is_null());
}
bool AlloyBrowserHostImpl::CheckMediaAccessPermission(

View File

@ -55,6 +55,15 @@ class BrowserDelegate : public content::WebContentsDelegate {
WindowOpenDisposition disposition) {
return false;
}
// Same as RequestMediaAccessPermission but returning |callback| if the
// request is unhandled.
[[nodiscard]] virtual content::MediaResponseCallback
RequestMediaAccessPermissionEx(content::WebContents* web_contents,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
return callback;
}
};
} // namespace cef

View File

@ -11,6 +11,7 @@
#include "libcef/browser/browser_info_manager.h"
#include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/chrome/chrome_browser_host_impl.h"
#include "libcef/browser/media_access_query.h"
#include "libcef/browser/request_context_impl.h"
#include "libcef/common/app_manager.h"
#include "libcef/common/frame_util.h"
@ -102,6 +103,19 @@ bool ChromeBrowserDelegate::HandleCommand(int command_id,
return false;
}
content::MediaResponseCallback
ChromeBrowserDelegate::RequestMediaAccessPermissionEx(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
return media_access_query::RequestMediaAccessPermission(
browser.get(), request, std::move(callback),
/*default_disallow=*/false);
}
return callback;
}
void ChromeBrowserDelegate::WebContentsCreated(
content::WebContents* source_contents,
int opener_render_process_id,

View File

@ -54,6 +54,10 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate {
bool ShowStatusBubble(bool show_by_default) override;
bool HandleCommand(int command_id,
WindowOpenDisposition disposition) override;
[[nodiscard]] content::MediaResponseCallback RequestMediaAccessPermissionEx(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) override;
// WebContentsDelegate methods:
void WebContentsCreated(content::WebContents* source_contents,

View File

@ -10,6 +10,7 @@
#include "libcef/browser/media_stream_registrar.h"
#include "libcef/common/cef_switches.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
@ -59,6 +60,10 @@ class CefMediaAccessQuery {
return requested_permissions;
}
[[nodiscard]] CallbackType DisconnectCallback() {
return std::move(callback_);
}
void ExecuteCallback(uint32_t allowed_permissions) {
CEF_REQUIRE_UIT();
@ -267,6 +272,7 @@ class CefMediaAccessCallbackImpl : public CefMediaAccessCallback {
void Cancel() override { Continue(CEF_MEDIA_PERMISSION_NONE); }
[[nodiscard]] CallbackType Disconnect() { return std::move(callback_); }
bool IsDisconnected() const { return callback_.is_null(); }
private:
static void RunNow(CallbackType callback, uint32_t allowed_permissions) {
@ -294,9 +300,11 @@ bool CheckMediaAccessPermission(CefBrowserHostBase* browser,
return true;
}
void RequestMediaAccessPermission(CefBrowserHostBase* browser,
content::MediaResponseCallback RequestMediaAccessPermission(
CefBrowserHostBase* browser,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
content::MediaResponseCallback callback,
bool default_disallow) {
CEF_REQUIRE_UIT();
CefMediaAccessQuery query(browser, request, std::move(callback));
@ -304,10 +312,10 @@ void RequestMediaAccessPermission(CefBrowserHostBase* browser,
if (CheckCommandLinePermission()) {
// Allow all requested permissions.
query.ExecuteCallback(query.requested_permissions());
return;
return base::NullCallback();
}
bool proceed = false;
bool handled = false;
if (auto client = browser->GetClient()) {
if (auto handler = client->GetPermissionHandler()) {
@ -320,18 +328,29 @@ void RequestMediaAccessPermission(CefBrowserHostBase* browser,
request.render_process_id, request.render_frame_id));
if (!frame)
frame = browser->GetMainFrame();
proceed = handler->OnRequestMediaAccessPermission(
handled = handler->OnRequestMediaAccessPermission(
browser, frame, request.security_origin.spec(), requested_permissions,
callbackImpl.get());
if (!proceed)
if (!handled) {
LOG_IF(ERROR, callbackImpl->IsDisconnected())
<< "Should return true from OnRequestMediaAccessPermission when "
"executing the callback";
query = callbackImpl->Disconnect();
}
}
}
if (!proceed && !query.is_null()) {
if (!query.is_null()) {
if (default_disallow && !handled) {
// Disallow access by default.
query.ExecuteCallback(CEF_MEDIA_PERMISSION_NONE);
} else {
// Proceed with default handling.
return query.DisconnectCallback();
}
}
return base::NullCallback();
}
} // namespace media_access_query

View File

@ -24,9 +24,13 @@ bool CheckMediaAccessPermission(CefBrowserHostBase* browser,
blink::mojom::MediaStreamType type);
// Called from WebContentsDelegate::RequestMediaAccessPermission.
void RequestMediaAccessPermission(CefBrowserHostBase* browser,
// |callback| will be returned if the request is unhandled and
// |default_disallow| is false.
[[nodiscard]] content::MediaResponseCallback RequestMediaAccessPermission(
CefBrowserHostBase* browser,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback);
content::MediaResponseCallback callback,
bool default_disallow);
} // namespace media_access_query

View File

@ -52,7 +52,7 @@ index 583a685cd125a..bef2272570eb1 100644
]
}
diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc
index 63d64acc72318..fd3cb52daf611 100644
index 63d64acc72318..21f0a0b81f996 100644
--- chrome/browser/ui/browser.cc
+++ chrome/browser/ui/browser.cc
@@ -264,6 +264,25 @@
@ -254,7 +254,23 @@ index 63d64acc72318..fd3cb52daf611 100644
}
bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) {
@@ -2664,13 +2763,20 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
@@ -2127,6 +2226,15 @@ void Browser::RequestMediaAccessPermission(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
+#if BUILDFLAG(ENABLE_CEF)
+ if (cef_browser_delegate_) {
+ callback = cef_browser_delegate_->RequestMediaAccessPermissionEx(
+ web_contents, request, std::move(callback));
+ if (callback.is_null())
+ return;
+ }
+#endif
+
const extensions::Extension* extension =
GetExtensionForOrigin(profile_, request.security_origin);
MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
@@ -2664,13 +2772,20 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
// Browser, Getters for UI (private):
StatusBubble* Browser::GetStatusBubble() {
@ -276,7 +292,7 @@ index 63d64acc72318..fd3cb52daf611 100644
return window_ ? window_->GetStatusBubble() : nullptr;
}
@@ -2797,6 +2903,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
@@ -2797,6 +2912,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
content_translate_driver->RemoveTranslationObserver(this);
BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this);
}

View File

@ -13,6 +13,7 @@
#include "include/wrapper/cef_stream_resource_handler.h"
#include "tests/ceftests/test_handler.h"
#include "tests/ceftests/test_suite.h"
#include "tests/ceftests/test_util.h"
#include "tests/gtest/include/gtest/gtest.h"
#include "tests/shared/browser/client_app_browser.h"
@ -22,6 +23,8 @@ namespace {
const char kMediaUrl[] = "https://media-access-test/media.html";
const char kMediaOrigin[] = "https://media-access-test/";
constexpr char kMediaNavUrl[] = "https://media-access-test/nav.html";
// Browser-side app delegate.
class MediaAccessBrowserTest : public client::ClientAppBrowser::Delegate,
public CefPermissionHandler {
@ -44,14 +47,35 @@ class TestSetup {
public:
TestSetup() {}
// CONFIGURATION
// Deny the prompt by returning false in OnRequestMediaAccessPermission.
bool deny_implicitly = false;
// Deny the prompt by returning true in OnRequestMediaAccessPermission but
// then never calling CefMediaAccessCallback::Continue.
bool deny_with_navigation = false;
// Don't synchronously execute the callback in OnRequestMediaAccessPermission.
bool continue_async = false;
// RESULTS
// Method callbacks.
TrackCallback got_request;
TrackCallback got_success;
TrackCallback got_change;
// JS success state.
TrackCallback got_js_success;
TrackCallback got_audio;
TrackCallback got_video;
TrackCallback got_change;
// JS error state.
TrackCallback got_js_error;
std::string js_error_str;
// JS timeout state.
TrackCallback got_js_timeout;
};
class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
@ -67,26 +91,25 @@ class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
std::string newUrl = request->GetURL();
if (newUrl.find("tests/exit") != std::string::npos) {
if (newUrl.find("SUCCESS") != std::string::npos) {
EXPECT_FALSE(test_setup_->got_success);
test_setup_->got_success.yes();
EXPECT_FALSE(test_setup_->got_js_success);
test_setup_->got_js_success.yes();
std::string data_string = newUrl.substr(newUrl.find("&data=") +
std::string("&data=").length());
std::string data_string_decoded = CefURIDecode(
data_string, false,
static_cast<cef_uri_unescape_rule_t>(
UU_SPACES | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS));
auto obj = CefParseJSON(data_string_decoded,
JSON_PARSER_ALLOW_TRAILING_COMMAS);
CefRefPtr<CefDictionaryValue> data = obj->GetDictionary();
const auto got_video = data->GetBool("got_video_track");
const auto got_audio = data->GetBool("got_audio_track");
if (got_video) {
auto dict = ParseURLData(newUrl);
if (dict->GetBool("got_video_track")) {
test_setup_->got_video.yes();
}
if (got_audio) {
if (dict->GetBool("got_audio_track")) {
test_setup_->got_audio.yes();
}
} else if (newUrl.find("ERROR") != std::string::npos) {
EXPECT_FALSE(test_setup_->got_js_error);
test_setup_->got_js_error.yes();
auto dict = ParseURLData(newUrl);
test_setup_->js_error_str = dict->GetString("error_str");
} else if (newUrl.find("TIMEOUT") != std::string::npos) {
EXPECT_FALSE(test_setup_->got_js_timeout);
test_setup_->got_js_timeout.yes();
}
DestroyTest();
return RV_CANCEL;
@ -101,7 +124,7 @@ class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
"<script>"
"function onResult(val, data) {"
" if(!data) {"
" data = { got_audio_track: false, got_video_track: false};"
" data = {};"
" }"
" document.location = "
"`http://tests/"
@ -120,13 +143,26 @@ class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
page +=
".then(function(stream) {"
"onResult(`SUCCESS`, {got_audio_track: stream.getAudioTracks().length "
" onResult(`SUCCESS`, {got_audio_track: "
"stream.getAudioTracks().length "
"> 0, got_video_track: stream.getVideoTracks().length > 0});"
"})"
".catch(function(err) {"
"console.log(err.toString());"
"onResult(`FAILURE`);"
"});"
" console.log(err.toString());"
" onResult(`ERROR`, {error_str: err.toString()});"
"});";
if (test_setup_->deny_implicitly && IsChromeRuntimeEnabled()) {
// Default behavior with the Chrome runtime is to show a UI prompt, so add
// a timeout.
page += "setTimeout(() => { onResult(`TIMEOUT`); }, 1000);";
} else if (test_setup_->deny_with_navigation) {
// Cancel the pending request by navigating.
page += "setTimeout(() => { document.location = '" +
std::string(kMediaNavUrl) + "'; }, 1000);";
}
page +=
"</script>"
"</head><body>MEDIA ACCESS TEST</body></html>";
@ -137,6 +173,11 @@ class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
AddResource(kMediaUrl, page, "text/html");
if (test_setup_->deny_with_navigation) {
AddResource(kMediaNavUrl, "<html><body>Navigated</body></html>",
"text/html");
}
// Create the browser.
CreateBrowser(kMediaUrl, request_context);
@ -148,6 +189,16 @@ class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
return this;
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
if (test_setup_->deny_with_navigation) {
if (frame->GetURL().ToString() == kMediaNavUrl) {
DestroyTest();
}
}
}
bool OnRequestMediaAccessPermission(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
@ -167,6 +218,12 @@ class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
return false;
}
if (test_setup_->deny_with_navigation) {
// Handle the request, but never execute the callback.
callback_ = callback;
return true;
}
if (test_setup_->continue_async) {
CefPostTask(TID_UI, base::BindOnce(&CefMediaAccessCallback::Continue,
callback, response_));
@ -186,6 +243,23 @@ class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
test_setup_->got_change.yes();
}
void DestroyTest() override {
callback_ = nullptr;
const size_t js_outcome_ct = test_setup_->got_js_success +
test_setup_->got_js_error +
test_setup_->got_js_timeout;
if (test_setup_->deny_with_navigation) {
// Expect no JS outcome.
EXPECT_EQ(0U, js_outcome_ct);
} else {
// Expect a single JS outcome.
EXPECT_EQ(1U, js_outcome_ct);
}
TestHandler::DestroyTest();
}
private:
bool want_audio_device() const {
return request_ & CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
@ -213,10 +287,25 @@ class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
return response_ & CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
}
CefRefPtr<CefDictionaryValue> ParseURLData(const std::string& url) {
const std::string& find_str = "&data=";
const std::string& data_string =
url.substr(url.find(find_str) + std::string(find_str).length());
const std::string& data_string_decoded = CefURIDecode(
data_string, false,
static_cast<cef_uri_unescape_rule_t>(
UU_SPACES | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS));
auto obj =
CefParseJSON(data_string_decoded, JSON_PARSER_ALLOW_TRAILING_COMMAS);
return obj->GetDictionary();
}
TestSetup* const test_setup_;
const uint32 request_;
const uint32 response_;
CefRefPtr<CefMediaAccessCallback> callback_;
IMPLEMENT_REFCOUNTING(MediaAccessTestHandler);
};
} // namespace
@ -235,9 +324,31 @@ TEST(MediaAccessTest, DeviceFailureWhenReturningFalse) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
if (IsChromeRuntimeEnabled()) {
// Chrome shows a UI prompt, so we time out.
EXPECT_TRUE(test_setup.got_js_timeout);
} else {
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Permission denied",
test_setup.js_error_str.c_str());
}
EXPECT_FALSE(test_setup.got_change);
}
TEST(MediaAccessTest, DeviceFailureWhenNoCallback) {
TestSetup test_setup;
test_setup.deny_with_navigation = true;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_NONE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
// No JS result.
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_change);
}
@ -253,9 +364,9 @@ TEST(MediaAccessTest, DeviceFailureWhenReturningNoPermission) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Permission denied",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -272,9 +383,9 @@ TEST(MediaAccessTest, DeviceFailureWhenReturningNoPermissionAsync) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Permission denied",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -288,9 +399,9 @@ TEST(MediaAccessTest, DeviceFailureWhenRequestingAudioButReturningVideo) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -304,9 +415,9 @@ TEST(MediaAccessTest, DeviceFailureWhenRequestingVideoButReturningAudio) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -322,9 +433,9 @@ TEST(MediaAccessTest, DevicePartialFailureReturningVideo) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -340,9 +451,9 @@ TEST(MediaAccessTest, DevicePartialFailureReturningAudio) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -358,9 +469,9 @@ TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture1) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -376,9 +487,9 @@ TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture2) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -392,9 +503,9 @@ TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture3) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -408,9 +519,9 @@ TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture4) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -424,9 +535,9 @@ TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture5) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -440,9 +551,9 @@ TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture6) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -456,7 +567,7 @@ TEST(MediaAccessTest, DeviceSuccessAudioOnly) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_TRUE(test_setup.got_success);
EXPECT_TRUE(test_setup.got_js_success);
EXPECT_TRUE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_change);
@ -472,7 +583,7 @@ TEST(MediaAccessTest, DeviceSuccessVideoOnly) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_TRUE(test_setup.got_success);
EXPECT_TRUE(test_setup.got_js_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_TRUE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_change);
@ -491,7 +602,7 @@ TEST(MediaAccessTest, DeviceSuccessAudioVideo) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_TRUE(test_setup.got_success);
EXPECT_TRUE(test_setup.got_js_success);
EXPECT_TRUE(test_setup.got_audio);
EXPECT_TRUE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_change);
@ -511,7 +622,7 @@ TEST(MediaAccessTest, DeviceSuccessAudioVideoAsync) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_TRUE(test_setup.got_success);
EXPECT_TRUE(test_setup.got_js_success);
EXPECT_TRUE(test_setup.got_audio);
EXPECT_TRUE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_change);
@ -530,9 +641,9 @@ TEST(MediaAccessTest, DesktopFailureWhenReturningNoPermission) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Permission denied",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -546,9 +657,9 @@ TEST(MediaAccessTest, DesktopFailureWhenRequestingVideoButReturningAudio) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}
@ -564,7 +675,7 @@ TEST(MediaAccessTest, DesktopPartialSuccessReturningVideo) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_TRUE(test_setup.got_success);
EXPECT_TRUE(test_setup.got_js_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_TRUE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_change);
@ -581,9 +692,9 @@ TEST(MediaAccessTest, DesktopPartialFailureReturningAudio) {
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_request);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
EXPECT_TRUE(test_setup.got_js_error);
EXPECT_STREQ("NotAllowedError: Invalid state",
test_setup.js_error_str.c_str());
EXPECT_FALSE(test_setup.got_change);
}