#include "content/browser/media/webrtc_internals.h"
-#include "base/command_line.h"
+#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
#include "content/browser/media/webrtc_internals_ui_observer.h"
+#include "content/browser/web_contents/web_contents_view.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_data.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/power_save_blocker.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
-#include "content/public/common/content_switches.h"
using base::ProcessId;
using std::string;
namespace content {
namespace {
+
+static base::LazyInstance<WebRTCInternals>::Leaky g_webrtc_internals =
+ LAZY_INSTANCE_INITIALIZER;
+
// Makes sure that |dict| has a ListValue under path "log".
static base::ListValue* EnsureLogList(base::DictionaryValue* dict) {
base::ListValue* log = NULL;
: aec_dump_enabled_(false) {
registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_TERMINATED,
NotificationService::AllBrowserContextsAndSources());
- BrowserChildProcessObserver::Add(this);
// TODO(grunell): Shouldn't all the webrtc_internals* files be excluded from the
// build if WebRTC is disabled?
#if defined(ENABLE_WEBRTC)
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableWebRtcAecRecordings)) {
- aec_dump_enabled_ = true;
- aec_dump_file_path_ = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
- switches::kEnableWebRtcAecRecordings);
+ aec_dump_file_path_ =
+ GetContentClient()->browser()->GetDefaultDownloadDirectory();
+ if (aec_dump_file_path_.empty()) {
+ // In this case the default path (|aec_dump_file_path_|) will be empty and
+ // the platform default path will be used in the file dialog (with no
+ // default file name). See SelectFileDialog::SelectFile. On Android where
+ // there's no dialog we'll fail to open the file.
+ VLOG(1) << "Could not get the download directory.";
} else {
-#if defined(OS_CHROMEOS)
aec_dump_file_path_ =
- base::FilePath(FILE_PATH_LITERAL("/tmp/audio.aecdump"));
-#elif defined(OS_ANDROID)
- aec_dump_file_path_ =
- base::FilePath(FILE_PATH_LITERAL("/sdcard/audio.aecdump"));
-#else
- aec_dump_file_path_ = base::FilePath(FILE_PATH_LITERAL("audio.aecdump"));
-#endif
+ aec_dump_file_path_.Append(FILE_PATH_LITERAL("audio.aecdump"));
}
#endif // defined(ENABLE_WEBRTC)
}
WebRTCInternals::~WebRTCInternals() {
- BrowserChildProcessObserver::Remove(this);
}
WebRTCInternals* WebRTCInternals::GetInstance() {
- return Singleton<WebRTCInternals>::get();
+ return g_webrtc_internals.Pointer();
}
void WebRTCInternals::OnAddPeerConnection(int render_process_id,
ProcessId pid,
int lid,
const string& url,
- const string& servers,
+ const string& rtc_configuration,
const string& constraints) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
dict->SetInteger("rid", render_process_id);
dict->SetInteger("pid", static_cast<int>(pid));
dict->SetInteger("lid", lid);
- dict->SetString("servers", servers);
+ dict->SetString("rtcConfiguration", rtc_configuration);
dict->SetString("constraints", constraints);
dict->SetString("url", url);
peer_connection_data_.Append(dict);
+ CreateOrReleasePowerSaveBlocker();
if (observers_.might_have_observers())
SendUpdate("addPeerConnection", dict);
continue;
peer_connection_data_.Remove(i, NULL);
+ CreateOrReleasePowerSaveBlocker();
if (observers_.might_have_observers()) {
base::DictionaryValue id;
if (!log_entry)
return;
+ double epoch_time = base::Time::Now().ToJsTime();
+ string time = base::DoubleToString(epoch_time);
+ log_entry->SetString("time", time);
log_entry->SetString("type", type);
log_entry->SetString("value", value);
log->Append(log_entry);
base::DictionaryValue update;
update.SetInteger("pid", static_cast<int>(pid));
update.SetInteger("lid", lid);
- update.SetString("type", type);
- update.SetString("value", value);
+ update.MergeDictionary(log_entry);
SendUpdate("updatePeerConnection", &update);
}
void WebRTCInternals::EnableAecDump(content::WebContents* web_contents) {
#if defined(ENABLE_WEBRTC)
+#if defined(OS_ANDROID)
+ EnableAecDumpOnAllRenderProcessHosts();
+#else
select_file_dialog_ = ui::SelectFileDialog::Create(this, NULL);
select_file_dialog_->SelectFile(
ui::SelectFileDialog::SELECT_SAVEAS_FILE,
NULL,
0,
FILE_PATH_LITERAL(""),
- web_contents->GetView()->GetTopLevelNativeWindow(),
+ web_contents->GetTopLevelNativeWindow(),
NULL);
#endif
+#endif
}
void WebRTCInternals::DisableAecDump() {
#if defined(ENABLE_WEBRTC)
aec_dump_enabled_ = false;
+
+ // Tear down the dialog since the user has unchecked the AEC dump box.
+ select_file_dialog_ = NULL;
+
for (RenderProcessHost::iterator i(
content::RenderProcessHost::AllHostsIterator());
!i.IsAtEnd(); i.Advance()) {
#endif
}
+void WebRTCInternals::ResetForTesting() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ observers_.Clear();
+ peer_connection_data_.Clear();
+ CreateOrReleasePowerSaveBlocker();
+ get_user_media_requests_.Clear();
+ aec_dump_enabled_ = false;
+}
+
void WebRTCInternals::SendUpdate(const string& command, base::Value* value) {
DCHECK(observers_.might_have_observers());
OnUpdate(command, value));
}
-void WebRTCInternals::BrowserChildProcessCrashed(
- const ChildProcessData& data) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- OnRendererExit(data.id);
-}
-
void WebRTCInternals::Observe(int type,
const NotificationSource& source,
const NotificationDetails& details) {
int /* unused_index */,
void* /*unused_params */) {
#if defined(ENABLE_WEBRTC)
- aec_dump_enabled_ = true;
aec_dump_file_path_ = path;
- for (RenderProcessHost::iterator i(
- content::RenderProcessHost::AllHostsIterator());
- !i.IsAtEnd(); i.Advance()) {
- i.GetCurrentValue()->EnableAecDump(aec_dump_file_path_);
- }
+ EnableAecDumpOnAllRenderProcessHosts();
+#endif
+}
+
+void WebRTCInternals::FileSelectionCanceled(void* params) {
+#if defined(ENABLE_WEBRTC)
+ SendUpdate("aecRecordingFileSelectionCancelled", NULL);
#endif
}
void WebRTCInternals::OnRendererExit(int render_process_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
// Iterates from the end of the list to remove the PeerConnections created
// by the exitting renderer.
for (int i = peer_connection_data_.GetSize() - 1; i >= 0; --i) {
peer_connection_data_.Remove(i, NULL);
}
}
+ CreateOrReleasePowerSaveBlocker();
bool found_any = false;
// Iterates from the end of the list to remove the getUserMedia requests
}
}
-void WebRTCInternals::ResetForTesting() {
+#if defined(ENABLE_WEBRTC)
+void WebRTCInternals::EnableAecDumpOnAllRenderProcessHosts() {
+ aec_dump_enabled_ = true;
+ for (RenderProcessHost::iterator i(
+ content::RenderProcessHost::AllHostsIterator());
+ !i.IsAtEnd(); i.Advance()) {
+ i.GetCurrentValue()->EnableAecDump(aec_dump_file_path_);
+ }
+}
+#endif
+
+void WebRTCInternals::CreateOrReleasePowerSaveBlocker() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- observers_.Clear();
- peer_connection_data_.Clear();
- get_user_media_requests_.Clear();
- aec_dump_enabled_ = false;
+
+ if (peer_connection_data_.empty() && power_save_blocker_) {
+ DVLOG(1) << ("Releasing the block on application suspension since no "
+ "PeerConnections are active anymore.");
+ power_save_blocker_.reset();
+ } else if (!peer_connection_data_.empty() && !power_save_blocker_) {
+ DVLOG(1) << ("Preventing the application from being suspended while one or "
+ "more PeerConnections are active.");
+ power_save_blocker_ = content::PowerSaveBlocker::Create(
+ content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
+ "WebRTC has active PeerConnections.").Pass();
+ }
}
} // namespace content