mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to b2g-inbound
This commit is contained in:
commit
a34e4464aa
@ -317,10 +317,6 @@ def is_module_header(enclosing_inclname, header_inclname):
|
|||||||
if m is not None and module.endswith('/' + m.group(1)):
|
if m is not None and module.endswith('/' + m.group(1)):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# A weird public header case.
|
|
||||||
if module == 'jsmemorymetrics' and header_inclname == 'js/MemoryMetrics.h':
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,6 +216,7 @@
|
|||||||
#include "mozilla/dom/BrowserElementDictionariesBinding.h"
|
#include "mozilla/dom/BrowserElementDictionariesBinding.h"
|
||||||
#include "mozilla/dom/FunctionBinding.h"
|
#include "mozilla/dom/FunctionBinding.h"
|
||||||
#include "mozilla/dom/WindowBinding.h"
|
#include "mozilla/dom/WindowBinding.h"
|
||||||
|
#include "mozilla/dom/TabChild.h"
|
||||||
|
|
||||||
#ifdef MOZ_WEBSPEECH
|
#ifdef MOZ_WEBSPEECH
|
||||||
#include "mozilla/dom/SpeechSynthesis.h"
|
#include "mozilla/dom/SpeechSynthesis.h"
|
||||||
@ -5713,6 +5714,9 @@ nsGlobalWindow::Focus()
|
|||||||
return fm->SetFocus(frameElement, flags);
|
return fm->SetFocus(frameElement, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (TabChild *child = TabChild::GetFrom(this)) {
|
||||||
|
child->SendRequestFocus(canFocus);
|
||||||
|
}
|
||||||
else if (canFocus) {
|
else if (canFocus) {
|
||||||
// if there is no parent, this must be a toplevel window, so raise the
|
// if there is no parent, this must be a toplevel window, so raise the
|
||||||
// window if canFocus is true
|
// window if canFocus is true
|
||||||
|
@ -36,7 +36,7 @@ def generate_binding_files(config, outputprefix, srcprefix, webidlfile,
|
|||||||
# too much. See the comment explaining $(binding_dependency_trackers) in
|
# too much. See the comment explaining $(binding_dependency_trackers) in
|
||||||
# Makefile.in.
|
# Makefile.in.
|
||||||
rule = mk.create_rule([outputprefix])
|
rule = mk.create_rule([outputprefix])
|
||||||
rule.add_dependencies(os.path.join(srcprefix, x) for x in root.deps())
|
rule.add_dependencies(os.path.join(srcprefix, x) for x in sorted(root.deps()))
|
||||||
rule.add_dependencies(iter_modules_in_path(topsrcdir))
|
rule.add_dependencies(iter_modules_in_path(topsrcdir))
|
||||||
with open(depsname, 'w') as f:
|
with open(depsname, 'w') as f:
|
||||||
mk.dump(f)
|
mk.dump(f)
|
||||||
|
@ -872,6 +872,22 @@ GetNativePropertyHooks(JSContext *cx, JS::Handle<JSObject*> obj,
|
|||||||
return ifaceAndProtoJSClass->mNativeHooks;
|
return ifaceAndProtoJSClass->mNativeHooks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to resolve a property as an unforgeable property from the given
|
||||||
|
// NativeProperties, if it's there. nativeProperties is allowed to be null (in
|
||||||
|
// which case we of course won't resolve anything).
|
||||||
|
static bool
|
||||||
|
XrayResolveUnforgeableProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
|
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||||
|
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||||
|
const NativeProperties* nativeProperties);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
|
const NativePropertyHooks* nativePropertyHooks,
|
||||||
|
DOMObjectType type, JS::Handle<JSObject*> obj,
|
||||||
|
JS::Handle<jsid> id,
|
||||||
|
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||||
@ -881,7 +897,32 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
|||||||
const NativePropertyHooks *nativePropertyHooks =
|
const NativePropertyHooks *nativePropertyHooks =
|
||||||
GetNativePropertyHooks(cx, obj, type);
|
GetNativePropertyHooks(cx, obj, type);
|
||||||
|
|
||||||
return type != eInstance || !nativePropertyHooks->mResolveOwnProperty ||
|
if (type != eInstance) {
|
||||||
|
// For prototype objects and interface objects, just return their
|
||||||
|
// normal set of properties.
|
||||||
|
return XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type,
|
||||||
|
obj, id, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for unforgeable properties before doing mResolveOwnProperty weirdness
|
||||||
|
const NativePropertiesHolder& nativeProperties =
|
||||||
|
nativePropertyHooks->mNativeProperties;
|
||||||
|
if (!XrayResolveUnforgeableProperty(cx, wrapper, obj, id, desc,
|
||||||
|
nativeProperties.regular)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (desc.object()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!XrayResolveUnforgeableProperty(cx, wrapper, obj, id, desc,
|
||||||
|
nativeProperties.chromeOnly)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (desc.object()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !nativePropertyHooks->mResolveOwnProperty ||
|
||||||
nativePropertyHooks->mResolveOwnProperty(cx, wrapper, obj, id, desc, flags);
|
nativePropertyHooks->mResolveOwnProperty(cx, wrapper, obj, id, desc, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -936,6 +977,20 @@ XrayResolveAttribute(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */ bool
|
||||||
|
XrayResolveUnforgeableProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
|
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||||
|
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||||
|
const NativeProperties* nativeProperties)
|
||||||
|
{
|
||||||
|
return !nativeProperties || !nativeProperties->unforgeableAttributes ||
|
||||||
|
XrayResolveAttribute(cx, wrapper, obj, id,
|
||||||
|
nativeProperties->unforgeableAttributes,
|
||||||
|
nativeProperties->unforgeableAttributeIds,
|
||||||
|
nativeProperties->unforgeableAttributeSpecs,
|
||||||
|
desc);
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
XrayResolveProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
XrayResolveProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
|
||||||
@ -1008,18 +1063,6 @@ XrayResolveProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nativeProperties->unforgeableAttributes) {
|
|
||||||
if (!XrayResolveAttribute(cx, wrapper, obj, id,
|
|
||||||
nativeProperties->unforgeableAttributes,
|
|
||||||
nativeProperties->unforgeableAttributeIds,
|
|
||||||
nativeProperties->unforgeableAttributeSpecs,
|
|
||||||
desc)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (desc.object()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nativeProperties->constants) {
|
if (nativeProperties->constants) {
|
||||||
@ -1068,7 +1111,7 @@ ResolvePrototypeOrConstructor(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
|||||||
return JS_WrapPropertyDescriptor(cx, desc);
|
return JS_WrapPropertyDescriptor(cx, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
/* static */ bool
|
||||||
XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
const NativePropertyHooks* nativePropertyHooks,
|
const NativePropertyHooks* nativePropertyHooks,
|
||||||
DOMObjectType type, JS::Handle<JSObject*> obj,
|
DOMObjectType type, JS::Handle<JSObject*> obj,
|
||||||
@ -1904,9 +1947,10 @@ InterfaceHasInstance(JSContext* cx, int prototypeID, int depth,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ReportLenientThisUnwrappingFailure(JSContext* cx, JS::Handle<JSObject*> obj)
|
ReportLenientThisUnwrappingFailure(JSContext* cx, JSObject* obj)
|
||||||
{
|
{
|
||||||
GlobalObject global(cx, obj);
|
JS::Rooted<JSObject*> rootedObj(cx, obj);
|
||||||
|
GlobalObject global(cx, rootedObj);
|
||||||
if (global.Failed()) {
|
if (global.Failed()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "mozilla/dom/Exceptions.h"
|
#include "mozilla/dom/Exceptions.h"
|
||||||
#include "mozilla/dom/NonRefcountedDOMObject.h"
|
#include "mozilla/dom/NonRefcountedDOMObject.h"
|
||||||
#include "mozilla/dom/Nullable.h"
|
#include "mozilla/dom/Nullable.h"
|
||||||
|
#include "mozilla/dom/RootedDictionary.h"
|
||||||
#include "mozilla/dom/workers/Workers.h"
|
#include "mozilla/dom/workers/Workers.h"
|
||||||
#include "mozilla/ErrorResult.h"
|
#include "mozilla/ErrorResult.h"
|
||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
@ -1756,42 +1757,6 @@ public:
|
|||||||
SequenceType mSequenceType;
|
SequenceType mSequenceType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class MOZ_STACK_CLASS RootedDictionary : public T,
|
|
||||||
private JS::CustomAutoRooter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RootedDictionary(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
|
|
||||||
T(),
|
|
||||||
JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void trace(JSTracer *trc) MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
this->TraceDictionary(trc);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class MOZ_STACK_CLASS NullableRootedDictionary : public Nullable<T>,
|
|
||||||
private JS::CustomAutoRooter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
NullableRootedDictionary(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
|
|
||||||
Nullable<T>(),
|
|
||||||
JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void trace(JSTracer *trc) MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
if (!this->IsNull()) {
|
|
||||||
this->Value().TraceDictionary(trc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class MOZ_STACK_CLASS RootedUnion : public T,
|
class MOZ_STACK_CLASS RootedUnion : public T,
|
||||||
private JS::CustomAutoRooter
|
private JS::CustomAutoRooter
|
||||||
@ -2062,7 +2027,7 @@ InterfaceHasInstance(JSContext* cx, int prototypeID, int depth,
|
|||||||
// Helper for lenient getters/setters to report to console. If this
|
// Helper for lenient getters/setters to report to console. If this
|
||||||
// returns false, we couldn't even get a global.
|
// returns false, we couldn't even get a global.
|
||||||
bool
|
bool
|
||||||
ReportLenientThisUnwrappingFailure(JSContext* cx, JS::Handle<JSObject*> obj);
|
ReportLenientThisUnwrappingFailure(JSContext* cx, JSObject* obj);
|
||||||
|
|
||||||
inline JSObject*
|
inline JSObject*
|
||||||
GetUnforgeableHolder(JSObject* aGlobal, prototypes::ID aId)
|
GetUnforgeableHolder(JSObject* aGlobal, prototypes::ID aId)
|
||||||
|
@ -826,8 +826,13 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
|
|||||||
declarations.add((typeDesc.nativeType, False))
|
declarations.add((typeDesc.nativeType, False))
|
||||||
implheaders.add(typeDesc.headerFile)
|
implheaders.add(typeDesc.headerFile)
|
||||||
elif f.isDictionary():
|
elif f.isDictionary():
|
||||||
declarations.add((f.inner.identifier.name, True))
|
# For a dictionary, we need to see its declaration in
|
||||||
implheaders.add(CGHeaders.getDeclarationFilename(f.inner))
|
# UnionTypes.h so we have its sizeof and know how big to
|
||||||
|
# make our union.
|
||||||
|
headers.add(CGHeaders.getDeclarationFilename(f.inner))
|
||||||
|
# And if it needs rooting, we need RootedDictionary too
|
||||||
|
if typeNeedsRooting(f):
|
||||||
|
headers.add("mozilla/dom/RootedDictionary.h")
|
||||||
elif t.isPrimitive():
|
elif t.isPrimitive():
|
||||||
implheaders.add("mozilla/dom/PrimitiveConversions.h")
|
implheaders.add("mozilla/dom/PrimitiveConversions.h")
|
||||||
|
|
||||||
@ -2554,7 +2559,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||||||
lenientFloatCode=None,
|
lenientFloatCode=None,
|
||||||
allowTreatNonCallableAsNull=False,
|
allowTreatNonCallableAsNull=False,
|
||||||
isCallbackReturnValue=False,
|
isCallbackReturnValue=False,
|
||||||
isInOwningUnion=False,
|
|
||||||
sourceDescription="value"):
|
sourceDescription="value"):
|
||||||
"""
|
"""
|
||||||
Get a template for converting a JS value to a native object based on the
|
Get a template for converting a JS value to a native object based on the
|
||||||
@ -2575,9 +2579,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||||||
if isMember is not False, we're being converted from a property of some JS
|
if isMember is not False, we're being converted from a property of some JS
|
||||||
object, not from an actual method argument, so we can't rely on our jsval
|
object, not from an actual method argument, so we can't rely on our jsval
|
||||||
being rooted or outliving us in any way. Callers can pass "Dictionary",
|
being rooted or outliving us in any way. Callers can pass "Dictionary",
|
||||||
"Variadic", or "Sequence" to indicate that the conversion is for something
|
"Variadic", "Sequence", or "OwningUnion" to indicate that the conversion is
|
||||||
that is a dictionary member, a variadic argument, or a sequence
|
for something that is a dictionary member, a variadic argument, a sequence,
|
||||||
respectively.
|
or an owning union respectively.
|
||||||
|
|
||||||
If isOptional is true, then we are doing conversion of an optional
|
If isOptional is true, then we are doing conversion of an optional
|
||||||
argument with no default value.
|
argument with no default value.
|
||||||
@ -2720,26 +2724,28 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||||||
return templateBody
|
return templateBody
|
||||||
|
|
||||||
# A helper function for converting things that look like a JSObject*.
|
# A helper function for converting things that look like a JSObject*.
|
||||||
def handleJSObjectType(type, isMember, isInOwningUnion, failureCode):
|
def handleJSObjectType(type, isMember, failureCode):
|
||||||
if not isMember and not isInOwningUnion:
|
if not isMember:
|
||||||
if isOptional:
|
if isOptional:
|
||||||
# We have a specialization of Optional that will use a
|
# We have a specialization of Optional that will use a
|
||||||
# Rooted for the storage here.
|
# Rooted for the storage here.
|
||||||
declType = CGGeneric("JS::Handle<JSObject*>")
|
declType = CGGeneric("JS::Handle<JSObject*>")
|
||||||
else:
|
else:
|
||||||
declType = CGGeneric("JS::Rooted<JSObject*>")
|
declType = CGGeneric("JS::Rooted<JSObject*>")
|
||||||
|
declArgs="cx"
|
||||||
else:
|
else:
|
||||||
assert (isMember == "Sequence" or isMember == "Variadic" or
|
assert (isMember == "Sequence" or isMember == "Variadic" or
|
||||||
isMember == "Dictionary" or isInOwningUnion)
|
isMember == "Dictionary" or isMember == "OwningUnion")
|
||||||
# We'll get traced by the sequence or dictionary or union tracer
|
# We'll get traced by the sequence or dictionary or union tracer
|
||||||
declType = CGGeneric("JSObject*")
|
declType = CGGeneric("JSObject*")
|
||||||
|
declArgs = None
|
||||||
templateBody = "${declName} = &${val}.toObject();"
|
templateBody = "${declName} = &${val}.toObject();"
|
||||||
setToNullCode = "${declName} = nullptr;"
|
setToNullCode = "${declName} = nullptr;"
|
||||||
template = wrapObjectTemplate(templateBody, type, setToNullCode,
|
template = wrapObjectTemplate(templateBody, type, setToNullCode,
|
||||||
failureCode)
|
failureCode)
|
||||||
return JSToNativeConversionInfo(template, declType=declType,
|
return JSToNativeConversionInfo(template, declType=declType,
|
||||||
dealWithOptional=isOptional,
|
dealWithOptional=isOptional,
|
||||||
declArgs="cx")
|
declArgs=declArgs)
|
||||||
|
|
||||||
assert not (isEnforceRange and isClamp) # These are mutually exclusive
|
assert not (isEnforceRange and isClamp) # These are mutually exclusive
|
||||||
|
|
||||||
@ -2925,31 +2931,31 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||||||
|
|
||||||
dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
|
dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
|
||||||
if len(dictionaryMemberTypes) > 0:
|
if len(dictionaryMemberTypes) > 0:
|
||||||
raise TypeError("No support for unwrapping dictionaries as member "
|
assert len(dictionaryMemberTypes) == 1
|
||||||
"of a union")
|
name = dictionaryMemberTypes[0].inner.identifier.name
|
||||||
|
setDictionary = CGGeneric("done = (failed = !%s.TrySetTo%s(cx, ${val}, ${mutableVal}, tryNext)) || !tryNext;" % (unionArgumentObj, name))
|
||||||
else:
|
else:
|
||||||
dictionaryObject = None
|
setDictionary = None
|
||||||
|
|
||||||
objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
|
objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
|
||||||
if len(objectMemberTypes) > 0:
|
if len(objectMemberTypes) > 0:
|
||||||
|
assert len(objectMemberTypes) == 1
|
||||||
object = CGGeneric("%s.SetToObject(cx, argObj);\n"
|
object = CGGeneric("%s.SetToObject(cx, argObj);\n"
|
||||||
"done = true;" % unionArgumentObj)
|
"done = true;" % unionArgumentObj)
|
||||||
else:
|
else:
|
||||||
object = None
|
object = None
|
||||||
|
|
||||||
hasObjectTypes = interfaceObject or arrayObject or dateObject or callbackObject or dictionaryObject or object
|
hasObjectTypes = interfaceObject or arrayObject or dateObject or callbackObject or object
|
||||||
if hasObjectTypes:
|
if hasObjectTypes:
|
||||||
# "object" is not distinguishable from other types
|
# "object" is not distinguishable from other types
|
||||||
assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or dictionaryObject)
|
assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject)
|
||||||
if arrayObject or dateObject or callbackObject or dictionaryObject:
|
if arrayObject or dateObject or callbackObject:
|
||||||
# An object can be both an array object and a callback or
|
# An object can be both an array object and a callback or
|
||||||
# dictionary, but we shouldn't have both in the union's members
|
# dictionary, but we shouldn't have both in the union's members
|
||||||
# because they are not distinguishable.
|
# because they are not distinguishable.
|
||||||
assert not (arrayObject and callbackObject)
|
assert not (arrayObject and callbackObject)
|
||||||
assert not (arrayObject and dictionaryObject)
|
templateBody = CGList([arrayObject, dateObject, callbackObject],
|
||||||
assert not (dictionaryObject and callbackObject)
|
" else ")
|
||||||
templateBody = CGList([arrayObject, dateObject, callbackObject,
|
|
||||||
dictionaryObject], " else ")
|
|
||||||
else:
|
else:
|
||||||
templateBody = None
|
templateBody = None
|
||||||
if interfaceObject:
|
if interfaceObject:
|
||||||
@ -2960,13 +2966,17 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||||||
else:
|
else:
|
||||||
templateBody = CGList([templateBody, object], "\n")
|
templateBody = CGList([templateBody, object], "\n")
|
||||||
|
|
||||||
if any([arrayObject, dateObject, callbackObject, dictionaryObject,
|
if any([arrayObject, dateObject, callbackObject, object]):
|
||||||
object]):
|
|
||||||
templateBody.prepend(CGGeneric("JS::Rooted<JSObject*> argObj(cx, &${val}.toObject());"))
|
templateBody.prepend(CGGeneric("JS::Rooted<JSObject*> argObj(cx, &${val}.toObject());"))
|
||||||
templateBody = CGIfWrapper(templateBody, "${val}.isObject()")
|
templateBody = CGIfWrapper(templateBody, "${val}.isObject()")
|
||||||
else:
|
else:
|
||||||
templateBody = CGGeneric()
|
templateBody = CGGeneric()
|
||||||
|
|
||||||
|
if setDictionary:
|
||||||
|
assert not object
|
||||||
|
templateBody = CGList([templateBody,
|
||||||
|
CGIfWrapper(setDictionary, "!done")], "\n")
|
||||||
|
|
||||||
stringTypes = [t for t in memberTypes if t.isString() or t.isEnum()]
|
stringTypes = [t for t in memberTypes if t.isString() or t.isEnum()]
|
||||||
numericTypes = [t for t in memberTypes if t.isNumeric()]
|
numericTypes = [t for t in memberTypes if t.isNumeric()]
|
||||||
booleanTypes = [t for t in memberTypes if t.isBoolean()]
|
booleanTypes = [t for t in memberTypes if t.isBoolean()]
|
||||||
@ -3005,7 +3015,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||||||
other.append(booleanConversion[0])
|
other.append(booleanConversion[0])
|
||||||
|
|
||||||
other = CGWrapper(CGIndenter(other), pre="do {\n", post="\n} while (0);")
|
other = CGWrapper(CGIndenter(other), pre="do {\n", post="\n} while (0);")
|
||||||
if hasObjectTypes:
|
if hasObjectTypes or setDictionary:
|
||||||
other = CGWrapper(CGIndenter(other), "{\n", post="\n}")
|
other = CGWrapper(CGIndenter(other), "{\n", post="\n}")
|
||||||
if object:
|
if object:
|
||||||
join = " else "
|
join = " else "
|
||||||
@ -3119,8 +3129,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||||||
if descriptor.nativeType == 'JSObject':
|
if descriptor.nativeType == 'JSObject':
|
||||||
# XXXbz Workers code does this sometimes
|
# XXXbz Workers code does this sometimes
|
||||||
assert descriptor.workers
|
assert descriptor.workers
|
||||||
return handleJSObjectType(type, isMember, isInOwningUnion,
|
return handleJSObjectType(type, isMember, failureCode)
|
||||||
failureCode)
|
|
||||||
|
|
||||||
if descriptor.interface.isCallback():
|
if descriptor.interface.isCallback():
|
||||||
name = descriptor.interface.identifier.name
|
name = descriptor.interface.identifier.name
|
||||||
@ -3156,7 +3165,6 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||||||
forceOwningType = ((descriptor.interface.isCallback() and
|
forceOwningType = ((descriptor.interface.isCallback() and
|
||||||
not descriptor.workers) or
|
not descriptor.workers) or
|
||||||
isMember or
|
isMember or
|
||||||
isInOwningUnion or
|
|
||||||
isCallbackReturnValue)
|
isCallbackReturnValue)
|
||||||
|
|
||||||
typeName = descriptor.nativeType
|
typeName = descriptor.nativeType
|
||||||
@ -3266,7 +3274,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||||||
CGIndenter(onFailureBadType(failureCode, type.name)).define()))
|
CGIndenter(onFailureBadType(failureCode, type.name)).define()))
|
||||||
template = wrapObjectTemplate(template, type, "${declName}.SetNull()",
|
template = wrapObjectTemplate(template, type, "${declName}.SetNull()",
|
||||||
failureCode)
|
failureCode)
|
||||||
if not isMember and not isInOwningUnion:
|
if not isMember:
|
||||||
# This is a bit annoying. In a union we don't want to have a
|
# This is a bit annoying. In a union we don't want to have a
|
||||||
# holder, since unions don't support that. But if we're optional we
|
# holder, since unions don't support that. But if we're optional we
|
||||||
# want to have a holder, so that the callee doesn't see
|
# want to have a holder, so that the callee doesn't see
|
||||||
@ -3358,22 +3366,14 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||||||
|
|
||||||
if isOptional:
|
if isOptional:
|
||||||
declType = "Optional<nsAString>"
|
declType = "Optional<nsAString>"
|
||||||
elif isInOwningUnion:
|
|
||||||
declType = "nsString"
|
|
||||||
else:
|
else:
|
||||||
declType = "NonNull<nsAString>"
|
declType = "NonNull<nsAString>"
|
||||||
|
|
||||||
# No need to deal with optional here; we handled it already
|
# No need to deal with optional here; we handled it already
|
||||||
decl = ""
|
|
||||||
if isInOwningUnion:
|
|
||||||
decl += "FakeDependentString str;\n"
|
|
||||||
return JSToNativeConversionInfo(
|
return JSToNativeConversionInfo(
|
||||||
"%s"
|
("%s\n"
|
||||||
"%s\n"
|
"${declName} = &${holderName};" %
|
||||||
"${declName} = %s" %
|
getConversionCode("${holderName}")),
|
||||||
(decl,
|
|
||||||
getConversionCode("str" if isInOwningUnion else "${holderName}"),
|
|
||||||
("str;" if isInOwningUnion else "&${holderName};")),
|
|
||||||
declType=CGGeneric(declType),
|
declType=CGGeneric(declType),
|
||||||
holderType=CGGeneric("FakeDependentString"))
|
holderType=CGGeneric("FakeDependentString"))
|
||||||
|
|
||||||
@ -3526,13 +3526,9 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||||||
|
|
||||||
if type.isObject():
|
if type.isObject():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
return handleJSObjectType(type, isMember, isInOwningUnion, failureCode)
|
return handleJSObjectType(type, isMember, failureCode)
|
||||||
|
|
||||||
if type.isDictionary():
|
if type.isDictionary():
|
||||||
if failureCode is not None and not isDefinitelyObject:
|
|
||||||
raise TypeError("Can't handle dictionaries when failureCode is "
|
|
||||||
"not None and we don't know we're an object")
|
|
||||||
|
|
||||||
# There are no nullable dictionaries
|
# There are no nullable dictionaries
|
||||||
assert not type.nullable()
|
assert not type.nullable()
|
||||||
# All optional dictionaries always have default values, so we
|
# All optional dictionaries always have default values, so we
|
||||||
@ -3557,12 +3553,15 @@ for (uint32_t i = 0; i < length; ++i) {
|
|||||||
val = "${val}"
|
val = "${val}"
|
||||||
|
|
||||||
if failureCode is not None:
|
if failureCode is not None:
|
||||||
assert isDefinitelyObject
|
if isDefinitelyObject:
|
||||||
|
dictionaryTest = "IsObjectValueConvertibleToDictionary"
|
||||||
|
else:
|
||||||
|
dictionaryTest = "IsConvertibleToDictionary"
|
||||||
# Check that the value we have can in fact be converted to
|
# Check that the value we have can in fact be converted to
|
||||||
# a dictionary, and return failureCode if not.
|
# a dictionary, and return failureCode if not.
|
||||||
template = CGIfWrapper(
|
template = CGIfWrapper(
|
||||||
CGGeneric(failureCode),
|
CGGeneric(failureCode),
|
||||||
"!IsObjectValueConvertibleToDictionary(cx, ${val})").define() + "\n\n"
|
"!%s(cx, ${val})" % dictionaryTest).define() + "\n\n"
|
||||||
else:
|
else:
|
||||||
template = ""
|
template = ""
|
||||||
|
|
||||||
@ -5321,9 +5320,18 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod):
|
|||||||
|this| object. Subclasses are expected to override the generate_code
|
|this| object. Subclasses are expected to override the generate_code
|
||||||
function to do the rest of the work. This function should return a
|
function to do the rest of the work. This function should return a
|
||||||
CGThing which is already properly indented.
|
CGThing which is already properly indented.
|
||||||
|
|
||||||
|
getThisObj should be code for getting a JSObject* for the binding
|
||||||
|
object. If this is None, we will auto-generate code based on
|
||||||
|
descriptor to do the right thing. "" can be passed in if the
|
||||||
|
binding object is already stored in 'obj'.
|
||||||
|
|
||||||
|
callArgs should be code for getting a JS::CallArgs into a variable
|
||||||
|
called 'args'. This can be "" if there is already such a variable
|
||||||
|
around.
|
||||||
"""
|
"""
|
||||||
def __init__(self, descriptor, name, args, unwrapFailureCode=None,
|
def __init__(self, descriptor, name, args, unwrapFailureCode=None,
|
||||||
getThisObj="args.computeThis(cx).toObjectOrNull()",
|
getThisObj=None,
|
||||||
callArgs="JS::CallArgs args = JS::CallArgsFromVp(argc, vp);"):
|
callArgs="JS::CallArgs args = JS::CallArgsFromVp(argc, vp);"):
|
||||||
CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
|
CGAbstractStaticMethod.__init__(self, descriptor, name, "bool", args)
|
||||||
|
|
||||||
@ -5331,7 +5339,26 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod):
|
|||||||
self.unwrapFailureCode = 'return ThrowErrorMessage(cx, MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, "Value", "%s");' % descriptor.interface.identifier.name
|
self.unwrapFailureCode = 'return ThrowErrorMessage(cx, MSG_THIS_DOES_NOT_IMPLEMENT_INTERFACE, "Value", "%s");' % descriptor.interface.identifier.name
|
||||||
else:
|
else:
|
||||||
self.unwrapFailureCode = unwrapFailureCode
|
self.unwrapFailureCode = unwrapFailureCode
|
||||||
self.getThisObj = getThisObj
|
|
||||||
|
if getThisObj == "":
|
||||||
|
self.getThisObj = None
|
||||||
|
else:
|
||||||
|
if getThisObj is None:
|
||||||
|
if descriptor.interface.isOnGlobalProtoChain():
|
||||||
|
ensureCondition = "!args.thisv().isNullOrUndefined() && !args.thisv().isObject()"
|
||||||
|
getThisObj = "args.thisv().isObject() ? &args.thisv().toObject() : js::GetGlobalForObjectCrossCompartment(&args.callee())"
|
||||||
|
else:
|
||||||
|
ensureCondition = "!args.thisv().isObject()"
|
||||||
|
getThisObj = "&args.thisv().toObject()"
|
||||||
|
ensureThisObj = CGIfWrapper(CGGeneric(self.unwrapFailureCode),
|
||||||
|
ensureCondition)
|
||||||
|
else:
|
||||||
|
ensureThisObj = None
|
||||||
|
self.getThisObj = CGList(
|
||||||
|
[ensureThisObj,
|
||||||
|
CGGeneric("JS::RootedObject obj(cx, %s);\n" %
|
||||||
|
getThisObj)],
|
||||||
|
"\n")
|
||||||
self.callArgs = callArgs
|
self.callArgs = callArgs
|
||||||
|
|
||||||
def definition_body(self):
|
def definition_body(self):
|
||||||
@ -5341,10 +5368,7 @@ class CGAbstractBindingMethod(CGAbstractStaticMethod):
|
|||||||
# consumption by CastableObjectUnwrapper.
|
# consumption by CastableObjectUnwrapper.
|
||||||
getThis = CGList([
|
getThis = CGList([
|
||||||
CGGeneric(self.callArgs) if self.callArgs != "" else None,
|
CGGeneric(self.callArgs) if self.callArgs != "" else None,
|
||||||
CGGeneric("JS::RootedObject obj(cx, %s);\n"
|
self.getThisObj,
|
||||||
"if (!obj) {\n"
|
|
||||||
" return false;\n"
|
|
||||||
"}" % self.getThisObj) if self.getThisObj else None,
|
|
||||||
CGGeneric("%s* self;" % self.descriptor.nativeType)
|
CGGeneric("%s* self;" % self.descriptor.nativeType)
|
||||||
], "\n")
|
], "\n")
|
||||||
unwrapThis = CGGeneric(
|
unwrapThis = CGGeneric(
|
||||||
@ -5585,7 +5609,7 @@ class CGGenericGetter(CGAbstractBindingMethod):
|
|||||||
name = "genericLenientGetter"
|
name = "genericLenientGetter"
|
||||||
unwrapFailureCode = (
|
unwrapFailureCode = (
|
||||||
"MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"
|
"MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"
|
||||||
"if (!ReportLenientThisUnwrappingFailure(cx, obj)) {\n"
|
"if (!ReportLenientThisUnwrappingFailure(cx, &args.callee())) {\n"
|
||||||
" return false;\n"
|
" return false;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"args.rval().set(JS::UndefinedValue());\n"
|
"args.rval().set(JS::UndefinedValue());\n"
|
||||||
@ -5665,7 +5689,7 @@ class CGGenericSetter(CGAbstractBindingMethod):
|
|||||||
name = "genericLenientSetter"
|
name = "genericLenientSetter"
|
||||||
unwrapFailureCode = (
|
unwrapFailureCode = (
|
||||||
"MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"
|
"MOZ_ASSERT(!JS_IsExceptionPending(cx));\n"
|
||||||
"if (!ReportLenientThisUnwrappingFailure(cx, obj)) {\n"
|
"if (!ReportLenientThisUnwrappingFailure(cx, &args.callee())) {\n"
|
||||||
" return false;\n"
|
" return false;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"args.rval().set(JS::UndefinedValue());\n"
|
"args.rval().set(JS::UndefinedValue());\n"
|
||||||
@ -6067,6 +6091,9 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
|
|||||||
if type.isObject():
|
if type.isObject():
|
||||||
return CGGeneric("JSObject*")
|
return CGGeneric("JSObject*")
|
||||||
|
|
||||||
|
if type.isDictionary():
|
||||||
|
return CGGeneric("const %s&" % type.inner.identifier.name)
|
||||||
|
|
||||||
if not type.isPrimitive():
|
if not type.isPrimitive():
|
||||||
raise TypeError("Need native type for argument type '%s'" % str(type))
|
raise TypeError("Need native type for argument type '%s'" % str(type))
|
||||||
|
|
||||||
@ -6081,14 +6108,11 @@ def getUnionTypeTemplateVars(unionType, type, descriptorProvider,
|
|||||||
# for getJSToNativeConversionInfo.
|
# for getJSToNativeConversionInfo.
|
||||||
# Also, for dictionaries we would need to handle conversion of
|
# Also, for dictionaries we would need to handle conversion of
|
||||||
# null/undefined to the dictionary correctly.
|
# null/undefined to the dictionary correctly.
|
||||||
if type.isDictionary() or type.isSequence():
|
if type.isSequence():
|
||||||
raise TypeError("Can't handle dictionaries or sequences in unions")
|
raise TypeError("Can't handle sequences in unions")
|
||||||
|
|
||||||
name = getUnionMemberName(type)
|
name = getUnionMemberName(type)
|
||||||
|
|
||||||
ctorNeedsCx = type.isSpiderMonkeyInterface() and not ownsMembers
|
|
||||||
ctorArgs = "cx" if ctorNeedsCx else ""
|
|
||||||
|
|
||||||
tryNextCode = ("tryNext = true;\n"
|
tryNextCode = ("tryNext = true;\n"
|
||||||
"return true;")
|
"return true;")
|
||||||
if type.isGeckoInterface():
|
if type.isGeckoInterface():
|
||||||
@ -6098,9 +6122,13 @@ def getUnionTypeTemplateVars(unionType, type, descriptorProvider,
|
|||||||
"}") % (prefix, prefix, prefix, name) + tryNextCode
|
"}") % (prefix, prefix, prefix, name) + tryNextCode
|
||||||
conversionInfo = getJSToNativeConversionInfo(
|
conversionInfo = getJSToNativeConversionInfo(
|
||||||
type, descriptorProvider, failureCode=tryNextCode,
|
type, descriptorProvider, failureCode=tryNextCode,
|
||||||
isDefinitelyObject=True, isInOwningUnion=ownsMembers,
|
isDefinitelyObject=not type.isDictionary(),
|
||||||
|
isMember=("OwningUnion" if ownsMembers else None),
|
||||||
sourceDescription="member of %s" % unionType)
|
sourceDescription="member of %s" % unionType)
|
||||||
|
|
||||||
|
ctorNeedsCx = conversionInfo.declArgs == "cx"
|
||||||
|
ctorArgs = "cx" if ctorNeedsCx else ""
|
||||||
|
|
||||||
# This is ugly, but UnionMember needs to call a constructor with no
|
# This is ugly, but UnionMember needs to call a constructor with no
|
||||||
# arguments so the type can't be const.
|
# arguments so the type can't be const.
|
||||||
structType = conversionInfo.declType.define()
|
structType = conversionInfo.declType.define()
|
||||||
@ -6267,6 +6295,11 @@ class CGUnionStruct(CGThing):
|
|||||||
CGGeneric('JS_CallObjectTracer(trc, %s, "%s");' %
|
CGGeneric('JS_CallObjectTracer(trc, %s, "%s");' %
|
||||||
("&mValue.m" + vars["name"] + ".Value()",
|
("&mValue.m" + vars["name"] + ".Value()",
|
||||||
"mValue.m" + vars["name"]))))
|
"mValue.m" + vars["name"]))))
|
||||||
|
elif t.isDictionary():
|
||||||
|
traceCases.append(
|
||||||
|
CGCase("e" + vars["name"],
|
||||||
|
CGGeneric("mValue.m%s.Value().TraceDictionary(trc);" %
|
||||||
|
vars["name"])))
|
||||||
else:
|
else:
|
||||||
assert t.isSpiderMonkeyInterface()
|
assert t.isSpiderMonkeyInterface()
|
||||||
traceCases.append(
|
traceCases.append(
|
||||||
@ -7285,14 +7318,16 @@ class CGDOMJSProxyHandler_getOwnPropertyDescriptor(ClassMethod):
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
MOZ_ASSERT_IF(desc.object(), desc.object() == ${holder});"""
|
MOZ_ASSERT_IF(desc.object(), desc.object() == ${holder});"""
|
||||||
|
# We don't want to look at the unforgeable holder at all
|
||||||
|
# in the xray case; that part got handled already.
|
||||||
getUnforgeable = CallOnUnforgeableHolder(self.descriptor,
|
getUnforgeable = CallOnUnforgeableHolder(self.descriptor,
|
||||||
getUnforgeable, "isXray")
|
getUnforgeable)
|
||||||
getUnforgeable += """if (desc.object()) {
|
getUnforgeable += """if (desc.object()) {
|
||||||
desc.object().set(proxy);
|
desc.object().set(proxy);
|
||||||
return !isXray || JS_WrapPropertyDescriptor(cx, desc);
|
return true;
|
||||||
}
|
}"""
|
||||||
|
getUnforgeable = CGIfWrapper(CGGeneric(getUnforgeable),
|
||||||
"""
|
"!isXray").define() + "\n\n"
|
||||||
else:
|
else:
|
||||||
getUnforgeable = ""
|
getUnforgeable = ""
|
||||||
|
|
||||||
@ -8123,13 +8158,26 @@ class CGDictionary(CGThing):
|
|||||||
isClamp=member.clamp,
|
isClamp=member.clamp,
|
||||||
isMember="Dictionary",
|
isMember="Dictionary",
|
||||||
isOptional=(not member.defaultValue),
|
isOptional=(not member.defaultValue),
|
||||||
# Set this to true so that we get an owning union.
|
|
||||||
isInOwningUnion=True,
|
|
||||||
defaultValue=member.defaultValue,
|
defaultValue=member.defaultValue,
|
||||||
sourceDescription=("'%s' member of %s" %
|
sourceDescription=("'%s' member of %s" %
|
||||||
(member.identifier.name,
|
(member.identifier.name,
|
||||||
dictionary.identifier.name))))
|
dictionary.identifier.name))))
|
||||||
for member in dictionary.members ]
|
for member in dictionary.members ]
|
||||||
|
# If we have a union member containing something in the same
|
||||||
|
# file as us, bail: the C++ includes won't work out.
|
||||||
|
for member in dictionary.members:
|
||||||
|
type = member.type.unroll()
|
||||||
|
if type.isUnion():
|
||||||
|
for t in type.flatMemberTypes:
|
||||||
|
if (t.isDictionary() and
|
||||||
|
CGHeaders.getDeclarationFilename(t.inner) ==
|
||||||
|
CGHeaders.getDeclarationFilename(dictionary)):
|
||||||
|
raise TypeError(
|
||||||
|
"Dictionary contains a union that contains a "
|
||||||
|
"dictionary in the same WebIDL file. This won't "
|
||||||
|
"compile. Move the inner dictionary to a "
|
||||||
|
"different file.\n%s\n%s" %
|
||||||
|
(t.location, t.inner.location))
|
||||||
self.structs = self.getStructs()
|
self.structs = self.getStructs()
|
||||||
|
|
||||||
def declare(self):
|
def declare(self):
|
||||||
|
@ -23,7 +23,7 @@ exported_generated_events_headers := $(subst .webidl,.h,$(generated_events_webid
|
|||||||
linked_binding_cpp_files := $(subst .webidl,Binding.cpp,$(all_webidl_files))
|
linked_binding_cpp_files := $(subst .webidl,Binding.cpp,$(all_webidl_files))
|
||||||
linked_generated_events_cpp_files := $(subst .webidl,.cpp,$(generated_events_webidl_files))
|
linked_generated_events_cpp_files := $(subst .webidl,.cpp,$(generated_events_webidl_files))
|
||||||
|
|
||||||
all_webidl_files += $(test_webidl_files)
|
all_webidl_files += $(test_webidl_files) $(preprocessed_test_webidl_files)
|
||||||
|
|
||||||
generated_header_files := $(subst .webidl,Binding.h,$(all_webidl_files)) $(exported_generated_events_headers)
|
generated_header_files := $(subst .webidl,Binding.h,$(all_webidl_files)) $(exported_generated_events_headers)
|
||||||
generated_cpp_files := $(subst .webidl,Binding.cpp,$(all_webidl_files)) $(linked_generated_events_cpp_files)
|
generated_cpp_files := $(subst .webidl,Binding.cpp,$(all_webidl_files)) $(linked_generated_events_cpp_files)
|
||||||
@ -168,6 +168,12 @@ $(preprocessed_webidl_files): %: $(webidl_base)/% $(GLOBAL_DEPS)
|
|||||||
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) \
|
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) \
|
||||||
$(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $(webidl_base)/$* -o $@
|
$(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $(webidl_base)/$* -o $@
|
||||||
|
|
||||||
|
# See the comment about PP_TARGETS for $(preprocessed_webidl_files)
|
||||||
|
$(preprocessed_test_webidl_files): %: $(srcdir)/test/% $(GLOBAL_DEPS)
|
||||||
|
$(RM) $@
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 $(PYTHON) \
|
||||||
|
$(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $(srcdir)/test/$* -o $@
|
||||||
|
|
||||||
# Make is dumb and can get confused between "foo" and "$(CURDIR)/foo". Make
|
# Make is dumb and can get confused between "foo" and "$(CURDIR)/foo". Make
|
||||||
# sure that the latter depends on the former, since the latter gets used in .pp
|
# sure that the latter depends on the former, since the latter gets used in .pp
|
||||||
# files.
|
# files.
|
||||||
|
56
dom/bindings/RootedDictionary.h
Normal file
56
dom/bindings/RootedDictionary.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
|
||||||
|
/* vim: set ts=2 sw=2 et tw=79: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_RootedDictionary_h__
|
||||||
|
#define mozilla_dom_RootedDictionary_h__
|
||||||
|
|
||||||
|
#include "mozilla/GuardObjects.h"
|
||||||
|
#include "mozilla/dom/Nullable.h"
|
||||||
|
#include "jsapi.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class MOZ_STACK_CLASS RootedDictionary : public T,
|
||||||
|
private JS::CustomAutoRooter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RootedDictionary(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
|
||||||
|
T(),
|
||||||
|
JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void trace(JSTracer *trc) MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
this->TraceDictionary(trc);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class MOZ_STACK_CLASS NullableRootedDictionary : public Nullable<T>,
|
||||||
|
private JS::CustomAutoRooter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NullableRootedDictionary(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
|
||||||
|
Nullable<T>(),
|
||||||
|
JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void trace(JSTracer *trc) MOZ_OVERRIDE
|
||||||
|
{
|
||||||
|
if (!this->IsNull()) {
|
||||||
|
this->Value().TraceDictionary(trc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif /* mozilla_dom_RootedDictionary_h__ */
|
@ -27,6 +27,7 @@ EXPORTS.mozilla.dom += [
|
|||||||
'Nullable.h',
|
'Nullable.h',
|
||||||
'OwningNonNull.h',
|
'OwningNonNull.h',
|
||||||
'PrimitiveConversions.h',
|
'PrimitiveConversions.h',
|
||||||
|
'RootedDictionary.h',
|
||||||
'TypedArray.h',
|
'TypedArray.h',
|
||||||
'UnionMember.h',
|
'UnionMember.h',
|
||||||
]
|
]
|
||||||
|
@ -523,6 +523,7 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
# have self as a consequential interface
|
# have self as a consequential interface
|
||||||
self.interfacesImplementingSelf = set()
|
self.interfacesImplementingSelf = set()
|
||||||
self._hasChildInterfaces = False
|
self._hasChildInterfaces = False
|
||||||
|
self._isOnGlobalProtoChain = False
|
||||||
|
|
||||||
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
IDLObjectWithScope.__init__(self, location, parentScope, name)
|
||||||
|
|
||||||
@ -586,6 +587,15 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
|
|
||||||
self.parent._hasChildInterfaces = True
|
self.parent._hasChildInterfaces = True
|
||||||
|
|
||||||
|
# Interfaces with [Global] must not have anything inherit from them
|
||||||
|
if self.parent.getExtendedAttribute("Global"):
|
||||||
|
# Note: This is not a self.parent.isOnGlobalProtoChain() check
|
||||||
|
# because ancestors of a [Global] interface can have other
|
||||||
|
# descendants.
|
||||||
|
raise WebIDLError("[Global] interface has another interface "
|
||||||
|
"inheriting from it",
|
||||||
|
[self.location, self.parent.location])
|
||||||
|
|
||||||
# Callbacks must not inherit from non-callbacks or inherit from
|
# Callbacks must not inherit from non-callbacks or inherit from
|
||||||
# anything that has consequential interfaces.
|
# anything that has consequential interfaces.
|
||||||
# XXXbz Can non-callbacks inherit from callbacks? Spec issue pending.
|
# XXXbz Can non-callbacks inherit from callbacks? Spec issue pending.
|
||||||
@ -741,6 +751,31 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
|
|
||||||
specialMembersSeen[memberType] = member
|
specialMembersSeen[memberType] = member
|
||||||
|
|
||||||
|
if self._isOnGlobalProtoChain:
|
||||||
|
# Make sure we have no named setters, creators, or deleters
|
||||||
|
for memberType in ["setter", "creator", "deleter"]:
|
||||||
|
memberId = "named " + memberType + "s"
|
||||||
|
if memberId in specialMembersSeen:
|
||||||
|
raise WebIDLError("Interface with [Global] has a named %s" %
|
||||||
|
memberType,
|
||||||
|
[self.location,
|
||||||
|
specialMembersSeen[memberId].location])
|
||||||
|
# Make sure we're not [OverrideBuiltins]
|
||||||
|
if self.getExtendedAttribute("OverrideBuiltins"):
|
||||||
|
raise WebIDLError("Interface with [Global] also has "
|
||||||
|
"[OverrideBuiltins]",
|
||||||
|
[self.location])
|
||||||
|
# Mark all of our ancestors as being on the global's proto chain too
|
||||||
|
parent = self.parent
|
||||||
|
while parent:
|
||||||
|
# Must not inherit from an interface with [OverrideBuiltins]
|
||||||
|
if parent.getExtendedAttribute("OverrideBuiltins"):
|
||||||
|
raise WebIDLError("Interface with [Global] inherits from "
|
||||||
|
"interface with [OverrideBuiltins]",
|
||||||
|
[self.location, parent.location])
|
||||||
|
parent._isOnGlobalProtoChain = True
|
||||||
|
parent = parent.parent
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
for member in self.members:
|
for member in self.members:
|
||||||
member.validate()
|
member.validate()
|
||||||
@ -924,6 +959,11 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
raise WebIDLError("[ArrayClass] must not be specified on "
|
raise WebIDLError("[ArrayClass] must not be specified on "
|
||||||
"an interface with inherited interfaces",
|
"an interface with inherited interfaces",
|
||||||
[attr.location, self.location])
|
[attr.location, self.location])
|
||||||
|
elif identifier == "Global":
|
||||||
|
if not attr.noArguments():
|
||||||
|
raise WebIDLError("[Global] must take no arguments",
|
||||||
|
[attr.location])
|
||||||
|
self._isOnGlobalProtoChain = True
|
||||||
elif (identifier == "PrefControlled" or
|
elif (identifier == "PrefControlled" or
|
||||||
identifier == "NeedNewResolve" or
|
identifier == "NeedNewResolve" or
|
||||||
identifier == "OverrideBuiltins" or
|
identifier == "OverrideBuiltins" or
|
||||||
@ -1042,6 +1082,9 @@ class IDLInterface(IDLObjectWithScope):
|
|||||||
def hasChildInterfaces(self):
|
def hasChildInterfaces(self):
|
||||||
return self._hasChildInterfaces
|
return self._hasChildInterfaces
|
||||||
|
|
||||||
|
def isOnGlobalProtoChain(self):
|
||||||
|
return self._isOnGlobalProtoChain
|
||||||
|
|
||||||
def _getDependentObjects(self):
|
def _getDependentObjects(self):
|
||||||
deps = set(self.members)
|
deps = set(self.members)
|
||||||
deps.union(self.implementedInterfaces)
|
deps.union(self.implementedInterfaces)
|
||||||
@ -2458,6 +2501,7 @@ class IDLNullValue(IDLObject):
|
|||||||
def coerceToType(self, type, location):
|
def coerceToType(self, type, location):
|
||||||
if (not isinstance(type, IDLNullableType) and
|
if (not isinstance(type, IDLNullableType) and
|
||||||
not (type.isUnion() and type.hasNullableType) and
|
not (type.isUnion() and type.hasNullableType) and
|
||||||
|
not (type.isUnion() and type.hasDictionaryType) and
|
||||||
not type.isDictionary() and
|
not type.isDictionary() and
|
||||||
not type.isAny()):
|
not type.isAny()):
|
||||||
raise WebIDLError("Cannot coerce null value to type %s." % type,
|
raise WebIDLError("Cannot coerce null value to type %s." % type,
|
||||||
@ -2797,7 +2841,9 @@ class IDLArgument(IDLObjectWithIdentifier):
|
|||||||
assert not isinstance(type.name, IDLUnresolvedIdentifier)
|
assert not isinstance(type.name, IDLUnresolvedIdentifier)
|
||||||
self.type = type
|
self.type = type
|
||||||
|
|
||||||
if self.type.isDictionary() and self.optional and not self.defaultValue:
|
if ((self.type.isDictionary() or
|
||||||
|
self.type.isUnion() and self.type.unroll().hasDictionaryType) and
|
||||||
|
self.optional and not self.defaultValue):
|
||||||
# Default optional dictionaries to null, for simplicity,
|
# Default optional dictionaries to null, for simplicity,
|
||||||
# so the codegen doesn't have to special-case this.
|
# so the codegen doesn't have to special-case this.
|
||||||
self.defaultValue = IDLNullValue(self.location)
|
self.defaultValue = IDLNullValue(self.location)
|
||||||
|
122
dom/bindings/parser/tests/test_global_extended_attr.py
Normal file
122
dom/bindings/parser/tests/test_global_extended_attr.py
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
def WebIDLTest(parser, harness):
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo : Bar {
|
||||||
|
getter any(DOMString name);
|
||||||
|
};
|
||||||
|
interface Bar {};
|
||||||
|
""")
|
||||||
|
|
||||||
|
results = parser.finish()
|
||||||
|
|
||||||
|
harness.ok(results[0].isOnGlobalProtoChain(),
|
||||||
|
"[Global] interface should be on global's proto chain")
|
||||||
|
harness.ok(results[1].isOnGlobalProtoChain(),
|
||||||
|
"[Global] interface should be on global's proto chain")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo {
|
||||||
|
getter any(DOMString name);
|
||||||
|
setter void(DOMString name, any arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"named setter")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo {
|
||||||
|
getter any(DOMString name);
|
||||||
|
creator void(DOMString name, any arg);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"named creator")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo {
|
||||||
|
getter any(DOMString name);
|
||||||
|
deleter void(DOMString name);
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"named deleter")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global, OverrideBuiltins]
|
||||||
|
interface Foo {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"[OverrideBuiltins]")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo : Bar {
|
||||||
|
};
|
||||||
|
[OverrideBuiltins]
|
||||||
|
interface Bar {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with an "
|
||||||
|
"[OverrideBuiltins] ancestor")
|
||||||
|
|
||||||
|
parser = parser.reset()
|
||||||
|
threw = False
|
||||||
|
try:
|
||||||
|
parser.parse("""
|
||||||
|
[Global]
|
||||||
|
interface Foo {
|
||||||
|
};
|
||||||
|
interface Bar : Foo {
|
||||||
|
};
|
||||||
|
""")
|
||||||
|
results = parser.finish()
|
||||||
|
except:
|
||||||
|
threw = True
|
||||||
|
|
||||||
|
harness.ok(threw,
|
||||||
|
"Should have thrown for [Global] used on an interface with a "
|
||||||
|
"descendant")
|
@ -13,11 +13,15 @@ endif
|
|||||||
# Need this to find all our DOM source files.
|
# Need this to find all our DOM source files.
|
||||||
include $(topsrcdir)/dom/dom-config.mk
|
include $(topsrcdir)/dom/dom-config.mk
|
||||||
|
|
||||||
# And need this for $(test_webidl_files)
|
# And need this for $(test_webidl_files) and $(preprocessed_test_webidl_files)
|
||||||
include ../webidlsrcs.mk
|
include ../webidlsrcs.mk
|
||||||
|
|
||||||
# But the webidl actually lives in our parent dir
|
# But the webidl actually lives in our parent dir
|
||||||
test_webidl_files := $(addprefix ../,$(test_webidl_files))
|
test_webidl_files := $(addprefix ../,$(test_webidl_files))
|
||||||
|
# Store the actual locations of our source preprocessed files, so we
|
||||||
|
# can depend on them sanely.
|
||||||
|
source_preprocessed_test_webidl_files := $(addprefix $(srcdir)/,$(preprocessed_test_webidl_files))
|
||||||
|
preprocessed_test_webidl_files := $(addprefix ../,$(preprocessed_test_webidl_files))
|
||||||
|
|
||||||
LOCAL_INCLUDES += \
|
LOCAL_INCLUDES += \
|
||||||
-I$(topsrcdir)/js/xpconnect/src \
|
-I$(topsrcdir)/js/xpconnect/src \
|
||||||
@ -68,11 +72,13 @@ MOCHITEST_FILES := \
|
|||||||
test_exception_messages.html \
|
test_exception_messages.html \
|
||||||
test_bug707564.html \
|
test_bug707564.html \
|
||||||
test_defineProperty.html \
|
test_defineProperty.html \
|
||||||
|
file_document_location_set_via_xray.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
MOCHITEST_CHROME_FILES = \
|
MOCHITEST_CHROME_FILES = \
|
||||||
test_bug775543.html \
|
test_bug775543.html \
|
||||||
test_bug707564-chrome.html \
|
test_bug707564-chrome.html \
|
||||||
|
test_document_location_set_via_xray.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifdef GNU_CC
|
ifdef GNU_CC
|
||||||
@ -87,6 +93,7 @@ $(CPPSRCS): .BindingGen
|
|||||||
|
|
||||||
.BindingGen: $(bindinggen_dependencies) \
|
.BindingGen: $(bindinggen_dependencies) \
|
||||||
$(test_webidl_files) \
|
$(test_webidl_files) \
|
||||||
|
$(source_preprocessed_test_webidl_files) \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
# The export phase in dom/bindings is what actually looks at
|
# The export phase in dom/bindings is what actually looks at
|
||||||
# dependencies and regenerates things as needed, so just go ahead and
|
# dependencies and regenerates things as needed, so just go ahead and
|
||||||
|
@ -502,6 +502,18 @@ public:
|
|||||||
returnValue.SetAsLong() = i;
|
returnValue.SetAsLong() = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
void PassUnion2(const LongOrBoolean& arg);
|
||||||
|
void PassUnion3(JSContext*, const ObjectOrLongOrBoolean& arg);
|
||||||
|
void PassUnion4(const NodeOrLongOrBoolean& arg);
|
||||||
|
void PassUnion5(JSContext*, const ObjectOrBoolean& arg);
|
||||||
|
void PassUnion6(JSContext*, const ObjectOrString& arg);
|
||||||
|
void PassUnion7(JSContext*, const ObjectOrStringOrLong& arg);
|
||||||
|
void PassUnion8(JSContext*, const ObjectOrStringOrBoolean& arg);
|
||||||
|
void PassUnion9(JSContext*, const ObjectOrStringOrLongOrBoolean& arg);
|
||||||
|
void PassUnion10(const EventInitOrLong& arg);
|
||||||
|
void PassUnion11(JSContext*, const CustomEventInitOrLong& arg);
|
||||||
|
#endif
|
||||||
void PassNullableUnion(JSContext*, const Nullable<ObjectOrLong>&);
|
void PassNullableUnion(JSContext*, const Nullable<ObjectOrLong>&);
|
||||||
void PassOptionalUnion(JSContext*, const Optional<ObjectOrLong>&);
|
void PassOptionalUnion(JSContext*, const Optional<ObjectOrLong>&);
|
||||||
void PassOptionalNullableUnion(JSContext*, const Optional<Nullable<ObjectOrLong> >&);
|
void PassOptionalNullableUnion(JSContext*, const Optional<Nullable<ObjectOrLong> >&);
|
||||||
|
@ -440,15 +440,20 @@ interface TestInterface {
|
|||||||
|
|
||||||
// Union types
|
// Union types
|
||||||
void passUnion((object or long) arg);
|
void passUnion((object or long) arg);
|
||||||
// Commented out tests 2-9 to avoid creating all those unused union types
|
// Some union tests are debug-only to avoid creating all those
|
||||||
/* void passUnion2((long or boolean) arg);
|
// unused union types in opt builds.
|
||||||
|
#ifdef DEBUG
|
||||||
|
void passUnion2((long or boolean) arg);
|
||||||
void passUnion3((object or long or boolean) arg);
|
void passUnion3((object or long or boolean) arg);
|
||||||
void passUnion4((Node or long or boolean) arg);
|
void passUnion4((Node or long or boolean) arg);
|
||||||
void passUnion5((object or boolean) arg);
|
void passUnion5((object or boolean) arg);
|
||||||
void passUnion6((object or DOMString) arg);
|
void passUnion6((object or DOMString) arg);
|
||||||
void passUnion7((object or DOMString or long) arg);
|
void passUnion7((object or DOMString or long) arg);
|
||||||
void passUnion8((object or DOMString or boolean) arg);
|
void passUnion8((object or DOMString or boolean) arg);
|
||||||
void passUnion9((object or DOMString or long or boolean) arg); */
|
void passUnion9((object or DOMString or long or boolean) arg);
|
||||||
|
void passUnion10(optional (EventInit or long) arg);
|
||||||
|
void passUnion11(optional (CustomEventInit or long) arg);
|
||||||
|
#endif
|
||||||
void passUnionWithNullable((object? or long) arg);
|
void passUnionWithNullable((object? or long) arg);
|
||||||
void passNullableUnion((object or long)? arg);
|
void passNullableUnion((object or long)? arg);
|
||||||
void passOptionalUnion(optional (object or long) arg);
|
void passOptionalUnion(optional (object or long) arg);
|
||||||
@ -744,6 +749,15 @@ dictionary Dict : ParentDict {
|
|||||||
|
|
||||||
(float or DOMString) floatOrString = "str";
|
(float or DOMString) floatOrString = "str";
|
||||||
(object or long) objectOrLong;
|
(object or long) objectOrLong;
|
||||||
|
#ifdef DEBUG
|
||||||
|
(EventInit or long) eventInitOrLong;
|
||||||
|
// CustomEventInit is useful to test because it needs rooting.
|
||||||
|
(CustomEventInit or long) eventInitOrLong2;
|
||||||
|
(EventInit or long) eventInitOrLongWithDefaultValue = null;
|
||||||
|
(CustomEventInit or long) eventInitOrLongWithDefaultValue2 = null;
|
||||||
|
(EventInit or long) eventInitOrLongWithDefaultValue3 = 5;
|
||||||
|
(CustomEventInit or long) eventInitOrLongWithDefaultValue4 = 5;
|
||||||
|
#endif
|
||||||
|
|
||||||
ArrayBuffer arrayBuffer;
|
ArrayBuffer arrayBuffer;
|
||||||
ArrayBuffer? nullableArrayBuffer;
|
ArrayBuffer? nullableArrayBuffer;
|
||||||
|
@ -336,15 +336,20 @@ interface TestExampleInterface {
|
|||||||
|
|
||||||
// Union types
|
// Union types
|
||||||
void passUnion((object or long) arg);
|
void passUnion((object or long) arg);
|
||||||
// Commented out tests 2-9 to avoid creating all those unused union types
|
// Some union tests are debug-only to avoid creating all those
|
||||||
/* void passUnion2((long or boolean) arg);
|
// unused union types in opt builds.
|
||||||
|
#ifdef DEBUG
|
||||||
|
void passUnion2((long or boolean) arg);
|
||||||
void passUnion3((object or long or boolean) arg);
|
void passUnion3((object or long or boolean) arg);
|
||||||
void passUnion4((Node or long or boolean) arg);
|
void passUnion4((Node or long or boolean) arg);
|
||||||
void passUnion5((object or boolean) arg);
|
void passUnion5((object or boolean) arg);
|
||||||
void passUnion6((object or DOMString) arg);
|
void passUnion6((object or DOMString) arg);
|
||||||
void passUnion7((object or DOMString or long) arg);
|
void passUnion7((object or DOMString or long) arg);
|
||||||
void passUnion8((object or DOMString or boolean) arg);
|
void passUnion8((object or DOMString or boolean) arg);
|
||||||
void passUnion9((object or DOMString or long or boolean) arg); */
|
void passUnion9((object or DOMString or long or boolean) arg);
|
||||||
|
void passUnion10(optional (EventInit or long) arg);
|
||||||
|
void passUnion11(optional (CustomEventInit or long) arg);
|
||||||
|
#endif
|
||||||
void passUnionWithNullable((object? or long) arg);
|
void passUnionWithNullable((object? or long) arg);
|
||||||
void passNullableUnion((object or long)? arg);
|
void passNullableUnion((object or long)? arg);
|
||||||
void passOptionalUnion(optional (object or long) arg);
|
void passOptionalUnion(optional (object or long) arg);
|
||||||
|
@ -358,15 +358,20 @@ interface TestJSImplInterface {
|
|||||||
|
|
||||||
// Union types
|
// Union types
|
||||||
void passUnion((object or long) arg);
|
void passUnion((object or long) arg);
|
||||||
// Commented out tests 2-9 to avoid creating all those unused union types
|
// Some union tests are debug-only to avoid creating all those
|
||||||
/* void passUnion2((long or boolean) arg);
|
// unused union types in opt builds.
|
||||||
|
#ifdef DEBUG
|
||||||
|
void passUnion2((long or boolean) arg);
|
||||||
void passUnion3((object or long or boolean) arg);
|
void passUnion3((object or long or boolean) arg);
|
||||||
void passUnion4((Node or long or boolean) arg);
|
void passUnion4((Node or long or boolean) arg);
|
||||||
void passUnion5((object or boolean) arg);
|
void passUnion5((object or boolean) arg);
|
||||||
void passUnion6((object or DOMString) arg);
|
void passUnion6((object or DOMString) arg);
|
||||||
void passUnion7((object or DOMString or long) arg);
|
void passUnion7((object or DOMString or long) arg);
|
||||||
void passUnion8((object or DOMString or boolean) arg);
|
void passUnion8((object or DOMString or boolean) arg);
|
||||||
void passUnion9((object or DOMString or long or boolean) arg); */
|
void passUnion9((object or DOMString or long or boolean) arg);
|
||||||
|
void passUnion10(optional (EventInit or long) arg);
|
||||||
|
void passUnion11(optional (CustomEventInit or long) arg);
|
||||||
|
#endif
|
||||||
void passUnionWithNullable((object? or long) arg);
|
void passUnionWithNullable((object? or long) arg);
|
||||||
// FIXME: Bug 863948 Nullable unions not supported yet
|
// FIXME: Bug 863948 Nullable unions not supported yet
|
||||||
// void passNullableUnion((object or long)? arg);
|
// void passNullableUnion((object or long)? arg);
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
document.x = 5;
|
||||||
|
</script>
|
||||||
|
</body>
|
@ -8,6 +8,7 @@ MODULE = 'dom'
|
|||||||
|
|
||||||
CPP_SOURCES += [
|
CPP_SOURCES += [
|
||||||
'$(subst .webidl,Binding.cpp,$(test_webidl_files))',
|
'$(subst .webidl,Binding.cpp,$(test_webidl_files))',
|
||||||
|
'$(subst .webidl,Binding.cpp,$(preprocessed_test_webidl_files))',
|
||||||
]
|
]
|
||||||
|
|
||||||
LIBXUL_LIBRARY = True
|
LIBXUL_LIBRARY = True
|
||||||
|
49
dom/bindings/test/test_document_location_set_via_xray.html
Normal file
49
dom/bindings/test/test_document_location_set_via_xray.html
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=905493
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 905493</title>
|
||||||
|
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=905493">Mozilla Bug 905493</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
<iframe id="t" src="http://example.org/tests/dom/bindings/test/file_document_location_set_via_xray.html"></iframe>
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
/** Test for Bug 905493 **/
|
||||||
|
|
||||||
|
function test()
|
||||||
|
{
|
||||||
|
var doc = document.getElementById("t").contentWindow.document;
|
||||||
|
ok(!("x" in doc), "Should have an Xray here");
|
||||||
|
is(doc.x, undefined, "Really should have an Xray here");
|
||||||
|
is(doc.wrappedJSObject.x, 5, "And wrapping the right thing");
|
||||||
|
document.getElementById("t").onload = function() {
|
||||||
|
ok(true, "Load happened");
|
||||||
|
SimpleTest.finish();
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
// Test the forwarding location setter
|
||||||
|
doc.location = "chrome://mochikit/content/tests/SimpleTest/test.css";
|
||||||
|
} catch (e) {
|
||||||
|
// Load failed
|
||||||
|
ok(false, "Load failed");
|
||||||
|
SimpleTest.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleTest.waitForExplicitFinish();
|
||||||
|
addLoadEvent(test);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -163,6 +163,12 @@ parent:
|
|||||||
*/
|
*/
|
||||||
sync EndIMEComposition(bool cancel) returns (nsString composition);
|
sync EndIMEComposition(bool cancel) returns (nsString composition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request that the parent process move focus to the browser's frame. If
|
||||||
|
* canRaise is true, the window can be raised if it is inactive.
|
||||||
|
*/
|
||||||
|
RequestFocus(bool canRaise);
|
||||||
|
|
||||||
sync GetInputContext() returns (int32_t IMEEnabled, int32_t IMEOpen,
|
sync GetInputContext() returns (int32_t IMEEnabled, int32_t IMEOpen,
|
||||||
intptr_t NativeIMEContext);
|
intptr_t NativeIMEContext);
|
||||||
|
|
||||||
|
@ -895,6 +895,28 @@ TabParent::RecvNotifyIMETextHint(const nsString& aText)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TabParent::RecvRequestFocus(const bool& aCanRaise)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIFocusManager> fm = nsFocusManager::GetFocusManager();
|
||||||
|
if (!fm) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIContent> content = do_QueryInterface(mFrameElement);
|
||||||
|
if (!content || !content->OwnerDoc()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t flags = nsIFocusManager::FLAG_NOSCROLL;
|
||||||
|
if (aCanRaise)
|
||||||
|
flags |= nsIFocusManager::FLAG_RAISE;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMElement> node = do_QueryInterface(mFrameElement);
|
||||||
|
fm->SetFocus(node, flags);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to answer query event using cached text.
|
* Try to answer query event using cached text.
|
||||||
*
|
*
|
||||||
|
@ -145,6 +145,7 @@ public:
|
|||||||
const nsString& aActionHint,
|
const nsString& aActionHint,
|
||||||
const int32_t& aCause,
|
const int32_t& aCause,
|
||||||
const int32_t& aFocusChange);
|
const int32_t& aFocusChange);
|
||||||
|
virtual bool RecvRequestFocus(const bool& aCanRaise);
|
||||||
virtual bool RecvSetCursor(const uint32_t& aValue);
|
virtual bool RecvSetCursor(const uint32_t& aValue);
|
||||||
virtual bool RecvSetBackgroundColor(const nscolor& aValue);
|
virtual bool RecvSetBackgroundColor(const nscolor& aValue);
|
||||||
virtual bool RecvSetStatus(const uint32_t& aType, const nsString& aStatus);
|
virtual bool RecvSetStatus(const uint32_t& aType, const nsString& aStatus);
|
||||||
|
@ -165,6 +165,7 @@ function RTCPeerConnection() {
|
|||||||
this._pendingType = null;
|
this._pendingType = null;
|
||||||
this._localType = null;
|
this._localType = null;
|
||||||
this._remoteType = null;
|
this._remoteType = null;
|
||||||
|
this._trickleIce = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Everytime we get a request from content, we put it in the queue. If
|
* Everytime we get a request from content, we put it in the queue. If
|
||||||
@ -193,6 +194,7 @@ RTCPeerConnection.prototype = {
|
|||||||
init: function(win) { this._win = win; },
|
init: function(win) { this._win = win; },
|
||||||
|
|
||||||
__init: function(rtcConfig) {
|
__init: function(rtcConfig) {
|
||||||
|
this._trickleIce = Services.prefs.getBoolPref("media.peerconnection.trickle_ice");
|
||||||
if (!rtcConfig.iceServers ||
|
if (!rtcConfig.iceServers ||
|
||||||
!Services.prefs.getBoolPref("media.peerconnection.use_document_iceservers")) {
|
!Services.prefs.getBoolPref("media.peerconnection.use_document_iceservers")) {
|
||||||
rtcConfig = {iceServers:
|
rtcConfig = {iceServers:
|
||||||
@ -224,11 +226,11 @@ RTCPeerConnection.prototype = {
|
|||||||
// Add a reference to the PeerConnection to global list (before init).
|
// Add a reference to the PeerConnection to global list (before init).
|
||||||
_globalPCList.addPC(this);
|
_globalPCList.addPC(this);
|
||||||
|
|
||||||
// Nothing starts until ICE gathering completes.
|
|
||||||
this._queueOrRun({
|
this._queueOrRun({
|
||||||
func: this._getPC().initialize,
|
func: this._getPC().initialize,
|
||||||
args: [this._observer, this._win, rtcConfig, Services.tm.currentThread],
|
args: [this._observer, this._win, rtcConfig, Services.tm.currentThread],
|
||||||
wait: true
|
// If not trickling, suppress start.
|
||||||
|
wait: !this._trickleIce
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -894,13 +896,11 @@ PeerConnectionObserver.prototype = {
|
|||||||
this._dompc._pendingType = null;
|
this._dompc._pendingType = null;
|
||||||
this.callCB(this._dompc._onSetLocalDescriptionSuccess);
|
this.callCB(this._dompc._onSetLocalDescriptionSuccess);
|
||||||
|
|
||||||
// Until we support generating trickle ICE candidates,
|
if (this._iceGatheringState == "complete") {
|
||||||
// we go ahead and trigger a call of onicecandidate here.
|
// If we are not trickling or we completed gathering prior
|
||||||
// This is to provide some level of compatibility with
|
// to setLocal, then trigger a call of onicecandidate here.
|
||||||
// scripts that expect this behavior (which is how Chrome
|
this.foundIceCandidate(null);
|
||||||
// signals that no further trickle candidates will be sent).
|
}
|
||||||
// TODO: This needs to be removed when Bug 842459 lands.
|
|
||||||
this.foundIceCandidate(null);
|
|
||||||
|
|
||||||
this._dompc._executeNext();
|
this._dompc._executeNext();
|
||||||
},
|
},
|
||||||
@ -938,6 +938,16 @@ PeerConnectionObserver.prototype = {
|
|||||||
this._dompc._executeNext();
|
this._dompc._executeNext();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onIceCandidate: function(level, mid, candidate) {
|
||||||
|
this.foundIceCandidate(new this._dompc._win.mozRTCIceCandidate(
|
||||||
|
{
|
||||||
|
candidate: candidate,
|
||||||
|
sdpMid: mid,
|
||||||
|
sdpMLineIndex: level
|
||||||
|
}
|
||||||
|
));
|
||||||
|
},
|
||||||
|
|
||||||
handleIceStateChanges: function(iceState) {
|
handleIceStateChanges: function(iceState) {
|
||||||
var histogram = Services.telemetry.getHistogramById("WEBRTC_ICE_SUCCESS_RATE");
|
var histogram = Services.telemetry.getHistogramById("WEBRTC_ICE_SUCCESS_RATE");
|
||||||
switch (iceState) {
|
switch (iceState) {
|
||||||
@ -945,8 +955,18 @@ PeerConnectionObserver.prototype = {
|
|||||||
this._dompc.changeIceConnectionState("new");
|
this._dompc.changeIceConnectionState("new");
|
||||||
this.callCB(this._dompc.ongatheringchange, "complete");
|
this.callCB(this._dompc.ongatheringchange, "complete");
|
||||||
this.callCB(this._onicechange, "starting");
|
this.callCB(this._onicechange, "starting");
|
||||||
// Now that the PC is ready to go, execute any pending operations.
|
|
||||||
this._dompc._executeNext();
|
if (!this._dompc._trickleIce) {
|
||||||
|
// If we are not trickling, then the queue is in a pending state
|
||||||
|
// waiting for ICE gathering and executeNext frees it
|
||||||
|
this._dompc._executeNext();
|
||||||
|
}
|
||||||
|
else if (this.localDescription) {
|
||||||
|
// If we are trickling but we have already done setLocal,
|
||||||
|
// then we need to send a final foundIceCandidate(null) to indicate
|
||||||
|
// that we are done gathering.
|
||||||
|
this.foundIceCandidate(null);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case Ci.IPeerConnection.kIceChecking:
|
case Ci.IPeerConnection.kIceChecking:
|
||||||
this._dompc.changeIceConnectionState("checking");
|
this._dompc.changeIceConnectionState("checking");
|
||||||
@ -1009,9 +1029,13 @@ PeerConnectionObserver.prototype = {
|
|||||||
{ stream: stream }));
|
{ stream: stream }));
|
||||||
},
|
},
|
||||||
|
|
||||||
foundIceCandidate: function(c) {
|
foundIceCandidate: function(cand, mid, line) {
|
||||||
this.dispatchEvent(new this._dompc._win.RTCPeerConnectionIceEvent("icecandidate",
|
this.dispatchEvent(new this._dompc._win.RTCPeerConnectionIceEvent("icecandidate",
|
||||||
{ candidate: c }));
|
{
|
||||||
|
candidate: cand,
|
||||||
|
sdpMid: mid,
|
||||||
|
sdpMLineIndex: line
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
notifyDataChannel: function(channel) {
|
notifyDataChannel: function(channel) {
|
||||||
|
@ -24,7 +24,7 @@ interface IPeerConnectionManager : nsISupports
|
|||||||
*
|
*
|
||||||
* See media/webrtc/signaling/include/PeerConnectionImpl.h
|
* See media/webrtc/signaling/include/PeerConnectionImpl.h
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(cf9152f0-c9a8-4093-9435-1daa056e0177)]
|
[scriptable, uuid(896dc16a-05d6-45e4-bdbf-aba57123ed3e)]
|
||||||
interface IPeerConnectionObserver : nsISupports
|
interface IPeerConnectionObserver : nsISupports
|
||||||
{
|
{
|
||||||
/* Constants */
|
/* Constants */
|
||||||
@ -45,6 +45,7 @@ interface IPeerConnectionObserver : nsISupports
|
|||||||
void onSetRemoteDescriptionError(in unsigned long name, in string message);
|
void onSetRemoteDescriptionError(in unsigned long name, in string message);
|
||||||
void onAddIceCandidateSuccess();
|
void onAddIceCandidateSuccess();
|
||||||
void onAddIceCandidateError(in unsigned long name, in string message);
|
void onAddIceCandidateError(in unsigned long name, in string message);
|
||||||
|
void onIceCandidate(in unsigned short level, in string mid, in string candidate);
|
||||||
|
|
||||||
/* Data channel callbacks */
|
/* Data channel callbacks */
|
||||||
void notifyDataChannel(in nsIDOMDataChannel channel);
|
void notifyDataChannel(in nsIDOMDataChannel channel);
|
||||||
@ -59,13 +60,6 @@ interface IPeerConnectionObserver : nsISupports
|
|||||||
void onRemoveStream();
|
void onRemoveStream();
|
||||||
void onAddTrack();
|
void onAddTrack();
|
||||||
void onRemoveTrack();
|
void onRemoveTrack();
|
||||||
|
|
||||||
/* When SDP is parsed and a candidate line is found this method is called.
|
|
||||||
* It should hook back into the media transport to notify it of ICE candidates
|
|
||||||
* listed in the SDP PeerConnectionImpl does not parse ICE candidates, just
|
|
||||||
* pulls them out of the SDP.
|
|
||||||
*/
|
|
||||||
void foundIceCandidate(in string candidate);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[scriptable, uuid(930dce8b-7c5e-4393-b8c0-cb3a928f68bd)]
|
[scriptable, uuid(930dce8b-7c5e-4393-b8c0-cb3a928f68bd)]
|
||||||
|
@ -49,6 +49,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
|
|||||||
ok(xhr, "'XMLHttpRequest.prototype' in a sandbox should return the XMLHttpRequest interface prototype object");
|
ok(xhr, "'XMLHttpRequest.prototype' in a sandbox should return the XMLHttpRequest interface prototype object");
|
||||||
ok(isXrayWrapper(xhr), "Getting an interface prototype object on an Xray wrapper should return an Xray wrapper");
|
ok(isXrayWrapper(xhr), "Getting an interface prototype object on an Xray wrapper should return an Xray wrapper");
|
||||||
ok(isXrayWrapper(xhr.constructor), "Getting the constructor property on an Xray wrapper of an interface prototype object should return an Xray wrapper");
|
ok(isXrayWrapper(xhr.constructor), "Getting the constructor property on an Xray wrapper of an interface prototype object should return an Xray wrapper");
|
||||||
|
isnot(Object.getOwnPropertyDescriptor(xhr, "send"), undefined,
|
||||||
|
"We should claim to have a send() method");
|
||||||
|
isnot(Object.keys(xhr).indexOf("responseType"), -1,
|
||||||
|
"We should claim to have a responseType property");
|
||||||
|
isnot(Object.getOwnPropertyNames(xhr).indexOf("open"), -1,
|
||||||
|
"We should claim to have an open() method");
|
||||||
|
isnot(Object.getOwnPropertyDescriptor(xhr, "constructor"), undefined,
|
||||||
|
"We should claim to have a 'constructor' property");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ok(false, "'XMLHttpRequest.prototype' shouldn't throw in a sandbox");
|
ok(false, "'XMLHttpRequest.prototype' shouldn't throw in a sandbox");
|
||||||
}
|
}
|
||||||
@ -87,6 +95,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=741267
|
|||||||
var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
|
var xhr = Components.utils.evalInSandbox("XMLHttpRequest", sandbox);
|
||||||
is(xhr, "[object XrayWrapper " + XMLHttpRequest + "]", "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object");
|
is(xhr, "[object XrayWrapper " + XMLHttpRequest + "]", "'XMLHttpRequest' in a sandbox should return the XMLHttpRequest interface object");
|
||||||
ok(isXrayWrapper(xhr.prototype), "Getting the prototype property on an Xray wrapper of an interface object should return an Xray wrapper");
|
ok(isXrayWrapper(xhr.prototype), "Getting the prototype property on an Xray wrapper of an interface object should return an Xray wrapper");
|
||||||
|
isnot(Object.getOwnPropertyDescriptor(xhr, "UNSENT"), undefined,
|
||||||
|
"We should claim to have an UNSENT constant");
|
||||||
|
isnot(Object.keys(xhr).indexOf("OPENED"), -1,
|
||||||
|
"We should claim to have an OPENED constant");
|
||||||
|
isnot(Object.getOwnPropertyNames(xhr).indexOf("DONE"), -1,
|
||||||
|
"We should claim to have a DONE constant");
|
||||||
|
isnot(Object.getOwnPropertyDescriptor(xhr, "prototype"), undefined,
|
||||||
|
"We should claim to have 'prototype' property");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ok(false, "'XMLHttpRequest' shouldn't throw in a sandbox");
|
ok(false, "'XMLHttpRequest' shouldn't throw in a sandbox");
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
// Dummy bindings that we need to force generation of things that
|
// Dummy bindings that we need to force generation of things that
|
||||||
// aren't actually referenced anywhere in IDL yet but are used in C++.
|
// aren't actually referenced anywhere in IDL yet but are used in C++.
|
||||||
|
|
||||||
interface DummyInterface {
|
[Global]
|
||||||
|
interface DummyInterface : EventTarget {
|
||||||
readonly attribute OnErrorEventHandlerNonNull onErrorEventHandler;
|
readonly attribute OnErrorEventHandlerNonNull onErrorEventHandler;
|
||||||
FilePropertyBag fileBag();
|
FilePropertyBag fileBag();
|
||||||
InspectorRGBTriple rgbTriple();
|
InspectorRGBTriple rgbTriple();
|
||||||
|
@ -522,13 +522,15 @@ if CONFIG['MOZ_B2G_FM']:
|
|||||||
|
|
||||||
if CONFIG['ENABLE_TESTS']:
|
if CONFIG['ENABLE_TESTS']:
|
||||||
TEST_WEBIDL_FILES += [
|
TEST_WEBIDL_FILES += [
|
||||||
'TestCodeGen.webidl',
|
|
||||||
'TestDictionary.webidl',
|
'TestDictionary.webidl',
|
||||||
'TestExampleGen.webidl',
|
|
||||||
'TestJSImplGen.webidl',
|
|
||||||
'TestJSImplInheritanceGen.webidl',
|
'TestJSImplInheritanceGen.webidl',
|
||||||
'TestTypedef.webidl',
|
'TestTypedef.webidl',
|
||||||
]
|
]
|
||||||
|
PREPROCESSED_TEST_WEBIDL_FILES += [
|
||||||
|
'TestCodeGen.webidl',
|
||||||
|
'TestExampleGen.webidl',
|
||||||
|
'TestJSImplGen.webidl',
|
||||||
|
]
|
||||||
|
|
||||||
if CONFIG['MOZ_B2G']:
|
if CONFIG['MOZ_B2G']:
|
||||||
WEBIDL_FILES += [
|
WEBIDL_FILES += [
|
||||||
|
@ -344,6 +344,7 @@ LayerManagerComposite::Render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (actualBounds.IsEmpty()) {
|
if (actualBounds.IsEmpty()) {
|
||||||
|
mCompositor->GetWidget()->PostRender(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,6 +370,8 @@ LayerManagerComposite::Render()
|
|||||||
PROFILER_LABEL("LayerManagerComposite", "EndFrame");
|
PROFILER_LABEL("LayerManagerComposite", "EndFrame");
|
||||||
mCompositor->EndFrame();
|
mCompositor->EndFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCompositor->GetWidget()->PostRender(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
#ifndef js_MemoryMetrics_h
|
#ifndef js_MemoryMetrics_h
|
||||||
#define js_MemoryMetrics_h
|
#define js_MemoryMetrics_h
|
||||||
|
|
||||||
// These declarations are not within jsapi.h because they are highly likely to
|
// These declarations are highly likely to change in the future. Depend on them
|
||||||
// change in the future. Depend on them at your own risk.
|
// at your own risk.
|
||||||
|
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/NullPtr.h"
|
#include "mozilla/NullPtr.h"
|
||||||
@ -23,7 +23,7 @@
|
|||||||
#include "js/Utility.h"
|
#include "js/Utility.h"
|
||||||
#include "js/Vector.h"
|
#include "js/Vector.h"
|
||||||
|
|
||||||
class nsISupports; // This is needed for ObjectPrivateVisitor.
|
class nsISupports; // Needed for ObjectPrivateVisitor.
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
@ -46,49 +46,65 @@ struct InefficientNonFlatteningStringHashPolicy
|
|||||||
static bool match(const JSString *const &k, const Lookup &l);
|
static bool match(const JSString *const &k, const Lookup &l);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This file features many classes with numerous size_t fields, and each such
|
||||||
|
// class has one or more methods that need to operate on all of these fields.
|
||||||
|
// Writing these individually is error-prone -- it's easy to add a new field
|
||||||
|
// without updating all the required methods. So we define a single macro list
|
||||||
|
// in each class to name the fields (and notable characteristics of them), and
|
||||||
|
// then use the following macros to transform those lists into the required
|
||||||
|
// methods.
|
||||||
|
//
|
||||||
|
// In some classes, one or more of the macro arguments aren't used. We use '_'
|
||||||
|
// for those.
|
||||||
|
//
|
||||||
|
#define DECL_SIZE(gc, mSize) size_t mSize;
|
||||||
|
#define ZERO_SIZE(gc, mSize) mSize(0),
|
||||||
|
#define COPY_OTHER_SIZE(gc, mSize) mSize(other.mSize),
|
||||||
|
#define ADD_OTHER_SIZE(gc, mSize) mSize += other.mSize;
|
||||||
|
#define ADD_SIZE_TO_N_IF_LIVE_GC_THING(gc, mSize) n += (gc == js::IsLiveGCThing) ? mSize : 0;
|
||||||
|
|
||||||
|
// Used to annotate which size_t fields measure live GC things and which don't.
|
||||||
|
enum {
|
||||||
|
IsLiveGCThing,
|
||||||
|
NotLiveGCThing
|
||||||
|
};
|
||||||
|
|
||||||
struct ZoneStatsPod
|
struct ZoneStatsPod
|
||||||
{
|
{
|
||||||
ZoneStatsPod() {
|
#define FOR_EACH_SIZE(macro) \
|
||||||
mozilla::PodZero(this);
|
macro(NotLiveGCThing, gcHeapArenaAdmin) \
|
||||||
}
|
macro(NotLiveGCThing, gcHeapUnusedGcThings) \
|
||||||
|
macro(IsLiveGCThing, gcHeapStringsNormal) \
|
||||||
|
macro(IsLiveGCThing, gcHeapStringsShort) \
|
||||||
|
macro(IsLiveGCThing, gcHeapLazyScripts) \
|
||||||
|
macro(IsLiveGCThing, gcHeapTypeObjects) \
|
||||||
|
macro(IsLiveGCThing, gcHeapIonCodes) \
|
||||||
|
macro(NotLiveGCThing, stringCharsNonNotable) \
|
||||||
|
macro(NotLiveGCThing, lazyScripts) \
|
||||||
|
macro(NotLiveGCThing, typeObjects) \
|
||||||
|
macro(NotLiveGCThing, typePool)
|
||||||
|
|
||||||
|
ZoneStatsPod()
|
||||||
|
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
|
extra()
|
||||||
|
{}
|
||||||
|
|
||||||
void add(const ZoneStatsPod &other) {
|
void add(const ZoneStatsPod &other) {
|
||||||
#define ADD(x) this->x += other.x
|
FOR_EACH_SIZE(ADD_OTHER_SIZE)
|
||||||
|
// Do nothing with |extra|.
|
||||||
ADD(gcHeapArenaAdmin);
|
|
||||||
ADD(gcHeapUnusedGcThings);
|
|
||||||
|
|
||||||
ADD(gcHeapStringsNormal);
|
|
||||||
ADD(gcHeapStringsShort);
|
|
||||||
ADD(gcHeapLazyScripts);
|
|
||||||
ADD(gcHeapTypeObjects);
|
|
||||||
ADD(gcHeapIonCodes);
|
|
||||||
|
|
||||||
ADD(stringCharsNonNotable);
|
|
||||||
ADD(lazyScripts);
|
|
||||||
ADD(typeObjects);
|
|
||||||
ADD(typePool);
|
|
||||||
|
|
||||||
#undef ADD
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This field can be used by embedders.
|
size_t sizeOfLiveGCThings() const {
|
||||||
void *extra;
|
size_t n = 0;
|
||||||
|
FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
|
||||||
|
// Do nothing with |extra|.
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
size_t gcHeapArenaAdmin;
|
FOR_EACH_SIZE(DECL_SIZE)
|
||||||
size_t gcHeapUnusedGcThings;
|
void *extra; // This field can be used by embedders.
|
||||||
|
|
||||||
size_t gcHeapStringsNormal;
|
#undef FOR_EACH_SIZE
|
||||||
size_t gcHeapStringsShort;
|
|
||||||
|
|
||||||
size_t gcHeapLazyScripts;
|
|
||||||
size_t gcHeapTypeObjects;
|
|
||||||
size_t gcHeapIonCodes;
|
|
||||||
|
|
||||||
size_t stringCharsNonNotable;
|
|
||||||
size_t lazyScripts;
|
|
||||||
size_t typeObjects;
|
|
||||||
size_t typePool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
@ -98,71 +114,92 @@ namespace JS {
|
|||||||
// Data for tracking memory usage of things hanging off objects.
|
// Data for tracking memory usage of things hanging off objects.
|
||||||
struct ObjectsExtraSizes
|
struct ObjectsExtraSizes
|
||||||
{
|
{
|
||||||
size_t slots;
|
#define FOR_EACH_SIZE(macro) \
|
||||||
size_t elementsNonAsmJS;
|
macro(js::NotLiveGCThing, slots) \
|
||||||
size_t elementsAsmJSHeap;
|
macro(js::NotLiveGCThing, elementsNonAsmJS) \
|
||||||
size_t elementsAsmJSNonHeap;
|
macro(js::NotLiveGCThing, elementsAsmJSHeap) \
|
||||||
size_t asmJSModuleCode;
|
macro(js::NotLiveGCThing, elementsAsmJSNonHeap) \
|
||||||
size_t asmJSModuleData;
|
macro(js::NotLiveGCThing, asmJSModuleCode) \
|
||||||
size_t argumentsData;
|
macro(js::NotLiveGCThing, asmJSModuleData) \
|
||||||
size_t regExpStatics;
|
macro(js::NotLiveGCThing, argumentsData) \
|
||||||
size_t propertyIteratorData;
|
macro(js::NotLiveGCThing, regExpStatics) \
|
||||||
size_t ctypesData;
|
macro(js::NotLiveGCThing, propertyIteratorData) \
|
||||||
size_t private_; // The '_' suffix is required because |private| is a keyword.
|
macro(js::NotLiveGCThing, ctypesData)
|
||||||
// Note that this field is measured separately from the others.
|
|
||||||
|
|
||||||
ObjectsExtraSizes() { memset(this, 0, sizeof(ObjectsExtraSizes)); }
|
ObjectsExtraSizes()
|
||||||
|
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
|
dummy()
|
||||||
|
{}
|
||||||
|
|
||||||
void add(ObjectsExtraSizes &sizes) {
|
void add(const ObjectsExtraSizes &other) {
|
||||||
this->slots += sizes.slots;
|
FOR_EACH_SIZE(ADD_OTHER_SIZE)
|
||||||
this->elementsNonAsmJS += sizes.elementsNonAsmJS;
|
|
||||||
this->elementsAsmJSHeap += sizes.elementsAsmJSHeap;
|
|
||||||
this->elementsAsmJSNonHeap += sizes.elementsAsmJSNonHeap;
|
|
||||||
this->asmJSModuleCode += sizes.asmJSModuleCode;
|
|
||||||
this->asmJSModuleData += sizes.asmJSModuleData;
|
|
||||||
this->argumentsData += sizes.argumentsData;
|
|
||||||
this->regExpStatics += sizes.regExpStatics;
|
|
||||||
this->propertyIteratorData += sizes.propertyIteratorData;
|
|
||||||
this->ctypesData += sizes.ctypesData;
|
|
||||||
this->private_ += sizes.private_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t sizeOfLiveGCThings() const {
|
||||||
|
size_t n = 0;
|
||||||
|
FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOR_EACH_SIZE(DECL_SIZE)
|
||||||
|
int dummy; // present just to absorb the trailing comma from FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
|
|
||||||
|
#undef FOR_EACH_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
// Data for tracking analysis/inference memory usage.
|
// Data for tracking analysis/inference memory usage.
|
||||||
struct TypeInferenceSizes
|
struct TypeInferenceSizes
|
||||||
{
|
{
|
||||||
size_t typeScripts;
|
#define FOR_EACH_SIZE(macro) \
|
||||||
size_t typeResults;
|
macro(js::NotLiveGCThing, typeScripts) \
|
||||||
size_t pendingArrays;
|
macro(js::NotLiveGCThing, typeResults) \
|
||||||
size_t allocationSiteTables;
|
macro(js::NotLiveGCThing, pendingArrays) \
|
||||||
size_t arrayTypeTables;
|
macro(js::NotLiveGCThing, allocationSiteTables) \
|
||||||
size_t objectTypeTables;
|
macro(js::NotLiveGCThing, arrayTypeTables) \
|
||||||
|
macro(js::NotLiveGCThing, objectTypeTables)
|
||||||
|
|
||||||
TypeInferenceSizes() { memset(this, 0, sizeof(TypeInferenceSizes)); }
|
TypeInferenceSizes()
|
||||||
|
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
|
dummy()
|
||||||
|
{}
|
||||||
|
|
||||||
void add(TypeInferenceSizes &sizes) {
|
void add(const TypeInferenceSizes &other) {
|
||||||
this->typeScripts += sizes.typeScripts;
|
FOR_EACH_SIZE(ADD_OTHER_SIZE)
|
||||||
this->typeResults += sizes.typeResults;
|
|
||||||
this->pendingArrays += sizes.pendingArrays;
|
|
||||||
this->allocationSiteTables += sizes.allocationSiteTables;
|
|
||||||
this->arrayTypeTables += sizes.arrayTypeTables;
|
|
||||||
this->objectTypeTables += sizes.objectTypeTables;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t sizeOfLiveGCThings() const {
|
||||||
|
size_t n = 0;
|
||||||
|
FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
FOR_EACH_SIZE(DECL_SIZE)
|
||||||
|
int dummy; // present just to absorb the trailing comma from FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
|
|
||||||
|
#undef FOR_EACH_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
// Data for tracking JIT-code memory usage.
|
// Data for tracking JIT-code memory usage.
|
||||||
struct CodeSizes
|
struct CodeSizes
|
||||||
{
|
{
|
||||||
size_t ion;
|
#define FOR_EACH_SIZE(macro) \
|
||||||
size_t baseline;
|
macro(_, ion) \
|
||||||
size_t regexp;
|
macro(_, baseline) \
|
||||||
size_t other;
|
macro(_, regexp) \
|
||||||
size_t unused;
|
macro(_, other) \
|
||||||
|
macro(_, unused)
|
||||||
|
|
||||||
CodeSizes() { memset(this, 0, sizeof(CodeSizes)); }
|
CodeSizes()
|
||||||
|
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
|
dummy()
|
||||||
|
{}
|
||||||
|
|
||||||
|
FOR_EACH_SIZE(DECL_SIZE)
|
||||||
|
int dummy; // present just to absorb the trailing comma from FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
|
|
||||||
|
#undef FOR_EACH_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// This class holds information about the memory taken up by identical copies of
|
// This class holds information about the memory taken up by identical copies of
|
||||||
// a particular string. Multiple JSStrings may have their sizes aggregated
|
// a particular string. Multiple JSStrings may have their sizes aggregated
|
||||||
// together into one StringInfo object.
|
// together into one StringInfo object.
|
||||||
@ -247,25 +284,32 @@ struct NotableStringInfo : public StringInfo
|
|||||||
char *buffer;
|
char *buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
// These measurements relate directly to the JSRuntime, and not to
|
// These measurements relate directly to the JSRuntime, and not to zones and
|
||||||
// compartments within it.
|
// compartments within it.
|
||||||
struct RuntimeSizes
|
struct RuntimeSizes
|
||||||
{
|
{
|
||||||
RuntimeSizes() { memset(this, 0, sizeof(RuntimeSizes)); }
|
#define FOR_EACH_SIZE(macro) \
|
||||||
|
macro(_, object) \
|
||||||
|
macro(_, atomsTable) \
|
||||||
|
macro(_, contexts) \
|
||||||
|
macro(_, dtoa) \
|
||||||
|
macro(_, temporary) \
|
||||||
|
macro(_, regexpData) \
|
||||||
|
macro(_, interpreterStack) \
|
||||||
|
macro(_, gcMarker) \
|
||||||
|
macro(_, mathCache) \
|
||||||
|
macro(_, scriptData) \
|
||||||
|
macro(_, scriptSources)
|
||||||
|
|
||||||
size_t object;
|
RuntimeSizes()
|
||||||
size_t atomsTable;
|
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
size_t contexts;
|
code()
|
||||||
size_t dtoa;
|
{}
|
||||||
size_t temporary;
|
|
||||||
size_t regexpData;
|
|
||||||
size_t interpreterStack;
|
|
||||||
size_t gcMarker;
|
|
||||||
size_t mathCache;
|
|
||||||
size_t scriptData;
|
|
||||||
size_t scriptSources;
|
|
||||||
|
|
||||||
|
FOR_EACH_SIZE(DECL_SIZE)
|
||||||
CodeSizes code;
|
CodeSizes code;
|
||||||
|
|
||||||
|
#undef FOR_EACH_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZoneStats : js::ZoneStatsPod
|
struct ZoneStats : js::ZoneStatsPod
|
||||||
@ -310,156 +354,88 @@ struct ZoneStats : js::ZoneStatsPod
|
|||||||
|
|
||||||
StringsHashMap strings;
|
StringsHashMap strings;
|
||||||
js::Vector<NotableStringInfo, 0, js::SystemAllocPolicy> notableStrings;
|
js::Vector<NotableStringInfo, 0, js::SystemAllocPolicy> notableStrings;
|
||||||
|
|
||||||
// The size of all the live things in the GC heap that don't belong to any
|
|
||||||
// compartment.
|
|
||||||
size_t GCHeapThingsSize();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CompartmentStats
|
struct CompartmentStats
|
||||||
{
|
{
|
||||||
|
#define FOR_EACH_SIZE(macro) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapObjectsOrdinary) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapObjectsFunction) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapObjectsDenseArray) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapObjectsSlowArray) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapObjectsCrossCompartmentWrapper) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapShapesTreeGlobalParented) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapShapesTreeNonGlobalParented) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapShapesDict) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapShapesBase) \
|
||||||
|
macro(js::IsLiveGCThing, gcHeapScripts) \
|
||||||
|
macro(js::NotLiveGCThing, objectsPrivate) \
|
||||||
|
macro(js::NotLiveGCThing, shapesExtraTreeTables) \
|
||||||
|
macro(js::NotLiveGCThing, shapesExtraDictTables) \
|
||||||
|
macro(js::NotLiveGCThing, shapesExtraTreeShapeKids) \
|
||||||
|
macro(js::NotLiveGCThing, shapesCompartmentTables) \
|
||||||
|
macro(js::NotLiveGCThing, scriptData) \
|
||||||
|
macro(js::NotLiveGCThing, baselineData) \
|
||||||
|
macro(js::NotLiveGCThing, baselineStubsFallback) \
|
||||||
|
macro(js::NotLiveGCThing, baselineStubsOptimized) \
|
||||||
|
macro(js::NotLiveGCThing, ionData) \
|
||||||
|
macro(js::NotLiveGCThing, compartmentObject) \
|
||||||
|
macro(js::NotLiveGCThing, crossCompartmentWrappersTable) \
|
||||||
|
macro(js::NotLiveGCThing, regexpCompartment) \
|
||||||
|
macro(js::NotLiveGCThing, debuggeesSet) \
|
||||||
|
|
||||||
CompartmentStats()
|
CompartmentStats()
|
||||||
: extra(nullptr),
|
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
gcHeapObjectsOrdinary(0),
|
|
||||||
gcHeapObjectsFunction(0),
|
|
||||||
gcHeapObjectsDenseArray(0),
|
|
||||||
gcHeapObjectsSlowArray(0),
|
|
||||||
gcHeapObjectsCrossCompartmentWrapper(0),
|
|
||||||
gcHeapShapesTreeGlobalParented(0),
|
|
||||||
gcHeapShapesTreeNonGlobalParented(0),
|
|
||||||
gcHeapShapesDict(0),
|
|
||||||
gcHeapShapesBase(0),
|
|
||||||
gcHeapScripts(0),
|
|
||||||
objectsExtra(),
|
objectsExtra(),
|
||||||
shapesExtraTreeTables(0),
|
typeInference(),
|
||||||
shapesExtraDictTables(0),
|
extra()
|
||||||
shapesExtraTreeShapeKids(0),
|
|
||||||
shapesCompartmentTables(0),
|
|
||||||
scriptData(0),
|
|
||||||
baselineData(0),
|
|
||||||
baselineStubsFallback(0),
|
|
||||||
baselineStubsOptimized(0),
|
|
||||||
ionData(0),
|
|
||||||
compartmentObject(0),
|
|
||||||
crossCompartmentWrappersTable(0),
|
|
||||||
regexpCompartment(0),
|
|
||||||
debuggeesSet(0),
|
|
||||||
typeInference()
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CompartmentStats(const CompartmentStats &other)
|
CompartmentStats(const CompartmentStats &other)
|
||||||
: extra(other.extra),
|
: FOR_EACH_SIZE(COPY_OTHER_SIZE)
|
||||||
gcHeapObjectsOrdinary(other.gcHeapObjectsOrdinary),
|
|
||||||
gcHeapObjectsFunction(other.gcHeapObjectsFunction),
|
|
||||||
gcHeapObjectsDenseArray(other.gcHeapObjectsDenseArray),
|
|
||||||
gcHeapObjectsSlowArray(other.gcHeapObjectsSlowArray),
|
|
||||||
gcHeapObjectsCrossCompartmentWrapper(other.gcHeapObjectsCrossCompartmentWrapper),
|
|
||||||
gcHeapShapesTreeGlobalParented(other.gcHeapShapesTreeGlobalParented),
|
|
||||||
gcHeapShapesTreeNonGlobalParented(other.gcHeapShapesTreeNonGlobalParented),
|
|
||||||
gcHeapShapesDict(other.gcHeapShapesDict),
|
|
||||||
gcHeapShapesBase(other.gcHeapShapesBase),
|
|
||||||
gcHeapScripts(other.gcHeapScripts),
|
|
||||||
objectsExtra(other.objectsExtra),
|
objectsExtra(other.objectsExtra),
|
||||||
shapesExtraTreeTables(other.shapesExtraTreeTables),
|
typeInference(other.typeInference),
|
||||||
shapesExtraDictTables(other.shapesExtraDictTables),
|
extra(other.extra)
|
||||||
shapesExtraTreeShapeKids(other.shapesExtraTreeShapeKids),
|
{}
|
||||||
shapesCompartmentTables(other.shapesCompartmentTables),
|
|
||||||
scriptData(other.scriptData),
|
void add(const CompartmentStats &other) {
|
||||||
baselineData(other.baselineData),
|
FOR_EACH_SIZE(ADD_OTHER_SIZE)
|
||||||
baselineStubsFallback(other.baselineStubsFallback),
|
objectsExtra.add(other.objectsExtra);
|
||||||
baselineStubsOptimized(other.baselineStubsOptimized),
|
typeInference.add(other.typeInference);
|
||||||
ionData(other.ionData),
|
// Do nothing with |extra|.
|
||||||
compartmentObject(other.compartmentObject),
|
|
||||||
crossCompartmentWrappersTable(other.crossCompartmentWrappersTable),
|
|
||||||
regexpCompartment(other.regexpCompartment),
|
|
||||||
debuggeesSet(other.debuggeesSet),
|
|
||||||
typeInference(other.typeInference)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This field can be used by embedders.
|
size_t sizeOfLiveGCThings() const {
|
||||||
void *extra;
|
size_t n = 0;
|
||||||
|
FOR_EACH_SIZE(ADD_SIZE_TO_N_IF_LIVE_GC_THING)
|
||||||
// If you add a new number, remember to update the constructors, add(), and
|
n += objectsExtra.sizeOfLiveGCThings();
|
||||||
// maybe gcHeapThingsSize()!
|
n += typeInference.sizeOfLiveGCThings();
|
||||||
size_t gcHeapObjectsOrdinary;
|
// Do nothing with |extra|.
|
||||||
size_t gcHeapObjectsFunction;
|
return n;
|
||||||
size_t gcHeapObjectsDenseArray;
|
}
|
||||||
size_t gcHeapObjectsSlowArray;
|
|
||||||
size_t gcHeapObjectsCrossCompartmentWrapper;
|
|
||||||
size_t gcHeapShapesTreeGlobalParented;
|
|
||||||
size_t gcHeapShapesTreeNonGlobalParented;
|
|
||||||
size_t gcHeapShapesDict;
|
|
||||||
size_t gcHeapShapesBase;
|
|
||||||
size_t gcHeapScripts;
|
|
||||||
ObjectsExtraSizes objectsExtra;
|
|
||||||
|
|
||||||
size_t shapesExtraTreeTables;
|
|
||||||
size_t shapesExtraDictTables;
|
|
||||||
size_t shapesExtraTreeShapeKids;
|
|
||||||
size_t shapesCompartmentTables;
|
|
||||||
size_t scriptData;
|
|
||||||
size_t baselineData;
|
|
||||||
size_t baselineStubsFallback;
|
|
||||||
size_t baselineStubsOptimized;
|
|
||||||
size_t ionData;
|
|
||||||
size_t compartmentObject;
|
|
||||||
size_t crossCompartmentWrappersTable;
|
|
||||||
size_t regexpCompartment;
|
|
||||||
size_t debuggeesSet;
|
|
||||||
|
|
||||||
|
FOR_EACH_SIZE(DECL_SIZE)
|
||||||
|
ObjectsExtraSizes objectsExtra;
|
||||||
TypeInferenceSizes typeInference;
|
TypeInferenceSizes typeInference;
|
||||||
|
void *extra; // This field can be used by embedders.
|
||||||
|
|
||||||
// Add cStats's numbers to this object's numbers.
|
#undef FOR_EACH_SIZE
|
||||||
void add(CompartmentStats &cStats) {
|
|
||||||
#define ADD(x) this->x += cStats.x
|
|
||||||
|
|
||||||
ADD(gcHeapObjectsOrdinary);
|
|
||||||
ADD(gcHeapObjectsFunction);
|
|
||||||
ADD(gcHeapObjectsDenseArray);
|
|
||||||
ADD(gcHeapObjectsSlowArray);
|
|
||||||
ADD(gcHeapObjectsCrossCompartmentWrapper);
|
|
||||||
ADD(gcHeapShapesTreeGlobalParented);
|
|
||||||
ADD(gcHeapShapesTreeNonGlobalParented);
|
|
||||||
ADD(gcHeapShapesDict);
|
|
||||||
ADD(gcHeapShapesBase);
|
|
||||||
ADD(gcHeapScripts);
|
|
||||||
objectsExtra.add(cStats.objectsExtra);
|
|
||||||
|
|
||||||
ADD(shapesExtraTreeTables);
|
|
||||||
ADD(shapesExtraDictTables);
|
|
||||||
ADD(shapesExtraTreeShapeKids);
|
|
||||||
ADD(shapesCompartmentTables);
|
|
||||||
ADD(scriptData);
|
|
||||||
ADD(baselineData);
|
|
||||||
ADD(baselineStubsFallback);
|
|
||||||
ADD(baselineStubsOptimized);
|
|
||||||
ADD(ionData);
|
|
||||||
ADD(compartmentObject);
|
|
||||||
ADD(crossCompartmentWrappersTable);
|
|
||||||
ADD(regexpCompartment);
|
|
||||||
ADD(debuggeesSet);
|
|
||||||
|
|
||||||
#undef ADD
|
|
||||||
|
|
||||||
typeInference.add(cStats.typeInference);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The size of all the live things in the GC heap.
|
|
||||||
size_t GCHeapThingsSize();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RuntimeStats
|
struct RuntimeStats
|
||||||
{
|
{
|
||||||
|
#define FOR_EACH_SIZE(macro) \
|
||||||
|
macro(_, gcHeapChunkTotal) \
|
||||||
|
macro(_, gcHeapDecommittedArenas) \
|
||||||
|
macro(_, gcHeapUnusedChunks) \
|
||||||
|
macro(_, gcHeapUnusedArenas) \
|
||||||
|
macro(_, gcHeapUnusedGcThings) \
|
||||||
|
macro(_, gcHeapChunkAdmin) \
|
||||||
|
macro(_, gcHeapGcThings) \
|
||||||
|
|
||||||
RuntimeStats(mozilla::MallocSizeOf mallocSizeOf)
|
RuntimeStats(mozilla::MallocSizeOf mallocSizeOf)
|
||||||
: runtime(),
|
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||||
gcHeapChunkTotal(0),
|
runtime(),
|
||||||
gcHeapDecommittedArenas(0),
|
|
||||||
gcHeapUnusedChunks(0),
|
|
||||||
gcHeapUnusedArenas(0),
|
|
||||||
gcHeapUnusedGcThings(0),
|
|
||||||
gcHeapChunkAdmin(0),
|
|
||||||
gcHeapGcThings(0),
|
|
||||||
cTotals(),
|
cTotals(),
|
||||||
zTotals(),
|
zTotals(),
|
||||||
compartmentStatsVector(),
|
compartmentStatsVector(),
|
||||||
@ -468,10 +444,6 @@ struct RuntimeStats
|
|||||||
mallocSizeOf_(mallocSizeOf)
|
mallocSizeOf_(mallocSizeOf)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
RuntimeSizes runtime;
|
|
||||||
|
|
||||||
// If you add a new number, remember to update the constructor!
|
|
||||||
|
|
||||||
// Here's a useful breakdown of the GC heap.
|
// Here's a useful breakdown of the GC heap.
|
||||||
//
|
//
|
||||||
// - rtStats.gcHeapChunkTotal
|
// - rtStats.gcHeapChunkTotal
|
||||||
@ -491,17 +463,12 @@ struct RuntimeStats
|
|||||||
// it's rare, and (b) this means that rtStats.gcHeapUnusedChunks is a
|
// it's rare, and (b) this means that rtStats.gcHeapUnusedChunks is a
|
||||||
// multiple of the chunk size, which is good.
|
// multiple of the chunk size, which is good.
|
||||||
|
|
||||||
size_t gcHeapChunkTotal;
|
FOR_EACH_SIZE(DECL_SIZE)
|
||||||
size_t gcHeapDecommittedArenas;
|
|
||||||
size_t gcHeapUnusedChunks;
|
|
||||||
size_t gcHeapUnusedArenas;
|
|
||||||
size_t gcHeapUnusedGcThings;
|
|
||||||
size_t gcHeapChunkAdmin;
|
|
||||||
size_t gcHeapGcThings;
|
|
||||||
|
|
||||||
// The sum of all compartment's measurements.
|
RuntimeSizes runtime;
|
||||||
CompartmentStats cTotals;
|
|
||||||
ZoneStats zTotals;
|
CompartmentStats cTotals; // The sum of this runtime's compartments' measurements.
|
||||||
|
ZoneStats zTotals; // The sum of this runtime's zones' measurements.
|
||||||
|
|
||||||
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
|
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
|
||||||
js::Vector<ZoneStats, 0, js::SystemAllocPolicy> zoneStatsVector;
|
js::Vector<ZoneStats, 0, js::SystemAllocPolicy> zoneStatsVector;
|
||||||
@ -512,6 +479,8 @@ struct RuntimeStats
|
|||||||
|
|
||||||
virtual void initExtraCompartmentStats(JSCompartment *c, CompartmentStats *cstats) = 0;
|
virtual void initExtraCompartmentStats(JSCompartment *c, CompartmentStats *cstats) = 0;
|
||||||
virtual void initExtraZoneStats(JS::Zone *zone, ZoneStats *zstats) = 0;
|
virtual void initExtraZoneStats(JS::Zone *zone, ZoneStats *zstats) = 0;
|
||||||
|
|
||||||
|
#undef FOR_EACH_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
class ObjectPrivateVisitor
|
class ObjectPrivateVisitor
|
||||||
|
@ -317,10 +317,6 @@ def is_module_header(enclosing_inclname, header_inclname):
|
|||||||
if m is not None and module.endswith('/' + m.group(1)):
|
if m is not None and module.endswith('/' + m.group(1)):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
# A weird public header case.
|
|
||||||
if module == 'jsmemorymetrics' and header_inclname == 'js/MemoryMetrics.h':
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ LOCAL_OBJDIR = $(OBJDIR)/editline
|
|||||||
# Default IEEE libm
|
# Default IEEE libm
|
||||||
#
|
#
|
||||||
CFLAGS += -DXP_UNIX $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \
|
CFLAGS += -DXP_UNIX $(OPTIMIZER) $(OS_CFLAGS) $(DEFINES) $(INCLUDES) \
|
||||||
-DJSFILE $(XCFLAGS) $(DEFS)
|
$(XCFLAGS) $(DEFS)
|
||||||
|
|
||||||
INCFILES = editline.h
|
INCFILES = editline.h
|
||||||
.INIT: $(INCFILES)
|
.INIT: $(INCFILES)
|
||||||
|
@ -8581,7 +8581,8 @@ class MAsmJSLoadHeap : public MUnaryInstruction, public MAsmJSHeapAccess
|
|||||||
MAsmJSLoadHeap(ArrayBufferView::ViewType vt, MDefinition *ptr)
|
MAsmJSLoadHeap(ArrayBufferView::ViewType vt, MDefinition *ptr)
|
||||||
: MUnaryInstruction(ptr), MAsmJSHeapAccess(vt, false)
|
: MUnaryInstruction(ptr), MAsmJSHeapAccess(vt, false)
|
||||||
{
|
{
|
||||||
setMovable();
|
// Disabled due to errors, see bug 919958
|
||||||
|
// setMovable();
|
||||||
if (vt == ArrayBufferView::TYPE_FLOAT32 || vt == ArrayBufferView::TYPE_FLOAT64)
|
if (vt == ArrayBufferView::TYPE_FLOAT32 || vt == ArrayBufferView::TYPE_FLOAT64)
|
||||||
setResultType(MIRType_Double);
|
setResultType(MIRType_Double);
|
||||||
else
|
else
|
||||||
|
@ -735,7 +735,7 @@ js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enc
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rooted<StaticBlockObject*> tmp(cx, static_cast<StaticBlockObject *>(objp->get()));
|
Rooted<StaticBlockObject*> tmp(cx, static_cast<StaticBlockObject *>(objp->get()));
|
||||||
if (!XDRStaticBlockObject(xdr, blockEnclosingScope, script, tmp.address()))
|
if (!XDRStaticBlockObject(xdr, blockEnclosingScope, tmp.address()))
|
||||||
return false;
|
return false;
|
||||||
*objp = tmp;
|
*objp = tmp;
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,7 @@ CPP_SOURCES += [
|
|||||||
'MapObject.cpp',
|
'MapObject.cpp',
|
||||||
'Marking.cpp',
|
'Marking.cpp',
|
||||||
'Memory.cpp',
|
'Memory.cpp',
|
||||||
|
'MemoryMetrics.cpp',
|
||||||
'Module.cpp',
|
'Module.cpp',
|
||||||
'Monitor.cpp',
|
'Monitor.cpp',
|
||||||
'NameFunctions.cpp',
|
'NameFunctions.cpp',
|
||||||
@ -164,7 +165,6 @@ CPP_SOURCES += [
|
|||||||
'jsinfer.cpp',
|
'jsinfer.cpp',
|
||||||
'jsiter.cpp',
|
'jsiter.cpp',
|
||||||
'jsmath.cpp',
|
'jsmath.cpp',
|
||||||
'jsmemorymetrics.cpp',
|
|
||||||
'jsnativestack.cpp',
|
'jsnativestack.cpp',
|
||||||
'jsnum.cpp',
|
'jsnum.cpp',
|
||||||
'jsobj.cpp',
|
'jsobj.cpp',
|
||||||
|
@ -153,50 +153,17 @@ NotableStringInfo &NotableStringInfo::operator=(MoveRef<NotableStringInfo> info)
|
|||||||
|
|
||||||
typedef HashSet<ScriptSource *, DefaultHasher<ScriptSource *>, SystemAllocPolicy> SourceSet;
|
typedef HashSet<ScriptSource *, DefaultHasher<ScriptSource *>, SystemAllocPolicy> SourceSet;
|
||||||
|
|
||||||
struct IteratorClosure
|
struct StatsClosure
|
||||||
{
|
{
|
||||||
RuntimeStats *rtStats;
|
RuntimeStats *rtStats;
|
||||||
ObjectPrivateVisitor *opv;
|
ObjectPrivateVisitor *opv;
|
||||||
SourceSet seenSources;
|
SourceSet seenSources;
|
||||||
IteratorClosure(RuntimeStats *rt, ObjectPrivateVisitor *v) : rtStats(rt), opv(v) {}
|
StatsClosure(RuntimeStats *rt, ObjectPrivateVisitor *v) : rtStats(rt), opv(v) {}
|
||||||
bool init() {
|
bool init() {
|
||||||
return seenSources.init();
|
return seenSources.init();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t
|
|
||||||
ZoneStats::GCHeapThingsSize()
|
|
||||||
{
|
|
||||||
// These are just the GC-thing measurements.
|
|
||||||
size_t n = 0;
|
|
||||||
n += gcHeapStringsNormal;
|
|
||||||
n += gcHeapStringsShort;
|
|
||||||
n += gcHeapLazyScripts;
|
|
||||||
n += gcHeapTypeObjects;
|
|
||||||
n += gcHeapIonCodes;
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
CompartmentStats::GCHeapThingsSize()
|
|
||||||
{
|
|
||||||
// These are just the GC-thing measurements.
|
|
||||||
size_t n = 0;
|
|
||||||
n += gcHeapObjectsOrdinary;
|
|
||||||
n += gcHeapObjectsFunction;
|
|
||||||
n += gcHeapObjectsDenseArray;
|
|
||||||
n += gcHeapObjectsSlowArray;
|
|
||||||
n += gcHeapObjectsCrossCompartmentWrapper;
|
|
||||||
n += gcHeapShapesTreeGlobalParented;
|
|
||||||
n += gcHeapShapesTreeNonGlobalParented;
|
|
||||||
n += gcHeapShapesDict;
|
|
||||||
n += gcHeapShapesBase;
|
|
||||||
n += gcHeapScripts;
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DecommittedArenasChunkCallback(JSRuntime *rt, void *data, gc::Chunk *chunk)
|
DecommittedArenasChunkCallback(JSRuntime *rt, void *data, gc::Chunk *chunk)
|
||||||
{
|
{
|
||||||
@ -217,7 +184,7 @@ static void
|
|||||||
StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
|
StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
|
||||||
{
|
{
|
||||||
// Append a new CompartmentStats to the vector.
|
// Append a new CompartmentStats to the vector.
|
||||||
RuntimeStats *rtStats = static_cast<IteratorClosure *>(data)->rtStats;
|
RuntimeStats *rtStats = static_cast<StatsClosure *>(data)->rtStats;
|
||||||
|
|
||||||
// CollectRuntimeStats reserves enough space.
|
// CollectRuntimeStats reserves enough space.
|
||||||
MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1));
|
MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1));
|
||||||
@ -241,7 +208,7 @@ static void
|
|||||||
StatsZoneCallback(JSRuntime *rt, void *data, Zone *zone)
|
StatsZoneCallback(JSRuntime *rt, void *data, Zone *zone)
|
||||||
{
|
{
|
||||||
// Append a new CompartmentStats to the vector.
|
// Append a new CompartmentStats to the vector.
|
||||||
RuntimeStats *rtStats = static_cast<IteratorClosure *>(data)->rtStats;
|
RuntimeStats *rtStats = static_cast<StatsClosure *>(data)->rtStats;
|
||||||
|
|
||||||
// CollectRuntimeStats reserves enough space.
|
// CollectRuntimeStats reserves enough space.
|
||||||
MOZ_ALWAYS_TRUE(rtStats->zoneStatsVector.growBy(1));
|
MOZ_ALWAYS_TRUE(rtStats->zoneStatsVector.growBy(1));
|
||||||
@ -257,7 +224,7 @@ static void
|
|||||||
StatsArenaCallback(JSRuntime *rt, void *data, gc::Arena *arena,
|
StatsArenaCallback(JSRuntime *rt, void *data, gc::Arena *arena,
|
||||||
JSGCTraceKind traceKind, size_t thingSize)
|
JSGCTraceKind traceKind, size_t thingSize)
|
||||||
{
|
{
|
||||||
RuntimeStats *rtStats = static_cast<IteratorClosure *>(data)->rtStats;
|
RuntimeStats *rtStats = static_cast<StatsClosure *>(data)->rtStats;
|
||||||
|
|
||||||
// The admin space includes (a) the header and (b) the padding between the
|
// The admin space includes (a) the header and (b) the padding between the
|
||||||
// end of the header and the start of the first GC thing.
|
// end of the header and the start of the first GC thing.
|
||||||
@ -281,7 +248,7 @@ static void
|
|||||||
StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKind,
|
StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKind,
|
||||||
size_t thingSize)
|
size_t thingSize)
|
||||||
{
|
{
|
||||||
IteratorClosure *closure = static_cast<IteratorClosure *>(data);
|
StatsClosure *closure = static_cast<StatsClosure *>(data);
|
||||||
RuntimeStats *rtStats = closure->rtStats;
|
RuntimeStats *rtStats = closure->rtStats;
|
||||||
ZoneStats *zStats = rtStats->currZoneStats;
|
ZoneStats *zStats = rtStats->currZoneStats;
|
||||||
switch (traceKind) {
|
switch (traceKind) {
|
||||||
@ -301,12 +268,12 @@ StatsCellCallback(JSRuntime *rt, void *data, void *thing, JSGCTraceKind traceKin
|
|||||||
obj->sizeOfExcludingThis(rtStats->mallocSizeOf_, &objectsExtra);
|
obj->sizeOfExcludingThis(rtStats->mallocSizeOf_, &objectsExtra);
|
||||||
cStats->objectsExtra.add(objectsExtra);
|
cStats->objectsExtra.add(objectsExtra);
|
||||||
|
|
||||||
// JSObject::sizeOfExcludingThis() doesn't measure objectsExtraPrivate,
|
// JSObject::sizeOfExcludingThis() doesn't measure objectsPrivate,
|
||||||
// so we do it here.
|
// so we do it here.
|
||||||
if (ObjectPrivateVisitor *opv = closure->opv) {
|
if (ObjectPrivateVisitor *opv = closure->opv) {
|
||||||
nsISupports *iface;
|
nsISupports *iface;
|
||||||
if (opv->getISupports_(obj, &iface) && iface) {
|
if (opv->getISupports_(obj, &iface) && iface) {
|
||||||
cStats->objectsExtra.private_ += opv->sizeOfIncludingThis(iface);
|
cStats->objectsPrivate += opv->sizeOfIncludingThis(iface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -473,7 +440,7 @@ JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisit
|
|||||||
DecommittedArenasChunkCallback);
|
DecommittedArenasChunkCallback);
|
||||||
|
|
||||||
// Take the per-compartment measurements.
|
// Take the per-compartment measurements.
|
||||||
IteratorClosure closure(rtStats, opv);
|
StatsClosure closure(rtStats, opv);
|
||||||
if (!closure.init())
|
if (!closure.init())
|
||||||
return false;
|
return false;
|
||||||
rtStats->runtime.scriptSources = 0;
|
rtStats->runtime.scriptSources = 0;
|
||||||
@ -490,7 +457,7 @@ JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisit
|
|||||||
ZoneStats &zStats = rtStats->zoneStatsVector[i];
|
ZoneStats &zStats = rtStats->zoneStatsVector[i];
|
||||||
|
|
||||||
rtStats->zTotals.add(zStats);
|
rtStats->zTotals.add(zStats);
|
||||||
rtStats->gcHeapGcThings += zStats.GCHeapThingsSize();
|
rtStats->gcHeapGcThings += zStats.sizeOfLiveGCThings();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
totalArenaSize += zStats.gcHeapArenaAdmin + zStats.gcHeapUnusedGcThings;
|
totalArenaSize += zStats.gcHeapArenaAdmin + zStats.gcHeapUnusedGcThings;
|
||||||
#endif
|
#endif
|
||||||
@ -506,7 +473,7 @@ JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisit
|
|||||||
CompartmentStats &cStats = rtStats->compartmentStatsVector[i];
|
CompartmentStats &cStats = rtStats->compartmentStatsVector[i];
|
||||||
|
|
||||||
rtStats->cTotals.add(cStats);
|
rtStats->cTotals.add(cStats);
|
||||||
rtStats->gcHeapGcThings += cStats.GCHeapThingsSize();
|
rtStats->gcHeapGcThings += cStats.sizeOfLiveGCThings();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
@ -730,7 +730,7 @@ const Class BlockObject::class_ = {
|
|||||||
|
|
||||||
template<XDRMode mode>
|
template<XDRMode mode>
|
||||||
bool
|
bool
|
||||||
js::XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript script,
|
js::XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope,
|
||||||
StaticBlockObject **objp)
|
StaticBlockObject **objp)
|
||||||
{
|
{
|
||||||
/* NB: Keep this in sync with CloneStaticBlockObject. */
|
/* NB: Keep this in sync with CloneStaticBlockObject. */
|
||||||
@ -834,10 +834,10 @@ js::XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope, Handl
|
|||||||
}
|
}
|
||||||
|
|
||||||
template bool
|
template bool
|
||||||
js::XDRStaticBlockObject(XDRState<XDR_ENCODE> *, HandleObject, HandleScript, StaticBlockObject **);
|
js::XDRStaticBlockObject(XDRState<XDR_ENCODE> *, HandleObject, StaticBlockObject **);
|
||||||
|
|
||||||
template bool
|
template bool
|
||||||
js::XDRStaticBlockObject(XDRState<XDR_DECODE> *, HandleObject, HandleScript, StaticBlockObject **);
|
js::XDRStaticBlockObject(XDRState<XDR_DECODE> *, HandleObject, StaticBlockObject **);
|
||||||
|
|
||||||
JSObject *
|
JSObject *
|
||||||
js::CloneStaticBlockObject(JSContext *cx, HandleObject enclosingScope, Handle<StaticBlockObject*> srcBlock)
|
js::CloneStaticBlockObject(JSContext *cx, HandleObject enclosingScope, Handle<StaticBlockObject*> srcBlock)
|
||||||
|
@ -470,7 +470,7 @@ class ClonedBlockObject : public BlockObject
|
|||||||
|
|
||||||
template<XDRMode mode>
|
template<XDRMode mode>
|
||||||
bool
|
bool
|
||||||
XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript script,
|
XDRStaticBlockObject(XDRState<mode> *xdr, HandleObject enclosingScope,
|
||||||
StaticBlockObject **objp);
|
StaticBlockObject **objp);
|
||||||
|
|
||||||
extern JSObject *
|
extern JSObject *
|
||||||
|
@ -11,6 +11,5 @@ LOCAL_INCLUDES += \
|
|||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
DEFINES += \
|
DEFINES += \
|
||||||
-DJSFILE \
|
|
||||||
-DJS_THREADSAFE \
|
-DJS_THREADSAFE \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
@ -46,9 +46,7 @@ include $(topsrcdir)/config/rules.mk
|
|||||||
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
include $(topsrcdir)/ipc/chromium/chromium-config.mk
|
||||||
|
|
||||||
DEFINES += \
|
DEFINES += \
|
||||||
-DJSFILE \
|
|
||||||
-DJS_THREADSAFE \
|
-DJS_THREADSAFE \
|
||||||
-DEXPORT_XPC_API \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifdef MOZ_JSDEBUGGER
|
ifdef MOZ_JSDEBUGGER
|
||||||
|
@ -1731,7 +1731,7 @@ private:
|
|||||||
rtTotal += amount; \
|
rtTotal += amount; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf)
|
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JSMallocSizeOf)
|
||||||
|
|
||||||
namespace xpc {
|
namespace xpc {
|
||||||
|
|
||||||
@ -2067,7 +2067,7 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats,
|
|||||||
// DOM nodes in the JS reporter, but we want to report them in a "dom"
|
// DOM nodes in the JS reporter, but we want to report them in a "dom"
|
||||||
// sub-tree rather than a "js" sub-tree.
|
// sub-tree rather than a "js" sub-tree.
|
||||||
ZCREPORT_BYTES(cDOMPathPrefix + NS_LITERAL_CSTRING("orphan-nodes"),
|
ZCREPORT_BYTES(cDOMPathPrefix + NS_LITERAL_CSTRING("orphan-nodes"),
|
||||||
cStats.objectsExtra.private_,
|
cStats.objectsPrivate,
|
||||||
"Memory used by orphan DOM nodes that are only reachable "
|
"Memory used by orphan DOM nodes that are only reachable "
|
||||||
"from JavaScript objects.");
|
"from JavaScript objects.");
|
||||||
|
|
||||||
@ -2441,7 +2441,7 @@ class XPCJSRuntimeStats : public JS::RuntimeStats
|
|||||||
public:
|
public:
|
||||||
XPCJSRuntimeStats(WindowPaths *windowPaths, WindowPaths *topWindowPaths,
|
XPCJSRuntimeStats(WindowPaths *windowPaths, WindowPaths *topWindowPaths,
|
||||||
bool getLocations)
|
bool getLocations)
|
||||||
: JS::RuntimeStats(JsMallocSizeOf),
|
: JS::RuntimeStats(JSMallocSizeOf),
|
||||||
mWindowPaths(windowPaths),
|
mWindowPaths(windowPaths),
|
||||||
mTopWindowPaths(topWindowPaths),
|
mTopWindowPaths(topWindowPaths),
|
||||||
mGetLocations(getLocations)
|
mGetLocations(getLocations)
|
||||||
@ -2574,8 +2574,8 @@ JSReporter::CollectReports(WindowPaths *windowPaths,
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
size_t xpconnect =
|
size_t xpconnect =
|
||||||
xpcrt->SizeOfIncludingThis(JsMallocSizeOf) +
|
xpcrt->SizeOfIncludingThis(JSMallocSizeOf) +
|
||||||
XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(JsMallocSizeOf);
|
XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(JSMallocSizeOf);
|
||||||
|
|
||||||
// This is the second step (see above). First we report stuff in the
|
// This is the second step (see above). First we report stuff in the
|
||||||
// "explicit" tree, then we report other stuff.
|
// "explicit" tree, then we report other stuff.
|
||||||
@ -3047,7 +3047,7 @@ XPCJSRuntime::newXPCJSRuntime(nsXPConnect* aXPConnect)
|
|||||||
XPCJSRuntime* self = new XPCJSRuntime(aXPConnect);
|
XPCJSRuntime* self = new XPCJSRuntime(aXPConnect);
|
||||||
|
|
||||||
if (self &&
|
if (self &&
|
||||||
self->Runtime() &&
|
self->Runtime() &&
|
||||||
self->GetWrappedJSMap() &&
|
self->GetWrappedJSMap() &&
|
||||||
self->GetWrappedJSClassMap() &&
|
self->GetWrappedJSClassMap() &&
|
||||||
self->GetIID2NativeInterfaceMap() &&
|
self->GetIID2NativeInterfaceMap() &&
|
||||||
|
@ -8,37 +8,32 @@
|
|||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
#define STACK_ARENA_MARK_INCREMENT 50
|
// A block of memory that the stack will chop up and hand out.
|
||||||
/* a bit under 4096, for malloc overhead */
|
|
||||||
#define STACK_ARENA_BLOCK_INCREMENT 4044
|
|
||||||
|
|
||||||
/**A block of memory that the stack will
|
|
||||||
* chop up and hand out
|
|
||||||
*/
|
|
||||||
struct StackBlock {
|
struct StackBlock {
|
||||||
|
// Subtract sizeof(StackBlock*) to give space for the |mNext| field.
|
||||||
// a block of memory. Note that this must be first so that it will
|
static const size_t MAX_USABLE_SIZE = 4096 - sizeof(StackBlock*);
|
||||||
// be aligned.
|
|
||||||
char mBlock[STACK_ARENA_BLOCK_INCREMENT];
|
|
||||||
|
|
||||||
// another block of memory that would only be created
|
// A block of memory.
|
||||||
// if our stack overflowed. Yes we have the ability
|
char mBlock[MAX_USABLE_SIZE];
|
||||||
// to grow on a stack overflow
|
|
||||||
StackBlock* mNext;
|
|
||||||
|
|
||||||
StackBlock() : mNext(nullptr) { }
|
// Another block of memory that would only be created if our stack
|
||||||
~StackBlock() { }
|
// overflowed.
|
||||||
|
StackBlock* mNext;
|
||||||
|
|
||||||
|
StackBlock() : mNext(nullptr) { }
|
||||||
|
~StackBlock() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* we hold an array of marks. A push pushes a mark on the stack
|
static_assert(sizeof(StackBlock) == 4096, "StackBlock must be 4096 bytes");
|
||||||
* a pop pops it off.
|
|
||||||
*/
|
// We hold an array of marks. A push pushes a mark on the stack.
|
||||||
|
// A pop pops it off.
|
||||||
struct StackMark {
|
struct StackMark {
|
||||||
// the block of memory we are currently handing out chunks of
|
// The block of memory from which we are currently handing out chunks.
|
||||||
StackBlock* mBlock;
|
StackBlock* mBlock;
|
||||||
|
|
||||||
// our current position in the memory
|
// Our current position in the block.
|
||||||
size_t mPos;
|
size_t mPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
StackArena* AutoStackArena::gStackArena;
|
StackArena* AutoStackArena::gStackArena;
|
||||||
@ -48,7 +43,7 @@ StackArena::StackArena()
|
|||||||
mMarkLength = 0;
|
mMarkLength = 0;
|
||||||
mMarks = nullptr;
|
mMarks = nullptr;
|
||||||
|
|
||||||
// allocate our stack memory
|
// Allocate our stack memory.
|
||||||
mBlocks = new StackBlock();
|
mBlocks = new StackBlock();
|
||||||
mCurBlock = mBlocks;
|
mCurBlock = mBlocks;
|
||||||
|
|
||||||
@ -58,15 +53,14 @@ StackArena::StackArena()
|
|||||||
|
|
||||||
StackArena::~StackArena()
|
StackArena::~StackArena()
|
||||||
{
|
{
|
||||||
// free up our data
|
// Free up our data.
|
||||||
delete[] mMarks;
|
delete [] mMarks;
|
||||||
while(mBlocks)
|
while (mBlocks) {
|
||||||
{
|
|
||||||
StackBlock* toDelete = mBlocks;
|
StackBlock* toDelete = mBlocks;
|
||||||
mBlocks = mBlocks->mNext;
|
mBlocks = mBlocks->mNext;
|
||||||
delete toDelete;
|
delete toDelete;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
StackArena::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
StackArena::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
||||||
@ -81,19 +75,21 @@ StackArena::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const int STACK_ARENA_MARK_INCREMENT = 50;
|
||||||
|
|
||||||
void
|
void
|
||||||
StackArena::Push()
|
StackArena::Push()
|
||||||
{
|
{
|
||||||
// Resize the mark array if we overrun it. Failure to allocate the
|
// Resize the mark array if we overrun it. Failure to allocate the
|
||||||
// mark array is not fatal; we just won't free to that mark. This
|
// mark array is not fatal; we just won't free to that mark. This
|
||||||
// allows callers not to worry about error checking.
|
// allows callers not to worry about error checking.
|
||||||
if (mStackTop >= mMarkLength)
|
if (mStackTop >= mMarkLength) {
|
||||||
{
|
|
||||||
uint32_t newLength = mStackTop + STACK_ARENA_MARK_INCREMENT;
|
uint32_t newLength = mStackTop + STACK_ARENA_MARK_INCREMENT;
|
||||||
StackMark* newMarks = new StackMark[newLength];
|
StackMark* newMarks = new StackMark[newLength];
|
||||||
if (newMarks) {
|
if (newMarks) {
|
||||||
if (mMarkLength)
|
if (mMarkLength) {
|
||||||
memcpy(newMarks, mMarks, sizeof(StackMark)*mMarkLength);
|
memcpy(newMarks, mMarks, sizeof(StackMark)*mMarkLength);
|
||||||
|
}
|
||||||
// Fill in any marks that we couldn't allocate during a prior call
|
// Fill in any marks that we couldn't allocate during a prior call
|
||||||
// to Push().
|
// to Push().
|
||||||
for (; mMarkLength < mStackTop; ++mMarkLength) {
|
for (; mMarkLength < mStackTop; ++mMarkLength) {
|
||||||
@ -107,7 +103,7 @@ StackArena::Push()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set a mark at the top (if we can)
|
// Set a mark at the top (if we can).
|
||||||
NS_ASSERTION(mStackTop < mMarkLength, "out of memory");
|
NS_ASSERTION(mStackTop < mMarkLength, "out of memory");
|
||||||
if (mStackTop < mMarkLength) {
|
if (mStackTop < mMarkLength) {
|
||||||
mMarks[mStackTop].mBlock = mCurBlock;
|
mMarks[mStackTop].mBlock = mCurBlock;
|
||||||
@ -122,23 +118,22 @@ StackArena::Allocate(size_t aSize)
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(mStackTop > 0, "Allocate called without Push");
|
NS_ASSERTION(mStackTop > 0, "Allocate called without Push");
|
||||||
|
|
||||||
// make sure we are aligned. Beard said 8 was safer then 4.
|
// Align to a multiple of 8.
|
||||||
// Round size to multiple of 8
|
|
||||||
aSize = NS_ROUNDUP<size_t>(aSize, 8);
|
aSize = NS_ROUNDUP<size_t>(aSize, 8);
|
||||||
|
|
||||||
// if the size makes the stack overflow. Grab another block for the stack
|
// On stack overflow, grab another block.
|
||||||
if (mPos + aSize >= STACK_ARENA_BLOCK_INCREMENT)
|
if (mPos + aSize >= StackBlock::MAX_USABLE_SIZE) {
|
||||||
{
|
NS_ASSERTION(aSize <= StackBlock::MAX_USABLE_SIZE,
|
||||||
NS_ASSERTION(aSize <= STACK_ARENA_BLOCK_INCREMENT,
|
|
||||||
"Requested memory is greater that our block size!!");
|
"Requested memory is greater that our block size!!");
|
||||||
if (mCurBlock->mNext == nullptr)
|
if (mCurBlock->mNext == nullptr) {
|
||||||
mCurBlock->mNext = new StackBlock();
|
mCurBlock->mNext = new StackBlock();
|
||||||
|
}
|
||||||
|
|
||||||
mCurBlock = mCurBlock->mNext;
|
mCurBlock = mCurBlock->mNext;
|
||||||
mPos = 0;
|
mPos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the chunk they need.
|
// Return the chunk they need.
|
||||||
void *result = mCurBlock->mBlock + mPos;
|
void *result = mCurBlock->mBlock + mPos;
|
||||||
mPos += aSize;
|
mPos += aSize;
|
||||||
|
|
||||||
@ -148,7 +143,7 @@ StackArena::Allocate(size_t aSize)
|
|||||||
void
|
void
|
||||||
StackArena::Pop()
|
StackArena::Pop()
|
||||||
{
|
{
|
||||||
// pop off the mark
|
// Pop off the mark.
|
||||||
NS_ASSERTION(mStackTop > 0, "unmatched pop");
|
NS_ASSERTION(mStackTop > 0, "unmatched pop");
|
||||||
mStackTop--;
|
mStackTop--;
|
||||||
|
|
||||||
|
@ -12,10 +12,8 @@ namespace mozilla {
|
|||||||
struct StackBlock;
|
struct StackBlock;
|
||||||
struct StackMark;
|
struct StackMark;
|
||||||
class AutoStackArena;
|
class AutoStackArena;
|
||||||
|
|
||||||
/**
|
// Private helper class for AutoStackArena.
|
||||||
* Private helper class for AutoStackArena.
|
|
||||||
*/
|
|
||||||
class StackArena {
|
class StackArena {
|
||||||
private:
|
private:
|
||||||
friend class AutoStackArena;
|
friend class AutoStackArena;
|
||||||
@ -24,49 +22,49 @@ private:
|
|||||||
|
|
||||||
nsresult Init() { return mBlocks ? NS_OK : NS_ERROR_OUT_OF_MEMORY; }
|
nsresult Init() { return mBlocks ? NS_OK : NS_ERROR_OUT_OF_MEMORY; }
|
||||||
|
|
||||||
// Memory management functions
|
// Memory management functions.
|
||||||
void* Allocate(size_t aSize);
|
void* Allocate(size_t aSize);
|
||||||
void Push();
|
void Push();
|
||||||
void Pop();
|
void Pop();
|
||||||
|
|
||||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||||
|
|
||||||
// our current position in memory
|
// Our current position in memory.
|
||||||
size_t mPos;
|
size_t mPos;
|
||||||
|
|
||||||
// a list of memory block. Usually there is only one
|
// A list of memory blocks. Usually there is only one
|
||||||
// but if we overrun our stack size we can get more memory.
|
// but if we overrun our stack size we can get more memory.
|
||||||
StackBlock* mBlocks;
|
StackBlock* mBlocks;
|
||||||
|
|
||||||
// the current block of memory we are passing our chucks of
|
// The current block.
|
||||||
StackBlock* mCurBlock;
|
StackBlock* mCurBlock;
|
||||||
|
|
||||||
// our stack of mark where push has been called
|
// Our stack of mark where push has been called.
|
||||||
StackMark* mMarks;
|
StackMark* mMarks;
|
||||||
|
|
||||||
// the current top of the mark list
|
// The current top of the mark list.
|
||||||
uint32_t mStackTop;
|
uint32_t mStackTop;
|
||||||
|
|
||||||
// the size of the mark array
|
// The size of the mark array.
|
||||||
uint32_t mMarkLength;
|
uint32_t mMarkLength;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Class for stack scoped arena memory allocations.
|
||||||
/**
|
//
|
||||||
* Class for stack scoped arena memory allocations.
|
// Callers who wish to allocate memory whose lifetime corresponds to the
|
||||||
*
|
// lifetime of a stack-allocated object can use this class. First,
|
||||||
* Callers who wish to allocate memory whose lifetime corresponds to
|
// declare an AutoStackArena object on the stack. Then all subsequent
|
||||||
* the lifetime of a stack-allocated object can use this class.
|
// calls to Allocate will allocate memory from an arena pool that will
|
||||||
* First, declare an AutoStackArena object on the stack.
|
// be freed when that variable goes out of scope. Nesting is allowed.
|
||||||
* Then all subsequent calls to Allocate will allocate memory from an
|
//
|
||||||
* arena pool that will be freed when that variable goes out of scope.
|
// Individual allocations cannot exceed StackBlock::MAX_USABLE_SIZE
|
||||||
* Nesting is allowed.
|
// bytes.
|
||||||
*
|
//
|
||||||
* The allocations cannot be for more than 4044 bytes.
|
|
||||||
*/
|
|
||||||
class MOZ_STACK_CLASS AutoStackArena {
|
class MOZ_STACK_CLASS AutoStackArena {
|
||||||
public:
|
public:
|
||||||
AutoStackArena() : mOwnsStackArena(false) {
|
AutoStackArena()
|
||||||
|
: mOwnsStackArena(false)
|
||||||
|
{
|
||||||
if (!gStackArena) {
|
if (!gStackArena) {
|
||||||
gStackArena = new StackArena();
|
gStackArena = new StackArena();
|
||||||
mOwnsStackArena = true;
|
mOwnsStackArena = true;
|
||||||
@ -84,7 +82,6 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void* Allocate(size_t aSize) {
|
static void* Allocate(size_t aSize) {
|
||||||
MOZ_ASSERT(aSize <= 4044);
|
|
||||||
return gStackArena->Allocate(aSize);
|
return gStackArena->Allocate(aSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,5 +90,4 @@ private:
|
|||||||
bool mOwnsStackArena;
|
bool mOwnsStackArena;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -252,7 +252,7 @@ int NrIceCtx::select_pair(void *obj,nr_ice_media_stream *stream,
|
|||||||
int NrIceCtx::stream_ready(void *obj, nr_ice_media_stream *stream) {
|
int NrIceCtx::stream_ready(void *obj, nr_ice_media_stream *stream) {
|
||||||
MOZ_MTLOG(ML_DEBUG, "stream_ready called");
|
MOZ_MTLOG(ML_DEBUG, "stream_ready called");
|
||||||
|
|
||||||
// Get the ICE ctx
|
// Get the ICE ctx.
|
||||||
NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
|
NrIceCtx *ctx = static_cast<NrIceCtx *>(obj);
|
||||||
|
|
||||||
RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
|
RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
|
||||||
@ -306,6 +306,30 @@ int NrIceCtx::msg_recvd(void *obj, nr_ice_peer_ctx *pctx,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NrIceCtx::trickle_cb(void *arg, nr_ice_ctx *ice_ctx,
|
||||||
|
nr_ice_media_stream *stream,
|
||||||
|
int component_id,
|
||||||
|
nr_ice_candidate *candidate) {
|
||||||
|
// Get the ICE ctx
|
||||||
|
NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
|
||||||
|
RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
|
||||||
|
|
||||||
|
// Streams which do not exist shouldn't have candidates.
|
||||||
|
MOZ_ASSERT(s);
|
||||||
|
|
||||||
|
// Format the candidate.
|
||||||
|
char candidate_str[NR_ICE_MAX_ATTRIBUTE_SIZE];
|
||||||
|
int r = nr_ice_format_candidate_attribute(candidate, candidate_str,
|
||||||
|
sizeof(candidate_str));
|
||||||
|
MOZ_ASSERT(!r);
|
||||||
|
if (r)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MOZ_MTLOG(ML_INFO, "NrIceCtx(" << ctx->name_ << "): trickling candidate "
|
||||||
|
<< candidate_str);
|
||||||
|
|
||||||
|
s->SignalCandidate(s, candidate_str);
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
||||||
bool offerer,
|
bool offerer,
|
||||||
@ -383,6 +407,14 @@ RefPtr<NrIceCtx> NrIceCtx::Create(const std::string& name,
|
|||||||
}
|
}
|
||||||
#endif // USE_INTERFACE_PRIORITIZER
|
#endif // USE_INTERFACE_PRIORITIZER
|
||||||
|
|
||||||
|
if (ctx->generating_trickle()) {
|
||||||
|
r = nr_ice_ctx_set_trickle_cb(ctx->ctx_, &NrIceCtx::trickle_cb, ctx);
|
||||||
|
if (r) {
|
||||||
|
MOZ_MTLOG(ML_ERROR, "Couldn't set trickle cb for '" << name << "'");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create the handler objects
|
// Create the handler objects
|
||||||
ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl();
|
ctx->ice_handler_vtbl_ = new nr_ice_handler_vtbl();
|
||||||
ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;
|
ctx->ice_handler_vtbl_->select_pair = &NrIceCtx::select_pair;
|
||||||
@ -535,15 +567,6 @@ nsresult NrIceCtx::StartGathering() {
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NrIceCtx::EmitAllCandidates() {
|
|
||||||
MOZ_MTLOG(ML_NOTICE, "Gathered all ICE candidates for '"
|
|
||||||
<< name_ << "'");
|
|
||||||
|
|
||||||
for(size_t i=0; i<streams_.size(); ++i) {
|
|
||||||
streams_[i]->EmitAllCandidates();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<NrIceMediaStream> NrIceCtx::FindStream(
|
RefPtr<NrIceMediaStream> NrIceCtx::FindStream(
|
||||||
nr_ice_media_stream *stream) {
|
nr_ice_media_stream *stream) {
|
||||||
for (size_t i=0; i<streams_.size(); ++i) {
|
for (size_t i=0; i<streams_.size(); ++i) {
|
||||||
@ -630,8 +653,6 @@ nsresult NrIceCtx::StartChecks() {
|
|||||||
void NrIceCtx::initialized_cb(NR_SOCKET s, int h, void *arg) {
|
void NrIceCtx::initialized_cb(NR_SOCKET s, int h, void *arg) {
|
||||||
NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
|
NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
|
||||||
|
|
||||||
ctx->EmitAllCandidates();
|
|
||||||
|
|
||||||
ctx->SetState(ICE_CTX_GATHERED);
|
ctx->SetState(ICE_CTX_GATHERED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx;
|
|||||||
typedef struct nr_ice_media_stream_ nr_ice_media_stream;
|
typedef struct nr_ice_media_stream_ nr_ice_media_stream;
|
||||||
typedef struct nr_ice_handler_ nr_ice_handler;
|
typedef struct nr_ice_handler_ nr_ice_handler;
|
||||||
typedef struct nr_ice_handler_vtbl_ nr_ice_handler_vtbl;
|
typedef struct nr_ice_handler_vtbl_ nr_ice_handler_vtbl;
|
||||||
|
typedef struct nr_ice_candidate_ nr_ice_candidate;
|
||||||
typedef struct nr_ice_cand_pair_ nr_ice_cand_pair;
|
typedef struct nr_ice_cand_pair_ nr_ice_cand_pair;
|
||||||
typedef struct nr_ice_stun_server_ nr_ice_stun_server;
|
typedef struct nr_ice_stun_server_ nr_ice_stun_server;
|
||||||
typedef struct nr_ice_turn_server_ nr_ice_turn_server;
|
typedef struct nr_ice_turn_server_ nr_ice_turn_server;
|
||||||
@ -221,6 +222,9 @@ class NrIceCtx {
|
|||||||
// more forking.
|
// more forking.
|
||||||
nsresult Finalize();
|
nsresult Finalize();
|
||||||
|
|
||||||
|
// Are we trickling?
|
||||||
|
bool generating_trickle() const { return trickle_; }
|
||||||
|
|
||||||
// Signals to indicate events. API users can (and should)
|
// Signals to indicate events. API users can (and should)
|
||||||
// register for these.
|
// register for these.
|
||||||
// TODO(ekr@rtfm.com): refactor this to be state change instead
|
// TODO(ekr@rtfm.com): refactor this to be state change instead
|
||||||
@ -244,8 +248,8 @@ class NrIceCtx {
|
|||||||
ctx_(nullptr),
|
ctx_(nullptr),
|
||||||
peer_(nullptr),
|
peer_(nullptr),
|
||||||
ice_handler_vtbl_(nullptr),
|
ice_handler_vtbl_(nullptr),
|
||||||
ice_handler_(nullptr)
|
ice_handler_(nullptr),
|
||||||
{
|
trickle_(true) {
|
||||||
// XXX: offerer_ will be used eventually; placate clang in the meantime.
|
// XXX: offerer_ will be used eventually; placate clang in the meantime.
|
||||||
(void)offerer_;
|
(void)offerer_;
|
||||||
}
|
}
|
||||||
@ -265,10 +269,8 @@ class NrIceCtx {
|
|||||||
static int msg_recvd(void *obj, nr_ice_peer_ctx *pctx,
|
static int msg_recvd(void *obj, nr_ice_peer_ctx *pctx,
|
||||||
nr_ice_media_stream *stream, int component_id,
|
nr_ice_media_stream *stream, int component_id,
|
||||||
unsigned char *msg, int len);
|
unsigned char *msg, int len);
|
||||||
|
static void trickle_cb(void *arg, nr_ice_ctx *ctx, nr_ice_media_stream *stream,
|
||||||
// Iterate through all media streams and emit the candidates
|
int component_id, nr_ice_candidate *candidate);
|
||||||
// Note that we don't do trickle ICE yet
|
|
||||||
void EmitAllCandidates();
|
|
||||||
|
|
||||||
// Find a media stream by stream ptr. Gross
|
// Find a media stream by stream ptr. Gross
|
||||||
RefPtr<NrIceMediaStream> FindStream(nr_ice_media_stream *stream);
|
RefPtr<NrIceMediaStream> FindStream(nr_ice_media_stream *stream);
|
||||||
@ -284,6 +286,7 @@ class NrIceCtx {
|
|||||||
nr_ice_peer_ctx *peer_;
|
nr_ice_peer_ctx *peer_;
|
||||||
nr_ice_handler_vtbl* ice_handler_vtbl_; // Must be pointer
|
nr_ice_handler_vtbl* ice_handler_vtbl_; // Must be pointer
|
||||||
nr_ice_handler* ice_handler_; // Must be pointer
|
nr_ice_handler* ice_handler_; // Must be pointer
|
||||||
|
bool trickle_;
|
||||||
nsCOMPtr<nsIEventTarget> sts_target_; // The thread to run on
|
nsCOMPtr<nsIEventTarget> sts_target_; // The thread to run on
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -243,26 +243,6 @@ nsresult NrIceMediaStream::GetActivePair(int component,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NrIceMediaStream::EmitAllCandidates() {
|
|
||||||
char **attrs = 0;
|
|
||||||
int attrct;
|
|
||||||
int r;
|
|
||||||
r = nr_ice_media_stream_get_attributes(stream_,
|
|
||||||
&attrs, &attrct);
|
|
||||||
if (r) {
|
|
||||||
MOZ_MTLOG(ML_ERROR, "Couldn't get ICE candidates for '"
|
|
||||||
<< name_ << "'");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<attrct; i++) {
|
|
||||||
SignalCandidate(this, attrs[i]);
|
|
||||||
RFREE(attrs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
RFREE(attrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult NrIceMediaStream::GetCandidatePairs(std::vector<NrIceCandidatePair>*
|
nsresult NrIceMediaStream::GetCandidatePairs(std::vector<NrIceCandidatePair>*
|
||||||
out_pairs) const {
|
out_pairs) const {
|
||||||
MOZ_ASSERT(out_pairs);
|
MOZ_ASSERT(out_pairs);
|
||||||
@ -332,23 +312,35 @@ nsresult NrIceMediaStream::GetDefaultCandidate(int component,
|
|||||||
r = nr_ice_media_stream_get_default_candidate(stream_,
|
r = nr_ice_media_stream_get_default_candidate(stream_,
|
||||||
component, &cand);
|
component, &cand);
|
||||||
if (r) {
|
if (r) {
|
||||||
MOZ_MTLOG(ML_ERROR, "Couldn't get default ICE candidate for '"
|
if (ctx_->generating_trickle()) {
|
||||||
<< name_ << "'");
|
// Generate default trickle candidates.
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
// draft-ivov-mmusic-trickle-ice-01.txt says to use port 9
|
||||||
|
// but "::" instead of "0.0.0.0". Since we don't do any
|
||||||
|
// IPv6 we are ignoring that for now.
|
||||||
|
*addrp = "0.0.0.0";
|
||||||
|
*portp = 9;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MOZ_MTLOG(ML_ERROR, "Couldn't get default ICE candidate for '"
|
||||||
|
<< name_ << "'");
|
||||||
|
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
char addr[64]; // Enough for IPv6 with colons.
|
||||||
|
r = nr_transport_addr_get_addrstring(&cand->addr,addr,sizeof(addr));
|
||||||
|
if (r)
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
char addr[64]; // Enough for IPv6 with colons.
|
int port;
|
||||||
r = nr_transport_addr_get_addrstring(&cand->addr,addr,sizeof(addr));
|
r=nr_transport_addr_get_port(&cand->addr,&port);
|
||||||
if (r)
|
if (r)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
int port;
|
*addrp = addr;
|
||||||
r=nr_transport_addr_get_port(&cand->addr,&port);
|
*portp = port;
|
||||||
if (r)
|
}
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
|
|
||||||
*addrp = addr;
|
|
||||||
*portp = port;
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,12 @@ struct NrIceCandidatePair {
|
|||||||
// TODO(bcampen@mozilla.com): Is it important to put the foundation in here?
|
// TODO(bcampen@mozilla.com): Is it important to put the foundation in here?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Abstract base class for opaque values.
|
||||||
|
class NrIceOpaque {
|
||||||
|
public:
|
||||||
|
virtual ~NrIceOpaque() {}
|
||||||
|
};
|
||||||
|
|
||||||
class NrIceMediaStream {
|
class NrIceMediaStream {
|
||||||
public:
|
public:
|
||||||
static RefPtr<NrIceMediaStream> Create(NrIceCtx *ctx,
|
static RefPtr<NrIceMediaStream> Create(NrIceCtx *ctx,
|
||||||
@ -164,6 +170,12 @@ class NrIceMediaStream {
|
|||||||
// the context has been destroyed.
|
// the context has been destroyed.
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
|
// Set an opaque value. Owned by the media stream.
|
||||||
|
void SetOpaque(NrIceOpaque *opaque) { opaque_ = opaque; }
|
||||||
|
|
||||||
|
// Get the opaque
|
||||||
|
NrIceOpaque* opaque() const { return opaque_; }
|
||||||
|
|
||||||
sigslot::signal2<NrIceMediaStream *, const std::string& >
|
sigslot::signal2<NrIceMediaStream *, const std::string& >
|
||||||
SignalCandidate; // A new ICE candidate:
|
SignalCandidate; // A new ICE candidate:
|
||||||
sigslot::signal1<NrIceMediaStream *> SignalReady; // Candidate pair ready.
|
sigslot::signal1<NrIceMediaStream *> SignalReady; // Candidate pair ready.
|
||||||
@ -171,10 +183,6 @@ class NrIceMediaStream {
|
|||||||
sigslot::signal4<NrIceMediaStream *, int, const unsigned char *, int>
|
sigslot::signal4<NrIceMediaStream *, int, const unsigned char *, int>
|
||||||
SignalPacketReceived; // Incoming packet
|
SignalPacketReceived; // Incoming packet
|
||||||
|
|
||||||
// Emit all the ICE candidates. Note that this doesn't
|
|
||||||
// work for trickle ICE yet--called internally
|
|
||||||
void EmitAllCandidates();
|
|
||||||
|
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceMediaStream)
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(NrIceMediaStream)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -184,7 +192,8 @@ class NrIceMediaStream {
|
|||||||
ctx_(ctx),
|
ctx_(ctx),
|
||||||
name_(name),
|
name_(name),
|
||||||
components_(components),
|
components_(components),
|
||||||
stream_(nullptr) {}
|
stream_(nullptr),
|
||||||
|
opaque_(nullptr) {}
|
||||||
|
|
||||||
DISALLOW_COPY_ASSIGN(NrIceMediaStream);
|
DISALLOW_COPY_ASSIGN(NrIceMediaStream);
|
||||||
|
|
||||||
@ -193,6 +202,7 @@ class NrIceMediaStream {
|
|||||||
const std::string name_;
|
const std::string name_;
|
||||||
const int components_;
|
const int components_;
|
||||||
nr_ice_media_stream *stream_;
|
nr_ice_media_stream *stream_;
|
||||||
|
ScopedDeletePtr<NrIceOpaque> opaque_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,13 +54,16 @@ const uint16_t kDefaultStunServerPort=3478;
|
|||||||
const std::string kBogusIceCandidate(
|
const std::string kBogusIceCandidate(
|
||||||
(char *)"candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ");
|
(char *)"candidate:0 2 UDP 2113601790 192.168.178.20 50769 typ");
|
||||||
|
|
||||||
|
std::string g_stun_server_address(kDefaultStunServerAddress);
|
||||||
|
std::string g_stun_server_hostname(kDefaultStunServerHostname);
|
||||||
std::string g_turn_server;
|
std::string g_turn_server;
|
||||||
std::string g_turn_user;
|
std::string g_turn_user;
|
||||||
std::string g_turn_password;
|
std::string g_turn_password;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
enum TrickleMode { TRICKLE_NONE, TRICKLE_DEFERRED };
|
enum TrickleMode { TRICKLE_NONE, TRICKLE_SIMULATE, TRICKLE_REAL };
|
||||||
|
|
||||||
typedef bool (*CandidateFilter)(const std::string& candidate);
|
typedef bool (*CandidateFilter)(const std::string& candidate);
|
||||||
|
|
||||||
static bool IsRelayCandidate(const std::string& candidate) {
|
static bool IsRelayCandidate(const std::string& candidate) {
|
||||||
@ -128,7 +131,9 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
remote_(nullptr),
|
remote_(nullptr),
|
||||||
candidate_filter_(nullptr),
|
candidate_filter_(nullptr),
|
||||||
expected_local_type_(NrIceCandidate::ICE_HOST),
|
expected_local_type_(NrIceCandidate::ICE_HOST),
|
||||||
expected_remote_type_(NrIceCandidate::ICE_HOST) {
|
expected_remote_type_(NrIceCandidate::ICE_HOST),
|
||||||
|
trickle_mode_(TRICKLE_NONE),
|
||||||
|
trickled_(0) {
|
||||||
ice_ctx_->SignalGatheringCompleted.connect(this,
|
ice_ctx_->SignalGatheringCompleted.connect(this,
|
||||||
&IceTestPeer::GatheringComplete);
|
&IceTestPeer::GatheringComplete);
|
||||||
ice_ctx_->SignalCompleted.connect(this, &IceTestPeer::IceCompleted);
|
ice_ctx_->SignalCompleted.connect(this, &IceTestPeer::IceCompleted);
|
||||||
@ -154,7 +159,7 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
|
|
||||||
ASSERT_TRUE(stream);
|
ASSERT_TRUE(stream);
|
||||||
streams_.push_back(stream);
|
streams_.push_back(stream);
|
||||||
stream->SignalCandidate.connect(this, &IceTestPeer::GotCandidate);
|
stream->SignalCandidate.connect(this, &IceTestPeer::CandidateInitialized);
|
||||||
stream->SignalReady.connect(this, &IceTestPeer::StreamReady);
|
stream->SignalReady.connect(this, &IceTestPeer::StreamReady);
|
||||||
stream->SignalFailed.connect(this, &IceTestPeer::StreamFailed);
|
stream->SignalFailed.connect(this, &IceTestPeer::StreamFailed);
|
||||||
stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
|
stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
|
||||||
@ -189,11 +194,11 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
void SetFakeResolver() {
|
void SetFakeResolver() {
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
|
ASSERT_TRUE(NS_SUCCEEDED(dns_resolver_->Init()));
|
||||||
PRNetAddr addr;
|
PRNetAddr addr;
|
||||||
PRStatus status = PR_StringToNetAddr(kDefaultStunServerAddress.c_str(),
|
PRStatus status = PR_StringToNetAddr(g_stun_server_address.c_str(),
|
||||||
&addr);
|
&addr);
|
||||||
addr.inet.port = kDefaultStunServerPort;
|
addr.inet.port = kDefaultStunServerPort;
|
||||||
ASSERT_EQ(PR_SUCCESS, status);
|
ASSERT_EQ(PR_SUCCESS, status);
|
||||||
fake_resolver_.SetAddr(kDefaultStunServerHostname, addr);
|
fake_resolver_.SetAddr(g_stun_server_hostname, addr);
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
|
ASSERT_TRUE(NS_SUCCEEDED(ice_ctx_->SetResolver(
|
||||||
fake_resolver_.AllocateResolver())));
|
fake_resolver_.AllocateResolver())));
|
||||||
}
|
}
|
||||||
@ -219,7 +224,18 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
return ice_ctx_->GetGlobalAttributes();
|
return ice_ctx_->GetGlobalAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetCandidates(size_t stream) {
|
std::vector<std::string> GetCandidates(size_t stream) {
|
||||||
|
std::vector<std::string> v;
|
||||||
|
|
||||||
|
RUN_ON_THREAD(
|
||||||
|
test_utils->sts_target(),
|
||||||
|
WrapRunnableRet(this, &IceTestPeer::GetCandidates_s, stream, &v),
|
||||||
|
NS_DISPATCH_SYNC);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> GetCandidates_s(size_t stream) {
|
||||||
std::vector<std::string> candidates;
|
std::vector<std::string> candidates;
|
||||||
|
|
||||||
if (stream >= streams_.size())
|
if (stream >= streams_.size())
|
||||||
@ -239,7 +255,8 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
return candidates;
|
return candidates;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetExpectedTypes(NrIceCandidate::Type local, NrIceCandidate::Type remote) {
|
void SetExpectedTypes(NrIceCandidate::Type local,
|
||||||
|
NrIceCandidate::Type remote) {
|
||||||
expected_local_type_ = local;
|
expected_local_type_ = local;
|
||||||
expected_remote_type_ = remote;
|
expected_remote_type_ = remote;
|
||||||
}
|
}
|
||||||
@ -254,46 +271,53 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
size_t sent() { return sent_; }
|
size_t sent() { return sent_; }
|
||||||
|
|
||||||
// Start connecting to another peer
|
// Start connecting to another peer
|
||||||
void Connect(IceTestPeer *remote, TrickleMode trickle_mode,
|
void Connect_s(IceTestPeer *remote, TrickleMode trickle_mode,
|
||||||
bool start = true) {
|
bool start = true) {
|
||||||
nsresult res;
|
nsresult res;
|
||||||
|
|
||||||
remote_ = remote;
|
remote_ = remote;
|
||||||
|
|
||||||
test_utils->sts_target()->Dispatch(
|
trickle_mode_ = trickle_mode;
|
||||||
WrapRunnableRet(ice_ctx_,
|
res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes());
|
||||||
&NrIceCtx::ParseGlobalAttributes, remote->GetGlobalAttributes(), &res),
|
|
||||||
NS_DISPATCH_SYNC);
|
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
|
|
||||||
if (trickle_mode == TRICKLE_NONE) {
|
if (trickle_mode == TRICKLE_NONE ||
|
||||||
|
trickle_mode == TRICKLE_REAL) {
|
||||||
for (size_t i=0; i<streams_.size(); ++i) {
|
for (size_t i=0; i<streams_.size(); ++i) {
|
||||||
test_utils->sts_target()->Dispatch(
|
std::vector<std::string> candidates =
|
||||||
WrapRunnableRet(streams_[i], &NrIceMediaStream::ParseAttributes,
|
remote->GetCandidates(i);
|
||||||
remote->GetCandidates(i),
|
|
||||||
&res), NS_DISPATCH_SYNC);
|
|
||||||
|
|
||||||
|
for (size_t j=0; j<candidates.size(); ++j) {
|
||||||
|
std::cerr << "Candidate: " + candidates[j] << std::endl;
|
||||||
|
}
|
||||||
|
res = streams_[i]->ParseAttributes(candidates);
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Parse empty attributes and then trickle them out later
|
// Parse empty attributes and then trickle them out later
|
||||||
for (size_t i=0; i<streams_.size(); ++i) {
|
for (size_t i=0; i<streams_.size(); ++i) {
|
||||||
std::vector<std::string> empty_attrs;
|
std::vector<std::string> empty_attrs;
|
||||||
test_utils->sts_target()->Dispatch(
|
res = streams_[i]->ParseAttributes(empty_attrs);
|
||||||
WrapRunnableRet(streams_[i], &NrIceMediaStream::ParseAttributes,
|
|
||||||
empty_attrs,
|
|
||||||
&res), NS_DISPATCH_SYNC);
|
|
||||||
|
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start) {
|
if (start) {
|
||||||
StartChecks();
|
// Now start checks
|
||||||
|
res = ice_ctx_->StartChecks();
|
||||||
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoTrickle(size_t stream) {
|
void Connect(IceTestPeer *remote, TrickleMode trickle_mode,
|
||||||
|
bool start = true) {
|
||||||
|
test_utils->sts_target()->Dispatch(
|
||||||
|
WrapRunnable(
|
||||||
|
this, &IceTestPeer::Connect_s, remote, trickle_mode, start),
|
||||||
|
NS_DISPATCH_SYNC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimulateTrickle(size_t stream) {
|
||||||
std::cerr << "Doing trickle for stream " << stream << std::endl;
|
std::cerr << "Doing trickle for stream " << stream << std::endl;
|
||||||
// If we are in trickle deferred mode, now trickle in the candidates
|
// If we are in trickle deferred mode, now trickle in the candidates
|
||||||
// for |stream}
|
// for |stream}
|
||||||
@ -392,12 +416,41 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
|
|
||||||
// Handle events
|
// Handle events
|
||||||
void GatheringComplete(NrIceCtx *ctx) {
|
void GatheringComplete(NrIceCtx *ctx) {
|
||||||
|
std::cerr << "Gathering complete for " << name_ << std::endl;
|
||||||
gathering_complete_ = true;
|
gathering_complete_ = true;
|
||||||
|
|
||||||
|
std::cerr << "CANDIDATES:" << std::endl;
|
||||||
|
for (size_t i=0; i<streams_.size(); ++i) {
|
||||||
|
std::cerr << "Stream " << name_ << std::endl;
|
||||||
|
std::vector<std::string> candidates =
|
||||||
|
streams_[i]->GetCandidates();
|
||||||
|
|
||||||
|
for(size_t j=0; j<candidates.size(); ++j) {
|
||||||
|
std::cerr << candidates[j] << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cerr << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GotCandidate(NrIceMediaStream *stream, const std::string &candidate) {
|
void CandidateInitialized(NrIceMediaStream *stream, const std::string &candidate) {
|
||||||
std::cerr << "Got candidate " << candidate << std::endl;
|
std::cerr << "Candidate initialized: " << candidate << std::endl;
|
||||||
candidates_[stream->name()].push_back(candidate);
|
candidates_[stream->name()].push_back(candidate);
|
||||||
|
|
||||||
|
// If we are connected, then try to trickle to the
|
||||||
|
// other side.
|
||||||
|
if (remote_ && remote_->remote_) {
|
||||||
|
std::vector<mozilla::RefPtr<NrIceMediaStream> >::iterator it =
|
||||||
|
std::find(streams_.begin(), streams_.end(), stream);
|
||||||
|
ASSERT_NE(streams_.end(), it);
|
||||||
|
size_t index = it - streams_.begin();
|
||||||
|
|
||||||
|
ASSERT_GT(remote_->streams_.size(), index);
|
||||||
|
nsresult res = remote_->streams_[index]->ParseTrickleCandidate(
|
||||||
|
candidate);
|
||||||
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
|
++trickled_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult GetCandidatePairs(size_t stream_index,
|
nsresult GetCandidatePairs(size_t stream_index,
|
||||||
@ -570,6 +623,8 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int trickled() { return trickled_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
nsRefPtr<NrIceCtx> ice_ctx_;
|
nsRefPtr<NrIceCtx> ice_ctx_;
|
||||||
@ -586,6 +641,8 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
CandidateFilter candidate_filter_;
|
CandidateFilter candidate_filter_;
|
||||||
NrIceCandidate::Type expected_local_type_;
|
NrIceCandidate::Type expected_local_type_;
|
||||||
NrIceCandidate::Type expected_remote_type_;
|
NrIceCandidate::Type expected_remote_type_;
|
||||||
|
TrickleMode trickle_mode_;
|
||||||
|
int trickled_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IceGatherTest : public ::testing::Test {
|
class IceGatherTest : public ::testing::Test {
|
||||||
@ -598,9 +655,15 @@ class IceGatherTest : public ::testing::Test {
|
|||||||
peer_->AddStream(1);
|
peer_->AddStream(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gather() {
|
void Gather(bool wait = true) {
|
||||||
peer_->Gather();
|
peer_->Gather();
|
||||||
|
|
||||||
|
if (wait) {
|
||||||
|
WaitForGather();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitForGather() {
|
||||||
ASSERT_TRUE_WAIT(peer_->gathering_complete(), 10000);
|
ASSERT_TRUE_WAIT(peer_->gathering_complete(), 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,18 +718,19 @@ class IceConnectTest : public ::testing::Test {
|
|||||||
|
|
||||||
bool Gather(bool wait) {
|
bool Gather(bool wait) {
|
||||||
Init(false);
|
Init(false);
|
||||||
p1_->SetStunServer(kDefaultStunServerAddress, kDefaultStunServerPort);
|
p1_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
|
||||||
p2_->SetStunServer(kDefaultStunServerAddress, kDefaultStunServerPort);
|
p2_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
|
||||||
p1_->Gather();
|
p1_->Gather();
|
||||||
p2_->Gather();
|
p2_->Gather();
|
||||||
|
|
||||||
EXPECT_TRUE_WAIT(p1_->gathering_complete(), 10000);
|
if (wait) {
|
||||||
if (!p1_->gathering_complete())
|
EXPECT_TRUE_WAIT(p1_->gathering_complete(), 10000);
|
||||||
return false;
|
if (!p1_->gathering_complete())
|
||||||
EXPECT_TRUE_WAIT(p2_->gathering_complete(), 10000);
|
return false;
|
||||||
if (!p2_->gathering_complete())
|
EXPECT_TRUE_WAIT(p2_->gathering_complete(), 10000);
|
||||||
return false;
|
if (!p2_->gathering_complete())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -720,24 +784,29 @@ class IceConnectTest : public ::testing::Test {
|
|||||||
ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(), 5000);
|
ASSERT_TRUE_WAIT(p1_->ice_complete() && p2_->ice_complete(), 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectTrickle() {
|
void WaitForGather() {
|
||||||
p1_->Connect(p2_, TRICKLE_DEFERRED);
|
ASSERT_TRUE_WAIT(p1_->gathering_complete(), 10000);
|
||||||
p2_->Connect(p1_, TRICKLE_DEFERRED);
|
ASSERT_TRUE_WAIT(p2_->gathering_complete(), 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoTrickle(size_t stream) {
|
void ConnectTrickle(TrickleMode trickle = TRICKLE_SIMULATE) {
|
||||||
p1_->DoTrickle(stream);
|
p1_->Connect(p2_, trickle);
|
||||||
p2_->DoTrickle(stream);
|
p2_->Connect(p1_, trickle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimulateTrickle(size_t stream) {
|
||||||
|
p1_->SimulateTrickle(stream);
|
||||||
|
p2_->SimulateTrickle(stream);
|
||||||
ASSERT_TRUE_WAIT(p1_->is_ready(stream), 5000);
|
ASSERT_TRUE_WAIT(p1_->is_ready(stream), 5000);
|
||||||
ASSERT_TRUE_WAIT(p2_->is_ready(stream), 5000);
|
ASSERT_TRUE_WAIT(p2_->is_ready(stream), 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoTrickleP1(size_t stream) {
|
void SimulateTrickleP1(size_t stream) {
|
||||||
p1_->DoTrickle(stream);
|
p1_->SimulateTrickle(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DoTrickleP2(size_t stream) {
|
void SimulateTrickleP2(size_t stream) {
|
||||||
p2_->DoTrickle(stream);
|
p2_->SimulateTrickle(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerifyConnected() {
|
void VerifyConnected() {
|
||||||
@ -828,18 +897,18 @@ class PrioritizerTest : public ::testing::Test {
|
|||||||
} // end namespace
|
} // end namespace
|
||||||
|
|
||||||
TEST_F(IceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
|
TEST_F(IceGatherTest, TestGatherFakeStunServerHostnameNoResolver) {
|
||||||
peer_->SetStunServer(kDefaultStunServerHostname, kDefaultStunServerPort);
|
peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
|
||||||
Gather();
|
Gather();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IceGatherTest, TestGatherFakeStunServerIpAddress) {
|
TEST_F(IceGatherTest, TestGatherFakeStunServerIpAddress) {
|
||||||
peer_->SetStunServer(kDefaultStunServerAddress, kDefaultStunServerPort);
|
peer_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
|
||||||
peer_->SetFakeResolver();
|
peer_->SetFakeResolver();
|
||||||
Gather();
|
Gather();
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IceGatherTest, TestGatherFakeStunServerHostname) {
|
TEST_F(IceGatherTest, TestGatherFakeStunServerHostname) {
|
||||||
peer_->SetStunServer(kDefaultStunServerHostname, kDefaultStunServerPort);
|
peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
|
||||||
peer_->SetFakeResolver();
|
peer_->SetFakeResolver();
|
||||||
Gather();
|
Gather();
|
||||||
}
|
}
|
||||||
@ -851,14 +920,14 @@ TEST_F(IceGatherTest, TestGatherFakeStunBogusHostname) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddress) {
|
TEST_F(IceGatherTest, TestGatherDNSStunServerIpAddress) {
|
||||||
peer_->SetStunServer(kDefaultStunServerAddress, kDefaultStunServerPort);
|
peer_->SetStunServer(g_stun_server_address, kDefaultStunServerPort);
|
||||||
peer_->SetDNSResolver();
|
peer_->SetDNSResolver();
|
||||||
Gather();
|
Gather();
|
||||||
// TODO(jib@mozilla.com): ensure we get server reflexive candidates Bug 848094
|
// TODO(jib@mozilla.com): ensure we get server reflexive candidates Bug 848094
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IceGatherTest, TestGatherDNSStunServerHostname) {
|
TEST_F(IceGatherTest, TestGatherDNSStunServerHostname) {
|
||||||
peer_->SetStunServer(kDefaultStunServerHostname, kDefaultStunServerPort);
|
peer_->SetStunServer(g_stun_server_hostname, kDefaultStunServerPort);
|
||||||
peer_->SetDNSResolver();
|
peer_->SetDNSResolver();
|
||||||
Gather();
|
Gather();
|
||||||
}
|
}
|
||||||
@ -923,6 +992,16 @@ TEST_F(IceGatherTest, TestStunServerReturnsLoopbackAddr) {
|
|||||||
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 "));
|
ASSERT_FALSE(StreamHasMatchingCandidate(0, " 127.0.0.133 "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(IceGatherTest, TestStunServerTrickle) {
|
||||||
|
UseFakeStunServerWithResponse("192.0.2.1", 3333);
|
||||||
|
TestStunServer::GetInstance()->SetActive(false);
|
||||||
|
Gather(false);
|
||||||
|
ASSERT_FALSE(StreamHasMatchingCandidate(0, "192.0.2.1"));
|
||||||
|
TestStunServer::GetInstance()->SetActive(true);
|
||||||
|
WaitForGather();
|
||||||
|
ASSERT_TRUE(StreamHasMatchingCandidate(0, "192.0.2.1"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(IceConnectTest, TestGather) {
|
TEST_F(IceConnectTest, TestGather) {
|
||||||
AddStream("first", 1);
|
AddStream("first", 1);
|
||||||
ASSERT_TRUE(Gather(true));
|
ASSERT_TRUE(Gather(true));
|
||||||
@ -970,8 +1049,8 @@ TEST_F(IceConnectTest, TestConnectP2ThenP1Trickle) {
|
|||||||
ASSERT_TRUE(Gather(true));
|
ASSERT_TRUE(Gather(true));
|
||||||
ConnectP2();
|
ConnectP2();
|
||||||
PR_Sleep(1000);
|
PR_Sleep(1000);
|
||||||
ConnectP1(TRICKLE_DEFERRED);
|
ConnectP1(TRICKLE_SIMULATE);
|
||||||
DoTrickleP1(0);
|
SimulateTrickleP1(0);
|
||||||
WaitForComplete();
|
WaitForComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -981,12 +1060,12 @@ TEST_F(IceConnectTest, TestConnectP2ThenP1TrickleTwoComponents) {
|
|||||||
ASSERT_TRUE(Gather(true));
|
ASSERT_TRUE(Gather(true));
|
||||||
ConnectP2();
|
ConnectP2();
|
||||||
PR_Sleep(1000);
|
PR_Sleep(1000);
|
||||||
ConnectP1(TRICKLE_DEFERRED);
|
ConnectP1(TRICKLE_SIMULATE);
|
||||||
DoTrickleP1(0);
|
SimulateTrickleP1(0);
|
||||||
std::cerr << "Sleeping between trickle streams" << std::endl;
|
std::cerr << "Sleeping between trickle streams" << std::endl;
|
||||||
PR_Sleep(1000); // Give this some time to settle but not complete
|
PR_Sleep(1000); // Give this some time to settle but not complete
|
||||||
// all of ICE.
|
// all of ICE.
|
||||||
DoTrickleP1(1);
|
SimulateTrickleP1(1);
|
||||||
WaitForComplete(2);
|
WaitForComplete(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1001,7 +1080,7 @@ TEST_F(IceConnectTest, TestConnectTrickleOneStreamOneComponent) {
|
|||||||
AddStream("first", 1);
|
AddStream("first", 1);
|
||||||
ASSERT_TRUE(Gather(true));
|
ASSERT_TRUE(Gather(true));
|
||||||
ConnectTrickle();
|
ConnectTrickle();
|
||||||
DoTrickle(0);
|
SimulateTrickle(0);
|
||||||
ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
|
ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
|
||||||
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
|
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
|
||||||
}
|
}
|
||||||
@ -1011,12 +1090,21 @@ TEST_F(IceConnectTest, TestConnectTrickleTwoStreamsOneComponent) {
|
|||||||
AddStream("second", 1);
|
AddStream("second", 1);
|
||||||
ASSERT_TRUE(Gather(true));
|
ASSERT_TRUE(Gather(true));
|
||||||
ConnectTrickle();
|
ConnectTrickle();
|
||||||
DoTrickle(0);
|
SimulateTrickle(0);
|
||||||
DoTrickle(1);
|
SimulateTrickle(1);
|
||||||
ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
|
ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
|
||||||
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
|
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(IceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
|
||||||
|
AddStream("first", 1);
|
||||||
|
AddStream("second", 1);
|
||||||
|
ASSERT_TRUE(Gather(false));
|
||||||
|
ConnectTrickle(TRICKLE_REAL);
|
||||||
|
ASSERT_TRUE_WAIT(p1_->ice_complete(), 5000);
|
||||||
|
ASSERT_TRUE_WAIT(p2_->ice_complete(), 5000);
|
||||||
|
WaitForGather(); // ICE can complete before we finish gathering.
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(IceConnectTest, TestSendReceive) {
|
TEST_F(IceConnectTest, TestSendReceive) {
|
||||||
AddStream("first", 1);
|
AddStream("first", 1);
|
||||||
@ -1195,6 +1283,15 @@ int main(int argc, char **argv)
|
|||||||
g_turn_server="";
|
g_turn_server="";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string tmp = get_environment("STUN_SERVER_ADDRESS");
|
||||||
|
if (tmp != "")
|
||||||
|
g_stun_server_address = tmp;
|
||||||
|
|
||||||
|
|
||||||
|
tmp = get_environment("STUN_SERVER_HOSTNAME");
|
||||||
|
if (tmp != "")
|
||||||
|
g_stun_server_hostname = tmp;
|
||||||
|
|
||||||
test_utils = new MtransportTestUtils();
|
test_utils = new MtransportTestUtils();
|
||||||
NSS_NoDB_Init(nullptr);
|
NSS_NoDB_Init(nullptr);
|
||||||
NSS_SetDomesticPolicy();
|
NSS_SetDomesticPolicy();
|
||||||
|
@ -416,8 +416,8 @@ static void nr_ice_candidate_fire_ready_cb(NR_SOCKET s, int how, void *cb_arg)
|
|||||||
{
|
{
|
||||||
nr_ice_candidate *cand = cb_arg;
|
nr_ice_candidate *cand = cb_arg;
|
||||||
|
|
||||||
cand->ready_cb(0, 0, cand->ready_cb_arg);
|
|
||||||
cand->ready_cb_timer = 0;
|
cand->ready_cb_timer = 0;
|
||||||
|
cand->ready_cb(0, 0, cand->ready_cb_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg)
|
int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, void *cb_arg)
|
||||||
|
@ -249,7 +249,7 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon
|
|||||||
ABORT(r);
|
ABORT(r);
|
||||||
cand->state=NR_ICE_CAND_STATE_INITIALIZING; /* Don't start */
|
cand->state=NR_ICE_CAND_STATE_INITIALIZING; /* Don't start */
|
||||||
cand->done_cb=nr_ice_initialize_finished_cb;
|
cand->done_cb=nr_ice_initialize_finished_cb;
|
||||||
cand->cb_arg=ctx;
|
cand->cb_arg=cand;
|
||||||
|
|
||||||
TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
|
TAILQ_INSERT_TAIL(&component->candidates,cand,entry_comp);
|
||||||
component->candidate_ct++;
|
component->candidate_ct++;
|
||||||
@ -315,7 +315,7 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon
|
|||||||
cand=TAILQ_FIRST(&component->candidates);
|
cand=TAILQ_FIRST(&component->candidates);
|
||||||
while(cand){
|
while(cand){
|
||||||
if(cand->state!=NR_ICE_CAND_STATE_INITIALIZING){
|
if(cand->state!=NR_ICE_CAND_STATE_INITIALIZING){
|
||||||
if(r=nr_ice_candidate_initialize(cand,nr_ice_initialize_finished_cb,ctx)){
|
if(r=nr_ice_candidate_initialize(cand,nr_ice_initialize_finished_cb,cand)){
|
||||||
if(r!=R_WOULDBLOCK){
|
if(r!=R_WOULDBLOCK){
|
||||||
ctx->uninitialized_candidates--;
|
ctx->uninitialized_candidates--;
|
||||||
cand->state=NR_ICE_CAND_STATE_FAILED;
|
cand->state=NR_ICE_CAND_STATE_FAILED;
|
||||||
@ -330,74 +330,64 @@ int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *compon
|
|||||||
return(_status);
|
return(_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prune redundant candidates. We use an n^2 algorithm for now.
|
/*
|
||||||
|
Compare this newly initialized candidate against the other initialized
|
||||||
|
candidates and discard the lower-priority one if they are redundant.
|
||||||
|
|
||||||
This algorithm combined with the other algorithms, favors
|
This algorithm combined with the other algorithms, favors
|
||||||
host > srflx > relay
|
host > srflx > relay
|
||||||
|
|
||||||
This actually won't prune relayed in the very rare
|
This actually won't prune relayed in the very rare
|
||||||
case that relayed is the same. Not relevant in practice.
|
case that relayed is the same. Not relevant in practice.
|
||||||
*/
|
*/
|
||||||
|
int nr_ice_component_maybe_prune_candidate(nr_ice_ctx *ctx, nr_ice_component *comp, nr_ice_candidate *c1, int *was_pruned)
|
||||||
int nr_ice_component_prune_candidates(nr_ice_ctx *ctx, nr_ice_component *comp)
|
|
||||||
{
|
{
|
||||||
nr_ice_candidate *c1,*c1n,*c2;
|
nr_ice_candidate *c2, *tmp = NULL;
|
||||||
|
|
||||||
c1=TAILQ_FIRST(&comp->candidates);
|
*was_pruned = 0;
|
||||||
while(c1){
|
c2 = TAILQ_FIRST(&comp->candidates);
|
||||||
c1n=TAILQ_NEXT(c1,entry_comp);
|
while(c2){
|
||||||
if(c1->state!=NR_ICE_CAND_STATE_INITIALIZED){
|
if((c1 != c2) &&
|
||||||
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Removing non-initialized candidate %s",
|
(c2->state == NR_ICE_CAND_STATE_INITIALIZED) &&
|
||||||
ctx->label,c1->label);
|
!nr_transport_addr_cmp(&c1->base,&c2->base,NR_TRANSPORT_ADDR_CMP_MODE_ALL) &&
|
||||||
if (c1->state == NR_ICE_CAND_STATE_INITIALIZING) {
|
!nr_transport_addr_cmp(&c1->addr,&c2->addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL)){
|
||||||
r_log(LOG_ICE,LOG_NOTICE, "ICE(%s): Removing candidate %s which is in INITIALIZING state",
|
|
||||||
ctx->label, c1->label);
|
|
||||||
}
|
|
||||||
TAILQ_REMOVE(&comp->candidates,c1,entry_comp);
|
|
||||||
comp->candidate_ct--;
|
|
||||||
TAILQ_REMOVE(&c1->isock->candidates,c1,entry_sock);
|
|
||||||
/* schedule this delete for later as we don't want to delete the underlying
|
|
||||||
* objects while in the middle of a callback on one of those objects */
|
|
||||||
NR_ASYNC_SCHEDULE(nr_ice_candidate_destroy_cb,c1);
|
|
||||||
goto next_c1;
|
|
||||||
}
|
|
||||||
|
|
||||||
c2=TAILQ_NEXT(c1,entry_comp);
|
if((c1->type == c2->type) ||
|
||||||
|
(c1->type==HOST && c2->type == SERVER_REFLEXIVE) ||
|
||||||
|
(c2->type==HOST && c1->type == SERVER_REFLEXIVE)){
|
||||||
|
|
||||||
while(c2){
|
/*
|
||||||
nr_ice_candidate *tmp;
|
These are redundant. Remove the lower pri one.
|
||||||
|
|
||||||
if(!nr_transport_addr_cmp(&c1->base,&c2->base,NR_TRANSPORT_ADDR_CMP_MODE_ALL) && !nr_transport_addr_cmp(&c1->addr,&c2->addr,NR_TRANSPORT_ADDR_CMP_MODE_ALL)){
|
Since this algorithmis run whenever a new candidate
|
||||||
|
is initialized, there should at most one duplicate.
|
||||||
if((c1->type == c2->type) ||
|
*/
|
||||||
(c1->type==HOST && c2->type == SERVER_REFLEXIVE) ||
|
if (c1->priority < c2->priority) {
|
||||||
(c2->type==HOST && c1->type == SERVER_REFLEXIVE)){
|
tmp = c1;
|
||||||
|
*was_pruned = 1;
|
||||||
/* OK these are redundant. Remove the lower pri one */
|
|
||||||
tmp=c2;
|
|
||||||
c2=TAILQ_NEXT(c2,entry_comp);
|
|
||||||
if(c1n==tmp)
|
|
||||||
c1n=c2;
|
|
||||||
|
|
||||||
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Removing redundant candidate %s",
|
|
||||||
ctx->label,tmp->label);
|
|
||||||
|
|
||||||
TAILQ_REMOVE(&comp->candidates,tmp,entry_comp);
|
|
||||||
comp->candidate_ct--;
|
|
||||||
TAILQ_REMOVE(&tmp->isock->candidates,tmp,entry_sock);
|
|
||||||
|
|
||||||
nr_ice_candidate_destroy(&tmp);
|
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
else{
|
tmp = c2;
|
||||||
c2=TAILQ_NEXT(c2,entry_comp);
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next_c1:
|
|
||||||
c1=c1n;
|
c2=TAILQ_NEXT(c2,entry_comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(0);
|
if (tmp) {
|
||||||
|
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Removing redundant candidate %s",
|
||||||
|
ctx->label,tmp->label);
|
||||||
|
|
||||||
|
TAILQ_REMOVE(&comp->candidates,tmp,entry_comp);
|
||||||
|
comp->candidate_ct--;
|
||||||
|
TAILQ_REMOVE(&tmp->isock->candidates,tmp,entry_sock);
|
||||||
|
|
||||||
|
nr_ice_candidate_destroy(&tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Section 7.2.1 */
|
/* Section 7.2.1 */
|
||||||
@ -652,74 +642,85 @@ int nr_ice_component_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_c
|
|||||||
return(_status);
|
return(_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp,nr_ice_component *pcomp)
|
int nr_ice_component_pair_candidate(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, nr_ice_candidate *lcand, int pair_all_remote)
|
||||||
{
|
{
|
||||||
nr_ice_candidate *lcand,*pcand;
|
int r, _status;
|
||||||
|
nr_ice_candidate *pcand;
|
||||||
nr_ice_cand_pair *pair=0;
|
nr_ice_cand_pair *pair=0;
|
||||||
nr_ice_socket *isock;
|
|
||||||
int r,_status;
|
|
||||||
char codeword[5];
|
char codeword[5];
|
||||||
|
|
||||||
|
nr_ice_compute_codeword(lcand->label,strlen(lcand->label),codeword);
|
||||||
|
r_log(LOG_ICE,LOG_DEBUG,"Pairing local candidate %s:%s",codeword,lcand->label);
|
||||||
|
|
||||||
|
switch(lcand->type){
|
||||||
|
case HOST:
|
||||||
|
break;
|
||||||
|
case SERVER_REFLEXIVE:
|
||||||
|
case PEER_REFLEXIVE:
|
||||||
|
/* Don't actually pair these candidates */
|
||||||
|
goto done;
|
||||||
|
break;
|
||||||
|
case RELAYED:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
ABORT(R_INTERNAL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pcand=TAILQ_FIRST(&pcomp->candidates);
|
||||||
|
while(pcand){
|
||||||
|
/*
|
||||||
|
Two modes, depending on |pair_all_remote|
|
||||||
|
|
||||||
|
1. Pair remote candidates which have not been paired
|
||||||
|
(used in initial pairing or in processing the other side's
|
||||||
|
trickle candidates).
|
||||||
|
2. Pair any remote candidate (used when processing our own
|
||||||
|
trickle candidates).
|
||||||
|
*/
|
||||||
|
if (pair_all_remote || (pcand->state == NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED)) {
|
||||||
|
/* If we are pairing our own trickle candidates, the remote candidate should
|
||||||
|
all be paired */
|
||||||
|
if (pair_all_remote)
|
||||||
|
assert (pcand->state == NR_ICE_CAND_PEER_CANDIDATE_PAIRED);
|
||||||
|
|
||||||
|
nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
|
||||||
|
r_log(LOG_ICE,LOG_DEBUG,"Pairing with peer candidate %s:%s",codeword,pcand->label);
|
||||||
|
|
||||||
|
if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
|
||||||
|
ABORT(r);
|
||||||
|
|
||||||
|
if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
|
||||||
|
pair))
|
||||||
|
ABORT(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
pcand=TAILQ_NEXT(pcand,entry_comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
_status = 0;
|
||||||
|
abort:
|
||||||
|
return(_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp,nr_ice_component *pcomp)
|
||||||
|
{
|
||||||
|
nr_ice_candidate *lcand, *pcand;
|
||||||
|
nr_ice_socket *isock;
|
||||||
|
int r,_status;
|
||||||
|
|
||||||
r_log(LOG_ICE,LOG_DEBUG,"Pairing candidates======");
|
r_log(LOG_ICE,LOG_DEBUG,"Pairing candidates======");
|
||||||
|
|
||||||
/* Create the candidate pairs */
|
/* Create the candidate pairs */
|
||||||
lcand=TAILQ_FIRST(&lcomp->candidates);
|
lcand=TAILQ_FIRST(&lcomp->candidates);
|
||||||
while(lcand){
|
while(lcand){
|
||||||
int was_paired = 0;
|
if (lcand->state == NR_ICE_CAND_STATE_INITIALIZED) {
|
||||||
|
if ((r = nr_ice_component_pair_candidate(pctx, pcomp, lcand, 0)))
|
||||||
nr_ice_compute_codeword(lcand->label,strlen(lcand->label),codeword);
|
ABORT(r);
|
||||||
r_log(LOG_ICE,LOG_DEBUG,"Examining local candidate %s:%s",codeword,lcand->label);
|
|
||||||
|
|
||||||
switch(lcand->type){
|
|
||||||
case HOST:
|
|
||||||
break;
|
|
||||||
case SERVER_REFLEXIVE:
|
|
||||||
case PEER_REFLEXIVE:
|
|
||||||
/* Don't actually pair these candidates */
|
|
||||||
goto next_cand;
|
|
||||||
break;
|
|
||||||
case RELAYED:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
ABORT(R_INTERNAL);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PAIR with each peer*/
|
|
||||||
if(TAILQ_EMPTY(&pcomp->candidates)) {
|
|
||||||
/* can happen if our peer proposes no (or all bogus) candidates */
|
|
||||||
goto next_cand;
|
|
||||||
}
|
|
||||||
pcand=TAILQ_FIRST(&pcomp->candidates);
|
|
||||||
while(pcand){
|
|
||||||
/* Only pair peer candidates which have not yet been paired.
|
|
||||||
This allows "trickle ICE". (Not yet standardized, but
|
|
||||||
part of WebRTC).
|
|
||||||
|
|
||||||
TODO(ekr@rtfm.com): Add refernece to the spec when there
|
|
||||||
is one.
|
|
||||||
*/
|
|
||||||
if (pcand->state == NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED) {
|
|
||||||
nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
|
|
||||||
r_log(LOG_ICE,LOG_DEBUG,"Examining peer candidate %s:%s",codeword,pcand->label);
|
|
||||||
|
|
||||||
if(r=nr_ice_candidate_pair_create(pctx,lcand,pcand,&pair))
|
|
||||||
ABORT(r);
|
|
||||||
|
|
||||||
if(r=nr_ice_candidate_pair_insert(&pcomp->stream->check_list,
|
|
||||||
pair))
|
|
||||||
ABORT(r);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
was_paired = 1;
|
|
||||||
}
|
|
||||||
pcand=TAILQ_NEXT(pcand,entry_comp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!pair)
|
|
||||||
goto next_cand;
|
|
||||||
|
|
||||||
next_cand:
|
|
||||||
lcand=TAILQ_NEXT(lcand,entry_comp);
|
lcand=TAILQ_NEXT(lcand,entry_comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +82,9 @@ typedef STAILQ_HEAD(nr_ice_component_head_,nr_ice_component_) nr_ice_component_h
|
|||||||
int nr_ice_component_create(struct nr_ice_media_stream_ *stream, int component_id, nr_ice_component **componentp);
|
int nr_ice_component_create(struct nr_ice_media_stream_ *stream, int component_id, nr_ice_component **componentp);
|
||||||
int nr_ice_component_destroy(nr_ice_component **componentp);
|
int nr_ice_component_destroy(nr_ice_component **componentp);
|
||||||
int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *component);
|
int nr_ice_component_initialize(struct nr_ice_ctx_ *ctx,nr_ice_component *component);
|
||||||
int nr_ice_component_prune_candidates(nr_ice_ctx *ctx, nr_ice_component *comp);
|
int nr_ice_component_maybe_prune_candidate(nr_ice_ctx *ctx, nr_ice_component *comp, nr_ice_candidate *c1, int *was_pruned);
|
||||||
int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp,nr_ice_component *pcomp);
|
int nr_ice_component_pair_candidate(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, nr_ice_candidate *lcand, int pair_all_remote);
|
||||||
|
int nr_ice_component_pair_candidates(nr_ice_peer_ctx *pctx, nr_ice_component *lcomp, nr_ice_component *pcomp);
|
||||||
int nr_ice_component_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, char *username, int *serviced);
|
int nr_ice_component_service_pre_answer_requests(nr_ice_peer_ctx *pctx, nr_ice_component *pcomp, char *username, int *serviced);
|
||||||
int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair);
|
int nr_ice_component_nominated_pair(nr_ice_component *comp, nr_ice_cand_pair *pair);
|
||||||
int nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair);
|
int nr_ice_component_failed_pair(nr_ice_component *comp, nr_ice_cand_pair *pair);
|
||||||
|
@ -64,6 +64,7 @@ static int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out);
|
|||||||
static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
|
static int nr_ice_fetch_turn_servers(int ct, nr_ice_turn_server **out);
|
||||||
#endif /* USE_TURN */
|
#endif /* USE_TURN */
|
||||||
static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
|
static void nr_ice_ctx_destroy_cb(NR_SOCKET s, int how, void *cb_arg);
|
||||||
|
static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand);
|
||||||
|
|
||||||
int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
|
int nr_ice_fetch_stun_servers(int ct, nr_ice_stun_server **out)
|
||||||
{
|
{
|
||||||
@ -431,6 +432,7 @@ int nr_ice_ctx_destroy(nr_ice_ctx **ctxp)
|
|||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
(*ctxp)->done_cb=0;
|
(*ctxp)->done_cb=0;
|
||||||
|
(*ctxp)->trickle_cb=0;
|
||||||
|
|
||||||
NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
|
NR_ASYNC_SCHEDULE(nr_ice_ctx_destroy_cb,*ctxp);
|
||||||
|
|
||||||
@ -441,13 +443,38 @@ int nr_ice_ctx_destroy(nr_ice_ctx **ctxp)
|
|||||||
|
|
||||||
void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
|
void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
|
||||||
{
|
{
|
||||||
nr_ice_ctx *ctx=cb_arg;
|
int r,_status;
|
||||||
|
nr_ice_candidate *cand=cb_arg;
|
||||||
|
nr_ice_ctx *ctx;
|
||||||
|
|
||||||
|
|
||||||
|
assert(cb_arg);
|
||||||
|
if (!cb_arg)
|
||||||
|
return;
|
||||||
|
ctx = cand->ctx;
|
||||||
|
|
||||||
/* r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): Candidate %s %s",ctx->label,
|
|
||||||
cand->label, cand->state==NR_ICE_CAND_STATE_INITIALIZED?"INITIALIZED":"FAILED");
|
|
||||||
*/
|
|
||||||
ctx->uninitialized_candidates--;
|
ctx->uninitialized_candidates--;
|
||||||
|
|
||||||
|
if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
|
||||||
|
int was_pruned = 0;
|
||||||
|
|
||||||
|
if (r=nr_ice_component_maybe_prune_candidate(ctx, cand->component,
|
||||||
|
cand, &was_pruned)) {
|
||||||
|
r_log(LOG_ICE, LOG_NOTICE, "ICE(%s): Problem pruning candidates",ctx->label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we are initialized, the candidate wasn't pruned,
|
||||||
|
and we have a trickle ICE callback fire the callback */
|
||||||
|
if (ctx->trickle_cb && !was_pruned) {
|
||||||
|
ctx->trickle_cb(ctx->trickle_cb_arg, ctx, cand->stream, cand->component_id, cand);
|
||||||
|
|
||||||
|
if (r==nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
|
||||||
|
r_log(LOG_ICE,LOG_ERR, "ICE(%s): All could not pair new trickle candidate",ctx->label);
|
||||||
|
/* But continue */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(ctx->uninitialized_candidates==0){
|
if(ctx->uninitialized_candidates==0){
|
||||||
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): All candidates initialized",ctx->label);
|
r_log(LOG_ICE,LOG_DEBUG,"ICE(%s): All candidates initialized",ctx->label);
|
||||||
ctx->state=NR_ICE_STATE_INITIALIZED;
|
ctx->state=NR_ICE_STATE_INITIALIZED;
|
||||||
@ -463,6 +490,28 @@ void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nr_ice_ctx_pair_new_trickle_candidates(nr_ice_ctx *ctx, nr_ice_candidate *cand)
|
||||||
|
{
|
||||||
|
int r,_status;
|
||||||
|
nr_ice_peer_ctx *pctx;
|
||||||
|
|
||||||
|
pctx=STAILQ_FIRST(&ctx->peers);
|
||||||
|
while(pctx){
|
||||||
|
if (pctx->state == NR_ICE_PEER_STATE_PAIRED) {
|
||||||
|
r = nr_ice_peer_ctx_pair_new_trickle_candidate(ctx, pctx, cand);
|
||||||
|
if (r)
|
||||||
|
ABORT(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
pctx=STAILQ_NEXT(pctx,entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
_status=0;
|
||||||
|
abort:
|
||||||
|
return(_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define MAXADDRS 100 // Ridiculously high
|
#define MAXADDRS 100 // Ridiculously high
|
||||||
int nr_ice_initialize(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
|
int nr_ice_initialize(nr_ice_ctx *ctx, NR_async_cb done_cb, void *cb_arg)
|
||||||
{
|
{
|
||||||
@ -689,3 +738,11 @@ int nr_ice_ctx_finalize(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
ctx->trickle_cb = cb;
|
||||||
|
ctx->trickle_cb_arg = cb_arg;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -89,6 +89,9 @@ typedef struct nr_ice_ctx_ nr_ice_ctx;
|
|||||||
typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx;
|
typedef struct nr_ice_peer_ctx_ nr_ice_peer_ctx;
|
||||||
typedef struct nr_ice_candidate_ nr_ice_candidate;
|
typedef struct nr_ice_candidate_ nr_ice_candidate;
|
||||||
typedef struct nr_ice_cand_pair_ nr_ice_cand_pair;
|
typedef struct nr_ice_cand_pair_ nr_ice_cand_pair;
|
||||||
|
typedef void (*nr_ice_trickle_candidate_cb) (void *cb_arg,
|
||||||
|
nr_ice_ctx *ctx, nr_ice_media_stream *stream, int component_id,
|
||||||
|
nr_ice_candidate *candidate);
|
||||||
|
|
||||||
#include "ice_socket.h"
|
#include "ice_socket.h"
|
||||||
#include "ice_component.h"
|
#include "ice_component.h"
|
||||||
@ -144,6 +147,9 @@ struct nr_ice_ctx_ {
|
|||||||
|
|
||||||
NR_async_cb done_cb;
|
NR_async_cb done_cb;
|
||||||
void *cb_arg;
|
void *cb_arg;
|
||||||
|
|
||||||
|
nr_ice_trickle_candidate_cb trickle_cb;
|
||||||
|
void *trickle_cb_arg;
|
||||||
};
|
};
|
||||||
|
|
||||||
int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
|
int nr_ice_ctx_create(char *label, UINT4 flags, nr_ice_ctx **ctxp);
|
||||||
@ -166,6 +172,9 @@ int nr_ice_ctx_set_stun_servers(nr_ice_ctx *ctx,nr_ice_stun_server *servers, int
|
|||||||
int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers, int ct);
|
int nr_ice_ctx_set_turn_servers(nr_ice_ctx *ctx,nr_ice_turn_server *servers, int ct);
|
||||||
int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver);
|
int nr_ice_ctx_set_resolver(nr_ice_ctx *ctx, nr_resolver *resolver);
|
||||||
int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *prioritizer);
|
int nr_ice_ctx_set_interface_prioritizer(nr_ice_ctx *ctx, nr_interface_prioritizer *prioritizer);
|
||||||
|
int nr_ice_ctx_set_trickle_cb(nr_ice_ctx *ctx, nr_ice_trickle_candidate_cb cb, void *cb_arg);
|
||||||
|
|
||||||
|
#define NR_ICE_MAX_ATTRIBUTE_SIZE 256
|
||||||
|
|
||||||
extern int LOG_ICE;
|
extern int LOG_ICE;
|
||||||
|
|
||||||
|
@ -140,14 +140,13 @@ int nr_ice_media_stream_initialize(nr_ice_ctx *ctx, nr_ice_media_stream *stream)
|
|||||||
return(_status);
|
return(_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_ATTRIBUTE_SIZE 256
|
|
||||||
|
|
||||||
int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp, int *attrctp)
|
int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attrsp, int *attrctp)
|
||||||
{
|
{
|
||||||
int attrct=0;
|
int attrct=0;
|
||||||
nr_ice_component *comp;
|
nr_ice_component *comp;
|
||||||
char **attrs=0;
|
char **attrs=0;
|
||||||
int index=0;
|
int index=0;
|
||||||
|
nr_ice_candidate *cand;
|
||||||
int r,_status;
|
int r,_status;
|
||||||
|
|
||||||
*attrctp=0;
|
*attrctp=0;
|
||||||
@ -156,12 +155,15 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr
|
|||||||
comp=STAILQ_FIRST(&stream->components);
|
comp=STAILQ_FIRST(&stream->components);
|
||||||
while(comp){
|
while(comp){
|
||||||
if (comp->state != NR_ICE_COMPONENT_DISABLED) {
|
if (comp->state != NR_ICE_COMPONENT_DISABLED) {
|
||||||
if(r=nr_ice_component_prune_candidates(stream->ctx,comp))
|
cand = TAILQ_FIRST(&comp->candidates);
|
||||||
ABORT(r);
|
while(cand){
|
||||||
|
if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
|
||||||
|
++attrct;
|
||||||
|
}
|
||||||
|
|
||||||
attrct+=comp->candidate_ct;
|
cand = TAILQ_NEXT(cand, entry_comp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
comp=STAILQ_NEXT(comp,entry);
|
comp=STAILQ_NEXT(comp,entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +176,7 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr
|
|||||||
if(!(attrs=RCALLOC(sizeof(char *)*attrct)))
|
if(!(attrs=RCALLOC(sizeof(char *)*attrct)))
|
||||||
ABORT(R_NO_MEMORY);
|
ABORT(R_NO_MEMORY);
|
||||||
for(index=0;index<attrct;index++){
|
for(index=0;index<attrct;index++){
|
||||||
if(!(attrs[index]=RMALLOC(MAX_ATTRIBUTE_SIZE)))
|
if(!(attrs[index]=RMALLOC(NR_ICE_MAX_ATTRIBUTE_SIZE)))
|
||||||
ABORT(R_NO_MEMORY);
|
ABORT(R_NO_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,12 +189,15 @@ int nr_ice_media_stream_get_attributes(nr_ice_media_stream *stream, char ***attr
|
|||||||
|
|
||||||
cand=TAILQ_FIRST(&comp->candidates);
|
cand=TAILQ_FIRST(&comp->candidates);
|
||||||
while(cand){
|
while(cand){
|
||||||
assert(index < attrct);
|
if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
|
||||||
|
assert(index < attrct);
|
||||||
|
|
||||||
if(r=nr_ice_format_candidate_attribute(cand, attrs[index],MAX_ATTRIBUTE_SIZE))
|
|
||||||
ABORT(r);
|
|
||||||
|
|
||||||
index++;
|
if(r=nr_ice_format_candidate_attribute(cand, attrs[index],NR_ICE_MAX_ATTRIBUTE_SIZE))
|
||||||
|
ABORT(r);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
cand=TAILQ_NEXT(cand,entry_comp);
|
cand=TAILQ_NEXT(cand,entry_comp);
|
||||||
}
|
}
|
||||||
@ -243,15 +248,17 @@ int nr_ice_media_stream_get_default_candidate(nr_ice_media_stream *stream, int c
|
|||||||
*/
|
*/
|
||||||
cand=TAILQ_FIRST(&comp->candidates);
|
cand=TAILQ_FIRST(&comp->candidates);
|
||||||
while(cand){
|
while(cand){
|
||||||
if (!best_cand) {
|
if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
|
||||||
best_cand = cand;
|
if (!best_cand) {
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (best_cand->type < cand->type) {
|
|
||||||
best_cand = cand;
|
best_cand = cand;
|
||||||
} else if (best_cand->type == cand->type) {
|
}
|
||||||
if (best_cand->priority < cand->priority)
|
else {
|
||||||
|
if (best_cand->type < cand->type) {
|
||||||
best_cand = cand;
|
best_cand = cand;
|
||||||
|
} else if (best_cand->type == cand->type) {
|
||||||
|
if (best_cand->priority < cand->priority)
|
||||||
|
best_cand = cand;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,6 +818,21 @@ int nr_ice_media_stream_finalize(nr_ice_media_stream *lstr,nr_ice_media_stream *
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int nr_ice_media_stream_pair_new_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, nr_ice_candidate *cand)
|
||||||
|
{
|
||||||
|
int r,_status;
|
||||||
|
nr_ice_component *comp;
|
||||||
|
|
||||||
|
if ((r=nr_ice_media_stream_find_component(pstream, cand->component_id, &comp)))
|
||||||
|
ABORT(R_NOT_FOUND);
|
||||||
|
|
||||||
|
if (r=nr_ice_component_pair_candidate(pctx, comp, cand, 1))
|
||||||
|
ABORT(r);
|
||||||
|
|
||||||
|
_status=0;
|
||||||
|
abort:
|
||||||
|
return(_status);
|
||||||
|
}
|
||||||
|
|
||||||
int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id)
|
int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id)
|
||||||
{
|
{
|
||||||
|
@ -95,7 +95,7 @@ int nr_ice_media_stream_addrs(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, i
|
|||||||
int
|
int
|
||||||
nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr);
|
nr_ice_peer_ctx_parse_media_stream_attribute(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *attr);
|
||||||
int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id);
|
int nr_ice_media_stream_disable_component(nr_ice_media_stream *stream, int component_id);
|
||||||
|
int nr_ice_media_stream_pair_new_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *pstream, nr_ice_candidate *cand);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,8 @@ int nr_ice_peer_ctx_create(nr_ice_ctx *ctx, nr_ice_handler *handler,char *label,
|
|||||||
if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx))))
|
if(!(pctx=RCALLOC(sizeof(nr_ice_peer_ctx))))
|
||||||
ABORT(R_NO_MEMORY);
|
ABORT(R_NO_MEMORY);
|
||||||
|
|
||||||
|
pctx->state = NR_ICE_PEER_STATE_UNPAIRED;
|
||||||
|
|
||||||
if(!(pctx->label=r_strdup(label)))
|
if(!(pctx->label=r_strdup(label)))
|
||||||
ABORT(R_NO_MEMORY);
|
ABORT(R_NO_MEMORY);
|
||||||
|
|
||||||
@ -257,25 +259,14 @@ int nr_ice_peer_ctx_find_pstream(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str
|
|||||||
|
|
||||||
int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *candidate)
|
int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream, char *candidate)
|
||||||
{
|
{
|
||||||
/* First need to find the stream. Because we don't have forward pointers,
|
|
||||||
iterate through all the peer streams to find one that matches us */
|
|
||||||
nr_ice_media_stream *pstream;
|
nr_ice_media_stream *pstream;
|
||||||
int r,_status;
|
int r,_status;
|
||||||
int needs_pairing = 0;
|
int needs_pairing = 0;
|
||||||
|
|
||||||
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) parsing trickle ICE candidate %s",pctx->ctx->label,pctx->label,candidate);
|
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) parsing trickle ICE candidate %s",pctx->ctx->label,pctx->label,candidate);
|
||||||
|
r = nr_ice_peer_ctx_find_pstream(pctx, stream, &pstream);
|
||||||
pstream=STAILQ_FIRST(&pctx->peer_streams);
|
if (r)
|
||||||
while(pstream) {
|
ABORT(r);
|
||||||
if (pstream->local_stream == stream)
|
|
||||||
break;
|
|
||||||
|
|
||||||
pstream = STAILQ_NEXT(pstream, entry);
|
|
||||||
}
|
|
||||||
if (!pstream) {
|
|
||||||
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) has no stream matching stream %s",pctx->ctx->label,pctx->label,stream->label);
|
|
||||||
ABORT(R_NOT_FOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(pstream->ice_state) {
|
switch(pstream->ice_state) {
|
||||||
case NR_ICE_MEDIA_STREAM_UNPAIRED:
|
case NR_ICE_MEDIA_STREAM_UNPAIRED:
|
||||||
@ -354,17 +345,36 @@ int nr_ice_peer_ctx_pair_candidates(nr_ice_peer_ctx *pctx)
|
|||||||
stream=STAILQ_NEXT(stream,entry);
|
stream=STAILQ_NEXT(stream,entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pctx->state = NR_ICE_PEER_STATE_PAIRED;
|
||||||
|
|
||||||
_status=0;
|
_status=0;
|
||||||
abort:
|
abort:
|
||||||
return(_status);
|
return(_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int nr_ice_peer_ctx_pair_new_trickle_candidate(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx, nr_ice_candidate *cand)
|
||||||
|
{
|
||||||
|
int r, _status;
|
||||||
|
nr_ice_media_stream *pstream;
|
||||||
|
|
||||||
|
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s) pairing local trickle ICE candidate %s",pctx->ctx->label,pctx->label,cand->label);
|
||||||
|
if ((r = nr_ice_peer_ctx_find_pstream(pctx, cand->stream, &pstream)))
|
||||||
|
ABORT(r);
|
||||||
|
|
||||||
|
if ((r = nr_ice_media_stream_pair_new_trickle_candidate(pctx, pstream, cand)))
|
||||||
|
ABORT(r);
|
||||||
|
|
||||||
|
_status=0;
|
||||||
|
abort:
|
||||||
|
return _status;
|
||||||
|
}
|
||||||
|
|
||||||
int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id)
|
int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id)
|
||||||
{
|
{
|
||||||
int r, _status;
|
int r, _status;
|
||||||
nr_ice_media_stream *pstream;
|
nr_ice_media_stream *pstream;
|
||||||
nr_ice_component *component;
|
nr_ice_component *component;
|
||||||
int j;
|
|
||||||
|
|
||||||
if ((r=nr_ice_peer_ctx_find_pstream(pctx, lstream, &pstream)))
|
if ((r=nr_ice_peer_ctx_find_pstream(pctx, lstream, &pstream)))
|
||||||
ABORT(r);
|
ABORT(r);
|
||||||
@ -543,7 +553,6 @@ static void nr_ice_peer_ctx_fire_done(NR_SOCKET s, int how, void *cb_arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* OK, a stream just went ready. Examine all the streams to see if we're
|
/* OK, a stream just went ready. Examine all the streams to see if we're
|
||||||
maybe miraculously done */
|
maybe miraculously done */
|
||||||
int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
|
int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stream)
|
||||||
|
@ -40,6 +40,10 @@ extern "C" {
|
|||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
struct nr_ice_peer_ctx_ {
|
struct nr_ice_peer_ctx_ {
|
||||||
|
int state;
|
||||||
|
#define NR_ICE_PEER_STATE_UNPAIRED 1
|
||||||
|
#define NR_ICE_PEER_STATE_PAIRED 2
|
||||||
|
|
||||||
char *label;
|
char *label;
|
||||||
nr_ice_ctx *ctx;
|
nr_ice_ctx *ctx;
|
||||||
nr_ice_handler *handler;
|
nr_ice_handler *handler;
|
||||||
@ -80,6 +84,7 @@ int nr_ice_peer_ctx_stream_done(nr_ice_peer_ctx *pctx, nr_ice_media_stream *stre
|
|||||||
int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp);
|
int nr_ice_peer_ctx_find_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *str, int component_id, nr_ice_component **compp);
|
||||||
int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
|
int nr_ice_peer_ctx_deliver_packet_maybe(nr_ice_peer_ctx *pctx, nr_ice_component *comp, nr_transport_addr *source_addr, UCHAR *data, int len);
|
||||||
int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id);
|
int nr_ice_peer_ctx_disable_component(nr_ice_peer_ctx *pctx, nr_ice_media_stream *lstream, int component_id);
|
||||||
|
int nr_ice_peer_ctx_pair_new_trickle_candidate(nr_ice_ctx *ctx, nr_ice_peer_ctx *pctx, nr_ice_candidate *cand);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -362,5 +362,10 @@ namespace CSF
|
|||||||
of its memory.
|
of its memory.
|
||||||
*/
|
*/
|
||||||
virtual Timecard *takeTimecard() = 0;
|
virtual Timecard *takeTimecard() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the latest candidate.
|
||||||
|
*/
|
||||||
|
virtual std::string getCandidate() = 0;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -152,6 +152,7 @@ public:
|
|||||||
public: \
|
public: \
|
||||||
static classname ## Ptr wrap(handletype handle); \
|
static classname ## Ptr wrap(handletype handle); \
|
||||||
static void reset(); \
|
static void reset(); \
|
||||||
|
static void release(handletype handle); \
|
||||||
private: \
|
private: \
|
||||||
friend class Wrapper<classname>; \
|
friend class Wrapper<classname>; \
|
||||||
typedef classname ## Ptr Ptr; \
|
typedef classname ## Ptr Ptr; \
|
||||||
@ -169,5 +170,8 @@ public:
|
|||||||
void classname::reset() \
|
void classname::reset() \
|
||||||
{ \
|
{ \
|
||||||
getWrapper().reset(); \
|
getWrapper().reset(); \
|
||||||
}
|
} \
|
||||||
|
void classname::release(handletype handle) \
|
||||||
|
{ \
|
||||||
|
getWrapper().release(handle); \
|
||||||
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#include "ccsdp.h"
|
#include "ccsdp.h"
|
||||||
#include "vcm.h"
|
#include "vcm.h"
|
||||||
|
#include "cc_call_feature.h"
|
||||||
#include "cip_mmgr_mediadefinitions.h"
|
#include "cip_mmgr_mediadefinitions.h"
|
||||||
#include "cip_Sipcc_CodecMask.h"
|
#include "cip_Sipcc_CodecMask.h"
|
||||||
|
|
||||||
@ -68,6 +69,7 @@ VcmSIPCCBinding * VcmSIPCCBinding::gSelf = NULL;
|
|||||||
int VcmSIPCCBinding::gAudioCodecMask = 0;
|
int VcmSIPCCBinding::gAudioCodecMask = 0;
|
||||||
int VcmSIPCCBinding::gVideoCodecMask = 0;
|
int VcmSIPCCBinding::gVideoCodecMask = 0;
|
||||||
nsIThread *VcmSIPCCBinding::gMainThread = NULL;
|
nsIThread *VcmSIPCCBinding::gMainThread = NULL;
|
||||||
|
nsIEventTarget *VcmSIPCCBinding::gSTSThread = NULL;
|
||||||
|
|
||||||
static mozilla::RefPtr<TransportFlow> vcmCreateTransportFlow(
|
static mozilla::RefPtr<TransportFlow> vcmCreateTransportFlow(
|
||||||
sipcc::PeerConnectionImpl *pc,
|
sipcc::PeerConnectionImpl *pc,
|
||||||
@ -102,10 +104,58 @@ VcmSIPCCBinding::VcmSIPCCBinding ()
|
|||||||
gSelf = this;
|
gSelf = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VcmIceOpaque : public NrIceOpaque {
|
||||||
|
public:
|
||||||
|
VcmIceOpaque(cc_streamid_t stream_id,
|
||||||
|
cc_call_handle_t call_handle,
|
||||||
|
uint16_t level) :
|
||||||
|
stream_id_(stream_id),
|
||||||
|
call_handle_(call_handle),
|
||||||
|
level_(level) {}
|
||||||
|
|
||||||
|
virtual ~VcmIceOpaque() {}
|
||||||
|
|
||||||
|
cc_streamid_t stream_id_;
|
||||||
|
cc_call_handle_t call_handle_;
|
||||||
|
uint16_t level_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
VcmSIPCCBinding::~VcmSIPCCBinding ()
|
VcmSIPCCBinding::~VcmSIPCCBinding ()
|
||||||
{
|
{
|
||||||
assert(gSelf);
|
assert(gSelf);
|
||||||
gSelf = NULL;
|
gSelf = NULL;
|
||||||
|
// In case we're torn down while STS is still running,
|
||||||
|
// we try to dispatch to STS to disconnect all of the
|
||||||
|
// ICE signals. If STS is no longer running, this will
|
||||||
|
// harmlessly fail.
|
||||||
|
SyncRunnable::DispatchToThread(
|
||||||
|
gSTSThread,
|
||||||
|
WrapRunnable(this, &VcmSIPCCBinding::disconnect_all),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VcmSIPCCBinding::CandidateReady(NrIceMediaStream* stream,
|
||||||
|
const std::string& candidate)
|
||||||
|
{
|
||||||
|
// This is called on the STS thread
|
||||||
|
NrIceOpaque *opaque = stream->opaque();
|
||||||
|
MOZ_ASSERT(opaque);
|
||||||
|
|
||||||
|
VcmIceOpaque *vcm_opaque = static_cast<VcmIceOpaque *>(opaque);
|
||||||
|
CSFLogDebug(logTag, "Candidate ready on call %u, level %u",
|
||||||
|
vcm_opaque->call_handle_, vcm_opaque->level_);
|
||||||
|
|
||||||
|
char *candidate_tmp = (char *)malloc(candidate.size() + 1);
|
||||||
|
if (!candidate_tmp)
|
||||||
|
return;
|
||||||
|
sstrncpy(candidate_tmp, candidate.c_str(), candidate.size() + 1);
|
||||||
|
// Send a message to the GSM thread.
|
||||||
|
CC_CallFeature_FoundICECandidate(vcm_opaque->call_handle_,
|
||||||
|
candidate_tmp,
|
||||||
|
NULL,
|
||||||
|
vcm_opaque->level_,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VcmSIPCCBinding::setStreamObserver(StreamObserver* obs)
|
void VcmSIPCCBinding::setStreamObserver(StreamObserver* obs)
|
||||||
@ -163,11 +213,23 @@ void VcmSIPCCBinding::setMainThread(nsIThread *thread)
|
|||||||
gMainThread = thread;
|
gMainThread = thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VcmSIPCCBinding::setSTSThread(nsIEventTarget *thread)
|
||||||
|
{
|
||||||
|
gSTSThread = thread;
|
||||||
|
}
|
||||||
|
|
||||||
nsIThread* VcmSIPCCBinding::getMainThread()
|
nsIThread* VcmSIPCCBinding::getMainThread()
|
||||||
{
|
{
|
||||||
return gMainThread;
|
return gMainThread;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VcmSIPCCBinding::connectCandidateSignal(
|
||||||
|
NrIceMediaStream *stream)
|
||||||
|
{
|
||||||
|
stream->SignalCandidate.connect(gSelf,
|
||||||
|
&VcmSIPCCBinding::CandidateReady);
|
||||||
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
AudioTermination * VcmSIPCCBinding::getAudioTermination()
|
AudioTermination * VcmSIPCCBinding::getAudioTermination()
|
||||||
{
|
{
|
||||||
@ -462,6 +524,12 @@ static short vcmRxAllocICE_m(cc_mcapid_t mcap_id,
|
|||||||
return VCM_ERROR;
|
return VCM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the opaque so we can correlate events.
|
||||||
|
stream->SetOpaque(new VcmIceOpaque(stream_id, call_handle, level));
|
||||||
|
|
||||||
|
// Attach ourself to the candidate signal.
|
||||||
|
VcmSIPCCBinding::connectCandidateSignal(stream);
|
||||||
|
|
||||||
std::vector<std::string> candidates = stream->GetCandidates();
|
std::vector<std::string> candidates = stream->GetCandidates();
|
||||||
CSFLogDebug( logTag, "%s: Got %lu candidates", __FUNCTION__, candidates.size());
|
CSFLogDebug( logTag, "%s: Got %lu candidates", __FUNCTION__, candidates.size());
|
||||||
|
|
||||||
@ -733,6 +801,7 @@ static short vcmSetIceCandidate_m(const char *peerconnection,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Set ice candidate for trickle ICE.
|
/* Set ice candidate for trickle ICE.
|
||||||
*
|
*
|
||||||
* This is a thunk to vcmSetIceCandidate_m
|
* This is a thunk to vcmSetIceCandidate_m
|
||||||
@ -792,7 +861,6 @@ static short vcmStartIceChecks_m(const char *peerconnection, cc_boolean isContro
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Start ICE checks
|
/* Start ICE checks
|
||||||
*
|
*
|
||||||
* This is a thunk to vcmStartIceChecks_m
|
* This is a thunk to vcmStartIceChecks_m
|
||||||
|
@ -10,7 +10,14 @@ extern "C"
|
|||||||
#include "ccapi_types.h"
|
#include "ccapi_types.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "sigslot.h"
|
||||||
|
|
||||||
class nsIThread;
|
class nsIThread;
|
||||||
|
class nsIEventTarget;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
class NrIceMediaStream;
|
||||||
|
};
|
||||||
|
|
||||||
namespace CSF
|
namespace CSF
|
||||||
{
|
{
|
||||||
@ -29,13 +36,12 @@ namespace CSF
|
|||||||
virtual void dtmfBurst(int digit, int direction, int duration) = 0;
|
virtual void dtmfBurst(int digit, int direction, int duration) = 0;
|
||||||
virtual void sendIFrame(cc_call_handle_t call) = 0;
|
virtual void sendIFrame(cc_call_handle_t call) = 0;
|
||||||
};
|
};
|
||||||
class VcmSIPCCBinding
|
class VcmSIPCCBinding : public sigslot::has_slots<>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VcmSIPCCBinding ();
|
VcmSIPCCBinding ();
|
||||||
virtual ~VcmSIPCCBinding();
|
virtual ~VcmSIPCCBinding();
|
||||||
|
|
||||||
|
|
||||||
// The getter is only for use by the vcm_* impl functions.
|
// The getter is only for use by the vcm_* impl functions.
|
||||||
void setStreamObserver(StreamObserver*);
|
void setStreamObserver(StreamObserver*);
|
||||||
static StreamObserver* getStreamObserver();
|
static StreamObserver* getStreamObserver();
|
||||||
@ -58,13 +64,21 @@ namespace CSF
|
|||||||
static void setMainThread(nsIThread *thread);
|
static void setMainThread(nsIThread *thread);
|
||||||
static nsIThread *getMainThread();
|
static nsIThread *getMainThread();
|
||||||
|
|
||||||
|
static void setSTSThread(nsIEventTarget *thread);
|
||||||
|
|
||||||
|
static void connectCandidateSignal(mozilla::NrIceMediaStream* stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void CandidateReady(mozilla::NrIceMediaStream* stream,
|
||||||
|
const std::string& candidate);
|
||||||
|
|
||||||
static VcmSIPCCBinding * gSelf;
|
static VcmSIPCCBinding * gSelf;
|
||||||
StreamObserver* streamObserver;
|
StreamObserver* streamObserver;
|
||||||
MediaProviderObserver *mediaProviderObserver;
|
MediaProviderObserver *mediaProviderObserver;
|
||||||
static int gAudioCodecMask;
|
static int gAudioCodecMask;
|
||||||
static int gVideoCodecMask;
|
static int gVideoCodecMask;
|
||||||
static nsIThread *gMainThread;
|
static nsIThread *gMainThread;
|
||||||
|
static nsIEventTarget *gSTSThread;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,8 @@ static void join_waiter() {
|
|||||||
NS_ProcessPendingEvents(PeerConnectionCtx::gMainThread);
|
NS_ProcessPendingEvents(PeerConnectionCtx::gMainThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread) {
|
nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread,
|
||||||
|
nsIEventTarget* stsThread) {
|
||||||
if (!gMainThread) {
|
if (!gMainThread) {
|
||||||
gMainThread = mainThread;
|
gMainThread = mainThread;
|
||||||
CSF::VcmSIPCCBinding::setMainThread(gMainThread);
|
CSF::VcmSIPCCBinding::setMainThread(gMainThread);
|
||||||
@ -133,6 +134,8 @@ nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSF::VcmSIPCCBinding::setSTSThread(stsThread);
|
||||||
|
|
||||||
nsresult res;
|
nsresult res;
|
||||||
|
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
|
@ -34,7 +34,7 @@ namespace sipcc {
|
|||||||
// * The observer class that demuxes events onto individual PCs.
|
// * The observer class that demuxes events onto individual PCs.
|
||||||
class PeerConnectionCtx : public CSF::CC_Observer {
|
class PeerConnectionCtx : public CSF::CC_Observer {
|
||||||
public:
|
public:
|
||||||
static nsresult InitializeGlobal(nsIThread *mainThread);
|
static nsresult InitializeGlobal(nsIThread *mainThread, nsIEventTarget *stsThread);
|
||||||
static PeerConnectionCtx* GetInstance();
|
static PeerConnectionCtx* GetInstance();
|
||||||
static bool isActive();
|
static bool isActive();
|
||||||
static void Destroy();
|
static void Destroy();
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cerrno>
|
||||||
|
|
||||||
#include "base/histogram.h"
|
#include "base/histogram.h"
|
||||||
#include "vcm.h"
|
#include "vcm.h"
|
||||||
@ -139,6 +141,7 @@ public:
|
|||||||
mCode(static_cast<PeerConnectionImpl::Error>(aInfo->getStatusCode())),
|
mCode(static_cast<PeerConnectionImpl::Error>(aInfo->getStatusCode())),
|
||||||
mReason(aInfo->getStatus()),
|
mReason(aInfo->getStatus()),
|
||||||
mSdpStr(),
|
mSdpStr(),
|
||||||
|
mCandidateStr(),
|
||||||
mCallState(aInfo->getCallState()),
|
mCallState(aInfo->getCallState()),
|
||||||
mFsmState(aInfo->getFsmState()),
|
mFsmState(aInfo->getFsmState()),
|
||||||
mStateStr(aInfo->callStateToString(mCallState)),
|
mStateStr(aInfo->callStateToString(mCallState)),
|
||||||
@ -148,8 +151,10 @@ public:
|
|||||||
streams = aInfo->getMediaStreams();
|
streams = aInfo->getMediaStreams();
|
||||||
mRemoteStream = mPC->media()->GetRemoteStream(streams->media_stream_id);
|
mRemoteStream = mPC->media()->GetRemoteStream(streams->media_stream_id);
|
||||||
MOZ_ASSERT(mRemoteStream);
|
MOZ_ASSERT(mRemoteStream);
|
||||||
}
|
} else if (mCallState == FOUNDICECANDIDATE) {
|
||||||
if ((mCallState == CREATEOFFERSUCCESS) || (mCallState == CREATEANSWERSUCCESS)) {
|
mCandidateStr = aInfo->getCandidate();
|
||||||
|
} else if ((mCallState == CREATEOFFERSUCCESS) ||
|
||||||
|
(mCallState == CREATEANSWERSUCCESS)) {
|
||||||
mSdpStr = aInfo->getSDP();
|
mSdpStr = aInfo->getSDP();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,6 +284,45 @@ public:
|
|||||||
mObserver->OnAddIceCandidateError(mCode, mReason.c_str());
|
mObserver->OnAddIceCandidateError(mCode, mReason.c_str());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case FOUNDICECANDIDATE:
|
||||||
|
{
|
||||||
|
size_t end_of_level = mCandidateStr.find('\t');
|
||||||
|
if (end_of_level == std::string::npos) {
|
||||||
|
MOZ_ASSERT(false);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
std::string level = mCandidateStr.substr(0, end_of_level);
|
||||||
|
if (!level.size()) {
|
||||||
|
MOZ_ASSERT(false);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
char *endptr;
|
||||||
|
errno = 0;
|
||||||
|
unsigned long level_long =
|
||||||
|
strtoul(level.c_str(), &endptr, 10);
|
||||||
|
if (errno || *endptr != 0 || level_long > 65535) {
|
||||||
|
/* Conversion failure */
|
||||||
|
MOZ_ASSERT(false);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
size_t end_of_mid = mCandidateStr.find('\t', end_of_level + 1);
|
||||||
|
if (end_of_mid == std::string::npos) {
|
||||||
|
MOZ_ASSERT(false);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string mid = mCandidateStr.substr(end_of_level + 1,
|
||||||
|
end_of_mid - (end_of_level + 1));
|
||||||
|
|
||||||
|
std::string candidate = mCandidateStr.substr(end_of_mid + 1);
|
||||||
|
|
||||||
|
|
||||||
|
mObserver->OnIceCandidate(
|
||||||
|
level_long & 0xffff,
|
||||||
|
mid.c_str(),
|
||||||
|
candidate.c_str());
|
||||||
|
}
|
||||||
|
break;
|
||||||
case REMOTESTREAMADD:
|
case REMOTESTREAMADD:
|
||||||
{
|
{
|
||||||
DOMMediaStream* stream = nullptr;
|
DOMMediaStream* stream = nullptr;
|
||||||
@ -323,6 +367,7 @@ private:
|
|||||||
PeerConnectionImpl::Error mCode;
|
PeerConnectionImpl::Error mCode;
|
||||||
std::string mReason;
|
std::string mReason;
|
||||||
std::string mSdpStr;
|
std::string mSdpStr;
|
||||||
|
std::string mCandidateStr;
|
||||||
cc_call_state_t mCallState;
|
cc_call_state_t mCallState;
|
||||||
fsmdef_states_t mFsmState;
|
fsmdef_states_t mFsmState;
|
||||||
std::string mStateStr;
|
std::string mStateStr;
|
||||||
@ -346,7 +391,9 @@ PeerConnectionImpl::PeerConnectionImpl()
|
|||||||
, mMedia(NULL)
|
, mMedia(NULL)
|
||||||
, mNumAudioStreams(0)
|
, mNumAudioStreams(0)
|
||||||
, mNumVideoStreams(0)
|
, mNumVideoStreams(0)
|
||||||
, mHaveDataStream(false) {
|
, mHaveDataStream(false)
|
||||||
|
, mTrickle(true) // TODO(ekr@rtfm.com): Use pref
|
||||||
|
{
|
||||||
#ifdef MOZILLA_INTERNAL_API
|
#ifdef MOZILLA_INTERNAL_API
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
#endif
|
#endif
|
||||||
@ -606,7 +653,7 @@ PeerConnectionImpl::Initialize(IPeerConnectionObserver* aObserver,
|
|||||||
mHandle = hex;
|
mHandle = hex;
|
||||||
|
|
||||||
STAMP_TIMECARD(mTimeCard, "Initializing PC Ctx");
|
STAMP_TIMECARD(mTimeCard, "Initializing PC Ctx");
|
||||||
res = PeerConnectionCtx::InitializeGlobal(mThread);
|
res = PeerConnectionCtx::InitializeGlobal(mThread, mSTSThread);
|
||||||
NS_ENSURE_SUCCESS(res, res);
|
NS_ENSURE_SUCCESS(res, res);
|
||||||
|
|
||||||
PeerConnectionCtx *pcctx = PeerConnectionCtx::GetInstance();
|
PeerConnectionCtx *pcctx = PeerConnectionCtx::GetInstance();
|
||||||
@ -1311,7 +1358,7 @@ nsresult
|
|||||||
PeerConnectionImpl::CheckApiState(bool assert_ice_ready) const
|
PeerConnectionImpl::CheckApiState(bool assert_ice_ready) const
|
||||||
{
|
{
|
||||||
PC_AUTO_ENTER_API_CALL_NO_CHECK();
|
PC_AUTO_ENTER_API_CALL_NO_CHECK();
|
||||||
PR_ASSERT(!assert_ice_ready || (mIceState != kIceGathering));
|
MOZ_ASSERT(mTrickle || !assert_ice_ready || (mIceState != kIceGathering));
|
||||||
|
|
||||||
if (mReadyState == kClosed)
|
if (mReadyState == kClosed)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -386,6 +386,8 @@ private:
|
|||||||
// Holder for error messages from parsing SDP
|
// Holder for error messages from parsing SDP
|
||||||
std::vector<std::string> mSDPParseErrorMessages;
|
std::vector<std::string> mSDPParseErrorMessages;
|
||||||
|
|
||||||
|
bool mTrickle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//these are temporary until the DataChannel Listen/Connect API is removed
|
//these are temporary until the DataChannel Listen/Connect API is removed
|
||||||
unsigned short listenPort;
|
unsigned short listenPort;
|
||||||
|
@ -107,6 +107,7 @@ typedef struct cc_call_info_t_{
|
|||||||
unsigned int media_stream_track_id;
|
unsigned int media_stream_track_id;
|
||||||
unsigned int media_stream_id;
|
unsigned int media_stream_id;
|
||||||
cc_media_constraints_t* cc_constraints;
|
cc_media_constraints_t* cc_constraints;
|
||||||
|
string_t candidate;
|
||||||
Timecard * timecard;
|
Timecard * timecard;
|
||||||
} session_data_t;
|
} session_data_t;
|
||||||
|
|
||||||
|
@ -149,6 +149,10 @@ cc_return_t cc_invokeFeatureSDPMode(cc_call_handle_t call_handle,
|
|||||||
callFeature.featData.ccData.info = strlib_malloc(data, strlen(data));
|
callFeature.featData.ccData.info = strlib_malloc(data, strlen(data));
|
||||||
callFeature.featData.ccData.info1 = strlib_malloc(data1, strlen(data1));
|
callFeature.featData.ccData.info1 = strlib_malloc(data1, strlen(data1));
|
||||||
break;
|
break;
|
||||||
|
case CC_FEATURE_FOUNDICECANDIDATE:
|
||||||
|
callFeature.featData.ccData.info = strlib_malloc(data, strlen(data));
|
||||||
|
callFeature.featData.ccData.info1 = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
callFeature.featData.ccData.info = NULL;
|
callFeature.featData.ccData.info = NULL;
|
||||||
@ -374,6 +378,19 @@ cc_return_t CC_CallFeature_AddICECandidate(cc_call_handle_t call_handle,
|
|||||||
0, 0, NO_STREAM, (uint16_t)level, constraints, candidate, mid, tc);
|
0, 0, NO_STREAM, (uint16_t)level, constraints, candidate, mid, tc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc_return_t CC_CallFeature_FoundICECandidate(cc_call_handle_t call_handle,
|
||||||
|
const char* candidate,
|
||||||
|
const char *mid,
|
||||||
|
cc_level_t level,
|
||||||
|
Timecard *tc) {
|
||||||
|
cc_media_constraints_t *constraints = NULL;
|
||||||
|
CCAPP_DEBUG(DEB_L_C_F_PREFIX, DEB_L_C_F_PREFIX_ARGS(SIP_CC_PROV, GET_CALL_ID(call_handle),
|
||||||
|
GET_LINE_ID(call_handle), __FUNCTION__));
|
||||||
|
|
||||||
|
return cc_invokeFeatureSDPMode(call_handle, CC_FEATURE_FOUNDICECANDIDATE, JSEP_NO_ACTION,
|
||||||
|
0, 0, NO_STREAM, (uint16_t)level, constraints, candidate, mid, tc);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiate a speed dial.
|
* Initiate a speed dial.
|
||||||
* @param call handle
|
* @param call handle
|
||||||
|
@ -747,6 +747,24 @@ cc_string_t CCAPI_CallInfo_getSDP(cc_callinfo_ref_t handle){
|
|||||||
return strlib_empty();
|
return strlib_empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get candidate for trickle ICE
|
||||||
|
* @param handle - call handle
|
||||||
|
* @return sdp
|
||||||
|
*/
|
||||||
|
cc_string_t CCAPI_CallInfo_getCandidate(cc_callinfo_ref_t handle){
|
||||||
|
static const char *fname="CCAPI_CallInfo_getCandiate";
|
||||||
|
session_data_t *data = (session_data_t *)handle;
|
||||||
|
CCAPP_DEBUG(DEB_F_PREFIX"Entering", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname));
|
||||||
|
|
||||||
|
if (data){
|
||||||
|
CCAPP_DEBUG(DEB_F_PREFIX"returned %s", DEB_F_PREFIX_ARGS(SIP_CC_PROV, fname), data->candidate);
|
||||||
|
return data->candidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return strlib_empty();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get status code from internal JSEP functions
|
* get status code from internal JSEP functions
|
||||||
* @param handle - call handle
|
* @param handle - call handle
|
||||||
|
@ -710,6 +710,13 @@ processSessionEvent (line_t line_id, callid_t call_id, unsigned int event, sdp_d
|
|||||||
sstrncpy(featdata.candidate.mid, data1, sizeof(featdata.candidate.mid)-1);
|
sstrncpy(featdata.candidate.mid, data1, sizeof(featdata.candidate.mid)-1);
|
||||||
cc_int_feature2(CC_MSG_ADDCANDIDATE, CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_ADDICECANDIDATE, &featdata, timecard);
|
cc_int_feature2(CC_MSG_ADDCANDIDATE, CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_ADDICECANDIDATE, &featdata, timecard);
|
||||||
break;
|
break;
|
||||||
|
case CC_FEATURE_FOUNDICECANDIDATE:
|
||||||
|
STAMP_TIMECARD(timecard, "Processing found candidate event");
|
||||||
|
featdata.candidate.level = ccData.level;
|
||||||
|
sstrncpy(featdata.candidate.candidate, data, sizeof(featdata.candidate.candidate)-1);
|
||||||
|
sstrncpy(featdata.candidate.mid, data1, sizeof(featdata.candidate.mid)-1);
|
||||||
|
cc_int_feature2(CC_MSG_FOUNDCANDIDATE, CC_SRC_UI, CC_SRC_GSM, call_id, (line_t)instance, CC_FEATURE_FOUNDICECANDIDATE, &featdata, timecard);
|
||||||
|
break;
|
||||||
case CC_FEATURE_DIALSTR:
|
case CC_FEATURE_DIALSTR:
|
||||||
if (CheckAndGetAvailableLine(&line_id, &call_id) == TRUE) {
|
if (CheckAndGetAvailableLine(&line_id, &call_id) == TRUE) {
|
||||||
getDigits(data, digits, sizeof(digits));
|
getDigits(data, digits, sizeof(digits));
|
||||||
@ -1061,7 +1068,8 @@ session_data_t * getDeepCopyOfSessionData(session_data_t *data)
|
|||||||
newData->plcd_number = strlib_copy(data->plcd_number);
|
newData->plcd_number = strlib_copy(data->plcd_number);
|
||||||
newData->status = strlib_copy(data->status);
|
newData->status = strlib_copy(data->status);
|
||||||
newData->sdp = strlib_copy(data->sdp);
|
newData->sdp = strlib_copy(data->sdp);
|
||||||
|
newData->candidate = data->candidate ?
|
||||||
|
strlib_copy(data->candidate) : strlib_empty();
|
||||||
/* The timecard can have only one owner */
|
/* The timecard can have only one owner */
|
||||||
newData->timecard = data->timecard;
|
newData->timecard = data->timecard;
|
||||||
data->timecard = NULL;
|
data->timecard = NULL;
|
||||||
@ -1085,6 +1093,7 @@ session_data_t * getDeepCopyOfSessionData(session_data_t *data)
|
|||||||
newData->plcd_number = strlib_empty();
|
newData->plcd_number = strlib_empty();
|
||||||
newData->status = strlib_empty();
|
newData->status = strlib_empty();
|
||||||
newData->sdp = strlib_empty();
|
newData->sdp = strlib_empty();
|
||||||
|
newData->candidate = strlib_empty();
|
||||||
newData->timecard = NULL;
|
newData->timecard = NULL;
|
||||||
calllogger_init_call_log(&newData->call_log);
|
calllogger_init_call_log(&newData->call_log);
|
||||||
}
|
}
|
||||||
@ -1132,6 +1141,9 @@ void cleanSessionData(session_data_t *data)
|
|||||||
data->status = strlib_empty();
|
data->status = strlib_empty();
|
||||||
strlib_free(data->sdp);
|
strlib_free(data->sdp);
|
||||||
data->sdp = strlib_empty();
|
data->sdp = strlib_empty();
|
||||||
|
if (data->candidate)
|
||||||
|
strlib_free(data->candidate);
|
||||||
|
data->candidate = strlib_empty();
|
||||||
data->timecard = NULL;
|
data->timecard = NULL;
|
||||||
calllogger_free_call_log(&data->call_log);
|
calllogger_free_call_log(&data->call_log);
|
||||||
}
|
}
|
||||||
@ -1450,6 +1462,7 @@ static void ccappUpdateSessionData (session_update_t *sessUpd)
|
|||||||
sessUpd->eventID == UPDATE_LOCAL_DESC ||
|
sessUpd->eventID == UPDATE_LOCAL_DESC ||
|
||||||
sessUpd->eventID == UPDATE_REMOTE_DESC ||
|
sessUpd->eventID == UPDATE_REMOTE_DESC ||
|
||||||
sessUpd->eventID == ICE_CANDIDATE_ADD ||
|
sessUpd->eventID == ICE_CANDIDATE_ADD ||
|
||||||
|
sessUpd->eventID == ICE_CANDIDATE_FOUND ||
|
||||||
sessUpd->eventID == REMOTE_STREAM_ADD ) {
|
sessUpd->eventID == REMOTE_STREAM_ADD ) {
|
||||||
data->attr = sessUpd->update.ccSessionUpd.data.state_data.attr;
|
data->attr = sessUpd->update.ccSessionUpd.data.state_data.attr;
|
||||||
data->inst = sessUpd->update.ccSessionUpd.data.state_data.inst;
|
data->inst = sessUpd->update.ccSessionUpd.data.state_data.inst;
|
||||||
@ -1832,6 +1845,12 @@ static void ccappUpdateSessionData (session_update_t *sessUpd)
|
|||||||
case UPDATE_LOCAL_DESC:
|
case UPDATE_LOCAL_DESC:
|
||||||
case UPDATE_REMOTE_DESC:
|
case UPDATE_REMOTE_DESC:
|
||||||
case ICE_CANDIDATE_ADD:
|
case ICE_CANDIDATE_ADD:
|
||||||
|
case ICE_CANDIDATE_FOUND:
|
||||||
|
if (sessUpd->update.ccSessionUpd.data.state_data.extra) {
|
||||||
|
if (sessUpd->eventID == ICE_CANDIDATE_FOUND) {
|
||||||
|
data->candidate = sessUpd->update.ccSessionUpd.data.state_data.extra;
|
||||||
|
}
|
||||||
|
}
|
||||||
data->sdp = sessUpd->update.ccSessionUpd.data.state_data.sdp;
|
data->sdp = sessUpd->update.ccSessionUpd.data.state_data.sdp;
|
||||||
/* Fall through to the next case... */
|
/* Fall through to the next case... */
|
||||||
case REMOTE_STREAM_ADD:
|
case REMOTE_STREAM_ADD:
|
||||||
|
@ -1556,6 +1556,7 @@ static void post_message_helper(group_call_event_t eventId,
|
|||||||
callid_t nCallId,
|
callid_t nCallId,
|
||||||
uint16_t call_instance_id,
|
uint16_t call_instance_id,
|
||||||
string_t sdp,
|
string_t sdp,
|
||||||
|
string_t extra,
|
||||||
Timecard *timecard,
|
Timecard *timecard,
|
||||||
pc_error error,
|
pc_error error,
|
||||||
const char *format,
|
const char *format,
|
||||||
@ -1580,6 +1581,7 @@ static void post_message_helper(group_call_event_t eventId,
|
|||||||
msg.update.ccSessionUpd.data.state_data.inst = call_instance_id;
|
msg.update.ccSessionUpd.data.state_data.inst = call_instance_id;
|
||||||
msg.update.ccSessionUpd.data.state_data.line_id = nLine;
|
msg.update.ccSessionUpd.data.state_data.line_id = nLine;
|
||||||
msg.update.ccSessionUpd.data.state_data.sdp = sdp;
|
msg.update.ccSessionUpd.data.state_data.sdp = sdp;
|
||||||
|
msg.update.ccSessionUpd.data.state_data.extra = extra;
|
||||||
msg.update.ccSessionUpd.data.state_data.cause = error;
|
msg.update.ccSessionUpd.data.state_data.cause = error;
|
||||||
msg.update.ccSessionUpd.data.state_data.timecard = timecard;
|
msg.update.ccSessionUpd.data.state_data.timecard = timecard;
|
||||||
|
|
||||||
@ -1627,7 +1629,7 @@ void ui_create_offer(call_events event,
|
|||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
post_message_helper(CREATE_OFFER, event, new_state, nLine, nCallID,
|
post_message_helper(CREATE_OFFER, event, new_state, nLine, nCallID,
|
||||||
call_instance_id, sdp, timecard, error, format, ap);
|
call_instance_id, sdp, NULL, timecard, error, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1655,7 +1657,7 @@ void ui_create_answer(call_events event,
|
|||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
post_message_helper(CREATE_ANSWER, event, new_state, nLine, nCallID,
|
post_message_helper(CREATE_ANSWER, event, new_state, nLine, nCallID,
|
||||||
call_instance_id, sdp, timecard, error, format, ap);
|
call_instance_id, sdp, NULL, timecard, error, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1683,7 +1685,7 @@ void ui_set_local_description(call_events event,
|
|||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
post_message_helper(SET_LOCAL_DESC, event, new_state, nLine, nCallID,
|
post_message_helper(SET_LOCAL_DESC, event, new_state, nLine, nCallID,
|
||||||
call_instance_id, sdp, timecard, error, format, ap);
|
call_instance_id, sdp, NULL, timecard, error, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1711,7 +1713,7 @@ void ui_set_remote_description(call_events event,
|
|||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
post_message_helper(SET_REMOTE_DESC, event, new_state, nLine, nCallID,
|
post_message_helper(SET_REMOTE_DESC, event, new_state, nLine, nCallID,
|
||||||
call_instance_id, sdp, timecard, error, format, ap);
|
call_instance_id, sdp, NULL, timecard, error, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1740,7 +1742,7 @@ void ui_update_local_description(call_events event,
|
|||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
post_message_helper(UPDATE_LOCAL_DESC, event, new_state, nLine, nCallID,
|
post_message_helper(UPDATE_LOCAL_DESC, event, new_state, nLine, nCallID,
|
||||||
call_instance_id, sdp, timecard, error, format, ap);
|
call_instance_id, sdp, NULL, timecard, error, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1768,7 +1770,35 @@ void ui_ice_candidate_add(call_events event,
|
|||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
post_message_helper(ICE_CANDIDATE_ADD, event, new_state, nLine, nCallID,
|
post_message_helper(ICE_CANDIDATE_ADD, event, new_state, nLine, nCallID,
|
||||||
call_instance_id, sdp, timecard, error, format, ap);
|
call_instance_id, sdp, NULL, timecard, error, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send data from foundIceCandidate to the UI
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ui_ice_candidate_found(call_events event,
|
||||||
|
fsmdef_states_t new_state,
|
||||||
|
line_t nLine,
|
||||||
|
callid_t nCallID,
|
||||||
|
uint16_t call_instance_id,
|
||||||
|
string_t sdp,
|
||||||
|
string_t candidate,
|
||||||
|
Timecard *timecard,
|
||||||
|
pc_error error,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
TNP_DEBUG(DEB_L_C_F_PREFIX"state=%d call_instance=%d",
|
||||||
|
DEB_L_C_F_PREFIX_ARGS(UI_API, nLine, nCallID, __FUNCTION__), event, call_instance_id);
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
post_message_helper(ICE_CANDIDATE_FOUND, event, new_state, nLine, nCallID,
|
||||||
|
call_instance_id, sdp, candidate, timecard, error, format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "platform_api.h"
|
#include "platform_api.h"
|
||||||
#include "peer_connection_types.h"
|
#include "peer_connection_types.h"
|
||||||
#include "prlog.h"
|
#include "prlog.h"
|
||||||
|
#include "prprf.h"
|
||||||
#include "sessionHash.h"
|
#include "sessionHash.h"
|
||||||
|
|
||||||
extern void update_kpmlconfig(int kpmlVal);
|
extern void update_kpmlconfig(int kpmlVal);
|
||||||
@ -93,6 +94,7 @@ static sm_rcs_t fsmdef_ev_setpeerconnection(sm_event_t *event);
|
|||||||
static sm_rcs_t fsmdef_ev_addstream(sm_event_t *event);
|
static sm_rcs_t fsmdef_ev_addstream(sm_event_t *event);
|
||||||
static sm_rcs_t fsmdef_ev_removestream(sm_event_t *event);
|
static sm_rcs_t fsmdef_ev_removestream(sm_event_t *event);
|
||||||
static sm_rcs_t fsmdef_ev_addcandidate(sm_event_t *event);
|
static sm_rcs_t fsmdef_ev_addcandidate(sm_event_t *event);
|
||||||
|
static sm_rcs_t fsmdef_ev_foundcandidate(sm_event_t *event);
|
||||||
|
|
||||||
static sm_rcs_t fsmdef_ev_default(sm_event_t *event);
|
static sm_rcs_t fsmdef_ev_default(sm_event_t *event);
|
||||||
static sm_rcs_t fsmdef_ev_default_feature_ack(sm_event_t *event);
|
static sm_rcs_t fsmdef_ev_default_feature_ack(sm_event_t *event);
|
||||||
@ -202,7 +204,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_setpeerconnection,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_setpeerconnection,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_COLLECT_INFO ---------------------------------------------------- */
|
/* FSMDEF_S_COLLECT_INFO ---------------------------------------------------- */
|
||||||
@ -232,7 +235,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_CALL_SENT ------------------------------------------------------- */
|
/* FSMDEF_S_CALL_SENT ------------------------------------------------------- */
|
||||||
@ -262,7 +266,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_OUTGOING_PROCEEDING --------------------------------------------- */
|
/* FSMDEF_S_OUTGOING_PROCEEDING --------------------------------------------- */
|
||||||
@ -292,7 +297,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_KPML_COLLECT_INFO ----------------------------------------------- */
|
/* FSMDEF_S_KPML_COLLECT_INFO ----------------------------------------------- */
|
||||||
@ -322,7 +328,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_OUTGOING_ALERTING ----------------------------------------------- */
|
/* FSMDEF_S_OUTGOING_ALERTING ----------------------------------------------- */
|
||||||
@ -352,7 +359,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_INCOMING_ALERTING ----------------------------------------------- */
|
/* FSMDEF_S_INCOMING_ALERTING ----------------------------------------------- */
|
||||||
@ -382,7 +390,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_CONNECTING ------------------------------------------------------ */
|
/* FSMDEF_S_CONNECTING ------------------------------------------------------ */
|
||||||
@ -412,7 +421,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_JOINING --------------------------------------------------------- */
|
/* FSMDEF_S_JOINING --------------------------------------------------------- */
|
||||||
@ -442,7 +452,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_CONNECTED ------------------------------------------------------- */
|
/* FSMDEF_S_CONNECTED ------------------------------------------------------- */
|
||||||
@ -472,7 +483,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_CONNECTED_MEDIA_PEND ------------------------------------------- */
|
/* FSMDEF_S_CONNECTED_MEDIA_PEND ------------------------------------------- */
|
||||||
@ -502,7 +514,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_RELEASING ------------------------------------------------------- */
|
/* FSMDEF_S_RELEASING ------------------------------------------------------- */
|
||||||
@ -532,7 +545,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_HOLD_PENDING ---------------------------------------------------- */
|
/* FSMDEF_S_HOLD_PENDING ---------------------------------------------------- */
|
||||||
@ -562,7 +576,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_HOLDING --------------------------------------------------------- */
|
/* FSMDEF_S_HOLDING --------------------------------------------------------- */
|
||||||
@ -592,7 +607,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_RESUME_PENDING -------------------------------------------------- */
|
/* FSMDEF_S_RESUME_PENDING -------------------------------------------------- */
|
||||||
@ -622,7 +638,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_PRESERVED ------------------------------------------------------ */
|
/* FSMDEF_S_PRESERVED ------------------------------------------------------ */
|
||||||
@ -652,7 +669,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
@ -683,7 +701,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_addstream,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_addstream,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_removestream,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_removestream,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_addcandidate
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_addcandidate,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_foundcandidate
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_HAVE_LOCAL_OFFER ----------------------------------------------- */
|
/* FSMDEF_S_HAVE_LOCAL_OFFER ----------------------------------------------- */
|
||||||
@ -713,8 +732,9 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default /* Reject lame-duck
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default, /* Reject lame-duck
|
||||||
candidates */
|
candidates */
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_foundcandidate
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_HAVE_REMOTE_OFFER ---------------------------------------------- */
|
/* FSMDEF_S_HAVE_REMOTE_OFFER ---------------------------------------------- */
|
||||||
@ -744,7 +764,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_addstream,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_addstream,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_removestream,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_removestream,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_addcandidate
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_addcandidate,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_HAVE_LOCAL_PRANSWER -------------------------------------------- */
|
/* FSMDEF_S_HAVE_LOCAL_PRANSWER -------------------------------------------- */
|
||||||
@ -774,7 +795,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_addcandidate
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_addcandidate,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_foundcandidate
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_HAVE_REMOTE_PRANSWER ------------------------------------------- */
|
/* FSMDEF_S_HAVE_REMOTE_PRANSWER ------------------------------------------- */
|
||||||
@ -804,7 +826,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_addcandidate
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_addcandidate,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_foundcandidate
|
||||||
},
|
},
|
||||||
|
|
||||||
/* FSMDEF_S_CLOSED --------------------------------------------------------- */
|
/* FSMDEF_S_CLOSED --------------------------------------------------------- */
|
||||||
@ -834,7 +857,8 @@ static sm_function_t fsmdef_function_table[FSMDEF_S_MAX][CC_MSG_MAX] =
|
|||||||
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
/* CC_MSG_SETPEERCONNECTION */fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
/* CC_MSG_ADDSTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
/* CC_MSG_REMOVESTREAM */ fsmdef_ev_default,
|
||||||
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default
|
/* CC_MSG_ADDCANDIDATE */ fsmdef_ev_default,
|
||||||
|
/* CC_MSG_FOUNDCANDIDATE */ fsmdef_ev_default
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1302,6 +1326,8 @@ fsmdef_init_dcb (fsmdef_dcb_t *dcb, callid_t call_id,
|
|||||||
|
|
||||||
dcb->digest_alg[0] = '\0';
|
dcb->digest_alg[0] = '\0';
|
||||||
dcb->digest[0] = '\0';
|
dcb->digest[0] = '\0';
|
||||||
|
|
||||||
|
sll_lite_init(&dcb->candidate_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1351,6 +1377,9 @@ fsmdef_free_dcb (fsmdef_dcb_t *dcb)
|
|||||||
/* clean media list */
|
/* clean media list */
|
||||||
gsmsdp_clean_media_list(dcb);
|
gsmsdp_clean_media_list(dcb);
|
||||||
|
|
||||||
|
/* clean candidate list */
|
||||||
|
gsmsdp_clean_candidate_list(dcb);
|
||||||
|
|
||||||
gsmsdp_free(dcb);
|
gsmsdp_free(dcb);
|
||||||
|
|
||||||
fsmdef_init_dcb(dcb, CC_NO_CALL_ID, FSMDEF_CALL_TYPE_NONE, NULL,
|
fsmdef_init_dcb(dcb, CC_NO_CALL_ID, FSMDEF_CALL_TYPE_NONE, NULL,
|
||||||
@ -2455,6 +2484,14 @@ fsmdef_ev_default (sm_event_t *event)
|
|||||||
fsmdef_state_name(fcb->state));
|
fsmdef_state_name(fcb->state));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CC_MSG_FOUNDCANDIDATE:
|
||||||
|
ui_ice_candidate_found(evFoundIceCandidateError, fcb->state, msg->line,
|
||||||
|
msg->call_id, dcb->caller_id.call_instance_id, strlib_empty(),
|
||||||
|
NULL, msg->timecard,
|
||||||
|
PC_INVALID_STATE, "Cannot add found ICE candidate in state %s",
|
||||||
|
fsmdef_state_name(fcb->state));
|
||||||
|
break;
|
||||||
|
|
||||||
case CC_MSG_ADDSTREAM:
|
case CC_MSG_ADDSTREAM:
|
||||||
case CC_MSG_REMOVESTREAM:
|
case CC_MSG_REMOVESTREAM:
|
||||||
/* This shouldn't happen, since PeerConnection should check
|
/* This shouldn't happen, since PeerConnection should check
|
||||||
@ -3170,6 +3207,9 @@ fsmdef_ev_createoffer (sm_event_t *event) {
|
|||||||
return (SM_RC_END);
|
return (SM_RC_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clean candidate list, since we are about to return the candidates */
|
||||||
|
gsmsdp_clean_candidate_list(dcb);
|
||||||
|
|
||||||
dcb->inbound = FALSE;
|
dcb->inbound = FALSE;
|
||||||
|
|
||||||
if (msg->data.session.constraints) {
|
if (msg->data.session.constraints) {
|
||||||
@ -3331,6 +3371,9 @@ fsmdef_ev_createanswer (sm_event_t *event) {
|
|||||||
return (SM_RC_END);
|
return (SM_RC_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* clean candidate list, since we are about to return the candidates */
|
||||||
|
gsmsdp_clean_candidate_list(dcb);
|
||||||
|
|
||||||
dcb->inbound = TRUE;
|
dcb->inbound = TRUE;
|
||||||
|
|
||||||
if (msg->data.session.constraints) {
|
if (msg->data.session.constraints) {
|
||||||
@ -3459,6 +3502,7 @@ fsmdef_ev_setlocaldesc(sm_event_t *event) {
|
|||||||
cc_causes_t lsm_rc;
|
cc_causes_t lsm_rc;
|
||||||
char *local_sdp = NULL;
|
char *local_sdp = NULL;
|
||||||
uint32_t local_sdp_len = 0;
|
uint32_t local_sdp_len = 0;
|
||||||
|
fsmdef_candidate_t *candidate = NULL;
|
||||||
|
|
||||||
FSM_DEBUG_SM(DEB_F_PREFIX"Entered.", DEB_F_PREFIX_ARGS(FSM, __FUNCTION__));
|
FSM_DEBUG_SM(DEB_F_PREFIX"Entered.", DEB_F_PREFIX_ARGS(FSM, __FUNCTION__));
|
||||||
|
|
||||||
@ -3603,6 +3647,21 @@ fsmdef_ev_setlocaldesc(sm_event_t *event) {
|
|||||||
msg->call_id, dcb->caller_id.call_instance_id,
|
msg->call_id, dcb->caller_id.call_instance_id,
|
||||||
strlib_malloc(local_sdp,-1), msg->timecard, PC_NO_ERROR, NULL);
|
strlib_malloc(local_sdp,-1), msg->timecard, PC_NO_ERROR, NULL);
|
||||||
|
|
||||||
|
/* If we have pending candidates flush them too */
|
||||||
|
while (TRUE) {
|
||||||
|
/* unlink head and free the media */
|
||||||
|
candidate = (fsmdef_candidate_t *)sll_lite_unlink_head(&dcb->candidate_list);
|
||||||
|
if (candidate) {
|
||||||
|
ui_ice_candidate_found(evFoundIceCandidate, fcb->state, line, call_id,
|
||||||
|
dcb->caller_id.call_instance_id, strlib_malloc(local_sdp,-1),
|
||||||
|
candidate->candidate, /* Transfer ownership */
|
||||||
|
NULL, PC_NO_ERROR, NULL);
|
||||||
|
free(candidate);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(local_sdp);
|
free(local_sdp);
|
||||||
return (SM_RC_END);
|
return (SM_RC_END);
|
||||||
}
|
}
|
||||||
@ -4122,6 +4181,117 @@ fsmdef_ev_addcandidate(sm_event_t *event) {
|
|||||||
return (SM_RC_END);
|
return (SM_RC_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static sm_rcs_t
|
||||||
|
fsmdef_ev_foundcandidate(sm_event_t *event) {
|
||||||
|
fsm_fcb_t *fcb = (fsm_fcb_t *) event->data;
|
||||||
|
fsmdef_dcb_t *dcb = fcb->dcb;
|
||||||
|
cc_causes_t cause = CC_CAUSE_NORMAL;
|
||||||
|
cc_feature_t *msg = (cc_feature_t *) event->msg;
|
||||||
|
int sdpmode = 0;
|
||||||
|
short vcm_res;
|
||||||
|
uint16_t level;
|
||||||
|
line_t line = msg->line;
|
||||||
|
callid_t call_id = msg->call_id;
|
||||||
|
char *local_sdp = 0;
|
||||||
|
uint32_t local_sdp_len = 0;
|
||||||
|
string_t candidate = 0;
|
||||||
|
char candidate_tmp[CANDIDATE_SIZE + 32]; /* Sort of arbitrary */
|
||||||
|
|
||||||
|
FSM_DEBUG_SM(DEB_F_PREFIX"Entered.", DEB_F_PREFIX_ARGS(FSM, __FUNCTION__));
|
||||||
|
|
||||||
|
if (!dcb) {
|
||||||
|
FSM_DEBUG_SM(DEB_F_PREFIX"dcb is NULL.", DEB_F_PREFIX_ARGS(FSM, __FUNCTION__));
|
||||||
|
ui_ice_candidate_add(evAddIceCandidateError, fcb->state, line, call_id,
|
||||||
|
0, strlib_empty(), msg->timecard, PC_INTERNAL_ERROR,
|
||||||
|
"DCB has not been created.");
|
||||||
|
return SM_RC_CLEANUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
config_get_value(CFGID_SDPMODE, &sdpmode, sizeof(sdpmode));
|
||||||
|
if (!sdpmode) {
|
||||||
|
MOZ_CRASH();
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(dcb->sdp && dcb->sdp->src_sdp);
|
||||||
|
if (!dcb->sdp || !dcb->sdp->src_sdp) {
|
||||||
|
FSM_DEBUG_SM(DEB_F_PREFIX"Has the "
|
||||||
|
"local description been set yet?\n",
|
||||||
|
DEB_F_PREFIX_ARGS(FSM, __FUNCTION__));
|
||||||
|
|
||||||
|
ui_ice_candidate_found(evFoundIceCandidateError, fcb->state, line, call_id,
|
||||||
|
dcb->caller_id.call_instance_id, strlib_empty(),
|
||||||
|
NULL, msg->timecard,
|
||||||
|
PC_INVALID_STATE, "Cannot add found ICE candidates without"
|
||||||
|
"local SDP.");
|
||||||
|
|
||||||
|
return SM_RC_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the candidate in the SDP for future reference */
|
||||||
|
level = msg->data.candidate.level;
|
||||||
|
gsmsdp_set_ice_attribute (SDP_ATTR_ICE_CANDIDATE, level,
|
||||||
|
dcb->sdp->src_sdp,
|
||||||
|
(char *)msg->data.candidate.candidate);
|
||||||
|
|
||||||
|
local_sdp = sipsdp_write_to_buf(dcb->sdp->src_sdp, &local_sdp_len);
|
||||||
|
|
||||||
|
if (!local_sdp) {
|
||||||
|
ui_ice_candidate_found(evFoundIceCandidateError, fcb->state, line, call_id,
|
||||||
|
dcb->caller_id.call_instance_id, strlib_empty(), NULL,
|
||||||
|
msg->timecard,
|
||||||
|
PC_INTERNAL_ERROR, "Could not serialize new SDP after adding ICE "
|
||||||
|
"candidate.");
|
||||||
|
return (SM_RC_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Distinguish between the following two cases:
|
||||||
|
|
||||||
|
1. CreateOffer() has been called but SetLocalDesc() has not.
|
||||||
|
2. We are mid-call.
|
||||||
|
|
||||||
|
Both of these are in state STABLE but only in one do we
|
||||||
|
pass up trickle candidates. In the other we buffer them
|
||||||
|
and send them later.
|
||||||
|
*/
|
||||||
|
/* Smuggle the entire candidate structure in a string */
|
||||||
|
PR_snprintf(candidate_tmp, sizeof(candidate_tmp), "%d\t%s\t%s",
|
||||||
|
msg->data.candidate.level,
|
||||||
|
(char *)msg->data.candidate.mid,
|
||||||
|
(char *)msg->data.candidate.candidate);
|
||||||
|
|
||||||
|
if (fcb->state == FSMDEF_S_STABLE) {
|
||||||
|
if (!dcb->sdp->dest_sdp) {
|
||||||
|
fsmdef_candidate_t *buffered_cand = NULL;
|
||||||
|
|
||||||
|
FSM_DEBUG_SM(DEB_F_PREFIX"dcb->sdp->dest_sdp is null."
|
||||||
|
"assuming CreateOffer called but not SetLocal...\n",
|
||||||
|
DEB_F_PREFIX_ARGS(FSM, __FUNCTION__));
|
||||||
|
|
||||||
|
buffered_cand = (fsmdef_candidate_t *)cpr_malloc(sizeof(fsmdef_candidate_t));
|
||||||
|
if (!buffered_cand)
|
||||||
|
return SM_RC_END;
|
||||||
|
|
||||||
|
buffered_cand->candidate = strlib_malloc(candidate_tmp, -1);
|
||||||
|
|
||||||
|
if (sll_lite_link_head(&dcb->candidate_list,
|
||||||
|
(sll_lite_node_t *)buffered_cand) != SLL_LITE_RET_SUCCESS)
|
||||||
|
return SM_RC_END;
|
||||||
|
|
||||||
|
/* Don't notify upward */
|
||||||
|
return SM_RC_END;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_ice_candidate_found(evFoundIceCandidate, fcb->state, line, call_id,
|
||||||
|
dcb->caller_id.call_instance_id, strlib_malloc(local_sdp,-1),
|
||||||
|
strlib_malloc(candidate_tmp, -1),
|
||||||
|
msg->timecard, PC_NO_ERROR, NULL);
|
||||||
|
|
||||||
|
return SM_RC_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fsmdef_check_active_feature (fsmdef_dcb_t *dcb, cc_features_t ftr_id)
|
fsmdef_check_active_feature (fsmdef_dcb_t *dcb, cc_features_t ftr_id)
|
||||||
{
|
{
|
||||||
|
@ -7327,3 +7327,31 @@ gsmsdp_find_level_from_mid(fsmdef_dcb_t * dcb_p, const char * mid, uint16_t *lev
|
|||||||
}
|
}
|
||||||
return CC_CAUSE_VALUE_NOT_FOUND;
|
return CC_CAUSE_VALUE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function performs cleaning candidate list of a given call. It walks
|
||||||
|
* through the list and deallocates each candidate entry.
|
||||||
|
*
|
||||||
|
* @param[in]dcb - pointer to fsmdef_def_t for the dcb whose
|
||||||
|
* media list to be cleaned.
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*
|
||||||
|
* @pre (dcb not_eq NULL)
|
||||||
|
*/
|
||||||
|
void gsmsdp_clean_candidate_list (fsmdef_dcb_t *dcb_p)
|
||||||
|
{
|
||||||
|
fsmdef_candidate_t *candidate = NULL;
|
||||||
|
|
||||||
|
while (TRUE) {
|
||||||
|
/* unlink head and free the media */
|
||||||
|
candidate = (fsmdef_candidate_t *)sll_lite_unlink_head(&dcb_p->candidate_list);
|
||||||
|
if (candidate) {
|
||||||
|
strlib_free(candidate->candidate);
|
||||||
|
free(candidate);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -429,6 +429,7 @@ typedef struct {
|
|||||||
char digest_alg[FSMDEF_MAX_DIGEST_ALG_LEN];
|
char digest_alg[FSMDEF_MAX_DIGEST_ALG_LEN];
|
||||||
char digest[FSMDEF_MAX_DIGEST_LEN];
|
char digest[FSMDEF_MAX_DIGEST_LEN];
|
||||||
|
|
||||||
|
sll_lite_list_t candidate_list;
|
||||||
} fsmdef_dcb_t;
|
} fsmdef_dcb_t;
|
||||||
|
|
||||||
typedef enum fsm_types_t_ {
|
typedef enum fsm_types_t_ {
|
||||||
@ -498,6 +499,11 @@ typedef enum fsmxfr_modes_t_ {
|
|||||||
FSMXFR_MODE_TARGET
|
FSMXFR_MODE_TARGET
|
||||||
} fsmxfr_modes_t;
|
} fsmxfr_modes_t;
|
||||||
|
|
||||||
|
typedef struct fsmdef_candidate_t_ {
|
||||||
|
sll_lite_node_t node; /* link node, must be first member of struct */
|
||||||
|
string_t candidate; /* the candidate value */
|
||||||
|
} fsmdef_candidate_t;
|
||||||
|
|
||||||
struct fsmxfr_xcb_t_;
|
struct fsmxfr_xcb_t_;
|
||||||
typedef struct fsmxfr_xcb_t_ {
|
typedef struct fsmxfr_xcb_t_ {
|
||||||
cc_srcs_t xfr_orig;
|
cc_srcs_t xfr_orig;
|
||||||
|
@ -141,6 +141,7 @@ fsmdef_media_t* gsmsdp_find_media_by_media_type(fsmdef_dcb_t *dcb, sdp_media_e
|
|||||||
|
|
||||||
extern void gsmsdp_set_ice_attribute (sdp_attr_e sdp_attr, uint16_t level,
|
extern void gsmsdp_set_ice_attribute (sdp_attr_e sdp_attr, uint16_t level,
|
||||||
void *sdp_p, char *ice_attrib);
|
void *sdp_p, char *ice_attrib);
|
||||||
|
extern void gsmsdp_clean_candidate_list(fsmdef_dcb_t *dcb);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -103,6 +103,7 @@ typedef enum {
|
|||||||
CC_FEATURE_ADDSTREAM,
|
CC_FEATURE_ADDSTREAM,
|
||||||
CC_FEATURE_REMOVESTREAM,
|
CC_FEATURE_REMOVESTREAM,
|
||||||
CC_FEATURE_ADDICECANDIDATE,
|
CC_FEATURE_ADDICECANDIDATE,
|
||||||
|
CC_FEATURE_FOUNDICECANDIDATE,
|
||||||
CC_FEATURE_MAX
|
CC_FEATURE_MAX
|
||||||
} group_cc_feature_t;
|
} group_cc_feature_t;
|
||||||
|
|
||||||
@ -168,6 +169,7 @@ static const char *const cc_feature_names[] = {
|
|||||||
"ADDSTREAM",
|
"ADDSTREAM",
|
||||||
"REMOVESTREAM",
|
"REMOVESTREAM",
|
||||||
"ADDICECANDIDATE",
|
"ADDICECANDIDATE",
|
||||||
|
"FOUNDICECANDIDATE",
|
||||||
"MAX"
|
"MAX"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -241,6 +243,7 @@ typedef enum cc_msgs_t_ {
|
|||||||
CC_MSG_ADDSTREAM,
|
CC_MSG_ADDSTREAM,
|
||||||
CC_MSG_REMOVESTREAM,
|
CC_MSG_REMOVESTREAM,
|
||||||
CC_MSG_ADDCANDIDATE,
|
CC_MSG_ADDCANDIDATE,
|
||||||
|
CC_MSG_FOUNDCANDIDATE,
|
||||||
CC_MSG_AUDIT_ACK,
|
CC_MSG_AUDIT_ACK,
|
||||||
CC_MSG_OPTIONS,
|
CC_MSG_OPTIONS,
|
||||||
CC_MSG_OPTIONS_ACK,
|
CC_MSG_OPTIONS_ACK,
|
||||||
@ -280,6 +283,7 @@ static const char *const cc_msg_names[] = {
|
|||||||
"ADDSTREAM",
|
"ADDSTREAM",
|
||||||
"REMOVESTREAM",
|
"REMOVESTREAM",
|
||||||
"ADDCANDIDATE",
|
"ADDCANDIDATE",
|
||||||
|
"FOUNDCANDIDATE",
|
||||||
"AUDIT_ACK",
|
"AUDIT_ACK",
|
||||||
"OPTIONS",
|
"OPTIONS",
|
||||||
"OPTIONS_ACK",
|
"OPTIONS_ACK",
|
||||||
|
@ -223,7 +223,8 @@ typedef enum {
|
|||||||
UPDATE_LOCAL_DESC,
|
UPDATE_LOCAL_DESC,
|
||||||
UPDATE_REMOTE_DESC,
|
UPDATE_REMOTE_DESC,
|
||||||
REMOTE_STREAM_ADD,
|
REMOTE_STREAM_ADD,
|
||||||
ICE_CANDIDATE_ADD
|
ICE_CANDIDATE_ADD,
|
||||||
|
ICE_CANDIDATE_FOUND
|
||||||
} group_call_event_t;
|
} group_call_event_t;
|
||||||
|
|
||||||
/* File Player Session Events */
|
/* File Player Session Events */
|
||||||
|
@ -66,6 +66,7 @@ typedef struct {
|
|||||||
int cause;
|
int cause;
|
||||||
string_t reason_text;
|
string_t reason_text;
|
||||||
string_t sdp;
|
string_t sdp;
|
||||||
|
string_t extra;
|
||||||
unsigned int media_stream_id;
|
unsigned int media_stream_id;
|
||||||
unsigned int media_stream_track_id;
|
unsigned int media_stream_track_id;
|
||||||
Timecard * timecard;
|
Timecard * timecard;
|
||||||
|
@ -44,6 +44,8 @@ typedef enum {
|
|||||||
evOnRemoteStreamAdd = REMOTESTREAMADD,
|
evOnRemoteStreamAdd = REMOTESTREAMADD,
|
||||||
evAddIceCandidate = ADDICECANDIDATE,
|
evAddIceCandidate = ADDICECANDIDATE,
|
||||||
evAddIceCandidateError = ADDICECANDIDATEERROR,
|
evAddIceCandidateError = ADDICECANDIDATEERROR,
|
||||||
|
evFoundIceCandidate = FOUNDICECANDIDATE,
|
||||||
|
evFoundIceCandidateError = FOUNDICECANDIDATEERROR,
|
||||||
evMaxEvent
|
evMaxEvent
|
||||||
} call_events;
|
} call_events;
|
||||||
|
|
||||||
@ -240,6 +242,17 @@ void ui_ice_candidate_add(call_events event,
|
|||||||
pc_error error,
|
pc_error error,
|
||||||
const char *format, ...);
|
const char *format, ...);
|
||||||
|
|
||||||
|
void ui_ice_candidate_found(call_events event,
|
||||||
|
fsmdef_states_t new_state,
|
||||||
|
line_t nLine,
|
||||||
|
callid_t nCallID,
|
||||||
|
uint16_t call_instance_id,
|
||||||
|
string_t sdp,
|
||||||
|
string_t candidate,
|
||||||
|
Timecard *timecard,
|
||||||
|
pc_error error,
|
||||||
|
const char *format, ...);
|
||||||
|
|
||||||
void ui_on_remote_stream_added(call_events event,
|
void ui_on_remote_stream_added(call_events event,
|
||||||
fsmdef_states_t new_state,
|
fsmdef_states_t new_state,
|
||||||
line_t nLine,
|
line_t nLine,
|
||||||
|
@ -186,6 +186,11 @@ cc_return_t CC_CallFeature_AddICECandidate(cc_call_handle_t call_handle,
|
|||||||
const char *mid,
|
const char *mid,
|
||||||
cc_level_t level,
|
cc_level_t level,
|
||||||
Timecard *tc);
|
Timecard *tc);
|
||||||
|
cc_return_t CC_CallFeature_FoundICECandidate(cc_call_handle_t call_handle,
|
||||||
|
const char* candidate,
|
||||||
|
const char *mid,
|
||||||
|
cc_level_t level,
|
||||||
|
Timecard *tc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiate a speed dial.
|
* Initiate a speed dial.
|
||||||
|
@ -289,6 +289,8 @@ typedef enum {
|
|||||||
REMOTESTREAMADD,
|
REMOTESTREAMADD,
|
||||||
ADDICECANDIDATE,
|
ADDICECANDIDATE,
|
||||||
ADDICECANDIDATEERROR,
|
ADDICECANDIDATEERROR,
|
||||||
|
FOUNDICECANDIDATE,
|
||||||
|
FOUNDICECANDIDATEERROR,
|
||||||
MAX_CALL_STATES
|
MAX_CALL_STATES
|
||||||
} cc_call_state_t;
|
} cc_call_state_t;
|
||||||
|
|
||||||
|
@ -302,6 +302,13 @@ cc_boolean CCAPI_CallInfo_isVideoMuted(cc_callinfo_ref_t handle);
|
|||||||
*/
|
*/
|
||||||
cc_string_t CCAPI_CallInfo_getSDP(cc_callinfo_ref_t handle);
|
cc_string_t CCAPI_CallInfo_getSDP(cc_callinfo_ref_t handle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get trickle candidate
|
||||||
|
* @param [in] handle - call info handle
|
||||||
|
* @return sdp
|
||||||
|
*/
|
||||||
|
cc_string_t CCAPI_CallInfo_getCandidate(cc_callinfo_ref_t handle);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get status code from internal JSEP functions
|
* get status code from internal JSEP functions
|
||||||
* @param [in] handle - call info handle
|
* @param [in] handle - call info handle
|
||||||
|
@ -454,6 +454,11 @@ Timecard *CC_SIPCCCallInfo::takeTimecard()
|
|||||||
return CCAPI_CallInfo_takeTimecard(callinfo_ref);
|
return CCAPI_CallInfo_takeTimecard(callinfo_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CC_SIPCCCallInfo::getCandidate()
|
||||||
|
{
|
||||||
|
return CCAPI_CallInfo_getCandidate(callinfo_ref);
|
||||||
|
}
|
||||||
|
|
||||||
bool CC_SIPCCCallInfo::isMediaStateAvailable()
|
bool CC_SIPCCCallInfo::isMediaStateAvailable()
|
||||||
{
|
{
|
||||||
// for softphone it will always be possible to query the mute state and video direction
|
// for softphone it will always be possible to query the mute state and video direction
|
||||||
|
@ -80,6 +80,7 @@ namespace CSF
|
|||||||
virtual bool isAudioMuted();
|
virtual bool isAudioMuted();
|
||||||
virtual bool isVideoMuted();
|
virtual bool isVideoMuted();
|
||||||
virtual std::string getSDP();
|
virtual std::string getSDP();
|
||||||
|
virtual std::string getCandidate();
|
||||||
virtual cc_int32_t getStatusCode();
|
virtual cc_int32_t getStatusCode();
|
||||||
virtual MediaStreamTable* getMediaStreams() const;
|
virtual MediaStreamTable* getMediaStreams() const;
|
||||||
virtual Timecard *takeTimecard();
|
virtual Timecard *takeTimecard();
|
||||||
|
@ -723,6 +723,18 @@ void CC_SIPCCService::onCallEvent(ccapi_call_event_e eventType, cc_call_handle_t
|
|||||||
call_event_getname(eventType), callPtr->toString().c_str(),
|
call_event_getname(eventType), callPtr->toString().c_str(),
|
||||||
call_state_getname(infoPtr->getCallState()), CC_CallCapabilityEnum::toString(capSet).c_str());
|
call_state_getname(infoPtr->getCallState()), CC_CallCapabilityEnum::toString(capSet).c_str());
|
||||||
_self->notifyCallEventObservers(eventType, callPtr.get(), infoPtr.get());
|
_self->notifyCallEventObservers(eventType, callPtr.get(), infoPtr.get());
|
||||||
|
|
||||||
|
// To prevent leaking CC_SIPCCCalls, we remove them from the wrapper
|
||||||
|
// map when the call event information indicates an "on hook" event.
|
||||||
|
if (infoPtr->getCallState() == ONHOOK) {
|
||||||
|
CSFLogDebug( logTag, "Removing call info from wrapper map (handle=%u)",
|
||||||
|
handle);
|
||||||
|
CC_SIPCCCall::release(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once the call info is dispatched to the observers, we never need to
|
||||||
|
// refer to it again. The next operation will contain its own unique info.
|
||||||
|
CC_SIPCCCallInfo::release(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CC_SIPCCService::addCCObserver ( CC_Observer * observer )
|
void CC_SIPCCService::addCCObserver ( CC_Observer * observer )
|
||||||
|
@ -114,6 +114,8 @@ endif
|
|||||||
|
|
||||||
DEFINES += \
|
DEFINES += \
|
||||||
-DUSE_FAKE_MEDIA_STREAMS \
|
-DUSE_FAKE_MEDIA_STREAMS \
|
||||||
|
-DNR_SOCKET_IS_VOID_PTR \
|
||||||
|
-DHAVE_STRDUP \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
ifeq ($(OS_TARGET),Darwin)
|
ifeq ($(OS_TARGET),Darwin)
|
||||||
@ -141,9 +143,35 @@ LOCAL_INCLUDES += \
|
|||||||
-I$(topsrcdir)/media/webrtc/signaling/src/peerconnection \
|
-I$(topsrcdir)/media/webrtc/signaling/src/peerconnection \
|
||||||
-I$(topsrcdir)/media/webrtc/signaling/media-conduit\
|
-I$(topsrcdir)/media/webrtc/signaling/media-conduit\
|
||||||
-I$(topsrcdir)/media/webrtc/trunk/third_party/libjingle/source/ \
|
-I$(topsrcdir)/media/webrtc/trunk/third_party/libjingle/source/ \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nICEr/src/ice \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nICEr/src/net \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nICEr/src/stun \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/share \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/util/libekr \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/log \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/registry \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/stats \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/plugin \
|
||||||
|
-I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/event \
|
||||||
-I$(topsrcdir)/xpcom/base/ \
|
-I$(topsrcdir)/xpcom/base/ \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
ifneq (,$(filter Darwin DragonFly FreeBSD NetBSD OpenBSD,$(OS_TARGET)))
|
||||||
|
LOCAL_INCLUDES += -I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/port/darwin/include
|
||||||
|
ifneq (,$(filter DragonFly FreeBSD NetBSD OpenBSD,$(OS_TARGET)))
|
||||||
|
LOCAL_INCLUDES += -I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/port/generic/include
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS_TARGET), Linux)
|
||||||
|
LOCAL_INCLUDES += -I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/port/linux/include
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(OS_TARGET), Android)
|
||||||
|
LOCAL_INCLUDES += -I$(topsrcdir)/media/mtransport/third_party/nrappkit/src/port/android/include
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
ifneq ($(OS_TARGET),WINNT)
|
ifneq ($(OS_TARGET),WINNT)
|
||||||
ifneq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
ifneq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||||
ifdef JS_SHARED_LIBRARY
|
ifdef JS_SHARED_LIBRARY
|
||||||
|
@ -40,7 +40,8 @@ static bool SetupGlobalThread() {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
gThread = thread;
|
gThread = thread;
|
||||||
sipcc::PeerConnectionCtx::InitializeGlobal(gThread);
|
sipcc::PeerConnectionCtx::InitializeGlobal(gThread,
|
||||||
|
test_utils->sts_target());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -230,6 +230,7 @@ pref("media.navigator.video.default_minfps",10);
|
|||||||
pref("media.peerconnection.enabled", true);
|
pref("media.peerconnection.enabled", true);
|
||||||
pref("media.navigator.permission.disabled", false);
|
pref("media.navigator.permission.disabled", false);
|
||||||
pref("media.peerconnection.default_iceservers", "[{\"url\": \"stun:23.21.150.121\"}]");
|
pref("media.peerconnection.default_iceservers", "[{\"url\": \"stun:23.21.150.121\"}]");
|
||||||
|
pref("media.peerconnection.trickle_ice", true);
|
||||||
pref("media.peerconnection.use_document_iceservers", true);
|
pref("media.peerconnection.use_document_iceservers", true);
|
||||||
// These values (aec, agc, and noice) are from media/webrtc/trunk/webrtc/common_types.h
|
// These values (aec, agc, and noice) are from media/webrtc/trunk/webrtc/common_types.h
|
||||||
// kXxxUnchanged = 0, kXxxDefault = 1, and higher values are specific to each
|
// kXxxUnchanged = 0, kXxxDefault = 1, and higher values are specific to each
|
||||||
|
@ -27,6 +27,7 @@ from ..frontend.data import (
|
|||||||
GeneratedWebIDLFile,
|
GeneratedWebIDLFile,
|
||||||
IPDLFile,
|
IPDLFile,
|
||||||
LocalInclude,
|
LocalInclude,
|
||||||
|
PreprocessedTestWebIDLFile,
|
||||||
PreprocessedWebIDLFile,
|
PreprocessedWebIDLFile,
|
||||||
Program,
|
Program,
|
||||||
SandboxDerived,
|
SandboxDerived,
|
||||||
@ -266,6 +267,7 @@ class RecursiveMakeBackend(CommonBackend):
|
|||||||
self._webidl_sources = set()
|
self._webidl_sources = set()
|
||||||
self._generated_events_webidl_sources = set()
|
self._generated_events_webidl_sources = set()
|
||||||
self._test_webidl_sources = set()
|
self._test_webidl_sources = set()
|
||||||
|
self._preprocessed_test_webidl_sources = set()
|
||||||
self._preprocessed_webidl_sources = set()
|
self._preprocessed_webidl_sources = set()
|
||||||
self._generated_webidl_sources = set()
|
self._generated_webidl_sources = set()
|
||||||
|
|
||||||
@ -371,6 +373,11 @@ class RecursiveMakeBackend(CommonBackend):
|
|||||||
obj.basename))
|
obj.basename))
|
||||||
# Test WebIDL files are not exported.
|
# Test WebIDL files are not exported.
|
||||||
|
|
||||||
|
elif isinstance(obj, PreprocessedTestWebIDLFile):
|
||||||
|
self._preprocessed_test_webidl_sources.add(mozpath.join(obj.srcdir,
|
||||||
|
obj.basename))
|
||||||
|
# Test WebIDL files are not exported.
|
||||||
|
|
||||||
elif isinstance(obj, GeneratedWebIDLFile):
|
elif isinstance(obj, GeneratedWebIDLFile):
|
||||||
self._generated_webidl_sources.add(mozpath.join(obj.srcdir,
|
self._generated_webidl_sources.add(mozpath.join(obj.srcdir,
|
||||||
obj.basename))
|
obj.basename))
|
||||||
@ -575,6 +582,8 @@ class RecursiveMakeBackend(CommonBackend):
|
|||||||
webidls.write('generated_events_webidl_files += %s\n' % os.path.basename(webidl))
|
webidls.write('generated_events_webidl_files += %s\n' % os.path.basename(webidl))
|
||||||
for webidl in sorted(self._test_webidl_sources):
|
for webidl in sorted(self._test_webidl_sources):
|
||||||
webidls.write('test_webidl_files += %s\n' % os.path.basename(webidl))
|
webidls.write('test_webidl_files += %s\n' % os.path.basename(webidl))
|
||||||
|
for webidl in sorted(self._preprocessed_test_webidl_sources):
|
||||||
|
webidls.write('preprocessed_test_webidl_files += %s\n' % os.path.basename(webidl))
|
||||||
for webidl in sorted(self._generated_webidl_sources):
|
for webidl in sorted(self._generated_webidl_sources):
|
||||||
webidls.write('generated_webidl_files += %s\n' % os.path.basename(webidl))
|
webidls.write('generated_webidl_files += %s\n' % os.path.basename(webidl))
|
||||||
for webidl in sorted(self._preprocessed_webidl_sources):
|
for webidl in sorted(self._preprocessed_webidl_sources):
|
||||||
|
@ -235,6 +235,19 @@ class TestWebIDLFile(SandboxDerived):
|
|||||||
|
|
||||||
self.basename = path
|
self.basename = path
|
||||||
|
|
||||||
|
class PreprocessedTestWebIDLFile(SandboxDerived):
|
||||||
|
"""Describes an individual test-only .webidl source file that requires
|
||||||
|
preprocessing."""
|
||||||
|
|
||||||
|
__slots__ = (
|
||||||
|
'basename',
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, sandbox, path):
|
||||||
|
SandboxDerived.__init__(self, sandbox)
|
||||||
|
|
||||||
|
self.basename = path
|
||||||
|
|
||||||
class PreprocessedWebIDLFile(SandboxDerived):
|
class PreprocessedWebIDLFile(SandboxDerived):
|
||||||
"""Describes an individual .webidl source file that requires preprocessing."""
|
"""Describes an individual .webidl source file that requires preprocessing."""
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ from .data import (
|
|||||||
GeneratedWebIDLFile,
|
GeneratedWebIDLFile,
|
||||||
IPDLFile,
|
IPDLFile,
|
||||||
LocalInclude,
|
LocalInclude,
|
||||||
|
PreprocessedTestWebIDLFile,
|
||||||
PreprocessedWebIDLFile,
|
PreprocessedWebIDLFile,
|
||||||
Program,
|
Program,
|
||||||
ReaderSummary,
|
ReaderSummary,
|
||||||
@ -189,6 +190,7 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||||||
('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile),
|
('GENERATED_WEBIDL_FILES', GeneratedWebIDLFile),
|
||||||
('IPDL_SOURCES', IPDLFile),
|
('IPDL_SOURCES', IPDLFile),
|
||||||
('LOCAL_INCLUDES', LocalInclude),
|
('LOCAL_INCLUDES', LocalInclude),
|
||||||
|
('PREPROCESSED_TEST_WEBIDL_FILES', PreprocessedTestWebIDLFile),
|
||||||
('PREPROCESSED_WEBIDL_FILES', PreprocessedWebIDLFile),
|
('PREPROCESSED_WEBIDL_FILES', PreprocessedWebIDLFile),
|
||||||
('TEST_WEBIDL_FILES', TestWebIDLFile),
|
('TEST_WEBIDL_FILES', TestWebIDLFile),
|
||||||
('WEBIDL_FILES', WebIDLFile),
|
('WEBIDL_FILES', WebIDLFile),
|
||||||
@ -237,7 +239,7 @@ class TreeMetadataEmitter(LoggingMixin):
|
|||||||
path = mozpath.normpath(mozpath.join(sandbox['SRCDIR'], manifest_path))
|
path = mozpath.normpath(mozpath.join(sandbox['SRCDIR'], manifest_path))
|
||||||
manifest_dir = mozpath.dirname(path)
|
manifest_dir = mozpath.dirname(path)
|
||||||
manifest_reldir = mozpath.dirname(mozpath.relpath(path,
|
manifest_reldir = mozpath.dirname(mozpath.relpath(path,
|
||||||
self.config.topsrcdir))
|
sandbox['TOPSRCDIR']))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
m = manifestparser.TestManifest(manifests=[path], strict=True)
|
m = manifestparser.TestManifest(manifests=[path], strict=True)
|
||||||
|
@ -444,6 +444,13 @@ VARIABLES = {
|
|||||||
These will be generated from some other files.
|
These will be generated from some other files.
|
||||||
"""),
|
"""),
|
||||||
|
|
||||||
|
'PREPROCESSED_TEST_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||||
|
"""Preprocessed test WebIDL source files.
|
||||||
|
|
||||||
|
These will be preprocessed, then parsed and converted to .cpp
|
||||||
|
and .h files if tests are enabled.
|
||||||
|
"""),
|
||||||
|
|
||||||
'PREPROCESSED_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
'PREPROCESSED_WEBIDL_FILES': (StrictOrderingOnAppendList, list, [],
|
||||||
"""Preprocessed WebIDL source files.
|
"""Preprocessed WebIDL source files.
|
||||||
|
|
||||||
|
@ -198,14 +198,14 @@
|
|||||||
"dom/imptests/editing/conformancetest/test_runtest.html": "",
|
"dom/imptests/editing/conformancetest/test_runtest.html": "",
|
||||||
"dom/imptests/editing/selecttest/test_addRange.html": "bug 775227",
|
"dom/imptests/editing/selecttest/test_addRange.html": "bug 775227",
|
||||||
"dom/imptests/html/webgl": "WebGL",
|
"dom/imptests/html/webgl": "WebGL",
|
||||||
"dom/imptests/webapps/DOMCore/tests/approved/test_Range-cloneContents.html": "bug 775227",
|
"dom/imptests/html/dom/ranges/test_Range-cloneContents.html": "bug 775227",
|
||||||
"dom/imptests/webapps/DOMCore/tests/approved/test_Range-compareBoundaryPoints.html": "bug 775227",
|
"dom/imptests/html/dom/ranges/test_Range-compareBoundaryPoints.html": "bug 775227",
|
||||||
"dom/imptests/webapps/DOMCore/tests/approved/test_Range-deleteContents.html": "bug 775227",
|
"dom/imptests/html/dom/ranges/test_Range-deleteContents.html": "bug 775227",
|
||||||
"dom/imptests/webapps/DOMCore/tests/approved/test_Range-extractContents.html": "bug 775227",
|
"dom/imptests/html/dom/ranges/test_Range-extractContents.html": "bug 775227",
|
||||||
"dom/imptests/webapps/DOMCore/tests/approved/test_Range-insertNode.html": "bug 775227",
|
"dom/imptests/html/dom/ranges/test_Range-insertNode.html": "bug 775227",
|
||||||
"dom/imptests/webapps/DOMCore/tests/approved/test_Range-mutations.html": "bug 775227",
|
"dom/imptests/html/dom/ranges/test_Range-mutations.html": "bug 775227",
|
||||||
"dom/imptests/webapps/DOMCore/tests/approved/test_Range-set.html": "bug 775227",
|
"dom/imptests/html/dom/ranges/test_Range-set.html": "bug 775227",
|
||||||
"dom/imptests/webapps/DOMCore/tests/approved/test_Range-surroundContents.html": "bug 775227",
|
"dom/imptests/html/dom/ranges/test_Range-surroundContents.html": "bug 775227",
|
||||||
"dom/imptests/webapps/WebStorage/tests/submissions/Infraware/test_storage_local_key.html": "bug 775227",
|
"dom/imptests/webapps/WebStorage/tests/submissions/Infraware/test_storage_local_key.html": "bug 775227",
|
||||||
"dom/indexedDB/ipc/test_ipc.html": "bug 783513",
|
"dom/indexedDB/ipc/test_ipc.html": "bug 783513",
|
||||||
"dom/indexedDB/test/test_third_party.html": "TIMED_OUT",
|
"dom/indexedDB/test/test_third_party.html": "TIMED_OUT",
|
||||||
|
@ -334,6 +334,7 @@ typedef NSInteger NSEventGestureAxis;
|
|||||||
|
|
||||||
- (void)setGLContext:(NSOpenGLContext *)aGLContext;
|
- (void)setGLContext:(NSOpenGLContext *)aGLContext;
|
||||||
- (void)preRender:(NSOpenGLContext *)aGLContext;
|
- (void)preRender:(NSOpenGLContext *)aGLContext;
|
||||||
|
- (void)postRender:(NSOpenGLContext *)aGLContext;
|
||||||
|
|
||||||
- (BOOL)isCoveringTitlebar;
|
- (BOOL)isCoveringTitlebar;
|
||||||
|
|
||||||
@ -537,6 +538,7 @@ public:
|
|||||||
virtual void PrepareWindowEffects() MOZ_OVERRIDE;
|
virtual void PrepareWindowEffects() MOZ_OVERRIDE;
|
||||||
virtual void CleanupWindowEffects() MOZ_OVERRIDE;
|
virtual void CleanupWindowEffects() MOZ_OVERRIDE;
|
||||||
virtual void PreRender(LayerManager* aManager) MOZ_OVERRIDE;
|
virtual void PreRender(LayerManager* aManager) MOZ_OVERRIDE;
|
||||||
|
virtual void PostRender(LayerManager* aManager) MOZ_OVERRIDE;
|
||||||
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) MOZ_OVERRIDE;
|
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries);
|
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries);
|
||||||
|
@ -2043,6 +2043,17 @@ nsChildView::PreRender(LayerManager* aManager)
|
|||||||
[(ChildView*)mView preRender:glContext];
|
[(ChildView*)mView preRender:glContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsChildView::PostRender(LayerManager* aManager)
|
||||||
|
{
|
||||||
|
nsAutoPtr<GLManager> manager(GLManager::CreateGLManager(aManager));
|
||||||
|
if (!manager) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NSOpenGLContext *glContext = (NSOpenGLContext *)manager->gl()->GetNativeData(GLContext::NativeGLContext);
|
||||||
|
[(ChildView*)mView postRender:glContext];
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsChildView::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
|
nsChildView::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
|
||||||
{
|
{
|
||||||
@ -2885,6 +2896,17 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||||||
[aGLContext setView:self];
|
[aGLContext setView:self];
|
||||||
[aGLContext update];
|
[aGLContext update];
|
||||||
|
|
||||||
|
CGLLockContext((CGLContextObj)[aGLContext CGLContextObj]);
|
||||||
|
|
||||||
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
-(void)postRender:(NSOpenGLContext *)aGLContext
|
||||||
|
{
|
||||||
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||||
|
|
||||||
|
CGLUnlockContext((CGLContextObj)[aGLContext CGLContextObj]);
|
||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3223,7 +3245,7 @@ NSEvent* gLastDragMouseDownEvent = nil;
|
|||||||
|
|
||||||
[super lockFocus];
|
[super lockFocus];
|
||||||
|
|
||||||
if (mGLContext) {
|
if (mGLContext && !mUsingOMTCompositor) {
|
||||||
if ([mGLContext view] != self) {
|
if ([mGLContext view] != self) {
|
||||||
[mGLContext setView:self];
|
[mGLContext setView:self];
|
||||||
}
|
}
|
||||||
|
@ -1216,6 +1216,7 @@ class nsIWidget : public nsISupports {
|
|||||||
virtual void CleanupWindowEffects() = 0;
|
virtual void CleanupWindowEffects() = 0;
|
||||||
|
|
||||||
virtual void PreRender(LayerManager* aManager) = 0;
|
virtual void PreRender(LayerManager* aManager) = 0;
|
||||||
|
virtual void PostRender(LayerManager* aManager) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called before the LayerManager draws the layer tree.
|
* Called before the LayerManager draws the layer tree.
|
||||||
|
@ -137,6 +137,7 @@ public:
|
|||||||
virtual void PrepareWindowEffects() {}
|
virtual void PrepareWindowEffects() {}
|
||||||
virtual void CleanupWindowEffects() {}
|
virtual void CleanupWindowEffects() {}
|
||||||
virtual void PreRender(LayerManager* aManager) {}
|
virtual void PreRender(LayerManager* aManager) {}
|
||||||
|
virtual void PostRender(LayerManager* aManager) {}
|
||||||
virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) {}
|
virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) {}
|
||||||
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) {}
|
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) {}
|
||||||
virtual mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing();
|
virtual mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing();
|
||||||
|
@ -34,16 +34,19 @@ public:
|
|||||||
, mMonitor("SyncRunnable")
|
, mMonitor("SyncRunnable")
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
void DispatchToThread(nsIEventTarget* thread)
|
void DispatchToThread(nsIEventTarget* thread,
|
||||||
|
bool forceDispatch = false)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
bool on;
|
bool on;
|
||||||
|
|
||||||
rv = thread->IsOnCurrentThread(&on);
|
if (!forceDispatch) {
|
||||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
rv = thread->IsOnCurrentThread(&on);
|
||||||
if (NS_SUCCEEDED(rv) && on) {
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||||
mRunnable->Run();
|
if (NS_SUCCEEDED(rv) && on) {
|
||||||
return;
|
mRunnable->Run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::MonitorAutoLock lock(mMonitor);
|
mozilla::MonitorAutoLock lock(mMonitor);
|
||||||
@ -54,10 +57,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void DispatchToThread(nsIEventTarget* thread,
|
static void DispatchToThread(nsIEventTarget* thread,
|
||||||
nsIRunnable* r)
|
nsIRunnable* r,
|
||||||
|
bool forceDispatch = false)
|
||||||
{
|
{
|
||||||
nsRefPtr<SyncRunnable> s(new SyncRunnable(r));
|
nsRefPtr<SyncRunnable> s(new SyncRunnable(r));
|
||||||
s->DispatchToThread(thread);
|
s->DispatchToThread(thread, forceDispatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Loading…
Reference in New Issue
Block a user