From cfb6ca569b2c834520ce50564e857dfc06831675 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 6 May 2021 00:46:14 +0300 Subject: SL-15168 Viewer side functionality for guidebook window opening --- indra/newview/llurlfloaterdispatchhandler.cpp | 107 ++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 indra/newview/llurlfloaterdispatchhandler.cpp (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp new file mode 100644 index 0000000000..7f9929041d --- /dev/null +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -0,0 +1,107 @@ +/** + * @file llurlfloaterdispatchhandler.cpp + * @brief Handles URLFloater generic message from server + * + * $LicenseInfo:firstyear=2021&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2021, 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 "llurlfloaterdispatchhandler.h" + +#include "llfloaterreg.h" +#include "llfloaterwebcontent.h" +#include "llsdserialize.h" +#include "llviewercontrol.h" +#include "llviewergenericmessage.h" +#include "llweb.h" + +// values specified by server side's dispatcher +const std::string MESSAGE_URL_FLOATER("URLFloater"); +const std::string KEY_ACTION("OpenURL"); +const std::string KEY_PARAMS("floater_params"); +const std::string KEY_FLOATER("floater_title"); +const std::string KEY_URL("floater_url"); + +LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler; + +LLUrlFloaterDispatchHandler::LLUrlFloaterDispatchHandler() +{ +} + +LLUrlFloaterDispatchHandler::~LLUrlFloaterDispatchHandler() +{ +} + +void LLUrlFloaterDispatchHandler::registerInDispatcher() +{ + if (!gGenericDispatcher.isHandlerPresent(MESSAGE_URL_FLOATER)) + { + gGenericDispatcher.addHandler(MESSAGE_URL_FLOATER, &sUrlDispatchhandler); + } +} + +//virtual +bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::string& key, const LLUUID& invoice, const sparam_t& strings) +{ + // invoice - transaction id + + LLSD message; + sparam_t::const_iterator it = strings.begin(); + + if (it != strings.end()) + { + const std::string& llsdRaw = *it++; + std::istringstream llsdData(llsdRaw); + if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length())) + { + LL_WARNS("URLFloater") << "Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; + } + } + + std::string floater = message[KEY_FLOATER]; + LLSD &command_params = message[KEY_PARAMS]; + + LLFloaterWebContent::Params params; + params.url = message[KEY_URL]; + + if (floater == "guidebook" || floater == "how_to") + { + if (command_params.isMap()) // by default is undefines + { + params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false; + } + LLFloaterReg::toggleInstanceOrBringToFront("how_to", params); + } + else if (!params.url.getValue().empty()) + { + if (command_params.isMap()) // by default is undefines + { + params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false; + params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"] : true; + params.allow_address_entry = command_params.has("allow_address_entry") ? command_params["allow_address_entry"] : true; + } + LLFloaterReg::showInstance("web_content", params); + } + + return true; +} -- cgit v1.2.3 From cb42bc2823931b84ce079423a471a332dc332b0c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 6 May 2021 21:57:46 +0300 Subject: SL-15168 Viewer side functionality for guidebook window opening #2 --- indra/newview/llurlfloaterdispatchhandler.cpp | 80 ++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 7 deletions(-) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index 7f9929041d..1a5da79a74 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -29,6 +29,7 @@ #include "llurlfloaterdispatchhandler.h" #include "llfloaterreg.h" +#include "llfloaterhowto.h" #include "llfloaterwebcontent.h" #include "llsdserialize.h" #include "llviewercontrol.h" @@ -36,11 +37,14 @@ #include "llweb.h" // values specified by server side's dispatcher +// for llopenfloater const std::string MESSAGE_URL_FLOATER("URLFloater"); -const std::string KEY_ACTION("OpenURL"); -const std::string KEY_PARAMS("floater_params"); +const std::string KEY_ACTION("action"); // "action" will be the string constant "OpenURL" +const std::string VALUE_OPEN_URL("OpenURL"); +const std::string KEY_DATA("action_data"); const std::string KEY_FLOATER("floater_title"); const std::string KEY_URL("floater_url"); +const std::string KEY_PARAMS("floater_params"); LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler; @@ -75,26 +79,75 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length())) { LL_WARNS("URLFloater") << "Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL; + return false; + } + } + + std::string floater; + LLSD command_params; + std::string url; + + if (message.has(KEY_ACTION) && message[KEY_ACTION].asString() == VALUE_OPEN_URL) + { + LLSD &action_data = message[KEY_DATA]; + if (action_data.isMap()) + { + floater = action_data[KEY_FLOATER]; + command_params = action_data[KEY_PARAMS]; + url = action_data[KEY_URL]; } } + else if (message.has(KEY_FLOATER)) + { + floater = message[KEY_FLOATER]; + command_params = message[KEY_PARAMS]; + url = message[KEY_URL]; + } + else + { + LL_WARNS("URLFloater") << "Received " << MESSAGE_URL_FLOATER << " with unexpected data format: " << message << LL_ENDL; + return false; + } - std::string floater = message[KEY_FLOATER]; - LLSD &command_params = message[KEY_PARAMS]; + if (url.find("://") == std::string::npos) + { + // try unescaping + url = LLURI::unescape(url); + } LLFloaterWebContent::Params params; - params.url = message[KEY_URL]; + params.url = url; if (floater == "guidebook" || floater == "how_to") { if (command_params.isMap()) // by default is undefines { params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false; + + // Script's side argument list can't include other lists, neither + // there is a LLRect type, so expect just width and height + if (command_params.has("width") && command_params.has("height")) + { + LLRect rect(0, command_params["height"].asInteger(), command_params["width"].asInteger(), 0); + params.preferred_media_size.setValue(rect); + } } + + // Some locations will have customized guidebook, which this function easists for + // only one instance of guidebook can exist at a time, so if this command arrives, + // we need to close previous guidebook then reopen it. + + LLFloater* instance = LLFloaterReg::findInstance("how_to"); + if (instance) + { + instance->closeHostedFloater(); + } + LLFloaterReg::toggleInstanceOrBringToFront("how_to", params); } - else if (!params.url.getValue().empty()) + else if (floater == "web_content") { - if (command_params.isMap()) // by default is undefines + if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params { params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false; params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"] : true; @@ -102,6 +155,19 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } LLFloaterReg::showInstance("web_content", params); } + else + { + if (LLFloaterReg::isRegistered(floater)) + { + // A valid floater + LL_INFOS("URLFloater") << "Floater " << floater << " is not supported by llopenfloater or URLFloater" << LL_ENDL; + } + else + { + // A valid message, but no such flaoter + LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater << LL_ENDL; + } + } return true; } -- cgit v1.2.3 From aac1fc4991338ef7c214e9b4e0dbc5d5bb554771 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 10 May 2021 21:15:12 +0300 Subject: SL-15168 Mac build fix --- indra/newview/llurlfloaterdispatchhandler.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index 1a5da79a74..65fbfe9fa3 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -92,16 +92,16 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st LLSD &action_data = message[KEY_DATA]; if (action_data.isMap()) { - floater = action_data[KEY_FLOATER]; + floater = action_data[KEY_FLOATER].asString(); command_params = action_data[KEY_PARAMS]; - url = action_data[KEY_URL]; + url = action_data[KEY_URL].asString(); } } else if (message.has(KEY_FLOATER)) { - floater = message[KEY_FLOATER]; + floater = message[KEY_FLOATER].asString(); command_params = message[KEY_PARAMS]; - url = message[KEY_URL]; + url = message[KEY_URL].asString(); } else { @@ -122,7 +122,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st { if (command_params.isMap()) // by default is undefines { - params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false; + params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"].asBoolean() : false; // Script's side argument list can't include other lists, neither // there is a LLRect type, so expect just width and height @@ -149,9 +149,9 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st { if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params { - params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"] : false; - params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"] : true; - params.allow_address_entry = command_params.has("allow_address_entry") ? command_params["allow_address_entry"] : true; + params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"].asBoolean() : false; + params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"].asBoolean() : true; + params.allow_address_entry = command_params.has("allow_address_entry") ? command_params["allow_address_entry"].asBoolean() : true; } LLFloaterReg::showInstance("web_content", params); } -- cgit v1.2.3 From 48394bdc23015c8289ef97fa1af99ba3e024ef36 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 11 May 2021 00:10:38 +0300 Subject: SL-15168 Reorginized contants --- indra/newview/llurlfloaterdispatchhandler.cpp | 40 +++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index 65fbfe9fa3..40afafa4c0 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -46,6 +46,24 @@ const std::string KEY_FLOATER("floater_title"); const std::string KEY_URL("floater_url"); const std::string KEY_PARAMS("floater_params"); +// Supported floaters +const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to +const std::string FLOATER_HOW_TO("how_to"); +const std::string FLOATER_WEB_CONTENT("web_content"); + +// Web content universal argument +const std::string KEY_TRUSTED_CONTENT("trusted_content"); + +// Guidebook specific arguments +const std::string KEY_WIDTH("width"); +const std::string KEY_HEGHT("height"); +const std::string KEY_CAN_CLOSE("can_close"); + +// web_content specific arguments +const std::string KEY_SHOW_PAGE_TITLE("show_page_title"); +const std::string KEY_ALLOW_ADRESS_ENTRY("allow_address_entry"); // It is not recomended to set this to true if trusted content is allowed + + LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler; LLUrlFloaterDispatchHandler::LLUrlFloaterDispatchHandler() @@ -118,17 +136,17 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st LLFloaterWebContent::Params params; params.url = url; - if (floater == "guidebook" || floater == "how_to") + if (floater == FLOATER_GUIDEBOOK || floater == FLOATER_HOW_TO) { if (command_params.isMap()) // by default is undefines { - params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"].asBoolean() : false; + params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; // Script's side argument list can't include other lists, neither // there is a LLRect type, so expect just width and height - if (command_params.has("width") && command_params.has("height")) + if (command_params.has(KEY_WIDTH) && command_params.has(KEY_HEGHT)) { - LLRect rect(0, command_params["height"].asInteger(), command_params["width"].asInteger(), 0); + LLRect rect(0, command_params[KEY_HEGHT].asInteger(), command_params[KEY_WIDTH].asInteger(), 0); params.preferred_media_size.setValue(rect); } } @@ -144,14 +162,20 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } LLFloaterReg::toggleInstanceOrBringToFront("how_to", params); + + if (command_params.isMap() && command_params.has(KEY_CAN_CLOSE)) + { + LLFloater* instance = LLFloaterReg::findInstance("how_to"); + instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean()); + } } - else if (floater == "web_content") + else if (floater == FLOATER_WEB_CONTENT) { if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params { - params.trusted_content = command_params.has("trusted_content") ? command_params["trusted_content"].asBoolean() : false; - params.show_page_title = command_params.has("show_page_title") ? command_params["show_page_title"].asBoolean() : true; - params.allow_address_entry = command_params.has("allow_address_entry") ? command_params["allow_address_entry"].asBoolean() : true; + params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; + params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true; + params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true; } LLFloaterReg::showInstance("web_content", params); } -- cgit v1.2.3 From 9dee16185a0b33177c6b7b3c60733682cebee66d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 11 May 2021 01:23:28 +0300 Subject: SL-15168 Changed format instead of an url function takes an uri --- indra/newview/llurlfloaterdispatchhandler.cpp | 97 ++++++++++++++++++--------- 1 file changed, 67 insertions(+), 30 deletions(-) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index 40afafa4c0..f03caf43b8 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -36,25 +36,30 @@ #include "llviewergenericmessage.h" #include "llweb.h" +#include + +// Example: +// llOpenFloater("My Help Title", "secondlife://guidebook", []); + // values specified by server side's dispatcher // for llopenfloater const std::string MESSAGE_URL_FLOATER("URLFloater"); const std::string KEY_ACTION("action"); // "action" will be the string constant "OpenURL" const std::string VALUE_OPEN_URL("OpenURL"); const std::string KEY_DATA("action_data"); -const std::string KEY_FLOATER("floater_title"); -const std::string KEY_URL("floater_url"); +const std::string KEY_FLOATER_TITLE("floater_title"); +const std::string KEY_URI("floater_url"); const std::string KEY_PARAMS("floater_params"); -// Supported floaters -const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to -const std::string FLOATER_HOW_TO("how_to"); -const std::string FLOATER_WEB_CONTENT("web_content"); +// Supported floaters, for now it's exact matching, later it might get extended +const std::string FLOATER_GUIDEBOOK("secondlife://guidebook"); // translates to "how_to" +const std::string FLOATER_WEB_CONTENT("secondlife://browser"); // translates to "web_content" -// Web content universal argument +// Web content universal arguments const std::string KEY_TRUSTED_CONTENT("trusted_content"); +const std::string KEY_URL("url"); -// Guidebook specific arguments +// Guidebook ("how_to") specific arguments const std::string KEY_WIDTH("width"); const std::string KEY_HEGHT("height"); const std::string KEY_CAN_CLOSE("can_close"); @@ -63,6 +68,10 @@ const std::string KEY_CAN_CLOSE("can_close"); const std::string KEY_SHOW_PAGE_TITLE("show_page_title"); const std::string KEY_ALLOW_ADRESS_ENTRY("allow_address_entry"); // It is not recomended to set this to true if trusted content is allowed +// expected format secondlife:///floater_alias +// intended to be extended to: secondlife:///floater_alias/instance_id +const boost::regex expression("secondlife:///[^ \n]{1,256}"); + LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler; @@ -101,25 +110,25 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } } - std::string floater; + std::string floater_title; LLSD command_params; - std::string url; + std::string floater_uri; if (message.has(KEY_ACTION) && message[KEY_ACTION].asString() == VALUE_OPEN_URL) { LLSD &action_data = message[KEY_DATA]; if (action_data.isMap()) { - floater = action_data[KEY_FLOATER].asString(); + floater_title = action_data[KEY_FLOATER_TITLE].asString(); command_params = action_data[KEY_PARAMS]; - url = action_data[KEY_URL].asString(); + floater_uri = action_data[KEY_URI].asString(); } } - else if (message.has(KEY_FLOATER)) + else if (message.has(KEY_FLOATER_TITLE)) { - floater = message[KEY_FLOATER].asString(); + floater_title = message[KEY_FLOATER_TITLE].asString(); command_params = message[KEY_PARAMS]; - url = message[KEY_URL].asString(); + floater_uri = message[KEY_URI].asString(); } else { @@ -127,16 +136,33 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st return false; } - if (url.find("://") == std::string::npos) + if (floater_uri.find(":///") == std::string::npos) { // try unescaping - url = LLURI::unescape(url); + floater_uri = LLURI::unescape(floater_uri); + } + + boost::cmatch what; + if (!boost::regex_match(floater_uri.c_str(), what, expression)) + { + LL_WARNS("URLFloater") << "Received " << MESSAGE_URL_FLOATER << " with invalid uri: " << floater_uri << LL_ENDL; + return false; } LLFloaterWebContent::Params params; - params.url = url; + if (command_params.isMap()) + { + if (command_params.has(KEY_TRUSTED_CONTENT)) + { + params.trusted_content = command_params[KEY_TRUSTED_CONTENT].asBoolean(); + } + if (command_params.has(KEY_URL)) + { + params.url = command_params[KEY_URL].asString(); + } + } - if (floater == FLOATER_GUIDEBOOK || floater == FLOATER_HOW_TO) + if (floater_uri == FLOATER_GUIDEBOOK) { if (command_params.isMap()) // by default is undefines { @@ -162,34 +188,45 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } LLFloaterReg::toggleInstanceOrBringToFront("how_to", params); - + + instance = LLFloaterReg::findInstance("how_to"); + instance->setTitle(floater_title); if (command_params.isMap() && command_params.has(KEY_CAN_CLOSE)) { - LLFloater* instance = LLFloaterReg::findInstance("how_to"); instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean()); } } - else if (floater == FLOATER_WEB_CONTENT) + else if (floater_uri == FLOATER_WEB_CONTENT) { - if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params + if (command_params.has(KEY_URL)) { - params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; - params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true; - params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true; + if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params + { + params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; + params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true; + params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true; + } + LLFloater* instance = LLFloaterReg::showInstance("web_content", params); + instance->setTitle(floater_title); } - LLFloaterReg::showInstance("web_content", params); } else { - if (LLFloaterReg::isRegistered(floater)) + LLSD path_array = LLURI(floater_uri).pathArray(); + S32 path_parts = path_array.size(); + if (path_parts == 0) + { + LL_INFOS("URLFloater") << "received an empty uri: " << floater_uri << LL_ENDL; + } + else if (LLFloaterReg::isRegistered(path_array[0])) { // A valid floater - LL_INFOS("URLFloater") << "Floater " << floater << " is not supported by llopenfloater or URLFloater" << LL_ENDL; + LL_INFOS("URLFloater") << "Floater " << path_array[0] << " is not supported by llopenfloater or URLFloater" << LL_ENDL; } else { // A valid message, but no such flaoter - LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater << LL_ENDL; + LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater_uri << LL_ENDL; } } -- cgit v1.2.3 From 2ddbdeb165efc0c41866f1fba084fb365474e63c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 11 May 2021 01:48:21 +0300 Subject: SL-15168 Reset title of guidebook when opening --- indra/newview/llurlfloaterdispatchhandler.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index f03caf43b8..519f81b72d 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -52,8 +52,8 @@ const std::string KEY_URI("floater_url"); const std::string KEY_PARAMS("floater_params"); // Supported floaters, for now it's exact matching, later it might get extended -const std::string FLOATER_GUIDEBOOK("secondlife://guidebook"); // translates to "how_to" -const std::string FLOATER_WEB_CONTENT("secondlife://browser"); // translates to "web_content" +const std::string FLOATER_GUIDEBOOK("secondlife:///guidebook"); // translates to "how_to" +const std::string FLOATER_WEB_CONTENT("secondlife:///browser"); // translates to "web_content" // Web content universal arguments const std::string KEY_TRUSTED_CONTENT("trusted_content"); -- cgit v1.2.3 From 80eb5ae1f21df34aa043d1aadd99abe042cfd3ba Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 11 May 2021 13:18:29 +0300 Subject: SL-15168 Improved uri recognition --- indra/newview/llurlfloaterdispatchhandler.cpp | 56 +++++++++++++++------------ 1 file changed, 31 insertions(+), 25 deletions(-) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index 519f81b72d..6de019d73c 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -52,8 +52,8 @@ const std::string KEY_URI("floater_url"); const std::string KEY_PARAMS("floater_params"); // Supported floaters, for now it's exact matching, later it might get extended -const std::string FLOATER_GUIDEBOOK("secondlife:///guidebook"); // translates to "how_to" -const std::string FLOATER_WEB_CONTENT("secondlife:///browser"); // translates to "web_content" +const std::string FLOATER_GUIDEBOOK("guidebook"); // translates to "how_to" +const std::string FLOATER_WEB_CONTENT("browser"); // translates to "web_content" // Web content universal arguments const std::string KEY_TRUSTED_CONTENT("trusted_content"); @@ -68,10 +68,6 @@ const std::string KEY_CAN_CLOSE("can_close"); const std::string KEY_SHOW_PAGE_TITLE("show_page_title"); const std::string KEY_ALLOW_ADRESS_ENTRY("allow_address_entry"); // It is not recomended to set this to true if trusted content is allowed -// expected format secondlife:///floater_alias -// intended to be extended to: secondlife:///floater_alias/instance_id -const boost::regex expression("secondlife:///[^ \n]{1,256}"); - LLUrlFloaterDispatchHandler LLUrlFloaterDispatchHandler::sUrlDispatchhandler; @@ -112,7 +108,8 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st std::string floater_title; LLSD command_params; - std::string floater_uri; + std::string raw_uri; + std::string floater_identifier; if (message.has(KEY_ACTION) && message[KEY_ACTION].asString() == VALUE_OPEN_URL) { @@ -121,14 +118,14 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st { floater_title = action_data[KEY_FLOATER_TITLE].asString(); command_params = action_data[KEY_PARAMS]; - floater_uri = action_data[KEY_URI].asString(); + raw_uri = action_data[KEY_URI].asString(); } } else if (message.has(KEY_FLOATER_TITLE)) { floater_title = message[KEY_FLOATER_TITLE].asString(); command_params = message[KEY_PARAMS]; - floater_uri = message[KEY_URI].asString(); + raw_uri = message[KEY_URI].asString(); } else { @@ -136,16 +133,31 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st return false; } - if (floater_uri.find(":///") == std::string::npos) + if (raw_uri.find(":///") == std::string::npos) { // try unescaping - floater_uri = LLURI::unescape(floater_uri); + raw_uri = LLURI::unescape(raw_uri); + } + + LLURI floater_uri(raw_uri); + if (floater_uri.scheme().empty() || floater_uri.scheme() != "secondlife") + { + LL_WARNS("URLFloater") << "Received " << raw_uri << " with unexpected scheme in uri: " << floater_uri << LL_ENDL; + return false; } - boost::cmatch what; - if (!boost::regex_match(floater_uri.c_str(), what, expression)) + LLSD path_array = floater_uri.pathArray(); + S32 path_parts = path_array.size(); + if (path_parts == 0) { - LL_WARNS("URLFloater") << "Received " << MESSAGE_URL_FLOATER << " with invalid uri: " << floater_uri << LL_ENDL; + LL_WARNS("URLFloater") << "received an empty uri: " << floater_uri << LL_ENDL; + return false; + } + + floater_identifier = path_array[0]; + if (floater_identifier.size() < 3) + { + LL_WARNS("URLFloater") << "received invalid flaoter indentifier: " << floater_identifier << LL_ENDL; return false; } @@ -162,7 +174,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } } - if (floater_uri == FLOATER_GUIDEBOOK) + if (floater_identifier == FLOATER_GUIDEBOOK) { if (command_params.isMap()) // by default is undefines { @@ -196,7 +208,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean()); } } - else if (floater_uri == FLOATER_WEB_CONTENT) + else if (floater_identifier == FLOATER_WEB_CONTENT) { if (command_params.has(KEY_URL)) { @@ -212,21 +224,15 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } else { - LLSD path_array = LLURI(floater_uri).pathArray(); - S32 path_parts = path_array.size(); - if (path_parts == 0) - { - LL_INFOS("URLFloater") << "received an empty uri: " << floater_uri << LL_ENDL; - } - else if (LLFloaterReg::isRegistered(path_array[0])) + if (LLFloaterReg::isRegistered(floater_identifier)) { // A valid floater - LL_INFOS("URLFloater") << "Floater " << path_array[0] << " is not supported by llopenfloater or URLFloater" << LL_ENDL; + LL_INFOS("URLFloater") << "Floater " << floater_identifier << " is not supported by llopenfloater or URLFloater" << LL_ENDL; } else { // A valid message, but no such flaoter - LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater_uri << LL_ENDL; + LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << raw_uri << LL_ENDL; } } -- cgit v1.2.3 From 8eede89c0f3edb7eb6289dc023c3b8e67ae33fd9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 11 May 2021 20:46:11 +0300 Subject: Revert "SL-15168 Changed format" --- indra/newview/llurlfloaterdispatchhandler.cpp | 103 ++++++++------------------ 1 file changed, 30 insertions(+), 73 deletions(-) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index 6de019d73c..40afafa4c0 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -36,30 +36,25 @@ #include "llviewergenericmessage.h" #include "llweb.h" -#include - -// Example: -// llOpenFloater("My Help Title", "secondlife://guidebook", []); - // values specified by server side's dispatcher // for llopenfloater const std::string MESSAGE_URL_FLOATER("URLFloater"); const std::string KEY_ACTION("action"); // "action" will be the string constant "OpenURL" const std::string VALUE_OPEN_URL("OpenURL"); const std::string KEY_DATA("action_data"); -const std::string KEY_FLOATER_TITLE("floater_title"); -const std::string KEY_URI("floater_url"); +const std::string KEY_FLOATER("floater_title"); +const std::string KEY_URL("floater_url"); const std::string KEY_PARAMS("floater_params"); -// Supported floaters, for now it's exact matching, later it might get extended -const std::string FLOATER_GUIDEBOOK("guidebook"); // translates to "how_to" -const std::string FLOATER_WEB_CONTENT("browser"); // translates to "web_content" +// Supported floaters +const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to +const std::string FLOATER_HOW_TO("how_to"); +const std::string FLOATER_WEB_CONTENT("web_content"); -// Web content universal arguments +// Web content universal argument const std::string KEY_TRUSTED_CONTENT("trusted_content"); -const std::string KEY_URL("url"); -// Guidebook ("how_to") specific arguments +// Guidebook specific arguments const std::string KEY_WIDTH("width"); const std::string KEY_HEGHT("height"); const std::string KEY_CAN_CLOSE("can_close"); @@ -106,26 +101,25 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } } - std::string floater_title; + std::string floater; LLSD command_params; - std::string raw_uri; - std::string floater_identifier; + std::string url; if (message.has(KEY_ACTION) && message[KEY_ACTION].asString() == VALUE_OPEN_URL) { LLSD &action_data = message[KEY_DATA]; if (action_data.isMap()) { - floater_title = action_data[KEY_FLOATER_TITLE].asString(); + floater = action_data[KEY_FLOATER].asString(); command_params = action_data[KEY_PARAMS]; - raw_uri = action_data[KEY_URI].asString(); + url = action_data[KEY_URL].asString(); } } - else if (message.has(KEY_FLOATER_TITLE)) + else if (message.has(KEY_FLOATER)) { - floater_title = message[KEY_FLOATER_TITLE].asString(); + floater = message[KEY_FLOATER].asString(); command_params = message[KEY_PARAMS]; - raw_uri = message[KEY_URI].asString(); + url = message[KEY_URL].asString(); } else { @@ -133,48 +127,16 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st return false; } - if (raw_uri.find(":///") == std::string::npos) + if (url.find("://") == std::string::npos) { // try unescaping - raw_uri = LLURI::unescape(raw_uri); - } - - LLURI floater_uri(raw_uri); - if (floater_uri.scheme().empty() || floater_uri.scheme() != "secondlife") - { - LL_WARNS("URLFloater") << "Received " << raw_uri << " with unexpected scheme in uri: " << floater_uri << LL_ENDL; - return false; - } - - LLSD path_array = floater_uri.pathArray(); - S32 path_parts = path_array.size(); - if (path_parts == 0) - { - LL_WARNS("URLFloater") << "received an empty uri: " << floater_uri << LL_ENDL; - return false; - } - - floater_identifier = path_array[0]; - if (floater_identifier.size() < 3) - { - LL_WARNS("URLFloater") << "received invalid flaoter indentifier: " << floater_identifier << LL_ENDL; - return false; + url = LLURI::unescape(url); } LLFloaterWebContent::Params params; - if (command_params.isMap()) - { - if (command_params.has(KEY_TRUSTED_CONTENT)) - { - params.trusted_content = command_params[KEY_TRUSTED_CONTENT].asBoolean(); - } - if (command_params.has(KEY_URL)) - { - params.url = command_params[KEY_URL].asString(); - } - } + params.url = url; - if (floater_identifier == FLOATER_GUIDEBOOK) + if (floater == FLOATER_GUIDEBOOK || floater == FLOATER_HOW_TO) { if (command_params.isMap()) // by default is undefines { @@ -200,39 +162,34 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } LLFloaterReg::toggleInstanceOrBringToFront("how_to", params); - - instance = LLFloaterReg::findInstance("how_to"); - instance->setTitle(floater_title); + if (command_params.isMap() && command_params.has(KEY_CAN_CLOSE)) { + LLFloater* instance = LLFloaterReg::findInstance("how_to"); instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean()); } } - else if (floater_identifier == FLOATER_WEB_CONTENT) + else if (floater == FLOATER_WEB_CONTENT) { - if (command_params.has(KEY_URL)) + if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params { - if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params - { - params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; - params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true; - params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true; - } - LLFloater* instance = LLFloaterReg::showInstance("web_content", params); - instance->setTitle(floater_title); + params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; + params.show_page_title = command_params.has(KEY_SHOW_PAGE_TITLE) ? command_params[KEY_SHOW_PAGE_TITLE].asBoolean() : true; + params.allow_address_entry = command_params.has(KEY_ALLOW_ADRESS_ENTRY) ? command_params[KEY_ALLOW_ADRESS_ENTRY].asBoolean() : true; } + LLFloaterReg::showInstance("web_content", params); } else { - if (LLFloaterReg::isRegistered(floater_identifier)) + if (LLFloaterReg::isRegistered(floater)) { // A valid floater - LL_INFOS("URLFloater") << "Floater " << floater_identifier << " is not supported by llopenfloater or URLFloater" << LL_ENDL; + LL_INFOS("URLFloater") << "Floater " << floater << " is not supported by llopenfloater or URLFloater" << LL_ENDL; } else { // A valid message, but no such flaoter - LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << raw_uri << LL_ENDL; + LL_WARNS("URLFloater") << "Recieved a command to open unknown floater: " << floater << LL_ENDL; } } -- cgit v1.2.3 From 87f1d6071ee480c5dfcf15f6da3f9a9b9766d723 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 11 May 2021 20:55:12 +0300 Subject: SL-15168 Added 'Title' argument --- indra/newview/llurlfloaterdispatchhandler.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index 40afafa4c0..ec2e423c64 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -36,13 +36,16 @@ #include "llviewergenericmessage.h" #include "llweb.h" +// Example: +// llOpenFloater("guidebook", "http://page.com", []); + // values specified by server side's dispatcher // for llopenfloater const std::string MESSAGE_URL_FLOATER("URLFloater"); const std::string KEY_ACTION("action"); // "action" will be the string constant "OpenURL" const std::string VALUE_OPEN_URL("OpenURL"); const std::string KEY_DATA("action_data"); -const std::string KEY_FLOATER("floater_title"); +const std::string KEY_FLOATER("floater_title"); // name of the floater, not title const std::string KEY_URL("floater_url"); const std::string KEY_PARAMS("floater_params"); @@ -58,6 +61,7 @@ const std::string KEY_TRUSTED_CONTENT("trusted_content"); const std::string KEY_WIDTH("width"); const std::string KEY_HEGHT("height"); const std::string KEY_CAN_CLOSE("can_close"); +const std::string KEY_TITLE("title"); // web_content specific arguments const std::string KEY_SHOW_PAGE_TITLE("show_page_title"); @@ -163,10 +167,17 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st LLFloaterReg::toggleInstanceOrBringToFront("how_to", params); - if (command_params.isMap() && command_params.has(KEY_CAN_CLOSE)) + if (command_params.isMap()) { LLFloater* instance = LLFloaterReg::findInstance("how_to"); - instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean()); + if (command_params.has(KEY_CAN_CLOSE)) + { + instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean()); + } + if (command_params.has(KEY_TITLE)) + { + instance->setTitle(command_params[KEY_TITLE].asString()); + } } } else if (floater == FLOATER_WEB_CONTENT) -- cgit v1.2.3 From 3917de54db0dacf2aaa4f8af083db632c6a51365 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 12 May 2021 14:25:46 +0300 Subject: SL-15245 Multiple guide books open, but cannot close them all Opening and closing single-instance floaters rapidly and multiple times could result in cleaning instance from floaterreg twice, thus removing new isntance instead of current one --- indra/newview/llurlfloaterdispatchhandler.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index ec2e423c64..0343485864 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -54,6 +54,7 @@ const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to const std::string FLOATER_HOW_TO("how_to"); const std::string FLOATER_WEB_CONTENT("web_content"); +// All arguments are palceholders! Server side will need to add validation first. // Web content universal argument const std::string KEY_TRUSTED_CONTENT("trusted_content"); @@ -105,6 +106,8 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } } + // At the moment command_params is a placeholder and code treats it as map + // Once server side adds argument validation this will be either a map or an array std::string floater; LLSD command_params; std::string url; -- cgit v1.2.3 From 5b730160f662d0324ba01f498744a279d002a910 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 8 Jun 2021 00:49:14 +0300 Subject: SL-15168 A bit of debug logging --- indra/newview/llurlfloaterdispatchhandler.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index 0343485864..2e595390cc 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -145,6 +145,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st if (floater == FLOATER_GUIDEBOOK || floater == FLOATER_HOW_TO) { + LL_DEBUGS("URLFloater") << "Opening how_to floater with parameters: " << message << LL_ENDL; if (command_params.isMap()) // by default is undefines { params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; @@ -185,6 +186,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } else if (floater == FLOATER_WEB_CONTENT) { + LL_DEBUGS("URLFloater") << "Opening web_content floater with parameters: " << message << LL_ENDL; if (command_params.isMap()) // by default is undefines, might be better idea to init params from command_params { params.trusted_content = command_params.has(KEY_TRUSTED_CONTENT) ? command_params[KEY_TRUSTED_CONTENT].asBoolean() : false; @@ -195,6 +197,7 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st } else { + LL_DEBUGS("URLFloater") << "Unknow floater with parameters: " << message << LL_ENDL; if (LLFloaterReg::isRegistered(floater)) { // A valid floater -- cgit v1.2.3 From 79f8c024c34efad93ce55ebacf656e6fc9804198 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 9 Jun 2021 19:46:23 +0300 Subject: SL-15363 how_to on older viewers is forced to persist Older how_to floater is not set to persist in between sessions and gets stuck, ranamed new how_to into guidebook to avoid the issue --- indra/newview/llurlfloaterdispatchhandler.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/llurlfloaterdispatchhandler.cpp') diff --git a/indra/newview/llurlfloaterdispatchhandler.cpp b/indra/newview/llurlfloaterdispatchhandler.cpp index 2e595390cc..6b1a373beb 100644 --- a/indra/newview/llurlfloaterdispatchhandler.cpp +++ b/indra/newview/llurlfloaterdispatchhandler.cpp @@ -50,8 +50,8 @@ const std::string KEY_URL("floater_url"); const std::string KEY_PARAMS("floater_params"); // Supported floaters -const std::string FLOATER_GUIDEBOOK("guidebook"); // alias for how_to -const std::string FLOATER_HOW_TO("how_to"); +const std::string FLOATER_GUIDEBOOK("guidebook"); +const std::string FLOATER_HOW_TO("how_to"); // alias for guidebook const std::string FLOATER_WEB_CONTENT("web_content"); // All arguments are palceholders! Server side will need to add validation first. @@ -163,17 +163,17 @@ bool LLUrlFloaterDispatchHandler::operator()(const LLDispatcher *, const std::st // only one instance of guidebook can exist at a time, so if this command arrives, // we need to close previous guidebook then reopen it. - LLFloater* instance = LLFloaterReg::findInstance("how_to"); + LLFloater* instance = LLFloaterReg::findInstance("guidebook"); if (instance) { instance->closeHostedFloater(); } - LLFloaterReg::toggleInstanceOrBringToFront("how_to", params); + LLFloaterReg::toggleInstanceOrBringToFront("guidebook", params); if (command_params.isMap()) { - LLFloater* instance = LLFloaterReg::findInstance("how_to"); + LLFloater* instance = LLFloaterReg::findInstance("guidebook"); if (command_params.has(KEY_CAN_CLOSE)) { instance->setCanClose(command_params[KEY_CAN_CLOSE].asBoolean()); -- cgit v1.2.3