svn merge -r 70819:70853 svn+ssh://svn/svn/linden/branches/urldispatcher-for-merge
parent
9763105427
commit
cfd17f3322
|
|
@ -58,7 +58,8 @@ const S32 SPACES_PER_TAB = 4;
|
|||
|
||||
LLColor4 LLTextEditor::mLinkColor = LLColor4::blue;
|
||||
void (* LLTextEditor::mURLcallback)(const char*) = NULL;
|
||||
BOOL (* LLTextEditor::mSecondlifeURLcallback)(LLString) = NULL;
|
||||
bool (* LLTextEditor::mSecondlifeURLcallback)(const std::string&) = NULL;
|
||||
bool (* LLTextEditor::mSecondlifeURLcallbackRightClick)(const std::string&) = NULL;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//virtuals
|
||||
|
|
|
|||
|
|
@ -194,9 +194,10 @@ public:
|
|||
|
||||
// Callbacks
|
||||
static void setLinkColor(LLColor4 color) { mLinkColor = color; }
|
||||
static void setURLCallbacks( void (*callback1) (const char* url),
|
||||
BOOL (*callback2) (LLString url) )
|
||||
{ mURLcallback = callback1; mSecondlifeURLcallback = callback2;}
|
||||
static void setURLCallbacks(void (*callback1) (const char* url),
|
||||
bool (*callback2) (const std::string& url),
|
||||
bool (*callback3) (const std::string& url) )
|
||||
{ mURLcallback = callback1; mSecondlifeURLcallback = callback2; mSecondlifeURLcallbackRightClick = callback3;}
|
||||
|
||||
void setOnScrollEndCallback(void (*callback)(void*), void* userdata);
|
||||
|
||||
|
|
@ -318,7 +319,8 @@ public:
|
|||
LLKeywords mKeywords;
|
||||
static LLColor4 mLinkColor;
|
||||
static void (*mURLcallback) (const char* url);
|
||||
static BOOL (*mSecondlifeURLcallback) (LLString url);
|
||||
static bool (*mSecondlifeURLcallback) (const std::string& url);
|
||||
static bool (*mSecondlifeURLcallbackRightClick) (const std::string& url);
|
||||
protected:
|
||||
LLWString mWText;
|
||||
mutable LLString mUTF8Text;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* @file llcommandhandler.cpp
|
||||
* @brief Central registry for text-driven "commands", most of
|
||||
* which manipulate user interface. For example, the command
|
||||
* "agent (uuid) about" will open the UI for an avatar's profile.
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llcommandhandler.h"
|
||||
|
||||
// system includes
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Underlying registry for command handlers, not directly accessible.
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class LLCommandHandlerRegistry
|
||||
{
|
||||
public:
|
||||
static LLCommandHandlerRegistry& instance();
|
||||
void add(const char* cmd, LLCommandHandler* handler);
|
||||
bool dispatch(const std::string& cmd, const std::vector<std::string>& params);
|
||||
|
||||
private:
|
||||
std::map<std::string, LLCommandHandler*> mMap;
|
||||
};
|
||||
|
||||
// static
|
||||
LLCommandHandlerRegistry& LLCommandHandlerRegistry::instance()
|
||||
{
|
||||
// Force this to be initialized on first call, because we're going
|
||||
// to be adding items to the std::map before main() and we can't
|
||||
// rely on a global being initialized in the right order.
|
||||
static LLCommandHandlerRegistry instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void LLCommandHandlerRegistry::add(const char* cmd, LLCommandHandler* handler)
|
||||
{
|
||||
mMap[cmd] = handler;
|
||||
}
|
||||
|
||||
bool LLCommandHandlerRegistry::dispatch(const std::string& cmd,
|
||||
const std::vector<std::string>& params)
|
||||
{
|
||||
std::map<std::string, LLCommandHandler*>::iterator it = mMap.find(cmd);
|
||||
if (it == mMap.end()) return false;
|
||||
LLCommandHandler* handler = it->second;
|
||||
if (!handler) return false;
|
||||
return handler->handle(params);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Automatic registration of commands, runs before main()
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LLCommandHandler::LLCommandHandler(const char* cmd)
|
||||
{
|
||||
LLCommandHandlerRegistry::instance().add(cmd, this);
|
||||
}
|
||||
|
||||
LLCommandHandler::~LLCommandHandler()
|
||||
{
|
||||
// Don't care about unregistering these, all the handlers
|
||||
// should be static objects.
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Public interface
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
bool LLCommandDispatcher::dispatch(const std::string& cmd, const std::vector<std::string>& params)
|
||||
{
|
||||
return LLCommandHandlerRegistry::instance().dispatch(cmd, params);
|
||||
}
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
* @file llcommandhandler.h
|
||||
* @brief Central registry for text-driven "commands", most of
|
||||
* which manipulate user interface. For example, the command
|
||||
* "agent (uuid) about" will open the UI for an avatar's profile.
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
#ifndef LLCOMMANDHANDLER_H
|
||||
#define LLCOMMANDHANDLER_H
|
||||
|
||||
/* To implement a command "foo" that takes one parameter,
|
||||
a UUID, do this:
|
||||
|
||||
class LLFooHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
// Inform the system you handle commands starting
|
||||
// with "foo"
|
||||
LLFooHandler() : LLCommandHandler("foo") { }
|
||||
|
||||
// Your code here
|
||||
bool handle(const std::vector<std::string>& tokens)
|
||||
{
|
||||
if (tokens.size() < 1) return false;
|
||||
LLUUID id( tokens[0] );
|
||||
return doFoo(id);
|
||||
}
|
||||
};
|
||||
|
||||
// Creating the object registers with the dispatcher.
|
||||
LLFooHandler gFooHandler;
|
||||
*/
|
||||
|
||||
class LLCommandHandler
|
||||
{
|
||||
public:
|
||||
LLCommandHandler(const char* command);
|
||||
// Automatically registers object to get called when
|
||||
// command is executed.
|
||||
|
||||
virtual ~LLCommandHandler();
|
||||
|
||||
virtual bool handle(const std::vector<std::string>& params) = 0;
|
||||
// Execute the command with a provided (possibly empty)
|
||||
// list of parameters.
|
||||
// Return true if you did something, false if the parameters
|
||||
// are invalid or on error.
|
||||
};
|
||||
|
||||
|
||||
class LLCommandDispatcher
|
||||
{
|
||||
public:
|
||||
static bool dispatch(const std::string& cmd, const std::vector<std::string>& params);
|
||||
// Execute a command registered via the above mechanism,
|
||||
// passing string parameters.
|
||||
// Returns true if command was found and executed correctly.
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -197,47 +197,3 @@ void LLFloaterMap::toggle(void*)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BOOL process_secondlife_url(LLString url)
|
||||
{
|
||||
S32 strpos, strpos2;
|
||||
|
||||
LLString slurlID = "slurl.com/secondlife/";
|
||||
strpos = url.find(slurlID);
|
||||
|
||||
if (strpos < 0)
|
||||
{
|
||||
slurlID="secondlife://";
|
||||
strpos = url.find(slurlID);
|
||||
}
|
||||
|
||||
if (strpos >= 0)
|
||||
{
|
||||
LLString simname;
|
||||
|
||||
strpos+=slurlID.length();
|
||||
strpos2=url.find("/",strpos);
|
||||
if (strpos2 < strpos) strpos2=url.length();
|
||||
simname="secondlife://" + url.substr(strpos,url.length() - strpos);
|
||||
|
||||
LLURLSimString::setString( simname );
|
||||
LLURLSimString::parse();
|
||||
|
||||
// if there is a world map
|
||||
if ( gFloaterWorldMap )
|
||||
{
|
||||
// mark where the destination is
|
||||
gFloaterWorldMap->trackURL( LLURLSimString::sInstance.mSimName.c_str(),
|
||||
LLURLSimString::sInstance.mX,
|
||||
LLURLSimString::sInstance.mY,
|
||||
LLURLSimString::sInstance.mZ );
|
||||
|
||||
// display map
|
||||
LLFloaterWorldMap::show( NULL, TRUE );
|
||||
};
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,4 @@ protected:
|
|||
|
||||
extern LLFloaterMap *gFloaterMap;
|
||||
|
||||
BOOL process_secondlife_url(LLString url);
|
||||
|
||||
#endif // LL_LLFLOATERMAP_H
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include "lltextbox.h"
|
||||
#include "llui.h"
|
||||
#include "lluiconstants.h"
|
||||
#include "llurlsimstring.h"
|
||||
#include "llviewerbuild.h"
|
||||
#include "llviewerimagelist.h"
|
||||
#include "llviewermenu.h" // for handle_preferences()
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@
|
|||
#include "lltexturefetch.h"
|
||||
#include "lltoolmgr.h"
|
||||
#include "llui.h"
|
||||
#include "llurldispatcher.h"
|
||||
#include "llurlsimstring.h"
|
||||
#include "llurlwhitelist.h"
|
||||
#include "lluserauth.h"
|
||||
#include "llviewerassetstorage.h"
|
||||
|
|
@ -779,7 +781,7 @@ BOOL idle_startup()
|
|||
|
||||
//For HTML parsing in text boxes.
|
||||
LLTextEditor::setLinkColor( gSavedSettings.getColor4("HTMLLinkColor") );
|
||||
LLTextEditor::setURLCallbacks ( &LLWeb::loadURL, &process_secondlife_url );
|
||||
LLTextEditor::setURLCallbacks ( &LLWeb::loadURL, &LLURLDispatcher::dispatch, &LLURLDispatcher::dispatch );
|
||||
|
||||
//-------------------------------------------------
|
||||
// Handle startup progress screen
|
||||
|
|
@ -2254,25 +2256,8 @@ BOOL idle_startup()
|
|||
gAgentPilot.startPlayback();
|
||||
}
|
||||
|
||||
// ok, if we've gotten this far and have a startup URL
|
||||
if (LLURLSimString::sInstance.parse())
|
||||
{
|
||||
// kick off request for landmark to startup URL
|
||||
if(gFloaterWorldMap)
|
||||
{
|
||||
LLVector3 pos = gAgent.getPositionAgent();
|
||||
if( LLURLSimString::sInstance.mSimName != gAgent.getRegion()->getName()
|
||||
|| LLURLSimString::sInstance.mX != llfloor(pos[VX])
|
||||
|| LLURLSimString::sInstance.mY != llfloor(pos[VY]) )
|
||||
{
|
||||
LLFloaterWorldMap::show(NULL, TRUE);
|
||||
gFloaterWorldMap->trackURL(LLURLSimString::sInstance.mSimName,
|
||||
LLURLSimString::sInstance.mX,
|
||||
LLURLSimString::sInstance.mY,
|
||||
LLURLSimString::sInstance.mZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we've got a startup URL, dispatch it
|
||||
LLStartUp::dispatchURL();
|
||||
|
||||
// Clean up the userauth stuff.
|
||||
if (gUserAuthp)
|
||||
|
|
@ -3664,13 +3649,6 @@ void release_start_screen()
|
|||
gStartImageGL = NULL;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLStartUp::canGoFullscreen()
|
||||
{
|
||||
return LLStartUp::getStartupState() >= STATE_WORLD_INIT;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void LLStartUp::setStartupState( S32 state )
|
||||
{
|
||||
|
|
@ -3692,3 +3670,40 @@ void reset_login()
|
|||
if ( gFloaterMap )
|
||||
gFloaterMap->setVisible( FALSE );
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
std::string LLStartUp::sSLURLCommand;
|
||||
|
||||
bool LLStartUp::canGoFullscreen()
|
||||
{
|
||||
return gStartupState >= STATE_WORLD_INIT;
|
||||
}
|
||||
|
||||
bool LLStartUp::dispatchURL()
|
||||
{
|
||||
// ok, if we've gotten this far and have a startup URL
|
||||
if (!sSLURLCommand.empty())
|
||||
{
|
||||
LLURLDispatcher::dispatch(sSLURLCommand);
|
||||
}
|
||||
else if (LLURLSimString::parse())
|
||||
{
|
||||
// If we started with a location, but we're already
|
||||
// at that location, don't pop dialogs open.
|
||||
LLVector3 pos = gAgent.getPositionAgent();
|
||||
F32 dx = pos.mV[VX] - (F32)LLURLSimString::sInstance.mX;
|
||||
F32 dy = pos.mV[VY] - (F32)LLURLSimString::sInstance.mY;
|
||||
const F32 SLOP = 2.f; // meters
|
||||
|
||||
if( LLURLSimString::sInstance.mSimName != gAgent.getRegion()->getName()
|
||||
|| (dx*dx > SLOP*SLOP)
|
||||
|| (dy*dy > SLOP*SLOP) )
|
||||
{
|
||||
std::string url = LLURLSimString::getURL();
|
||||
LLURLDispatcher::dispatch(url);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,6 +64,14 @@ public:
|
|||
static void setStartupState( S32 state );
|
||||
static S32 getStartupState() { return gStartupState; };
|
||||
|
||||
static bool dispatchURL();
|
||||
// if we have a SLURL or sim string ("Ahern/123/45") that started
|
||||
// the viewer, dispatch it
|
||||
|
||||
static std::string sSLURLCommand;
|
||||
// *HACK: On startup, if we were passed a secondlife://app/do/foo
|
||||
// command URL, store it for later processing.
|
||||
|
||||
protected:
|
||||
static S32 gStartupState; // Do not set directly, use LLStartup::setStartupState
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,303 @@
|
|||
/**
|
||||
* @file llurldispatcher.cpp
|
||||
* @brief Central registry for all URL handlers
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
#include "llviewerprecompiledheaders.h"
|
||||
|
||||
#include "llurldispatcher.h"
|
||||
|
||||
// viewer includes
|
||||
#include "llagent.h" // teleportViaLocation()
|
||||
#include "llcommandhandler.h"
|
||||
// *FIX: code in merge sl-search-8
|
||||
//#include "llfloaterurldisplay.h"
|
||||
#include "llfloaterdirectory.h"
|
||||
#include "llfloaterhtmlhelp.h"
|
||||
#include "llfloaterworldmap.h"
|
||||
#include "llpanellogin.h"
|
||||
#include "llstartup.h" // gStartupState
|
||||
#include "llurlsimstring.h"
|
||||
#include "llviewerwindow.h" // alertXml()
|
||||
#include "llworldmap.h"
|
||||
|
||||
// library includes
|
||||
#include "llsd.h"
|
||||
|
||||
// system includes
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
const std::string SLURL_SL_HELP_PREFIX = "secondlife://app.";
|
||||
const std::string SLURL_SL_PREFIX = "sl://";
|
||||
const std::string SLURL_SECONDLIFE_PREFIX = "secondlife://";
|
||||
const std::string SLURL_SLURL_PREFIX = "http://slurl.com/secondlife/";
|
||||
|
||||
const std::string SLURL_APP_TOKEN = "app/";
|
||||
|
||||
class LLURLDispatcherImpl
|
||||
{
|
||||
public:
|
||||
static bool isSLURL(const std::string& url);
|
||||
|
||||
static bool isSLURLCommand(const std::string& url);
|
||||
|
||||
static bool dispatch(const std::string& url);
|
||||
// returns true if handled
|
||||
|
||||
static bool dispatchRightClick(const std::string& url);
|
||||
|
||||
private:
|
||||
static bool dispatchCore(const std::string& url, bool right_mouse);
|
||||
// handles both left and right click
|
||||
|
||||
static bool dispatchHelp(const std::string& url, BOOL right_mouse);
|
||||
// Handles sl://app.floater.html.help by showing Help floater.
|
||||
// Returns true if handled.
|
||||
|
||||
static bool dispatchApp(const std::string& url, BOOL right_mouse);
|
||||
// Handles secondlife://app/agent/<agent_id>/about and similar
|
||||
// by showing panel in Search floater.
|
||||
// Returns true if handled.
|
||||
|
||||
static bool dispatchRegion(const std::string& url, BOOL right_mouse);
|
||||
// handles secondlife://Ahern/123/45/67/
|
||||
// Returns true if handled.
|
||||
|
||||
// *FIX: code in merge sl-search-8
|
||||
// static void regionHandleCallback(U64 handle, const std::string& url,
|
||||
// const LLUUID& snapshot_id, bool teleport);
|
||||
// // Called by LLWorldMap when a region name has been resolved to a
|
||||
// // location in-world, used by places-panel display.
|
||||
|
||||
static bool matchPrefix(const std::string& url, const std::string& prefix);
|
||||
|
||||
static std::string stripProtocol(const std::string& url);
|
||||
|
||||
friend class LLTeleportHandler;
|
||||
};
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::isSLURL(const std::string& url)
|
||||
{
|
||||
if (matchPrefix(url, SLURL_SL_HELP_PREFIX)) return true;
|
||||
if (matchPrefix(url, SLURL_SL_PREFIX)) return true;
|
||||
if (matchPrefix(url, SLURL_SECONDLIFE_PREFIX)) return true;
|
||||
if (matchPrefix(url, SLURL_SLURL_PREFIX)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::isSLURLCommand(const std::string& url)
|
||||
{
|
||||
if (matchPrefix(url, SLURL_SL_PREFIX + SLURL_APP_TOKEN)
|
||||
|| matchPrefix(url, SLURL_SECONDLIFE_PREFIX + SLURL_APP_TOKEN)
|
||||
|| matchPrefix(url, SLURL_SLURL_PREFIX + SLURL_APP_TOKEN) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatchCore(const std::string& url, bool right_mouse)
|
||||
{
|
||||
if (url.empty()) return false;
|
||||
if (dispatchHelp(url, right_mouse)) return true;
|
||||
if (dispatchApp(url, right_mouse)) return true;
|
||||
if (dispatchRegion(url, right_mouse)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatch(const std::string& url)
|
||||
{
|
||||
llinfos << "url: " << url << llendl;
|
||||
return dispatchCore(url, false); // not right click
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatchRightClick(const std::string& url)
|
||||
{
|
||||
llinfos << "url: " << url << llendl;
|
||||
return dispatchCore(url, true); // yes right click
|
||||
}
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatchHelp(const std::string& url, BOOL right_mouse)
|
||||
{
|
||||
if (matchPrefix(url, SLURL_SL_HELP_PREFIX))
|
||||
{
|
||||
gViewerHtmlHelp.show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatchApp(const std::string& url, BOOL right_mouse)
|
||||
{
|
||||
if (!isSLURL(url))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
std::string s = stripProtocol(url);
|
||||
|
||||
// At this point, "secondlife://app/foo/bar/baz/" should be left
|
||||
// as: "app/foo/bar/baz/"
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
boost::char_separator<char> sep("/", "", boost::drop_empty_tokens);
|
||||
tokenizer tokens(s, sep);
|
||||
tokenizer::iterator it = tokens.begin();
|
||||
tokenizer::iterator end = tokens.end();
|
||||
|
||||
// Build parameter list suitable for LLDispatcher dispatch
|
||||
if (it == end) return false;
|
||||
if (*it != "app") return false;
|
||||
++it;
|
||||
|
||||
if (it == end) return false;
|
||||
std::string cmd = *it;
|
||||
++it;
|
||||
|
||||
std::vector<std::string> params;
|
||||
for ( ; it != end; ++it)
|
||||
{
|
||||
params.push_back(*it);
|
||||
}
|
||||
|
||||
bool handled = LLCommandDispatcher::dispatch(cmd, params);
|
||||
if (handled) return true;
|
||||
|
||||
// Inform the user we can't handle this
|
||||
std::map<std::string, std::string> args;
|
||||
args["[SLURL]"] = url;
|
||||
gViewerWindow->alertXml("BadURL", args);
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::dispatchRegion(const std::string& url, BOOL right_mouse)
|
||||
{
|
||||
if (!isSLURL(url))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Before we're logged in, need to update the startup screen
|
||||
// to tell the user where they are going.
|
||||
if (LLStartUp::getStartupState() < STATE_CLEANUP)
|
||||
{
|
||||
// Parse it and stash in globals, it will be dispatched in
|
||||
// STATE_CLEANUP.
|
||||
LLURLSimString::setString(url);
|
||||
// We're at the login screen, so make sure user can see
|
||||
// the login location box to know where they are going.
|
||||
LLPanelLogin::refreshLocation( true );
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string sim_string = stripProtocol(url);
|
||||
std::string region_name;
|
||||
S32 x = 128;
|
||||
S32 y = 128;
|
||||
S32 z = 0;
|
||||
LLURLSimString::parse(sim_string, ®ion_name, &x, &y, &z);
|
||||
if (gFloaterWorldMap)
|
||||
{
|
||||
llinfos << "Opening map to " << region_name << llendl;
|
||||
gFloaterWorldMap->trackURL( region_name.c_str(), x, y, z );
|
||||
LLFloaterWorldMap::show(NULL, TRUE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcherImpl::matchPrefix(const std::string& url, const std::string& prefix)
|
||||
{
|
||||
std::string test_prefix = url.substr(0, prefix.length());
|
||||
LLString::toLower(test_prefix);
|
||||
return test_prefix == prefix;
|
||||
}
|
||||
|
||||
// static
|
||||
std::string LLURLDispatcherImpl::stripProtocol(const std::string& url)
|
||||
{
|
||||
std::string stripped = url;
|
||||
if (matchPrefix(stripped, SLURL_SL_HELP_PREFIX))
|
||||
{
|
||||
stripped.erase(0, SLURL_SL_HELP_PREFIX.length());
|
||||
}
|
||||
else if (matchPrefix(stripped, SLURL_SL_PREFIX))
|
||||
{
|
||||
stripped.erase(0, SLURL_SL_PREFIX.length());
|
||||
}
|
||||
else if (matchPrefix(stripped, SLURL_SECONDLIFE_PREFIX))
|
||||
{
|
||||
stripped.erase(0, SLURL_SECONDLIFE_PREFIX.length());
|
||||
}
|
||||
else if (matchPrefix(stripped, SLURL_SLURL_PREFIX))
|
||||
{
|
||||
stripped.erase(0, SLURL_SLURL_PREFIX.length());
|
||||
}
|
||||
return stripped;
|
||||
}
|
||||
|
||||
// *FIX: code in merge sl-search-8
|
||||
//
|
||||
////---------------------------------------------------------------------------
|
||||
//// Teleportation links are handled here because they are tightly coupled
|
||||
//// to URL parsing and sim-fragment parsing
|
||||
//class LLTeleportHandler : public LLCommandHandler
|
||||
//{
|
||||
//public:
|
||||
// LLTeleportHandler() : LLCommandHandler("teleport") { }
|
||||
// bool handle(const std::vector<std::string>& tokens)
|
||||
// {
|
||||
// // construct a "normal" SLURL, resolve the region to
|
||||
// // a global position, and teleport to it
|
||||
// if (tokens.size() < 1) return false;
|
||||
//
|
||||
// // Region names may be %20 escaped.
|
||||
// std::string region_name = LLURLSimString::unescapeRegionName(tokens[0]);
|
||||
//
|
||||
// // build secondlife://De%20Haro/123/45/67 for use in callback
|
||||
// std::string url = SLURL_SECONDLIFE_PREFIX;
|
||||
// for (size_t i = 0; i < tokens.size(); ++i)
|
||||
// {
|
||||
// url += tokens[i] + "/";
|
||||
// }
|
||||
// gWorldMap->sendNamedRegionRequest(region_name,
|
||||
// LLURLDispatcherImpl::regionHandleCallback,
|
||||
// url,
|
||||
// true); // teleport
|
||||
// return true;
|
||||
// }
|
||||
//};
|
||||
//LLTeleportHandler gTeleportHandler;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
bool LLURLDispatcher::isSLURL(const std::string& url)
|
||||
{
|
||||
return LLURLDispatcherImpl::isSLURL(url);
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcher::isSLURLCommand(const std::string& url)
|
||||
{
|
||||
return LLURLDispatcherImpl::isSLURLCommand(url);
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLURLDispatcher::dispatch(const std::string& url)
|
||||
{
|
||||
return LLURLDispatcherImpl::dispatch(url);
|
||||
}
|
||||
// static
|
||||
bool LLURLDispatcher::dispatchRightClick(const std::string& url)
|
||||
{
|
||||
return LLURLDispatcherImpl::dispatchRightClick(url);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* @file llurldispatcher.h
|
||||
* @brief Central registry for all SL URL handlers
|
||||
*
|
||||
* Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
|
||||
* $License$
|
||||
*/
|
||||
#ifndef LLURLDISPATCHER_H
|
||||
#define LLURLDISPATCHER_H
|
||||
|
||||
class LLURLDispatcher
|
||||
{
|
||||
public:
|
||||
static bool isSLURL(const std::string& url);
|
||||
// Is this any sort of secondlife:// or sl:// URL?
|
||||
|
||||
static bool isSLURLCommand(const std::string& url);
|
||||
// Is this a special secondlife://app/ URL?
|
||||
|
||||
static bool dispatch(const std::string& url);
|
||||
// At startup time and on clicks in internal web browsers,
|
||||
// teleport, open map, or run requested command.
|
||||
// Handles:
|
||||
// secondlife://RegionName/123/45/67/
|
||||
// secondlife://app/agent/3d6181b0-6a4b-97ef-18d8-722652995cf1/show
|
||||
// sl://app/foo/bar
|
||||
// Returns true if someone handled the URL.
|
||||
static bool dispatchRightClick(const std::string& url);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -83,7 +83,6 @@
|
|||
#include "llfloatergroups.h"
|
||||
#include "llfloaterhtml.h"
|
||||
#include "llfloaterhtmlhelp.h"
|
||||
#include "llfloaterhtmlfind.h"
|
||||
#include "llfloaterinspect.h"
|
||||
#include "llfloaterlagmeter.h"
|
||||
#include "llfloaterland.h"
|
||||
|
|
@ -340,6 +339,7 @@ void toggle_show_xui_names(void *);
|
|||
BOOL check_show_xui_names(void *);
|
||||
|
||||
// Debug UI
|
||||
void handle_slurl_test(void*);
|
||||
void handle_save_to_xml(void*);
|
||||
void handle_load_from_xml(void*);
|
||||
|
||||
|
|
@ -976,6 +976,7 @@ extern BOOL gVectorizePerfTest;
|
|||
|
||||
void init_debug_ui_menu(LLMenuGL* menu)
|
||||
{
|
||||
menu->append(new LLMenuItemCallGL("SLURL Test", &handle_slurl_test));
|
||||
menu->append(new LLMenuItemCallGL("Editable UI", &edit_ui));
|
||||
menu->append(new LLMenuItemToggleGL("Async Keystrokes", &gHandleKeysAsync));
|
||||
menu->append(new LLMenuItemCallGL( "Dump SelectMgr", &dump_select_mgr));
|
||||
|
|
@ -7282,6 +7283,11 @@ void handle_load_from_xml(void*)
|
|||
}
|
||||
}
|
||||
|
||||
void handle_slurl_test(void*)
|
||||
{
|
||||
LLFloaterHtml::getInstance()->show("http://user.lindenlab.com/~james/slurl.html", "SLURL Test");
|
||||
}
|
||||
|
||||
void handle_rebake_textures(void*)
|
||||
{
|
||||
LLVOAvatar* avatar = gAgent.getAvatarObject();
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@
|
|||
#include "lltoolview.h"
|
||||
#include "llvieweruictrlfactory.h"
|
||||
#include "lluploaddialog.h"
|
||||
#include "llurldispatcher.h" // SLURL from other app instance
|
||||
#include "llviewercamera.h"
|
||||
#include "llviewergesture.h"
|
||||
#include "llviewerimagelist.h"
|
||||
|
|
@ -1394,22 +1395,14 @@ void LLViewerWindow::handleWindowUnblock(LLWindow *window)
|
|||
|
||||
void LLViewerWindow::handleDataCopy(LLWindow *window, S32 data_type, void *data)
|
||||
{
|
||||
const S32 SLURL_MESSAGE_TYPE = 0;
|
||||
switch (data_type)
|
||||
{
|
||||
case 0:
|
||||
case SLURL_MESSAGE_TYPE:
|
||||
// received URL
|
||||
if (LLURLSimString::unpack_data(data))
|
||||
std::string url = (const char*)data;
|
||||
if (LLURLDispatcher::dispatch(url))
|
||||
{
|
||||
if(gFloaterWorldMap)
|
||||
{
|
||||
gFloaterWorldMap->trackURL(LLURLSimString::sInstance.mSimName,
|
||||
LLURLSimString::sInstance.mX,
|
||||
LLURLSimString::sInstance.mY,
|
||||
LLURLSimString::sInstance.mZ);
|
||||
|
||||
LLFloaterWorldMap::show(NULL, TRUE);
|
||||
}
|
||||
|
||||
// bring window to foreground, as it has just been "launched" from a URL
|
||||
mWindow->bringToFront();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue