Remove PlatformFile from profile_browsertest
[chromium-blink-merge.git] / content / browser / media / webrtc_internals_browsertest.cc
blob8e071c737f07379a6de5e490053513ee062696b7
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 "net/test/embedded_test_server/embedded_test_server.h"
17 using std::string;
18 namespace content {
20 struct SsrcEntry {
21 string GetSsrcAttributeString() const {
22 std::stringstream ss;
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;
28 return ss.str();
31 string GetAsJSON() const {
32 std::stringstream ss;
33 ss << "{";
34 std::map<string, string>::const_iterator iter;
35 for (iter = properties.begin(); iter != properties.end(); ++iter) {
36 if (iter != properties.begin())
37 ss << ",";
38 ss << "\"" << iter->first << "\":\"" << iter->second << "\"";
40 ss << "}";
41 return ss.str();
44 string id;
45 std::map<string, string> properties;
48 struct EventEntry {
49 string type;
50 string value;
53 struct StatsUnit {
54 string GetString() const {
55 std::stringstream ss;
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 << "',";
61 ss << "]}";
62 return ss.str();
65 int64 timestamp;
66 std::map<string, string> values;
69 struct StatsEntry {
70 string type;
71 string id;
72 StatsUnit stats;
75 typedef std::map<string, std::vector<string> > StatsMap;
77 class PeerConnectionEntry {
78 public:
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 {
87 std::stringstream ss;
88 ss << pid_ << "-" << lid_;
89 return ss.str();
92 string getLogIdString() const {
93 std::stringstream ss;
94 ss << pid_ << "-" << lid_ << "-update-log";
95 return ss.str();
98 string getAllUpdateString() const {
99 std::stringstream ss;
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 << "'},";
105 ss << "]}";
106 return ss.str();
109 int pid_;
110 int lid_;
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 class UserMediaRequestEntry {
120 public:
121 UserMediaRequestEntry(int pid,
122 int rid,
123 const std::string& origin,
124 const std::string& audio_constraints,
125 const std::string& video_constraints)
126 : pid(pid),
127 rid(rid),
128 origin(origin),
129 audio_constraints(audio_constraints),
130 video_constraints(video_constraints) {}
132 int pid;
133 int rid;
134 std::string origin;
135 std::string audio_constraints;
136 std::string video_constraints;
139 static const int64 FAKE_TIME_STAMP = 3600000;
141 #if defined(OS_WIN)
142 // All tests are flaky on Windows: crbug.com/277322.
143 #define MAYBE_WebRtcInternalsBrowserTest DISABLED_WebRtcInternalsBrowserTest
144 #else
145 #define MAYBE_WebRtcInternalsBrowserTest WebRtcInternalsBrowserTest
146 #endif
148 class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
149 public:
150 MAYBE_WebRtcInternalsBrowserTest() {}
151 virtual ~MAYBE_WebRtcInternalsBrowserTest() {}
153 virtual void SetUpOnMainThread() OVERRIDE {
154 // We need fake devices in this test since we want to run on naked VMs. We
155 // assume these switches are set by default in content_browsertests.
156 ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
157 switches::kUseFakeDeviceForMediaStream));
158 ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
159 switches::kUseFakeUIForMediaStream));
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', servers:'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);
263 // Verifies that DOM for |pc| is correctly created with the right content.
264 void VerifyPeerConnectionEntry(const PeerConnectionEntry& pc) {
265 VerifyElementWithId(pc.getIdString());
266 if (pc.events_.size() == 0)
267 return;
269 string log_id = pc.getLogIdString();
270 VerifyElementWithId(log_id);
271 string result;
272 for (size_t i = 0; i < pc.events_.size(); ++i) {
273 std::stringstream ss;
274 ss << "var row = $('" << log_id << "').rows[" << (i + 1) << "];"
275 "var cell = row.lastChild;"
276 "window.domAutomationController.send(cell.firstChild.textContent);";
277 ASSERT_TRUE(ExecuteScriptAndExtractString(
278 shell()->web_contents(), ss.str(), &result));
279 EXPECT_EQ(pc.events_[i].type + pc.events_[i].value, result);
283 // Executes the javascript of updatePeerConnection and verifies the result.
284 void ExecuteAndVerifyUpdatePeerConnection(
285 PeerConnectionEntry& pc, const string& type, const string& value) {
286 pc.AddEvent(type, value);
288 std::stringstream ss;
289 ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ <<
290 ", type:'" << type << "', value:'" << value << "'}";
291 ASSERT_TRUE(ExecuteJavascript("updatePeerConnection(" + ss.str() + ")"));
293 VerifyPeerConnectionEntry(pc);
296 // Execute addStats and verifies that the stats table has the right content.
297 void ExecuteAndVerifyAddStats(
298 PeerConnectionEntry& pc, const string& type, const string& id,
299 StatsUnit& stats) {
300 StatsEntry entry = {type, id, stats};
302 // Adds each new value to the map of stats history.
303 std::map<string, string>::iterator iter;
304 for (iter = stats.values.begin(); iter != stats.values.end(); iter++) {
305 pc.stats_[id][iter->first].push_back(iter->second);
307 std::stringstream ss;
308 ss << "{pid:" << pc.pid_ << ", lid:" << pc.lid_ << ","
309 "reports:[" << "{id:'" << id << "', type:'" << type << "', "
310 "stats:" << stats.GetString() << "}]}";
312 ASSERT_TRUE(ExecuteJavascript("addStats(" + ss.str() + ")"));
313 VerifyStatsTable(pc, entry);
317 // Verifies that the stats table has the right content.
318 void VerifyStatsTable(const PeerConnectionEntry& pc,
319 const StatsEntry& report) {
320 string table_id =
321 pc.getIdString() + "-table-" + report.id;
322 VerifyElementWithId(table_id);
324 std::map<string, string>::const_iterator iter;
325 for (iter = report.stats.values.begin();
326 iter != report.stats.values.end(); iter++) {
327 VerifyStatsTableRow(table_id, iter->first, iter->second);
331 // Verifies that the row named as |name| of the stats table |table_id| has
332 // the correct content as |name| : |value|.
333 void VerifyStatsTableRow(const string& table_id,
334 const string& name,
335 const string& value) {
336 VerifyElementWithId(table_id + "-" + name);
338 string result;
339 ASSERT_TRUE(ExecuteScriptAndExtractString(
340 shell()->web_contents(),
341 "var row = $('" + table_id + "-" + name + "');"
342 "var name = row.cells[0].textContent;"
343 "var value = row.cells[1].textContent;"
344 "window.domAutomationController.send(name + ':' + value)",
345 &result));
346 EXPECT_EQ(name + ":" + value, result);
349 // Verifies that the graph data series consistent with pc.stats_.
350 void VerifyStatsGraph(const PeerConnectionEntry& pc) {
351 std::map<string, StatsMap>::const_iterator stream_iter;
352 for (stream_iter = pc.stats_.begin();
353 stream_iter != pc.stats_.end(); stream_iter++) {
354 StatsMap::const_iterator stats_iter;
355 for (stats_iter = stream_iter->second.begin();
356 stats_iter != stream_iter->second.end();
357 stats_iter++) {
358 string graph_id = stream_iter->first + "-" + stats_iter->first;
359 for (size_t i = 0; i < stats_iter->second.size(); ++i) {
360 float number;
361 std::stringstream stream(stats_iter->second[i]);
362 stream >> number;
363 if (stream.fail())
364 continue;
365 VerifyGraphDataPoint(
366 pc.getIdString(), graph_id, i, stats_iter->second[i]);
372 // Verifies that the graph data point at index |index| has value |value|.
373 void VerifyGraphDataPoint(const string& pc_id, const string& graph_id,
374 int index, const string& value) {
375 bool result = false;
376 ASSERT_TRUE(ExecuteScriptAndExtractBool(
377 shell()->web_contents(),
378 "window.domAutomationController.send("
379 "graphViews['" + pc_id + "-" + graph_id + "'] != null)",
380 &result));
381 EXPECT_TRUE(result);
383 std::stringstream ss;
384 ss << "var dp = peerConnectionDataStore['" << pc_id << "']"
385 ".getDataSeries('" << graph_id << "').dataPoints_[" << index << "];"
386 "window.domAutomationController.send(dp.value.toString())";
387 string actual_value;
388 ASSERT_TRUE(ExecuteScriptAndExtractString(
389 shell()->web_contents(), ss.str(), &actual_value));
390 EXPECT_EQ(value, actual_value);
393 // Get the JSON string of the ssrc info from the page.
394 string GetSsrcInfo(const string& ssrc_id) {
395 string result;
396 EXPECT_TRUE(ExecuteScriptAndExtractString(
397 shell()->web_contents(),
398 "window.domAutomationController.send(JSON.stringify("
399 "ssrcInfoManager.streamInfoContainer_['" + ssrc_id + "']))",
400 &result));
401 return result;
404 int GetSsrcInfoBlockCount(Shell* shell) {
405 int count = 0;
406 EXPECT_TRUE(ExecuteScriptAndExtractInt(
407 shell->web_contents(),
408 "window.domAutomationController.send("
409 "document.getElementsByClassName("
410 "ssrcInfoManager.SSRC_INFO_BLOCK_CLASS).length);",
411 &count));
412 return count;
415 // Verifies |dump| contains |peer_connection_number| peer connection dumps,
416 // each containing |update_number| updates and |stats_number| stats tables.
417 void VerifyPageDumpStructure(base::Value* dump,
418 int peer_connection_number,
419 int update_number,
420 int stats_number) {
421 EXPECT_NE((base::Value*)NULL, dump);
422 EXPECT_EQ(base::Value::TYPE_DICTIONARY, dump->GetType());
424 base::DictionaryValue* dict_dump =
425 static_cast<base::DictionaryValue*>(dump);
426 EXPECT_EQ((size_t) peer_connection_number, dict_dump->size());
428 base::DictionaryValue::Iterator it(*dict_dump);
429 for (; !it.IsAtEnd(); it.Advance()) {
430 base::Value* value = NULL;
431 dict_dump->Get(it.key(), &value);
432 EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
433 base::DictionaryValue* pc_dump =
434 static_cast<base::DictionaryValue*>(value);
435 EXPECT_TRUE(pc_dump->HasKey("updateLog"));
436 EXPECT_TRUE(pc_dump->HasKey("stats"));
438 // Verifies the number of updates.
439 pc_dump->Get("updateLog", &value);
440 EXPECT_EQ(base::Value::TYPE_LIST, value->GetType());
441 base::ListValue* list = static_cast<base::ListValue*>(value);
442 EXPECT_EQ((size_t) update_number, list->GetSize());
444 // Verifies the number of stats tables.
445 pc_dump->Get("stats", &value);
446 EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
447 base::DictionaryValue* dict = static_cast<base::DictionaryValue*>(value);
448 EXPECT_EQ((size_t) stats_number, dict->size());
452 // Verifies |dump| contains the correct statsTable and statsDataSeries for
453 // |pc|.
454 void VerifyStatsDump(base::Value* dump,
455 const PeerConnectionEntry& pc,
456 const string& report_type,
457 const string& report_id,
458 const StatsUnit& stats) {
459 EXPECT_NE((base::Value*)NULL, dump);
460 EXPECT_EQ(base::Value::TYPE_DICTIONARY, dump->GetType());
462 base::DictionaryValue* dict_dump =
463 static_cast<base::DictionaryValue*>(dump);
464 base::Value* value = NULL;
465 dict_dump->Get(pc.getIdString(), &value);
466 base::DictionaryValue* pc_dump = static_cast<base::DictionaryValue*>(value);
468 // Verifies there is one data series per stats name.
469 value = NULL;
470 pc_dump->Get("stats", &value);
471 EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
473 base::DictionaryValue* dataSeries =
474 static_cast<base::DictionaryValue*>(value);
475 EXPECT_EQ(stats.values.size(), dataSeries->size());
479 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
480 AddAndRemovePeerConnection) {
481 GURL url("chrome://webrtc-internals");
482 NavigateToURL(shell(), url);
484 // Add two PeerConnections and then remove them.
485 PeerConnectionEntry pc_1(1, 0);
486 ExecuteAddPeerConnectionJs(pc_1);
487 VerifyPeerConnectionEntry(pc_1);
489 PeerConnectionEntry pc_2(2, 1);
490 ExecuteAddPeerConnectionJs(pc_2);
491 VerifyPeerConnectionEntry(pc_2);
493 ExecuteRemovePeerConnectionJs(pc_1);
494 VerifyNoElementWithId(pc_1.getIdString());
495 VerifyPeerConnectionEntry(pc_2);
497 ExecuteRemovePeerConnectionJs(pc_2);
498 VerifyNoElementWithId(pc_2.getIdString());
501 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
502 UpdateAllPeerConnections) {
503 GURL url("chrome://webrtc-internals");
504 NavigateToURL(shell(), url);
506 PeerConnectionEntry pc_0(1, 0);
507 pc_0.AddEvent("e1", "v1");
508 pc_0.AddEvent("e2", "v2");
509 PeerConnectionEntry pc_1(1, 1);
510 pc_1.AddEvent("e3", "v3");
511 pc_1.AddEvent("e4", "v4");
512 string pc_array = "[" + pc_0.getAllUpdateString() + ", " +
513 pc_1.getAllUpdateString() + "]";
514 EXPECT_TRUE(ExecuteJavascript("updateAllPeerConnections(" + pc_array + ");"));
515 VerifyPeerConnectionEntry(pc_0);
516 VerifyPeerConnectionEntry(pc_1);
519 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, UpdatePeerConnection) {
520 GURL url("chrome://webrtc-internals");
521 NavigateToURL(shell(), url);
523 // Add one PeerConnection and send one update.
524 PeerConnectionEntry pc_1(1, 0);
525 ExecuteAddPeerConnectionJs(pc_1);
527 ExecuteAndVerifyUpdatePeerConnection(pc_1, "e1", "v1");
529 // Add another PeerConnection and send two updates.
530 PeerConnectionEntry pc_2(1, 1);
531 ExecuteAddPeerConnectionJs(pc_2);
533 SsrcEntry ssrc1, ssrc2;
534 ssrc1.id = "ssrcid1";
535 ssrc1.properties["msid"] = "mymsid";
536 ssrc2.id = "ssrcid2";
537 ssrc2.properties["label"] = "mylabel";
538 ssrc2.properties["cname"] = "mycname";
540 ExecuteAndVerifyUpdatePeerConnection(pc_2, "setRemoteDescription",
541 ssrc1.GetSsrcAttributeString());
543 ExecuteAndVerifyUpdatePeerConnection(pc_2, "setLocalDescription",
544 ssrc2.GetSsrcAttributeString());
546 EXPECT_EQ(ssrc1.GetAsJSON(), GetSsrcInfo(ssrc1.id));
547 EXPECT_EQ(ssrc2.GetAsJSON(), GetSsrcInfo(ssrc2.id));
549 StatsUnit stats = {FAKE_TIME_STAMP};
550 stats.values["ssrc"] = ssrc1.id;
551 ExecuteAndVerifyAddStats(pc_2, "ssrc", "dummyId", stats);
552 EXPECT_GT(GetSsrcInfoBlockCount(shell()), 0);
555 // Tests that adding random named stats updates the dataSeries and graphs.
556 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, AddStats) {
557 GURL url("chrome://webrtc-internals");
558 NavigateToURL(shell(), url);
560 PeerConnectionEntry pc(1, 0);
561 ExecuteAddPeerConnectionJs(pc);
563 const string type = "ssrc";
564 const string id = "ssrc-1234";
565 StatsUnit stats = {FAKE_TIME_STAMP};
566 stats.values["trackId"] = "abcd";
567 stats.values["bitrate"] = "2000";
568 stats.values["framerate"] = "30";
570 // Add new stats and verify the stats table and graphs.
571 ExecuteAndVerifyAddStats(pc, type, id, stats);
572 VerifyStatsGraph(pc);
574 // Update existing stats and verify the stats table and graphs.
575 stats.values["bitrate"] = "2001";
576 stats.values["framerate"] = "31";
577 ExecuteAndVerifyAddStats(pc, type, id, stats);
578 VerifyStatsGraph(pc);
581 // Tests that the bandwidth estimation values are drawn on a single graph.
582 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, BweCompoundGraph) {
583 GURL url("chrome://webrtc-internals");
584 NavigateToURL(shell(), url);
586 PeerConnectionEntry pc(1, 0);
587 ExecuteAddPeerConnectionJs(pc);
589 StatsUnit stats = {FAKE_TIME_STAMP};
590 stats.values["googAvailableSendBandwidth"] = "1000000";
591 stats.values["googTargetEncBitrate"] = "1000";
592 stats.values["googActualEncBitrate"] = "1000000";
593 stats.values["googRetransmitBitrate"] = "10";
594 stats.values["googTransmitBitrate"] = "1000000";
595 const string stats_type = "bwe";
596 const string stats_id = "videobwe";
597 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
599 string graph_id =
600 pc.getIdString() + "-" + stats_id + "-bweCompound";
601 bool result = false;
602 // Verify that the bweCompound graph exists.
603 ASSERT_TRUE(ExecuteScriptAndExtractBool(
604 shell()->web_contents(),
605 "window.domAutomationController.send("
606 " graphViews['" + graph_id + "'] != null)",
607 &result));
608 EXPECT_TRUE(result);
610 // Verify that the bweCompound graph contains multiple dataSeries.
611 int count = 0;
612 ASSERT_TRUE(ExecuteScriptAndExtractInt(
613 shell()->web_contents(),
614 "window.domAutomationController.send("
615 " graphViews['" + graph_id + "'].getDataSeriesCount())",
616 &count));
617 EXPECT_EQ((int)stats.values.size(), count);
620 // Tests that the total packet/byte count is converted to count per second,
621 // and the converted data is drawn.
622 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, ConvertedGraphs) {
623 GURL url("chrome://webrtc-internals");
624 NavigateToURL(shell(), url);
626 PeerConnectionEntry pc(1, 0);
627 ExecuteAddPeerConnectionJs(pc);
629 const string stats_type = "s";
630 const string stats_id = "1";
631 const int num_converted_stats = 4;
632 const string stats_names[] =
633 {"packetsSent", "bytesSent", "packetsReceived", "bytesReceived"};
634 const string converted_names[] =
635 {"packetsSentPerSecond", "bitsSentPerSecond",
636 "packetsReceivedPerSecond", "bitsReceivedPerSecond"};
637 const string first_value = "1000";
638 const string second_value = "2000";
639 const string converted_values[] = {"1000", "8000", "1000", "8000"};
641 // Send the first data point.
642 StatsUnit stats = {FAKE_TIME_STAMP};
643 for (int i = 0; i < num_converted_stats; ++i)
644 stats.values[stats_names[i]] = first_value;
646 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
648 // Send the second data point at 1000ms after the first data point.
649 stats.timestamp += 1000;
650 for (int i = 0; i < num_converted_stats; ++i)
651 stats.values[stats_names[i]] = second_value;
652 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
654 // Verifies the graph data matches converted_values.
655 for (int i = 0; i < num_converted_stats; ++i) {
656 VerifyGraphDataPoint(pc.getIdString(), stats_id + "-" + converted_names[i],
657 1, converted_values[i]);
661 // Timing out on ARM linux bot: http://crbug.com/238490
662 // Disabling due to failure on Linux, Mac, Win: http://crbug.com/272413
663 // Sanity check of the page content under a real PeerConnection call.
664 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
665 DISABLED_WithRealPeerConnectionCall) {
666 // Start a peerconnection call in the first window.
667 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
668 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
669 NavigateToURL(shell(), url);
670 ASSERT_TRUE(ExecuteJavascript("call({video:true});"));
671 ExpectTitle("OK");
673 // Open webrtc-internals in the second window.
674 GURL url2("chrome://webrtc-internals");
675 Shell* shell2 = CreateBrowser();
676 NavigateToURL(shell2, url2);
678 const int NUMBER_OF_PEER_CONNECTIONS = 2;
680 // Verifies the number of peerconnections.
681 int count = 0;
682 ASSERT_TRUE(ExecuteScriptAndExtractInt(
683 shell2->web_contents(),
684 "window.domAutomationController.send("
685 "$('peer-connections-list').getElementsByTagName('li').length);",
686 &count));
687 EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
689 // Verifies the the event tables.
690 ASSERT_TRUE(ExecuteScriptAndExtractInt(
691 shell2->web_contents(),
692 "window.domAutomationController.send($('peer-connections-list')"
693 ".getElementsByClassName('update-log-table').length);",
694 &count));
695 EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
697 ASSERT_TRUE(ExecuteScriptAndExtractInt(
698 shell2->web_contents(),
699 "window.domAutomationController.send($('peer-connections-list')"
700 ".getElementsByClassName('update-log-table')[0].rows.length);",
701 &count));
702 EXPECT_GT(count, 1);
704 ASSERT_TRUE(ExecuteScriptAndExtractInt(
705 shell2->web_contents(),
706 "window.domAutomationController.send($('peer-connections-list')"
707 ".getElementsByClassName('update-log-table')[1].rows.length);",
708 &count));
709 EXPECT_GT(count, 1);
711 // Wait until the stats table containers are created.
712 count = 0;
713 while (count != NUMBER_OF_PEER_CONNECTIONS) {
714 ASSERT_TRUE(ExecuteScriptAndExtractInt(
715 shell2->web_contents(),
716 "window.domAutomationController.send("
717 "$('peer-connections-list').getElementsByClassName("
718 "'stats-table-container').length);",
719 &count));
722 // Verifies each stats table having more than one rows.
723 bool result = false;
724 ASSERT_TRUE(ExecuteScriptAndExtractBool(
725 shell2->web_contents(),
726 "var tableContainers = $('peer-connections-list')"
727 ".getElementsByClassName('stats-table-container');"
728 "var result = true;"
729 "for (var i = 0; i < tableContainers.length && result; ++i) {"
730 "var tables = tableContainers[i].getElementsByTagName('table');"
731 "for (var j = 0; j < tables.length && result; ++j) {"
732 "result = (tables[j].rows.length > 1);"
734 "if (!result) {"
735 "console.log(tableContainers[i].innerHTML);"
738 "window.domAutomationController.send(result);",
739 &result));
741 EXPECT_TRUE(result);
743 count = GetSsrcInfoBlockCount(shell2);
744 EXPECT_GT(count, 0);
747 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, CreatePageDump) {
748 GURL url("chrome://webrtc-internals");
749 NavigateToURL(shell(), url);
751 PeerConnectionEntry pc_0(1, 0);
752 pc_0.AddEvent("e1", "v1");
753 pc_0.AddEvent("e2", "v2");
754 PeerConnectionEntry pc_1(1, 1);
755 pc_1.AddEvent("e3", "v3");
756 pc_1.AddEvent("e4", "v4");
757 string pc_array =
758 "[" + pc_0.getAllUpdateString() + ", " + pc_1.getAllUpdateString() + "]";
759 EXPECT_TRUE(ExecuteJavascript("updateAllPeerConnections(" + pc_array + ");"));
761 // Verifies the peer connection data store can be created without stats.
762 string dump_json;
763 ASSERT_TRUE(ExecuteScriptAndExtractString(
764 shell()->web_contents(),
765 "window.domAutomationController.send("
766 "JSON.stringify(peerConnectionDataStore));",
767 &dump_json));
768 scoped_ptr<base::Value> dump;
769 dump.reset(base::JSONReader::Read(dump_json));
770 VerifyPageDumpStructure(dump.get(),
771 2 /*peer_connection_number*/,
772 2 /*update_number*/,
773 0 /*stats_number*/);
775 // Adds a stats report.
776 const string type = "dummy";
777 const string id = "1234";
778 StatsUnit stats = { FAKE_TIME_STAMP };
779 stats.values["bitrate"] = "2000";
780 stats.values["framerate"] = "30";
781 ExecuteAndVerifyAddStats(pc_0, type, id, stats);
783 ASSERT_TRUE(ExecuteScriptAndExtractString(
784 shell()->web_contents(),
785 "window.domAutomationController.send("
786 "JSON.stringify(peerConnectionDataStore));",
787 &dump_json));
788 dump.reset(base::JSONReader::Read(dump_json));
789 VerifyStatsDump(dump.get(), pc_0, type, id, stats);
792 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, UpdateGetUserMedia) {
793 GURL url("chrome://webrtc-internals");
794 NavigateToURL(shell(), url);
796 UserMediaRequestEntry request1(1, 1, "origin", "ac", "vc");
797 UserMediaRequestEntry request2(2, 2, "origin2", "ac2", "vc2");
798 ExecuteAddGetUserMediaJs(request1);
799 ExecuteAddGetUserMediaJs(request2);
801 std::vector<UserMediaRequestEntry> list;
802 list.push_back(request1);
803 list.push_back(request2);
804 VerifyUserMediaRequest(list);
806 ExecuteRemoveGetUserMediaForRendererJs(1);
807 list.erase(list.begin());
808 VerifyUserMediaRequest(list);
810 ExecuteRemoveGetUserMediaForRendererJs(2);
811 list.erase(list.begin());
812 VerifyUserMediaRequest(list);
815 // Tests that the received propagation delta values are converted and drawn
816 // correctly.
817 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
818 ReceivedPropagationDelta) {
819 GURL url("chrome://webrtc-internals");
820 NavigateToURL(shell(), url);
822 PeerConnectionEntry pc(1, 0);
823 ExecuteAddPeerConnectionJs(pc);
825 StatsUnit stats = {FAKE_TIME_STAMP};
826 stats.values["googReceivedPacketGroupArrivalTimeDebug"] =
827 "[1000, 1100, 1200]";
828 stats.values["googReceivedPacketGroupPropagationDeltaDebug"] =
829 "[10, 20, 30]";
830 const string stats_type = "bwe";
831 const string stats_id = "videobwe";
832 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
834 string graph_id = pc.getIdString() + "-" + stats_id +
835 "-googReceivedPacketGroupPropagationDeltaDebug";
836 string data_series_id =
837 stats_id + "-googReceivedPacketGroupPropagationDeltaDebug";
838 bool result = false;
839 // Verify that the graph exists.
840 ASSERT_TRUE(ExecuteScriptAndExtractBool(
841 shell()->web_contents(),
842 "window.domAutomationController.send("
843 " graphViews['" + graph_id + "'] != null)",
844 &result));
845 EXPECT_TRUE(result);
847 // Verify that the graph contains multiple data points.
848 int count = 0;
849 ASSERT_TRUE(ExecuteScriptAndExtractInt(
850 shell()->web_contents(),
851 "window.domAutomationController.send("
852 " graphViews['" + graph_id + "'].getDataSeriesCount())",
853 &count));
854 EXPECT_EQ(1, count);
855 ASSERT_TRUE(ExecuteScriptAndExtractInt(
856 shell()->web_contents(),
857 "window.domAutomationController.send("
858 " peerConnectionDataStore['" + pc.getIdString() + "']" +
859 " .getDataSeries('" + data_series_id + "').getCount())",
860 &count));
861 EXPECT_EQ(3, count);
864 } // namespace content