- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / media / webrtc_internals_browsertest.cc
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.
4
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"
16
17 using std::string;
18 namespace content {
19
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;
27     }
28     return ss.str();
29   }
30
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 << "\"";
39     }
40     ss << "}";
41     return ss.str();
42   }
43
44   string id;
45   std::map<string, string> properties;
46 };
47
48 struct EventEntry {
49   string type;
50   string value;
51 };
52
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 << "',";
60     }
61     ss << "]}";
62     return ss.str();
63   }
64
65   int64 timestamp;
66   std::map<string, string> values;
67 };
68
69 struct StatsEntry {
70   string type;
71   string id;
72   StatsUnit stats;
73 };
74
75 typedef std::map<string, std::vector<string> > StatsMap;
76
77 class PeerConnectionEntry {
78  public:
79   PeerConnectionEntry(int pid, int lid) : pid_(pid), lid_(lid) {}
80
81   void AddEvent(const string& type, const string& value) {
82     EventEntry entry = {type, value};
83     events_.push_back(entry);
84   }
85
86   string getIdString() const {
87     std::stringstream ss;
88     ss << pid_ << "-" << lid_;
89     return ss.str();
90   }
91
92   string getLogIdString() const {
93     std::stringstream ss;
94     ss << pid_ << "-" << lid_ << "-update-log";
95     return ss.str();
96   }
97
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 << "'},";
104     }
105     ss << "]}";
106     return ss.str();
107   }
108
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_;
117 };
118
119 static const int64 FAKE_TIME_STAMP = 3600000;
120
121 #if defined(OS_WIN)
122 // All tests are flaky on Windows: crbug.com/277322.
123 #define MAYBE_WebRTCInternalsBrowserTest DISABLED_WebRTCInternalsBrowserTest
124 #else
125 #define MAYBE_WebRTCInternalsBrowserTest WebRTCInternalsBrowserTest
126 #endif
127
128 class MAYBE_WebRTCInternalsBrowserTest: public ContentBrowserTest {
129  public:
130   MAYBE_WebRTCInternalsBrowserTest() {}
131   virtual ~MAYBE_WebRTCInternalsBrowserTest() {}
132
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));
140   }
141
142  protected:
143   bool ExecuteJavascript(const string& javascript) {
144     return ExecuteScript(shell()->web_contents(), javascript);
145   }
146
147   void ExpectTitle(const std::string& expected_title) const {
148     string16 expected_title16(ASCIIToUTF16(expected_title));
149     TitleWatcher title_watcher(shell()->web_contents(), expected_title16);
150     EXPECT_EQ(expected_title16, title_watcher.WaitAndGetTitle());
151   }
152
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() + ");"));
159   }
160
161   // Execute the javascript of removePeerConnection.
162   void ExecuteRemovePeerConnectionJs(const PeerConnectionEntry& pc) {
163     std::stringstream ss;
164     ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ << "}";
165
166     ASSERT_TRUE(ExecuteJavascript("removePeerConnection(" + ss.str() + ");"));
167   }
168
169   // Verifies that the DOM element with id |id| exists.
170   void VerifyElementWithId(const string& id) {
171     bool result = false;
172     ASSERT_TRUE(ExecuteScriptAndExtractBool(
173         shell()->web_contents(),
174         "window.domAutomationController.send($('" + id + "') != null);",
175         &result));
176     EXPECT_TRUE(result);
177   }
178
179   // Verifies that the DOM element with id |id| does not exist.
180   void VerifyNoElementWithId(const string& id) {
181     bool result = false;
182     ASSERT_TRUE(ExecuteScriptAndExtractBool(
183         shell()->web_contents(),
184         "window.domAutomationController.send($('" + id + "') == null);",
185         &result));
186     EXPECT_TRUE(result);
187   }
188
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)
193       return;
194
195     string log_id = pc.getLogIdString();
196     VerifyElementWithId(log_id);
197     string result;
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);
206     }
207   }
208
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);
213
214     std::stringstream ss;
215     ss << "{pid:" << pc.pid_ <<", lid:" << pc.lid_ <<
216          ", type:'" << type << "', value:'" << value << "'}";
217     ASSERT_TRUE(ExecuteJavascript("updatePeerConnection(" + ss.str() + ")"));
218
219     VerifyPeerConnectionEntry(pc);
220   }
221
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,
225       StatsUnit& stats) {
226     StatsEntry entry = {type, id, stats};
227
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);
232     }
233     std::stringstream ss;
234     ss << "{pid:" << pc.pid_ << ", lid:" << pc.lid_ << ","
235            "reports:[" << "{id:'" << id << "', type:'" << type << "', "
236                            "stats:" << stats.GetString() << "}]}";
237
238     ASSERT_TRUE(ExecuteJavascript("addStats(" + ss.str() + ")"));
239     VerifyStatsTable(pc, entry);
240   }
241
242
243   // Verifies that the stats table has the right content.
244   void VerifyStatsTable(const PeerConnectionEntry& pc,
245                         const StatsEntry& report) {
246     string table_id =
247         pc.getIdString() + "-table-" + report.id;
248     VerifyElementWithId(table_id);
249
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);
254     }
255   }
256
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,
260                            const string& name,
261                            const string& value) {
262     VerifyElementWithId(table_id + "-" + name);
263
264     string result;
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)",
271         &result));
272     EXPECT_EQ(name + ":" + value, result);
273   }
274
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();
283            stats_iter++) {
284         string graph_id = stream_iter->first + "-" + stats_iter->first;
285         for (size_t i = 0; i < stats_iter->second.size(); ++i) {
286           float number;
287           std::stringstream stream(stats_iter->second[i]);
288           stream >> number;
289           if (stream.fail())
290             continue;
291           VerifyGraphDataPoint(
292               pc.getIdString(), graph_id, i, stats_iter->second[i]);
293         }
294       }
295     }
296   }
297
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) {
301     bool result = false;
302     ASSERT_TRUE(ExecuteScriptAndExtractBool(
303         shell()->web_contents(),
304         "window.domAutomationController.send("
305            "graphViews['" + pc_id + "-" + graph_id + "'] != null)",
306         &result));
307     EXPECT_TRUE(result);
308
309     std::stringstream ss;
310     ss << "var dp = peerConnectionDataStore['" << pc_id << "']"
311           ".getDataSeries('" << graph_id << "').dataPoints_[" << index << "];"
312           "window.domAutomationController.send(dp.value.toString())";
313     string actual_value;
314     ASSERT_TRUE(ExecuteScriptAndExtractString(
315         shell()->web_contents(), ss.str(), &actual_value));
316     EXPECT_EQ(value, actual_value);
317   }
318
319   // Get the JSON string of the ssrc info from the page.
320   string GetSsrcInfo(const string& ssrc_id) {
321     string result;
322     EXPECT_TRUE(ExecuteScriptAndExtractString(
323         shell()->web_contents(),
324         "window.domAutomationController.send(JSON.stringify("
325            "ssrcInfoManager.streamInfoContainer_['" + ssrc_id + "']))",
326         &result));
327     return result;
328   }
329
330   int GetSsrcInfoBlockCount(Shell* shell) {
331     int count = 0;
332     EXPECT_TRUE(ExecuteScriptAndExtractInt(
333         shell->web_contents(),
334         "window.domAutomationController.send("
335             "document.getElementsByClassName("
336                 "ssrcInfoManager.SSRC_INFO_BLOCK_CLASS).length);",
337         &count));
338     return count;
339   }
340
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,
345                                int update_number,
346                                int stats_number) {
347     EXPECT_NE((base::Value*)NULL, dump);
348     EXPECT_EQ(base::Value::TYPE_DICTIONARY, dump->GetType());
349
350     base::DictionaryValue* dict_dump =
351         static_cast<base::DictionaryValue*>(dump);
352     EXPECT_EQ((size_t) peer_connection_number, dict_dump->size());
353
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"));
363
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());
369
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());
375     }
376   }
377
378   // Verifies |dump| contains the correct statsTable and statsDataSeries for
379   // |pc|.
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());
387
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);
393
394     // Verifies there is one data series per stats name.
395     value = NULL;
396     pc_dump->Get("stats", &value);
397     EXPECT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
398
399     base::DictionaryValue* dataSeries =
400         static_cast<base::DictionaryValue*>(value);
401     EXPECT_EQ(stats.values.size(), dataSeries->size());
402   }
403 };
404
405 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest,
406                        AddAndRemovePeerConnection) {
407   GURL url("chrome://webrtc-internals");
408   NavigateToURL(shell(), url);
409
410   // Add two PeerConnections and then remove them.
411   PeerConnectionEntry pc_1(1, 0);
412   ExecuteAddPeerConnectionJs(pc_1);
413   VerifyPeerConnectionEntry(pc_1);
414
415   PeerConnectionEntry pc_2(2, 1);
416   ExecuteAddPeerConnectionJs(pc_2);
417   VerifyPeerConnectionEntry(pc_2);
418
419   ExecuteRemovePeerConnectionJs(pc_1);
420   VerifyNoElementWithId(pc_1.getIdString());
421   VerifyPeerConnectionEntry(pc_2);
422
423   ExecuteRemovePeerConnectionJs(pc_2);
424   VerifyNoElementWithId(pc_2.getIdString());
425 }
426
427 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest,
428                        UpdateAllPeerConnections) {
429   GURL url("chrome://webrtc-internals");
430   NavigateToURL(shell(), url);
431
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);
443 }
444
445 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest, UpdatePeerConnection) {
446   GURL url("chrome://webrtc-internals");
447   NavigateToURL(shell(), url);
448
449   // Add one PeerConnection and send one update.
450   PeerConnectionEntry pc_1(1, 0);
451   ExecuteAddPeerConnectionJs(pc_1);
452
453   ExecuteAndVerifyUpdatePeerConnection(pc_1, "e1", "v1");
454
455   // Add another PeerConnection and send two updates.
456   PeerConnectionEntry pc_2(1, 1);
457   ExecuteAddPeerConnectionJs(pc_2);
458
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";
465
466   ExecuteAndVerifyUpdatePeerConnection(pc_2, "setRemoteDescription",
467       ssrc1.GetSsrcAttributeString());
468
469   ExecuteAndVerifyUpdatePeerConnection(pc_2, "setLocalDescription",
470       ssrc2.GetSsrcAttributeString());
471
472   EXPECT_EQ(ssrc1.GetAsJSON(), GetSsrcInfo(ssrc1.id));
473   EXPECT_EQ(ssrc2.GetAsJSON(), GetSsrcInfo(ssrc2.id));
474
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);
479 }
480
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);
485
486   PeerConnectionEntry pc(1, 0);
487   ExecuteAddPeerConnectionJs(pc);
488
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";
495
496   // Add new stats and verify the stats table and graphs.
497   ExecuteAndVerifyAddStats(pc, type, id, stats);
498   VerifyStatsGraph(pc);
499
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);
505 }
506
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);
511
512   PeerConnectionEntry pc(1, 0);
513   ExecuteAddPeerConnectionJs(pc);
514
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);
524
525   string graph_id =
526       pc.getIdString() + "-" + stats_id + "-bweCompound";
527   bool result = false;
528   // Verify that the bweCompound graph exists.
529   ASSERT_TRUE(ExecuteScriptAndExtractBool(
530         shell()->web_contents(),
531         "window.domAutomationController.send("
532         "   graphViews['" + graph_id + "'] != null)",
533         &result));
534   EXPECT_TRUE(result);
535
536   // Verify that the bweCompound graph contains multiple dataSeries.
537   int count = 0;
538   ASSERT_TRUE(ExecuteScriptAndExtractInt(
539         shell()->web_contents(),
540         "window.domAutomationController.send("
541         "   graphViews['" + graph_id + "'].getDataSeriesCount())",
542         &count));
543   EXPECT_EQ((int)stats.values.size(), count);
544 }
545
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);
551
552   PeerConnectionEntry pc(1, 0);
553   ExecuteAddPeerConnectionJs(pc);
554
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"};
566
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;
571
572   ExecuteAndVerifyAddStats(pc, stats_type, stats_id, stats);
573
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);
579
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]);
584   }
585 }
586
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});"));
597   ExpectTitle("OK");
598
599   // Open webrtc-internals in the second window.
600   GURL url2("chrome://webrtc-internals");
601   Shell* shell2 = CreateBrowser();
602   NavigateToURL(shell2, url2);
603
604   const int NUMBER_OF_PEER_CONNECTIONS = 2;
605
606   // Verifies the number of peerconnections.
607   int count = 0;
608   ASSERT_TRUE(ExecuteScriptAndExtractInt(
609       shell2->web_contents(),
610       "window.domAutomationController.send("
611           "$('peer-connections-list').getElementsByTagName('li').length);",
612       &count));
613   EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
614
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);",
620       &count));
621   EXPECT_EQ(NUMBER_OF_PEER_CONNECTIONS, count);
622
623   ASSERT_TRUE(ExecuteScriptAndExtractInt(
624       shell2->web_contents(),
625       "window.domAutomationController.send($('peer-connections-list')"
626           ".getElementsByClassName('update-log-table')[0].rows.length);",
627       &count));
628   EXPECT_GT(count, 1);
629
630   ASSERT_TRUE(ExecuteScriptAndExtractInt(
631       shell2->web_contents(),
632       "window.domAutomationController.send($('peer-connections-list')"
633           ".getElementsByClassName('update-log-table')[1].rows.length);",
634       &count));
635   EXPECT_GT(count, 1);
636
637   // Wait until the stats table containers are created.
638   count = 0;
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);",
645         &count));
646   }
647
648   // Verifies each stats table having more than one rows.
649   bool result = false;
650   ASSERT_TRUE(ExecuteScriptAndExtractBool(
651       shell2->web_contents(),
652       "var tableContainers = $('peer-connections-list')"
653           ".getElementsByClassName('stats-table-container');"
654       "var result = true;"
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);"
659         "}"
660         "if (!result) {"
661           "console.log(tableContainers[i].innerHTML);"
662         "}"
663       "}"
664       "window.domAutomationController.send(result);",
665       &result));
666
667   EXPECT_TRUE(result);
668
669   count = GetSsrcInfoBlockCount(shell2);
670   EXPECT_GT(count, 0);
671 }
672
673 IN_PROC_BROWSER_TEST_F(MAYBE_WebRTCInternalsBrowserTest, CreatePageDump) {
674   GURL url("chrome://webrtc-internals");
675   NavigateToURL(shell(), url);
676
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");
683   string pc_array =
684       "[" + pc_0.getAllUpdateString() + ", " + pc_1.getAllUpdateString() + "]";
685   EXPECT_TRUE(ExecuteJavascript("updateAllPeerConnections(" + pc_array + ");"));
686
687   // Verifies the peer connection data store can be created without stats.
688   string dump_json;
689   ASSERT_TRUE(ExecuteScriptAndExtractString(
690       shell()->web_contents(),
691       "window.domAutomationController.send("
692       "JSON.stringify(peerConnectionDataStore));",
693       &dump_json));
694   scoped_ptr<base::Value> dump;
695   dump.reset(base::JSONReader::Read(dump_json));
696   VerifyPageDumpStructure(dump.get(),
697                           2 /*peer_connection_number*/,
698                           2 /*update_number*/,
699                           0 /*stats_number*/);
700
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);
708
709   ASSERT_TRUE(ExecuteScriptAndExtractString(
710       shell()->web_contents(),
711       "window.domAutomationController.send("
712       "JSON.stringify(peerConnectionDataStore));",
713       &dump_json));
714   dump.reset(base::JSONReader::Read(dump_json));
715   VerifyStatsDump(dump.get(), pc_0, type, id, stats);
716 }
717
718 }  // namespace content