summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc')
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc651
1 files changed, 651 insertions, 0 deletions
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc b/chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
new file mode 100644
index 00000000000..3affb26a72b
--- /dev/null
+++ b/chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
@@ -0,0 +1,651 @@
+// Copyright 2013 The Chromium 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 "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
+
+#include <stddef.h>
+
+#include <limits>
+
+#include "base/json/json_reader.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/browser/extensions/chrome_test_extension_loader.h"
+#include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
+#include "chrome/browser/permissions/permission_request_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/browser_test_utils.h"
+#include "extensions/browser/extension_registry.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+#if defined(OS_WIN)
+// For fine-grained suppression.
+#include "base/win/windows_version.h"
+#endif
+
+const char WebRtcTestBase::kAudioVideoCallConstraints[] =
+ "{audio: true, video: true}";
+const char WebRtcTestBase::kVideoCallConstraintsQVGA[] =
+ "{video: {mandatory: {minWidth: 320, maxWidth: 320, "
+ " minHeight: 240, maxHeight: 240}}}";
+const char WebRtcTestBase::kVideoCallConstraints360p[] =
+ "{video: {mandatory: {minWidth: 640, maxWidth: 640, "
+ " minHeight: 360, maxHeight: 360}}}";
+const char WebRtcTestBase::kVideoCallConstraintsVGA[] =
+ "{video: {mandatory: {minWidth: 640, maxWidth: 640, "
+ " minHeight: 480, maxHeight: 480}}}";
+const char WebRtcTestBase::kVideoCallConstraints720p[] =
+ "{video: {mandatory: {minWidth: 1280, maxWidth: 1280, "
+ " minHeight: 720, maxHeight: 720}}}";
+const char WebRtcTestBase::kVideoCallConstraints1080p[] =
+ "{video: {mandatory: {minWidth: 1920, maxWidth: 1920, "
+ " minHeight: 1080, maxHeight: 1080}}}";
+const char WebRtcTestBase::kAudioOnlyCallConstraints[] = "{audio: true}";
+const char WebRtcTestBase::kVideoOnlyCallConstraints[] = "{video: true}";
+const char WebRtcTestBase::kOkGotStream[] = "ok-got-stream";
+const char WebRtcTestBase::kFailedWithNotAllowedError[] =
+ "failed-with-error-NotAllowedError";
+const char WebRtcTestBase::kAudioVideoCallConstraints360p[] =
+ "{audio: true, video: {mandatory: {minWidth: 640, maxWidth: 640, "
+ " minHeight: 360, maxHeight: 360}}}";
+const char WebRtcTestBase::kAudioVideoCallConstraints720p[] =
+ "{audio: true, video: {mandatory: {minWidth: 1280, maxWidth: 1280, "
+ " minHeight: 720, maxHeight: 720}}}";
+const char WebRtcTestBase::kUseDefaultCertKeygen[] = "null";
+const char WebRtcTestBase::kUseDefaultAudioCodec[] = "";
+const char WebRtcTestBase::kUseDefaultVideoCodec[] = "";
+const char WebRtcTestBase::kVP9Profile0Specifier[] = "profile-id=0";
+const char WebRtcTestBase::kVP9Profile2Specifier[] = "profile-id=2";
+const char WebRtcTestBase::kUndefined[] = "undefined";
+
+namespace {
+
+base::LazyInstance<bool>::DestructorAtExit hit_javascript_errors_ =
+ LAZY_INSTANCE_INITIALIZER;
+
+// Intercepts all log messages. We always attach this handler but only look at
+// the results if the test requests so. Note that this will only work if the
+// WebrtcTestBase-inheriting test cases do not run in parallel (if they did they
+// would race to look at the log, which is global to all tests).
+bool JavascriptErrorDetectingLogHandler(int severity,
+ const char* file,
+ int line,
+ size_t message_start,
+ const std::string& str) {
+ if (file == NULL || std::string("CONSOLE") != file)
+ return false;
+
+ // TODO(crbug.com/918871): Fix AppRTC and stop ignoring this error.
+ if (str.find("Synchronous XHR in page dismissal") != std::string::npos)
+ return false;
+
+ bool contains_uncaught = str.find("\"Uncaught ") != std::string::npos;
+ if (severity == logging::LOG_ERROR ||
+ (severity == logging::LOG_INFO && contains_uncaught)) {
+ hit_javascript_errors_.Get() = true;
+ }
+
+ return false;
+}
+
+// PermissionRequestObserver ---------------------------------------------------
+
+// Used to observe the creation of permission prompt without responding.
+class PermissionRequestObserver : public PermissionRequestManager::Observer {
+ public:
+ explicit PermissionRequestObserver(content::WebContents* web_contents)
+ : request_manager_(
+ PermissionRequestManager::FromWebContents(web_contents)),
+ request_shown_(false),
+ message_loop_runner_(new content::MessageLoopRunner) {
+ request_manager_->AddObserver(this);
+ }
+ ~PermissionRequestObserver() override {
+ // Safe to remove twice if it happens.
+ request_manager_->RemoveObserver(this);
+ }
+
+ void Wait() { message_loop_runner_->Run(); }
+
+ bool request_shown() const { return request_shown_; }
+
+ private:
+ // PermissionRequestManager::Observer
+ void OnBubbleAdded() override {
+ request_shown_ = true;
+ request_manager_->RemoveObserver(this);
+ message_loop_runner_->Quit();
+ }
+
+ PermissionRequestManager* request_manager_;
+ bool request_shown_;
+ scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(PermissionRequestObserver);
+};
+
+std::vector<std::string> JsonArrayToVectorOfStrings(
+ const std::string& json_array) {
+ std::unique_ptr<base::Value> value =
+ base::JSONReader::ReadDeprecated(json_array);
+ EXPECT_TRUE(value);
+ EXPECT_TRUE(value->is_list());
+ std::unique_ptr<base::ListValue> list =
+ base::ListValue::From(std::move(value));
+ std::vector<std::string> vector;
+ vector.reserve(list->GetSize());
+ for (size_t i = 0; i < list->GetSize(); ++i) {
+ base::Value* item;
+ EXPECT_TRUE(list->Get(i, &item));
+ EXPECT_TRUE(item->is_string());
+ std::string item_str;
+ EXPECT_TRUE(item->GetAsString(&item_str));
+ vector.push_back(std::move(item_str));
+ }
+ return vector;
+}
+
+} // namespace
+
+WebRtcTestBase::WebRtcTestBase(): detect_errors_in_javascript_(false) {
+ // The handler gets set for each test method, but that's fine since this
+ // set operation is idempotent.
+ logging::SetLogMessageHandler(&JavascriptErrorDetectingLogHandler);
+ hit_javascript_errors_.Get() = false;
+
+ EnablePixelOutput();
+}
+
+WebRtcTestBase::~WebRtcTestBase() {
+ if (detect_errors_in_javascript_) {
+ EXPECT_FALSE(hit_javascript_errors_.Get())
+ << "Encountered javascript errors during test execution (Search "
+ << "for Uncaught or ERROR:CONSOLE in the test output).";
+ }
+}
+
+bool WebRtcTestBase::GetUserMediaAndAccept(
+ content::WebContents* tab_contents) const {
+ return GetUserMediaWithSpecificConstraintsAndAccept(
+ tab_contents, kAudioVideoCallConstraints);
+}
+
+bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAccept(
+ content::WebContents* tab_contents,
+ const std::string& constraints) const {
+ std::string result;
+ PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ PermissionRequestObserver permissionRequestObserver(tab_contents);
+ GetUserMedia(tab_contents, constraints);
+ EXPECT_TRUE(permissionRequestObserver.request_shown());
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
+ return kOkGotStream == result;
+}
+
+bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAcceptIfPrompted(
+ content::WebContents* tab_contents,
+ const std::string& constraints) const {
+ std::string result;
+ PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ GetUserMedia(tab_contents, constraints);
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
+ return kOkGotStream == result;
+}
+
+void WebRtcTestBase::GetUserMediaAndDeny(content::WebContents* tab_contents) {
+ return GetUserMediaWithSpecificConstraintsAndDeny(tab_contents,
+ kAudioVideoCallConstraints);
+}
+
+void WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndDeny(
+ content::WebContents* tab_contents,
+ const std::string& constraints) const {
+ std::string result;
+ PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(PermissionRequestManager::DENY_ALL);
+ PermissionRequestObserver permissionRequestObserver(tab_contents);
+ GetUserMedia(tab_contents, constraints);
+ EXPECT_TRUE(permissionRequestObserver.request_shown());
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
+ EXPECT_EQ(kFailedWithNotAllowedError, result);
+}
+
+void WebRtcTestBase::GetUserMediaAndDismiss(
+ content::WebContents* tab_contents) const {
+ std::string result;
+ PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(PermissionRequestManager::DISMISS);
+ PermissionRequestObserver permissionRequestObserver(tab_contents);
+ GetUserMedia(tab_contents, kAudioVideoCallConstraints);
+ EXPECT_TRUE(permissionRequestObserver.request_shown());
+ // A dismiss should be treated like a deny.
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
+ EXPECT_EQ(kFailedWithNotAllowedError, result);
+}
+
+void WebRtcTestBase::GetUserMediaAndExpectAutoAcceptWithoutPrompt(
+ content::WebContents* tab_contents) const {
+ std::string result;
+ // We issue a GetUserMedia() request. We expect that the origin already has a
+ // sticky "accept" permission (e.g. because the caller previously called
+ // GetUserMediaAndAccept()), and therefore the GetUserMedia() request
+ // automatically succeeds without a prompt.
+ // If the caller made a mistake, a prompt may show up instead. For this case,
+ // we set an auto-response to avoid leaving the prompt hanging. The choice of
+ // DENY_ALL makes sure that the response to the prompt doesn't accidentally
+ // result in a newly granted media stream permission.
+ PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(PermissionRequestManager::DENY_ALL);
+ PermissionRequestObserver permissionRequestObserver(tab_contents);
+ GetUserMedia(tab_contents, kAudioVideoCallConstraints);
+ EXPECT_FALSE(permissionRequestObserver.request_shown());
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
+ EXPECT_EQ(kOkGotStream, result);
+}
+
+void WebRtcTestBase::GetUserMediaAndExpectAutoDenyWithoutPrompt(
+ content::WebContents* tab_contents) const {
+ std::string result;
+ // We issue a GetUserMedia() request. We expect that the origin already has a
+ // sticky "deny" permission (e.g. because the caller previously called
+ // GetUserMediaAndDeny()), and therefore the GetUserMedia() request
+ // automatically succeeds without a prompt.
+ // If the caller made a mistake, a prompt may show up instead. For this case,
+ // we set an auto-response to avoid leaving the prompt hanging. The choice of
+ // ACCEPT_ALL makes sure that the response to the prompt doesn't accidentally
+ // result in a newly granted media stream permission.
+ PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ PermissionRequestObserver permissionRequestObserver(tab_contents);
+ GetUserMedia(tab_contents, kAudioVideoCallConstraints);
+ EXPECT_FALSE(permissionRequestObserver.request_shown());
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
+ EXPECT_EQ(kFailedWithNotAllowedError, result);
+}
+
+void WebRtcTestBase::GetUserMedia(content::WebContents* tab_contents,
+ const std::string& constraints) const {
+ // Request user media: this will launch the media stream info bar or bubble.
+ std::string result;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ tab_contents, "doGetUserMedia(" + constraints + ");", &result));
+ EXPECT_TRUE(result == "request-callback-denied" ||
+ result == "request-callback-granted");
+}
+
+content::WebContents* WebRtcTestBase::OpenPageAndGetUserMediaInNewTab(
+ const GURL& url) const {
+ return OpenPageAndGetUserMediaInNewTabWithConstraints(
+ url, kAudioVideoCallConstraints);
+}
+
+content::WebContents*
+WebRtcTestBase::OpenPageAndGetUserMediaInNewTabWithConstraints(
+ const GURL& url,
+ const std::string& constraints) const {
+ chrome::AddTabAt(browser(), GURL(), -1, true);
+ ui_test_utils::NavigateToURL(browser(), url);
+ content::WebContents* new_tab =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ // Accept if necessary, but don't expect a prompt (because auto-accept is also
+ // okay).
+ PermissionRequestManager::FromWebContents(new_tab)
+ ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ GetUserMedia(new_tab, constraints);
+ std::string result;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ new_tab->GetMainFrame(), "obtainGetUserMediaResult();", &result));
+ EXPECT_EQ(kOkGotStream, result);
+ return new_tab;
+}
+
+content::WebContents* WebRtcTestBase::OpenTestPageAndGetUserMediaInNewTab(
+ const std::string& test_page) const {
+ return OpenPageAndGetUserMediaInNewTab(
+ embedded_test_server()->GetURL(test_page));
+}
+
+content::WebContents* WebRtcTestBase::OpenTestPageInNewTab(
+ const std::string& test_page) const {
+ chrome::AddTabAt(browser(), GURL(), -1, true);
+ GURL url = embedded_test_server()->GetURL(test_page);
+ ui_test_utils::NavigateToURL(browser(), url);
+ content::WebContents* new_tab =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ // Accept if necessary, but don't expect a prompt (because auto-accept is also
+ // okay).
+ PermissionRequestManager::FromWebContents(new_tab)
+ ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ return new_tab;
+}
+
+void WebRtcTestBase::CloseLastLocalStream(
+ content::WebContents* tab_contents) const {
+ EXPECT_EQ("ok-stopped",
+ ExecuteJavascript("stopLocalStream();", tab_contents));
+}
+
+// Convenience method which executes the provided javascript in the context
+// of the provided web contents and returns what it evaluated to.
+std::string WebRtcTestBase::ExecuteJavascript(
+ const std::string& javascript,
+ content::WebContents* tab_contents) const {
+ std::string result;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ tab_contents, javascript, &result));
+ return result;
+}
+
+void WebRtcTestBase::ChangeToLegacyGetStats(content::WebContents* tab) const {
+ content::ExecuteScriptAsync(tab, "changeToLegacyGetStats()");
+}
+
+void WebRtcTestBase::SetupPeerconnectionWithLocalStream(
+ content::WebContents* tab,
+ const std::string& certificate_keygen_algorithm) const {
+ SetupPeerconnectionWithoutLocalStream(tab, certificate_keygen_algorithm);
+ EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", tab));
+}
+
+void WebRtcTestBase::SetupPeerconnectionWithoutLocalStream(
+ content::WebContents* tab,
+ const std::string& certificate_keygen_algorithm) const {
+ std::string javascript = base::StringPrintf(
+ "preparePeerConnection(%s)", certificate_keygen_algorithm.c_str());
+ EXPECT_EQ("ok-peerconnection-created", ExecuteJavascript(javascript, tab));
+}
+
+void WebRtcTestBase::SetupPeerconnectionWithCertificateAndLocalStream(
+ content::WebContents* tab,
+ const std::string& certificate) const {
+ SetupPeerconnectionWithCertificateWithoutLocalStream(tab, certificate);
+ EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", tab));
+}
+
+void WebRtcTestBase::SetupPeerconnectionWithCertificateWithoutLocalStream(
+ content::WebContents* tab,
+ const std::string& certificate) const {
+ std::string javascript = base::StringPrintf(
+ "preparePeerConnectionWithCertificate(%s)", certificate.c_str());
+ EXPECT_EQ("ok-peerconnection-created", ExecuteJavascript(javascript, tab));
+}
+
+void WebRtcTestBase::SetupPeerconnectionWithConstraintsAndLocalStream(
+ content::WebContents* tab,
+ const std::string& constraints,
+ const std::string& certificate_keygen_algorithm) const {
+ std::string javascript = base::StringPrintf(
+ "preparePeerConnection(%s, %s)", certificate_keygen_algorithm.c_str(),
+ constraints.c_str());
+ EXPECT_EQ("ok-peerconnection-created", ExecuteJavascript(javascript, tab));
+ EXPECT_EQ("ok-added", ExecuteJavascript("addLocalStream()", tab));
+}
+
+std::string WebRtcTestBase::CreateLocalOffer(
+ content::WebContents* from_tab) const {
+ std::string response = ExecuteJavascript("createLocalOffer({})", from_tab);
+ EXPECT_EQ("ok-", response.substr(0, 3)) << "Failed to create local offer: "
+ << response;
+
+ std::string local_offer = response.substr(3);
+ return local_offer;
+}
+
+std::string WebRtcTestBase::CreateAnswer(std::string local_offer,
+ content::WebContents* to_tab) const {
+ std::string javascript =
+ base::StringPrintf("receiveOfferFromPeer('%s', {})", local_offer.c_str());
+ std::string response = ExecuteJavascript(javascript, to_tab);
+ EXPECT_EQ("ok-", response.substr(0, 3))
+ << "Receiving peer failed to receive offer and create answer: "
+ << response;
+
+ std::string answer = response.substr(3);
+ response = ExecuteJavascript(
+ base::StringPrintf("verifyDefaultCodecs('%s')", answer.c_str()),
+ to_tab);
+ EXPECT_EQ("ok-", response.substr(0, 3))
+ << "Receiving peer failed to verify default codec: " << response;
+ return answer;
+}
+
+void WebRtcTestBase::ReceiveAnswer(const std::string& answer,
+ content::WebContents* from_tab) const {
+ ASSERT_EQ(
+ "ok-accepted-answer",
+ ExecuteJavascript(
+ base::StringPrintf("receiveAnswerFromPeer('%s')", answer.c_str()),
+ from_tab));
+}
+
+void WebRtcTestBase::GatherAndSendIceCandidates(
+ content::WebContents* from_tab,
+ content::WebContents* to_tab) const {
+ std::string ice_candidates =
+ ExecuteJavascript("getAllIceCandidates()", from_tab);
+
+ EXPECT_EQ("ok-received-candidates", ExecuteJavascript(
+ base::StringPrintf("receiveIceCandidates('%s')", ice_candidates.c_str()),
+ to_tab));
+}
+
+void WebRtcTestBase::CreateDataChannel(content::WebContents* tab,
+ const std::string& label) {
+ EXPECT_EQ("ok-created",
+ ExecuteJavascript("createDataChannel('" + label + "')", tab));
+}
+
+void WebRtcTestBase::NegotiateCall(content::WebContents* from_tab,
+ content::WebContents* to_tab) const {
+ std::string local_offer = CreateLocalOffer(from_tab);
+ std::string answer = CreateAnswer(local_offer, to_tab);
+ ReceiveAnswer(answer, from_tab);
+
+ // Send all ICE candidates (wait for gathering to finish if necessary).
+ GatherAndSendIceCandidates(to_tab, from_tab);
+ GatherAndSendIceCandidates(from_tab, to_tab);
+}
+
+void WebRtcTestBase::VerifyLocalDescriptionContainsCertificate(
+ content::WebContents* tab,
+ const std::string& certificate) const {
+ std::string javascript = base::StringPrintf(
+ "verifyLocalDescriptionContainsCertificate(%s)", certificate.c_str());
+ EXPECT_EQ("ok-verified", ExecuteJavascript(javascript, tab));
+}
+
+void WebRtcTestBase::HangUp(content::WebContents* from_tab) const {
+ EXPECT_EQ("ok-call-hung-up", ExecuteJavascript("hangUp()", from_tab));
+}
+
+void WebRtcTestBase::DetectErrorsInJavaScript() {
+ detect_errors_in_javascript_ = true;
+}
+
+void WebRtcTestBase::StartDetectingVideo(
+ content::WebContents* tab_contents,
+ const std::string& video_element) const {
+ std::string javascript = base::StringPrintf(
+ "startDetection('%s', 320, 240)", video_element.c_str());
+ EXPECT_EQ("ok-started", ExecuteJavascript(javascript, tab_contents));
+}
+
+bool WebRtcTestBase::WaitForVideoToPlay(
+ content::WebContents* tab_contents) const {
+ bool is_video_playing = test::PollingWaitUntil(
+ "isVideoPlaying()", "video-playing", tab_contents);
+ EXPECT_TRUE(is_video_playing);
+ return is_video_playing;
+}
+
+std::string WebRtcTestBase::GetStreamSize(
+ content::WebContents* tab_contents,
+ const std::string& video_element) const {
+ std::string javascript =
+ base::StringPrintf("getStreamSize('%s')", video_element.c_str());
+ std::string result = ExecuteJavascript(javascript, tab_contents);
+ EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
+ return result.substr(3);
+}
+
+bool WebRtcTestBase::OnWin8OrHigher() const {
+#if defined(OS_WIN)
+ return base::win::GetVersion() >= base::win::Version::WIN8;
+#else
+ return false;
+#endif
+}
+
+void WebRtcTestBase::OpenDatabase(content::WebContents* tab) const {
+ EXPECT_EQ("ok-database-opened", ExecuteJavascript("openDatabase()", tab));
+}
+
+void WebRtcTestBase::CloseDatabase(content::WebContents* tab) const {
+ EXPECT_EQ("ok-database-closed", ExecuteJavascript("closeDatabase()", tab));
+}
+
+void WebRtcTestBase::DeleteDatabase(content::WebContents* tab) const {
+ EXPECT_EQ("ok-database-deleted", ExecuteJavascript("deleteDatabase()", tab));
+}
+
+void WebRtcTestBase::GenerateAndCloneCertificate(
+ content::WebContents* tab, const std::string& keygen_algorithm) const {
+ std::string javascript = base::StringPrintf(
+ "generateAndCloneCertificate(%s)", keygen_algorithm.c_str());
+ EXPECT_EQ("ok-generated-and-cloned", ExecuteJavascript(javascript, tab));
+}
+
+void WebRtcTestBase::VerifyStatsGeneratedCallback(
+ content::WebContents* tab) const {
+ EXPECT_EQ("ok-got-stats",
+ ExecuteJavascript("verifyLegacyStatsGenerated()", tab));
+}
+
+std::vector<std::string> WebRtcTestBase::VerifyStatsGeneratedPromise(
+ content::WebContents* tab) const {
+ std::string result = ExecuteJavascript("verifyStatsGeneratedPromise()", tab);
+ EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
+ return JsonArrayToVectorOfStrings(result.substr(3));
+}
+
+double WebRtcTestBase::MeasureGetStatsCallbackPerformance(
+ content::WebContents* tab) const {
+ std::string result = ExecuteJavascript(
+ "measureGetStatsCallbackPerformance()", tab);
+ EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
+ double ms;
+ if (!base::StringToDouble(result.substr(3), &ms))
+ return std::numeric_limits<double>::infinity();
+ return ms;
+}
+
+scoped_refptr<content::TestStatsReportDictionary>
+WebRtcTestBase::GetStatsReportDictionary(content::WebContents* tab) const {
+ std::string result = ExecuteJavascript("getStatsReportDictionary()", tab);
+ EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
+ std::unique_ptr<base::Value> parsed_json =
+ base::JSONReader::ReadDeprecated(result.substr(3));
+ base::DictionaryValue* dictionary;
+ CHECK(parsed_json);
+ CHECK(parsed_json->GetAsDictionary(&dictionary));
+ ignore_result(parsed_json.release());
+ return scoped_refptr<content::TestStatsReportDictionary>(
+ new content::TestStatsReportDictionary(
+ std::unique_ptr<base::DictionaryValue>(dictionary)));
+}
+
+double WebRtcTestBase::MeasureGetStatsPerformance(
+ content::WebContents* tab) const {
+ std::string result = ExecuteJavascript("measureGetStatsPerformance()", tab);
+ EXPECT_TRUE(base::StartsWith(result, "ok-", base::CompareCase::SENSITIVE));
+ double ms;
+ if (!base::StringToDouble(result.substr(3), &ms))
+ return std::numeric_limits<double>::infinity();
+ return ms;
+}
+
+std::vector<std::string> WebRtcTestBase::GetMandatoryStatsTypes(
+ content::WebContents* tab) const {
+ return JsonArrayToVectorOfStrings(
+ ExecuteJavascript("getMandatoryStatsTypes()", tab));
+}
+
+void WebRtcTestBase::SetDefaultAudioCodec(
+ content::WebContents* tab,
+ const std::string& audio_codec) const {
+ EXPECT_EQ("ok", ExecuteJavascript(
+ "setDefaultAudioCodec('" + audio_codec + "')", tab));
+}
+
+void WebRtcTestBase::SetDefaultVideoCodec(content::WebContents* tab,
+ const std::string& video_codec,
+ bool prefer_hw_codec,
+ const std::string& profile) const {
+ std::string codec_profile = profile;
+ // When no |profile| is given, we default VP9 to Profile 0.
+ if (video_codec.compare("VP9") == 0 && codec_profile.empty())
+ codec_profile = kVP9Profile0Specifier;
+
+ EXPECT_EQ("ok", ExecuteJavascript(
+ "setDefaultVideoCodec('" + video_codec + "'," +
+ (prefer_hw_codec ? "true" : "false") + "," +
+ (codec_profile.empty() ? "null"
+ : "'" + codec_profile + "'") +
+ ")",
+ tab));
+}
+
+void WebRtcTestBase::EnableOpusDtx(content::WebContents* tab) const {
+ EXPECT_EQ("ok-forced", ExecuteJavascript("forceOpusDtx()", tab));
+}
+
+std::string WebRtcTestBase::GetDesktopMediaStream(content::WebContents* tab) {
+ DCHECK(static_cast<bool>(LoadDesktopCaptureExtension()));
+
+ // Post a task to the extension, opening a desktop media stream.
+ return ExecuteJavascript("openDesktopMediaStream()", tab);
+}
+
+base::Optional<std::string> WebRtcTestBase::LoadDesktopCaptureExtension() {
+ base::Optional<std::string> extension_id;
+ if (!desktop_capture_extension_.get()) {
+ extensions::ChromeTestExtensionLoader loader(browser()->profile());
+ base::FilePath extension_path;
+ EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &extension_path));
+ extension_path = extension_path.AppendASCII("extensions/desktop_capture");
+ desktop_capture_extension_ = loader.LoadExtension(extension_path);
+ LOG(INFO) << "Loaded desktop capture extension, id = "
+ << desktop_capture_extension_->id();
+
+ extensions::ExtensionRegistry* registry =
+ extensions::ExtensionRegistry::Get(browser()->profile());
+
+ EXPECT_TRUE(registry->enabled_extensions().GetByID(
+ desktop_capture_extension_->id()));
+ }
+ if (desktop_capture_extension_)
+ extension_id.emplace(desktop_capture_extension_->id());
+ return extension_id;
+}