PageRenderTime 133ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/lllogininstance.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 918 lines | 645 code | 162 blank | 111 comment | 52 complexity | 6024b5a77d604a97ceb71915e83f0746 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lllogininstance.cpp
  3. * @brief Viewer's host for a login connection.
  4. *
  5. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "lllogininstance.h"
  28. // llcommon
  29. #include "llevents.h"
  30. #include "llmd5.h"
  31. #include "stringize.h"
  32. // llmessage (!)
  33. #include "llfiltersd2xmlrpc.h" // for xml_escape_string()
  34. // login
  35. #include "lllogin.h"
  36. // newview
  37. #include "llviewernetwork.h"
  38. #include "llviewercontrol.h"
  39. #include "llversioninfo.h"
  40. #include "llslurl.h"
  41. #include "llstartup.h"
  42. #include "llfloaterreg.h"
  43. #include "llnotifications.h"
  44. #include "llwindow.h"
  45. #include "llviewerwindow.h"
  46. #include "llprogressview.h"
  47. #if LL_LINUX || LL_SOLARIS
  48. #include "lltrans.h"
  49. #endif
  50. #include "llsecapi.h"
  51. #include "llstartup.h"
  52. #include "llmachineid.h"
  53. #include "llupdaterservice.h"
  54. #include "llevents.h"
  55. #include "llnotificationsutil.h"
  56. #include "llappviewer.h"
  57. #include <boost/scoped_ptr.hpp>
  58. #include <sstream>
  59. class LLLoginInstance::Disposable {
  60. public:
  61. virtual ~Disposable() {}
  62. };
  63. namespace {
  64. class MandatoryUpdateMachine:
  65. public LLLoginInstance::Disposable
  66. {
  67. public:
  68. MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService);
  69. void start(void);
  70. private:
  71. class State;
  72. class CheckingForUpdate;
  73. class Error;
  74. class ReadyToInstall;
  75. class StartingUpdaterService;
  76. class WaitingForDownload;
  77. LLLoginInstance & mLoginInstance;
  78. boost::scoped_ptr<State> mState;
  79. LLUpdaterService & mUpdaterService;
  80. void setCurrentState(State * newState);
  81. };
  82. class MandatoryUpdateMachine::State {
  83. public:
  84. virtual ~State() {}
  85. virtual void enter(void) {}
  86. virtual void exit(void) {}
  87. };
  88. class MandatoryUpdateMachine::CheckingForUpdate:
  89. public MandatoryUpdateMachine::State
  90. {
  91. public:
  92. CheckingForUpdate(MandatoryUpdateMachine & machine);
  93. virtual void enter(void);
  94. virtual void exit(void);
  95. private:
  96. LLTempBoundListener mConnection;
  97. MandatoryUpdateMachine & mMachine;
  98. LLProgressView * mProgressView;
  99. bool onEvent(LLSD const & event);
  100. };
  101. class MandatoryUpdateMachine::Error:
  102. public MandatoryUpdateMachine::State
  103. {
  104. public:
  105. Error(MandatoryUpdateMachine & machine);
  106. virtual void enter(void);
  107. virtual void exit(void);
  108. void onButtonClicked(const LLSD &, const LLSD &);
  109. private:
  110. MandatoryUpdateMachine & mMachine;
  111. };
  112. class MandatoryUpdateMachine::ReadyToInstall:
  113. public MandatoryUpdateMachine::State
  114. {
  115. public:
  116. ReadyToInstall(MandatoryUpdateMachine & machine);
  117. virtual void enter(void);
  118. virtual void exit(void);
  119. private:
  120. MandatoryUpdateMachine & mMachine;
  121. };
  122. class MandatoryUpdateMachine::StartingUpdaterService:
  123. public MandatoryUpdateMachine::State
  124. {
  125. public:
  126. StartingUpdaterService(MandatoryUpdateMachine & machine);
  127. virtual void enter(void);
  128. virtual void exit(void);
  129. void onButtonClicked(const LLSD & uiform, const LLSD & result);
  130. private:
  131. MandatoryUpdateMachine & mMachine;
  132. };
  133. class MandatoryUpdateMachine::WaitingForDownload:
  134. public MandatoryUpdateMachine::State
  135. {
  136. public:
  137. WaitingForDownload(MandatoryUpdateMachine & machine);
  138. virtual void enter(void);
  139. virtual void exit(void);
  140. private:
  141. LLTempBoundListener mConnection;
  142. MandatoryUpdateMachine & mMachine;
  143. LLProgressView * mProgressView;
  144. bool onEvent(LLSD const & event);
  145. };
  146. }
  147. static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback";
  148. static const char * const TOS_LISTENER_NAME = "lllogininstance_tos";
  149. std::string construct_start_string();
  150. // MandatoryUpdateMachine
  151. //-----------------------------------------------------------------------------
  152. MandatoryUpdateMachine::MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService):
  153. mLoginInstance(loginInstance),
  154. mUpdaterService(updaterService)
  155. {
  156. ; // No op.
  157. }
  158. void MandatoryUpdateMachine::start(void)
  159. {
  160. llinfos << "starting manditory update machine" << llendl;
  161. if(mUpdaterService.isChecking()) {
  162. switch(mUpdaterService.getState()) {
  163. case LLUpdaterService::UP_TO_DATE:
  164. mUpdaterService.stopChecking();
  165. mUpdaterService.startChecking();
  166. // Fall through.
  167. case LLUpdaterService::INITIAL:
  168. case LLUpdaterService::CHECKING_FOR_UPDATE:
  169. setCurrentState(new CheckingForUpdate(*this));
  170. break;
  171. case LLUpdaterService::TEMPORARY_ERROR:
  172. setCurrentState(new Error(*this));
  173. break;
  174. case LLUpdaterService::DOWNLOADING:
  175. setCurrentState(new WaitingForDownload(*this));
  176. break;
  177. case LLUpdaterService::TERMINAL:
  178. if(LLUpdaterService::updateReadyToInstall()) {
  179. setCurrentState(new ReadyToInstall(*this));
  180. } else {
  181. setCurrentState(new Error(*this));
  182. }
  183. break;
  184. case LLUpdaterService::FAILURE:
  185. setCurrentState(new Error(*this));
  186. break;
  187. default:
  188. llassert(!"unpossible case");
  189. break;
  190. }
  191. } else {
  192. setCurrentState(new StartingUpdaterService(*this));
  193. }
  194. }
  195. void MandatoryUpdateMachine::setCurrentState(State * newStatePointer)
  196. {
  197. {
  198. boost::scoped_ptr<State> newState(newStatePointer);
  199. if(mState != 0) mState->exit();
  200. mState.swap(newState);
  201. // Old state will be deleted on exit from this block before the new state
  202. // is entered.
  203. }
  204. if(mState != 0) mState->enter();
  205. }
  206. // MandatoryUpdateMachine::CheckingForUpdate
  207. //-----------------------------------------------------------------------------
  208. MandatoryUpdateMachine::CheckingForUpdate::CheckingForUpdate(MandatoryUpdateMachine & machine):
  209. mMachine(machine)
  210. {
  211. ; // No op.
  212. }
  213. void MandatoryUpdateMachine::CheckingForUpdate::enter(void)
  214. {
  215. llinfos << "entering checking for update" << llendl;
  216. mProgressView = gViewerWindow->getProgressView();
  217. mProgressView->setMessage("Looking for update...");
  218. mProgressView->setText("There is a required update for your Second Life installation.");
  219. mProgressView->setPercent(0);
  220. mProgressView->setVisible(true);
  221. mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).
  222. listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::CheckingForUpdate::onEvent, this, _1));
  223. }
  224. void MandatoryUpdateMachine::CheckingForUpdate::exit(void)
  225. {
  226. }
  227. bool MandatoryUpdateMachine::CheckingForUpdate::onEvent(LLSD const & event)
  228. {
  229. if(event["type"].asInteger() == LLUpdaterService::STATE_CHANGE) {
  230. switch(event["state"].asInteger()) {
  231. case LLUpdaterService::DOWNLOADING:
  232. mMachine.setCurrentState(new WaitingForDownload(mMachine));
  233. break;
  234. case LLUpdaterService::TEMPORARY_ERROR:
  235. case LLUpdaterService::UP_TO_DATE:
  236. case LLUpdaterService::TERMINAL:
  237. case LLUpdaterService::FAILURE:
  238. mProgressView->setVisible(false);
  239. mMachine.setCurrentState(new Error(mMachine));
  240. break;
  241. case LLUpdaterService::INSTALLING:
  242. llassert(!"can't possibly be installing");
  243. break;
  244. default:
  245. break;
  246. }
  247. } else {
  248. ; // Ignore.
  249. }
  250. return false;
  251. }
  252. // MandatoryUpdateMachine::Error
  253. //-----------------------------------------------------------------------------
  254. MandatoryUpdateMachine::Error::Error(MandatoryUpdateMachine & machine):
  255. mMachine(machine)
  256. {
  257. ; // No op.
  258. }
  259. void MandatoryUpdateMachine::Error::enter(void)
  260. {
  261. llinfos << "entering error" << llendl;
  262. LLNotificationsUtil::add("FailedRequiredUpdateInstall", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::Error::onButtonClicked, this, _1, _2));
  263. }
  264. void MandatoryUpdateMachine::Error::exit(void)
  265. {
  266. LLAppViewer::instance()->forceQuit();
  267. }
  268. void MandatoryUpdateMachine::Error::onButtonClicked(const LLSD &, const LLSD &)
  269. {
  270. mMachine.setCurrentState(0);
  271. }
  272. // MandatoryUpdateMachine::ReadyToInstall
  273. //-----------------------------------------------------------------------------
  274. MandatoryUpdateMachine::ReadyToInstall::ReadyToInstall(MandatoryUpdateMachine & machine):
  275. mMachine(machine)
  276. {
  277. ; // No op.
  278. }
  279. void MandatoryUpdateMachine::ReadyToInstall::enter(void)
  280. {
  281. llinfos << "entering ready to install" << llendl;
  282. // Open update ready dialog.
  283. }
  284. void MandatoryUpdateMachine::ReadyToInstall::exit(void)
  285. {
  286. // Restart viewer.
  287. }
  288. // MandatoryUpdateMachine::StartingUpdaterService
  289. //-----------------------------------------------------------------------------
  290. MandatoryUpdateMachine::StartingUpdaterService::StartingUpdaterService(MandatoryUpdateMachine & machine):
  291. mMachine(machine)
  292. {
  293. ; // No op.
  294. }
  295. void MandatoryUpdateMachine::StartingUpdaterService::enter(void)
  296. {
  297. llinfos << "entering start update service" << llendl;
  298. LLNotificationsUtil::add("UpdaterServiceNotRunning", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked, this, _1, _2));
  299. }
  300. void MandatoryUpdateMachine::StartingUpdaterService::exit(void)
  301. {
  302. ; // No op.
  303. }
  304. void MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked(const LLSD & uiform, const LLSD & result)
  305. {
  306. if(result["OK_okcancelbuttons"].asBoolean()) {
  307. mMachine.mUpdaterService.startChecking(false);
  308. mMachine.setCurrentState(new CheckingForUpdate(mMachine));
  309. } else {
  310. LLAppViewer::instance()->forceQuit();
  311. }
  312. }
  313. // MandatoryUpdateMachine::WaitingForDownload
  314. //-----------------------------------------------------------------------------
  315. MandatoryUpdateMachine::WaitingForDownload::WaitingForDownload(MandatoryUpdateMachine & machine):
  316. mMachine(machine),
  317. mProgressView(0)
  318. {
  319. ; // No op.
  320. }
  321. void MandatoryUpdateMachine::WaitingForDownload::enter(void)
  322. {
  323. llinfos << "entering waiting for download" << llendl;
  324. mProgressView = gViewerWindow->getProgressView();
  325. mProgressView->setMessage("Downloading update...");
  326. std::ostringstream stream;
  327. stream << "There is a required update for your Second Life installation." << std::endl <<
  328. "Version " << mMachine.mUpdaterService.updatedVersion();
  329. mProgressView->setText(stream.str());
  330. mProgressView->setPercent(0);
  331. mProgressView->setVisible(true);
  332. mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).
  333. listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::WaitingForDownload::onEvent, this, _1));
  334. }
  335. void MandatoryUpdateMachine::WaitingForDownload::exit(void)
  336. {
  337. mProgressView->setVisible(false);
  338. }
  339. bool MandatoryUpdateMachine::WaitingForDownload::onEvent(LLSD const & event)
  340. {
  341. switch(event["type"].asInteger()) {
  342. case LLUpdaterService::DOWNLOAD_COMPLETE:
  343. mMachine.setCurrentState(new ReadyToInstall(mMachine));
  344. break;
  345. case LLUpdaterService::DOWNLOAD_ERROR:
  346. mMachine.setCurrentState(new Error(mMachine));
  347. break;
  348. case LLUpdaterService::PROGRESS: {
  349. double downloadSize = event["download_size"].asReal();
  350. double bytesDownloaded = event["bytes_downloaded"].asReal();
  351. mProgressView->setPercent(100. * bytesDownloaded / downloadSize);
  352. break;
  353. }
  354. default:
  355. break;
  356. }
  357. return false;
  358. }
  359. // LLLoginInstance
  360. //-----------------------------------------------------------------------------
  361. LLLoginInstance::LLLoginInstance() :
  362. mLoginModule(new LLLogin()),
  363. mNotifications(NULL),
  364. mLoginState("offline"),
  365. mSkipOptionalUpdate(false),
  366. mAttemptComplete(false),
  367. mTransferRate(0.0f),
  368. mDispatcher("LLLoginInstance", "change"),
  369. mUpdaterService(0)
  370. {
  371. mLoginModule->getEventPump().listen("lllogininstance",
  372. boost::bind(&LLLoginInstance::handleLoginEvent, this, _1));
  373. // This internal use of LLEventDispatcher doesn't really need
  374. // per-function descriptions.
  375. mDispatcher.add("fail.login", "", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1));
  376. mDispatcher.add("connect", "", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1));
  377. mDispatcher.add("disconnect", "", boost::bind(&LLLoginInstance::handleDisconnect, this, _1));
  378. mDispatcher.add("indeterminate", "", boost::bind(&LLLoginInstance::handleIndeterminate, this, _1));
  379. }
  380. LLLoginInstance::~LLLoginInstance()
  381. {
  382. }
  383. void LLLoginInstance::connect(LLPointer<LLCredential> credentials)
  384. {
  385. std::vector<std::string> uris;
  386. LLGridManager::getInstance()->getLoginURIs(uris);
  387. connect(uris.front(), credentials);
  388. }
  389. void LLLoginInstance::connect(const std::string& uri, LLPointer<LLCredential> credentials)
  390. {
  391. mAttemptComplete = false; // Reset attempt complete at this point!
  392. constructAuthParams(credentials);
  393. mLoginModule->connect(uri, mRequestData);
  394. }
  395. void LLLoginInstance::reconnect()
  396. {
  397. // Sort of like connect, only using the pre-existing
  398. // request params.
  399. std::vector<std::string> uris;
  400. LLGridManager::getInstance()->getLoginURIs(uris);
  401. mLoginModule->connect(uris.front(), mRequestData);
  402. gViewerWindow->setShowProgress(true);
  403. }
  404. void LLLoginInstance::disconnect()
  405. {
  406. mAttemptComplete = false; // Reset attempt complete at this point!
  407. mRequestData.clear();
  408. mLoginModule->disconnect();
  409. }
  410. LLSD LLLoginInstance::getResponse()
  411. {
  412. return mResponseData;
  413. }
  414. void LLLoginInstance::constructAuthParams(LLPointer<LLCredential> user_credential)
  415. {
  416. // Set up auth request options.
  417. //#define LL_MINIMIAL_REQUESTED_OPTIONS
  418. LLSD requested_options;
  419. // *Note: this is where gUserAuth used to be created.
  420. requested_options.append("inventory-root");
  421. requested_options.append("inventory-skeleton");
  422. //requested_options.append("inventory-meat");
  423. //requested_options.append("inventory-skel-targets");
  424. #if (!defined LL_MINIMIAL_REQUESTED_OPTIONS)
  425. if(FALSE == gSavedSettings.getBOOL("NoInventoryLibrary"))
  426. {
  427. requested_options.append("inventory-lib-root");
  428. requested_options.append("inventory-lib-owner");
  429. requested_options.append("inventory-skel-lib");
  430. // requested_options.append("inventory-meat-lib");
  431. }
  432. requested_options.append("initial-outfit");
  433. requested_options.append("gestures");
  434. requested_options.append("display_names");
  435. requested_options.append("event_categories");
  436. requested_options.append("event_notifications");
  437. requested_options.append("classified_categories");
  438. requested_options.append("adult_compliant");
  439. //requested_options.append("inventory-targets");
  440. requested_options.append("buddy-list");
  441. requested_options.append("newuser-config");
  442. requested_options.append("ui-config");
  443. //send this info to login.cgi for stats gathering
  444. //since viewerstats isn't reliable enough
  445. requested_options.append("advanced-mode");
  446. #endif
  447. requested_options.append("max-agent-groups");
  448. requested_options.append("map-server-url");
  449. requested_options.append("voice-config");
  450. requested_options.append("tutorial_setting");
  451. requested_options.append("login-flags");
  452. requested_options.append("global-textures");
  453. if(gSavedSettings.getBOOL("ConnectAsGod"))
  454. {
  455. gSavedSettings.setBOOL("UseDebugMenus", TRUE);
  456. requested_options.append("god-connect");
  457. }
  458. // (re)initialize the request params with creds.
  459. LLSD request_params = user_credential->getLoginParams();
  460. char hashed_unique_id_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */
  461. LLMD5 hashed_unique_id;
  462. unsigned char unique_id[MAC_ADDRESS_BYTES];
  463. if(LLUUID::getNodeID(unique_id) == 0) {
  464. if(LLMachineID::getUniqueID(unique_id, sizeof(unique_id)) == 0) {
  465. llerrs << "Failed to get an id; cannot uniquely identify this machine." << llendl;
  466. }
  467. }
  468. hashed_unique_id.update(unique_id, MAC_ADDRESS_BYTES);
  469. hashed_unique_id.finalize();
  470. hashed_unique_id.hex_digest(hashed_unique_id_string);
  471. request_params["start"] = construct_start_string();
  472. request_params["skipoptional"] = mSkipOptionalUpdate;
  473. request_params["agree_to_tos"] = false; // Always false here. Set true in
  474. request_params["read_critical"] = false; // handleTOSResponse
  475. request_params["last_exec_event"] = mLastExecEvent;
  476. request_params["mac"] = hashed_unique_id_string;
  477. request_params["version"] = LLVersionInfo::getChannelAndVersion(); // Includes channel name
  478. request_params["channel"] = LLVersionInfo::getChannel();
  479. request_params["id0"] = mSerialNumber;
  480. request_params["host_id"] = gSavedSettings.getString("HostID");
  481. request_params["extended_errors"] = true; // request message_id and message_args
  482. mRequestData.clear();
  483. mRequestData["method"] = "login_to_simulator";
  484. mRequestData["params"] = request_params;
  485. mRequestData["options"] = requested_options;
  486. mRequestData["cfg_srv_timeout"] = gSavedSettings.getF32("LoginSRVTimeout");
  487. mRequestData["cfg_srv_pump"] = gSavedSettings.getString("LoginSRVPump");
  488. }
  489. bool LLLoginInstance::handleLoginEvent(const LLSD& event)
  490. {
  491. LL_DEBUGS("LLLogin") << "LoginListener called!: \n" << event << LL_ENDL;
  492. if(!(event.has("state") && event.has("change") && event.has("progress")))
  493. {
  494. llerrs << "Unknown message from LLLogin: " << event << llendl;
  495. }
  496. mLoginState = event["state"].asString();
  497. mResponseData = event["data"];
  498. if(event.has("transfer_rate"))
  499. {
  500. mTransferRate = event["transfer_rate"].asReal();
  501. }
  502. // Call the method registered in constructor, if any, for more specific
  503. // handling
  504. mDispatcher.try_call(event);
  505. return false;
  506. }
  507. void LLLoginInstance::handleLoginFailure(const LLSD& event)
  508. {
  509. // Login has failed.
  510. // Figure out why and respond...
  511. LLSD response = event["data"];
  512. std::string reason_response = response["reason"].asString();
  513. std::string message_response = response["message"].asString();
  514. // For the cases of critical message or TOS agreement,
  515. // start the TOS dialog. The dialog response will be handled
  516. // by the LLLoginInstance::handleTOSResponse() callback.
  517. // The callback intiates the login attempt next step, either
  518. // to reconnect or to end the attempt in failure.
  519. if(reason_response == "tos")
  520. {
  521. LLSD data(LLSD::emptyMap());
  522. data["message"] = message_response;
  523. data["reply_pump"] = TOS_REPLY_PUMP;
  524. gViewerWindow->setShowProgress(FALSE);
  525. LLFloaterReg::showInstance("message_tos", data);
  526. LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
  527. .listen(TOS_LISTENER_NAME,
  528. boost::bind(&LLLoginInstance::handleTOSResponse,
  529. this, _1, "agree_to_tos"));
  530. }
  531. else if(reason_response == "critical")
  532. {
  533. LLSD data(LLSD::emptyMap());
  534. data["message"] = message_response;
  535. data["reply_pump"] = TOS_REPLY_PUMP;
  536. if(response.has("error_code"))
  537. {
  538. data["error_code"] = response["error_code"];
  539. }
  540. if(response.has("certificate"))
  541. {
  542. data["certificate"] = response["certificate"];
  543. }
  544. gViewerWindow->setShowProgress(FALSE);
  545. LLFloaterReg::showInstance("message_critical", data);
  546. LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
  547. .listen(TOS_LISTENER_NAME,
  548. boost::bind(&LLLoginInstance::handleTOSResponse,
  549. this, _1, "read_critical"));
  550. }
  551. else if(reason_response == "update" || gSavedSettings.getBOOL("ForceMandatoryUpdate"))
  552. {
  553. gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
  554. updateApp(true, message_response);
  555. }
  556. else if(reason_response == "optional")
  557. {
  558. updateApp(false, message_response);
  559. }
  560. else
  561. {
  562. attemptComplete();
  563. }
  564. }
  565. void LLLoginInstance::handleLoginSuccess(const LLSD& event)
  566. {
  567. if(gSavedSettings.getBOOL("ForceMandatoryUpdate"))
  568. {
  569. LLSD response = event["data"];
  570. std::string message_response = response["message"].asString();
  571. // Testing update...
  572. gSavedSettings.setBOOL("ForceMandatoryUpdate", FALSE);
  573. // Don't confuse startup by leaving login "online".
  574. mLoginModule->disconnect();
  575. updateApp(true, message_response);
  576. }
  577. else
  578. {
  579. attemptComplete();
  580. }
  581. }
  582. void LLLoginInstance::handleDisconnect(const LLSD& event)
  583. {
  584. // placeholder
  585. }
  586. void LLLoginInstance::handleIndeterminate(const LLSD& event)
  587. {
  588. // The indeterminate response means that the server
  589. // gave the viewer a new url and params to try.
  590. // The login module handles the retry, but it gives us the
  591. // server response so that we may show
  592. // the user some status.
  593. LLSD message = event.get("data").get("message");
  594. if(message.isDefined())
  595. {
  596. LLSD progress_update;
  597. progress_update["desc"] = message;
  598. LLEventPumps::getInstance()->obtain("LLProgressView").post(progress_update);
  599. }
  600. }
  601. bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
  602. {
  603. if(accepted)
  604. {
  605. // Set the request data to true and retry login.
  606. mRequestData["params"][key] = true;
  607. reconnect();
  608. }
  609. else
  610. {
  611. attemptComplete();
  612. }
  613. LLEventPumps::instance().obtain(TOS_REPLY_PUMP).stopListening(TOS_LISTENER_NAME);
  614. return true;
  615. }
  616. void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)
  617. {
  618. if(mandatory)
  619. {
  620. gViewerWindow->setShowProgress(false);
  621. MandatoryUpdateMachine * machine = new MandatoryUpdateMachine(*this, *mUpdaterService);
  622. mUpdateStateMachine.reset(machine);
  623. machine->start();
  624. return;
  625. }
  626. // store off config state, as we might quit soon
  627. gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
  628. LLUIColorTable::instance().saveUserSettings();
  629. std::ostringstream message;
  630. std::string msg;
  631. if (!auth_msg.empty())
  632. {
  633. msg = "(" + auth_msg + ") \n";
  634. }
  635. LLSD args;
  636. args["MESSAGE"] = msg;
  637. LLSD payload;
  638. payload["mandatory"] = mandatory;
  639. /*
  640. We're constructing one of the following 9 strings here:
  641. "DownloadWindowsMandatory"
  642. "DownloadWindowsReleaseForDownload"
  643. "DownloadWindows"
  644. "DownloadMacMandatory"
  645. "DownloadMacReleaseForDownload"
  646. "DownloadMac"
  647. "DownloadLinuxMandatory"
  648. "DownloadLinuxReleaseForDownload"
  649. "DownloadLinux"
  650. I've called them out explicitly in this comment so that they can be grepped for.
  651. */
  652. std::string notification_name = "Download";
  653. #if LL_WINDOWS
  654. notification_name += "Windows";
  655. #elif LL_DARWIN
  656. notification_name += "Mac";
  657. #else
  658. notification_name += "Linux";
  659. #endif
  660. if (mandatory)
  661. {
  662. notification_name += "Mandatory";
  663. }
  664. else
  665. {
  666. #if LL_RELEASE_FOR_DOWNLOAD
  667. notification_name += "ReleaseForDownload";
  668. #endif
  669. }
  670. if(mNotifications)
  671. {
  672. mNotifications->add(notification_name, args, payload,
  673. boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2));
  674. gViewerWindow->setShowProgress(false);
  675. }
  676. }
  677. bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response)
  678. {
  679. S32 option = LLNotification::getSelectedOption(notification, response);
  680. std::string update_exe_path;
  681. bool mandatory = notification["payload"]["mandatory"].asBoolean();
  682. #if !LL_RELEASE_FOR_DOWNLOAD
  683. if (option == 2)
  684. {
  685. // This condition attempts to skip the
  686. // update if using a dev build.
  687. // The relog probably won't work if the
  688. // update is mandatory. :)
  689. // *REMOVE:Mani - Saving for reference...
  690. //LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
  691. mSkipOptionalUpdate = true;
  692. reconnect();
  693. return false;
  694. }
  695. #endif
  696. if (option == 1)
  697. {
  698. // ...user doesn't want to do it
  699. if (mandatory)
  700. {
  701. // Mandatory update, user chose to not to update...
  702. // The login attemp is complete, startup should
  703. // quit when detecting this.
  704. attemptComplete();
  705. // *REMOVE:Mani - Saving for reference...
  706. //LLAppViewer::instance()->forceQuit();
  707. // // Bump them back to the login screen.
  708. // //reset_login();
  709. }
  710. else
  711. {
  712. // Optional update, user chose to skip
  713. mSkipOptionalUpdate = true;
  714. reconnect();
  715. }
  716. return false;
  717. }
  718. if(mUpdaterLauncher)
  719. {
  720. mUpdaterLauncher();
  721. }
  722. attemptComplete();
  723. return false;
  724. }
  725. std::string construct_start_string()
  726. {
  727. std::string start;
  728. LLSLURL start_slurl = LLStartUp::getStartSLURL();
  729. switch(start_slurl.getType())
  730. {
  731. case LLSLURL::LOCATION:
  732. {
  733. // a startup URL was specified
  734. LLVector3 position = start_slurl.getPosition();
  735. std::string unescaped_start =
  736. STRINGIZE( "uri:"
  737. << start_slurl.getRegion() << "&"
  738. << position[VX] << "&"
  739. << position[VY] << "&"
  740. << position[VZ]);
  741. start = xml_escape_string(unescaped_start);
  742. break;
  743. }
  744. case LLSLURL::HOME_LOCATION:
  745. {
  746. start = "home";
  747. break;
  748. }
  749. default:
  750. {
  751. start = "last";
  752. }
  753. }
  754. return start;
  755. }