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/shell/browser/shell.h"
13 #include "content/test/content_browser_test.h"
14 #include "content/test/content_browser_test_utils.h"
15 #include "net/test/embedded_test_server/embedded_test_server.h"
21 string
GetSsrcAttributeString() const {
23 ss
<< "a=ssrc:" << id
;
24 std::map
<string
, string
>::const_iterator iter
;
25 for (iter
= properties
.begin(); iter
!= properties
.end(); ++iter
) {
26 ss
<< " " << iter
->first
<< ":" << iter
->second
;
31 string
GetAsJSON() const {
34 std::map
<string
, string
>::const_iterator iter
;
35 for (iter
= properties
.begin(); iter
!= properties
.end(); ++iter
) {
36 if (iter
!= properties
.begin())
38 ss
<< "\"" << iter
->first
<< "\":\"" << iter
->second
<< "\"";
45 std::map
<string
, string
> properties
;
54 string
GetString() const {
56 ss
<< "{timestamp:" << timestamp
<< ", values:[";
57 std::map
<string
, string
>::const_iterator iter
;
58 for (iter
= values
.begin(); iter
!= values
.end(); ++iter
) {
59 ss
<< "'" << iter
->first
<< "','" << iter
->second
<< "',";
66 std::map
<string
, string
> values
;
75 typedef std::map
<string
, std::vector
<string
> > StatsMap
;
77 class PeerConnectionEntry
{
79 PeerConnectionEntry(int pid
, int lid
) : pid_(pid
), lid_(lid
) {}
81 void AddEvent(const string
& type
, const string
& value
) {
82 EventEntry entry
= {type
, value
};
83 events_
.push_back(entry
);
86 string
getIdString() const {
88 ss
<< pid_
<< "-" << lid_
;
92 string
getLogIdString() const {
94 ss
<< pid_
<< "-" << lid_
<< "-update-log";
98 string
getAllUpdateString() const {
100 ss
<< "{pid:" << pid_
<< ", lid:" << lid_
<< ", log:[";
101 for (size_t i
= 0; i
< events_
.size(); ++i
) {
102 ss
<< "{type:'" << events_
[i
].type
<<
103 "', value:'" << events_
[i
].value
<< "'},";
111 std::vector
<EventEntry
> events_
;
112 // This is a record of the history of stats value reported for each stats
113 // report id (e.g. ssrc-1234) for each stats name (e.g. framerate).
114 // It a 2-D map with each map entry is a vector of reported values.
115 // It is used to verify the graph data series.
116 std::map
<string
, StatsMap
> stats_
;
119 static const int64 FAKE_TIME_STAMP
= 3600000;
122 // All tests are flaky on Windows: crbug.com/277322.
123 #define MAYBE_WebRTCInternalsBrowserTest DISABLED_WebRTCInternalsBrowserTest
125 #define MAYBE_WebRTCInternalsBrowserTest WebRTCInternalsBrowserTest
128 class MAYBE_WebRTCInternalsBrowserTest
: public ContentBrowserTest
{
130 MAYBE_WebRTCInternalsBrowserTest() {}
131 virtual ~MAYBE_WebRTCInternalsBrowserTest() {}
133 virtual void SetUpOnMainThread() OVERRIDE
{
134 // We need fake devices in this test since we want to run on naked VMs. We
135 // assume these switches are set by default in content_browsertests.
136 ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
137 switches::kUseFakeDeviceForMediaStream
));
138 ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
139 switches::kUseFakeUIForMediaStream
));
143 bool ExecuteJavascript(const string
& javascript
) {
144 return ExecuteScript(shell()->web_contents(), javascript
);
147 void ExpectTitle(const std::string
& expected_title
) const {
148 base::string16
expected_title16(base::ASCIIToUTF16(expected_title
));
149 TitleWatcher
title_watcher(shell()->web_contents(), expected_title16
);
150 EXPECT_EQ(expected_title16
, title_watcher
.WaitAndGetTitle());
153 // Execute the javascript of addPeerConnection.
154 void ExecuteAddPeerConnectionJs(const PeerConnectionEntry
& pc
) {
155 std::stringstream ss
;
156 ss
<< "{pid:" << pc
.pid_
<<", lid:" << pc
.lid_
<< ", " <<
157 "url:'u', servers:'s', constraints:'c'}";
158 ASSERT_TRUE(ExecuteJavascript("addPeerConnection(" + ss
.str() + ");"));
161 // Execute the javascript of removePeerConnection.
162 void ExecuteRemovePeerConnectionJs(const PeerConnectionEntry
& pc
) {
163 std::stringstream ss
;
164 ss
<< "{pid:" << pc
.pid_
<<", lid:" << pc
.lid_
<< "}";
166 ASSERT_TRUE(ExecuteJavascript("removePeerConnection(" + ss
.str() + ");"));
169 // Verifies that the DOM element with id |id| exists.
170 void VerifyElementWithId(const string
& id
) {
172 ASSERT_TRUE(ExecuteScriptAndExtractBool(
173 shell()->web_contents(),
174 "window.domAutomationController.send($('" + id
+ "') != null);",
179 // Verifies that the DOM element with id |id| does not exist.
180 void VerifyNoElementWithId(const string
& id
) {
182 ASSERT_TRUE(ExecuteScriptAndExtractBool(
183 shell()->web_contents(),
184 "window.domAutomationController.send($('" + id
+ "') == null);",
189 // Verifies that DOM for |pc| is correctly created with the right content.
190 void VerifyPeerConnectionEntry(const PeerConnectionEntry
& pc
) {
191 VerifyElementWithId(pc
.getIdString());
192 if (pc
.events_
.size() == 0)
195 string log_id
= pc
.getLogIdString();
196 VerifyElementWithId(log_id
);
198 for (size_t i
= 0; i
< pc
.events_
.size(); ++i
) {
199 std::stringstream ss
;
200 ss
<< "var row = $('" << log_id
<< "').rows[" << (i
+ 1) << "];"
201 "var cell = row.lastChild;"
202 "window.domAutomationController.send(cell.firstChild.textContent);";
203 ASSERT_TRUE(ExecuteScriptAndExtractString(
204 shell()->web_contents(), ss
.str(), &result
));
205 EXPECT_EQ(pc
.events_
[i
].type
+ pc
.events_
[i
].value
, result
);
209 // Executes the javascript of updatePeerConnection and verifies the result.
210 void ExecuteAndVerifyUpdatePeerConnection(
211 PeerConnectionEntry
& pc
, const string
& type
, const string
& value
) {
212 pc
.AddEvent(type
, value
);
214 std::stringstream ss
;
215 ss
<< "{pid:" << pc
.pid_
<<", lid:" << pc
.lid_
<<
216 ", type:'" << type
<< "', value:'" << value
<< "'}";
217 ASSERT_TRUE(ExecuteJavascript("updatePeerConnection(" + ss
.str() + ")"));
219 VerifyPeerConnectionEntry(pc
);
222 // Execute addStats and verifies that the stats table has the right content.
223 void ExecuteAndVerifyAddStats(
224 PeerConnectionEntry
& pc
, const string
& type
, const string
& id
,
226 StatsEntry entry
= {type
, id
, stats
};
228 // Adds each new value to the map of stats history.
229 std::map
<string
, string
>::iterator iter
;
230 for (iter
= stats
.values
.begin(); iter
!= stats
.values
.end(); iter
++) {
231 pc
.stats_
[id
][iter
->first
].push_back(iter
->second
);
233 std::stringstream ss
;
234 ss
<< "{pid:" << pc
.pid_
<< ", lid:" << pc
.lid_
<< ","
235 "reports:[" << "{id:'" << id
<< "', type:'" << type
<< "', "
236 "stats:" << stats
.GetString() << "}]}";
238 ASSERT_TRUE(ExecuteJavascript("addStats(" + ss
.str() + ")"));
239 VerifyStatsTable(pc
, entry
);
243 // Verifies that the stats table has the right content.
244 void VerifyStatsTable(const PeerConnectionEntry
& pc
,
245 const StatsEntry
& report
) {
247 pc
.getIdString() + "-table-" + report
.id
;
248 VerifyElementWithId(table_id
);
250 std::map
<string
, string
>::const_iterator iter
;
251 for (iter
= report
.stats
.values
.begin();
252 iter
!= report
.stats
.values
.end(); iter
++) {
253 VerifyStatsTableRow(table_id
, iter
->first
, iter
->second
);
257 // Verifies that the row named as |name| of the stats table |table_id| has
258 // the correct content as |name| : |value|.
259 void VerifyStatsTableRow(const string
& table_id
,
261 const string
& value
) {
262 VerifyElementWithId(table_id
+ "-" + name
);
265 ASSERT_TRUE(ExecuteScriptAndExtractString(
266 shell()->web_contents(),
267 "var row = $('" + table_id
+ "-" + name
+ "');"
268 "var name = row.cells[0].textContent;"
269 "var value = row.cells[1].textContent;"
270 "window.domAutomationController.send(name + ':' + value)",
272 EXPECT_EQ(name
+ ":" + value
, result
);
275 // Verifies that the graph data series consistent with pc.stats_.
276 void VerifyStatsGraph(const PeerConnectionEntry
& pc
) {
277 std::map
<string
, StatsMap
>::const_iterator stream_iter
;
278 for (stream_iter
= pc
.stats_
.begin();
279 stream_iter
!= pc
.stats_
.end(); stream_iter
++) {
280 StatsMap::const_iterator stats_iter
;
281 for (stats_iter
= stream_iter
->second
.begin();
282 stats_iter
!= stream_iter
->second
.end();
284 string graph_id
= stream_iter
->first
+ "-" + stats_iter
->first
;
285 for (size_t i
= 0; i
< stats_iter
->second
.size(); ++i
) {
287 std::stringstream
stream(stats_iter
->second
[i
]);
291 VerifyGraphDataPoint(
292 pc
.getIdString(), graph_id
, i
, stats_iter
->second
[i
]);
298 // Verifies that the graph data point at index |index| has value |value|.
299 void VerifyGraphDataPoint(const string
& pc_id
, const string
& graph_id
,
300 int index
, const string
& value
) {
302 ASSERT_TRUE(ExecuteScriptAndExtractBool(
303 shell()->web_contents(),
304 "window.domAutomationController.send("
305 "graphViews['" + pc_id
+ "-" + graph_id
+ "'] != null)",
309 std::stringstream ss
;
310 ss
<< "var dp = peerConnectionDataStore['" << pc_id
<< "']"
311 ".getDataSeries('" << graph_id
<< "').dataPoints_[" << index
<< "];"
312 "window.domAutomationController.send(dp.value.toString())";
314 ASSERT_TRUE(ExecuteScriptAndExtractString(
315 shell()->web_contents(), ss
.str(), &actual_value
));
316 EXPECT_EQ(value
, actual_value
);
319 // Get the JSON string of the ssrc info from the page.
320 string
GetSsrcInfo(const string
& ssrc_id
) {
322 EXPECT_TRUE(ExecuteScriptAndExtractString(
323 shell()->web_contents(),
324 "window.domAutomationController.send(JSON.stringify("
325 "ssrcInfoManager.streamInfoContainer_['" + ssrc_id
+ "']))",
330 int GetSsrcInfoBlockCount(Shell
* shell
) {
332 EXPECT_TRUE(ExecuteScriptAndExtractInt(
333 shell
->web_contents(),
334 "window.domAutomationController.send("
335 "document.getElementsByClassName("
336 "ssrcInfoManager.SSRC_INFO_BLOCK_CLASS).length);",
341 // Verifies |dump| contains |peer_connection_number| peer connection dumps,
342 // each containing |update_number| updates and |stats_number| stats tables.
343 void VerifyPageDumpStructure(base::Value
* dump
,
344 int peer_connection_number
,
347 EXPECT_NE((base::Value
*)NULL
, dump
);
348 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, dump
->GetType());
350 base::DictionaryValue
* dict_dump
=
351 static_cast<base::DictionaryValue
*>(dump
);
352 EXPECT_EQ((size_t) peer_connection_number
, dict_dump
->size());
354 base::DictionaryValue::Iterator
it(*dict_dump
);
355 for (; !it
.IsAtEnd(); it
.Advance()) {
356 base::Value
* value
= NULL
;
357 dict_dump
->Get(it
.key(), &value
);
358 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, value
->GetType());
359 base::DictionaryValue
* pc_dump
=
360 static_cast<base::DictionaryValue
*>(value
);
361 EXPECT_TRUE(pc_dump
->HasKey("updateLog"));
362 EXPECT_TRUE(pc_dump
->HasKey("stats"));
364 // Verifies the number of updates.
365 pc_dump
->Get("updateLog", &value
);
366 EXPECT_EQ(base::Value::TYPE_LIST
, value
->GetType());
367 base::ListValue
* list
= static_cast<base::ListValue
*>(value
);
368 EXPECT_EQ((size_t) update_number
, list
->GetSize());
370 // Verifies the number of stats tables.
371 pc_dump
->Get("stats", &value
);
372 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, value
->GetType());
373 base::DictionaryValue
* dict
= static_cast<base::DictionaryValue
*>(value
);
374 EXPECT_EQ((size_t) stats_number
, dict
->size());
378 // Verifies |dump| contains the correct statsTable and statsDataSeries for
380 void VerifyStatsDump(base::Value
* dump
,
381 const PeerConnectionEntry
& pc
,
382 const string
& report_type
,
383 const string
& report_id
,
384 const StatsUnit
& stats
) {
385 EXPECT_NE((base::Value
*)NULL
, dump
);
386 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, dump
->GetType());
388 base::DictionaryValue
* dict_dump
=
389 static_cast<base::DictionaryValue
*>(dump
);
390 base::Value
* value
= NULL
;
391 dict_dump
->Get(pc
.getIdString(), &value
);
392 base::DictionaryValue
* pc_dump
= static_cast<base::DictionaryValue
*>(value
);
394 // Verifies there is one data series per stats name.
396 pc_dump
->Get("stats", &value
);
397 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, value
->GetType());
399 base::DictionaryValue
* dataSeries
=
400 static_cast<base::DictionaryValue
*>(value
);
401 EXPECT_EQ(stats
.values
.size(), dataSeries
->size());
405 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest
,
406 AddAndRemovePeerConnection
) {
407 GURL
url("chrome://webrtc-internals");
408 NavigateToURL(shell(), url
);
410 // Add two PeerConnections and then remove them.
411 PeerConnectionEntry
pc_1(1, 0);
412 ExecuteAddPeerConnectionJs(pc_1
);
413 VerifyPeerConnectionEntry(pc_1
);
415 PeerConnectionEntry
pc_2(2, 1);
416 ExecuteAddPeerConnectionJs(pc_2
);
417 VerifyPeerConnectionEntry(pc_2
);
419 ExecuteRemovePeerConnectionJs(pc_1
);
420 VerifyNoElementWithId(pc_1
.getIdString());
421 VerifyPeerConnectionEntry(pc_2
);
423 ExecuteRemovePeerConnectionJs(pc_2
);
424 VerifyNoElementWithId(pc_2
.getIdString());
427 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest
,
428 UpdateAllPeerConnections
) {
429 GURL
url("chrome://webrtc-internals");
430 NavigateToURL(shell(), url
);
432 PeerConnectionEntry
pc_0(1, 0);
433 pc_0
.AddEvent("e1", "v1");
434 pc_0
.AddEvent("e2", "v2");
435 PeerConnectionEntry
pc_1(1, 1);
436 pc_1
.AddEvent("e3", "v3");
437 pc_1
.AddEvent("e4", "v4");
438 string pc_array
= "[" + pc_0
.getAllUpdateString() + ", " +
439 pc_1
.getAllUpdateString() + "]";
440 EXPECT_TRUE(ExecuteJavascript("updateAllPeerConnections(" + pc_array
+ ");"));
441 VerifyPeerConnectionEntry(pc_0
);
442 VerifyPeerConnectionEntry(pc_1
);
445 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest
, UpdatePeerConnection
) {
446 GURL
url("chrome://webrtc-internals");
447 NavigateToURL(shell(), url
);
449 // Add one PeerConnection and send one update.
450 PeerConnectionEntry
pc_1(1, 0);
451 ExecuteAddPeerConnectionJs(pc_1
);
453 ExecuteAndVerifyUpdatePeerConnection(pc_1
, "e1", "v1");
455 // Add another PeerConnection and send two updates.
456 PeerConnectionEntry
pc_2(1, 1);
457 ExecuteAddPeerConnectionJs(pc_2
);
459 SsrcEntry ssrc1
, ssrc2
;
460 ssrc1
.id
= "ssrcid1";
461 ssrc1
.properties
["msid"] = "mymsid";
462 ssrc2
.id
= "ssrcid2";
463 ssrc2
.properties
["label"] = "mylabel";
464 ssrc2
.properties
["cname"] = "mycname";
466 ExecuteAndVerifyUpdatePeerConnection(pc_2
, "setRemoteDescription",
467 ssrc1
.GetSsrcAttributeString());
469 ExecuteAndVerifyUpdatePeerConnection(pc_2
, "setLocalDescription",
470 ssrc2
.GetSsrcAttributeString());
472 EXPECT_EQ(ssrc1
.GetAsJSON(), GetSsrcInfo(ssrc1
.id
));
473 EXPECT_EQ(ssrc2
.GetAsJSON(), GetSsrcInfo(ssrc2
.id
));
475 StatsUnit stats
= {FAKE_TIME_STAMP
};
476 stats
.values
["ssrc"] = ssrc1
.id
;
477 ExecuteAndVerifyAddStats(pc_2
, "ssrc", "dummyId", stats
);
478 EXPECT_GT(GetSsrcInfoBlockCount(shell()), 0);
481 // Tests that adding random named stats updates the dataSeries and graphs.
482 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest
, AddStats
) {
483 GURL
url("chrome://webrtc-internals");
484 NavigateToURL(shell(), url
);
486 PeerConnectionEntry
pc(1, 0);
487 ExecuteAddPeerConnectionJs(pc
);
489 const string type
= "ssrc";
490 const string id
= "ssrc-1234";
491 StatsUnit stats
= {FAKE_TIME_STAMP
};
492 stats
.values
["trackId"] = "abcd";
493 stats
.values
["bitrate"] = "2000";
494 stats
.values
["framerate"] = "30";
496 // Add new stats and verify the stats table and graphs.
497 ExecuteAndVerifyAddStats(pc
, type
, id
, stats
);
498 VerifyStatsGraph(pc
);
500 // Update existing stats and verify the stats table and graphs.
501 stats
.values
["bitrate"] = "2001";
502 stats
.values
["framerate"] = "31";
503 ExecuteAndVerifyAddStats(pc
, type
, id
, stats
);
504 VerifyStatsGraph(pc
);
507 // Tests that the bandwidth estimation values are drawn on a single graph.
508 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest
, BweCompoundGraph
) {
509 GURL
url("chrome://webrtc-internals");
510 NavigateToURL(shell(), url
);
512 PeerConnectionEntry
pc(1, 0);
513 ExecuteAddPeerConnectionJs(pc
);
515 StatsUnit stats
= {FAKE_TIME_STAMP
};
516 stats
.values
["googAvailableSendBandwidth"] = "1000000";
517 stats
.values
["googTargetEncBitrate"] = "1000";
518 stats
.values
["googActualEncBitrate"] = "1000000";
519 stats
.values
["googRetransmitBitrate"] = "10";
520 stats
.values
["googTransmitBitrate"] = "1000000";
521 const string stats_type
= "bwe";
522 const string stats_id
= "videobwe";
523 ExecuteAndVerifyAddStats(pc
, stats_type
, stats_id
, stats
);
526 pc
.getIdString() + "-" + stats_id
+ "-bweCompound";
528 // Verify that the bweCompound graph exists.
529 ASSERT_TRUE(ExecuteScriptAndExtractBool(
530 shell()->web_contents(),
531 "window.domAutomationController.send("
532 " graphViews['" + graph_id
+ "'] != null)",
536 // Verify that the bweCompound graph contains multiple dataSeries.
538 ASSERT_TRUE(ExecuteScriptAndExtractInt(
539 shell()->web_contents(),
540 "window.domAutomationController.send("
541 " graphViews['" + graph_id
+ "'].getDataSeriesCount())",
543 EXPECT_EQ((int)stats
.values
.size(), count
);
546 // Tests that the total packet/byte count is converted to count per second,
547 // and the converted data is drawn.
548 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest
, ConvertedGraphs
) {
549 GURL
url("chrome://webrtc-internals");
550 NavigateToURL(shell(), url
);
552 PeerConnectionEntry
pc(1, 0);
553 ExecuteAddPeerConnectionJs(pc
);
555 const string stats_type
= "s";
556 const string stats_id
= "1";
557 const int num_converted_stats
= 4;
558 const string stats_names
[] =
559 {"packetsSent", "bytesSent", "packetsReceived", "bytesReceived"};
560 const string converted_names
[] =
561 {"packetsSentPerSecond", "bitsSentPerSecond",
562 "packetsReceivedPerSecond", "bitsReceivedPerSecond"};
563 const string first_value
= "1000";
564 const string second_value
= "2000";
565 const string converted_values
[] = {"1000", "8000", "1000", "8000"};
567 // Send the first data point.
568 StatsUnit stats
= {FAKE_TIME_STAMP
};
569 for (int i
= 0; i
< num_converted_stats
; ++i
)
570 stats
.values
[stats_names
[i
]] = first_value
;
572 ExecuteAndVerifyAddStats(pc
, stats_type
, stats_id
, stats
);
574 // Send the second data point at 1000ms after the first data point.
575 stats
.timestamp
+= 1000;
576 for (int i
= 0; i
< num_converted_stats
; ++i
)
577 stats
.values
[stats_names
[i
]] = second_value
;
578 ExecuteAndVerifyAddStats(pc
, stats_type
, stats_id
, stats
);
580 // Verifies the graph data matches converted_values.
581 for (int i
= 0; i
< num_converted_stats
; ++i
) {
582 VerifyGraphDataPoint(pc
.getIdString(), stats_id
+ "-" + converted_names
[i
],
583 1, converted_values
[i
]);
587 // Timing out on ARM linux bot: http://crbug.com/238490
588 // Disabling due to failure on Linux, Mac, Win: http://crbug.com/272413
589 // Sanity check of the page content under a real PeerConnection call.
590 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest
,
591 DISABLED_WithRealPeerConnectionCall
) {
592 // Start a peerconnection call in the first window.
593 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
594 GURL
url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
595 NavigateToURL(shell(), url
);
596 ASSERT_TRUE(ExecuteJavascript("call({video:true});"));
599 // Open webrtc-internals in the second window.
600 GURL
url2("chrome://webrtc-internals");
601 Shell
* shell2
= CreateBrowser();
602 NavigateToURL(shell2
, url2
);
604 const int NUMBER_OF_PEER_CONNECTIONS
= 2;
606 // Verifies the number of peerconnections.
608 ASSERT_TRUE(ExecuteScriptAndExtractInt(
609 shell2
->web_contents(),
610 "window.domAutomationController.send("
611 "$('peer-connections-list').getElementsByTagName('li').length);",
613 EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS
, count
);
615 // Verifies the the event tables.
616 ASSERT_TRUE(ExecuteScriptAndExtractInt(
617 shell2
->web_contents(),
618 "window.domAutomationController.send($('peer-connections-list')"
619 ".getElementsByClassName('update-log-table').length);",
621 EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS
, count
);
623 ASSERT_TRUE(ExecuteScriptAndExtractInt(
624 shell2
->web_contents(),
625 "window.domAutomationController.send($('peer-connections-list')"
626 ".getElementsByClassName('update-log-table')[0].rows.length);",
630 ASSERT_TRUE(ExecuteScriptAndExtractInt(
631 shell2
->web_contents(),
632 "window.domAutomationController.send($('peer-connections-list')"
633 ".getElementsByClassName('update-log-table')[1].rows.length);",
637 // Wait until the stats table containers are created.
639 while (count
!= NUMBER_OF_PEER_CONNECTIONS
) {
640 ASSERT_TRUE(ExecuteScriptAndExtractInt(
641 shell2
->web_contents(),
642 "window.domAutomationController.send("
643 "$('peer-connections-list').getElementsByClassName("
644 "'stats-table-container').length);",
648 // Verifies each stats table having more than one rows.
650 ASSERT_TRUE(ExecuteScriptAndExtractBool(
651 shell2
->web_contents(),
652 "var tableContainers = $('peer-connections-list')"
653 ".getElementsByClassName('stats-table-container');"
655 "for (var i = 0; i < tableContainers.length && result; ++i) {"
656 "var tables = tableContainers[i].getElementsByTagName('table');"
657 "for (var j = 0; j < tables.length && result; ++j) {"
658 "result = (tables[j].rows.length > 1);"
661 "console.log(tableContainers[i].innerHTML);"
664 "window.domAutomationController.send(result);",
669 count
= GetSsrcInfoBlockCount(shell2
);
673 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest
, CreatePageDump
) {
674 GURL
url("chrome://webrtc-internals");
675 NavigateToURL(shell(), url
);
677 PeerConnectionEntry
pc_0(1, 0);
678 pc_0
.AddEvent("e1", "v1");
679 pc_0
.AddEvent("e2", "v2");
680 PeerConnectionEntry
pc_1(1, 1);
681 pc_1
.AddEvent("e3", "v3");
682 pc_1
.AddEvent("e4", "v4");
684 "[" + pc_0
.getAllUpdateString() + ", " + pc_1
.getAllUpdateString() + "]";
685 EXPECT_TRUE(ExecuteJavascript("updateAllPeerConnections(" + pc_array
+ ");"));
687 // Verifies the peer connection data store can be created without stats.
689 ASSERT_TRUE(ExecuteScriptAndExtractString(
690 shell()->web_contents(),
691 "window.domAutomationController.send("
692 "JSON.stringify(peerConnectionDataStore));",
694 scoped_ptr
<base::Value
> dump
;
695 dump
.reset(base::JSONReader::Read(dump_json
));
696 VerifyPageDumpStructure(dump
.get(),
697 2 /*peer_connection_number*/,
701 // Adds a stats report.
702 const string type
= "dummy";
703 const string id
= "1234";
704 StatsUnit stats
= { FAKE_TIME_STAMP
};
705 stats
.values
["bitrate"] = "2000";
706 stats
.values
["framerate"] = "30";
707 ExecuteAndVerifyAddStats(pc_0
, type
, id
, stats
);
709 ASSERT_TRUE(ExecuteScriptAndExtractString(
710 shell()->web_contents(),
711 "window.domAutomationController.send("
712 "JSON.stringify(peerConnectionDataStore));",
714 dump
.reset(base::JSONReader::Read(dump_json
));
715 VerifyStatsDump(dump
.get(), pc_0
, type
, id
, stats
);
718 } // namespace content