summaryrefslogtreecommitdiff
path: root/indra/newview/llscripteditorws.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llscripteditorws.cpp')
-rw-r--r--indra/newview/llscripteditorws.cpp99
1 files changed, 60 insertions, 39 deletions
diff --git a/indra/newview/llscripteditorws.cpp b/indra/newview/llscripteditorws.cpp
index 017d9a5540..178b03d4da 100644
--- a/indra/newview/llscripteditorws.cpp
+++ b/indra/newview/llscripteditorws.cpp
@@ -69,6 +69,7 @@
#include "llviewertexteditor.h"
#include "llvoinventorylistener.h"
#include "roles_constants.h"
+#include "workqueue.h"
#include <array>
@@ -627,27 +628,27 @@ void LLScriptEditorWSServer::setupConnectionMethods(LLJSONRPCConnection::ptr_t c
LL_DEBUGS("ScriptEditorWS") << "Setting up script editor connection methods" << LL_ENDL;
U32 connection_id = script_connection->getConnectionID();
- // Sync methods (run on the WebSocket I/O thread; must not touch
- // main-thread-only viewer state).
- script_connection->registerMethod("language.syntax.id",
+ // All per-connection methods dispatch to the main thread inside a
+ // coroutine (see LLJSONRPCConnection::processRequest).
+ script_connection->registerAsyncMethod("language.syntax.id",
bindHandler([](LLScriptEditorWSServer& s, auto&, auto&, auto&)
{
return s.handleLanguageIdRequest();
}));
- script_connection->registerMethod("language.syntax",
+ script_connection->registerAsyncMethod("language.syntax",
bindHandler([](LLScriptEditorWSServer& s, auto&, auto&, const LLSD& params)
{
return s.handleSyntaxRequest(params);
}));
- script_connection->registerMethod("language.syntax.cache",
+ script_connection->registerAsyncMethod("language.syntax.cache",
bindHandler([](LLScriptEditorWSServer& s, auto&, auto&, auto&)
{
return s.handleSyntaxCacheRequest();
}));
- script_connection->registerMethod("language.syntax.get",
+ script_connection->registerAsyncMethod("language.syntax.get",
bindHandler([](LLScriptEditorWSServer& s, auto&, auto&, const LLSD& params)
{
return s.handleSyntaxCacheFileRequest(params);
@@ -659,7 +660,7 @@ void LLScriptEditorWSServer::setupConnectionMethods(LLJSONRPCConnection::ptr_t c
return s.handleScriptSubscribe(connection_id, params);
}));
- script_connection->registerMethod("script.list",
+ script_connection->registerAsyncMethod("script.list",
bindHandler([](LLScriptEditorWSServer& s, auto&, auto&, auto&)
{
return s.handleFileWatcherFileListRequest();
@@ -671,7 +672,6 @@ void LLScriptEditorWSServer::setupConnectionMethods(LLJSONRPCConnection::ptr_t c
return s.handleObjectUnpublish(connection_id, params);
}));
- // Async methods (dispatched to the main thread inside a coroutine).
script_connection->registerAsyncMethod("script.unsubscribe",
bindHandler([connection_id](LLScriptEditorWSServer& s, auto&, auto&, const LLSD& params)
{
@@ -2299,7 +2299,6 @@ void LLScriptEditorWSServer::forwardChatToIDE(
void LLScriptEditorWSServer::sendRuntimeEvent(
const LLPublishedObjectMgr::RuntimeChatEvent& event) const
{
-
std::string script_id;
if (event.mItemID.notNull())
{
@@ -2395,7 +2394,7 @@ void LLScriptEditorWSServer::notifyAll(const std::string& method, const LLSD& pa
// static
-std::string LLScriptEditorWSServer::getPrimName(LLViewerObject* obj)
+std::string LLScriptEditorWSServer::getPrimName(LLViewerObject* obj, S32 link_number)
{
std::string name = nv_string(obj, "Name");
if (!name.empty())
@@ -2414,8 +2413,8 @@ std::string LLScriptEditorWSServer::getPrimName(LLViewerObject* obj)
return node->mName;
}
- // Never emit an empty prim/object name to downstream tooling.
- return obj->getID().asString();
+ // Real prim names need a full ObjectProperties reply, which requires selection.
+ return (link_number > 1) ? llformat("Link #%d", link_number) : std::string("Object");
}
bool LLScriptEditorWSServer::publishObject(const LLUUID& object_id)
@@ -2443,12 +2442,8 @@ bool LLScriptEditorWSServer::publishObject(const LLUUID& object_id)
// Collect root + all children
std::vector<LLViewerObject*> prims = collect_linkset(root);
- // Request object properties for each prim in the linkset (root + children),
- // matching the hover path so name/description metadata is refreshed.
- for (LLViewerObject* prim : prims)
- {
- LLSelectMgr::instance().requestObjectPropertiesFamily(prim);
- }
+ // The sim coalesces properties-family requests to the root, so one request covers the linkset.
+ LLSelectMgr::instance().requestObjectPropertiesFamily(root);
// Set up a PendingPublish to coordinate inventory loading across all prims.
// We register a listener and call requestInventory() on every prim.
@@ -2513,24 +2508,14 @@ void LLScriptEditorWSServer::buildAndSendPublish(const LLUUID& object_id)
info.mOwnerID = root->mOwnerID;
info.mObjectName = pub["object_name"].asString();
info.mObjectDescription = pub["object_description"].asString();
+ info.mPermissions = LLPublishedObjectMgr::getObjectPermissionsLLSD(root);
if (root->getRegion())
{
info.mRegionName = root->getRegion()->getName();
}
- LLSelectNode* root_select_node = LLSelectMgr::instance().getSelection()->findNode(root);
- if (root_select_node
- && root_select_node->mValid
- && !root_select_node->mFromTaskID.isNull()
- && !root->isAttachment())
- {
- info.mCanSaveBackToContents = true;
- info.mSourceTaskID = root_select_node->mFromTaskID;
- }
- else
- {
- info.mCanSaveBackToContents = false;
- info.mSourceTaskID.setNull();
- }
+ LLUUID source_task_id;
+ info.mCanSaveBackToContents = LLPublishedObjectMgr::computeCanSaveBack(root, source_task_id);
+ info.mSourceTaskID = source_task_id;
S32 link_num = 1;
std::vector<LLViewerObject*> prims = collect_linkset(root);
@@ -2538,9 +2523,10 @@ void LLScriptEditorWSServer::buildAndSendPublish(const LLUUID& object_id)
{
LLPublishedObjectMgr::PublishedPrimInfo prim_info;
prim_info.mPrimID = prim->getID();
- prim_info.mPrimName = getPrimName(prim); // Use helper with selection fallback
prim_info.mLinkNumber = link_num++;
+ prim_info.mPrimName = getPrimName(prim, prim_info.mLinkNumber);
prim_info.mInventorySerial = static_cast<S16>(prim->getInventorySerial());
+ prim_info.mPermissions = LLPublishedObjectMgr::getObjectPermissionsLLSD(prim);
info.mPrims.push_back(prim_info);
}
@@ -2581,12 +2567,9 @@ void LLScriptEditorWSServer::buildAndSendPublish(const LLUUID& object_id)
<< " (" << pub["object_name"].asString() << ") with "
<< (prims.size() - 1) << " linked prim(s)" << LL_ENDL;
- // Re-request object properties now that the object is published so
- // onObjectPropertyChanged can emit object.update for root and linked prims.
- for (LLViewerObject* prim : prims)
- {
- LLSelectMgr::instance().requestObjectPropertiesFamily(prim);
- }
+ // Re-request now that the object is published so onObjectPropertyChanged can emit
+ // object.update. The sim answers per linkset, so only the root needs asking.
+ LLSelectMgr::instance().requestObjectPropertiesFamily(root);
}
void LLScriptEditorWSServer::onLinksetChildAdded(const LLUUID& root_id, LLViewerObject* child)
@@ -2748,6 +2731,24 @@ void LLScriptEditorWSServer::onObjectPropertyChanged(
}
}
+void LLScriptEditorWSServer::onObjectPermissionsReceived(
+ const LLUUID& prim_id, const LLUUID& owner_id, U32 owner_mask, U32 next_owner_mask)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SCRIPTDEV;
+ LLViewerObject* prim = gObjectList.findObject(prim_id);
+ if (!prim)
+ {
+ return;
+ }
+
+ LLSD update;
+ if (mPublishedObjectManager.applyPermissionsChange(
+ prim->getRootEdit()->getID(), prim_id, owner_id, owner_mask, next_owner_mask, update))
+ {
+ notifyAll("object.update", update);
+ }
+}
+
void LLScriptEditorWSServer::unpublishObject(const LLUUID& object_id, const std::string& reason)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_SCRIPTDEV;
@@ -2785,6 +2786,26 @@ void LLScriptEditorWSConnection::onOpen()
LL_INFOS("ScriptEditorWS") << "Script editor JSON-RPC connection opened" << LL_ENDL;
+ // gAgent, LLVersionInfo, LLSyntaxDefCache, and challenge file I/O below
+ // are main-thread only; this callback runs on the WS I/O thread.
+ wptr_t that = weak_from_this();
+ if (!LL::WorkQueue::postToMainLoop([that]()
+ {
+ auto self = that.lock();
+ if (self)
+ {
+ self->sendHandshake();
+ }
+ }))
+ {
+ LL_WARNS("ScriptEditorWS") << "Main loop unavailable; dropping handshake for new connection" << LL_ENDL;
+ }
+}
+
+void LLScriptEditorWSConnection::sendHandshake()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_SCRIPTDEV;
+
// Build hello data
LLSD handshake;
handshake["server_version"] = "1.0.0";