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 17 matching lines...) Expand all Loading... | |
| 28 #define IntToStringType base::IntToString | 28 #define IntToStringType base::IntToString |
| 29 #endif | 29 #endif |
| 30 | 30 |
| 31 using base::ProcessId; | 31 using base::ProcessId; |
| 32 using std::string; | 32 using std::string; |
| 33 | 33 |
| 34 namespace content { | 34 namespace content { |
| 35 | 35 |
| 36 namespace { | 36 namespace { |
| 37 | 37 |
| 38 static base::LazyInstance<WebRTCInternals>::Leaky g_webrtc_internals = | 38 base::LazyInstance<WebRTCInternals>::Leaky g_webrtc_internals = |
| 39 LAZY_INSTANCE_INITIALIZER; | 39 LAZY_INSTANCE_INITIALIZER; |
| 40 | 40 |
| 41 // Makes sure that |dict| has a ListValue under path "log". | 41 // Makes sure that |dict| has a ListValue under path "log". |
| 42 static base::ListValue* EnsureLogList(base::DictionaryValue* dict) { | 42 base::ListValue* EnsureLogList(base::DictionaryValue* dict) { |
| 43 base::ListValue* log = NULL; | 43 base::ListValue* log = NULL; |
| 44 if (!dict->GetList("log", &log)) { | 44 if (!dict->GetList("log", &log)) { |
| 45 log = new base::ListValue(); | 45 log = new base::ListValue(); |
| 46 if (log) | 46 dict->Set("log", log); |
| 47 dict->Set("log", log); | |
| 48 } | 47 } |
| 49 return log; | 48 return log; |
| 50 } | 49 } |
| 51 | 50 |
| 51 // Removes the log entry associated with a given record. | |
| 52 void FreeLogList(base::Value* value) { | |
| 53 DCHECK(value->IsType(base::Value::Type::DICTIONARY)); | |
| 54 auto* dict = static_cast<base::DictionaryValue*>(value); | |
|
Henrik Grunell
2017/03/03 12:40:09
Not being particularly familiar with base::Value,
tommi (sloooow) - chröme
2017/03/03 14:15:14
Yes, it's a polymorphic design with an enum that p
Henrik Grunell
2017/03/06 11:49:24
Acknowledged.
| |
| 55 dict->Remove("log", nullptr); | |
| 56 } | |
| 57 | |
| 52 } // namespace | 58 } // namespace |
| 53 | 59 |
| 54 WebRTCInternals::PendingUpdate::PendingUpdate( | 60 WebRTCInternals::PendingUpdate::PendingUpdate( |
| 55 const char* command, | 61 const char* command, |
| 56 std::unique_ptr<base::Value> value) | 62 std::unique_ptr<base::Value> value) |
| 57 : command_(command), value_(std::move(value)) {} | 63 : command_(command), value_(std::move(value)) {} |
| 58 | 64 |
| 59 WebRTCInternals::PendingUpdate::PendingUpdate(PendingUpdate&& other) | 65 WebRTCInternals::PendingUpdate::PendingUpdate(PendingUpdate&& other) |
| 60 : command_(other.command_), | 66 : command_(other.command_), |
| 61 value_(std::move(other.value_)) {} | 67 value_(std::move(other.value_)) {} |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 116 } | 122 } |
| 117 | 123 |
| 118 void WebRTCInternals::OnAddPeerConnection(int render_process_id, | 124 void WebRTCInternals::OnAddPeerConnection(int render_process_id, |
| 119 ProcessId pid, | 125 ProcessId pid, |
| 120 int lid, | 126 int lid, |
| 121 const string& url, | 127 const string& url, |
| 122 const string& rtc_configuration, | 128 const string& rtc_configuration, |
| 123 const string& constraints) { | 129 const string& constraints) { |
| 124 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 130 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 125 | 131 |
| 132 // TODO(tommi): Consider changing this design so that webrtc-internals has | |
| 133 // minimal impact if chrome://webrtc-internals isn't open. | |
| 134 | |
| 126 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 135 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 127 dict->SetInteger("rid", render_process_id); | 136 dict->SetInteger("rid", render_process_id); |
| 128 dict->SetInteger("pid", static_cast<int>(pid)); | 137 dict->SetInteger("pid", static_cast<int>(pid)); |
| 129 dict->SetInteger("lid", lid); | 138 dict->SetInteger("lid", lid); |
| 130 dict->SetString("rtcConfiguration", rtc_configuration); | 139 dict->SetString("rtcConfiguration", rtc_configuration); |
| 131 dict->SetString("constraints", constraints); | 140 dict->SetString("constraints", constraints); |
| 132 dict->SetString("url", url); | 141 dict->SetString("url", url); |
| 133 dict->SetBoolean("isOpen", true); | 142 dict->SetBoolean("isOpen", true); |
| 134 | 143 |
| 135 if (observers_.might_have_observers()) | 144 if (observers_.might_have_observers()) |
| 136 SendUpdate("addPeerConnection", dict->CreateDeepCopy()); | 145 SendUpdate("addPeerConnection", dict->CreateDeepCopy()); |
| 137 | 146 |
| 138 peer_connection_data_.Append(std::move(dict)); | 147 peer_connection_data_.Append(std::move(dict)); |
| 139 ++num_open_connections_; | 148 ++num_open_connections_; |
| 140 CreateOrReleasePowerSaveBlocker(); | 149 CreateOrReleasePowerSaveBlocker(); |
| 141 | 150 |
| 142 if (render_process_id_set_.insert(render_process_id).second) { | 151 if (render_process_id_set_.insert(render_process_id).second) { |
| 143 RenderProcessHost* host = RenderProcessHost::FromID(render_process_id); | 152 RenderProcessHost* host = RenderProcessHost::FromID(render_process_id); |
| 144 if (host) | 153 if (host) |
| 145 host->AddObserver(this); | 154 host->AddObserver(this); |
| 146 } | 155 } |
| 147 } | 156 } |
| 148 | 157 |
| 149 void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) { | 158 void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) { |
|
Henrik Grunell
2017/03/03 12:40:09
Great that you cleaned up the awkward code in this
tommi (sloooow) - chröme
2017/03/03 14:15:14
:D
| |
| 150 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 159 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 151 for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) { | |
| 152 base::DictionaryValue* dict = NULL; | |
| 153 peer_connection_data_.GetDictionary(i, &dict); | |
| 154 | 160 |
| 155 int this_pid = 0; | 161 size_t i; |
|
Henrik Grunell
2017/03/03 12:40:09
Nit: perhaps a more descriptive variable name?
tommi (sloooow) - chröme
2017/03/03 14:15:14
Done... although I only changed it to 'index'. |i
| |
| 156 int this_lid = 0; | 162 base::DictionaryValue* dict = FindRecord(pid, lid, &i); |
| 157 dict->GetInteger("pid", &this_pid); | 163 if (dict) { |
| 158 dict->GetInteger("lid", &this_lid); | |
| 159 | |
| 160 if (this_pid != static_cast<int>(pid) || this_lid != lid) | |
| 161 continue; | |
| 162 | |
| 163 MaybeClosePeerConnection(dict); | 164 MaybeClosePeerConnection(dict); |
| 164 peer_connection_data_.Remove(i, NULL); | 165 peer_connection_data_.Remove(i, NULL); |
| 166 } | |
| 165 | 167 |
| 166 if (observers_.might_have_observers()) { | 168 if (observers_.might_have_observers()) { |
| 167 std::unique_ptr<base::DictionaryValue> id(new base::DictionaryValue()); | 169 std::unique_ptr<base::DictionaryValue> id(new base::DictionaryValue()); |
| 168 id->SetInteger("pid", static_cast<int>(pid)); | 170 id->SetInteger("pid", static_cast<int>(pid)); |
| 169 id->SetInteger("lid", lid); | 171 id->SetInteger("lid", lid); |
| 170 SendUpdate("removePeerConnection", std::move(id)); | 172 SendUpdate("removePeerConnection", std::move(id)); |
| 171 } | |
| 172 break; | |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 | 175 |
| 176 void WebRTCInternals::OnUpdatePeerConnection( | 176 void WebRTCInternals::OnUpdatePeerConnection( |
| 177 ProcessId pid, int lid, const string& type, const string& value) { | 177 ProcessId pid, int lid, const string& type, const string& value) { |
| 178 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 178 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 179 | 179 |
| 180 for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) { | 180 base::DictionaryValue* record = FindRecord(pid, lid); |
| 181 base::DictionaryValue* record = NULL; | 181 if (record && type == "stop") |
| 182 peer_connection_data_.GetDictionary(i, &record); | 182 MaybeClosePeerConnection(record); |
| 183 | 183 |
| 184 int this_pid = 0, this_lid = 0; | 184 // Don't update entries if there aren't any observers. |
| 185 record->GetInteger("pid", &this_pid); | 185 if (!observers_.might_have_observers()) |
| 186 record->GetInteger("lid", &this_lid); | 186 return; |
| 187 | 187 |
| 188 if (this_pid != static_cast<int>(pid) || this_lid != lid) | 188 std::unique_ptr<base::DictionaryValue> log_entry(new base::DictionaryValue()); |
| 189 continue; | |
| 190 | 189 |
| 191 if (type == "stop") { | 190 double epoch_time = base::Time::Now().ToJsTime(); |
| 192 MaybeClosePeerConnection(record); | 191 string time = base::DoubleToString(epoch_time); |
| 193 } | 192 log_entry->SetString("time", time); |
| 193 log_entry->SetString("type", type); | |
| 194 log_entry->SetString("value", value); | |
| 194 | 195 |
| 196 std::unique_ptr<base::DictionaryValue> update(new base::DictionaryValue()); | |
| 197 update->SetInteger("pid", static_cast<int>(pid)); | |
| 198 update->SetInteger("lid", lid); | |
| 199 update->MergeDictionary(log_entry.get()); | |
| 200 | |
| 201 SendUpdate("updatePeerConnection", std::move(update)); | |
|
Henrik Grunell
2017/03/03 12:40:09
In the previous code, this would not be done if no
tommi (sloooow) - chröme
2017/03/03 14:15:14
Not intentional. Changed the behavior back now.
| |
| 202 | |
| 203 if (record) { | |
| 195 // Append the update to the end of the log. | 204 // Append the update to the end of the log. |
| 196 base::ListValue* log = EnsureLogList(record); | 205 EnsureLogList(record)->Append(std::move(log_entry)); |
| 197 if (!log) | |
| 198 return; | |
| 199 | |
| 200 std::unique_ptr<base::DictionaryValue> log_entry( | |
| 201 new base::DictionaryValue()); | |
| 202 | |
| 203 double epoch_time = base::Time::Now().ToJsTime(); | |
| 204 string time = base::DoubleToString(epoch_time); | |
| 205 log_entry->SetString("time", time); | |
| 206 log_entry->SetString("type", type); | |
| 207 log_entry->SetString("value", value); | |
| 208 | |
| 209 if (observers_.might_have_observers()) { | |
| 210 std::unique_ptr<base::DictionaryValue> update( | |
| 211 new base::DictionaryValue()); | |
| 212 update->SetInteger("pid", static_cast<int>(pid)); | |
| 213 update->SetInteger("lid", lid); | |
| 214 update->MergeDictionary(log_entry.get()); | |
| 215 | |
| 216 SendUpdate("updatePeerConnection", std::move(update)); | |
| 217 } | |
| 218 | |
| 219 log->Append(std::move(log_entry)); | |
| 220 | |
| 221 return; | |
| 222 } | 206 } |
| 223 } | 207 } |
| 224 | 208 |
| 225 void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid, | 209 void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid, |
| 226 const base::ListValue& value) { | 210 const base::ListValue& value) { |
| 227 if (!observers_.might_have_observers()) | 211 if (!observers_.might_have_observers()) |
| 228 return; | 212 return; |
| 229 | 213 |
| 230 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 214 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 231 dict->SetInteger("pid", static_cast<int>(pid)); | 215 dict->SetInteger("pid", static_cast<int>(pid)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 } | 251 } |
| 268 | 252 |
| 269 void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver* observer) { | 253 void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver* observer) { |
| 270 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 254 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 271 observers_.AddObserver(observer); | 255 observers_.AddObserver(observer); |
| 272 } | 256 } |
| 273 | 257 |
| 274 void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver* observer) { | 258 void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver* observer) { |
| 275 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 259 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 276 observers_.RemoveObserver(observer); | 260 observers_.RemoveObserver(observer); |
| 261 if (observers_.might_have_observers()) | |
| 262 return; | |
| 277 | 263 |
| 278 // Disables event log and audio debug recordings if enabled and the last | 264 // Disables event log and audio debug recordings if enabled and the last |
| 279 // webrtc-internals page is going away. | 265 // webrtc-internals page is going away. |
| 280 if (!observers_.might_have_observers()) { | 266 DisableAudioDebugRecordings(); |
| 281 if (audio_debug_recordings_) | 267 DisableEventLogRecordings(); |
| 282 DisableAudioDebugRecordings(); | 268 |
| 283 DisableEventLogRecordings(); | 269 // TODO(tommi): Consider removing all the peer_connection_data_. |
| 284 } | 270 for (auto& dictionary : peer_connection_data_) |
| 271 FreeLogList(dictionary.get()); | |
|
Henrik Grunell
2017/03/03 12:40:09
I don't know the design of WebRTC internals, so to
tommi (sloooow) - chröme
2017/03/03 14:15:14
We do loose data but the thinking is that when chr
Henrik Grunell
2017/03/06 11:49:24
OK, if that's the intention that's fine then.
| |
| 285 } | 272 } |
| 286 | 273 |
| 287 void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) { | 274 void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) { |
| 288 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 275 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 289 if (peer_connection_data_.GetSize() > 0) | 276 if (peer_connection_data_.GetSize() > 0) |
| 290 observer->OnUpdate("updateAllPeerConnections", &peer_connection_data_); | 277 observer->OnUpdate("updateAllPeerConnections", &peer_connection_data_); |
| 291 | 278 |
| 292 for (const auto& request : get_user_media_requests_) { | 279 for (const auto& request : get_user_media_requests_) { |
| 293 observer->OnUpdate("addGetUserMedia", request.get()); | 280 observer->OnUpdate("addGetUserMedia", request.get()); |
| 294 } | 281 } |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 313 FILE_PATH_LITERAL(""), | 300 FILE_PATH_LITERAL(""), |
| 314 web_contents->GetTopLevelNativeWindow(), | 301 web_contents->GetTopLevelNativeWindow(), |
| 315 NULL); | 302 NULL); |
| 316 #endif | 303 #endif |
| 317 #endif | 304 #endif |
| 318 } | 305 } |
| 319 | 306 |
| 320 void WebRTCInternals::DisableAudioDebugRecordings() { | 307 void WebRTCInternals::DisableAudioDebugRecordings() { |
| 321 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 308 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 322 #if BUILDFLAG(ENABLE_WEBRTC) | 309 #if BUILDFLAG(ENABLE_WEBRTC) |
| 310 if (!audio_debug_recordings_) | |
| 311 return; | |
| 312 | |
| 323 audio_debug_recordings_ = false; | 313 audio_debug_recordings_ = false; |
| 324 | 314 |
| 325 // Tear down the dialog since the user has unchecked the audio debug | 315 // Tear down the dialog since the user has unchecked the audio debug |
| 326 // recordings box. | 316 // recordings box. |
| 327 select_file_dialog_ = nullptr; | 317 select_file_dialog_ = nullptr; |
| 328 | 318 |
| 329 for (RenderProcessHost::iterator i( | 319 for (RenderProcessHost::iterator i( |
| 330 content::RenderProcessHost::AllHostsIterator()); | 320 content::RenderProcessHost::AllHostsIterator()); |
| 331 !i.IsAtEnd(); i.Advance()) { | 321 !i.IsAtEnd(); i.Advance()) { |
| 332 i.GetCurrentValue()->DisableAudioDebugRecordings(); | 322 i.GetCurrentValue()->DisableAudioDebugRecordings(); |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 void WebRTCInternals::ProcessPendingUpdates() { | 560 void WebRTCInternals::ProcessPendingUpdates() { |
| 571 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 561 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 572 while (!pending_updates_.empty()) { | 562 while (!pending_updates_.empty()) { |
| 573 const auto& update = pending_updates_.front(); | 563 const auto& update = pending_updates_.front(); |
| 574 for (auto& observer : observers_) | 564 for (auto& observer : observers_) |
| 575 observer.OnUpdate(update.command(), update.value()); | 565 observer.OnUpdate(update.command(), update.value()); |
| 576 pending_updates_.pop(); | 566 pending_updates_.pop(); |
| 577 } | 567 } |
| 578 } | 568 } |
| 579 | 569 |
| 570 base::DictionaryValue* WebRTCInternals::FindRecord( | |
| 571 ProcessId pid, | |
| 572 int lid, | |
| 573 size_t* index /*= nullptr*/) { | |
| 574 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 575 | |
| 576 base::DictionaryValue* record = nullptr; | |
| 577 for (size_t i = 0; i < peer_connection_data_.GetSize(); ++i) { | |
| 578 peer_connection_data_.GetDictionary(i, &record); | |
| 579 | |
| 580 int this_pid = 0, this_lid = 0; | |
| 581 record->GetInteger("pid", &this_pid); | |
| 582 record->GetInteger("lid", &this_lid); | |
| 583 | |
| 584 if (this_pid == static_cast<int>(pid) && this_lid == lid) { | |
| 585 if (index) | |
| 586 *index = i; | |
| 587 return record; | |
| 588 } | |
| 589 } | |
| 590 return nullptr; | |
| 591 } | |
| 580 } // namespace content | 592 } // namespace content |
| OLD | NEW |