From c4bcc83336c623b97e982443ce2f91d82d1a187d Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 16 Apr 2015 17:01:10 -0700 Subject: Facebook conversion. --- indra/llmessage/llcorehttputil.cpp | 91 +++++- indra/llmessage/llcorehttputil.h | 39 +++ indra/llxml/llcontrol.h | 2 +- indra/newview/llavatarrenderinfoaccountant.cpp | 4 +- indra/newview/llfacebookconnect.cpp | 396 ++++++++++++++++++++++++- indra/newview/llfacebookconnect.h | 11 + indra/newview/llviewerregion.cpp | 40 --- 7 files changed, 522 insertions(+), 61 deletions(-) (limited to 'indra') diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp index 2d6cca214c..a3226ee2c3 100644 --- a/indra/llmessage/llcorehttputil.cpp +++ b/indra/llmessage/llcorehttputil.cpp @@ -291,7 +291,7 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons // this method can return a map to the caller. // *TODO: Should it always do this? LLSD newResult = LLSD::emptyMap(); - newResult["content"] = result; + newResult[HttpCoroutineAdapter::HTTP_RESULTS_CONTENT] = result; result = newResult; } } @@ -305,11 +305,6 @@ void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::H LLSD httpresults = LLSD::emptyMap(); writeStatusCodes(status, response->getRequestURL(), httpresults); - // httpresults["success"] = static_cast(status); - // httpresults["type"] = static_cast(status.getType()); - // httpresults["status"] = static_cast(status.getStatus()); - // httpresults["message"] = static_cast(status.getMessage()); - // httpresults["url"] = static_cast(response->getRequestURL()); LLSD httpHeaders = LLSD::emptyMap(); LLCore::HttpHeaders * hdrs = response->getHeaders(); @@ -329,24 +324,24 @@ void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::H } } - httpresults["headers"] = httpHeaders; - result["http_result"] = httpresults; + httpresults[HttpCoroutineAdapter::HTTP_RESULTS_HEADERS] = httpHeaders; + result[HttpCoroutineAdapter::HTTP_RESULTS] = httpresults; } void HttpCoroHandler::writeStatusCodes(LLCore::HttpStatus status, const std::string &url, LLSD &result) { - result["success"] = static_cast(status); - result["type"] = static_cast(status.getType()); - result["status"] = static_cast(status.getStatus()); - result["message"] = static_cast(status.getMessage()); - result["url"] = static_cast(url); + result[HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS] = static_cast(status); + result[HttpCoroutineAdapter::HTTP_RESULTS_TYPE] = static_cast(status.getType()); + result[HttpCoroutineAdapter::HTTP_RESULTS_STATUS] = static_cast(status.getStatus()); + result[HttpCoroutineAdapter::HTTP_RESULTS_MESSAGE] = static_cast(status.getMessage()); + result[HttpCoroutineAdapter::HTTP_RESULTS_URL] = static_cast(url); } LLCore::HttpStatus HttpCoroHandler::getStatusFromLLSD(const LLSD &httpResults) { - LLCore::HttpStatus::type_enum_t type = static_cast(httpResults["type"].asInteger()); - short code = static_cast(httpResults["status"].asInteger()); + LLCore::HttpStatus::type_enum_t type = static_cast(httpResults[HttpCoroutineAdapter::HTTP_RESULTS_TYPE].asInteger()); + short code = static_cast(httpResults[HttpCoroutineAdapter::HTTP_RESULTS_STATUS].asInteger()); return LLCore::HttpStatus(type, code); } @@ -377,6 +372,16 @@ bool HttpRequestPumper::pollRequest(const LLSD&) } //======================================================================== +const std::string HttpCoroutineAdapter::HTTP_RESULTS("http_result"); +const std::string HttpCoroutineAdapter::HTTP_RESULTS_SUCCESS("success"); +const std::string HttpCoroutineAdapter::HTTP_RESULTS_TYPE("type"); +const std::string HttpCoroutineAdapter::HTTP_RESULTS_STATUS("status"); +const std::string HttpCoroutineAdapter::HTTP_RESULTS_MESSAGE("message"); +const std::string HttpCoroutineAdapter::HTTP_RESULTS_URL("url"); +const std::string HttpCoroutineAdapter::HTTP_RESULTS_HEADERS("headers"); +const std::string HttpCoroutineAdapter::HTTP_RESULTS_CONTENT("content"); + + HttpCoroutineAdapter::HttpCoroutineAdapter(const std::string &name, LLCore::HttpRequest::policy_t policyId, LLCore::HttpRequest::priority_t priority) : mAdapterName(name), @@ -422,6 +427,34 @@ LLSD HttpCoroutineAdapter::postAndYield(LLCoros::self & self, LLCore::HttpReques return results; } +LLSD HttpCoroutineAdapter::postAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t request, + const std::string & url, LLCore::BufferArray::ptr_t rawbody, + LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers) +{ + LLEventStream replyPump(mAdapterName, true); + LLCoreHttpUtil::HttpCoroHandler::ptr_t httpHandler = + LLCoreHttpUtil::HttpCoroHandler::ptr_t(new LLCoreHttpUtil::HttpCoroHandler(replyPump)); + + //LL_INFOS() << "Requesting transaction " << transactionId << LL_ENDL; + LLCoreHttpUtil::HttpRequestPumper pumper(request); + // The HTTPCoroHandler does not self delete, so retrieval of a the contained + // pointer from the smart pointer is safe in this case. + LLCore::HttpHandle hhandle = request->requestPost(mPolicyId, mPriority, url, rawbody.get(), + options.get(), headers.get(), httpHandler.get()); + + if (hhandle == LLCORE_HTTP_HANDLE_INVALID) + { + return HttpCoroutineAdapter::buildImmediateErrorResult(request, url); + } + + saveState(hhandle, request, httpHandler); + LLSD results = waitForEventOn(self, replyPump); + cleanState(); + + //LL_INFOS() << "Results for transaction " << transactionId << LL_ENDL; + return results; +} + LLSD HttpCoroutineAdapter::putAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t request, const std::string & url, const LLSD & body, LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers) @@ -477,6 +510,34 @@ LLSD HttpCoroutineAdapter::getAndYield(LLCoros::self & self, LLCore::HttpRequest return results; } +LLSD HttpCoroutineAdapter::deleteAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t request, + const std::string & url, + LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers) +{ + LLEventStream replyPump(mAdapterName + "Reply", true); + LLCoreHttpUtil::HttpCoroHandler::ptr_t httpHandler = + LLCoreHttpUtil::HttpCoroHandler::ptr_t(new LLCoreHttpUtil::HttpCoroHandler(replyPump)); + + //LL_INFOS() << "Requesting transaction " << transactionId << LL_ENDL; + LLCoreHttpUtil::HttpRequestPumper pumper(request); + // The HTTPCoroHandler does not self delete, so retrieval of a the contained + // pointer from the smart pointer is safe in this case. + LLCore::HttpHandle hhandle = request->requestDelete(mPolicyId, mPriority, + url, options.get(), headers.get(), httpHandler.get()); + + if (hhandle == LLCORE_HTTP_HANDLE_INVALID) + { + return HttpCoroutineAdapter::buildImmediateErrorResult(request, url); + } + + saveState(hhandle, request, httpHandler); + LLSD results = waitForEventOn(self, replyPump); + cleanState(); + //LL_INFOS() << "Results for transaction " << transactionId << LL_ENDL; + return results; +} + + void HttpCoroutineAdapter::cancelYieldingOperation() { LLCore::HttpRequest::ptr_t request = mWeakRequest.lock(); diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h index 6fcf03b95c..cd137dbbe1 100644 --- a/indra/llmessage/llcorehttputil.h +++ b/indra/llmessage/llcorehttputil.h @@ -205,6 +205,7 @@ LLCore::HttpHandle requestPatchWithLLSD(LLCore::HttpRequest::ptr_t & request, class HttpCoroHandler : public LLCore::HttpHandler { public: + typedef boost::shared_ptr ptr_t; typedef boost::weak_ptr wptr_t; @@ -248,6 +249,15 @@ private: class HttpCoroutineAdapter { public: + static const std::string HTTP_RESULTS; + static const std::string HTTP_RESULTS_SUCCESS; + static const std::string HTTP_RESULTS_TYPE; + static const std::string HTTP_RESULTS_STATUS; + static const std::string HTTP_RESULTS_MESSAGE; + static const std::string HTTP_RESULTS_URL; + static const std::string HTTP_RESULTS_HEADERS; + static const std::string HTTP_RESULTS_CONTENT; + typedef boost::shared_ptr ptr_t; typedef boost::weak_ptr wptr_t; @@ -264,6 +274,25 @@ public: const std::string & url, const LLSD & body, LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false)); + LLSD postAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t request, + const std::string & url, LLCore::BufferArray::ptr_t rawbody, + LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), + LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false)); + LLSD postAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t &request, + const std::string & url, const LLSD & body, + LLCore::HttpHeaders::ptr_t &headers) + { + return postAndYield(self, request, url, body, + LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), headers); + } + + LLSD postAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t &request, + const std::string & url, LLCore::BufferArray::ptr_t &rawbody, + LLCore::HttpHeaders::ptr_t &headers) + { + return postAndYield(self, request, url, rawbody, + LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), headers); + } /// Execute a Put transaction on the supplied URL and yield execution of /// the coroutine until a result is available. @@ -285,6 +314,16 @@ public: LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false)); + /// Execute a DELETE transaction on the supplied URL and yield execution of + /// the coroutine until a result is available. + /// + /// @Note: the request's smart pointer is passed by value so that it will + /// not be deallocated during the yield. + LLSD deleteAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t request, + const std::string & url, + LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), + LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false)); + /// void cancelYieldingOperation(); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 04575d81e0..8116adeae2 100755 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -256,7 +256,7 @@ public: } else { - LL_WARNS() << "Control " << name << " not found." << LL_ENDL; + LL_WARNS_ONCE() << "Control " << name << " not found." << LL_ENDL; return T(); } return convert_from_llsd(value, type, name); diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index d532dbc6b1..4436fe74d6 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -65,7 +65,7 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro(LLCoros::self& self, { LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentRequest", httpPolicy)); + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); LLSD result = httpAdapter->getAndYield(self, httpRequest, url); @@ -135,7 +135,7 @@ void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(LLCoros::self& sel { LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t - httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentRequest", httpPolicy)); + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); diff --git a/indra/newview/llfacebookconnect.cpp b/indra/newview/llfacebookconnect.cpp index 28319564e4..dc50ec81f1 100755 --- a/indra/newview/llfacebookconnect.cpp +++ b/indra/newview/llfacebookconnect.cpp @@ -45,6 +45,7 @@ #include "llfloaterwebcontent.h" #include "llfloaterreg.h" +#include "llcorehttputil.h" boost::scoped_ptr LLFacebookConnect::sStateWatcher(new LLEventStream("FacebookConnectState")); boost::scoped_ptr LLFacebookConnect::sInfoWatcher(new LLEventStream("FacebookConnectInfo")); @@ -125,6 +126,58 @@ LLFacebookConnectHandler gFacebookConnectHandler; /////////////////////////////////////////////////////////////////////////////// // +#if 1 + +void LLFacebookConnect::facebookConnectCoro(LLCoros::self& self, std::string authCode, std::string authState) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions); + + LLSD putData; + if (!authCode.empty()) + { + putData["code"] = authCode; + } + if (!authState.empty()) + { + putData["state"] = authState; + } + + httpOpts->setWantHeaders(true); + + setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS); + + LLSD result = httpAdapter->putAndYield(self, httpRequest, getFacebookConnectURL("/connection"), putData, httpOpts); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + if (!status) + { + if (status == LLCore::HttpStatus(HTTP_FOUND)) + { + std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION]; + if (location.empty()) + { + LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL; + } + else + { + openFacebookWeb(location); + } + } + } + else + { + LL_INFOS("FacebookConnect") << "Connect successful. " << LL_ENDL; + setConnectionState(LLFacebookConnect::FB_CONNECTED); + } + +} + +#else class LLFacebookConnectResponder : public LLHTTPClient::Responder { LOG_CLASS(LLFacebookConnectResponder); @@ -166,9 +219,129 @@ public: } } }; +#endif /////////////////////////////////////////////////////////////////////////////// // +#if 1 +bool LLFacebookConnect::testShareStatus(LLSD &result) +{ + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + + if (status) + return true; + + if (status == LLCore::HttpStatus(HTTP_FOUND)) + { + std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION]; + if (location.empty()) + { + LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL; + } + else + { + openFacebookWeb(location); + } + } + if (status == LLCore::HttpStatus(HTTP_NOT_FOUND)) + { + LL_DEBUGS("FacebookConnect") << "Not connected. " << LL_ENDL; + connectToFacebook(); + } + else + { + LL_WARNS("FacebookConnect") << "HTTP Status error " << status.toString() << LL_ENDL; + setConnectionState(LLFacebookConnect::FB_POST_FAILED); + log_facebook_connect_error("Share", status.getStatus(), status.toString(), + result.get("error_code"), result.get("error_description")); + } + return false; +} + +void LLFacebookConnect::facebookShareCoro(LLCoros::self& self, std::string route, LLSD share) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + setConnectionState(LLFacebookConnect::FB_POSTING); + + LLSD result = httpAdapter->postAndYield(self, httpRequest, getFacebookConnectURL(route, true), share); + + if (testShareStatus(result)) + { + toast_user_for_facebook_success(); + LL_DEBUGS("FacebookConnect") << "Post successful. " << LL_ENDL; + setConnectionState(LLFacebookConnect::FB_POSTED); + } +} + +void LLFacebookConnect::facebookShareImageCoro(LLCoros::self& self, std::string route, LLPointer image, std::string caption) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders); + + std::string imageFormat; + if (dynamic_cast(image.get())) + { + imageFormat = "png"; + } + else if (dynamic_cast(image.get())) + { + imageFormat = "jpg"; + } + else + { + LL_WARNS() << "Image to upload is not a PNG or JPEG" << LL_ENDL; + return; + } + + // All this code is mostly copied from LLWebProfile::post() + static const std::string boundary = "----------------------------0123abcdefab"; + + std::string contentType = "multipart/form-data; boundary=" + boundary; + httpHeaders->append("Content-Type", contentType.c_str()); + + LLCore::BufferArray::ptr_t raw = LLCore::BufferArray::ptr_t(new LLCore::BufferArray(), false); // + LLCore::BufferArrayStream body(raw.get()); + + // *NOTE: The order seems to matter. + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"caption\"\r\n\r\n" + << caption << "\r\n"; + + body << "--" << boundary << "\r\n" + << "Content-Disposition: form-data; name=\"image\"; filename=\"Untitled." << imageFormat << "\"\r\n" + << "Content-Type: image/" << imageFormat << "\r\n\r\n"; + + // Insert the image data. + // *FIX: Treating this as a string will probably screw it up ... + U8* image_data = image->getData(); + for (S32 i = 0; i < image->getDataSize(); ++i) + { + body << image_data[i]; + } + + body << "\r\n--" << boundary << "--\r\n"; + + setConnectionState(LLFacebookConnect::FB_POSTING); + + LLSD result = httpAdapter->postAndYield(self, httpRequest, getFacebookConnectURL(route, true), raw, httpHeaders); + + if (testShareStatus(result)) + { + toast_user_for_facebook_success(); + LL_DEBUGS("FacebookConnect") << "Post successful. " << LL_ENDL; + setConnectionState(LLFacebookConnect::FB_POSTED); + } +} + +#else class LLFacebookShareResponder : public LLHTTPClient::Responder { LOG_CLASS(LLFacebookShareResponder); @@ -215,9 +388,43 @@ public: } } }; +#endif /////////////////////////////////////////////////////////////////////////////// // +#if 1 +void LLFacebookConnect::facebookDisconnectCoro(LLCoros::self& self) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + setConnectionState(LLFacebookConnect::FB_DISCONNECTING); + + LLSD result = httpAdapter->deleteAndYield(self, httpRequest, getFacebookConnectURL("/connection")); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + if (!status && (status != LLCore::HttpStatus(HTTP_FOUND))) + { + LL_WARNS("FacebookConnect") << "Failed to disconnect:" << status.toTerseString() << LL_ENDL; + setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED); + log_facebook_connect_error("Disconnect", status.getStatus(), status.toString(), + result.get("error_code"), result.get("error_description")); + } + else + { + LL_DEBUGS("FacebookConnect") << "Facebook Disconnect successful. " << LL_ENDL; + clearInfo(); + clearContent(); + //Notify state change + setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED); + } + +} + +#else class LLFacebookDisconnectResponder : public LLHTTPClient::Responder { LOG_CLASS(LLFacebookDisconnectResponder); @@ -261,9 +468,56 @@ public: } } }; +#endif /////////////////////////////////////////////////////////////////////////////// // +#if 1 +void LLFacebookConnect::facebookConnectedCheckCoro(LLCoros::self& self, bool autoConnect) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + setConnectionState(LLFacebookConnect::FB_CONNECTION_IN_PROGRESS); + + LLSD result = httpAdapter->getAndYield(self, httpRequest, getFacebookConnectURL("/connection", true)); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + + if (!status) + { + if ( status == LLCore::HttpStatus(HTTP_NOT_FOUND) ) + { + LL_DEBUGS("FacebookConnect") << "Not connected. " << LL_ENDL; + if (autoConnect) + { + connectToFacebook(); + } + else + { + setConnectionState(LLFacebookConnect::FB_NOT_CONNECTED); + } + } + else + { + LL_WARNS("FacebookConnect") << "Failed to test connection:" << status.toTerseString() << LL_ENDL; + + setConnectionState(LLFacebookConnect::FB_DISCONNECT_FAILED); + log_facebook_connect_error("Connected", status.getStatus(), status.toString(), + result.get("error_code"), result.get("error_description")); + } + } + else + { + LL_DEBUGS("FacebookConnect") << "Connect successful. " << LL_ENDL; + setConnectionState(LLFacebookConnect::FB_CONNECTED); + } +} + +#else class LLFacebookConnectedResponder : public LLHTTPClient::Responder { LOG_CLASS(LLFacebookConnectedResponder); @@ -308,9 +562,50 @@ public: private: bool mAutoConnect; }; +#endif /////////////////////////////////////////////////////////////////////////////// // +#if 1 +void LLFacebookConnect::facebookConnectInfoCoro(LLCoros::self& self) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndYield(self, httpRequest, getFacebookConnectURL("/info", true)); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + + if (status == LLCore::HttpStatus(HTTP_FOUND)) + { + std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION]; + if (location.empty()) + { + LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL; + } + else + { + openFacebookWeb(location); + } + } + else if (!status) + { + LL_WARNS("FacebookConnect") << "Facebook Info failed: " << status.toString() << LL_ENDL; + log_facebook_connect_error("Info", status.getStatus(), status.toString(), + result.get("error_code"), result.get("error_description")); + } + else + { + LL_INFOS("FacebookConnect") << "Facebook: Info received" << LL_ENDL; + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + storeInfo(result); + } +} + +#else class LLFacebookInfoResponder : public LLHTTPClient::Responder { LOG_CLASS(LLFacebookInfoResponder); @@ -347,9 +642,51 @@ public: } } }; +#endif /////////////////////////////////////////////////////////////////////////////// // +#if 1 +void LLFacebookConnect::facebookConnectFriendsCoro(LLCoros::self& self) +{ + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("FacebookConnect", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndYield(self, httpRequest, getFacebookConnectURL("/friends", true)); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + + if (status == LLCore::HttpStatus(HTTP_FOUND)) + { + std::string location = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS][HTTP_IN_HEADER_LOCATION]; + if (location.empty()) + { + LL_WARNS("FacebookConnect") << "Missing Location header " << LL_ENDL; + } + else + { + openFacebookWeb(location); + } + } + else if (!status) + { + LL_WARNS("FacebookConnect") << "Facebook Friends failed: " << status.toString() << LL_ENDL; + log_facebook_connect_error("Info", status.getStatus(), status.toString(), + result.get("error_code"), result.get("error_description")); + } + else + { + LL_INFOS("FacebookConnect") << "Facebook: Friends received" << LL_ENDL; + result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS); + LLSD content = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_CONTENT]; + storeContent(content); + } +} + +#else class LLFacebookFriendsResponder : public LLHTTPClient::Responder { LOG_CLASS(LLFacebookFriendsResponder); @@ -385,6 +722,7 @@ public: } } }; +#endif /////////////////////////////////////////////////////////////////////////////// // @@ -439,6 +777,11 @@ std::string LLFacebookConnect::getFacebookConnectURL(const std::string& route, b void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const std::string& auth_state) { +#if 1 + LLCoros::instance().launch("LLFacebookConnect::facebookConnectCoro", + boost::bind(&LLFacebookConnect::facebookConnectCoro, this, _1, auth_code, auth_state)); + +#else LLSD body; if (!auth_code.empty()) { @@ -450,29 +793,48 @@ void LLFacebookConnect::connectToFacebook(const std::string& auth_code, const st } LLHTTPClient::put(getFacebookConnectURL("/connection"), body, new LLFacebookConnectResponder()); +#endif } void LLFacebookConnect::disconnectFromFacebook() { - LLHTTPClient::del(getFacebookConnectURL("/connection"), new LLFacebookDisconnectResponder()); +#if 1 + LLCoros::instance().launch("LLFacebookConnect::facebookDisconnectCoro", + boost::bind(&LLFacebookConnect::facebookDisconnectCoro, this, _1)); + +#else + LLHTTPClient::del(getFacebookConnectURL("/connection"), new LLFacebookDisconnectResponder()); +#endif } void LLFacebookConnect::checkConnectionToFacebook(bool auto_connect) { +#if 1 + LLCoros::instance().launch("LLFacebookConnect::facebookConnectedCheckCoro", + boost::bind(&LLFacebookConnect::facebookConnectedCheckCoro, this, _1, auto_connect)); + +#else const bool follow_redirects = false; const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; LLHTTPClient::get(getFacebookConnectURL("/connection", true), new LLFacebookConnectedResponder(auto_connect), LLSD(), timeout, follow_redirects); +#endif } void LLFacebookConnect::loadFacebookInfo() { if(mRefreshInfo) { +#if 1 + LLCoros::instance().launch("LLFacebookConnect::facebookConnectInfoCoro", + boost::bind(&LLFacebookConnect::facebookConnectInfoCoro, this, _1)); + +#else const bool follow_redirects = false; const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; LLHTTPClient::get(getFacebookConnectURL("/info", true), new LLFacebookInfoResponder(), LLSD(), timeout, follow_redirects); +#endif } } @@ -480,14 +842,21 @@ void LLFacebookConnect::loadFacebookFriends() { if(mRefreshContent) { +#if 1 + LLCoros::instance().launch("LLFacebookConnect::facebookConnectFriendsCoro", + boost::bind(&LLFacebookConnect::facebookConnectFriendsCoro, this, _1)); +#else + const bool follow_redirects = false; const F32 timeout = HTTP_REQUEST_EXPIRY_SECS; LLHTTPClient::get(getFacebookConnectURL("/friends", true), new LLFacebookFriendsResponder(), LLSD(), timeout, follow_redirects); +#endif } } -void LLFacebookConnect::postCheckin(const std::string& location, const std::string& name, const std::string& description, const std::string& image, const std::string& message) +void LLFacebookConnect::postCheckin(const std::string& location, const std::string& name, + const std::string& description, const std::string& image, const std::string& message) { LLSD body; if (!location.empty()) @@ -511,22 +880,37 @@ void LLFacebookConnect::postCheckin(const std::string& location, const std::stri body["message"] = message; } +#if 1 + LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro", + boost::bind(&LLFacebookConnect::facebookShareCoro, this, _1, "/share/checkin", body)); +#else // Note: we can use that route for different publish action. We should be able to use the same responder. LLHTTPClient::post(getFacebookConnectURL("/share/checkin", true), body, new LLFacebookShareResponder()); +#endif } void LLFacebookConnect::sharePhoto(const std::string& image_url, const std::string& caption) { + // *TODO: I could not find an instace where this method is used. Remove? LLSD body; body["image"] = image_url; body["caption"] = caption; +#if 1 + LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro", + boost::bind(&LLFacebookConnect::facebookShareCoro, this, _1, "/share/photo", body)); +#else // Note: we can use that route for different publish action. We should be able to use the same responder. LLHTTPClient::post(getFacebookConnectURL("/share/photo", true), body, new LLFacebookShareResponder()); +#endif } void LLFacebookConnect::sharePhoto(LLPointer image, const std::string& caption) { +#if 1 + LLCoros::instance().launch("LLFacebookConnect::facebookShareImageCoro", + boost::bind(&LLFacebookConnect::facebookShareImageCoro, this, _1, "/share/photo", image, caption)); +#else std::string imageFormat; if (dynamic_cast(image.get())) { @@ -576,15 +960,21 @@ void LLFacebookConnect::sharePhoto(LLPointer image, const std: // Note: we can use that route for different publish action. We should be able to use the same responder. LLHTTPClient::postRaw(getFacebookConnectURL("/share/photo", true), data, size, new LLFacebookShareResponder(), headers); +#endif } void LLFacebookConnect::updateStatus(const std::string& message) { LLSD body; body["message"] = message; - + +#if 1 + LLCoros::instance().launch("LLFacebookConnect::facebookShareCoro", + boost::bind(&LLFacebookConnect::facebookShareCoro, this, _1, "/share/wall", body)); +#else // Note: we can use that route for different publish action. We should be able to use the same responder. LLHTTPClient::post(getFacebookConnectURL("/share/wall", true), body, new LLFacebookShareResponder()); +#endif } void LLFacebookConnect::storeInfo(const LLSD& info) diff --git a/indra/newview/llfacebookconnect.h b/indra/newview/llfacebookconnect.h index c157db2178..f569c2f486 100644 --- a/indra/newview/llfacebookconnect.h +++ b/indra/newview/llfacebookconnect.h @@ -30,6 +30,8 @@ #include "llsingleton.h" #include "llimage.h" +#include "llcoros.h" +#include "lleventcoro.h" class LLEventPump; @@ -101,6 +103,15 @@ private: static boost::scoped_ptr sStateWatcher; static boost::scoped_ptr sInfoWatcher; static boost::scoped_ptr sContentWatcher; + + bool testShareStatus(LLSD &results); + void facebookConnectCoro(LLCoros::self& self, std::string authCode, std::string authState); + void facebookConnectedCheckCoro(LLCoros::self& self, bool autoConnect); + void facebookDisconnectCoro(LLCoros::self& self); + void facebookShareCoro(LLCoros::self& self, std::string route, LLSD share); + void facebookShareImageCoro(LLCoros::self& self, std::string route, LLPointer image, std::string caption); + void facebookConnectInfoCoro(LLCoros::self& self); + void facebookConnectFriendsCoro(LLCoros::self& self); }; #endif // LL_LLFACEBOOKCONNECT_H diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index f78b08eb70..36dd778746 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -201,46 +201,6 @@ public: void requestSimulatorFeatureCoro(LLCoros::self& self, std::string url, U64 regionHandle); }; -// support for secondlife:///app/region/{REGION} SLapps -// N.B. this is defined to work exactly like the classic secondlife://{REGION} -// However, the later syntax cannot support spaces in the region name because -// spaces (and %20 chars) are illegal in the hostname of an http URL. Some -// browsers let you get away with this, but some do not (such as Qt's Webkit). -// Hence we introduced the newer secondlife:///app/region alternative. -class LLRegionHandler : public LLCommandHandler -{ -public: - // requests will be throttled from a non-trusted browser - LLRegionHandler() : LLCommandHandler("region", UNTRUSTED_THROTTLE) {} - - bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) - { - // make sure that we at least have a region name - int num_params = params.size(); - if (num_params < 1) - { - return false; - } - - // build a secondlife://{PLACE} SLurl from this SLapp - std::string url = "secondlife://"; - for (int i = 0; i < num_params; i++) - { - if (i > 0) - { - url += "/"; - } - url += params[i].asString(); - } - - // Process the SLapp as if it was a secondlife://{PLACE} SLurl - LLURLDispatcher::dispatch(url, "clicked", web, true); - return true; - } - -}; -LLRegionHandler gRegionHandler; - void LLViewerRegionImpl::requestBaseCapabilitiesCoro(LLCoros::self& self, U64 regionHandle) { LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); -- cgit v1.2.3