llfloaterabout.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  1. /**
  2. * @file llfloaterabout.cpp
  3. * @author James Cook
  4. * @brief The about box from Help->About
  5. *
  6. * $LicenseInfo:firstyear=2001&license=viewergpl$
  7. *
  8. * Copyright (c) 2001-2009, Linden Research, Inc.
  9. * Copyright (c) 2009-2024, Henri Beauchamp.
  10. *
  11. * Second Life Viewer Source Code
  12. * The source code in this file ("Source Code") is provided by Linden Lab
  13. * to you under the terms of the GNU General Public License, version 2.0
  14. * ("GPL"), unless you have obtained a separate licensing agreement
  15. * ("Other License"), formally executed by you and Linden Lab. Terms of
  16. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18. *
  19. * There are special exceptions to the terms and conditions of the GPL as
  20. * it is applied to this Source Code. View the full text of the exception
  21. * in the file doc/FLOSS-exception.txt in this software distribution, or
  22. * online at
  23. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24. *
  25. * By copying, modifying or distributing this software, you acknowledge
  26. * that you have read and understood your obligations described above,
  27. * and agree to abide by those obligations.
  28. *
  29. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31. * COMPLETENESS OR PERFORMANCE.
  32. * $/LicenseInfo$
  33. */
  34. #include "llviewerprecompiledheaders.h"
  35. #include <sstream>
  36. #if LL_JEMALLOC
  37. # include "jemalloc/jemalloc.h"
  38. #elif LL_MIMALLOC
  39. # include "mimalloc/mimalloc.h" // For MI_MALLOC_VERSION
  40. #endif
  41. #include "llfloaterabout.h"
  42. #include "llaudioengine.h"
  43. #include "llcorehttputil.h"
  44. #include "llimagej2c.h"
  45. #include "llpluginprocessparent.h"
  46. #include "llsdserialize.h"
  47. #include "llsys.h"
  48. #include "lltexteditor.h"
  49. #include "lltrans.h"
  50. #include "lluictrlfactory.h"
  51. #include "lluri.h"
  52. #include "llversionviewer.h"
  53. #include "llwindow.h"
  54. #if LL_LINUX
  55. # include "llwindowsdl.h" // For gXlibThreadSafe and gXWayland
  56. #elif LL_WINDOWS
  57. # include "lldxhardware.h" // For gDXHardware
  58. #endif
  59. #include "llagent.h"
  60. #include "llappviewer.h"
  61. #include "llgridmanager.h"
  62. #include "llmediactrl.h"
  63. //MK
  64. #include "mkrlinterface.h"
  65. //mk
  66. #include "llviewercontrol.h"
  67. #include "llviewerregion.h"
  68. #include "llviewerstats.h"
  69. #include "llweb.h"
  70. #if LL_WINDOWS
  71. std::string gDriverVersionInfo;
  72. #endif
  73. LLFloaterAbout::LLFloaterAbout(const LLSD&)
  74. {
  75. LLUICtrlFactory::getInstance()->buildFloater(this, "floater_about.xml");
  76. mRegionChangedConnection =
  77. gAgent.addRegionChangedCB(boost::bind(&LLFloaterAbout::setSupportText,
  78. this));
  79. }
  80. //virtual
  81. LLFloaterAbout::~LLFloaterAbout()
  82. {
  83. mRegionChangedConnection.disconnect();
  84. }
  85. //virtual
  86. bool LLFloaterAbout::postBuild()
  87. {
  88. center();
  89. childSetAction("copy_button", onClickCopyToClipboard, this);
  90. childSetAction("close_button", onClickClose, this);
  91. mSupportTextEditor = getChild<LLTextEditor>("support");
  92. LLTextEditor* text = getChild<LLTextEditor>("credits");
  93. text->setCursorPos(0);
  94. text->setEnabled(false);
  95. text->setHandleEditKeysDirectly(true);
  96. text = getChild<LLTextEditor>("licenses");
  97. // Build-specific copyrights
  98. #if LL_LINUX
  99. text->replaceTextAll("elfio", getString("elfio"), false);
  100. text->replaceTextAll("fontconfig", getString("fontconfig"), false);
  101. text->replaceTextAll("libglib", getString("libglib"), false);
  102. text->replaceTextAll("libsdl", getString("libsdl"), false);
  103. #else
  104. text->replaceTextAll("elfio\n", "", false);
  105. text->replaceTextAll("fontconfig\n", "", false);
  106. text->replaceTextAll("libglib\n", "", false);
  107. text->replaceTextAll("libsdl\n", "", false);
  108. #endif
  109. #if LL_JEMALLOC
  110. text->replaceTextAll("jemalloc", getString("jemalloc"), false);
  111. #else
  112. text->replaceTextAll("jemalloc\n", "", false);
  113. #endif
  114. #if LL_MIMALLOC
  115. text->replaceTextAll("mimalloc", getString("mimalloc"), false);
  116. #else
  117. text->replaceTextAll("mimalloc\n", "", false);
  118. #endif
  119. #if LL_NGHTTP2
  120. text->replaceTextAll("nghttp2", getString("nghttp2"), false);
  121. #else
  122. text->replaceTextAll("nghttp2\n", "", false);
  123. #endif
  124. #if LL_FMOD
  125. text->replaceTextAll("fmod", getString("fmodstudio"), false);
  126. #else
  127. text->replaceTextAll("fmod\n", "", false);
  128. #endif
  129. #if LL_OPENAL
  130. text->replaceTextAll("openal", getString("openal"), false);
  131. #else
  132. text->replaceTextAll("openal\n", "", false);
  133. #endif
  134. #if LL_NO_PHMAP
  135. text->replaceTextAll("phmap\n", "", false);
  136. #else
  137. text->replaceTextAll("phmap", getString("phmap"), false);
  138. #endif
  139. #if SSE2NEON
  140. text->replaceTextAll("sse2neon", getString("sse2neon"), false);
  141. #else
  142. text->replaceTextAll("sse2neon\n", "", false);
  143. #endif
  144. #if TRACY_ENABLE
  145. text->replaceTextAll("tracy", getString("tracy"), false);
  146. #else
  147. text->replaceTextAll("tracy\n", "", false);
  148. #endif
  149. // Plugins specific copyrights, based on the actual presence of the
  150. // corresponding plugin in the viewer distribution.
  151. if (gHasGstreamer)
  152. {
  153. text->replaceTextAll("gstreamer", getString("gstreamer"), false);
  154. }
  155. else
  156. {
  157. text->replaceTextAll("gstreamer\n", "", false);
  158. }
  159. text->setCursorPos(0);
  160. text->setEnabled(false);
  161. text->setHandleEditKeysDirectly(true);
  162. LLMediaCtrl* browserp = getChild<LLMediaCtrl>("tos");
  163. if (browserp)
  164. {
  165. browserp->navigateToLocalPage("tpv", "policy.html");
  166. }
  167. LLViewerRegion* regionp = gAgent.getRegion();
  168. if (regionp)
  169. {
  170. const std::string& url = regionp->getCapability("ServerReleaseNotes");
  171. if (!url.empty())
  172. {
  173. if (url.find("/cap/") != std::string::npos)
  174. {
  175. // The URL is itself a capability URL: start fetching the
  176. // actual server release notes URL
  177. LL_DEBUGS("About") << "Fetching release notes URL from cap: "
  178. << url << LL_ENDL;
  179. mServerReleaseNotesUrl = LLTrans::getString("RetrievingData");
  180. startFetchServerReleaseNotes(url);
  181. }
  182. else
  183. {
  184. // On OpenSim grids, we could still get a direct URL
  185. LL_DEBUGS("About") << "Got release notes URL: " << url
  186. << LL_ENDL;
  187. mServerReleaseNotesUrl = url;
  188. }
  189. }
  190. }
  191. // Note: the media browser should load at least once as the About floater
  192. // is opened (thanks to the Usage policy tab), so the media browser version
  193. // will get refreshed at some point, which is checked in the draw() method.
  194. mLastBrowserVersion = LLPluginProcessParent::getMediaBrowserVersion();
  195. if (mLastBrowserVersion.empty()) // This should never happen...
  196. {
  197. mLastBrowserVersion = LLTrans::getString("LoadingData");
  198. }
  199. #if LL_WINDOWS
  200. if (gDriverVersionInfo.empty())
  201. {
  202. LLSD driver_info = gDXHardware.getDisplayInfo();
  203. if (driver_info.has("DriverVersion"))
  204. {
  205. gDriverVersionInfo = driver_info["DriverVersion"].asString();
  206. }
  207. }
  208. #endif
  209. setSupportText();
  210. return true;
  211. }
  212. //virtual
  213. void LLFloaterAbout::draw()
  214. {
  215. if (mLastBrowserVersion != LLPluginProcessParent::getMediaBrowserVersion())
  216. {
  217. mLastBrowserVersion = LLPluginProcessParent::getMediaBrowserVersion();
  218. setSupportText();
  219. }
  220. LLFloater::draw();
  221. }
  222. void LLFloaterAbout::updateServerReleaseNotesURL(const std::string& url)
  223. {
  224. mServerReleaseNotesUrl = url;
  225. setSupportText();
  226. }
  227. void LLFloaterAbout::setSupportText()
  228. {
  229. mSupportTextEditor->clear();
  230. mSupportTextEditor->setParseHTML(true);
  231. // Text styles for release notes hyperlinks
  232. LLStyleSP viewer_link_style(new LLStyle);
  233. viewer_link_style->setVisible(true);
  234. viewer_link_style->setFontName(LLStringUtil::null);
  235. viewer_link_style->setLinkHREF(getString("rel_notes"));
  236. viewer_link_style->setColor(gSavedSettings.getColor4("HTMLLinkColor"));
  237. // Version string
  238. std::string text = gSecondLife;
  239. #if LL_DEBUG || LL_NO_FORCE_INLINE
  240. text += " [DEVEL]";
  241. #endif
  242. text += llformat(" v%d.%d.%d.%d, %s %s", LL_VERSION_MAJOR,
  243. LL_VERSION_MINOR, LL_VERSION_BRANCH, LL_VERSION_RELEASE,
  244. __DATE__, __TIME__) + "\n";
  245. LLUIString ui_str;
  246. std::string channel = gSavedSettings.getString("VersionChannelName");
  247. if (channel != gSecondLife)
  248. {
  249. ui_str = getString("channel");
  250. ui_str.setArg("[CHANNEL]", channel);
  251. text.append(ui_str);
  252. text += '\n';
  253. }
  254. //MK
  255. if (gRLenabled)
  256. {
  257. text += gRLInterface.getVersion2() + "\n";
  258. }
  259. //mk
  260. const LLColor4& fg_color = LLUI::sTextFgReadOnlyColor;
  261. mSupportTextEditor->appendColoredText(text, false, false, fg_color);
  262. mSupportTextEditor->appendStyledText(getString("ReleaseNotes"), false,
  263. false, viewer_link_style);
  264. text = "\n\n";
  265. // Position
  266. LLViewerRegion* regionp = gAgent.getRegion();
  267. if (regionp)
  268. {
  269. LLStyleSP server_link_style(new LLStyle);
  270. if (mServerReleaseNotesUrl.find("http") == 0)
  271. {
  272. server_link_style->setVisible(true);
  273. server_link_style->setFontName(LLStringUtil::null);
  274. server_link_style->setLinkHREF(mServerReleaseNotesUrl);
  275. server_link_style->setColor(gSavedSettings.getColor4("HTMLLinkColor"));
  276. }
  277. ui_str = getString("you_are_at");
  278. //MK
  279. if (gRLenabled && gRLInterface.mContainsShowloc)
  280. {
  281. ui_str.setArg("[POSITION]",
  282. LLTrans::getString("position_hidden").c_str());
  283. ui_str.setArg("[REGION]",
  284. LLTrans::getString("region_hidden").c_str());
  285. }
  286. else
  287. //mk
  288. {
  289. const LLVector3d& pos = gAgent.getPositionGlobal();
  290. ui_str.setArg("[POSITION]",
  291. llformat("%.1f, %.1f, %.1f ",
  292. pos.mdV[VX], pos.mdV[VY], pos.mdV[VZ]));
  293. ui_str.setArg("[REGION]", regionp->getName().c_str());
  294. }
  295. text.append(ui_str);
  296. text += '\n';
  297. //MK
  298. if (gRLenabled && gRLInterface.mContainsShowloc)
  299. {
  300. text += getString("server_info_hiddden") + "\n";
  301. }
  302. else
  303. //mk
  304. {
  305. const LLHost& host = regionp->getHost();
  306. std::string hostname = regionp->getSimHostName();
  307. text += hostname + " (" + host.getIPandPort() + ")\n";
  308. if (hostname != host.getHostName())
  309. {
  310. text += "Alias: " + host.getHostName() + "\n";
  311. }
  312. text += gLastVersionChannel + "\n";
  313. }
  314. mSupportTextEditor->appendColoredText(text, false, false, fg_color);
  315. if (!mServerReleaseNotesUrl.empty())
  316. {
  317. if (mServerReleaseNotesUrl.find("http") == 0)
  318. {
  319. text = getString("ReleaseNotes") + "\n";
  320. mSupportTextEditor->appendStyledText(text, false, false,
  321. server_link_style);
  322. }
  323. else
  324. {
  325. text = getString("ReleaseNotes") + ": " +
  326. mServerReleaseNotesUrl + "\n";
  327. mSupportTextEditor->appendColoredText(text, false, false,
  328. fg_color);
  329. }
  330. }
  331. }
  332. else
  333. {
  334. mSupportTextEditor->appendColoredText(" \n", false, false, fg_color);
  335. }
  336. // *NOTE: Do not translate text like GPU, Graphics Card, etc; most PC users
  337. // that know what these mean will be used to the english versions and this
  338. // info sometimes gets sent to support.
  339. // CPU
  340. text = "CPU: ";
  341. text += LLCPUInfo::getInstance()->getCPUString(true) + "\n";
  342. // Moved hack adjustment to Windows memory size into llsys.cpp
  343. U32 memory = LLMemory::getPhysicalMemoryKB() / 1024;
  344. ui_str = getString("memory");
  345. ui_str.setArg("[AMOUNT]", llformat("%d", memory));
  346. text.append(ui_str);
  347. text += '\n';
  348. ui_str = getString("os_version");
  349. ui_str.setArg("[VERSION]", LLOSInfo::getInstance()->getOSString());
  350. text.append(ui_str);
  351. text += '\n';
  352. #if LL_JEMALLOC
  353. std::string manager;
  354. {
  355. std::string git;
  356. const char* version;
  357. size_t i = sizeof(version);
  358. mallctl("version", &version, &i, NULL, 0);
  359. manager.assign(version);
  360. i = manager.find("-g");
  361. if (i != std::string::npos)
  362. {
  363. git = "-" + manager.substr(i + 2);
  364. if (git.length() > 9)
  365. {
  366. git = git.substr(0, 9);
  367. }
  368. }
  369. i = manager.find('-');
  370. if (i != std::string::npos)
  371. {
  372. manager = manager.substr(0, i);
  373. }
  374. manager = "jemalloc v" + manager + git;
  375. }
  376. #elif LL_MIMALLOC
  377. std::string manager = llformat("mimalloc v%.2f",
  378. F32(MI_MALLOC_VERSION) / 100.f);
  379. #else
  380. std::string manager = getString("native_manager");
  381. #endif
  382. ui_str = getString("memory_manager");
  383. ui_str.setArg("[VERSION]", manager);
  384. text.append(ui_str);
  385. text += '\n';
  386. ui_str = getString("graphics_card");
  387. ui_str.setArg("[MODEL]", gGLManager.mGLRenderer);
  388. text.append(ui_str);
  389. text += '\n';
  390. #if LL_WINDOWS
  391. ui_str = getString("windows_graphics");
  392. if (gDriverVersionInfo.empty())
  393. {
  394. ui_str.setArg("[VERSION]", LLTrans::getString("LoadingData"));
  395. }
  396. else
  397. {
  398. ui_str.setArg("[VERSION]", gDriverVersionInfo);
  399. }
  400. text.append(ui_str);
  401. text += '\n';
  402. #endif
  403. ui_str = getString("opengl_version");
  404. ui_str.setArg("[VERSION]", gGLManager.mGLVersionString);
  405. text.append(ui_str);
  406. text += '\n';
  407. ui_str = getString("vram");
  408. ui_str.setArg("[AMOUNT]", llformat("%d", gGLManager.mVRAM));
  409. text.append(ui_str);
  410. text += '\n';
  411. #if LL_LINUX
  412. if (!gXlibThreadSafe)
  413. {
  414. ui_str = getString("xlib-not-threaded");
  415. text.append(ui_str);
  416. text += '\n';
  417. }
  418. if (gXWayland)
  419. {
  420. ui_str = getString("xwayland");
  421. text.append(ui_str);
  422. text += '\n';
  423. }
  424. #endif
  425. ui_str = getString("j2c_decoder");
  426. ui_str.setArg("[VERSION]", LLImageJ2C::getEngineInfo());
  427. text.append(ui_str);
  428. text += '\n';
  429. ui_str = getString("audio_driver");
  430. if (gAudiop)
  431. {
  432. ui_str.setArg("[VERSION]", gAudiop->getDriverName(true));
  433. }
  434. else
  435. {
  436. ui_str.setArg("[VERSION]", getString("none"));
  437. }
  438. text.append(ui_str);
  439. text += '\n';
  440. ui_str = getString("networking");
  441. ui_str.setArg("[VERSION]", LLCore::LLHttp::getCURLVersion());
  442. text.append(ui_str);
  443. text += '\n';
  444. ui_str = getString("browser");
  445. ui_str.setArg("[VERSION]", mLastBrowserVersion);
  446. text.append(ui_str);
  447. text += '\n';
  448. if (gPacketsIn > 0)
  449. {
  450. ui_str = getString("packets_loss");
  451. ui_str.setArg("[STATS]",
  452. llformat("%d/%d (%.1f%%)",
  453. (S32)gViewerStats.mPacketsLostStat.getCurrent(),
  454. gPacketsIn,
  455. 100.f *
  456. gViewerStats.mPacketsLostStat.getCurrent() /
  457. (F32)gPacketsIn));
  458. text.append(ui_str);
  459. text += '\n';
  460. }
  461. text += '\n';
  462. ui_str = getString("compiler");
  463. #if LL_MSVC
  464. ui_str.setArg("[COMPILER]", llformat("MSVC v%d", _MSC_VER));
  465. #elif LL_CLANG
  466. ui_str.setArg("[COMPILER]",
  467. llformat("Clang/LLVM v%d.%d.%d", __clang_major__,
  468. __clang_minor__, __clang_patchlevel__));
  469. #elif LL_GNUC
  470. ui_str.setArg("[COMPILER]",
  471. llformat("GCC v%d.%d.%d", __GNUC__, __GNUC_MINOR__,
  472. __GNUC_PATCHLEVEL__));
  473. #else
  474. ui_str.setArg("[COMPILER]", LLTrans::getString("unknown"));
  475. #endif
  476. text.append(ui_str);
  477. text += '\n';
  478. ui_str = getString("maths");
  479. LLStringUtil::format_map_t args;
  480. #if SSE2NEON
  481. ui_str.setArg("[MATHS]", "NEON");
  482. #elif defined(__AVX512IFMA__) || defined(__AVX512VBMI__) || \
  483. defined(__AVX512VBMI2__) || defined(__AVX512VL__) || \
  484. defined(__AVX512DQ__) || defined(__AVX512BW__) || \
  485. defined(__AVX512F__) || defined(__AVX512CD__)
  486. ui_str.setArg("[MATHS]", "AVX-512");
  487. #elif defined(__AVX2__)
  488. ui_str.setArg("[MATHS]", "AVX2");
  489. #elif defined(__AVX__)
  490. ui_str.setArg("[MATHS]", "AVX");
  491. #elif defined(__SSE4_1__)
  492. ui_str.setArg("[MATHS]", "SSE4.1");
  493. #elif defined(__SSSE3__)
  494. ui_str.setArg("[MATHS]", "SSSE3");
  495. #elif defined(__SSE3__)
  496. ui_str.setArg("[MATHS]", "SSE3");
  497. #elif defined(__SSE2__)
  498. ui_str.setArg("[MATHS]", "SSE2");
  499. #elif defined(__SSE__)
  500. ui_str.setArg("[MATHS]", "SSE");
  501. #else
  502. ui_str.setArg("[MATHS]", LLTrans::getString("unknown"));
  503. #endif
  504. text.append(ui_str);
  505. text += "\n\n";
  506. text += getString("compile_flags") + "\n";
  507. // *HACK: to get around unwanted macro expansions (due to compile flags
  508. // containing "errno" in their name) caused by the hack below:
  509. #ifdef errno
  510. # undef errno
  511. #endif
  512. // *HACK: for string quotation issues in macros:
  513. #define make_string2(x) #x
  514. #define make_string(s) make_string2(s)
  515. // The double parenthesis prevents issues in macro expansion when the
  516. // compile flags contain commas (such as with: -Wl,some-linker-option).
  517. #define FLAGS make_string((LL_COMPILE_FLAGS))
  518. std::string flags = FLAGS;
  519. // Remove the parenthesis enclosing the flags:
  520. LLStringUtil::replaceString(flags, "(", "");
  521. LLStringUtil::replaceString(flags, ")", "");
  522. // Remove the double, double-quotes enclosing the flags:
  523. LLStringUtil::replaceString(flags, "\"\"", "");
  524. // Remove the irrelevant (code-generation-wise) warning-related flags.
  525. size_t i;
  526. #if LL_WINDOWS
  527. // Note: clang may be used for Windows builds, so we must check for both
  528. // types of compiler command line formats...
  529. while ((i = flags.find("-W")) != std::string::npos ||
  530. (i = flags.find("/W")) != std::string::npos)
  531. #else
  532. while ((i = flags.find("-W")) != std::string::npos)
  533. #endif
  534. {
  535. size_t j = flags.find(' ', i);
  536. if (j > i)
  537. {
  538. flags = flags.erase(i, j - i);
  539. }
  540. }
  541. // Remove double-spaces introduced by above flags editing.
  542. LLStringUtil::replaceString(flags, " ", " ");
  543. text += flags + "\n";
  544. mSupportTextEditor->appendColoredText(text, false, true, fg_color);
  545. // Fix views
  546. mSupportTextEditor->setCursorPos(0);
  547. mSupportTextEditor->setEnabled(false);
  548. mSupportTextEditor->setHandleEditKeysDirectly(true);
  549. }
  550. //static
  551. void LLFloaterAbout::onClickCopyToClipboard(void* userdata)
  552. {
  553. LLFloaterAbout* self = (LLFloaterAbout*)userdata;
  554. if (self)
  555. {
  556. self->mSupportTextEditor->selectAll();
  557. self->mSupportTextEditor->copy();
  558. self->mSupportTextEditor->deselect();
  559. }
  560. }
  561. //static
  562. void LLFloaterAbout::onClickClose(void* userdata)
  563. {
  564. LLFloaterAbout* self = (LLFloaterAbout*)userdata;
  565. if (self)
  566. {
  567. self->close();
  568. }
  569. }
  570. // Try to build a hard-coded release note URL for the SL Wiki...
  571. //static
  572. std::string LLFloaterAbout::getHardCodedURL()
  573. {
  574. std::string url;
  575. if (gIsInSecondLifeProductionGrid)
  576. {
  577. // For the SL main grid, gLastVersionChannel should be in the form:
  578. // "Second Life Server YYYY-MM-DD.build". We extract "YYYY-MM-DD.build"
  579. // since it is the filename for the HTML release note file.
  580. size_t i = gLastVersionChannel.rfind(' ');
  581. if (i != std::string::npos)
  582. {
  583. LLStringUtil::format_map_t subs;
  584. subs["[SRVVER]"] = gLastVersionChannel.substr(i + 1);
  585. url = gSavedSettings.getString("AgniServerReleaseNotesURL");
  586. url = LLWeb::expandURLSubstitutions(url, subs);
  587. LL_DEBUGS("About") << "Using a hard-coded URL: " << url << LL_ENDL;
  588. }
  589. }
  590. return url;
  591. }
  592. //static
  593. void LLFloaterAbout::startFetchServerReleaseNotes(const std::string& cap_url)
  594. {
  595. // We cannot display the URL returned by the ServerReleaseNotes capability
  596. // because opening it in an external browser will trigger a warning about
  597. // untrusted SSL certificate.
  598. // So we query the URL ourselves, expecting to find an URL suitable for
  599. // external browsers in the "Location:" HTTP header.
  600. LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(cap_url,
  601. &LLFloaterAbout::handleServerReleaseNotes,
  602. &LLFloaterAbout::handleServerReleaseNotes);
  603. }
  604. //static
  605. void LLFloaterAbout::handleServerReleaseNotes(const LLSD& results)
  606. {
  607. LLFloaterAbout* self = findInstance();
  608. if (!self) return; // Floater has been closed...
  609. LLSD http_headers;
  610. if (results.has(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS))
  611. {
  612. const LLSD& http_results =
  613. results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
  614. http_headers =
  615. http_results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
  616. }
  617. else
  618. {
  619. http_headers =
  620. results[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
  621. }
  622. LL_DEBUGS("About") << "HTTP headers:\n";
  623. std::stringstream str;
  624. LLSDSerialize::toPrettyXML(http_headers, str);
  625. LL_CONT << str.str() << LL_ENDL;
  626. std::string url = http_headers[HTTP_IN_HEADER_LOCATION].asString();
  627. if (url.empty())
  628. {
  629. url = getHardCodedURL();
  630. }
  631. if (url.empty())
  632. {
  633. url = self->getString("ErrorFetchingServerReleaseNotesURL");
  634. }
  635. self->updateServerReleaseNotesURL(url);
  636. }