12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/media/webrtc_internals.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/path_service.h"
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/strings/string_number_conversions.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/media/webrtc_internals_ui_observer.h"
10010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/browser/web_contents/web_contents_view.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "content/public/browser/content_browser_client.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_service.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_types.h"
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "content/public/browser/power_save_blocker.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/render_process_host.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/web_contents.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using base::ProcessId;
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::string;
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace content {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic base::LazyInstance<WebRTCInternals>::Leaky g_webrtc_internals =
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    LAZY_INSTANCE_INITIALIZER;
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Makes sure that |dict| has a ListValue under path "log".
307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)static base::ListValue* EnsureLogList(base::DictionaryValue* dict) {
317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::ListValue* log = NULL;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict->GetList("log", &log)) {
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    log = new base::ListValue();
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (log)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      dict->Set("log", log);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return log;
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)WebRTCInternals::WebRTCInternals()
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : aec_dump_enabled_(false) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 NotificationService::AllBrowserContextsAndSources());
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(grunell): Shouldn't all the webrtc_internals* files be excluded from the
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// build if WebRTC is disabled?
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(ENABLE_WEBRTC)
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  aec_dump_file_path_ =
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      GetContentClient()->browser()->GetDefaultDownloadDirectory();
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (aec_dump_file_path_.empty()) {
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // In this case the default path (|aec_dump_file_path_|) will be empty and
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // the platform default path will be used in the file dialog (with no
54010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // default file name). See SelectFileDialog::SelectFile. On Android where
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // there's no dialog we'll fail to open the file.
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    VLOG(1) << "Could not get the download directory.";
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    aec_dump_file_path_ =
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        aec_dump_file_path_.Append(FILE_PATH_LITERAL("audio.aecdump"));
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif  // defined(ENABLE_WEBRTC)
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebRTCInternals::~WebRTCInternals() {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WebRTCInternals* WebRTCInternals::GetInstance() {
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return g_webrtc_internals.Pointer();
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebRTCInternals::OnAddPeerConnection(int render_process_id,
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          ProcessId pid,
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          int lid,
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const string& url,
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                          const string& rtc_configuration,
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const string& constraints) {
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!dict)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetInteger("rid", render_process_id);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetInteger("pid", static_cast<int>(pid));
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetInteger("lid", lid);
865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  dict->SetString("rtcConfiguration", rtc_configuration);
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString("constraints", constraints);
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString("url", url);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  peer_connection_data_.Append(dict);
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  CreateOrReleasePowerSaveBlocker();
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (observers_.might_have_observers())
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendUpdate("addPeerConnection", dict);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) {
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::DictionaryValue* dict = NULL;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    peer_connection_data_.GetDictionary(i, &dict);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int this_pid = 0;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int this_lid = 0;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->GetInteger("pid", &this_pid);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dict->GetInteger("lid", &this_lid);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (this_pid != static_cast<int>(pid) || this_lid != lid)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    peer_connection_data_.Remove(i, NULL);
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CreateOrReleasePowerSaveBlocker();
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
113424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (observers_.might_have_observers()) {
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::DictionaryValue id;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      id.SetInteger("pid", static_cast<int>(pid));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      id.SetInteger("lid", lid);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SendUpdate("removePeerConnection", &id);
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    break;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebRTCInternals::OnUpdatePeerConnection(
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProcessId pid, int lid, const string& type, const string& value) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) {
1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::DictionaryValue* record = NULL;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    peer_connection_data_.GetDictionary(i, &record);
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int this_pid = 0, this_lid = 0;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    record->GetInteger("pid", &this_pid);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    record->GetInteger("lid", &this_lid);
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (this_pid != static_cast<int>(pid) || this_lid != lid)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Append the update to the end of the log.
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::ListValue* log = EnsureLogList(record);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!log)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::DictionaryValue* log_entry = new base::DictionaryValue();
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!log_entry)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    double epoch_time = base::Time::Now().ToJsTime();
1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    string time = base::DoubleToString(epoch_time);
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    log_entry->SetString("time", time);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    log_entry->SetString("type", type);
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    log_entry->SetString("value", value);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    log->Append(log_entry);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
154424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (observers_.might_have_observers()) {
1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::DictionaryValue update;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      update.SetInteger("pid", static_cast<int>(pid));
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      update.SetInteger("lid", lid);
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      update.MergeDictionary(log_entry);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SendUpdate("updatePeerConnection", &update);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid,
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 const base::ListValue& value) {
168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!observers_.might_have_observers())
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue dict;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict.SetInteger("pid", static_cast<int>(pid));
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict.SetInteger("lid", lid);
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::ListValue* list = value.DeepCopy();
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!list)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict.Set("reports", list);
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendUpdate("addStats", &dict);
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRTCInternals::OnGetUserMedia(int rid,
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     base::ProcessId pid,
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     const std::string& origin,
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     bool audio,
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     bool video,
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     const std::string& audio_constraints,
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     const std::string& video_constraints) {
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dict->SetInteger("rid", rid);
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dict->SetInteger("pid", static_cast<int>(pid));
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  dict->SetString("origin", origin);
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (audio)
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dict->SetString("audio", audio_constraints);
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (video)
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    dict->SetString("video", video_constraints);
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  get_user_media_requests_.Append(dict);
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (observers_.might_have_observers())
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SendUpdate("addGetUserMedia", dict);
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver *observer) {
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.AddObserver(observer);
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver *observer) {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  observers_.RemoveObserver(observer);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Disables the AEC recording if it is enabled and the last webrtc-internals
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // page is going away.
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (aec_dump_enabled_ && !observers_.might_have_observers())
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DisableAecDump();
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) {
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (peer_connection_data_.GetSize() > 0)
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    observer->OnUpdate("updateAllPeerConnections", &peer_connection_data_);
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (base::ListValue::iterator it = get_user_media_requests_.begin();
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != get_user_media_requests_.end();
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ++it) {
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    observer->OnUpdate("addGetUserMedia", *it);
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRTCInternals::EnableAecDump(content::WebContents* web_contents) {
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(ENABLE_WEBRTC)
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID)
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EnableAecDumpOnAllRenderProcessHosts();
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#else
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  select_file_dialog_ = ui::SelectFileDialog::Create(this, NULL);
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  select_file_dialog_->SelectFile(
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ui::SelectFileDialog::SELECT_SAVEAS_FILE,
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::string16(),
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      aec_dump_file_path_,
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL,
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      0,
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FILE_PATH_LITERAL(""),
248010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      web_contents->GetTopLevelNativeWindow(),
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      NULL);
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRTCInternals::DisableAecDump() {
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(ENABLE_WEBRTC)
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aec_dump_enabled_ = false;
25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Tear down the dialog since the user has unchecked the AEC dump box.
25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  select_file_dialog_ = NULL;
26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (RenderProcessHost::iterator i(
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           content::RenderProcessHost::AllHostsIterator());
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       !i.IsAtEnd(); i.Advance()) {
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    i.GetCurrentValue()->DisableAecDump();
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRTCInternals::ResetForTesting() {
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  observers_.Clear();
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  peer_connection_data_.Clear();
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  CreateOrReleasePowerSaveBlocker();
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  get_user_media_requests_.Clear();
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aec_dump_enabled_ = false;
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void WebRTCInternals::SendUpdate(const string& command, base::Value* value) {
279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(observers_.might_have_observers());
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FOR_EACH_OBSERVER(WebRTCInternalsUIObserver,
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    observers_,
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    OnUpdate(command, value));
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRTCInternals::Observe(int type,
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const NotificationSource& source,
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const NotificationDetails& details) {
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(type, NOTIFICATION_RENDERER_PROCESS_TERMINATED);
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OnRendererExit(Source<RenderProcessHost>(source)->GetID());
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRTCInternals::FileSelected(const base::FilePath& path,
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   int /* unused_index */,
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   void* /*unused_params */) {
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(ENABLE_WEBRTC)
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aec_dump_file_path_ = path;
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EnableAecDumpOnAllRenderProcessHosts();
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid WebRTCInternals::FileSelectionCanceled(void* params) {
304effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#if defined(ENABLE_WEBRTC)
305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SendUpdate("aecRecordingFileSelectionCancelled", NULL);
306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif
307effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WebRTCInternals::OnRendererExit(int render_process_id) {
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Iterates from the end of the list to remove the PeerConnections created
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // by the exitting renderer.
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = peer_connection_data_.GetSize() - 1; i >= 0; --i) {
3157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::DictionaryValue* record = NULL;
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    peer_connection_data_.GetDictionary(i, &record);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int this_rid = 0;
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    record->GetInteger("rid", &this_rid);
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (this_rid == render_process_id) {
322424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (observers_.might_have_observers()) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int lid = 0, pid = 0;
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        record->GetInteger("lid", &lid);
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        record->GetInteger("pid", &pid);
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::DictionaryValue update;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        update.SetInteger("lid", lid);
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        update.SetInteger("pid", pid);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        SendUpdate("removePeerConnection", &update);
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      peer_connection_data_.Remove(i, NULL);
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  CreateOrReleasePowerSaveBlocker();
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool found_any = false;
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Iterates from the end of the list to remove the getUserMedia requests
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // created by the exiting renderer.
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (int i = get_user_media_requests_.GetSize() - 1; i >= 0; --i) {
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* record = NULL;
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    get_user_media_requests_.GetDictionary(i, &record);
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int this_rid = 0;
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    record->GetInteger("rid", &this_rid);
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (this_rid == render_process_id) {
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      get_user_media_requests_.Remove(i, NULL);
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      found_any = true;
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (found_any && observers_.might_have_observers()) {
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue update;
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    update.SetInteger("rid", render_process_id);
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    SendUpdate("removeGetUserMediaForRenderer", &update);
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(ENABLE_WEBRTC)
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void WebRTCInternals::EnableAecDumpOnAllRenderProcessHosts() {
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  aec_dump_enabled_ = true;
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (RenderProcessHost::iterator i(
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           content::RenderProcessHost::AllHostsIterator());
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       !i.IsAtEnd(); i.Advance()) {
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    i.GetCurrentValue()->EnableAecDump(aec_dump_file_path_);
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void WebRTCInternals::CreateOrReleasePowerSaveBlocker() {
3726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (peer_connection_data_.empty() && power_save_blocker_) {
3756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DVLOG(1) << ("Releasing the block on application suspension since no "
3766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 "PeerConnections are active anymore.");
3776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    power_save_blocker_.reset();
3786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else if (!peer_connection_data_.empty() && !power_save_blocker_) {
3796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    DVLOG(1) << ("Preventing the application from being suspended while one or "
3806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                 "more PeerConnections are active.");
3816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    power_save_blocker_ = content::PowerSaveBlocker::Create(
3826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
3836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        "WebRTC has active PeerConnections.").Pass();
3846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
3866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace content
388