PageRenderTime 14ms CodeModel.GetById 2ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llfloaterregiondebugconsole.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 224 lines | 142 code | 24 blank | 58 comment | 6 complexity | 3d4123444144a9cc5577533e6c0f33c8 MD5 | raw file
  1/** 
  2 * @file llfloaterregiondebugconsole.h
  3 * @author Brad Kittenbrink <brad@lindenlab.com>
  4 * @brief Quick and dirty console for region debug settings
  5 *
  6 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
  7 * Second Life Viewer Source Code
  8 * Copyright (C) 2010, Linden Research, Inc.
  9 * 
 10 * This library is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Lesser General Public
 12 * License as published by the Free Software Foundation;
 13 * version 2.1 of the License only.
 14 * 
 15 * This library is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18 * Lesser General Public License for more details.
 19 * 
 20 * You should have received a copy of the GNU Lesser General Public
 21 * License along with this library; if not, write to the Free Software
 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 23 * 
 24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 25 * $/LicenseInfo$
 26 */
 27
 28#include "llviewerprecompiledheaders.h"
 29
 30#include "llfloaterregiondebugconsole.h"
 31
 32#include "llagent.h"
 33#include "llhttpclient.h"
 34#include "llhttpnode.h"
 35#include "lllineeditor.h"
 36#include "lltexteditor.h"
 37#include "llviewerregion.h"
 38
 39// Two versions of the sim console API are supported.
 40//
 41// SimConsole capability (deprecated):
 42// This is the initial implementation that is supported by some versions of the
 43// simulator. It is simple and straight forward, just POST a command and the
 44// body of the response has the result. This API is deprecated because it
 45// doesn't allow the sim to use any asynchronous API.
 46//
 47// SimConsoleAsync capability:
 48// This capability replaces the original SimConsole capability. It is similar
 49// in that the command is POSTed to the SimConsoleAsync cap, but the response
 50// comes in through the event poll, which gives the simulator more flexibility
 51// and allows it to perform complex operations without blocking any frames.
 52//
 53// We will assume the SimConsoleAsync capability is available, and fall back to
 54// the SimConsole cap if it is not. The simulator will only support one or the
 55// other.
 56
 57namespace
 58{
 59	// Signal used to notify the floater of responses from the asynchronous
 60	// API.
 61	console_reply_signal_t sConsoleReplySignal;
 62
 63	const std::string PROMPT("\n\n> ");
 64	const std::string UNABLE_TO_SEND_COMMAND(
 65		"ERROR: The last command was not received by the server.");
 66	const std::string CONSOLE_UNAVAILABLE(
 67		"ERROR: No console available for this region/simulator.");
 68	const std::string CONSOLE_NOT_SUPPORTED(
 69		"This region does not support the simulator console.");
 70
 71	// This responder handles the initial response. Unless error() is called
 72	// we assume that the simulator has received our request. Error will be
 73	// called if this request times out.
 74	class AsyncConsoleResponder : public LLHTTPClient::Responder
 75	{
 76	public:
 77		/* virtual */
 78		void error(U32 status, const std::string& reason)
 79		{
 80			sConsoleReplySignal(UNABLE_TO_SEND_COMMAND);
 81		}
 82	};
 83
 84	class ConsoleResponder : public LLHTTPClient::Responder
 85	{
 86	public:
 87		ConsoleResponder(LLTextEditor *output) : mOutput(output)
 88		{
 89		}
 90
 91		/*virtual*/
 92		void error(U32 status, const std::string& reason)
 93		{
 94			if (mOutput)
 95			{
 96				mOutput->appendText(
 97					UNABLE_TO_SEND_COMMAND + PROMPT,
 98					false);
 99			}
100		}
101
102		/*virtual*/
103		void result(const LLSD& content)
104		{
105			if (mOutput)
106			{
107				mOutput->appendText(
108					content.asString() + PROMPT, false);
109			}
110		}
111
112		LLTextEditor * mOutput;
113	};
114
115	// This handles responses for console commands sent via the asynchronous
116	// API.
117	class ConsoleResponseNode : public LLHTTPNode
118	{
119	public:
120		/* virtual */
121		void post(
122			LLHTTPNode::ResponsePtr reponse,
123			const LLSD& context,
124			const LLSD& input) const
125		{
126			llinfos << "Received response from the debug console: "
127				<< input << llendl;
128			sConsoleReplySignal(input["body"].asString());
129		}
130	};
131}
132
133boost::signals2::connection LLFloaterRegionDebugConsole::setConsoleReplyCallback(const console_reply_signal_t::slot_type& cb)
134{
135	return sConsoleReplySignal.connect(cb);
136}
137
138LLFloaterRegionDebugConsole::LLFloaterRegionDebugConsole(LLSD const & key)
139: LLFloater(key), mOutput(NULL)
140{
141	mReplySignalConnection = sConsoleReplySignal.connect(
142		boost::bind(
143			&LLFloaterRegionDebugConsole::onReplyReceived,
144			this,
145			_1));
146}
147
148LLFloaterRegionDebugConsole::~LLFloaterRegionDebugConsole()
149{
150	mReplySignalConnection.disconnect();
151}
152
153BOOL LLFloaterRegionDebugConsole::postBuild()
154{
155	LLLineEditor* input = getChild<LLLineEditor>("region_debug_console_input");
156	input->setEnableLineHistory(true);
157	input->setCommitCallback(boost::bind(&LLFloaterRegionDebugConsole::onInput, this, _1, _2));
158	input->setFocus(true);
159	input->setCommitOnFocusLost(false);
160
161	mOutput = getChild<LLTextEditor>("region_debug_console_output");
162
163	std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync");
164	if (url.empty())
165	{
166		// Fall back to see if the old API is supported.
167		url = gAgent.getRegion()->getCapability("SimConsole");
168		if (url.empty())
169		{
170			mOutput->appendText(
171				CONSOLE_NOT_SUPPORTED + PROMPT,
172				false);
173			return TRUE;
174		}
175	}
176
177	mOutput->appendText("> ", false);
178	return TRUE;
179}
180
181void LLFloaterRegionDebugConsole::onInput(LLUICtrl* ctrl, const LLSD& param)
182{
183	LLLineEditor* input = static_cast<LLLineEditor*>(ctrl);
184	std::string text = input->getText() + "\n";
185
186	std::string url = gAgent.getRegion()->getCapability("SimConsoleAsync");
187	if (url.empty())
188	{
189		// Fall back to the old API
190		url = gAgent.getRegion()->getCapability("SimConsole");
191		if (url.empty())
192		{
193			text += CONSOLE_UNAVAILABLE + PROMPT;
194		}
195		else
196		{
197			// Using SimConsole (deprecated)
198			LLHTTPClient::post(
199				url,
200				LLSD(input->getText()),
201				new ConsoleResponder(mOutput));
202		}
203	}
204	else
205	{
206		// Using SimConsoleAsync
207		LLHTTPClient::post(
208			url,
209			LLSD(input->getText()),
210			new AsyncConsoleResponder);
211	}
212
213	mOutput->appendText(text, false);
214	input->clear();
215}
216
217void LLFloaterRegionDebugConsole::onReplyReceived(const std::string& output)
218{
219	mOutput->appendText(output + PROMPT, false);
220}
221
222LLHTTPRegistration<ConsoleResponseNode>
223	gHTTPRegistrationMessageDebugConsoleResponse(
224		"/message/SimConsoleResponse");