| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147 |
- /****************************************************************************
- Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
- http://www.cocos.com
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated engine source code (the "Software"), a limited,
- worldwide, royalty-free, non-assignable, revocable and non-exclusive license
- to use Cocos Creator solely to develop games on your target platforms. You shall
- not use Cocos Creator software for developing other software or tools that's
- used for developing games. You are not granted to publish, distribute,
- sublicense, and/or sell copies of Cocos Creator.
- The software or tools in this License Agreement are licensed, not sold.
- Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- ****************************************************************************/
- //
- // jsb_XMLHttpRequest.cpp
- // cocos2d_js_bindings
- //
- // Created by James Chen on 5/15/17.
- //
- //
- #include "base/ccConfig.h"
- #include "jsb_xmlhttprequest.hpp"
- #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
- #include <unordered_map>
- #include <string>
- #include <functional>
- #include <algorithm>
- #include <sstream>
- #include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
- #include "cocos/scripting/js-bindings/manual/jsb_conversions.hpp"
- #include "cocos/network/HttpClient.h"
- #include "cocos/base/CCData.h"
- #include "platform/CCApplication.h"
- using namespace cocos2d;
- using namespace cocos2d::network;
- namespace
- {
- std::unordered_map<int, std::string> _httpStatusCodeMap = {
- {100, "Continue"},
- {101, "Switching Protocols"},
- {102, "Processing"},
- {200, "OK"},
- {201, "Created"},
- {202, "Accepted"},
- {203, "Non-authoritative Information"},
- {204, "No Content"},
- {205, "Reset Content"},
- {206, "Partial Content"},
- {207, "Multi-Status"},
- {208, "Already Reported"},
- {226, "IM Used"},
- {300, "Multiple Choices"},
- {301, "Moved Permanently"},
- {302, "Found"},
- {303, "See Other"},
- {304, "Not Modified"},
- {305, "Use Proxy"},
- {307, "Temporary Redirect"},
- {308, "Permanent Redirect"},
- {400, "Bad Request"},
- {401, "Unauthorized"},
- {402, "Payment Required"},
- {403, "Forbidden"},
- {404, "Not Found"},
- {405, "Method Not Allowed"},
- {406, "Not Acceptable"},
- {407, "Proxy Authentication Required"},
- {408, "Request Timeout"},
- {409, "Conflict"},
- {410, "Gone"},
- {411, "Length Required"},
- {412, "Precondition Failed"},
- {413, "Payload Too Large"},
- {414, "Request-URI Too Long"},
- {415, "Unsupported Media Type"},
- {416, "Requested Range Not Satisfiable"},
- {417, "Expectation Failed"},
- {418, "I'm a teapot"},
- {421, "Misdirected Request"},
- {422, "Unprocessable Entity"},
- {423, "Locked"},
- {424, "Failed Dependency"},
- {426, "Upgrade Required"},
- {428, "Precondition Required"},
- {429, "Too Many Requests"},
- {431, "Request Header Fields Too Large"},
- {444, "Connection Closed Without Response"},
- {451, "Unavailable For Legal Reasons"},
- {499, "Client Closed Request"},
- {500, "Internal Server Error"},
- {501, "Not Implemented"},
- {502, "Bad Gateway"},
- {503, "Service Unavailable"},
- {504, "Gateway Timeout"},
- {505, "HTTP Version Not Supported"},
- {506, "Variant Also Negotiates"},
- {507, "Insufficient Storage"},
- {508, "Loop Detected"},
- {510, "Not Extended"},
- {511, "Network Authentication Required"},
- {599, "Network Connect Timeout Error"}};
- }
- class XMLHttpRequest : public Ref
- {
- public:
- // Ready States: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState
- enum class ReadyState : char
- {
- UNSENT = 0, // Client has been created. open() not called yet.
- OPENED = 1, // open() has been called.
- HEADERS_RECEIVED = 2, // send() has been called, and headers and status are available.
- LOADING = 3, // Downloading; responseText holds partial data.
- DONE = 4 // The operation is complete.
- };
- enum class ResponseType : char
- {
- STRING,
- ARRAY_BUFFER,
- BLOB,
- DOCUMENT,
- JSON
- };
- std::function<void()> onloadstart;
- std::function<void()> onload;
- std::function<void()> onloadend;
- std::function<void()> onreadystatechange;
- std::function<void()> onabort;
- std::function<void()> onerror;
- std::function<void()> ontimeout;
- XMLHttpRequest();
- bool open(const std::string& method, const std::string& url);
- void send();
- void sendString(const std::string& str);
- void sendBinary(const cocos2d::Data& data);
- void setRequestHeader(const std::string& key, const std::string& value);
- std::string getAllResponseHeaders() const;
- std::string getResonpseHeader(const std::string& key) const;
- ReadyState getReadyState() const { return _readyState; }
- uint16_t getStatus() const { return _status; }
- const std::string& getStatusText() const { return _statusText; }
- const std::string& getResponseText() const { return _responseText; }
- const cocos2d::Data& getResponseData() const { return _responseData; }
- ResponseType getResponseType() const { return _responseType; }
- void setResponseType(ResponseType type) { _responseType = type; }
- void overrideMimeType(const std::string &mimeType);
- std::string getMimeType() const;
- void setTimeout(unsigned long timeoutInMilliseconds);
- unsigned long getTimeout() const;
- void abort();
- bool isDiscardedByReset() const { return _isDiscardedByReset; }
- private:
- virtual ~XMLHttpRequest();
- void setReadyState(ReadyState readyState);
- void getHeader(const std::string& header);
- void onResponse(cocos2d::network::HttpClient* client, cocos2d::network::HttpResponse* response);
- void setHttpRequestData(const char* data, size_t len);
- void sendRequest();
- void setHttpRequestHeader();
- std::unordered_map<std::string, std::string> _httpHeader;
- std::unordered_map<std::string, std::string> _requestHeader;
- std::string _url;
- std::string _method;
- std::string _responseText;
- std::string _responseXML;
- std::string _statusText;
- std::string _overrideMimeType;
- cocos2d::Data _responseData;
- cocos2d::network::HttpRequest* _httpRequest;
- // cocos2d::EventListenerCustom* _resetDirectorListener;
- unsigned long _timeoutInMilliseconds;
- uint16_t _status;
- ResponseType _responseType;
- ReadyState _readyState;
- bool _withCredentialsValue;
- bool _errorFlag;
- bool _isAborted;
- bool _isLoadStart;
- bool _isLoadEnd;
- bool _isDiscardedByReset;
- bool _isTimeout;
- bool _isSending;
- };
- XMLHttpRequest::XMLHttpRequest()
- : onloadstart(nullptr)
- , onload(nullptr)
- , onloadend(nullptr)
- , onreadystatechange(nullptr)
- , onabort(nullptr)
- , onerror(nullptr)
- , ontimeout(nullptr)
- , _httpRequest(new (std::nothrow) HttpRequest())
- , _timeoutInMilliseconds(0UL)
- , _status(0)
- , _responseType(ResponseType:: STRING)
- , _readyState(ReadyState::UNSENT)
- , _withCredentialsValue(false)
- , _errorFlag(false)
- , _isAborted(false)
- , _isLoadStart(false)
- , _isLoadEnd(false)
- , _isDiscardedByReset(false)
- , _isTimeout(false)
- , _isSending(false)
- {
- }
- XMLHttpRequest::~XMLHttpRequest()
- {
- Application::getInstance()->getScheduler()->unscheduleAllForTarget(this);
- // Avoid HttpClient response call a released object!
- _httpRequest->setResponseCallback(nullptr);
- CC_SAFE_RELEASE(_httpRequest);
- }
- bool XMLHttpRequest::open(const std::string& method, const std::string& url)
- {
- if (_readyState != ReadyState::UNSENT)
- return false;
- _method = method;
- _url = url;
- HttpRequest::Type requestType = HttpRequest::Type::UNKNOWN;
- if (_method == "get" || _method == "GET")
- requestType = HttpRequest::Type::GET;
- else if (_method == "post" || _method == "POST")
- requestType = HttpRequest::Type::POST;
- else if (_method == "put" || _method == "PUT")
- requestType = HttpRequest::Type::PUT;
- else if (_method == "delete" || _method == "DELETE")
- requestType = HttpRequest::Type::DELETE;
- CCASSERT(requestType != HttpRequest::Type::UNKNOWN, (std::string("XMLHttpRequest.open: Unknown method: ") + method).c_str());
- _httpRequest->setRequestType(requestType);
- _httpRequest->setUrl(_url);
- _status = 0;
- _isAborted = false;
- _isTimeout = false;
- setReadyState(ReadyState::OPENED);
- return true;
- }
- void XMLHttpRequest::send()
- {
- sendRequest();
- }
- void XMLHttpRequest::sendString(const std::string& str)
- {
- setHttpRequestData(str.c_str(), str.length());
- sendRequest();
- }
- void XMLHttpRequest::sendBinary(const Data& data)
- {
- setHttpRequestData((const char*)data.getBytes(), data.getSize());
- sendRequest();
- }
- void XMLHttpRequest::setTimeout(unsigned long timeoutInMilliseconds)
- {
- _timeoutInMilliseconds = timeoutInMilliseconds;
- _httpRequest->setTimeout(timeoutInMilliseconds / 1000.0f + 2.0f); // Add 2 seconds more to ensure the timeout scheduler is invoked before http response.
- }
- unsigned long XMLHttpRequest::getTimeout() const
- {
- return _httpRequest->getTimeout() * 1000.0f;
- }
- void XMLHttpRequest::abort()
- {
- if (!_isLoadStart)
- return;
- _isAborted = true;
- _isSending = false;
- setReadyState(ReadyState::DONE);
- if (onabort != nullptr)
- {
- onabort();
- }
- _isLoadEnd = true;
- if (onloadend != nullptr)
- {
- onloadend();
- }
-
- _readyState = ReadyState::UNSENT;
-
- //request is aborted, no more callback needed.
- _httpRequest->setResponseCallback(nullptr);
- }
- void XMLHttpRequest::setReadyState(ReadyState readyState)
- {
- if (_readyState != readyState)
- {
- _readyState = readyState;
- if (onreadystatechange != nullptr)
- {
- onreadystatechange();
- }
- }
- }
- void XMLHttpRequest::getHeader(const std::string& header)
- {
- // check for colon.
- size_t found_header_field = header.find_first_of(":");
- if (found_header_field != std::string::npos)
- {
- // Found a header field.
- std::string http_field;
- std::string http_value;
- http_field = header.substr(0,found_header_field);
- http_value = header.substr(found_header_field+1, header.length());
- // Get rid of all \n
- if (!http_value.empty() && http_value[http_value.size() - 1] == '\n') {
- http_value.erase(http_value.size() - 1);
- }
- // Get rid of leading space (header is field: value format)
- if (!http_value.empty() && http_value[0] == ' ') {
- http_value.erase(0, 1);
- }
- // Transform field name to lower case as they are case-insensitive
- std::transform(http_field.begin(), http_field.end(), http_field.begin(), ::tolower);
- _httpHeader[http_field] = http_value;
- }
- else
- {
- // Get Header and Set StatusText
- // Split String into Tokens
- if (header.find("HTTP") == 0)
- {
- int _v1, _v2, code = 0;
- char statusText[64] = {0};
- sscanf(header.c_str(), "HTTP/%d.%d %d %63[^\n]", &_v1, &_v2, &code, statusText);
- _statusText = statusText;
- if(_statusText.empty())
- {
- auto itCode = _httpStatusCodeMap.find(code);
- if(itCode != _httpStatusCodeMap.end())
- {
- _statusText = itCode->second;
- }
- else
- {
- CCLOG("XMLHTTPRequest invalid response code %d", code);
- }
- }
- }
- }
- }
- void XMLHttpRequest::onResponse(HttpClient* client, HttpResponse* response)
- {
- Application::getInstance()->getScheduler()->unscheduleAllForTarget(this);
- _isSending = false;
-
- if(_isTimeout) {
- _isLoadEnd = true;
- if(onloadend)
- {
- onloadend();
- }
- return;
- }
-
- if (_isAborted || _readyState == ReadyState::UNSENT)
- {
- return;
- }
- std::string tag = response->getHttpRequest()->getTag();
- if (!tag.empty())
- {
- SE_LOGD("XMLHttpRequest::onResponse, %s completed\n", tag.c_str());
- }
- long statusCode = response->getResponseCode();
- char statusString[64] = {0};
- sprintf(statusString, "HTTP Status Code: %ld, tag = %s", statusCode, tag.c_str());
- _responseText.clear();
- _responseData.clear();
- if (!response->isSucceed())
- {
- std::string errorBuffer = response->getErrorBuffer();
- SE_LOGD("Response failed, error buffer: %s\n", errorBuffer.c_str());
- if (statusCode == 0 || statusCode == -1)
- {
- _errorFlag = true;
- _status = 0;
- _statusText.clear();
- if (onerror != nullptr)
- {
- onerror();
- }
- _isLoadEnd = true;
- if (onloadend != nullptr)
- {
- onloadend();
- }
- return;
- }
- }
- // set header
- std::vector<char> *headers = response->getResponseHeader();
- std::string header(headers->begin(), headers->end());
- std::istringstream stream(header);
- std::string line;
- while(std::getline(stream, line))
- {
- getHeader(line);
- }
- /** get the response data **/
- std::vector<char>* buffer = response->getResponseData();
- if (_responseType == ResponseType::STRING || _responseType == ResponseType::JSON)
- {
- _responseText.append(buffer->data(), buffer->size());
- }
- else
- {
- _responseData.copy((unsigned char*)buffer->data(), buffer->size());
- }
- _status = statusCode;
- setReadyState(ReadyState::DONE);
- if (onload != nullptr)
- {
- onload();
- }
- _isLoadEnd = true;
- if (onloadend != nullptr)
- {
- onloadend();
- }
- }
- void XMLHttpRequest::overrideMimeType(const std::string &mimeType)
- {
- _overrideMimeType = mimeType;
- }
- std::string XMLHttpRequest::getMimeType() const
- {
- if (!_overrideMimeType.empty()) {
- return _overrideMimeType;
- }
- auto contentType = getResonpseHeader("Content-Type");
- return contentType.empty() ? "text" : contentType;
- }
- void XMLHttpRequest::sendRequest()
- {
- if(_isSending)
- {
- //ref https://xhr.spec.whatwg.org/#the-send()-method
- //TODO: if send() flag is set, an exception should be thrown out.
- return;
- }
- _isSending = true;
- _isTimeout = false;
- if (_timeoutInMilliseconds > 0)
- {
- Application::getInstance()->getScheduler()->schedule([this](float dt){
- if (ontimeout != nullptr)
- ontimeout();
- _isTimeout = true;
- _readyState = ReadyState::UNSENT;
- }, this, _timeoutInMilliseconds / 1000.0f, 0, 0.0f, false, "XMLHttpRequest");
- }
- setHttpRequestHeader();
- _httpRequest->setResponseCallback(CC_CALLBACK_2(XMLHttpRequest::onResponse, this));
- cocos2d::network::HttpClient::getInstance()->sendImmediate(_httpRequest);
- if (onloadstart != nullptr)
- {
- onloadstart();
- }
- _isLoadStart = true;
- }
- void XMLHttpRequest::setHttpRequestData(const char* data, size_t len)
- {
- if (len > 0 &&
- (_method == "post" || _method == "POST" || _method == "put" || _method == "PUT"))
- {
- _httpRequest->setRequestData(data, len);
- }
- }
- void XMLHttpRequest::setRequestHeader(const std::string& key, const std::string& value)
- {
- std::stringstream header_s;
- std::stringstream value_s;
- std::string header;
- auto iter = _requestHeader.find(key);
- // Concatenate values when header exists.
- if (iter != _requestHeader.end())
- {
- value_s << iter->second << "," << value;
- }
- else
- {
- value_s << value;
- }
- _requestHeader[key] = value_s.str();
- }
- std::string XMLHttpRequest::getAllResponseHeaders() const
- {
- std::stringstream responseheaders;
- std::string responseheader;
- for (auto it = _httpHeader.begin(); it != _httpHeader.end(); ++it)
- {
- responseheaders << it->first << ": " << it->second << "\n";
- }
- responseheader = responseheaders.str();
- return responseheader;
- }
- std::string XMLHttpRequest::getResonpseHeader(const std::string& key) const
- {
- std::string ret;
- std::string value = key;
- std::transform(value.begin(), value.end(), value.begin(), ::tolower);
- auto iter = _httpHeader.find(value);
- if (iter != _httpHeader.end())
- {
- ret = iter->second;
- }
- return ret;
- }
- void XMLHttpRequest::setHttpRequestHeader()
- {
- std::vector<std::string> header;
- for (auto it = _requestHeader.begin(); it != _requestHeader.end(); ++it)
- {
- const char* first = it->first.c_str();
- const char* second = it->second.c_str();
- size_t len = sizeof(char) * (strlen(first) + 3 + strlen(second));
- char* test = (char*) malloc(len);
- memset(test, 0, len);
- strcpy(test, first);
- strcpy(test + strlen(first) , ": ");
- strcpy(test + strlen(first) + 2, second);
- header.push_back(test);
- free(test);
- }
- if (!header.empty())
- {
- _httpRequest->setHeaders(header);
- }
- }
- se::Class* __jsb_XMLHttpRequest_class = nullptr;
- static bool XMLHttpRequest_finalize(se::State& s)
- {
- XMLHttpRequest* request = (XMLHttpRequest*)s.nativeThisObject();
- SE_LOGD("XMLHttpRequest_finalize, %p ... \n", request);
- if (request->getReferenceCount() == 1)
- {
- request->autorelease();
- }
- else
- {
- request->release();
- }
- return true;
- }
- SE_BIND_FINALIZE_FUNC(XMLHttpRequest_finalize)
- static bool XMLHttpRequest_constructor(se::State& s)
- {
- XMLHttpRequest* request = new XMLHttpRequest();
- s.thisObject()->setPrivateData(request);
- se::Value thiz(s.thisObject());
- auto cb = [thiz](const char* eventName){
- se::ScriptEngine::getInstance()->clearException();
- se::AutoHandleScope hs;
-
- se::Object* thizObj = thiz.toObject();
- se::Value func;
- if (thizObj->getProperty(eventName, &func) && func.isObject() && func.toObject()->isFunction())
- {
- func.toObject()->call(se::EmptyValueArray, thizObj);
- }
- };
-
- request->onloadstart = [=](){
- if (!request->isDiscardedByReset())
- {
- thiz.toObject()->root();
- cb("onloadstart");
- }
- };
- request->onload = [=](){
- if (!request->isDiscardedByReset())
- {
- cb("onload");
- }
- };
- request->onloadend = [=](){
- if (!request->isDiscardedByReset())
- {
- // SE_LOGD("XMLHttpRequest (%p) onloadend ...\n", request);
- cb("onloadend");
- thiz.toObject()->unroot();
- }
- else
- {
- SE_LOGD("XMLHttpRequest (%p) onloadend after restart ScriptEngine.\n", request);
- request->release();
- }
- };
- request->onreadystatechange = [=](){
- if (!request->isDiscardedByReset())
- {
- cb("onreadystatechange");
- }
- };
- request->onabort = [=](){
- if (!request->isDiscardedByReset())
- {
- cb("onabort");
- }
- };
- request->onerror = [=](){
- if (!request->isDiscardedByReset())
- {
- cb("onerror");
- }
- };
- request->ontimeout = [=](){
- if (!request->isDiscardedByReset())
- {
- cb("ontimeout");
- }
- };
- return true;
- }
- SE_BIND_CTOR(XMLHttpRequest_constructor, __jsb_XMLHttpRequest_class, XMLHttpRequest_finalize)
- static bool XMLHttpRequest_open(se::State& s)
- {
- const auto& args = s.args();
- int argc = (int)args.size();
- if (argc >= 2)
- {
- XMLHttpRequest* request = (XMLHttpRequest*)s.nativeThisObject();
- bool ok = false;
- std::string method;
- ok = seval_to_std_string(args[0], &method);
- SE_PRECONDITION2(ok, false, "args[0] isn't a string.");
- std::string url;
- ok = seval_to_std_string(args[1], &url);
- SE_PRECONDITION2(ok, false, "args[1] isn't a string.");
- bool ret = request->open(method, url);
- s.rval().setBoolean(ret);
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting >=2", (int)argc);
- return false;
- }
- SE_BIND_FUNC(XMLHttpRequest_open)
- static bool XMLHttpRequest_abort(se::State& s)
- {
- XMLHttpRequest* request = (XMLHttpRequest*)s.nativeThisObject();
- request->abort();
- return true;
- }
- SE_BIND_FUNC(XMLHttpRequest_abort)
- static bool XMLHttpRequest_send(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- XMLHttpRequest* request = (XMLHttpRequest*)s.nativeThisObject();
- if (argc == 0)
- {
- request->send();
- }
- else if (argc > 0)
- {
- const auto& arg0 = args[0];
- if (arg0.isNullOrUndefined())
- {
- request->send();
- }
- else if (arg0.isString())
- {
- request->sendString(arg0.toString());
- }
- else if (arg0.isObject())
- {
- se::Object* obj = arg0.toObject();
- if (obj->isTypedArray())
- {
- uint8_t* ptr = nullptr;
- size_t len = 0;
- if (obj->getTypedArrayData(&ptr, &len))
- {
- Data data;
- data.copy(ptr, len);
- request->sendBinary(data);
- }
- else
- {
- SE_REPORT_ERROR("Failed to get data of TypedArray!");
- return false;
- }
- }
- else if (obj->isArrayBuffer())
- {
- uint8_t* ptr = nullptr;
- size_t len = 0;
- if (obj->getArrayBufferData(&ptr, &len))
- {
- Data data;
- data.copy(ptr, len);
- request->sendBinary(data);
- }
- else
- {
- SE_REPORT_ERROR("Failed to get data of ArrayBufferObject!");
- return false;
- }
- }
- else
- {
- SE_REPORT_ERROR("args[0] isn't a typed array or an array buffer");
- return false;
- }
- }
- else
- {
- const char* typeName = "UNKNOWN";
- if (arg0.isBoolean())
- typeName = "boolean";
- else if (arg0.isNumber())
- typeName = "number";
- SE_REPORT_ERROR("args[0] type: %s isn't supported!", typeName);
- return false;
- }
- }
- return true;
- }
- SE_BIND_FUNC(XMLHttpRequest_send)
- static bool XMLHttpRequest_setRequestHeader(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- if (argc >= 2)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- std::string key;
- bool ok = seval_to_std_string(args[0], &key);
- SE_PRECONDITION2(ok, false, "args[0] couldn't be converted to string.");
- std::string value;
- ok = seval_to_std_string(args[1], &value);
- SE_PRECONDITION2(ok, false, "args[1] couldn't be converted to string.");
- xhr->setRequestHeader(key, value);
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting >=2", (int)argc);
- return false;
- }
- SE_BIND_FUNC(XMLHttpRequest_setRequestHeader)
- static bool XMLHttpRequest_getAllResponseHeaders(se::State& s)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- std::string headers = xhr->getAllResponseHeaders();
- s.rval().setString(headers);
- return true;
- }
- SE_BIND_FUNC(XMLHttpRequest_getAllResponseHeaders)
- static bool XMLHttpRequest_getResonpseHeader(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- if (argc > 0)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- std::string key;
- bool ok = seval_to_std_string(args[0], &key);
- SE_PRECONDITION2(ok, false, "args[0] couldn't be converted to string.");
- std::string header = xhr->getResonpseHeader(key);
- s.rval().setString(header);
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting > 0", (int)argc);
- return false;
- }
- SE_BIND_FUNC(XMLHttpRequest_getResonpseHeader)
- static bool XMLHttpRequest_overrideMimeType(se::State& s)
- {
- const auto& args = s.args();
- int argc = (int)args.size();
- if(argc > 0 && args[0].isString())
- {
- std::string mimeType;
- seval_to_std_string(args[0], &mimeType);
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- xhr->overrideMimeType(mimeType);
- }
- return true;
- }
- SE_BIND_FUNC(XMLHttpRequest_overrideMimeType)
- static bool XMLHttpRequest_getMIMEType(se::State& s)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- auto type = xhr->getMimeType();
- s.rval().setString(type);
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getMIMEType)
- // getter
- static bool XMLHttpRequest_getReadyState(se::State& s)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- s.rval().setInt32((int32_t)xhr->getReadyState());
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getReadyState)
- static bool XMLHttpRequest_getStatus(se::State& s)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- s.rval().setInt32((int32_t)xhr->getStatus());
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getStatus)
- static bool XMLHttpRequest_getStatusText(se::State& s)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- s.rval().setString(xhr->getStatusText());
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getStatusText)
- static bool XMLHttpRequest_getResponseText(se::State& s)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- s.rval().setString(xhr->getResponseText());
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getResponseText)
- static bool XMLHttpRequest_getResponseXML(se::State& s)
- {
- // DOM API is not fully supported in cocos2d-x-lite.
- // `.responseXML` requires a document object that is not possible to fulfill.
- s.rval().setNull();
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getResponseXML)
- static bool XMLHttpRequest_getResponse(se::State& s)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- if (xhr->getResponseType() == XMLHttpRequest::ResponseType::STRING)
- {
- s.rval().setString(xhr->getResponseText());
- }
- else
- {
- if (xhr->getReadyState() != XMLHttpRequest::ReadyState::DONE)
- {
- s.rval().setNull();
- }
- else
- {
- if (xhr->getResponseType() == XMLHttpRequest::ResponseType::JSON)
- {
- const std::string& jsonText = xhr->getResponseText();
- se::HandleObject seObj(se::Object::createJSONObject(jsonText));
- if (!seObj.isEmpty())
- {
- s.rval().setObject(seObj);
- }
- else
- {
- s.rval().setNull();
- }
- }
- else if (xhr->getResponseType() == XMLHttpRequest::ResponseType::ARRAY_BUFFER)
- {
- const Data& data = xhr->getResponseData();
- se::HandleObject seObj(se::Object::createArrayBufferObject(data.getBytes(), data.getSize()));
- if (!seObj.isEmpty())
- {
- s.rval().setObject(seObj);
- }
- else
- {
- s.rval().setNull();
- }
- }
- else
- {
- SE_PRECONDITION2(false, false, "Invalid response type");
- }
- }
- }
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getResponse)
- static bool XMLHttpRequest_getTimeout(se::State& s)
- {
- XMLHttpRequest* cobj = (XMLHttpRequest*)s.nativeThisObject();
- s.rval().setUlong(cobj->getTimeout());
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getTimeout)
- static bool XMLHttpRequest_setTimeout(se::State& s)
- {
- const auto& args = s.args();
- int argc = (int)args.size();
- if (argc > 0)
- {
- XMLHttpRequest* cobj = (XMLHttpRequest*)s.nativeThisObject();
- unsigned long timeoutInMilliseconds = 0;
- bool ok = seval_to_ulong(args[0], &timeoutInMilliseconds);
- SE_PRECONDITION2(ok, false, "args[0] isn't a number");
- if (timeoutInMilliseconds < 50)
- {
- SE_LOGE("The timeout value (%lu ms) is too small, please note that timeout unit is milliseconds!", timeoutInMilliseconds);
- }
- cobj->setTimeout(timeoutInMilliseconds);
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting > 0", argc);
- return false;
- }
- SE_BIND_PROP_SET(XMLHttpRequest_setTimeout)
- static bool XMLHttpRequest_getResponseType(se::State& s)
- {
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- switch(xhr->getResponseType())
- {
- case XMLHttpRequest::ResponseType::STRING:
- s.rval().setString("text");
- break;
- case XMLHttpRequest::ResponseType::ARRAY_BUFFER:
- s.rval().setString("arraybuffer");
- break;
- case XMLHttpRequest::ResponseType::JSON:
- s.rval().setString("json");
- break;
- default:
- break;
- }
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getResponseType)
- static bool XMLHttpRequest_setResponseType(se::State& s)
- {
- const auto& args = s.args();
- size_t argc = args.size();
- if (argc > 0)
- {
- std::string type;
- bool ok = seval_to_std_string(args[0], &type);
- SE_PRECONDITION2(ok, false, "args[0] couldn't be converted to string!");
- XMLHttpRequest* xhr = (XMLHttpRequest*)s.nativeThisObject();
- if (type == "text")
- {
- xhr->setResponseType(XMLHttpRequest::ResponseType::STRING);
- }
- else if (type == "arraybuffer")
- {
- xhr->setResponseType(XMLHttpRequest::ResponseType::ARRAY_BUFFER);
- }
- else if (type == "json")
- {
- xhr->setResponseType(XMLHttpRequest::ResponseType::JSON);
- }
- else if (type == "document")
- {
- xhr->setResponseType(XMLHttpRequest::ResponseType::DOCUMENT);
- }
- else
- {
- SE_PRECONDITION2(false, false, "The response type isn't supported!");
- }
- return true;
- }
- SE_REPORT_ERROR("wrong number of arguments: %d, was expecting > 0", (int)argc);
- return false;
- }
- SE_BIND_PROP_SET(XMLHttpRequest_setResponseType)
- static bool XMLHttpRequest_getWithCredentials(se::State& s)
- {
- SE_LOGD("XMLHttpRequest.withCredentials isn't implemented on JSB!");
- return true;
- }
- SE_BIND_PROP_GET(XMLHttpRequest_getWithCredentials)
- bool register_all_xmlhttprequest(se::Object* global)
- {
- se::Class* cls = se::Class::create("XMLHttpRequest", global, nullptr, _SE(XMLHttpRequest_constructor));
- cls->defineFinalizeFunction(_SE(XMLHttpRequest_finalize));
- cls->defineFunction("open", _SE(XMLHttpRequest_open));
- cls->defineFunction("abort", _SE(XMLHttpRequest_abort));
- cls->defineFunction("send", _SE(XMLHttpRequest_send));
- cls->defineFunction("setRequestHeader", _SE(XMLHttpRequest_setRequestHeader));
- cls->defineFunction("getAllResponseHeaders", _SE(XMLHttpRequest_getAllResponseHeaders));
- cls->defineFunction("getResponseHeader", _SE(XMLHttpRequest_getResonpseHeader));
- cls->defineFunction("overrideMimeType", _SE(XMLHttpRequest_overrideMimeType));
- cls->defineProperty("__mimeType", _SE(XMLHttpRequest_getMIMEType), nullptr);
- cls->defineProperty("readyState", _SE(XMLHttpRequest_getReadyState), nullptr);
- cls->defineProperty("status", _SE(XMLHttpRequest_getStatus), nullptr);
- cls->defineProperty("statusText", _SE(XMLHttpRequest_getStatusText), nullptr);
- cls->defineProperty("responseText", _SE(XMLHttpRequest_getResponseText), nullptr);
- cls->defineProperty("responseXML", _SE(XMLHttpRequest_getResponseXML), nullptr);
- cls->defineProperty("response", _SE(XMLHttpRequest_getResponse), nullptr);
- cls->defineProperty("timeout", _SE(XMLHttpRequest_getTimeout), _SE(XMLHttpRequest_setTimeout));
- cls->defineProperty("responseType", _SE(XMLHttpRequest_getResponseType), _SE(XMLHttpRequest_setResponseType));
- cls->defineProperty("withCredentials", _SE(XMLHttpRequest_getWithCredentials), nullptr);
- cls->install();
- JSBClassType::registerClass<XMLHttpRequest>(cls);
- __jsb_XMLHttpRequest_class = cls;
- se::ScriptEngine::getInstance()->clearException();
- return true;
- }
- #endif //#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID || CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
|