Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/webrtc/webrtc_internals.h" | 5 #include "content/browser/webrtc/webrtc_internals.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 #define IntToStringType base::IntToString | 27 #define IntToStringType base::IntToString |
| 28 #endif | 28 #endif |
| 29 | 29 |
| 30 using base::ProcessId; | 30 using base::ProcessId; |
| 31 using std::string; | 31 using std::string; |
| 32 | 32 |
| 33 namespace content { | 33 namespace content { |
| 34 | 34 |
| 35 namespace { | 35 namespace { |
| 36 | 36 |
| 37 static base::LazyInstance<WebRTCInternals>::Leaky g_webrtc_internals = | 37 base::LazyInstance<WebRTCInternals>::Leaky g_webrtc_internals = |
| 38 LAZY_INSTANCE_INITIALIZER; | 38 LAZY_INSTANCE_INITIALIZER; |
| 39 | 39 |
| 40 // Makes sure that |dict| has a ListValue under path "log". | 40 // Makes sure that |dict| has a ListValue under path "log". |
| 41 static base::ListValue* EnsureLogList(base::DictionaryValue* dict) { | 41 base::ListValue* EnsureLogList(base::DictionaryValue* dict) { |
| 42 base::ListValue* log = NULL; | 42 base::ListValue* log = NULL; |
| 43 if (!dict->GetList("log", &log)) { | 43 if (!dict->GetList("log", &log)) { |
| 44 log = new base::ListValue(); | 44 log = new base::ListValue(); |
| 45 if (log) | 45 dict->Set("log", new base::ListValue()); |
|
tommi (sloooow) - chröme
2017/03/02 11:17:46
oops... fix is on the way.
| |
| 46 dict->Set("log", log); | |
| 47 } | 46 } |
| 48 return log; | 47 return log; |
| 49 } | 48 } |
| 50 | 49 |
| 50 // Removes the log entry associated with a given record. | |
| 51 void FreeLogList(base::Value* value) { | |
| 52 DCHECK(value->IsType(base::Value::Type::DICTIONARY)); | |
| 53 auto* dict = static_cast<base::DictionaryValue*>(value); | |
| 54 dict->Remove("log", nullptr); | |
| 55 } | |
| 56 | |
| 51 } // namespace | 57 } // namespace |
| 52 | 58 |
| 53 WebRTCInternals::PendingUpdate::PendingUpdate( | 59 WebRTCInternals::PendingUpdate::PendingUpdate( |
| 54 const char* command, | 60 const char* command, |
| 55 std::unique_ptr<base::Value> value) | 61 std::unique_ptr<base::Value> value) |
| 56 : command_(command), value_(std::move(value)) {} | 62 : command_(command), value_(std::move(value)) {} |
| 57 | 63 |
| 58 WebRTCInternals::PendingUpdate::PendingUpdate(PendingUpdate&& other) | 64 WebRTCInternals::PendingUpdate::PendingUpdate(PendingUpdate&& other) |
| 59 : command_(other.command_), | 65 : command_(other.command_), |
| 60 value_(std::move(other.value_)) {} | 66 value_(std::move(other.value_)) {} |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 } | 121 } |
| 116 | 122 |
| 117 void WebRTCInternals::OnAddPeerConnection(int render_process_id, | 123 void WebRTCInternals::OnAddPeerConnection(int render_process_id, |
| 118 ProcessId pid, | 124 ProcessId pid, |
| 119 int lid, | 125 int lid, |
| 120 const string& url, | 126 const string& url, |
| 121 const string& rtc_configuration, | 127 const string& rtc_configuration, |
| 122 const string& constraints) { | 128 const string& constraints) { |
| 123 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 129 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 124 | 130 |
| 131 // TODO(tommi): Consider changing this design so that webrtc-internals has | |
| 132 // minimal impact if chrome://webrtc-internals isn't open. | |
| 133 | |
| 125 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 134 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 126 dict->SetInteger("rid", render_process_id); | 135 dict->SetInteger("rid", render_process_id); |
| 127 dict->SetInteger("pid", static_cast<int>(pid)); | 136 dict->SetInteger("pid", static_cast<int>(pid)); |
| 128 dict->SetInteger("lid", lid); | 137 dict->SetInteger("lid", lid); |
| 129 dict->SetString("rtcConfiguration", rtc_configuration); | 138 dict->SetString("rtcConfiguration", rtc_configuration); |
| 130 dict->SetString("constraints", constraints); | 139 dict->SetString("constraints", constraints); |
| 131 dict->SetString("url", url); | 140 dict->SetString("url", url); |
| 132 dict->SetBoolean("isOpen", true); | 141 dict->SetBoolean("isOpen", true); |
| 133 | 142 |
| 134 if (observers_.might_have_observers()) | 143 if (observers_.might_have_observers()) |
| 135 SendUpdate("addPeerConnection", dict->CreateDeepCopy()); | 144 SendUpdate("addPeerConnection", dict->CreateDeepCopy()); |
| 136 | 145 |
| 137 peer_connection_data_.Append(std::move(dict)); | 146 peer_connection_data_.Append(std::move(dict)); |
| 138 ++num_open_connections_; | 147 ++num_open_connections_; |
| 139 CreateOrReleasePowerSaveBlocker(); | 148 CreateOrReleasePowerSaveBlocker(); |
| 140 | 149 |
| 141 if (render_process_id_set_.insert(render_process_id).second) { | 150 if (render_process_id_set_.insert(render_process_id).second) { |
| 142 RenderProcessHost* host = RenderProcessHost::FromID(render_process_id); | 151 RenderProcessHost* host = RenderProcessHost::FromID(render_process_id); |
| 143 if (host) | 152 if (host) |
| 144 host->AddObserver(this); | 153 host->AddObserver(this); |
| 145 } | 154 } |
| 146 } | 155 } |
| 147 | 156 |
| 148 void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) { | 157 void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) { |
| 149 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 158 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 150 for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) { | |
| 151 base::DictionaryValue* dict = NULL; | |
| 152 peer_connection_data_.GetDictionary(i, &dict); | |
| 153 | 159 |
| 154 int this_pid = 0; | 160 size_t i; |
| 155 int this_lid = 0; | 161 base::DictionaryValue* dict = FindRecord(pid, lid, &i); |
| 156 dict->GetInteger("pid", &this_pid); | 162 if (!dict) |
| 157 dict->GetInteger("lid", &this_lid); | 163 return; |
| 158 | 164 |
| 159 if (this_pid != static_cast<int>(pid) || this_lid != lid) | 165 MaybeClosePeerConnection(dict); |
| 160 continue; | 166 peer_connection_data_.Remove(i, NULL); |
| 161 | 167 |
| 162 MaybeClosePeerConnection(dict); | 168 if (observers_.might_have_observers()) { |
| 163 peer_connection_data_.Remove(i, NULL); | 169 std::unique_ptr<base::DictionaryValue> id(new base::DictionaryValue()); |
| 164 | 170 id->SetInteger("pid", static_cast<int>(pid)); |
| 165 if (observers_.might_have_observers()) { | 171 id->SetInteger("lid", lid); |
| 166 std::unique_ptr<base::DictionaryValue> id(new base::DictionaryValue()); | 172 SendUpdate("removePeerConnection", std::move(id)); |
| 167 id->SetInteger("pid", static_cast<int>(pid)); | |
| 168 id->SetInteger("lid", lid); | |
| 169 SendUpdate("removePeerConnection", std::move(id)); | |
| 170 } | |
| 171 break; | |
| 172 } | 173 } |
| 173 } | 174 } |
| 174 | 175 |
| 175 void WebRTCInternals::OnUpdatePeerConnection( | 176 void WebRTCInternals::OnUpdatePeerConnection( |
| 176 ProcessId pid, int lid, const string& type, const string& value) { | 177 ProcessId pid, int lid, const string& type, const string& value) { |
| 177 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 178 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 178 | 179 |
| 179 for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) { | 180 base::DictionaryValue* record = FindRecord(pid, lid); |
| 180 base::DictionaryValue* record = NULL; | 181 if (!record) |
| 181 peer_connection_data_.GetDictionary(i, &record); | 182 return; |
| 182 | 183 |
| 183 int this_pid = 0, this_lid = 0; | 184 if (type == "stop") |
| 184 record->GetInteger("pid", &this_pid); | 185 MaybeClosePeerConnection(record); |
| 185 record->GetInteger("lid", &this_lid); | |
| 186 | 186 |
| 187 if (this_pid != static_cast<int>(pid) || this_lid != lid) | 187 // Don't collect entries into the log if there aren't any observers. |
| 188 continue; | 188 if (!observers_.might_have_observers()) |
| 189 return; | |
| 189 | 190 |
| 190 if (type == "stop") { | 191 // Append the update to the end of the log. |
| 191 MaybeClosePeerConnection(record); | 192 base::ListValue* log = EnsureLogList(record); |
| 192 } | 193 std::unique_ptr<base::DictionaryValue> log_entry(new base::DictionaryValue()); |
| 193 | 194 |
| 194 // Append the update to the end of the log. | 195 double epoch_time = base::Time::Now().ToJsTime(); |
| 195 base::ListValue* log = EnsureLogList(record); | 196 string time = base::DoubleToString(epoch_time); |
| 196 if (!log) | 197 log_entry->SetString("time", time); |
| 197 return; | 198 log_entry->SetString("type", type); |
| 199 log_entry->SetString("value", value); | |
| 198 | 200 |
| 199 std::unique_ptr<base::DictionaryValue> log_entry( | 201 std::unique_ptr<base::DictionaryValue> update(new base::DictionaryValue()); |
| 200 new base::DictionaryValue()); | 202 update->SetInteger("pid", static_cast<int>(pid)); |
| 203 update->SetInteger("lid", lid); | |
| 204 update->MergeDictionary(log_entry.get()); | |
| 201 | 205 |
| 202 double epoch_time = base::Time::Now().ToJsTime(); | 206 SendUpdate("updatePeerConnection", std::move(update)); |
| 203 string time = base::DoubleToString(epoch_time); | |
| 204 log_entry->SetString("time", time); | |
| 205 log_entry->SetString("type", type); | |
| 206 log_entry->SetString("value", value); | |
| 207 | 207 |
| 208 if (observers_.might_have_observers()) { | 208 log->Append(std::move(log_entry)); |
| 209 std::unique_ptr<base::DictionaryValue> update( | |
| 210 new base::DictionaryValue()); | |
| 211 update->SetInteger("pid", static_cast<int>(pid)); | |
| 212 update->SetInteger("lid", lid); | |
| 213 update->MergeDictionary(log_entry.get()); | |
| 214 | |
| 215 SendUpdate("updatePeerConnection", std::move(update)); | |
| 216 } | |
| 217 | |
| 218 log->Append(std::move(log_entry)); | |
| 219 | |
| 220 return; | |
| 221 } | |
| 222 } | 209 } |
| 223 | 210 |
| 224 void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid, | 211 void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid, |
| 225 const base::ListValue& value) { | 212 const base::ListValue& value) { |
| 226 if (!observers_.might_have_observers()) | 213 if (!observers_.might_have_observers()) |
| 227 return; | 214 return; |
| 228 | 215 |
| 229 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 216 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 230 dict->SetInteger("pid", static_cast<int>(pid)); | 217 dict->SetInteger("pid", static_cast<int>(pid)); |
| 231 dict->SetInteger("lid", lid); | 218 dict->SetInteger("lid", lid); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 } | 253 } |
| 267 | 254 |
| 268 void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver* observer) { | 255 void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver* observer) { |
| 269 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 256 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 270 observers_.AddObserver(observer); | 257 observers_.AddObserver(observer); |
| 271 } | 258 } |
| 272 | 259 |
| 273 void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver* observer) { | 260 void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver* observer) { |
| 274 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 261 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 275 observers_.RemoveObserver(observer); | 262 observers_.RemoveObserver(observer); |
| 263 if (observers_.might_have_observers()) | |
| 264 return; | |
| 276 | 265 |
| 277 // Disables event log and audio debug recordings if enabled and the last | 266 // Disables event log and audio debug recordings if enabled and the last |
| 278 // webrtc-internals page is going away. | 267 // webrtc-internals page is going away. |
| 279 if (!observers_.might_have_observers()) { | 268 DisableAudioDebugRecordings(); |
| 280 if (audio_debug_recordings_) | 269 DisableEventLogRecordings(); |
| 281 DisableAudioDebugRecordings(); | 270 |
| 282 DisableEventLogRecordings(); | 271 // TODO(tommi): Consider removing all the peer_connection_data_. |
| 283 } | 272 for (auto& dictionary : peer_connection_data_) |
| 273 FreeLogList(dictionary.get()); | |
| 284 } | 274 } |
| 285 | 275 |
| 286 void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) { | 276 void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) { |
| 287 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 277 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 288 if (peer_connection_data_.GetSize() > 0) | 278 if (peer_connection_data_.GetSize() > 0) |
| 289 observer->OnUpdate("updateAllPeerConnections", &peer_connection_data_); | 279 observer->OnUpdate("updateAllPeerConnections", &peer_connection_data_); |
| 290 | 280 |
| 291 for (const auto& request : get_user_media_requests_) { | 281 for (const auto& request : get_user_media_requests_) { |
| 292 observer->OnUpdate("addGetUserMedia", request.get()); | 282 observer->OnUpdate("addGetUserMedia", request.get()); |
| 293 } | 283 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 312 FILE_PATH_LITERAL(""), | 302 FILE_PATH_LITERAL(""), |
| 313 web_contents->GetTopLevelNativeWindow(), | 303 web_contents->GetTopLevelNativeWindow(), |
| 314 NULL); | 304 NULL); |
| 315 #endif | 305 #endif |
| 316 #endif | 306 #endif |
| 317 } | 307 } |
| 318 | 308 |
| 319 void WebRTCInternals::DisableAudioDebugRecordings() { | 309 void WebRTCInternals::DisableAudioDebugRecordings() { |
| 320 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 310 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 321 #if BUILDFLAG(ENABLE_WEBRTC) | 311 #if BUILDFLAG(ENABLE_WEBRTC) |
| 312 if (!audio_debug_recordings_) | |
| 313 return; | |
| 314 | |
| 322 audio_debug_recordings_ = false; | 315 audio_debug_recordings_ = false; |
| 323 | 316 |
| 324 // Tear down the dialog since the user has unchecked the audio debug | 317 // Tear down the dialog since the user has unchecked the audio debug |
| 325 // recordings box. | 318 // recordings box. |
| 326 select_file_dialog_ = NULL; | 319 select_file_dialog_ = NULL; |
| 327 | 320 |
| 328 for (RenderProcessHost::iterator i( | 321 for (RenderProcessHost::iterator i( |
| 329 content::RenderProcessHost::AllHostsIterator()); | 322 content::RenderProcessHost::AllHostsIterator()); |
| 330 !i.IsAtEnd(); i.Advance()) { | 323 !i.IsAtEnd(); i.Advance()) { |
| 331 i.GetCurrentValue()->DisableAudioDebugRecordings(); | 324 i.GetCurrentValue()->DisableAudioDebugRecordings(); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 549 void WebRTCInternals::ProcessPendingUpdates() { | 542 void WebRTCInternals::ProcessPendingUpdates() { |
| 550 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 543 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 551 while (!pending_updates_.empty()) { | 544 while (!pending_updates_.empty()) { |
| 552 const auto& update = pending_updates_.front(); | 545 const auto& update = pending_updates_.front(); |
| 553 for (auto& observer : observers_) | 546 for (auto& observer : observers_) |
| 554 observer.OnUpdate(update.command(), update.value()); | 547 observer.OnUpdate(update.command(), update.value()); |
| 555 pending_updates_.pop(); | 548 pending_updates_.pop(); |
| 556 } | 549 } |
| 557 } | 550 } |
| 558 | 551 |
| 552 base::DictionaryValue* WebRTCInternals::FindRecord( | |
| 553 ProcessId pid, | |
| 554 int lid, | |
| 555 size_t* index /*= nullptr*/) { | |
| 556 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 557 | |
| 558 base::DictionaryValue* record = nullptr; | |
| 559 for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) { | |
| 560 peer_connection_data_.GetDictionary(i, &record); | |
| 561 | |
| 562 int this_pid = 0, this_lid = 0; | |
| 563 record->GetInteger("pid", &this_pid); | |
| 564 record->GetInteger("lid", &this_lid); | |
| 565 | |
| 566 if (this_pid == static_cast<int>(pid) && this_lid != lid) { | |
| 567 if (index) | |
| 568 *index = i; | |
| 569 return record; | |
| 570 } | |
| 571 } | |
| 572 return nullptr; | |
| 573 } | |
| 559 } // namespace content | 574 } // namespace content |
| OLD | NEW |