"Not enough arguments" error should be TypeError
[WebKit-https.git] / Source / WebCore / bindings / v8 / custom / V8WebSocketCustom.cpp
1 /*
2  * Copyright (C) 2011 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this 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(WEB_SOCKETS)
34
35 #include "V8WebSocket.h"
36
37 #include "ExceptionCode.h"
38 #include "Frame.h"
39 #include "Settings.h"
40 #include "V8ArrayBuffer.h"
41 #include "V8Binding.h"
42 #include "V8Blob.h"
43 #include "V8Proxy.h"
44 #include "V8Utilities.h"
45 #include "WebSocket.h"
46 #include "WebSocketChannel.h"
47 #include "WorkerContext.h"
48 #include "WorkerContextExecutionProxy.h"
49 #include <wtf/MathExtras.h>
50 #include <wtf/Vector.h>
51
52 namespace WebCore {
53
54 v8::Handle<v8::Value> V8WebSocket::constructorCallback(const v8::Arguments& args)
55 {
56     INC_STATS("DOM.WebSocket.Constructor");
57
58     if (!args.IsConstructCall())
59         return throwError("DOM object constructor cannot be called as a function.", V8Proxy::TypeError);
60
61     if (ConstructorMode::current() == ConstructorMode::WrapExistingObject)
62         return args.Holder();
63
64     if (args.Length() == 0)
65         return throwError("Not enough arguments", V8Proxy::TypeError);
66
67     v8::TryCatch tryCatch;
68     v8::Handle<v8::String> urlstring = args[0]->ToString();
69     if (tryCatch.HasCaught())
70         return throwError(tryCatch.Exception());
71     if (urlstring.IsEmpty())
72         return throwError("Empty URL", V8Proxy::SyntaxError);
73
74     // Get the script execution context.
75     ScriptExecutionContext* context = getScriptExecutionContext();
76     if (!context)
77         return throwError("WebSocket constructor's associated frame is not available", V8Proxy::ReferenceError);
78
79     const KURL& url = context->completeURL(toWebCoreString(urlstring));
80
81     RefPtr<WebSocket> webSocket = WebSocket::create(context);
82     ExceptionCode ec = 0;
83
84     if (args.Length() < 2)
85         webSocket->connect(url, ec);
86     else {
87         v8::Local<v8::Value> protocolsValue = args[1];
88         if (protocolsValue->IsArray()) {
89             Vector<String> protocols;
90             v8::Local<v8::Array> protocolsArray = v8::Local<v8::Array>::Cast(protocolsValue);
91             for (uint32_t i = 0; i < protocolsArray->Length(); ++i) {
92                 v8::TryCatch tryCatchProtocol;
93                 v8::Handle<v8::String> protocol = protocolsArray->Get(v8::Int32::New(i))->ToString();
94                 if (tryCatchProtocol.HasCaught())
95                     return throwError(tryCatchProtocol.Exception());
96                 protocols.append(toWebCoreString(protocol));
97             }
98             webSocket->connect(url, protocols, ec);
99         } else {
100             v8::TryCatch tryCatchProtocol;
101             v8::Handle<v8::String> protocol = protocolsValue->ToString();
102             if (tryCatchProtocol.HasCaught())
103                 return throwError(tryCatchProtocol.Exception());
104             webSocket->connect(url, toWebCoreString(protocol), ec);
105         }
106     }
107     if (ec)
108         return throwError(ec);
109
110     V8DOMWrapper::setDOMWrapper(args.Holder(), &info, webSocket.get());
111     V8DOMWrapper::setJSWrapperForActiveDOMObject(webSocket.release(), v8::Persistent<v8::Object>::New(args.Holder()));
112     return args.Holder();
113 }
114
115 v8::Handle<v8::Value> V8WebSocket::sendCallback(const v8::Arguments& args)
116 {
117     INC_STATS("DOM.WebSocket.send()");
118
119     if (!args.Length())
120         return throwError("Not enough arguments", V8Proxy::TypeError);
121
122     WebSocket* webSocket = V8WebSocket::toNative(args.Holder());
123     v8::Handle<v8::Value> message = args[0];
124     ExceptionCode ec = 0;
125     bool result;
126     if (V8ArrayBuffer::HasInstance(message)) {
127         ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(message));
128         ASSERT(arrayBuffer);
129         result = webSocket->send(arrayBuffer, ec);
130     } else if (V8Blob::HasInstance(message)) {
131         Blob* blob = V8Blob::toNative(v8::Handle<v8::Object>::Cast(message));
132         ASSERT(blob);
133         result = webSocket->send(blob, ec);
134     } else {
135         v8::TryCatch tryCatch;
136         v8::Handle<v8::String> stringMessage = message->ToString();
137         if (tryCatch.HasCaught())
138             return throwError(tryCatch.Exception());
139         result = webSocket->send(toWebCoreString(stringMessage), ec);
140     }
141     if (ec)
142         return throwError(ec);
143
144     return v8Boolean(result);
145 }
146
147 v8::Handle<v8::Value> V8WebSocket::closeCallback(const v8::Arguments& args)
148 {
149     // FIXME: We should implement [Clamp] for IDL binding code generator, and
150     // remove this custom method.
151     WebSocket* webSocket = toNative(args.Holder());
152     int argumentCount = args.Length();
153     int code = WebSocketChannel::CloseEventCodeNotSpecified;
154     String reason = "";
155     if (argumentCount >= 1) {
156         double x = args[0]->NumberValue();
157         double maxValue = static_cast<double>(std::numeric_limits<uint16_t>::max());
158         double minValue = static_cast<double>(std::numeric_limits<uint16_t>::min());
159         if (isnan(x))
160             x = 0.0;
161         else
162             x = clampTo(x, minValue, maxValue);
163         code = clampToInteger(x);
164         if (argumentCount >= 2) {
165             v8::TryCatch tryCatch;
166             v8::Handle<v8::String> reasonValue = args[1]->ToString();
167             if (tryCatch.HasCaught())
168                 return throwError(tryCatch.Exception());
169             reason = toWebCoreString(reasonValue);
170         }
171     }
172     ExceptionCode ec = 0;
173     webSocket->close(code, reason, ec);
174     if (ec)
175         return throwError(ec);
176     return v8::Undefined();
177 }
178
179 }  // namespace WebCore
180
181 #endif  // ENABLE(WEB_SOCKETS)