1/*
2 * Copyright (C) 2010 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 in the
12 *     documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "OptionsObject.h"
28
29#include "DOMStringList.h"
30#include "V8Binding.h"
31#include <limits>
32
33#if ENABLE(INDEXED_DATABASE)
34#include "IDBKeyRange.h"
35#include "V8IDBKeyRange.h"
36#endif
37
38namespace WebCore {
39
40OptionsObject::OptionsObject()
41{
42}
43
44OptionsObject::OptionsObject(const v8::Local<v8::Value>& options)
45    : m_options(options)
46{
47}
48
49OptionsObject::~OptionsObject()
50{
51}
52
53OptionsObject& OptionsObject::operator=(const OptionsObject& optionsObject)
54{
55    m_options = optionsObject.m_options;
56    return *this;
57}
58
59bool OptionsObject::isUndefinedOrNull() const
60{
61    if (m_options.IsEmpty())
62        return true;
63    return WebCore::isUndefinedOrNull(m_options);
64}
65
66bool OptionsObject::getKeyBool(const String& key, bool& value) const
67{
68    v8::Local<v8::Value> v8Value;
69    if (!getKey(key, v8Value))
70        return false;
71
72    v8::Local<v8::Boolean> v8Bool = v8Value->ToBoolean();
73    if (v8Bool.IsEmpty())
74        return false;
75    value = v8Bool->Value();
76    return true;
77}
78
79bool OptionsObject::getKeyInt32(const String& key, int32_t& value) const
80{
81    v8::Local<v8::Value> v8Value;
82    if (!getKey(key, v8Value))
83        return false;
84
85    v8::Local<v8::Int32> v8Int32 = v8Value->ToInt32();
86    if (v8Int32.IsEmpty())
87        return false;
88    value = v8Int32->Value();
89    return true;
90}
91
92bool OptionsObject::getKeyString(const String& key, String& value) const
93{
94    v8::Local<v8::Value> v8Value;
95    if (!getKey(key, v8Value))
96        return false;
97
98    // FIXME: It is possible for this to throw in which case we'd be getting back
99    //        an empty string and returning true when we should be returning false.
100    //        See fast/dom/Geolocation/script-tests/argument-types.js for a similar
101    //        example.
102    value = v8ValueToWebCoreString(v8Value);
103    return true;
104}
105
106PassRefPtr<DOMStringList> OptionsObject::getKeyDOMStringList(const String& key) const
107{
108    v8::Local<v8::Value> v8Value;
109    if (!getKey(key, v8Value))
110        return 0;
111
112    if (!v8Value->IsArray())
113        return 0;
114
115    RefPtr<DOMStringList> ret = DOMStringList::create();
116    v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value);
117    for (size_t i = 0; i < v8Array->Length(); ++i) {
118        v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(i));
119        ret->append(v8ValueToWebCoreString(indexedValue));
120    }
121    return ret.release();
122}
123
124#if ENABLE(INDEXED_DATABASE)
125
126PassRefPtr<IDBKeyRange> OptionsObject::getKeyKeyRange(const String& key) const
127{
128    v8::Local<v8::Value> v8Value;
129    if (!getKey(key, v8Value))
130        return 0;
131
132    if (!V8IDBKeyRange::HasInstance(v8Value))
133        return 0;
134
135    return V8IDBKeyRange::toNative(v8::Handle<v8::Object>::Cast(v8Value));
136}
137
138#endif
139
140bool OptionsObject::getKey(const String& key, v8::Local<v8::Value>& value) const
141{
142    if (isUndefinedOrNull())
143        return false;
144    v8::Local<v8::Object> options = m_options->ToObject();
145    ASSERT(!options.IsEmpty());
146
147    v8::Handle<v8::String> v8Key = v8String(key);
148    if (!options->Has(v8Key))
149        return false;
150    value = options->Get(v8Key);
151    if (value.IsEmpty())
152        return false;
153    return !value->IsUndefined(); // FIXME: Is the undefined check necessary?
154}
155
156} // namespace WebCore
157