/** * @file llfloatertos.cpp * @brief Terms of Service Agreement dialog * * $LicenseInfo:firstyear=2003&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llfloatertos.h" // viewer includes #include "llviewerstats.h" #include "llviewerwindow.h" // linden library includes #include "llbutton.h" #include "llevents.h" #include "llnotificationsutil.h" #include "llradiogroup.h" #include "lltextbox.h" #include "llui.h" #include "lluictrlfactory.h" #include "llfilesystem.h" #include "message.h" #include "llstartup.h" // login_alert_done #include "llcorehttputil.h" #include "llfloaterreg.h" LLFloaterTOS::LLFloaterTOS(const LLSD& data) : LLModalDialog( data["message"].asString() ), mMessage(data["message"].asString()), mLoadingScreenLoaded(false), mSiteAlive(false), mRealNavigateBegun(false), mReplyPumpName(data["reply_pump"].asString()) { } bool LLFloaterTOS::postBuild() { childSetAction("Continue", onContinue, this); childSetAction("Cancel", onCancel, this); childSetCommitCallback("agree_chk", updateAgree, this); if (hasChild("tos_text")) { // this displays the critical message LLUICtrl *tos_text = getChild("tos_text"); tos_text->setEnabled(false); tos_text->setFocus(true); tos_text->setValue(LLSD(mMessage)); return true; } // disable Agree to TOS radio button until the page has fully loaded updateAgreeEnabled(false); // hide the SL text widget if we're displaying TOS with using a browser widget. LLUICtrl *editor = getChild("tos_text"); editor->setVisible(false); LLMediaCtrl* web_browser = getChild("tos_html"); if ( web_browser ) { // if we are forced to send users to an external site in their system browser // (e.g.) Linux users because of lack of media support for HTML ToS page // remove exisiting UI and replace with a link to external page where users can accept ToS #ifdef EXTERNAL_TOS LLTextBox* header = getChild("tos_heading"); if (header) header->setVisible(false); LLTextBox* external_prompt = getChild("external_tos_required"); if (external_prompt) external_prompt->setVisible(true); web_browser->setVisible(false); updateAgreeEnabled(true); #else web_browser->addObserver(this); // Don't use the start_url parameter for this browser instance -- it may finish loading before we get to add our observer. // Store the URL separately and navigate here instead. web_browser->navigateTo( getString( "loading_url" ) ); LLPluginClassMedia* media_plugin = web_browser->getMediaPlugin(); if (media_plugin) { // All links from tos_html should be opened in external browser media_plugin->setOverrideClickTarget("_external"); } #endif } return true; } void LLFloaterTOS::setSiteIsAlive( bool alive ) { // if we are forced to send users to an external site in their system browser // (e.g.) Linux users because of lack of media support for HTML ToS page // force the regular HTML UI to deactivate so alternative is rendered instead. #ifdef EXTERNAL_TOS mSiteAlive = false; #else mSiteAlive = alive; // only do this for TOS pages if (hasChild("tos_html")) { // if the contents of the site was retrieved if ( alive ) { // navigate to the "real" page if(!mRealNavigateBegun && mSiteAlive) { LLMediaCtrl* web_browser = getChild("tos_html"); if(web_browser) { mRealNavigateBegun = true; web_browser->navigateTo( getString( "real_url" ) ); } } } else { LL_INFOS("TOS") << "ToS page: ToS page unavailable!" << LL_ENDL; // normally this is set when navigation to TOS page navigation completes (so you can't accept before TOS loads) // but if the page is unavailable, we need to do this now updateAgreeEnabled(true); LLTextBox* tos_list = getChild("agree_list"); tos_list->setEnabled(true); } } #endif } LLFloaterTOS::~LLFloaterTOS() { } // virtual void LLFloaterTOS::draw() { // draw children LLModalDialog::draw(); } // update status of "Agree" checkbox and text void LLFloaterTOS::updateAgreeEnabled(bool enabled) { LLCheckBoxCtrl* tos_agreement_agree_cb = getChild("agree_chk"); tos_agreement_agree_cb->setEnabled(enabled); LLTextBox* tos_agreement_agree_text = getChild("agree_list"); tos_agreement_agree_text->setEnabled(enabled); } // static void LLFloaterTOS::updateAgree(LLUICtrl*, void* userdata ) { LLFloaterTOS* self = (LLFloaterTOS*) userdata; bool agree = self->getChild("agree_chk")->getValue().asBoolean(); self->getChildView("Continue")->setEnabled(agree); } // static void LLFloaterTOS::onContinue( void* userdata ) { LLFloaterTOS* self = (LLFloaterTOS*) userdata; LL_INFOS("TOS") << "User agrees with TOS." << LL_ENDL; if(self->mReplyPumpName != "") { LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(true)); } self->closeFloater(); // destroys this object } // static void LLFloaterTOS::onCancel( void* userdata ) { LLFloaterTOS* self = (LLFloaterTOS*) userdata; LL_INFOS("TOS") << "User disagrees with TOS." << LL_ENDL; LLNotificationsUtil::add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done); if(self->mReplyPumpName != "") { LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(false)); } // reset state for next time we come to TOS self->mLoadingScreenLoaded = false; self->mSiteAlive = false; self->mRealNavigateBegun = false; // destroys this object self->closeFloater(); } //virtual void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event) { if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) { if(!mLoadingScreenLoaded) { mLoadingScreenLoaded = true; std::string url(getString("real_url")); LLHandle handle = getHandle(); LLCoros::instance().launch("LLFloaterTOS::testSiteIsAliveCoro", boost::bind(&LLFloaterTOS::testSiteIsAliveCoro, handle, url)); } else if(mRealNavigateBegun) { LL_INFOS("TOS") << "TOS: NAVIGATE COMPLETE" << LL_ENDL; // enable Agree to TOS check box now that page has loaded updateAgreeEnabled(true); } } } void LLFloaterTOS::testSiteIsAliveCoro(LLHandle handle, std::string url) { LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("genericPostCoro", httpPolicy)); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); LLCore::HttpOptions::ptr_t httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions); httpOpts->setWantHeaders(true); httpOpts->setHeadersOnly(true); LL_INFOS("testSiteIsAliveCoro") << "Generic POST for " << url << LL_ENDL; LLSD result = httpAdapter->getAndSuspend(httpRequest, url); LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); if (handle.isDead()) { LL_WARNS("testSiteIsAliveCoro") << "Dialog canceled before response." << LL_ENDL; return; } LLFloaterTOS *that = dynamic_cast(handle.get()); if (that) that->setSiteIsAlive(static_cast(status)); else { LL_WARNS("testSiteIsAliveCoro") << "Handle was not a TOS floater." << LL_ENDL; } }