Files
SingularityViewer/indra/newview/llfloaterurlentry.cpp
Aleric Inglewood 6f8ea87c46 Add ResponderHeadersOnly.
ResponderHeadersOnly is a base class for responders that use
HTTPClient::head or HTTPClient::getHeaderOnly. It already
has a needsHeaders() that return true and only allows for
completedHeaders to be overridden.

I removed the CURLOPT_HEADER option for these cases, because
that only causes the headers to be send to the writeCallback
as if they are part of the body, in addition to the headerCallback;
That gave raise to some confusion for the existing code (ie,
unexpected errors when trying to decode the body as LLSD and
duplicated 'low speed' information for the Timeout policy code.
2012-11-13 21:46:35 +01:00

303 lines
9.0 KiB
C++

/**
* @file llfloaterurlentry.cpp
* @brief LLFloaterURLEntry class implementation
*
* $LicenseInfo:firstyear=2007&license=viewergpl$
*
* Copyright (c) 2007-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloaterurlentry.h"
#include "llpanellandmedia.h"
// project includes
#include "llcombobox.h"
#include "llnotificationsutil.h"
#include "llurlhistory.h"
#include "lluictrlfactory.h"
#include "llwindow.h"
#include "llviewerwindow.h"
#include "llhttpclient.h"
class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy mediaTypeResponder_timeout;
static LLFloaterURLEntry* sInstance = NULL;
// Move this to its own file.
// helper class that tries to download a URL from a web site and calls a method
// on the Panel Land Media and to discover the MIME type
class LLMediaTypeResponder : public LLHTTPClient::ResponderHeadersOnly
{
public:
LLMediaTypeResponder( const LLHandle<LLFloater> parent ) :
mParent( parent )
{}
LLHandle<LLFloater> mParent;
virtual void completedHeaders(U32 status, std::string const& reason, AIHTTPReceivedHeaders const& headers)
{
if (200 <= status && status < 300)
{
std::string media_type;
if (headers.getFirstValue("content-type", media_type))
{
std::string::size_type idx1 = media_type.find_first_of(";");
std::string mime_type = media_type.substr(0, idx1);
completeAny(status, mime_type);
return;
}
llwarns << "LLMediaTypeResponder::completedHeaders: OK HTTP status (" << status << ") but no Content-Type! Received headers: " << headers << llendl;
}
completeAny(status, "none/none");
}
void completeAny(U32 status, const std::string& mime_type)
{
// Set empty type to none/none. Empty string is reserved for legacy parcels
// which have no mime type set.
std::string resolved_mime_type = ! mime_type.empty() ? mime_type : "none/none";
LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mParent.get();
if ( floater_url_entry )
floater_url_entry->headerFetchComplete( status, resolved_mime_type );
}
virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return mediaTypeResponder_timeout; }
};
//-----------------------------------------------------------------------------
// LLFloaterURLEntry()
//-----------------------------------------------------------------------------
LLFloaterURLEntry::LLFloaterURLEntry(LLHandle<LLPanel> parent)
:
LLFloater(),
mPanelLandMediaHandle(parent)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_url_entry.xml");
mMediaURLEdit = getChild<LLComboBox>("media_entry");
// Cancel button
childSetAction("cancel_btn", onBtnCancel, this);
// Cancel button
childSetAction("clear_btn", onBtnClear, this);
// clear media list button
LLSD parcel_history = LLURLHistory::getURLHistory("parcel");
bool enable_clear_button = parcel_history.size() > 0 ? true : false;
childSetEnabled( "clear_btn", enable_clear_button );
// OK button
childSetAction("ok_btn", onBtnOK, this);
setDefaultBtn("ok_btn");
buildURLHistory();
sInstance = this;
}
//-----------------------------------------------------------------------------
// ~LLFloaterURLEntry()
//-----------------------------------------------------------------------------
LLFloaterURLEntry::~LLFloaterURLEntry()
{
sInstance = NULL;
}
void LLFloaterURLEntry::buildURLHistory()
{
LLCtrlListInterface* url_list = childGetListInterface("media_entry");
if (url_list)
{
url_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
}
// Get all of the entries in the "parcel" collection
LLSD parcel_history = LLURLHistory::getURLHistory("parcel");
LLSD::array_iterator iter_history =
parcel_history.beginArray();
LLSD::array_iterator end_history =
parcel_history.endArray();
for(; iter_history != end_history; ++iter_history)
{
url_list->addSimpleElement((*iter_history).asString());
}
}
void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type)
{
LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get();
if (panel_media)
{
// status is ignored for now -- error = "none/none"
panel_media->setMediaType(mime_type);
panel_media->setMediaURL(mMediaURLEdit->getValue().asString());
}
// Decrement the cursor
getWindow()->decBusyCount();
childSetVisible("loading_label", false);
close();
}
// static
LLHandle<LLFloater> LLFloaterURLEntry::show(LLHandle<LLPanel> parent)
{
if (sInstance)
{
sInstance->open();
}
else
{
sInstance = new LLFloaterURLEntry(parent);
}
sInstance->updateFromLandMediaPanel();
return sInstance->getHandle();
}
void LLFloaterURLEntry::updateFromLandMediaPanel()
{
LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get();
if (panel_media)
{
std::string media_url = panel_media->getMediaURL();
addURLToCombobox(media_url);
}
}
bool LLFloaterURLEntry::addURLToCombobox(const std::string& media_url)
{
if(! mMediaURLEdit->setSimple( media_url ) && ! media_url.empty())
{
mMediaURLEdit->add( media_url );
mMediaURLEdit->setSimple( media_url );
return true;
}
// URL was not added for whatever reason (either it was empty or already existed)
return false;
}
// static
//-----------------------------------------------------------------------------
// onBtnOK()
//-----------------------------------------------------------------------------
void LLFloaterURLEntry::onBtnOK( void* userdata )
{
LLFloaterURLEntry *self =(LLFloaterURLEntry *)userdata;
std::string media_url = self->mMediaURLEdit->getValue().asString();
self->mMediaURLEdit->remove(media_url);
LLURLHistory::removeURL("parcel", media_url);
if(self->addURLToCombobox(media_url))
{
// Add this url to the parcel collection
LLURLHistory::addURL("parcel", media_url);
}
// leading whitespace causes problems with the MIME-type detection so strip it
LLStringUtil::trim( media_url );
// First check the URL scheme
LLURI url(media_url);
std::string scheme = url.scheme();
// We assume that an empty scheme is an http url, as this is how we will treat it.
if(scheme == "")
{
scheme = "http";
}
// Discover the MIME type only for "http" scheme.
if(scheme == "http" || scheme == "https")
{
LLHTTPClient::getHeaderOnly( media_url,
new LLMediaTypeResponder(self->getHandle()));
}
else
{
self->headerFetchComplete(0, scheme);
}
// Grey the buttons until we get the header response
self->childSetEnabled("ok_btn", false);
self->childSetEnabled("cancel_btn", false);
self->childSetEnabled("media_entry", false);
// show progress bar here?
getWindow()->incBusyCount();
self->childSetVisible("loading_label", true);
}
// static
//-----------------------------------------------------------------------------
// onBtnCancel()
//-----------------------------------------------------------------------------
void LLFloaterURLEntry::onBtnCancel( void* userdata )
{
LLFloaterURLEntry *self =(LLFloaterURLEntry *)userdata;
self->close();
}
// static
//-----------------------------------------------------------------------------
// onBtnClear()
//-----------------------------------------------------------------------------
void LLFloaterURLEntry::onBtnClear( void* userdata )
{
LLNotificationsUtil::add( "ConfirmClearMediaUrlList", LLSD(), LLSD(),
boost::bind(&LLFloaterURLEntry::callback_clear_url_list, (LLFloaterURLEntry*)userdata, _1, _2) );
}
bool LLFloaterURLEntry::callback_clear_url_list(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if ( option == 0 ) // YES
{
// clear saved list
LLCtrlListInterface* url_list = childGetListInterface("media_entry");
if ( url_list )
{
url_list->operateOnAll( LLCtrlListInterface::OP_DELETE );
}
// clear current contents of combo box
mMediaURLEdit->clear();
// clear stored version of list
LLURLHistory::clear("parcel");
// cleared the list so disable Clear button
childSetEnabled( "clear_btn", false );
}
return false;
}