Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / content / browser / media / webrtc_internals_browsertest.cc
blob05c42ccae7bb4ea432d794e5b8480100859f0258
1 // Copyright (c) 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.
5 #include "base/command_line.h"
6 #include "base/json/json_reader.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/time/time.h"
9 #include "base/values.h"
10 #include "content/public/common/content_switches.h"
11 #include "content/public/test/browser_test_utils.h"
12 #include "content/public/test/content_browser_test.h"
13 #include "content/public/test/content_browser_test_utils.h"
14 #include "content/shell/browser/shell.h"
15 #include "media/base/media_switches.h"
16 #include "net/test/embedded_test_server/embedded_test_server.h"
18 using std::string;
19 namespace content {
21 struct SsrcEntry {
22 string GetSsrcAttributeString() const {
23 std::stringstream ss;
24 ss << "a=ssrc:" << id;
25 std::map<string, string>::const_iterator iter;
26 for (iter = properties.begin(); iter != properties.end(); ++iter) {
27 ss << " " << iter->first << ":" << iter->second;
29 return ss.str();
32 string GetAsJSON() const {
33 std::stringstream ss;
34 ss << "{";
35 std::map<string, string>::const_iterator iter;
36 for (iter = properties.begin(); iter != properties.end(); ++iter) {
37 if (iter != properties.begin())
38 ss << ",";
39 ss << "\"" << iter->first << "\":\"" << iter->second << "\"";
41 ss << "}";
42 return ss.str();
45 string id;
46 std::map<string, string> properties;
49 struct EventEntry {
50 string type;
51 string value;
54 struct StatsUnit {
55 string GetString() const {
56 std::stringstream ss;
57 ss << "{timestamp:" << timestamp << ", values:[";
58 std::map<string, string>::const_iterator iter;
59 for (iter = values.begin(); iter != values.end(); ++iter) {
60 ss << "'" << iter->first << "','" << iter->second << "',";
62 ss << "]}";
63 return ss.str();
66 int64 timestamp;
67 std::map<string, string> values;
70 struct StatsEntry {
71 string type;
72 string id;
73 StatsUnit stats;
76 typedef std::map<string, std::vector<string> > StatsMap;
78 class PeerConnectionEntry {
79 public:
80 PeerConnectionEntry(int pid, int lid) : pid_(pid), lid_(lid) {}
82 void AddEvent(const string& type, const string& value) {
83 EventEntry entry = {type, value};
84 events_.push_back(entry);
87 string getIdString() const {
88 std::stringstream ss;
89 ss << pid_ << "-" << lid_;
90 return ss.str();
93 string getLogIdString() const {
94 std::stringstream ss;
95 ss << pid_ << "-" << lid_ << "-update-log";
96 return ss.str();
99 string getAllUpdateString() const {
100 std::stringstream ss;
101 ss << "{pid:" << pid_ << ", lid:" << lid_ << ", log:[";
102 for (size_t i = 0; i < events_.size(); ++i) {
103 ss << "{type:'" << events_[i].type <<
104 "', value:'" << events_[i].value << "'},";
106 ss << "]}";
107 return ss.str();
110 int pid_;
111 int lid_;
112 std::vector<EventEntry> events_;
113 // This is a record of the history of stats value reported for each stats
114 // report id (e.g. ssrc-1234) for each stats name (e.g. framerate).
115 // It a 2-D map with each map entry is a vector of reported values.
116 // It is used to verify the graph data series.
117 std::map<string, StatsMap> stats_;
120 class UserMediaRequestEntry {
121 public:
122 UserMediaRequestEntry(int pid,
123 int rid,
124 const std::string& origin,
125 const std::string& audio_constraints,
126 const std::string& video_constraints)
127 : pid(pid),
128 rid(rid),
129 origin(origin),
130 audio_constraints(audio_constraints),
131 video_constraints(video_constraints) {}
133 int pid;
134 int rid;
135 std::string origin;
136 std::string audio_constraints;
137 std::string video_constraints;
140 static const int64 FAKE_TIME_STAMP = 3600000;
142 #if defined(OS_WIN)
143 // All tests are flaky on Windows: crbug.com/277322.
144 #define MAYBE_WebRtcInternalsBrowserTest DISABLED_WebRtcInternalsBrowserTest
145 #else
146 #define MAYBE_WebRtcInternalsBrowserTest WebRtcInternalsBrowserTest
147 #endif
149 class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
150 public:
151 MAYBE_WebRtcInternalsBrowserTest() {}
152 ~MAYBE_WebRtcInternalsBrowserTest() override {}
154 void SetUpOnMainThread() override {
155 // Assume this is set by the content test launcher.
156 ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
157 switches::kUseFakeUIForMediaStream));
158 ASSERT_TRUE(base::CommandLine::ForCurrentProcess()->HasSwitch(
159 switches::kUseFakeDeviceForMediaStream));
162 protected:
163 bool ExecuteJavascript(const string& javascript) {
164 return ExecuteScript(shell()->web_contents(), javascript);
167 void ExpectTitle(const std::string& expected_title) const {
168 base::string16 expected_title16(base::ASCIIToUTF16(expected_title));
169 TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
170 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
173 // Execute the javascript of addPeerConnection.
174 void ExecuteAddPeerConnectionJs(const PeerConnectionEntry& pc) {
175 std::stringstream ss;
176 ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ << ", " <<
177 "url:'u', rtcConfiguration:'s', constraints:'c'}";
178 ASSERT_TRUE(ExecuteJavascript("addPeerConnection(" + ss.str() + ");"));
181 // Execute the javascript of removePeerConnection.
182 void ExecuteRemovePeerConnectionJs(const PeerConnectionEntry& pc) {
183 std::stringstream ss;
184 ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ << "}";
186 ASSERT_TRUE(ExecuteJavascript("removePeerConnection(" + ss.str() + ");"));
189 // Execute the javascript of addGetUserMedia.
190 void ExecuteAddGetUserMediaJs(const UserMediaRequestEntry& request) {
191 std::stringstream ss;
192 ss << "{pid:" << request.pid << ", rid:" << request.rid << ", origin:'"
193 << request.origin << "', audio:'" << request.audio_constraints
194 << "', video:'" << request.video_constraints << "'}";
196 ASSERT_TRUE(ExecuteJavascript("addGetUserMedia(" + ss.str() + ");"));
199 // Execute the javascript of removeGetUserMediaForRenderer.
200 void ExecuteRemoveGetUserMediaForRendererJs(int rid) {
201 std::stringstream ss;
202 ss << "{rid:" << rid << "}";
203 ASSERT_TRUE(
204 ExecuteJavascript("removeGetUserMediaForRenderer(" + ss.str() + ");"));
207 // Verifies that the DOM element with id |id| exists.
208 void VerifyElementWithId(const string& id) {
209 bool result = false;
210 ASSERT_TRUE(ExecuteScriptAndExtractBool(
211 shell()->web_contents(),
212 "window.domAutomationController.send($('" + id + "') != null);",
213 &result));
214 EXPECT_TRUE(result);
217 // Verifies that the DOM element with id |id| does not exist.
218 void VerifyNoElementWithId(const string& id) {
219 bool result = false;
220 ASSERT_TRUE(ExecuteScriptAndExtractBool(
221 shell()->web_contents(),
222 "window.domAutomationController.send($('" + id + "') == null);",
223 &result));
224 EXPECT_TRUE(result);
227 // Verifies the JS Array of userMediaRequests matches |requests|.
228 void VerifyUserMediaRequest(
229 const std::vector<UserMediaRequestEntry>& requests) {
230 string json_requests;
231 ASSERT_TRUE(ExecuteScriptAndExtractString(
232 shell()->web_contents(),
233 "window.domAutomationController.send("
234 "JSON.stringify(userMediaRequests));",
235 &json_requests));
236 scoped_ptr<base::Value> value_requests;
237 value_requests.reset(base::JSONReader::Read(json_requests));
239 EXPECT_EQ(base::Value::TYPE_LIST, value_requests->GetType());
241 base::ListValue* list_request =
242 static_cast<base::ListValue*>(value_requests.get());
243 EXPECT_EQ(requests.size(), list_request->GetSize());
245 for (size_t i = 0; i < requests.size(); ++i) {
246 base::DictionaryValue* dict = NULL;
247 ASSERT_TRUE(list_request->GetDictionary(i, &dict));
248 int pid, rid;
249 std::string origin, audio, video;
250 ASSERT_TRUE(dict->GetInteger("pid", &pid));
251 ASSERT_TRUE(dict->GetInteger("rid", &rid));
252 ASSERT_TRUE(dict->GetString("origin", &origin));
253 ASSERT_TRUE(dict->GetString("audio", &audio));
254 ASSERT_TRUE(dict->GetString("video", &video));
255 EXPECT_EQ(requests[i].pid, pid);
256 EXPECT_EQ(requests[i].rid, rid);
257 EXPECT_EQ(requests[i].origin, origin);
258 EXPECT_EQ(requests[i].audio_constraints, audio);
259 EXPECT_EQ(requests[i].video_constraints, video);
262 bool user_media_tab_existed = false;
263 ASSERT_TRUE(ExecuteScriptAndExtractBool(
264 shell()->web_contents(),
265 "window.domAutomationController.send("
266 "$('user-media-tab-id') != null);",
267 &user_media_tab_existed));
268 EXPECT_EQ(!requests.empty(), user_media_tab_existed);
270 if (user_media_tab_existed) {
271 int user_media_request_count = -1;
272 ASSERT_TRUE(ExecuteScriptAndExtractInt(
273 shell()->web_contents(),
274 "window.domAutomationController.send("
275 "$('user-media-tab-id').childNodes.length);",
276 &user_media_request_count));
277 ASSERT_EQ(requests.size(), static_cast<size_t>(user_media_request_count));
281 // Verifies that DOM for |pc| is correctly created with the right content.
282 void VerifyPeerConnectionEntry(const PeerConnectionEntry& pc) {
283 VerifyElementWithId(pc.getIdString());
284 if (pc.events_.size() == 0)
285 return;
287 string log_id = pc.getLogIdString();
288 VerifyElementWithId(log_id);
289 string result;
290 for (size_t i = 0; i < pc.events_.size(); ++i) {
291 std::stringstream ss;
292 ss << "var row = $('" << log_id << "').rows[" << (i + 1) << "];"
293 "var cell = row.lastChild;"
294 "window.domAutomationController.send(cell.firstChild.textContent);";
295 ASSERT_TRUE(ExecuteScriptAndExtractString(
296 shell()->web_contents(), ss.str(), &result));
297 EXPECT_EQ(pc.events_[i].type + pc.events_[i].value, result);
301 // Executes the javascript of updatePeerConnection and verifies the result.
302 void ExecuteAndVerifyUpdatePeerConnection(
303 PeerConnectionEntry& pc, const string& type, const string& value) {
304 pc.AddEvent(type, value);
306 std::stringstream ss;
307 ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ <<
308 ", type:'" << type << "', value:'" << value << "'}";
309 ASSERT_TRUE(ExecuteJavascript("updatePeerConnection(" + ss.str() + ")"));
311 VerifyPeerConnectionEntry(pc);
314 // Execute addStats and verifies that the stats table has the right content.
315 void ExecuteAndVerifyAddStats(
316 PeerConnectionEntry& pc, const string& type, const string& id,
317 StatsUnit& stats) {
318 StatsEntry entry = {type, id, stats};
320 // Adds each new value to the map of stats history.
321 std::map<string, string>::iterator iter;
322 for (iter = stats.values.begin(); iter != stats.values.end(); iter++) {
323 pc.stats_[id][iter->first].push_back(iter->second);
325 std::stringstream ss;
326 ss << "{pid:" << pc.pid_ << ", lid:" << pc.lid_ << ","
327 "reports:[" << "{id:'" << id << "', type:'" << type << "', "
328 "stats:" << stats.GetString() << "}]}";
330 ASSERT_TRUE(ExecuteJavascript("addStats(" + ss.str() + ")"));
331 VerifyStatsTable(pc, entry);
335 // Verifies that the stats table has the right content.
336 void VerifyStatsTable(const PeerConnectionEntry& pc,
337 const StatsEntry& report) {
338 string table_id =
339 pc.getIdString() + "-table-" + report.id;
340 VerifyElementWithId(table_id);
342 std::map<string, string>::const_iterator iter;
343 for (iter = report.stats.values.begin();
344 iter != report.stats.values.end(); iter++) {
345 VerifyStatsTableRow(table_id, iter->first, iter->second);
349 // Verifies that the row named as |name| of the stats table |table_id| has
350 // the correct content as |name| : |value|.
351 void VerifyStatsTableRow(const string& table_id,
352 const string& name,
353 const string& value) {
354 VerifyElementWithId(table_id + "-" + name);
356 string result;
357 ASSERT_TRUE(ExecuteScriptAndExtractString(
358 shell()->web_contents(),
359 "var row = $('" + table_id + "-" + name + "');"
360 "var name = row.cells[0].textContent;"
361 "var value = row.cells[1].textContent;"
362 "window.domAutomationController.send(name + ':' + value)",
363 &result));
364 EXPECT_EQ(name + ":" + value, result);
367 // Verifies that the graph data series consistent with pc.stats_.
368 void VerifyStatsGraph(const PeerConnectionEntry& pc) {
369 std::map<string, StatsMap>::const_iterator stream_iter;
370 for (stream_iter = pc.stats_.begin();
371 stream_iter != pc.stats_.end(); stream_iter++) {
372 StatsMap::const_iterator stats_iter;
373 for (stats_iter = stream_iter->second.begin();
374 stats_iter != stream_iter->second.end();
375 stats_iter++) {
376 string graph_id = stream_iter->first + "-" + stats_iter->first;
377 for (size_t i = 0; i < stats_iter->second.size(); ++i) {
378 float number;
379 std::stringstream stream(stats_iter->second[i]);
380 stream >> number;
381 if (stream.fail())
382 continue;
383 VerifyGraphDataPoint(
384 pc.getIdString(), graph_id, i, stats_iter->second[i]);
390 // Verifies that the graph data point at index |index| has value |value|.
391 void VerifyGraphDataPoint(const string& pc_id, const string& graph_id,
392 int index, const string& value) {
393 bool result = false;
394 ASSERT_TRUE(ExecuteScriptAndExtractBool(
395 shell()->web_contents(),
396 "window.domAutomationController.send("
397 "graphViews['" + pc_id + "-" + graph_id + "'] != null)",
398 &result));
399 EXPECT_TRUE(result);
401 std::stringstream ss;
402 ss << "var dp = peerConnectionDataStore['" << pc_id << "']"
403 ".getDataSeries('" << graph_id << "').dataPoints_[" << index << "];"
404 "window.domAutomationController.send(dp.value.toString())";
405 string actual_value;
406 ASSERT_TRUE(ExecuteScriptAndExtractString(
407 shell()->web_contents(), ss.str(), &actual_value));
408 EXPECT_EQ(value, actual_value);
411 // Get the JSON string of the ssrc info from the page.
412 string GetSsrcInfo(const string& ssrc_id) {
413 string result;
414 EXPECT_TRUE(ExecuteScriptAndExtractString(
415 shell()->web_contents(),
416 "window.domAutomationController.send(JSON.stringify("
417 "ssrcInfoManager.streamInfoContainer_['" + ssrc_id + "']))",
418 &result));
419 return result;
422 int GetSsrcInfoBlockCount(Shell* shell) {
423 int count = 0;
424 EXPECT_TRUE(ExecuteScriptAndExtractInt(
425 shell->web_contents(),
426 "window.domAutomationController.send("
427 "document.getElementsByClassName("
428 "ssrcInfoManager.SSRC_INFO_BLOCK_CLASS).length);",
429 &count));
430 return count;
433 // Verifies |dump| contains |peer_connection_number| peer connection dumps,
434 // each containing |update_number| updates and |stats_number| stats tables.
435 void VerifyPageDumpStructure(base::Value* dump,
436 int peer_connection_number,
437 int update_number,
438 int stats_number) {
439 EXPECT_NE((base::Value*)NULL, dump);
440 EXPECT_EQ(base::Value::TYPE_DICTIONARY, dump->GetType());
442 base::DictionaryValue* dict_dump =
443 static_cast<base::DictionaryValue*>(dump);
444 EXPECT_EQ((size_t) peer_connection_number, dict_dump->size());
446 base::DictionaryValue::Iterator it(*dict_dump);
447 for (; !it.IsAtEnd(); it.Advance()) {
448 base::Value* value = NULL;
449 dict_dump->Get(it.key(), &value);
450 EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
451 base::DictionaryValue* pc_dump =
452 static_cast<base::DictionaryValue*>(value);
453 EXPECT_TRUE(pc_dump->HasKey("updateLog"));
454 EXPECT_TRUE(pc_dump->HasKey("stats"));
456 // Verifies the number of updates.
457 pc_dump->Get("updateLog", &value);
458 EXPECT_EQ(base::Value::TYPE_LIST, value->GetType());
459 base::ListValue* list = static_cast<base::ListValue*>(value);
460 EXPECT_EQ((size_t) update_number, list->GetSize());
462 // Verifies the number of stats tables.
463 pc_dump->Get("stats", &value);
464 EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
465 base::DictionaryValue* dict = static_cast<base::DictionaryValue*>(value);
466 EXPECT_EQ((size_t) stats_number, dict->size());
470 // Verifies |dump| contains the correct statsTable and statsDataSeries for
471 // |pc|.
472 void VerifyStatsDump(base::Value* dump,
473 const PeerConnectionEntry& pc,
474 const string& report_type,
475 const string& report_id,
476 const StatsUnit& stats) {
477 EXPECT_NE((base::Value*)NULL, dump);
478 EXPECT_EQ(base::Value::TYPE_DICTIONARY, dump->GetType());
480 base::DictionaryValue* dict_dump =
481 static_cast<base::DictionaryValue*>(dump);
482 base::Value* value = NULL;
483 dict_dump->Get(pc.getIdString(), &value);
484 base::DictionaryValue* pc_dump = static_cast<base::DictionaryValue*>(value);
486 // Verifies there is one data series per stats name.
487 value = NULL;
488 pc_dump->Get("stats", &value);
489 EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
491 base::DictionaryValue* dataSeries =
492 static_cast<base::DictionaryValue*>(value);
493 EXPECT_EQ(stats.values.size(), dataSeries->size());
497 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
498 AddAndRemovePeerConnection) {
499 GURL url("chrome://webrtc-internals");
500 NavigateToURL(shell(), url);
502 // Add two PeerConnections and then remove them.
503 PeerConnectionEntry pc_1(1, 0);
504 ExecuteAddPeerConnectionJs(pc_1);
505 VerifyPeerConnectionEntry(pc_1);
507 PeerConnectionEntry pc_2(2, 1);
508 ExecuteAddPeerConnectionJs(pc_2);
509 VerifyPeerConnectionEntry(pc_2);
511 ExecuteRemovePeerConnectionJs(pc_1);
512 VerifyNoElementWithId(pc_1.getIdString());
513 VerifyPeerConnectionEntry(pc_2);
515 ExecuteRemovePeerConnectionJs(pc_2);
516 VerifyNoElementWithId(pc_2.getIdString());
519 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
520 UpdateAllPeerConnections) {
521 GURL url("chrome://webrtc-internals");
522 NavigateToURL(shell(), url);
524 PeerConnectionEntry pc_0(1, 0);
525 pc_0.AddEvent("e1", "v1");
526 pc_0.AddEvent("e2", "v2");
527 PeerConnectionEntry pc_1(1, 1);
528 pc_1.AddEvent("e3", "v3");
529 pc_1.AddEvent("e4", "v4");
530 string pc_array = "[" + pc_0.getAllUpdateString() + ", " +
531 pc_1.getAllUpdateString() + "]";
532 EXPECT_TRUE(ExecuteJavascript("updateAllPeerConnections(" + pc_array + ");"));
533 VerifyPeerConnectionEntry(pc_0);
534 VerifyPeerConnectionEntry(pc_1);
537 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, UpdatePeerConnection) {
538 GURL url("chrome://webrtc-internals");
539 NavigateToURL(shell(), url);
541 // Add one PeerConnection and send one update.
542 PeerConnectionEntry pc_1(1, 0);
543 ExecuteAddPeerConnectionJs(pc_1);
545 ExecuteAndVerifyUpdatePeerConnection(pc_1, "e1", "v1");
547 // Add another PeerConnection and send two updates.
548 PeerConnectionEntry pc_2(1, 1);
549 ExecuteAddPeerConnectionJs(pc_2);
551 SsrcEntry ssrc1, ssrc2;
552 ssrc1.id = "ssrcid1";
553 ssrc1.properties["msid"] = "mymsid";
554 ssrc2.id = "ssrcid2";
555 ssrc2.properties["label"] = "mylabel";
556 ssrc2.properties["cname"] = "mycname";
558 ExecuteAndVerifyUpdatePeerConnection(pc_2, "setRemoteDescription",
559 ssrc1.GetSsrcAttributeString());
561 ExecuteAndVerifyUpdatePeerConnection(pc_2, "setLocalDescription",
562 ssrc2.GetSsrcAttributeString());
564 EXPECT_EQ(ssrc1.GetAsJSON(), GetSsrcInfo(ssrc1.id));
565 EXPECT_EQ(ssrc2.GetAsJSON(), GetSsrcInfo(ssrc2.id));
567 StatsUnit stats = {FAKE_TIME_STAMP};
568 stats.values["ssrc"] = ssrc1.id;
569 ExecuteAndVerifyAddStats(pc_2, "ssrc", "dummyId", stats);
570 EXPECT_GT(GetSsrcInfoBlockCount(shell()), 0);
573 // Tests that adding random named stats updates the dataSeries and graphs.
574 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, AddStats) {
575 GURL url("chrome://webrtc-internals");
576 NavigateToURL(shell(), url);
578 PeerConnectionEntry pc(1, 0);
579 ExecuteAddPeerConnectionJs(pc);
581 const string type = "ssrc";
582 const string id = "ssrc-1234";
583 StatsUnit stats = {FAKE_TIME_STAMP};
584 stats.values["trackId"] = "abcd";
585 stats.values["bitrate"] = "2000";
586 stats.values["framerate"] = "30";
588 // Add new stats and verify the stats table and graphs.
589 ExecuteAndVerifyAddStats(pc, type, id, stats);
590 VerifyStatsGraph(pc);
592 // Update existing stats and verify the stats table and graphs.
593 stats.values["bitrate"] = "2001";
594 stats.values["framerate"] = "31";
595 ExecuteAndVerifyAddStats(pc, type, id, stats);
596 VerifyStatsGraph(pc);
599 // Tests that the bandwidth estimation values are drawn on a single graph.
600 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, BweCompoundGraph) {
601 GURL url("chrome://webrtc-internals");
602 NavigateToURL(shell(), url);
604 PeerConnectionEntry pc(1, 0);
605 ExecuteAddPeerConnectionJs(pc);
607 StatsUnit stats = {FAKE_TIME_STAMP};
608 stats.values["googAvailableSendBandwidth"] = "1000000";
609 stats.values["googTargetEncBitrate"] = "1000";
610 stats.values["googActualEncBitrate"] = "1000000";
611 stats.values["googRetransmitBitrate"] = "10";
612 stats.values["googTransmitBitrate"] = "1000000";
613 const string stats_type = "bwe";
614 const string stats_id = "videobwe";
615 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
617 string graph_id =
618 pc.getIdString() + "-" + stats_id + "-bweCompound";
619 bool result = false;
620 // Verify that the bweCompound graph exists.
621 ASSERT_TRUE(ExecuteScriptAndExtractBool(
622 shell()->web_contents(),
623 "window.domAutomationController.send("
624 " graphViews['" + graph_id + "'] != null)",
625 &result));
626 EXPECT_TRUE(result);
628 // Verify that the bweCompound graph contains multiple dataSeries.
629 int count = 0;
630 ASSERT_TRUE(ExecuteScriptAndExtractInt(
631 shell()->web_contents(),
632 "window.domAutomationController.send("
633 " graphViews['" + graph_id + "'].getDataSeriesCount())",
634 &count));
635 EXPECT_EQ((int)stats.values.size(), count);
638 // Tests that the total packet/byte count is converted to count per second,
639 // and the converted data is drawn.
640 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, ConvertedGraphs) {
641 GURL url("chrome://webrtc-internals");
642 NavigateToURL(shell(), url);
644 PeerConnectionEntry pc(1, 0);
645 ExecuteAddPeerConnectionJs(pc);
647 const string stats_type = "s";
648 const string stats_id = "1";
649 const int num_converted_stats = 4;
650 const string stats_names[] =
651 {"packetsSent", "bytesSent", "packetsReceived", "bytesReceived"};
652 const string converted_names[] =
653 {"packetsSentPerSecond", "bitsSentPerSecond",
654 "packetsReceivedPerSecond", "bitsReceivedPerSecond"};
655 const string first_value = "1000";
656 const string second_value = "2000";
657 const string converted_values[] = {"1000", "8000", "1000", "8000"};
659 // Send the first data point.
660 StatsUnit stats = {FAKE_TIME_STAMP};
661 for (int i = 0; i < num_converted_stats; ++i)
662 stats.values[stats_names[i]] = first_value;
664 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
666 // Send the second data point at 1000ms after the first data point.
667 stats.timestamp += 1000;
668 for (int i = 0; i < num_converted_stats; ++i)
669 stats.values[stats_names[i]] = second_value;
670 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
672 // Verifies the graph data matches converted_values.
673 for (int i = 0; i < num_converted_stats; ++i) {
674 VerifyGraphDataPoint(pc.getIdString(), stats_id + "-" + converted_names[i],
675 1, converted_values[i]);
679 // Timing out on ARM linux bot: http://crbug.com/238490
680 // Disabling due to failure on Linux, Mac, Win: http://crbug.com/272413
681 // Sanity check of the page content under a real PeerConnection call.
682 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
683 DISABLED_WithRealPeerConnectionCall) {
684 // Start a peerconnection call in the first window.
685 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
686 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
687 NavigateToURL(shell(), url);
688 ASSERT_TRUE(ExecuteJavascript("call({video:true});"));
689 ExpectTitle("OK");
691 // Open webrtc-internals in the second window.
692 GURL url2("chrome://webrtc-internals");
693 Shell* shell2 = CreateBrowser();
694 NavigateToURL(shell2, url2);
696 const int NUMBER_OF_PEER_CONNECTIONS = 2;
698 // Verifies the number of peerconnections.
699 int count = 0;
700 ASSERT_TRUE(ExecuteScriptAndExtractInt(
701 shell2->web_contents(),
702 "window.domAutomationController.send("
703 "$('peer-connections-list').getElementsByTagName('li').length);",
704 &count));
705 EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
707 // Verifies the the event tables.
708 ASSERT_TRUE(ExecuteScriptAndExtractInt(
709 shell2->web_contents(),
710 "window.domAutomationController.send($('peer-connections-list')"
711 ".getElementsByClassName('update-log-table').length);",
712 &count));
713 EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
715 ASSERT_TRUE(ExecuteScriptAndExtractInt(
716 shell2->web_contents(),
717 "window.domAutomationController.send($('peer-connections-list')"
718 ".getElementsByClassName('update-log-table')[0].rows.length);",
719 &count));
720 EXPECT_GT(count, 1);
722 ASSERT_TRUE(ExecuteScriptAndExtractInt(
723 shell2->web_contents(),
724 "window.domAutomationController.send($('peer-connections-list')"
725 ".getElementsByClassName('update-log-table')[1].rows.length);",
726 &count));
727 EXPECT_GT(count, 1);
729 // Wait until the stats table containers are created.
730 count = 0;
731 while (count != NUMBER_OF_PEER_CONNECTIONS) {
732 ASSERT_TRUE(ExecuteScriptAndExtractInt(
733 shell2->web_contents(),
734 "window.domAutomationController.send("
735 "$('peer-connections-list').getElementsByClassName("
736 "'stats-table-container').length);",
737 &count));
740 // Verifies each stats table having more than one rows.
741 bool result = false;
742 ASSERT_TRUE(ExecuteScriptAndExtractBool(
743 shell2->web_contents(),
744 "var tableContainers = $('peer-connections-list')"
745 ".getElementsByClassName('stats-table-container');"
746 "var result = true;"
747 "for (var i = 0; i < tableContainers.length && result; ++i) {"
748 "var tables = tableContainers[i].getElementsByTagName('table');"
749 "for (var j = 0; j < tables.length && result; ++j) {"
750 "result = (tables[j].rows.length > 1);"
752 "if (!result) {"
753 "console.log(tableContainers[i].innerHTML);"
756 "window.domAutomationController.send(result);",
757 &result));
759 EXPECT_TRUE(result);
761 count = GetSsrcInfoBlockCount(shell2);
762 EXPECT_GT(count, 0);
765 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, CreatePageDump) {
766 GURL url("chrome://webrtc-internals");
767 NavigateToURL(shell(), url);
769 PeerConnectionEntry pc_0(1, 0);
770 pc_0.AddEvent("e1", "v1");
771 pc_0.AddEvent("e2", "v2");
772 PeerConnectionEntry pc_1(1, 1);
773 pc_1.AddEvent("e3", "v3");
774 pc_1.AddEvent("e4", "v4");
775 string pc_array =
776 "[" + pc_0.getAllUpdateString() + ", " + pc_1.getAllUpdateString() + "]";
777 EXPECT_TRUE(ExecuteJavascript("updateAllPeerConnections(" + pc_array + ");"));
779 // Verifies the peer connection data store can be created without stats.
780 string dump_json;
781 ASSERT_TRUE(ExecuteScriptAndExtractString(
782 shell()->web_contents(),
783 "window.domAutomationController.send("
784 "JSON.stringify(peerConnectionDataStore));",
785 &dump_json));
786 scoped_ptr<base::Value> dump;
787 dump.reset(base::JSONReader::Read(dump_json));
788 VerifyPageDumpStructure(dump.get(),
789 2 /*peer_connection_number*/,
790 2 /*update_number*/,
791 0 /*stats_number*/);
793 // Adds a stats report.
794 const string type = "dummy";
795 const string id = "1234";
796 StatsUnit stats = { FAKE_TIME_STAMP };
797 stats.values["bitrate"] = "2000";
798 stats.values["framerate"] = "30";
799 ExecuteAndVerifyAddStats(pc_0, type, id, stats);
801 ASSERT_TRUE(ExecuteScriptAndExtractString(
802 shell()->web_contents(),
803 "window.domAutomationController.send("
804 "JSON.stringify(peerConnectionDataStore));",
805 &dump_json));
806 dump.reset(base::JSONReader::Read(dump_json));
807 VerifyStatsDump(dump.get(), pc_0, type, id, stats);
810 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, UpdateGetUserMedia) {
811 GURL url("chrome://webrtc-internals");
812 NavigateToURL(shell(), url);
814 UserMediaRequestEntry request1(1, 1, "origin", "ac", "vc");
815 UserMediaRequestEntry request2(2, 2, "origin2", "ac2", "vc2");
816 ExecuteAddGetUserMediaJs(request1);
817 ExecuteAddGetUserMediaJs(request2);
819 std::vector<UserMediaRequestEntry> list;
820 list.push_back(request1);
821 list.push_back(request2);
822 VerifyUserMediaRequest(list);
824 ExecuteRemoveGetUserMediaForRendererJs(1);
825 list.erase(list.begin());
826 VerifyUserMediaRequest(list);
828 ExecuteRemoveGetUserMediaForRendererJs(2);
829 list.erase(list.begin());
830 VerifyUserMediaRequest(list);
833 // Tests that the received propagation delta values are converted and drawn
834 // correctly.
835 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
836 ReceivedPropagationDelta) {
837 GURL url("chrome://webrtc-internals");
838 NavigateToURL(shell(), url);
840 PeerConnectionEntry pc(1, 0);
841 ExecuteAddPeerConnectionJs(pc);
843 StatsUnit stats = {FAKE_TIME_STAMP};
844 stats.values["googReceivedPacketGroupArrivalTimeDebug"] =
845 "[1000, 1100, 1200]";
846 stats.values["googReceivedPacketGroupPropagationDeltaDebug"] =
847 "[10, 20, 30]";
848 const string stats_type = "bwe";
849 const string stats_id = "videobwe";
850 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
852 string graph_id = pc.getIdString() + "-" + stats_id +
853 "-googReceivedPacketGroupPropagationDeltaDebug";
854 string data_series_id =
855 stats_id + "-googReceivedPacketGroupPropagationDeltaDebug";
856 bool result = false;
857 // Verify that the graph exists.
858 ASSERT_TRUE(ExecuteScriptAndExtractBool(
859 shell()->web_contents(),
860 "window.domAutomationController.send("
861 " graphViews['" + graph_id + "'] != null)",
862 &result));
863 EXPECT_TRUE(result);
865 // Verify that the graph contains multiple data points.
866 int count = 0;
867 ASSERT_TRUE(ExecuteScriptAndExtractInt(
868 shell()->web_contents(),
869 "window.domAutomationController.send("
870 " graphViews['" + graph_id + "'].getDataSeriesCount())",
871 &count));
872 EXPECT_EQ(1, count);
873 ASSERT_TRUE(ExecuteScriptAndExtractInt(
874 shell()->web_contents(),
875 "window.domAutomationController.send("
876 " peerConnectionDataStore['" + pc.getIdString() + "']" +
877 " .getDataSeries('" + data_series_id + "').getCount())",
878 &count));
879 EXPECT_EQ(3, count);
882 } // namespace content