1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_BROWSERTEST_BASE_H_ 6 #define CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_BROWSERTEST_BASE_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/macros.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/optional.h" 14 #include "chrome/browser/media/webrtc/test_stats_dictionary.h" 15 #include "chrome/test/base/in_process_browser_test.h" 16 17 namespace infobars { 18 class InfoBar; 19 } 20 21 namespace content { 22 class WebContents; 23 } 24 25 namespace extensions { 26 class Extension; 27 } 28 29 // Base class for WebRTC browser tests with useful primitives for interacting 30 // getUserMedia. We use inheritance here because it makes the test code look 31 // as clean as it can be. 32 class WebRtcTestBase : public InProcessBrowserTest { 33 public: 34 // Typical constraints. 35 static const char kAudioVideoCallConstraints[]; 36 static const char kAudioOnlyCallConstraints[]; 37 static const char kVideoOnlyCallConstraints[]; 38 static const char kVideoCallConstraintsQVGA[]; 39 static const char kVideoCallConstraints360p[]; 40 static const char kVideoCallConstraintsVGA[]; 41 static const char kVideoCallConstraints720p[]; 42 static const char kVideoCallConstraints1080p[]; 43 static const char kAudioVideoCallConstraints360p[]; 44 static const char kAudioVideoCallConstraints720p[]; 45 46 static const char kOkGotStream[]; 47 static const char kFailedWithNotAllowedError[]; 48 49 static const char kUseDefaultCertKeygen[]; 50 static const char kUseDefaultAudioCodec[]; 51 static const char kUseDefaultVideoCodec[]; 52 53 static const char kVP9Profile0Specifier[]; 54 static const char kVP9Profile2Specifier[]; 55 56 static const char kUndefined[]; 57 58 enum class StreamArgumentType { 59 NO_STREAM, 60 SHARED_STREAM, 61 INDIVIDUAL_STREAMS 62 }; 63 64 protected: 65 WebRtcTestBase(); 66 ~WebRtcTestBase() override; 67 68 // These all require that the loaded page fulfills the public interface in 69 // chrome/test/data/webrtc/getusermedia.js. 70 // If an error is reported back from the getUserMedia call, these functions 71 // will return false. 72 // The ...AndAccept()/...AndDeny()/...AndDismiss() functions expect that a 73 // prompt will be shown (i.e. the current origin in the tab_contents doesn't 74 // have a saved permission). 75 bool GetUserMediaAndAccept(content::WebContents* tab_contents) const; 76 bool GetUserMediaWithSpecificConstraintsAndAccept( 77 content::WebContents* tab_contents, 78 const std::string& constraints) const; 79 bool GetUserMediaWithSpecificConstraintsAndAcceptIfPrompted( 80 content::WebContents* tab_contents, 81 const std::string& constraints) const; 82 void GetUserMediaAndDeny(content::WebContents* tab_contents); 83 void GetUserMediaWithSpecificConstraintsAndDeny( 84 content::WebContents* tab_contents, 85 const std::string& constraints) const; 86 void GetUserMediaAndDismiss(content::WebContents* tab_contents) const; 87 void GetUserMediaAndExpectAutoAcceptWithoutPrompt( 88 content::WebContents* tab_contents) const; 89 void GetUserMediaAndExpectAutoDenyWithoutPrompt( 90 content::WebContents* tab_contents) const; 91 void GetUserMedia(content::WebContents* tab_contents, 92 const std::string& constraints) const; 93 94 // Convenience method which opens the page at url, calls GetUserMediaAndAccept 95 // and returns the new tab. 96 content::WebContents* OpenPageAndGetUserMediaInNewTab(const GURL& url) const; 97 98 // Convenience method which opens the page at url, calls 99 // GetUserMediaAndAcceptWithSpecificConstraints and returns the new tab. 100 content::WebContents* OpenPageAndGetUserMediaInNewTabWithConstraints( 101 const GURL& url, const std::string& constraints) const; 102 103 // Convenience method which gets the URL for |test_page| and calls 104 // OpenPageAndGetUserMediaInNewTab(). 105 content::WebContents* OpenTestPageAndGetUserMediaInNewTab( 106 const std::string& test_page) const; 107 108 // Convenience method which gets the URL for |test_page|, but without calling 109 // GetUserMedia. 110 content::WebContents* OpenTestPageInNewTab( 111 const std::string& test_page) const; 112 113 // Closes the last local stream acquired by the GetUserMedia* methods. 114 void CloseLastLocalStream(content::WebContents* tab_contents) const; 115 116 std::string ExecuteJavascript(const std::string& javascript, 117 content::WebContents* tab_contents) const; 118 119 // TODO(https://crbug.com/1004239): Remove this function as soon as browser 120 // tests stop relying on the legacy getStats() API. 121 void ChangeToLegacyGetStats(content::WebContents* tab) const; 122 123 // Sets up a peer connection in the tab and adds the current local stream 124 // (which you can prepare by calling one of the GetUserMedia* methods above). 125 // Optionally, |certificate_keygen_algorithm| is JavaScript for an 126 // |AlgorithmIdentifier| to be used as parameter to 127 // |RTCPeerConnection.generateCertificate|. The resulting certificate will be 128 // used by the peer connection. Or use |kUseDefaultCertKeygen| to use a 129 // certificate. 130 void SetupPeerconnectionWithLocalStream( 131 content::WebContents* tab, 132 const std::string& certificate_keygen_algorithm = 133 kUseDefaultCertKeygen) const; 134 // Same as above but does not add the local stream. 135 void SetupPeerconnectionWithoutLocalStream( 136 content::WebContents* tab, 137 const std::string& certificate_keygen_algorithm = 138 kUseDefaultCertKeygen) const; 139 // Same as |SetupPeerconnectionWithLocalStream| except a certificate is 140 // specified, which is a reference to an |RTCCertificate| object. 141 void SetupPeerconnectionWithCertificateAndLocalStream( 142 content::WebContents* tab, 143 const std::string& certificate) const; 144 // Same as above but does not add the local stream. 145 void SetupPeerconnectionWithCertificateWithoutLocalStream( 146 content::WebContents* tab, 147 const std::string& certificate) const; 148 // Same as |SetupPeerconnectionWithLocalStream| except RTCPeerConnection 149 // constraints are specified. 150 void SetupPeerconnectionWithConstraintsAndLocalStream( 151 content::WebContents* tab, 152 const std::string& constraints, 153 const std::string& certificate_keygen_algorithm = 154 kUseDefaultCertKeygen) const; 155 156 void CreateDataChannel(content::WebContents* tab, const std::string& label); 157 158 // Exchanges offers and answers between the peer connections in the 159 // respective tabs. Before calling this, you must have prepared peer 160 // connections in both tabs and configured them as you like (for instance by 161 // calling SetupPeerconnectionWithLocalStream). 162 // If |video_codec| is not |kUseDefaultVideoCodec|, the SDP offer is modified 163 // (and SDP answer verified) so that the specified video codec (case-sensitive 164 // name) is used during the call instead of the default one. 165 void NegotiateCall(content::WebContents* from_tab, 166 content::WebContents* to_tab) const; 167 168 void VerifyLocalDescriptionContainsCertificate( 169 content::WebContents* tab, 170 const std::string& certificate) const; 171 172 // Hangs up a negotiated call. 173 void HangUp(content::WebContents* from_tab) const; 174 175 // Call this to enable monitoring of javascript errors for this test method. 176 // This will only work if the tests are run sequentially by the test runner 177 // (i.e. with --test-launcher-developer-mode or --test-launcher-jobs=1). 178 void DetectErrorsInJavaScript(); 179 180 // Methods for detecting if video is playing (the loaded page must have 181 // chrome/test/data/webrtc/video_detector.js and its dependencies loaded to 182 // make that work). Looks at a 320x240 area of the target video tag. 183 void StartDetectingVideo(content::WebContents* tab_contents, 184 const std::string& video_element) const; 185 186 // Wait for a video to start/stop playing. StartDetectingVideo must have 187 // been called already. 188 bool WaitForVideoToPlay(content::WebContents* tab_contents) const; 189 bool WaitForVideoToStop(content::WebContents* tab_contents) const; 190 191 // Returns the stream size as a string on the format <width>x<height>. 192 std::string GetStreamSize(content::WebContents* tab_contents, 193 const std::string& video_element) const; 194 195 // Returns true if we're on Windows 8 or higher. 196 bool OnWin8OrHigher() const; 197 198 void OpenDatabase(content::WebContents* tab) const; 199 void CloseDatabase(content::WebContents* tab) const; 200 void DeleteDatabase(content::WebContents* tab) const; 201 202 void GenerateAndCloneCertificate(content::WebContents* tab, 203 const std::string& keygen_algorithm) const; 204 205 void VerifyStatsGeneratedCallback(content::WebContents* tab) const; 206 double MeasureGetStatsCallbackPerformance(content::WebContents* tab) const; 207 std::vector<std::string> VerifyStatsGeneratedPromise( 208 content::WebContents* tab) const; 209 scoped_refptr<content::TestStatsReportDictionary> GetStatsReportDictionary( 210 content::WebContents* tab) const; 211 double MeasureGetStatsPerformance(content::WebContents* tab) const; 212 std::vector<std::string> GetMandatoryStatsTypes( 213 content::WebContents* tab) const; 214 215 // Change the default audio/video codec in the offer SDP. 216 void SetDefaultAudioCodec(content::WebContents* tab, 217 const std::string& audio_codec) const; 218 // |prefer_hw_codec| controls what codec with name |video_codec| (and with 219 // profile |profile| if given)should be selected. This parameter only matters 220 // if there are multiple codecs with the same name, which can be the case for 221 // H264. 222 void SetDefaultVideoCodec(content::WebContents* tab, 223 const std::string& video_codec, 224 bool prefer_hw_codec = false, 225 const std::string& profile = std::string()) const; 226 227 // Add 'usedtx=1' to the offer SDP. 228 void EnableOpusDtx(content::WebContents* tab) const; 229 230 // Try to open a dekstop media stream, and return the stream id. 231 // On failure, will return empty string. 232 std::string GetDesktopMediaStream(content::WebContents* tab); 233 base::Optional<std::string> LoadDesktopCaptureExtension(); 234 235 private: 236 void CloseInfoBarInTab(content::WebContents* tab_contents, 237 infobars::InfoBar* infobar) const; 238 239 std::string CreateLocalOffer(content::WebContents* from_tab) const; 240 std::string CreateAnswer(std::string local_offer, 241 content::WebContents* to_tab) const; 242 void ReceiveAnswer(const std::string& answer, 243 content::WebContents* from_tab) const; 244 void GatherAndSendIceCandidates(content::WebContents* from_tab, 245 content::WebContents* to_tab) const; 246 bool HasStreamWithTrack(content::WebContents* tab, 247 const char* function_name, 248 std::string stream_id, 249 std::string track_id) const; 250 251 infobars::InfoBar* GetUserMediaAndWaitForInfoBar( 252 content::WebContents* tab_contents, 253 const std::string& constraints) const; 254 255 bool detect_errors_in_javascript_; 256 scoped_refptr<const extensions::Extension> desktop_capture_extension_; 257 258 DISALLOW_COPY_AND_ASSIGN(WebRtcTestBase); 259 }; 260 261 #endif // CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_BROWSERTEST_BASE_H_ 262