Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / browser / media / webrtc_internals_browsertest.cc
blobc1a418590afebab48cfb5b5490b0468a8a8f532a
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 virtual ~MAYBE_WebRtcInternalsBrowserTest() {}
154 virtual void SetUpOnMainThread() OVERRIDE {
155 // We need fake devices in this test since we want to run on naked VMs. We
156 // assume these switches are set by default in content_browsertests.
157 ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
158 switches::kUseFakeDeviceForMediaStream));
159 ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
160 switches::kUseFakeUIForMediaStream));
163 protected:
164 bool ExecuteJavascript(const string& javascript) {
165 return ExecuteScript(shell()->web_contents(), javascript);
168 void ExpectTitle(const std::string& expected_title) const {
169 base::string16 expected_title16(base::ASCIIToUTF16(expected_title));
170 TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
171 EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
174 // Execute the javascript of addPeerConnection.
175 void ExecuteAddPeerConnectionJs(const PeerConnectionEntry& pc) {
176 std::stringstream ss;
177 ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ << ", " <<
178 "url:'u', rtcConfiguration:'s', constraints:'c'}";
179 ASSERT_TRUE(ExecuteJavascript("addPeerConnection(" + ss.str() + ");"));
182 // Execute the javascript of removePeerConnection.
183 void ExecuteRemovePeerConnectionJs(const PeerConnectionEntry& pc) {
184 std::stringstream ss;
185 ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ << "}";
187 ASSERT_TRUE(ExecuteJavascript("removePeerConnection(" + ss.str() + ");"));
190 // Execute the javascript of addGetUserMedia.
191 void ExecuteAddGetUserMediaJs(const UserMediaRequestEntry& request) {
192 std::stringstream ss;
193 ss << "{pid:" << request.pid << ", rid:" << request.rid << ", origin:'"
194 << request.origin << "', audio:'" << request.audio_constraints
195 << "', video:'" << request.video_constraints << "'}";
197 ASSERT_TRUE(ExecuteJavascript("addGetUserMedia(" + ss.str() + ");"));
200 // Execute the javascript of removeGetUserMediaForRenderer.
201 void ExecuteRemoveGetUserMediaForRendererJs(int rid) {
202 std::stringstream ss;
203 ss << "{rid:" << rid << "}";
204 ASSERT_TRUE(
205 ExecuteJavascript("removeGetUserMediaForRenderer(" + ss.str() + ");"));
208 // Verifies that the DOM element with id |id| exists.
209 void VerifyElementWithId(const string& id) {
210 bool result = false;
211 ASSERT_TRUE(ExecuteScriptAndExtractBool(
212 shell()->web_contents(),
213 "window.domAutomationController.send($('" + id + "') != null);",
214 &result));
215 EXPECT_TRUE(result);
218 // Verifies that the DOM element with id |id| does not exist.
219 void VerifyNoElementWithId(const string& id) {
220 bool result = false;
221 ASSERT_TRUE(ExecuteScriptAndExtractBool(
222 shell()->web_contents(),
223 "window.domAutomationController.send($('" + id + "') == null);",
224 &result));
225 EXPECT_TRUE(result);
228 // Verifies the JS Array of userMediaRequests matches |requests|.
229 void VerifyUserMediaRequest(
230 const std::vector<UserMediaRequestEntry>& requests) {
231 string json_requests;
232 ASSERT_TRUE(ExecuteScriptAndExtractString(
233 shell()->web_contents(),
234 "window.domAutomationController.send("
235 "JSON.stringify(userMediaRequests));",
236 &json_requests));
237 scoped_ptr<base::Value> value_requests;
238 value_requests.reset(base::JSONReader::Read(json_requests));
240 EXPECT_EQ(base::Value::TYPE_LIST, value_requests->GetType());
242 base::ListValue* list_request =
243 static_cast<base::ListValue*>(value_requests.get());
244 EXPECT_EQ(requests.size(), list_request->GetSize());
246 for (size_t i = 0; i < requests.size(); ++i) {
247 base::DictionaryValue* dict = NULL;
248 ASSERT_TRUE(list_request->GetDictionary(i, &dict));
249 int pid, rid;
250 std::string origin, audio, video;
251 ASSERT_TRUE(dict->GetInteger("pid", &pid));
252 ASSERT_TRUE(dict->GetInteger("rid", &rid));
253 ASSERT_TRUE(dict->GetString("origin", &origin));
254 ASSERT_TRUE(dict->GetString("audio", &audio));
255 ASSERT_TRUE(dict->GetString("video", &video));
256 EXPECT_EQ(requests[i].pid, pid);
257 EXPECT_EQ(requests[i].rid, rid);
258 EXPECT_EQ(requests[i].origin, origin);
259 EXPECT_EQ(requests[i].audio_constraints, audio);
260 EXPECT_EQ(requests[i].video_constraints, video);
263 bool user_media_tab_existed = false;
264 ASSERT_TRUE(ExecuteScriptAndExtractBool(
265 shell()->web_contents(),
266 "window.domAutomationController.send("
267 "$('user-media-tab-id') != null);",
268 &user_media_tab_existed));
269 EXPECT_EQ(!requests.empty(), user_media_tab_existed);
271 if (user_media_tab_existed) {
272 int user_media_request_count = -1;
273 ASSERT_TRUE(ExecuteScriptAndExtractInt(
274 shell()->web_contents(),
275 "window.domAutomationController.send("
276 "$('user-media-tab-id').childNodes.length);",
277 &user_media_request_count));
278 ASSERT_EQ(requests.size(), static_cast<size_t>(user_media_request_count));
282 // Verifies that DOM for |pc| is correctly created with the right content.
283 void VerifyPeerConnectionEntry(const PeerConnectionEntry& pc) {
284 VerifyElementWithId(pc.getIdString());
285 if (pc.events_.size() == 0)
286 return;
288 string log_id = pc.getLogIdString();
289 VerifyElementWithId(log_id);
290 string result;
291 for (size_t i = 0; i < pc.events_.size(); ++i) {
292 std::stringstream ss;
293 ss << "var row = $('" << log_id << "').rows[" << (i + 1) << "];"
294 "var cell = row.lastChild;"
295 "window.domAutomationController.send(cell.firstChild.textContent);";
296 ASSERT_TRUE(ExecuteScriptAndExtractString(
297 shell()->web_contents(), ss.str(), &result));
298 EXPECT_EQ(pc.events_[i].type + pc.events_[i].value, result);
302 // Executes the javascript of updatePeerConnection and verifies the result.
303 void ExecuteAndVerifyUpdatePeerConnection(
304 PeerConnectionEntry& pc, const string& type, const string& value) {
305 pc.AddEvent(type, value);
307 std::stringstream ss;
308 ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ <<
309 ", type:'" << type << "', value:'" << value << "'}";
310 ASSERT_TRUE(ExecuteJavascript("updatePeerConnection(" + ss.str() + ")"));
312 VerifyPeerConnectionEntry(pc);
315 // Execute addStats and verifies that the stats table has the right content.
316 void ExecuteAndVerifyAddStats(
317 PeerConnectionEntry& pc, const string& type, const string& id,
318 StatsUnit& stats) {
319 StatsEntry entry = {type, id, stats};
321 // Adds each new value to the map of stats history.
322 std::map<string, string>::iterator iter;
323 for (iter = stats.values.begin(); iter != stats.values.end(); iter++) {
324 pc.stats_[id][iter->first].push_back(iter->second);
326 std::stringstream ss;
327 ss << "{pid:" << pc.pid_ << ", lid:" << pc.lid_ << ","
328 "reports:[" << "{id:'" << id << "', type:'" << type << "', "
329 "stats:" << stats.GetString() << "}]}";
331 ASSERT_TRUE(ExecuteJavascript("addStats(" + ss.str() + ")"));
332 VerifyStatsTable(pc, entry);
336 // Verifies that the stats table has the right content.
337 void VerifyStatsTable(const PeerConnectionEntry& pc,
338 const StatsEntry& report) {
339 string table_id =
340 pc.getIdString() + "-table-" + report.id;
341 VerifyElementWithId(table_id);
343 std::map<string, string>::const_iterator iter;
344 for (iter = report.stats.values.begin();
345 iter != report.stats.values.end(); iter++) {
346 VerifyStatsTableRow(table_id, iter->first, iter->second);
350 // Verifies that the row named as |name| of the stats table |table_id| has
351 // the correct content as |name| : |value|.
352 void VerifyStatsTableRow(const string& table_id,
353 const string& name,
354 const string& value) {
355 VerifyElementWithId(table_id + "-" + name);
357 string result;
358 ASSERT_TRUE(ExecuteScriptAndExtractString(
359 shell()->web_contents(),
360 "var row = $('" + table_id + "-" + name + "');"
361 "var name = row.cells[0].textContent;"
362 "var value = row.cells[1].textContent;"
363 "window.domAutomationController.send(name + ':' + value)",
364 &result));
365 EXPECT_EQ(name + ":" + value, result);
368 // Verifies that the graph data series consistent with pc.stats_.
369 void VerifyStatsGraph(const PeerConnectionEntry& pc) {
370 std::map<string, StatsMap>::const_iterator stream_iter;
371 for (stream_iter = pc.stats_.begin();
372 stream_iter != pc.stats_.end(); stream_iter++) {
373 StatsMap::const_iterator stats_iter;
374 for (stats_iter = stream_iter->second.begin();
375 stats_iter != stream_iter->second.end();
376 stats_iter++) {
377 string graph_id = stream_iter->first + "-" + stats_iter->first;
378 for (size_t i = 0; i < stats_iter->second.size(); ++i) {
379 float number;
380 std::stringstream stream(stats_iter->second[i]);
381 stream >> number;
382 if (stream.fail())
383 continue;
384 VerifyGraphDataPoint(
385 pc.getIdString(), graph_id, i, stats_iter->second[i]);
391 // Verifies that the graph data point at index |index| has value |value|.
392 void VerifyGraphDataPoint(const string& pc_id, const string& graph_id,
393 int index, const string& value) {
394 bool result = false;
395 ASSERT_TRUE(ExecuteScriptAndExtractBool(
396 shell()->web_contents(),
397 "window.domAutomationController.send("
398 "graphViews['" + pc_id + "-" + graph_id + "'] != null)",
399 &result));
400 EXPECT_TRUE(result);
402 std::stringstream ss;
403 ss << "var dp = peerConnectionDataStore['" << pc_id << "']"
404 ".getDataSeries('" << graph_id << "').dataPoints_[" << index << "];"
405 "window.domAutomationController.send(dp.value.toString())";
406 string actual_value;
407 ASSERT_TRUE(ExecuteScriptAndExtractString(
408 shell()->web_contents(), ss.str(), &actual_value));
409 EXPECT_EQ(value, actual_value);
412 // Get the JSON string of the ssrc info from the page.
413 string GetSsrcInfo(const string& ssrc_id) {
414 string result;
415 EXPECT_TRUE(ExecuteScriptAndExtractString(
416 shell()->web_contents(),
417 "window.domAutomationController.send(JSON.stringify("
418 "ssrcInfoManager.streamInfoContainer_['" + ssrc_id + "']))",
419 &result));
420 return result;
423 int GetSsrcInfoBlockCount(Shell* shell) {
424 int count = 0;
425 EXPECT_TRUE(ExecuteScriptAndExtractInt(
426 shell->web_contents(),
427 "window.domAutomationController.send("
428 "document.getElementsByClassName("
429 "ssrcInfoManager.SSRC_INFO_BLOCK_CLASS).length);",
430 &count));
431 return count;
434 // Verifies |dump| contains |peer_connection_number| peer connection dumps,
435 // each containing |update_number| updates and |stats_number| stats tables.
436 void VerifyPageDumpStructure(base::Value* dump,
437 int peer_connection_number,
438 int update_number,
439 int stats_number) {
440 EXPECT_NE((base::Value*)NULL, dump);
441 EXPECT_EQ(base::Value::TYPE_DICTIONARY, dump->GetType());
443 base::DictionaryValue* dict_dump =
444 static_cast<base::DictionaryValue*>(dump);
445 EXPECT_EQ((size_t) peer_connection_number, dict_dump->size());
447 base::DictionaryValue::Iterator it(*dict_dump);
448 for (; !it.IsAtEnd(); it.Advance()) {
449 base::Value* value = NULL;
450 dict_dump->Get(it.key(), &value);
451 EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
452 base::DictionaryValue* pc_dump =
453 static_cast<base::DictionaryValue*>(value);
454 EXPECT_TRUE(pc_dump->HasKey("updateLog"));
455 EXPECT_TRUE(pc_dump->HasKey("stats"));
457 // Verifies the number of updates.
458 pc_dump->Get("updateLog", &value);
459 EXPECT_EQ(base::Value::TYPE_LIST, value->GetType());
460 base::ListValue* list = static_cast<base::ListValue*>(value);
461 EXPECT_EQ((size_t) update_number, list->GetSize());
463 // Verifies the number of stats tables.
464 pc_dump->Get("stats", &value);
465 EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
466 base::DictionaryValue* dict = static_cast<base::DictionaryValue*>(value);
467 EXPECT_EQ((size_t) stats_number, dict->size());
471 // Verifies |dump| contains the correct statsTable and statsDataSeries for
472 // |pc|.
473 void VerifyStatsDump(base::Value* dump,
474 const PeerConnectionEntry& pc,
475 const string& report_type,
476 const string& report_id,
477 const StatsUnit& stats) {
478 EXPECT_NE((base::Value*)NULL, dump);
479 EXPECT_EQ(base::Value::TYPE_DICTIONARY, dump->GetType());
481 base::DictionaryValue* dict_dump =
482 static_cast<base::DictionaryValue*>(dump);
483 base::Value* value = NULL;
484 dict_dump->Get(pc.getIdString(), &value);
485 base::DictionaryValue* pc_dump = static_cast<base::DictionaryValue*>(value);
487 // Verifies there is one data series per stats name.
488 value = NULL;
489 pc_dump->Get("stats", &value);
490 EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
492 base::DictionaryValue* dataSeries =
493 static_cast<base::DictionaryValue*>(value);
494 EXPECT_EQ(stats.values.size(), dataSeries->size());
498 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
499 AddAndRemovePeerConnection) {
500 GURL url("chrome://webrtc-internals");
501 NavigateToURL(shell(), url);
503 // Add two PeerConnections and then remove them.
504 PeerConnectionEntry pc_1(1, 0);
505 ExecuteAddPeerConnectionJs(pc_1);
506 VerifyPeerConnectionEntry(pc_1);
508 PeerConnectionEntry pc_2(2, 1);
509 ExecuteAddPeerConnectionJs(pc_2);
510 VerifyPeerConnectionEntry(pc_2);
512 ExecuteRemovePeerConnectionJs(pc_1);
513 VerifyNoElementWithId(pc_1.getIdString());
514 VerifyPeerConnectionEntry(pc_2);
516 ExecuteRemovePeerConnectionJs(pc_2);
517 VerifyNoElementWithId(pc_2.getIdString());
520 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
521 UpdateAllPeerConnections) {
522 GURL url("chrome://webrtc-internals");
523 NavigateToURL(shell(), url);
525 PeerConnectionEntry pc_0(1, 0);
526 pc_0.AddEvent("e1", "v1");
527 pc_0.AddEvent("e2", "v2");
528 PeerConnectionEntry pc_1(1, 1);
529 pc_1.AddEvent("e3", "v3");
530 pc_1.AddEvent("e4", "v4");
531 string pc_array = "[" + pc_0.getAllUpdateString() + ", " +
532 pc_1.getAllUpdateString() + "]";
533 EXPECT_TRUE(ExecuteJavascript("updateAllPeerConnections(" + pc_array + ");"));
534 VerifyPeerConnectionEntry(pc_0);
535 VerifyPeerConnectionEntry(pc_1);
538 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, UpdatePeerConnection) {
539 GURL url("chrome://webrtc-internals");
540 NavigateToURL(shell(), url);
542 // Add one PeerConnection and send one update.
543 PeerConnectionEntry pc_1(1, 0);
544 ExecuteAddPeerConnectionJs(pc_1);
546 ExecuteAndVerifyUpdatePeerConnection(pc_1, "e1", "v1");
548 // Add another PeerConnection and send two updates.
549 PeerConnectionEntry pc_2(1, 1);
550 ExecuteAddPeerConnectionJs(pc_2);
552 SsrcEntry ssrc1, ssrc2;
553 ssrc1.id = "ssrcid1";
554 ssrc1.properties["msid"] = "mymsid";
555 ssrc2.id = "ssrcid2";
556 ssrc2.properties["label"] = "mylabel";
557 ssrc2.properties["cname"] = "mycname";
559 ExecuteAndVerifyUpdatePeerConnection(pc_2, "setRemoteDescription",
560 ssrc1.GetSsrcAttributeString());
562 ExecuteAndVerifyUpdatePeerConnection(pc_2, "setLocalDescription",
563 ssrc2.GetSsrcAttributeString());
565 EXPECT_EQ(ssrc1.GetAsJSON(), GetSsrcInfo(ssrc1.id));
566 EXPECT_EQ(ssrc2.GetAsJSON(), GetSsrcInfo(ssrc2.id));
568 StatsUnit stats = {FAKE_TIME_STAMP};
569 stats.values["ssrc"] = ssrc1.id;
570 ExecuteAndVerifyAddStats(pc_2, "ssrc", "dummyId", stats);
571 EXPECT_GT(GetSsrcInfoBlockCount(shell()), 0);
574 // Tests that adding random named stats updates the dataSeries and graphs.
575 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, AddStats) {
576 GURL url("chrome://webrtc-internals");
577 NavigateToURL(shell(), url);
579 PeerConnectionEntry pc(1, 0);
580 ExecuteAddPeerConnectionJs(pc);
582 const string type = "ssrc";
583 const string id = "ssrc-1234";
584 StatsUnit stats = {FAKE_TIME_STAMP};
585 stats.values["trackId"] = "abcd";
586 stats.values["bitrate"] = "2000";
587 stats.values["framerate"] = "30";
589 // Add new stats and verify the stats table and graphs.
590 ExecuteAndVerifyAddStats(pc, type, id, stats);
591 VerifyStatsGraph(pc);
593 // Update existing stats and verify the stats table and graphs.
594 stats.values["bitrate"] = "2001";
595 stats.values["framerate"] = "31";
596 ExecuteAndVerifyAddStats(pc, type, id, stats);
597 VerifyStatsGraph(pc);
600 // Tests that the bandwidth estimation values are drawn on a single graph.
601 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, BweCompoundGraph) {
602 GURL url("chrome://webrtc-internals");
603 NavigateToURL(shell(), url);
605 PeerConnectionEntry pc(1, 0);
606 ExecuteAddPeerConnectionJs(pc);
608 StatsUnit stats = {FAKE_TIME_STAMP};
609 stats.values["googAvailableSendBandwidth"] = "1000000";
610 stats.values["googTargetEncBitrate"] = "1000";
611 stats.values["googActualEncBitrate"] = "1000000";
612 stats.values["googRetransmitBitrate"] = "10";
613 stats.values["googTransmitBitrate"] = "1000000";
614 const string stats_type = "bwe";
615 const string stats_id = "videobwe";
616 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
618 string graph_id =
619 pc.getIdString() + "-" + stats_id + "-bweCompound";
620 bool result = false;
621 // Verify that the bweCompound graph exists.
622 ASSERT_TRUE(ExecuteScriptAndExtractBool(
623 shell()->web_contents(),
624 "window.domAutomationController.send("
625 " graphViews['" + graph_id + "'] != null)",
626 &result));
627 EXPECT_TRUE(result);
629 // Verify that the bweCompound graph contains multiple dataSeries.
630 int count = 0;
631 ASSERT_TRUE(ExecuteScriptAndExtractInt(
632 shell()->web_contents(),
633 "window.domAutomationController.send("
634 " graphViews['" + graph_id + "'].getDataSeriesCount())",
635 &count));
636 EXPECT_EQ((int)stats.values.size(), count);
639 // Tests that the total packet/byte count is converted to count per second,
640 // and the converted data is drawn.
641 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, ConvertedGraphs) {
642 GURL url("chrome://webrtc-internals");
643 NavigateToURL(shell(), url);
645 PeerConnectionEntry pc(1, 0);
646 ExecuteAddPeerConnectionJs(pc);
648 const string stats_type = "s";
649 const string stats_id = "1";
650 const int num_converted_stats = 4;
651 const string stats_names[] =
652 {"packetsSent", "bytesSent", "packetsReceived", "bytesReceived"};
653 const string converted_names[] =
654 {"packetsSentPerSecond", "bitsSentPerSecond",
655 "packetsReceivedPerSecond", "bitsReceivedPerSecond"};
656 const string first_value = "1000";
657 const string second_value = "2000";
658 const string converted_values[] = {"1000", "8000", "1000", "8000"};
660 // Send the first data point.
661 StatsUnit stats = {FAKE_TIME_STAMP};
662 for (int i = 0; i < num_converted_stats; ++i)
663 stats.values[stats_names[i]] = first_value;
665 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
667 // Send the second data point at 1000ms after the first data point.
668 stats.timestamp += 1000;
669 for (int i = 0; i < num_converted_stats; ++i)
670 stats.values[stats_names[i]] = second_value;
671 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
673 // Verifies the graph data matches converted_values.
674 for (int i = 0; i < num_converted_stats; ++i) {
675 VerifyGraphDataPoint(pc.getIdString(), stats_id + "-" + converted_names[i],
676 1, converted_values[i]);
680 // Timing out on ARM linux bot: http://crbug.com/238490
681 // Disabling due to failure on Linux, Mac, Win: http://crbug.com/272413
682 // Sanity check of the page content under a real PeerConnection call.
683 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
684 DISABLED_WithRealPeerConnectionCall) {
685 // Start a peerconnection call in the first window.
686 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
687 GURL url(embedded_test_server()->GetURL("/media/peerconnection-call.html"));
688 NavigateToURL(shell(), url);
689 ASSERT_TRUE(ExecuteJavascript("call({video:true});"));
690 ExpectTitle("OK");
692 // Open webrtc-internals in the second window.
693 GURL url2("chrome://webrtc-internals");
694 Shell* shell2 = CreateBrowser();
695 NavigateToURL(shell2, url2);
697 const int NUMBER_OF_PEER_CONNECTIONS = 2;
699 // Verifies the number of peerconnections.
700 int count = 0;
701 ASSERT_TRUE(ExecuteScriptAndExtractInt(
702 shell2->web_contents(),
703 "window.domAutomationController.send("
704 "$('peer-connections-list').getElementsByTagName('li').length);",
705 &count));
706 EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
708 // Verifies the the event tables.
709 ASSERT_TRUE(ExecuteScriptAndExtractInt(
710 shell2->web_contents(),
711 "window.domAutomationController.send($('peer-connections-list')"
712 ".getElementsByClassName('update-log-table').length);",
713 &count));
714 EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
716 ASSERT_TRUE(ExecuteScriptAndExtractInt(
717 shell2->web_contents(),
718 "window.domAutomationController.send($('peer-connections-list')"
719 ".getElementsByClassName('update-log-table')[0].rows.length);",
720 &count));
721 EXPECT_GT(count, 1);
723 ASSERT_TRUE(ExecuteScriptAndExtractInt(
724 shell2->web_contents(),
725 "window.domAutomationController.send($('peer-connections-list')"
726 ".getElementsByClassName('update-log-table')[1].rows.length);",
727 &count));
728 EXPECT_GT(count, 1);
730 // Wait until the stats table containers are created.
731 count = 0;
732 while (count != NUMBER_OF_PEER_CONNECTIONS) {
733 ASSERT_TRUE(ExecuteScriptAndExtractInt(
734 shell2->web_contents(),
735 "window.domAutomationController.send("
736 "$('peer-connections-list').getElementsByClassName("
737 "'stats-table-container').length);",
738 &count));
741 // Verifies each stats table having more than one rows.
742 bool result = false;
743 ASSERT_TRUE(ExecuteScriptAndExtractBool(
744 shell2->web_contents(),
745 "var tableContainers = $('peer-connections-list')"
746 ".getElementsByClassName('stats-table-container');"
747 "var result = true;"
748 "for (var i = 0; i < tableContainers.length && result; ++i) {"
749 "var tables = tableContainers[i].getElementsByTagName('table');"
750 "for (var j = 0; j < tables.length && result; ++j) {"
751 "result = (tables[j].rows.length > 1);"
753 "if (!result) {"
754 "console.log(tableContainers[i].innerHTML);"
757 "window.domAutomationController.send(result);",
758 &result));
760 EXPECT_TRUE(result);
762 count = GetSsrcInfoBlockCount(shell2);
763 EXPECT_GT(count, 0);
766 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, CreatePageDump) {
767 GURL url("chrome://webrtc-internals");
768 NavigateToURL(shell(), url);
770 PeerConnectionEntry pc_0(1, 0);
771 pc_0.AddEvent("e1", "v1");
772 pc_0.AddEvent("e2", "v2");
773 PeerConnectionEntry pc_1(1, 1);
774 pc_1.AddEvent("e3", "v3");
775 pc_1.AddEvent("e4", "v4");
776 string pc_array =
777 "[" + pc_0.getAllUpdateString() + ", " + pc_1.getAllUpdateString() + "]";
778 EXPECT_TRUE(ExecuteJavascript("updateAllPeerConnections(" + pc_array + ");"));
780 // Verifies the peer connection data store can be created without stats.
781 string dump_json;
782 ASSERT_TRUE(ExecuteScriptAndExtractString(
783 shell()->web_contents(),
784 "window.domAutomationController.send("
785 "JSON.stringify(peerConnectionDataStore));",
786 &dump_json));
787 scoped_ptr<base::Value> dump;
788 dump.reset(base::JSONReader::Read(dump_json));
789 VerifyPageDumpStructure(dump.get(),
790 2 /*peer_connection_number*/,
791 2 /*update_number*/,
792 0 /*stats_number*/);
794 // Adds a stats report.
795 const string type = "dummy";
796 const string id = "1234";
797 StatsUnit stats = { FAKE_TIME_STAMP };
798 stats.values["bitrate"] = "2000";
799 stats.values["framerate"] = "30";
800 ExecuteAndVerifyAddStats(pc_0, type, id, stats);
802 ASSERT_TRUE(ExecuteScriptAndExtractString(
803 shell()->web_contents(),
804 "window.domAutomationController.send("
805 "JSON.stringify(peerConnectionDataStore));",
806 &dump_json));
807 dump.reset(base::JSONReader::Read(dump_json));
808 VerifyStatsDump(dump.get(), pc_0, type, id, stats);
811 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, UpdateGetUserMedia) {
812 GURL url("chrome://webrtc-internals");
813 NavigateToURL(shell(), url);
815 UserMediaRequestEntry request1(1, 1, "origin", "ac", "vc");
816 UserMediaRequestEntry request2(2, 2, "origin2", "ac2", "vc2");
817 ExecuteAddGetUserMediaJs(request1);
818 ExecuteAddGetUserMediaJs(request2);
820 std::vector<UserMediaRequestEntry> list;
821 list.push_back(request1);
822 list.push_back(request2);
823 VerifyUserMediaRequest(list);
825 ExecuteRemoveGetUserMediaForRendererJs(1);
826 list.erase(list.begin());
827 VerifyUserMediaRequest(list);
829 ExecuteRemoveGetUserMediaForRendererJs(2);
830 list.erase(list.begin());
831 VerifyUserMediaRequest(list);
834 // Tests that the received propagation delta values are converted and drawn
835 // correctly.
836 IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest,
837 ReceivedPropagationDelta) {
838 GURL url("chrome://webrtc-internals");
839 NavigateToURL(shell(), url);
841 PeerConnectionEntry pc(1, 0);
842 ExecuteAddPeerConnectionJs(pc);
844 StatsUnit stats = {FAKE_TIME_STAMP};
845 stats.values["googReceivedPacketGroupArrivalTimeDebug"] =
846 "[1000, 1100, 1200]";
847 stats.values["googReceivedPacketGroupPropagationDeltaDebug"] =
848 "[10, 20, 30]";
849 const string stats_type = "bwe";
850 const string stats_id = "videobwe";
851 ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
853 string graph_id = pc.getIdString() + "-" + stats_id +
854 "-googReceivedPacketGroupPropagationDeltaDebug";
855 string data_series_id =
856 stats_id + "-googReceivedPacketGroupPropagationDeltaDebug";
857 bool result = false;
858 // Verify that the graph exists.
859 ASSERT_TRUE(ExecuteScriptAndExtractBool(
860 shell()->web_contents(),
861 "window.domAutomationController.send("
862 " graphViews['" + graph_id + "'] != null)",
863 &result));
864 EXPECT_TRUE(result);
866 // Verify that the graph contains multiple data points.
867 int count = 0;
868 ASSERT_TRUE(ExecuteScriptAndExtractInt(
869 shell()->web_contents(),
870 "window.domAutomationController.send("
871 " graphViews['" + graph_id + "'].getDataSeriesCount())",
872 &count));
873 EXPECT_EQ(1, count);
874 ASSERT_TRUE(ExecuteScriptAndExtractInt(
875 shell()->web_contents(),
876 "window.domAutomationController.send("
877 " peerConnectionDataStore['" + pc.getIdString() + "']" +
878 " .getDataSeries('" + data_series_id + "').getCount())",
879 &count));
880 EXPECT_EQ(3, count);
883 } // namespace content