Bug 906990: Part 10. Webidl and implementation for WebrtcGlobal. Encompasses things like global stats and logging. r=jib,bz

This commit is contained in:
Byron Campen [:bwc] 2013-11-25 11:01:03 -08:00
Родитель aecbe64228
Коммит aebc089f65
9 изменённых файлов: 209 добавлений и 13 удалений

Просмотреть файл

@ -18,4 +18,5 @@
# Modifying this file will now automatically clobber the buildbot machines \o/
#
Bug 942207 - apparently need clobber to avoid bustage
WebIDL dictionary modification requires clobber on Windows (bug 928195), part of
bug 906990.

Просмотреть файл

@ -10,6 +10,7 @@ Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
const PC_CONTRACT = "@mozilla.org/dom/peerconnection;1";
const WEBRTC_GLOBAL_CONTRACT = "@mozilla.org/dom/webrtcglobalinformation1";
const PC_OBS_CONTRACT = "@mozilla.org/dom/peerconnectionobserver;1";
const PC_ICE_CONTRACT = "@mozilla.org/dom/rtcicecandidate;1";
const PC_SESSION_CONTRACT = "@mozilla.org/dom/rtcsessiondescription;1";
@ -17,7 +18,8 @@ const PC_MANAGER_CONTRACT = "@mozilla.org/dom/peerconnectionmanager;1";
const PC_STATS_CONTRACT = "@mozilla.org/dom/rtcstatsreport;1";
const PC_CID = Components.ID("{00e0e20d-1494-4776-8e0e-0f0acbea3c79}");
const PC_OBS_CID = Components.ID("{1d44a18e-4545-4ff3-863d-6dbd6234a583}");
const WEBRTC_GLOBAL_CID = Components.ID("{f6063d11-f467-49ad-9765-e7923050dc08}");
const PC_OBS_CID = Components.ID("{d1748d4c-7f6a-4dc5-add6-d55b7678537e}");
const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
const PC_MANAGER_CID = Components.ID("{7293e901-2be3-4c02-b4bd-cbef6fc24f78}");
@ -63,6 +65,10 @@ GlobalPCList.prototype = {
}
this._list[winID] = this._list[winID].filter(
function (e,i,a) { return e.get() !== null; });
if (this._list[winID].length === 0) {
delete this._list[winID];
}
},
hasActivePeerConnection: function(winID) {
@ -111,9 +117,60 @@ GlobalPCList.prototype = {
}
}
},
getStatsForEachPC: function(callback, errorCallback) {
for (let winId in this._list) {
if (this._list.hasOwnProperty(winId)) {
this.removeNullRefs(winId);
if (this._list[winId]) {
this._list[winId].forEach(function(pcref) {
pcref.get().getStatsInternal(null, callback, errorCallback);
});
}
}
}
},
getLoggingFromFirstPC: function(pattern, callback, errorCallback) {
for (let winId in this._list) {
this.removeNullRefs(winId);
if (this._list[winId]) {
// We expect removeNullRefs to not leave us with an empty array here
let pcref = this._list[winId][0];
pcref.get().getLogging(pattern, callback, errorCallback);
return;
}
}
},
};
let _globalPCList = new GlobalPCList();
function WebrtcGlobalInformation() {
}
WebrtcGlobalInformation.prototype = {
classDescription: "WebrtcGlobalInformation",
classID: WEBRTC_GLOBAL_CID,
contractID: WEBRTC_GLOBAL_CONTRACT,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
getAllStats: function(successCallback, failureCallback) {
if (_globalPCList) {
_globalPCList.getStatsForEachPC(successCallback, failureCallback);
} else {
failureCallback("No global PeerConnection list");
}
},
getCandPairLogs: function(candPairId, callback, errorCallback) {
let pattern = 'CAND-PAIR(' + candPairId + ')';
if (_globalPCList) {
_globalPCList.getLoggingFromFirstPC(pattern, callback, errorCallback);
} else {
errorCallback("No global PeerConnection list");
}
},
};
function RTCIceCandidate() {
this.candidate = this.sdpMid = this.sdpMLineIndex = null;
}
@ -151,9 +208,10 @@ RTCSessionDescription.prototype = {
}
};
function RTCStatsReport(win, report) {
function RTCStatsReport(win, report, pcid) {
this._win = win;
this.report = report;
this.mozPcid = pcid;
}
RTCStatsReport.prototype = {
classDescription: "RTCStatsReport",
@ -204,6 +262,8 @@ function RTCPeerConnection() {
this._onCreateAnswerFailure = null;
this._onGetStatsSuccess = null;
this._onGetStatsFailure = null;
this._onGetLoggingSuccess = null;
this._onGetLoggingFailure = null;
this._pendingType = null;
this._localType = null;
@ -736,6 +796,21 @@ RTCPeerConnection.prototype = {
this._getPC().getStats(selector, internal);
},
getLogging: function(pattern, onSuccess, onError) {
this._queueOrRun({
func: this._getLogging,
args: [pattern, onSuccess, onError],
wait: true
});
},
_getLogging: function(pattern, onSuccess, onError) {
this._onGetLoggingSuccess = onSuccess;
this._onGetLoggingFailure = onError;
this._getPC().getLogging(pattern);
},
createDataChannel: function(label, dict) {
this._checkClosed();
if (dict == undefined) {
@ -1086,7 +1161,8 @@ PeerConnectionObserver.prototype = {
this.callCB(this._dompc._onGetStatsSuccess,
this._dompc._win.RTCStatsReport._create(this._dompc._win,
new RTCStatsReport(this._dompc._win,
report)));
report,
dict.pcid)));
this._dompc._executeNext();
},
@ -1095,6 +1171,16 @@ PeerConnectionObserver.prototype = {
this._dompc._executeNext();
},
onGetLoggingSuccess: function(logs) {
this.callCB(this._dompc._onGetLoggingSuccess, logs);
this._dompc._executeNext();
},
onGetLoggingError: function(code, message) {
this.callCB(this._dompc._onGetLoggingFailure, new RTCError(code, message));
this._dompc._executeNext();
},
onAddStream: function(stream) {
this.dispatchEvent(new this._dompc._win.MediaStreamEvent("addstream",
{ stream: stream }));
@ -1129,6 +1215,11 @@ PeerConnectionObserver.prototype = {
};
this.NSGetFactory = XPCOMUtils.generateNSGetFactory(
[GlobalPCList, RTCIceCandidate, RTCSessionDescription, RTCPeerConnection,
RTCStatsReport, PeerConnectionObserver]
[GlobalPCList,
RTCIceCandidate,
RTCSessionDescription,
RTCPeerConnection,
RTCStatsReport,
PeerConnectionObserver,
WebrtcGlobalInformation]
);

Просмотреть файл

@ -1,12 +1,14 @@
component {00e0e20d-1494-4776-8e0e-0f0acbea3c79} PeerConnection.js
component {1d44a18e-4545-4ff3-863d-6dbd6234a583} PeerConnection.js
component {f6063d11-f467-49ad-9765-e7923050dc08} PeerConnection.js
component {d1748d4c-7f6a-4dc5-add6-d55b7678537e} PeerConnection.js
component {02b9970c-433d-4cc2-923d-f7028ac66073} PeerConnection.js
component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
component {7293e901-2be3-4c02-b4bd-cbef6fc24f78} PeerConnection.js
component {7fe6e18b-0da3-4056-bf3b-440ef3809e06} PeerConnection.js
contract @mozilla.org/dom/peerconnection;1 {00e0e20d-1494-4776-8e0e-0f0acbea3c79}
contract @mozilla.org/dom/peerconnectionobserver;1 {1d44a18e-4545-4ff3-863d-6dbd6234a583}
contract @mozilla.org/dom/webrtcglobalinformation;1 {f6063d11-f467-49ad-9765-e7923050dc08}
contract @mozilla.org/dom/peerconnectionobserver;1 {d1748d4c-7f6a-4dc5-add6-d55b7678537e}
contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac66073}
contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067bbf508a7}
contract @mozilla.org/dom/peerconnectionmanager;1 {7293e901-2be3-4c02-b4bd-cbef6fc24f78}

Просмотреть файл

@ -33,10 +33,17 @@ interface PeerConnectionImpl {
[Throws]
void setRemoteDescription(long action, DOMString sdp);
/* Stats call */
/* Stats call, calls either |onGetStatsSuccess| or |onGetStatsError| on our
observer. (see the |PeerConnectionObserver| interface) */
[Throws]
void getStats(MediaStreamTrack? selector, boolean internalStats);
/* Scrapes the RLogRingbuffer, and calls either |onGetLoggingSuccess|
or |onGetLoggingError| on our observer.
(see the |PeerConnectionObserver| interface) */
[Throws]
void getLogging(DOMString pattern);
/* Adds the stream created by GetUserMedia */
[Throws]
void addStream(MediaStream stream);

Просмотреть файл

@ -28,6 +28,10 @@ interface PeerConnectionObserver
void onGetStatsSuccess(optional RTCStatsReportInternal report);
void onGetStatsError(unsigned long name, DOMString message);
/* Logging callbacks */
void onGetLoggingSuccess(sequence<DOMString> logs);
void onGetLoggingError(unsigned long name, DOMString message);
/* Data channel callbacks */
void notifyDataChannel(DataChannel channel);
void notifyConnection();

Просмотреть файл

@ -137,3 +137,19 @@ interface mozRTCPeerConnection : EventTarget {
attribute EventHandler onconnection;
attribute EventHandler onclosedconnection;
};
callback RTCLogCallback = void (sequence<DOMString> logMessages);
[JSImplementation="@mozilla.org/dom/webrtcglobalinformation;1",
ChromeOnly,
Constructor ()]
interface WebrtcGlobalInformation {
void getAllStats(RTCStatsCallback callback,
RTCPeerConnectionErrorCallback errorCallback);
void getCandPairLogs(DOMString candPairId,
RTCLogCallback callback,
RTCPeerConnectionErrorCallback errorCallback);
};

Просмотреть файл

@ -124,6 +124,7 @@ callback RTCStatsReportCallback = void (RTCStatsReport obj);
// to be received from c++
dictionary RTCStatsReportInternal {
DOMString pcid;
sequence<RTCRTPStreamStats> rtpStreamStats;
sequence<RTCInboundRTPStreamStats> inboundRTPStreamStats;
sequence<RTCOutboundRTPStreamStats> outboundRTPStreamStats;
@ -141,6 +142,8 @@ dictionary RTCStatsReportInternal {
// MapClass(DOMString, object)
JSImplementation="@mozilla.org/dom/rtcstatsreport;1"]
interface RTCStatsReport {
[ChromeOnly]
readonly attribute DOMString mozPcid;
void forEach(RTCStatsReportCallback callbackFn, optional any thisArg);
object get(DOMString key);
boolean has(DOMString key);

Просмотреть файл

@ -4,6 +4,7 @@
#include <cstdlib>
#include <cerrno>
#include <deque>
#include "base/histogram.h"
#include "vcm.h"
@ -64,6 +65,7 @@
#include "MediaStreamTrack.h"
#include "nsIScriptGlobalObject.h"
#include "DOMMediaStream.h"
#include "rlogringbuffer.h"
#endif
#ifndef USE_FAKE_MEDIA_STREAMS
@ -1200,6 +1202,23 @@ PeerConnectionImpl::GetStats(MediaStreamTrack *aSelector,
return NS_OK;
}
NS_IMETHODIMP
PeerConnectionImpl::GetLogging(const nsAString& aPattern) {
PC_AUTO_ENTER_API_CALL(true);
#ifdef MOZILLA_INTERNAL_API
std::string pattern(NS_ConvertUTF16toUTF8(aPattern).get());
nsRefPtr<PeerConnectionImpl> pc(this);
RUN_ON_THREAD(mSTSThread,
WrapRunnable(pc,
&PeerConnectionImpl::GetLogging_s,
pattern),
NS_DISPATCH_NORMAL);
#endif
return NS_OK;
}
NS_IMETHODIMP
PeerConnectionImpl::AddIceCandidate(const char* aCandidate, const char* aMid, unsigned short aLevel) {
PC_AUTO_ENTER_API_CALL(true);
@ -1704,6 +1723,8 @@ void PeerConnectionImpl::GetStats_s(
if (!report) {
result = NS_ERROR_FAILURE;
}
report->mPcid.Construct(NS_ConvertASCIItoUTF16(mHandle.c_str()));
if (mMedia) {
RefPtr<NrIceMediaStream> mediaStream(
mMedia->ice_media_stream(trackId));
@ -1715,10 +1736,8 @@ void PeerConnectionImpl::GetStats_s(
NS_ConvertASCIItoUTF16 componentId(mediaStream->name().c_str());
for (auto p = candPairs.begin(); p != candPairs.end(); ++p) {
NS_ConvertASCIItoUTF16 codeword(p->codeword.c_str());
const nsString localCodeword(
NS_ConvertASCIItoUTF16("local_") + codeword);
const nsString remoteCodeword(
NS_ConvertASCIItoUTF16("remote_") + codeword);
NS_ConvertASCIItoUTF16 localCodeword(p->local.codeword.c_str());
NS_ConvertASCIItoUTF16 remoteCodeword(p->remote.codeword.c_str());
// Only expose candidate-pair statistics to chrome, until we've thought
// through the implications of exposing it to content.
@ -1798,6 +1817,45 @@ void PeerConnectionImpl::OnStatsReport_m(
}
}
}
void PeerConnectionImpl::GetLogging_s(const std::string& pattern) {
RLogRingBuffer* logs = RLogRingBuffer::GetInstance();
std::deque<std::string> result;
logs->Filter(pattern, 0, &result);
nsRefPtr<PeerConnectionImpl> pc(this);
RUN_ON_THREAD(mThread,
WrapRunnable(pc,
&PeerConnectionImpl::OnGetLogging_m,
pattern,
result),
NS_DISPATCH_NORMAL);
}
void PeerConnectionImpl::OnGetLogging_m(const std::string& pattern,
const std::deque<std::string>& logging) {
nsRefPtr<PeerConnectionObserver> pco = do_QueryObjectReferent(mPCObserver);
if (!pco) {
return;
}
JSErrorResult rv;
if (!logging.empty()) {
Sequence<nsString> nsLogs;
for (auto l = logging.begin(); l != logging.end(); ++l) {
nsLogs.AppendElement(ObString(l->c_str()));
}
pco->OnGetLoggingSuccess(nsLogs, rv);
} else {
pco->OnGetLoggingError(kInternalError,
ObString(("No logging matching pattern " + pattern).c_str()), rv);
}
if (rv.Failed()) {
CSFLogError(logTag, "Error firing stats observer callback");
}
}
#endif
void

Просмотреть файл

@ -5,6 +5,7 @@
#ifndef _PEER_CONNECTION_IMPL_H_
#define _PEER_CONNECTION_IMPL_H_
#include <deque>
#include <string>
#include <vector>
#include <map>
@ -307,6 +308,12 @@ public:
rv = GetStats(aSelector, internalStats);
}
NS_IMETHODIMP_TO_ERRORRESULT(GetLogging, ErrorResult &rv,
const nsAString& pattern)
{
rv = GetLogging(pattern);
}
NS_IMETHODIMP AddIceCandidate(const char* aCandidate, const char* aMid,
unsigned short aLevel);
void AddIceCandidate(const nsAString& aCandidate, const nsAString& aMid,
@ -494,6 +501,13 @@ private:
void OnStatsReport_m(uint32_t trackId,
nsresult result,
nsAutoPtr<mozilla::dom::RTCStatsReportInternal> report);
// Fetches logs matching pattern from RLogRingBuffer. Must be run on STS.
void GetLogging_s(const std::string& pattern);
// Sends logging to JS. Must run on main thread.
void OnGetLogging_m(const std::string& pattern,
const std::deque<std::string>& logging);
#endif
// Timecard used to measure processing time. This should be the first class