2022-06-30 09:31:18 +02:00
|
|
|
// 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 <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "include/base/cef_bind.h"
|
|
|
|
#include "include/cef_parser.h"
|
|
|
|
#include "include/cef_permission_handler.h"
|
|
|
|
#include "include/cef_request_context_handler.h"
|
2023-02-02 22:48:25 +01:00
|
|
|
#include "include/test/cef_test_helpers.h"
|
2022-06-30 09:31:18 +02:00
|
|
|
#include "include/wrapper/cef_closure_task.h"
|
|
|
|
#include "include/wrapper/cef_stream_resource_handler.h"
|
|
|
|
#include "tests/ceftests/test_handler.h"
|
|
|
|
#include "tests/ceftests/test_suite.h"
|
2022-07-08 09:40:35 +02:00
|
|
|
#include "tests/ceftests/test_util.h"
|
2022-06-30 09:31:18 +02:00
|
|
|
#include "tests/gtest/include/gtest/gtest.h"
|
|
|
|
#include "tests/shared/browser/client_app_browser.h"
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
// Media access requires HTTPS.
|
|
|
|
const char kMediaUrl[] = "https://media-access-test/media.html";
|
2022-07-07 12:01:24 +02:00
|
|
|
const char kMediaOrigin[] = "https://media-access-test/";
|
2022-06-30 09:31:18 +02:00
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
constexpr char kMediaNavUrl[] = "https://media-access-test/nav.html";
|
|
|
|
|
2022-06-30 09:31:18 +02:00
|
|
|
// Browser-side app delegate.
|
|
|
|
class MediaAccessBrowserTest : public client::ClientAppBrowser::Delegate,
|
|
|
|
public CefPermissionHandler {
|
|
|
|
public:
|
|
|
|
MediaAccessBrowserTest() {}
|
|
|
|
|
|
|
|
void OnBeforeCommandLineProcessing(
|
|
|
|
CefRefPtr<client::ClientAppBrowser> app,
|
|
|
|
CefRefPtr<CefCommandLine> command_line) override {
|
|
|
|
// We might run tests on systems that don't have media device,
|
|
|
|
// so just use fake devices.
|
|
|
|
command_line->AppendSwitch("use-fake-device-for-media-stream");
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
IMPLEMENT_REFCOUNTING(MediaAccessBrowserTest);
|
|
|
|
};
|
|
|
|
|
|
|
|
class TestSetup {
|
|
|
|
public:
|
|
|
|
TestSetup() {}
|
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
// CONFIGURATION
|
|
|
|
|
2023-02-02 22:48:25 +01:00
|
|
|
// True if a user gesture is required for the getDisplayMedia call.
|
|
|
|
bool needs_user_gesture = false;
|
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
// Deny the prompt by returning false in OnRequestMediaAccessPermission.
|
2022-06-30 09:31:18 +02:00
|
|
|
bool deny_implicitly = false;
|
2022-07-08 09:40:35 +02:00
|
|
|
|
|
|
|
// 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.
|
2022-06-30 09:31:18 +02:00
|
|
|
bool continue_async = false;
|
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
// RESULTS
|
|
|
|
|
|
|
|
// Method callbacks.
|
2022-07-07 12:01:24 +02:00
|
|
|
TrackCallback got_request;
|
2022-07-08 09:40:35 +02:00
|
|
|
TrackCallback got_change;
|
|
|
|
|
|
|
|
// JS success state.
|
|
|
|
TrackCallback got_js_success;
|
2022-06-30 09:31:18 +02:00
|
|
|
TrackCallback got_audio;
|
|
|
|
TrackCallback got_video;
|
2022-07-08 09:40:35 +02:00
|
|
|
|
|
|
|
// JS error state.
|
|
|
|
TrackCallback got_js_error;
|
|
|
|
std::string js_error_str;
|
|
|
|
|
|
|
|
// JS timeout state.
|
|
|
|
TrackCallback got_js_timeout;
|
2022-06-30 09:31:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
|
|
|
|
public:
|
2023-06-01 16:06:15 +02:00
|
|
|
MediaAccessTestHandler(TestSetup* tr, uint32_t request, uint32_t response)
|
2022-06-30 09:31:18 +02:00
|
|
|
: test_setup_(tr), request_(request), response_(response) {}
|
|
|
|
|
|
|
|
cef_return_value_t OnBeforeResourceLoad(
|
|
|
|
CefRefPtr<CefBrowser> browser,
|
|
|
|
CefRefPtr<CefFrame> frame,
|
|
|
|
CefRefPtr<CefRequest> request,
|
|
|
|
CefRefPtr<CefCallback> callback) override {
|
|
|
|
std::string newUrl = request->GetURL();
|
|
|
|
if (newUrl.find("tests/exit") != std::string::npos) {
|
|
|
|
if (newUrl.find("SUCCESS") != std::string::npos) {
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_FALSE(test_setup_->got_js_success);
|
|
|
|
test_setup_->got_js_success.yes();
|
|
|
|
|
|
|
|
auto dict = ParseURLData(newUrl);
|
|
|
|
if (dict->GetBool("got_video_track")) {
|
2022-06-30 09:31:18 +02:00
|
|
|
test_setup_->got_video.yes();
|
|
|
|
}
|
2022-07-08 09:40:35 +02:00
|
|
|
if (dict->GetBool("got_audio_track")) {
|
2022-06-30 09:31:18 +02:00
|
|
|
test_setup_->got_audio.yes();
|
|
|
|
}
|
2022-07-08 09:40:35 +02:00
|
|
|
} 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();
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
DestroyTest();
|
|
|
|
return RV_CANCEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return RV_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void RunTest() override {
|
|
|
|
std::string page =
|
|
|
|
"<html><head>"
|
|
|
|
"<script>"
|
|
|
|
"function onResult(val, data) {"
|
|
|
|
" if(!data) {"
|
2022-07-08 09:40:35 +02:00
|
|
|
" data = {};"
|
2022-06-30 09:31:18 +02:00
|
|
|
" }"
|
|
|
|
" document.location = "
|
2023-04-29 00:17:03 +02:00
|
|
|
"`https://tests/"
|
2022-06-30 09:31:18 +02:00
|
|
|
"exit?result=${val}&data=${encodeURIComponent(JSON.stringify(data))}`;"
|
2023-02-02 22:48:25 +01:00
|
|
|
"}"
|
|
|
|
"function runTest() {";
|
2022-06-30 09:31:18 +02:00
|
|
|
|
2022-06-30 14:22:28 +02:00
|
|
|
if (want_audio_device() || want_video_device()) {
|
2022-06-30 09:31:18 +02:00
|
|
|
page += std::string("navigator.mediaDevices.getUserMedia({audio: ") +
|
2022-06-30 14:22:28 +02:00
|
|
|
(want_audio_device() ? "true" : "false") +
|
|
|
|
", video: " + (want_video_device() ? "true" : "false") + "})";
|
2022-06-30 09:31:18 +02:00
|
|
|
} else {
|
|
|
|
page += std::string("navigator.mediaDevices.getDisplayMedia({audio: ") +
|
2022-06-30 14:22:28 +02:00
|
|
|
(want_audio_desktop() ? "true" : "false") +
|
|
|
|
", video: " + (want_video_desktop() ? "true" : "false") + "})";
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
page +=
|
|
|
|
".then(function(stream) {"
|
2022-07-08 09:40:35 +02:00
|
|
|
" onResult(`SUCCESS`, {got_audio_track: "
|
|
|
|
"stream.getAudioTracks().length "
|
2022-06-30 09:31:18 +02:00
|
|
|
"> 0, got_video_track: stream.getVideoTracks().length > 0});"
|
|
|
|
"})"
|
|
|
|
".catch(function(err) {"
|
2022-07-08 09:40:35 +02:00
|
|
|
" console.log(err.toString());"
|
|
|
|
" onResult(`ERROR`, {error_str: err.toString()});"
|
2023-02-02 22:48:25 +01:00
|
|
|
"});"
|
|
|
|
"}";
|
2022-07-08 09:40:35 +02:00
|
|
|
|
|
|
|
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 +=
|
2022-06-30 09:31:18 +02:00
|
|
|
"</script>"
|
2023-02-02 22:48:25 +01:00
|
|
|
"</head><body>";
|
|
|
|
|
|
|
|
if (!test_setup_->needs_user_gesture) {
|
|
|
|
page += "<script>runTest();</script>";
|
|
|
|
}
|
|
|
|
|
|
|
|
page += "MEDIA ACCESS TEST</body></html>";
|
2022-06-30 09:31:18 +02:00
|
|
|
|
|
|
|
// Create the request context that will use an in-memory cache.
|
|
|
|
CefRequestContextSettings settings;
|
|
|
|
CefRefPtr<CefRequestContext> request_context =
|
|
|
|
CefRequestContext::CreateContext(settings, nullptr);
|
|
|
|
|
|
|
|
AddResource(kMediaUrl, page, "text/html");
|
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
if (test_setup_->deny_with_navigation) {
|
|
|
|
AddResource(kMediaNavUrl, "<html><body>Navigated</body></html>",
|
|
|
|
"text/html");
|
|
|
|
}
|
|
|
|
|
2022-06-30 09:31:18 +02:00
|
|
|
// Create the browser.
|
|
|
|
CreateBrowser(kMediaUrl, request_context);
|
|
|
|
|
|
|
|
// Time out the test after a reasonable period of time.
|
|
|
|
SetTestTimeout();
|
|
|
|
}
|
|
|
|
|
|
|
|
CefRefPtr<CefPermissionHandler> GetPermissionHandler() override {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
|
|
|
CefRefPtr<CefFrame> frame,
|
|
|
|
int httpStatusCode) override {
|
|
|
|
if (test_setup_->deny_with_navigation) {
|
|
|
|
if (frame->GetURL().ToString() == kMediaNavUrl) {
|
|
|
|
DestroyTest();
|
|
|
|
}
|
2023-02-02 22:48:25 +01:00
|
|
|
} else if (test_setup_->needs_user_gesture) {
|
|
|
|
CefExecuteJavaScriptWithUserGestureForTests(frame, "runTest()");
|
2022-07-08 09:40:35 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-30 09:31:18 +02:00
|
|
|
bool OnRequestMediaAccessPermission(
|
|
|
|
CefRefPtr<CefBrowser> browser,
|
|
|
|
CefRefPtr<CefFrame> frame,
|
2022-07-07 12:01:24 +02:00
|
|
|
const CefString& requesting_origin,
|
2023-06-01 16:06:15 +02:00
|
|
|
uint32_t requested_permissions,
|
2022-06-30 09:31:18 +02:00
|
|
|
CefRefPtr<CefMediaAccessCallback> callback) override {
|
|
|
|
EXPECT_UI_THREAD();
|
|
|
|
EXPECT_TRUE(frame->IsMain());
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_EQ(requested_permissions, request_);
|
|
|
|
EXPECT_STREQ(kMediaOrigin, requesting_origin.ToString().c_str());
|
|
|
|
|
|
|
|
EXPECT_FALSE(test_setup_->got_request);
|
|
|
|
test_setup_->got_request.yes();
|
|
|
|
|
2022-06-30 09:31:18 +02:00
|
|
|
if (test_setup_->deny_implicitly) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
if (test_setup_->deny_with_navigation) {
|
|
|
|
// Handle the request, but never execute the callback.
|
|
|
|
callback_ = callback;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-06-30 09:31:18 +02:00
|
|
|
if (test_setup_->continue_async) {
|
|
|
|
CefPostTask(TID_UI, base::BindOnce(&CefMediaAccessCallback::Continue,
|
|
|
|
callback, response_));
|
|
|
|
} else {
|
|
|
|
callback->Continue(response_);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-06-30 14:22:28 +02:00
|
|
|
void OnMediaAccessChange(CefRefPtr<CefBrowser> browser,
|
|
|
|
bool has_video_access,
|
|
|
|
bool has_audio_access) override {
|
|
|
|
EXPECT_UI_THREAD();
|
|
|
|
EXPECT_EQ(got_video_device() || got_video_desktop(), has_video_access);
|
|
|
|
EXPECT_EQ(got_audio_device() || got_audio_desktop(), has_audio_access);
|
|
|
|
EXPECT_FALSE(test_setup_->got_change);
|
|
|
|
test_setup_->got_change.yes();
|
|
|
|
}
|
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2022-06-30 14:22:28 +02:00
|
|
|
private:
|
|
|
|
bool want_audio_device() const {
|
|
|
|
return request_ & CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
|
|
|
|
}
|
|
|
|
bool want_video_device() const {
|
|
|
|
return request_ & CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE;
|
|
|
|
}
|
|
|
|
bool want_audio_desktop() const {
|
|
|
|
return request_ & CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE;
|
|
|
|
}
|
|
|
|
bool want_video_desktop() const {
|
|
|
|
return request_ & CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool got_audio_device() const {
|
|
|
|
return response_ & CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
|
|
|
|
}
|
|
|
|
bool got_video_device() const {
|
|
|
|
return response_ & CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE;
|
|
|
|
}
|
|
|
|
bool got_audio_desktop() const {
|
|
|
|
return response_ & CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE;
|
|
|
|
}
|
|
|
|
bool got_video_desktop() const {
|
|
|
|
return response_ & CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
|
|
|
|
}
|
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2022-06-30 09:31:18 +02:00
|
|
|
TestSetup* const test_setup_;
|
2023-06-01 16:06:15 +02:00
|
|
|
const uint32_t request_;
|
|
|
|
const uint32_t response_;
|
2022-06-30 09:31:18 +02:00
|
|
|
|
2022-07-08 09:40:35 +02:00
|
|
|
CefRefPtr<CefMediaAccessCallback> callback_;
|
|
|
|
|
2022-06-30 09:31:18 +02:00
|
|
|
IMPLEMENT_REFCOUNTING(MediaAccessTestHandler);
|
|
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
// Capture device tests
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenReturningFalse) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
test_setup.deny_implicitly = 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);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
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);
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenReturningNoPermission) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Permission denied",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenReturningNoPermissionAsync) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
test_setup.continue_async = 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);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Permission denied",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenRequestingAudioButReturningVideo) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
|
|
|
|
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenRequestingVideoButReturningAudio) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
|
|
|
|
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DevicePartialFailureReturningVideo) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler =
|
|
|
|
new MediaAccessTestHandler(&test_setup,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DevicePartialFailureReturningAudio) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler =
|
|
|
|
new MediaAccessTestHandler(&test_setup,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture1) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler =
|
|
|
|
new MediaAccessTestHandler(&test_setup,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture2) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler =
|
|
|
|
new MediaAccessTestHandler(&test_setup,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture3) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
|
|
|
|
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture4) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
|
|
|
|
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture5) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
|
|
|
|
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture6) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
|
|
|
|
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceSuccessAudioOnly) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
|
|
|
|
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_success);
|
2022-06-30 09:31:18 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_audio);
|
|
|
|
EXPECT_FALSE(test_setup.got_video);
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceSuccessVideoOnly) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
|
|
|
|
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_success);
|
2022-06-30 09:31:18 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_audio);
|
|
|
|
EXPECT_TRUE(test_setup.got_video);
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceSuccessAudioVideo) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler =
|
|
|
|
new MediaAccessTestHandler(&test_setup,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_success);
|
2022-06-30 09:31:18 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_audio);
|
|
|
|
EXPECT_TRUE(test_setup.got_video);
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DeviceSuccessAudioVideoAsync) {
|
|
|
|
TestSetup test_setup;
|
|
|
|
test_setup.continue_async = true;
|
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler =
|
|
|
|
new MediaAccessTestHandler(&test_setup,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_success);
|
2022-06-30 09:31:18 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_audio);
|
|
|
|
EXPECT_TRUE(test_setup.got_video);
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Screen capture tests
|
|
|
|
TEST(MediaAccessTest, DesktopFailureWhenReturningNoPermission) {
|
|
|
|
TestSetup test_setup;
|
2023-02-02 22:48:25 +01:00
|
|
|
test_setup.needs_user_gesture = true;
|
2022-06-30 09:31:18 +02:00
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler =
|
|
|
|
new MediaAccessTestHandler(&test_setup,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_NONE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Permission denied",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DesktopFailureWhenRequestingVideoButReturningAudio) {
|
|
|
|
TestSetup test_setup;
|
2023-02-02 22:48:25 +01:00
|
|
|
test_setup.needs_user_gesture = true;
|
2022-06-30 09:31:18 +02:00
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
|
|
|
|
&test_setup, CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DesktopPartialSuccessReturningVideo) {
|
|
|
|
TestSetup test_setup;
|
2023-02-02 22:48:25 +01:00
|
|
|
test_setup.needs_user_gesture = true;
|
2022-06-30 09:31:18 +02:00
|
|
|
|
|
|
|
CefRefPtr<MediaAccessTestHandler> handler =
|
|
|
|
new MediaAccessTestHandler(&test_setup,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_success);
|
2022-06-30 09:31:18 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_audio);
|
|
|
|
EXPECT_TRUE(test_setup.got_video);
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST(MediaAccessTest, DesktopPartialFailureReturningAudio) {
|
|
|
|
TestSetup test_setup;
|
2023-02-02 22:48:25 +01:00
|
|
|
test_setup.needs_user_gesture = true;
|
|
|
|
|
2022-06-30 09:31:18 +02:00
|
|
|
CefRefPtr<MediaAccessTestHandler> handler =
|
|
|
|
new MediaAccessTestHandler(&test_setup,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
|
|
|
|
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
|
|
|
|
handler->ExecuteTest();
|
|
|
|
ReleaseAndWaitForDestructor(handler);
|
|
|
|
|
2022-07-07 12:01:24 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_request);
|
2022-07-08 09:40:35 +02:00
|
|
|
EXPECT_TRUE(test_setup.got_js_error);
|
|
|
|
EXPECT_STREQ("NotAllowedError: Invalid state",
|
|
|
|
test_setup.js_error_str.c_str());
|
2022-06-30 14:22:28 +02:00
|
|
|
EXPECT_FALSE(test_setup.got_change);
|
2022-06-30 09:31:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Entry point for creating media access browser test objects.
|
|
|
|
// Called from client_app_delegates.cc.
|
|
|
|
void CreateMediaAccessBrowserTests(
|
|
|
|
client::ClientAppBrowser::DelegateSet& delegates) {
|
|
|
|
delegates.insert(new MediaAccessBrowserTest);
|
|
|
|
}
|