summaryrefslogtreecommitdiff
path: root/indra/newview/llviewermedia.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llviewermedia.cpp')
-rw-r--r--indra/newview/llviewermedia.cpp406
1 files changed, 402 insertions, 4 deletions
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 64dcd62a6a..d9fabc7d64 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -45,6 +45,7 @@
#include "llviewertexturelist.h"
#include "llvovolume.h"
#include "llpluginclassmedia.h"
+#include "llplugincookiestore.h"
#include "llviewerwindow.h"
#include "llfocusmgr.h"
#include "llcallbacklist.h"
@@ -256,6 +257,43 @@ public:
LLViewerMediaImpl *mMediaImpl;
bool mInitialized;
};
+
+class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder
+{
+LOG_CLASS(LLViewerMediaOpenIDResponder);
+public:
+ LLViewerMediaOpenIDResponder( )
+ {
+ }
+
+ ~LLViewerMediaOpenIDResponder()
+ {
+ }
+
+ /* virtual */ void completedHeader(U32 status, const std::string& reason, const LLSD& content)
+ {
+ LL_DEBUGS("MediaAuth") << "status = " << status << ", reason = " << reason << LL_ENDL;
+ LL_DEBUGS("MediaAuth") << content << LL_ENDL;
+ std::string cookie = content["set-cookie"].asString();
+
+ LLViewerMedia::openIDCookieResponse(cookie);
+ }
+
+ /* virtual */ void completedRaw(
+ U32 status,
+ const std::string& reason,
+ const LLChannelDescriptors& channels,
+ const LLIOPipe::buffer_ptr_t& buffer)
+ {
+ // This is just here to disable the default behavior (attempting to parse the response as llsd).
+ // We don't care about the content of the response, only the set-cookie header.
+ }
+
+};
+
+LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;
+LLURL LLViewerMedia::sOpenIDURL;
+std::string LLViewerMedia::sOpenIDCookie;
static LLViewerMedia::impl_list sViewerMediaImplList;
static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap;
static LLTimer sMediaCreateTimer;
@@ -264,6 +302,8 @@ static F32 sGlobalVolume = 1.0f;
static F64 sLowestLoadableImplInterest = 0.0f;
static bool sAnyMediaShowing = false;
static boost::signals2::connection sTeleportFinishConnection;
+static std::string sUpdatedCookies;
+static const char *PLUGIN_COOKIE_FILE_NAME = "plugin_cookies.txt";
//////////////////////////////////////////////////////////////////////////////////////////
static void add_media_impl(LLViewerMediaImpl* media)
@@ -399,7 +439,6 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
media_impl->setHomeURL(media_entry->getHomeURL());
media_impl->mMediaAutoPlay = media_entry->getAutoPlay();
media_impl->mMediaEntryURL = media_entry->getCurrentURL();
-
if(media_impl->isAutoPlayable())
{
needs_navigate = true;
@@ -698,6 +737,13 @@ static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMedi
void LLViewerMedia::updateMedia(void *dummy_arg)
{
sAnyMediaShowing = false;
+ sUpdatedCookies = getCookieStore()->getChangedCookies();
+ if(!sUpdatedCookies.empty())
+ {
+ lldebugs << "updated cookies will be sent to all loaded plugins: " << llendl;
+ lldebugs << sUpdatedCookies << llendl;
+ }
+
impl_list::iterator iter = sViewerMediaImplList.begin();
impl_list::iterator end = sViewerMediaImplList.end();
@@ -982,6 +1028,314 @@ bool LLViewerMedia::isParcelAudioPlaying()
return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying());
}
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::clearAllCookies()
+{
+ // Clear all cookies for all plugins
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+ for (; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ if(pimpl->mMediaSource)
+ {
+ pimpl->mMediaSource->clear_cookies();
+ }
+ }
+
+ // Clear all cookies from the cookie store
+ getCookieStore()->setAllCookies("");
+
+ // FIXME: this may not be sufficient, since the on-disk cookie file won't get written until some browser instance exits cleanly.
+ // It also won't clear cookies for other accounts, or for any account if we're not logged in, and won't do anything at all if there are no webkit plugins loaded.
+ // Until such time as we can centralize cookie storage, the following hack should cover these cases:
+
+ // HACK: Look for cookie files in all possible places and delete them.
+ // NOTE: this assumes knowledge of what happens inside the webkit plugin (it's what adds 'browser_profile' to the path and names the cookie file)
+
+ // Places that cookie files can be:
+ // <getOSUserAppDir>/browser_profile/cookies
+ // <getOSUserAppDir>/first_last/browser_profile/cookies (note that there may be any number of these!)
+ // <getOSUserAppDir>/first_last/plugin_cookies.txt (note that there may be any number of these!)
+
+ std::string base_dir = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter();
+ std::string target;
+ std::string filename;
+
+ lldebugs << "base dir = " << base_dir << llendl;
+
+ // The non-logged-in version is easy
+ target = base_dir;
+ target += "browser_profile";
+ target += gDirUtilp->getDirDelimiter();
+ target += "cookies";
+ lldebugs << "target = " << target << llendl;
+ if(LLFile::isfile(target))
+ {
+ LLFile::remove(target);
+ }
+
+ // the hard part: iterate over all user directories and delete the cookie file from each one
+ while(gDirUtilp->getNextFileInDir(base_dir, "*_*", filename, false))
+ {
+ target = base_dir;
+ target += filename;
+ target += gDirUtilp->getDirDelimiter();
+ target += "browser_profile";
+ target += gDirUtilp->getDirDelimiter();
+ target += "cookies";
+ lldebugs << "target = " << target << llendl;
+ if(LLFile::isfile(target))
+ {
+ LLFile::remove(target);
+ }
+
+ // Other accounts may have new-style cookie files too -- delete them as well
+ target = base_dir;
+ target += filename;
+ target += gDirUtilp->getDirDelimiter();
+ target += PLUGIN_COOKIE_FILE_NAME;
+ lldebugs << "target = " << target << llendl;
+ if(LLFile::isfile(target))
+ {
+ LLFile::remove(target);
+ }
+ }
+
+ // If we have an OpenID cookie, re-add it to the cookie store.
+ setOpenIDCookie();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::clearAllCaches()
+{
+ // Clear all plugins' caches
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+ for (; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ pimpl->clearCache();
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setCookiesEnabled(bool enabled)
+{
+ // Set the "cookies enabled" flag for all loaded plugins
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+ for (; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ if(pimpl->mMediaSource)
+ {
+ pimpl->mMediaSource->enable_cookies(enabled);
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int port)
+{
+ // Set the proxy config for all loaded plugins
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+ for (; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ if(pimpl->mMediaSource)
+ {
+ pimpl->mMediaSource->proxy_setup(enable, host, port);
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+LLPluginCookieStore *LLViewerMedia::getCookieStore()
+{
+ if(sCookieStore == NULL)
+ {
+ sCookieStore = new LLPluginCookieStore;
+ }
+
+ return sCookieStore;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::loadCookieFile()
+{
+ // build filename for each user
+ std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
+
+ if (resolved_filename.empty())
+ {
+ llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl;
+ return;
+ }
+
+ // open the file for reading
+ llifstream file(resolved_filename);
+ if (!file.is_open())
+ {
+ llwarns << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << llendl;
+ return;
+ }
+
+ getCookieStore()->readAllCookies(file, true);
+
+ file.close();
+
+ // send the clear_cookies message to all loaded plugins
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+ for (; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ if(pimpl->mMediaSource)
+ {
+ pimpl->mMediaSource->clear_cookies();
+ }
+ }
+
+ // If we have an OpenID cookie, re-add it to the cookie store.
+ setOpenIDCookie();
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::saveCookieFile()
+{
+ // build filename for each user
+ std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, PLUGIN_COOKIE_FILE_NAME);
+
+ if (resolved_filename.empty())
+ {
+ llinfos << "can't get path to plugin cookie file - probably not logged in yet." << llendl;
+ return;
+ }
+
+ // open a file for writing
+ llofstream file (resolved_filename);
+ if (!file.is_open())
+ {
+ llwarns << "can't open plugin cookie file \"" << PLUGIN_COOKIE_FILE_NAME << "\" for writing" << llendl;
+ return;
+ }
+
+ getCookieStore()->writePersistentCookies(file);
+
+ file.close();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path, bool secure)
+{
+ std::stringstream cookie;
+
+ cookie << name << "=" << LLPluginCookieStore::quoteString(value);
+
+ if(expires.notNull())
+ {
+ cookie << "; expires=" << expires.asRFC1123();
+ }
+
+ cookie << "; domain=" << domain;
+
+ cookie << "; path=" << path;
+
+ if(secure)
+ {
+ cookie << "; secure";
+ }
+
+ getCookieStore()->setCookies(cookie.str());
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path, bool secure)
+{
+ // A session cookie just has a NULL date.
+ addCookie(name, value, domain, LLDate(), path, secure);
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::removeCookie(const std::string &name, const std::string &domain, const std::string &path )
+{
+ // To remove a cookie, add one with the same name, domain, and path that expires in the past.
+
+ addCookie(name, "", domain, LLDate(LLDate::now().secondsSinceEpoch() - 1.0), path);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setOpenIDCookie()
+{
+ if(!sOpenIDCookie.empty())
+ {
+ getCookieStore()->setCookiesFromHost(sOpenIDCookie, sOpenIDURL.mAuthority);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token)
+{
+ LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL;
+
+ // post the token to the url
+ // the responder will need to extract the cookie(s).
+
+ // Save the OpenID URL for later -- we may need the host when adding the cookie.
+ sOpenIDURL.init(openid_url.c_str());
+
+ // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.
+ sOpenIDCookie.clear();
+
+ LLSD headers = LLSD::emptyMap();
+ // Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header
+ headers["Accept"] = "*/*";
+ // and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream"
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
+
+ // postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
+ size_t size = openid_token.size();
+ U8 *data = new U8[size];
+ memcpy(data, openid_token.data(), size);
+
+ LLHTTPClient::postRaw(
+ openid_url,
+ data,
+ size,
+ new LLViewerMediaOpenIDResponder(),
+ headers);
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::openIDCookieResponse(const std::string &cookie)
+{
+ LL_DEBUGS("MediaAuth") << "Cookie received: \"" << cookie << "\"" << LL_ENDL;
+
+ sOpenIDCookie += cookie;
+
+ setOpenIDCookie();
+}
+
bool LLViewerMedia::hasInWorldMedia()
{
if (sInWorldMediaDisabled) return false;
@@ -1258,8 +1612,22 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_
{
LLPluginClassMedia* media_source = new LLPluginClassMedia(owner);
media_source->setSize(default_width, default_height);
- std::string language_code = LLUI::getLanguage();
- if (media_source->init(launcher_name, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"), user_data_path, language_code))
+ media_source->setUserDataPath(user_data_path);
+ media_source->setLanguageCode(LLUI::getLanguage());
+
+ // collect 'cookies enabled' setting from prefs and send to embedded browser
+ bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" );
+ media_source->enable_cookies( cookies_enabled );
+
+ // collect 'plugins enabled' setting from prefs and send to embedded browser
+ bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" );
+ media_source->setPluginsEnabled( plugins_enabled );
+
+ // collect 'javascript enabled' setting from prefs and send to embedded browser
+ bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" );
+ media_source->setJavascriptEnabled( javascript_enabled );
+
+ if (media_source->init(launcher_name, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")))
{
return media_source;
}
@@ -1320,12 +1688,25 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
media_source->focus(mHasFocus);
media_source->setBackgroundColor(mBackgroundColor);
+ media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"));
+
if(mClearCache)
{
mClearCache = false;
media_source->clear_cache();
}
+ // TODO: Only send cookies to plugins that need them
+ // Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message.
+ // Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message,
+ // which could cause odd race conditions.
+ std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies();
+ lldebugs << "setting cookies: " << all_cookies << llendl;
+ if(!all_cookies.empty())
+ {
+ media_source->set_cookies(all_cookies);
+ }
+
mMediaSource = media_source;
updateVolume();
@@ -2023,6 +2404,16 @@ void LLViewerMediaImpl::update()
}
}
}
+ else
+ {
+ // If we didn't just create the impl, it may need to get cookie updates.
+ if(!sUpdatedCookies.empty())
+ {
+ // TODO: Only send cookies to plugins that need them
+ mMediaSource->set_cookies(sUpdatedCookies);
+ }
+ }
+
if(mMediaSource == NULL)
{
@@ -2485,6 +2876,13 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
////////////////////////////////////////////////////////////////////////////////
// virtual
+void LLViewerMediaImpl::handleCookieSet(LLPluginClassMedia* self, const std::string &cookie)
+{
+ LLViewerMedia::getCookieStore()->setCookies(cookie);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
void
LLViewerMediaImpl::cut()
{
@@ -2896,7 +3294,7 @@ bool LLViewerMediaImpl::isObjectAttachedToAnotherAvatar(LLVOVolume *obj)
if (NULL != object)
{
LLVOAvatar *avatar = object->asAvatar();
- if (NULL != avatar && avatar != gAgent.getAvatarObject())
+ if ((NULL != avatar) && (avatar != gAgentAvatarp))
{
result = true;
break;