1/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer
12 *    in the documentation and/or other materials provided with the
13 *    distribution.
14 * 3. Neither the name of Google Inc. nor the names of its contributors
15 *    may be used to endorse or promote products derived from this
16 *    software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32
33#if ENABLE(MEDIA_STREAM)
34
35#include "MediaConstraintsImpl.h"
36
37#include "ArrayValue.h"
38#include "Dictionary.h"
39#include "ExceptionCode.h"
40#include <wtf/HashMap.h>
41
42namespace WebCore {
43
44PassRefPtr<MediaConstraintsImpl> MediaConstraintsImpl::create(const Dictionary& constraints, ExceptionCode& ec)
45{
46    RefPtr<MediaConstraintsImpl> object = adoptRef(new MediaConstraintsImpl());
47    if (!object->initialize(constraints)) {
48        ec = TYPE_MISMATCH_ERR;
49        return 0;
50    }
51    return object.release();
52}
53
54PassRefPtr<MediaConstraintsImpl> MediaConstraintsImpl::create()
55{
56    return adoptRef(new MediaConstraintsImpl());
57}
58
59bool MediaConstraintsImpl::initialize(const Dictionary& constraints)
60{
61    if (constraints.isUndefinedOrNull())
62        return true;
63
64    Vector<String> names;
65    constraints.getOwnPropertyNames(names);
66
67    String mandatory = ASCIILiteral("mandatory");
68    String optional = ASCIILiteral("optional");
69
70    for (Vector<String>::iterator it = names.begin(); it != names.end(); ++it) {
71        if (*it != mandatory && *it != optional)
72            return false;
73    }
74
75    if (names.contains(mandatory)) {
76        Dictionary mandatoryConstraints;
77        bool ok = constraints.get(mandatory, mandatoryConstraints);
78        if (!ok || mandatoryConstraints.isUndefinedOrNull())
79            return false;
80
81        ok = mandatoryConstraints.getOwnPropertiesAsStringHashMap(m_mandatoryConstraints);
82        if (!ok)
83            return false;
84    }
85
86    if (names.contains(optional)) {
87        ArrayValue optionalConstraints;
88        bool ok = constraints.get(optional, optionalConstraints);
89        if (!ok || optionalConstraints.isUndefinedOrNull())
90            return false;
91
92        size_t numberOfConstraints;
93        ok = optionalConstraints.length(numberOfConstraints);
94        if (!ok)
95            return false;
96
97        for (size_t i = 0; i < numberOfConstraints; ++i) {
98            Dictionary constraint;
99            ok = optionalConstraints.get(i, constraint);
100            if (!ok || constraint.isUndefinedOrNull())
101                return false;
102            Vector<String> localNames;
103            constraint.getOwnPropertyNames(localNames);
104            if (localNames.size() != 1)
105                return false;
106            String key = localNames[0];
107            String value;
108            ok = constraint.get(key, value);
109            if (!ok)
110                return false;
111            m_optionalConstraints.append(MediaConstraint(key, value));
112        }
113    }
114
115    return true;
116}
117
118MediaConstraintsImpl::~MediaConstraintsImpl()
119{
120}
121
122void MediaConstraintsImpl::getMandatoryConstraints(Vector<MediaConstraint>& constraints) const
123{
124    constraints.clear();
125    HashMap<String, String>::const_iterator i = m_mandatoryConstraints.begin();
126    for (; i != m_mandatoryConstraints.end(); ++i)
127        constraints.append(MediaConstraint(i->key, i->value));
128}
129
130void MediaConstraintsImpl::getOptionalConstraints(Vector<MediaConstraint>& constraints) const
131{
132    constraints.clear();
133    constraints.appendRange(m_optionalConstraints.begin(), m_optionalConstraints.end());
134}
135
136bool MediaConstraintsImpl::getMandatoryConstraintValue(const String& name, String& value) const
137{
138    HashMap<String, String>::const_iterator i = m_mandatoryConstraints.find(name);
139    if (i == m_mandatoryConstraints.end())
140        return false;
141
142    value = i->value;
143    return true;
144}
145
146bool MediaConstraintsImpl::getOptionalConstraintValue(const String& name, String& value) const
147{
148    Vector<MediaConstraint>::const_iterator i = m_optionalConstraints.begin();
149    for (; i != m_optionalConstraints.end(); ++i) {
150        if (i->m_name == name) {
151            value = i->m_value;
152            return true;
153        }
154    }
155
156    return false;
157}
158
159} // namespace WebCore
160
161#endif // ENABLE(MEDIA_STREAM)
162