diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 5c0c5f14c..42a7a99a9 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1745,9 +1745,6 @@ bool LLAppViewer::cleanup() removeDumpDir(); writeDebugInfo(); - if(!gDirUtilp->getLindenUserDir(true).empty()) - LLViewerMedia::saveCookieFile(); - // Stop the plugin read thread if it's running. LLPluginProcessParent::setUseReadThread(false); // Stop curl responder call backs. diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index a65c25338..f9b72c774 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -70,14 +70,14 @@ LLMediaCtrl::Params::Params() : start_url("start_url"), border_visible("border_visible", false), decouple_texture_size("decouple_texture_size", false), + trusted_content("trusted_content", false), + focus_on_click("focus_on_click", true), texture_width("texture_width", 1024), texture_height("texture_height", 1024), caret_color("caret_color"), initial_mime_type("initial_mime_type"), - error_page_url("error_page_url"), media_id("media_id"), - trusted_content("trusted_content", false), - focus_on_click("focus_on_click", true) + error_page_url("error_page_url") { } @@ -85,25 +85,25 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : LLPanel( p.name, p.rect, FALSE), LLInstanceTracker(LLUUID::generateNewID()), mTextureDepthBytes( 4 ), - mBorder(NULL), + mBorder(nullptr), mFrequentUpdates( true ), mForceUpdate( false ), - mHomePageUrl( "" ), + mTrusted(p.trusted_content), mAlwaysRefresh( false ), - mMediaSource( 0 ), mTakeFocusOnClick( p.focus_on_click ), - mCurrentNavUrl( "about:blank" ), mStretchToFill( true ), mMaintainAspectRatio ( true ), + mClearCache(false), + mHoverTextChanged(false), mDecoupleTextureSize ( false ), + mUpdateScrolls( false ), + mHomePageUrl( "" ), + mHomePageMimeType(p.initial_mime_type), + mCurrentNavUrl( "about:blank" ), + mErrorPageURL(p.error_page_url), + mMediaSource( nullptr ), mTextureWidth ( 1024 ), mTextureHeight ( 1024 ), - mClearCache(false), - mUpdateScrolls( false ), - mHomePageMimeType(p.initial_mime_type), - mErrorPageURL(p.error_page_url), - mTrusted(p.trusted_content), - mHoverTextChanged(false), mContextMenu() { { @@ -141,6 +141,13 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : LLMediaCtrl::~LLMediaCtrl() { + auto menu = mContextMenu.get(); + if (menu) + { + menu->die(); + mContextMenu.markDead(); + } + if (mMediaSource) { mMediaSource->remObserver( this ); @@ -158,7 +165,9 @@ void LLMediaCtrl::setBorderVisible( BOOL border_visible ) addChild( mBorder ); } if(mBorder) + { mBorder->setVisible(border_visible); + } }; //////////////////////////////////////////////////////////////////////////////// @@ -241,7 +250,7 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) mMediaSource->mouseUp(x, y, mask); } - gFocusMgr.setMouseCapture( NULL ); + gFocusMgr.setMouseCapture(nullptr ); return TRUE; } @@ -286,7 +295,7 @@ BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask ) } } - gFocusMgr.setMouseCapture( NULL ); + gFocusMgr.setMouseCapture(nullptr ); return TRUE; } @@ -310,12 +319,19 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) setFocus( TRUE ); } - LLMenuGL* menu = (LLMenuGL*)mContextMenu.get(); - if (menu) + auto con_menu = (LLMenuGL*)mContextMenu.get(); + if (con_menu) { - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLMenuGL::showPopup(this,menu, x, y); + /* Singu Note: Share your toys!! + // hide/show debugging options + bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); + con_menu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); + con_menu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); + */ + + con_menu->buildDrawLabels(); + con_menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, con_menu, x, y); } return TRUE; @@ -367,7 +383,7 @@ void LLMediaCtrl::onFocusLost() if( LLEditMenuHandler::gEditMenuHandler == mMediaSource ) { // Clear focus for edit menu items - LLEditMenuHandler::gEditMenuHandler = NULL; + LLEditMenuHandler::gEditMenuHandler = nullptr; } } @@ -380,13 +396,21 @@ void LLMediaCtrl::onFocusLost() // BOOL LLMediaCtrl::postBuild () { - LLMenuGL* menu = LLUICtrlFactory::getInstance()->buildMenu("menu_media_ctrl.xml",LLMenuGL::sMenuContainer); + /*LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; + registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); + registar.add("Open.ViewSource", boost::bind(&LLMediaCtrl::onShowSource, this)); + + // stinson 05/05/2014 : use this as the parent of the context menu if the static menu + // container has yet to be created + LLView* menuParent = (gMenuHolder != nullptr) ? dynamic_cast(gMenuHolder) : dynamic_cast(this); + llassert(menuParent != NULL);*/ + auto menu = LLUICtrlFactory::getInstance()->buildMenu("menu_media_ctrl.xml",LLMenuGL::sMenuContainer); if(menu) { mContextMenu = menu->getHandle(); } - setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2)); + setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2)); return true; } @@ -453,12 +477,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) { BOOL result = FALSE; - // only accept 'printable' characters, sigh... - if (uni_char >= 32 // discard 'control' characters - && uni_char != 127) // SDL thinks this is 'delete' - yuck. + if (mMediaSource) { - if (mMediaSource) - result = mMediaSource->handleUnicodeCharHere(uni_char); + result = mMediaSource->handleUnicodeCharHere(uni_char); } if ( ! result ) @@ -469,7 +490,7 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::onVisibilityChange ( const LLSD& new_visibility ) +void LLMediaCtrl::onVisibilityChanged( const LLSD& new_visibility ) { // set state of frequent updates automatically if visibility changes if ( new_visibility.asBoolean() ) @@ -568,7 +589,7 @@ void LLMediaCtrl::clearCache() //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) +void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type, bool clean_browser) { // don't browse to anything that starts with secondlife:// or sl:// const std::string protocol1 = "secondlife://"; @@ -585,7 +606,7 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) { mCurrentNavUrl = url_in; mMediaSource->setSize(mTextureWidth, mTextureHeight); - mMediaSource->navigateTo(url_in, mime_type, mime_type.empty()); + mMediaSource->navigateTo(url_in, mime_type, mime_type.empty(), false, clean_browser); } } @@ -768,8 +789,8 @@ void LLMediaCtrl::draw() bool draw_media = false; - LLPluginClassMedia* media_plugin = NULL; - LLViewerMediaTexture* media_texture = NULL; + LLPluginClassMedia* media_plugin = nullptr; + LLViewerMediaTexture* media_texture = nullptr; if(mMediaSource && mMediaSource->hasMedia()) { @@ -806,52 +827,8 @@ void LLMediaCtrl::draw() F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth(); F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight(); - LLRect r = getRect(); - S32 width, height; - S32 x_offset = 0; - S32 y_offset = 0; - - if(mStretchToFill) - { - if(mMaintainAspectRatio) - { - F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight()); - F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); - if(media_aspect > view_aspect) - { - // max width, adjusted height - width = r.getWidth(); - height = llmin(llmax(ll_round(width / media_aspect), 0), r.getHeight()); - } - else - { - // max height, adjusted width - height = r.getHeight(); - width = llmin(llmax(ll_round(height * media_aspect), 0), r.getWidth()); - } - } - else - { - width = r.getWidth(); - height = r.getHeight(); - } - } - else - { - width = llmin(media_plugin->getWidth(), r.getWidth()); - height = llmin(media_plugin->getHeight(), r.getHeight()); - } - - x_offset = (r.getWidth() - width) / 2; - y_offset = (r.getHeight() - height) / 2; - - /*if (mIgnoreUIScale) - { - x_offset = ll_round((F32)x_offset * LLUI::getScaleFactor().mV[VX]); - y_offset = ll_round((F32)y_offset * LLUI::getScaleFactor().mV[VY]); - width = ll_round((F32)width * LLUI::getScaleFactor().mV[VX]); - height = ll_round((F32)height * LLUI::getScaleFactor().mV[VY]); - }*/ + S32 x_offset, y_offset, width, height; + calcOffsetsAndSize(&x_offset, &y_offset, &width, &height); // draw the browser gGL.setSceneBlendType(LLRender::BT_REPLACE); @@ -910,6 +887,50 @@ void LLMediaCtrl::draw() setBackgroundOpaque(background_opaque); } +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::calcOffsetsAndSize(S32 *x_offset, S32 *y_offset, S32 *width, S32 *height) +{ + const LLRect &r = getRect(); + *x_offset = *y_offset = 0; + + const auto& media_plugin = mMediaSource->getMediaPlugin(); + + if(mStretchToFill) + { + if(mMaintainAspectRatio) + { + F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight()); + F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); + if(media_aspect > view_aspect) + { + // max width, adjusted height + *width = r.getWidth(); + *height = llmin(llmax(ll_round(*width / media_aspect), 0), r.getHeight()); + } + else + { + // max height, adjusted width + *height = r.getHeight(); + *width = llmin(llmax(ll_round(*height * media_aspect), 0), r.getWidth()); + } + } + else + { + *width = r.getWidth(); + *height = r.getHeight(); + } + } + else + { + *width = llmin(media_plugin->getWidth(), r.getWidth()); + *height = llmin(media_plugin->getHeight(), r.getHeight()); + } + + *x_offset = (r.getWidth() - *width) / 2; + *y_offset = (r.getHeight() - *height) / 2; +} + //////////////////////////////////////////////////////////////////////////////// // void LLMediaCtrl::convertInputCoords(S32& x, S32& y) @@ -1013,17 +1034,24 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_CLICK_LINK_HREF: { - LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL; // retrieve the event parameters std::string url = self->getClickURL(); std::string target = self->getClickTarget(); std::string uuid = self->getClickUUID(); + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL; - LLWeb::loadURL(url, target, std::string()); + // try as slurl first + if (!LLURLDispatcher::dispatch(url, "clicked", nullptr, mTrusted)) + { + LLWeb::loadURL(url, target, uuid); + } - //LLNotification::Params notify_params("PopupAttempt"); + // CP: removing this code because we no longer support popups so this breaks the flow. + // replaced with a bare call to LLWeb::LoadURL(...) + //LLNotification::Params notify_params; + //notify_params.name = "PopupAttempt"; //notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID); - //notify_params.functor(boost::bind(&LLMediaCtrl::onPopup, this, _1, _2)); + //notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2); //if (mTrusted) //{ @@ -1111,7 +1139,24 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_DEBUG_MESSAGE: { - LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL; + std::string level = self->getDebugMessageLevel(); + if (level == "debug") + { + LL_DEBUGS("Media") << self->getDebugMessageText() << LL_ENDL; + } + else if (level == "info") + { + LL_INFOS("Media") << self->getDebugMessageText() << LL_ENDL; + } + else if (level == "warn") + { + LL_WARNS("Media") << self->getDebugMessageText() << LL_ENDL; + } + else if (level == "error") + { + LL_ERRS("Media") << self->getDebugMessageText() << LL_ENDL; + } + }; break; @@ -1132,7 +1177,7 @@ std::string LLMediaCtrl::getCurrentNavUrl() return mCurrentNavUrl; } -bool LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) +void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) { if (response["open"]) { @@ -1143,7 +1188,6 @@ bool LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) // Make sure the opening instance knows its window open request was denied, so it can clean things up. LLViewerMedia::proxyWindowClosed(notification["payload"]["uuid"]); } - return FALSE; } void LLMediaCtrl::showNotification(LLNotificationPtr notify) diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 7c4c785ca..6235ee9cb 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -2,31 +2,25 @@ * @file llmediactrl.h * @brief Web browser UI control * - * $LicenseInfo:firstyear=2006&license=viewergpl$ - * - * Copyright (c) 2006-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * 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 + * Copyright (C) 2010, Linden Research, Inc. * - * 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 + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -90,7 +84,7 @@ public: // Defaults to true. void setTakeFocusOnClick( bool take_focus ); - virtual LLXMLNodePtr getXML(bool save_children = true) const; + virtual LLXMLNodePtr getXML(bool save_children = true) const override; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); // handle mouse related methods @@ -104,7 +98,7 @@ public: BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) override; // navigation - void navigateTo( std::string url_in, std::string mime_type = ""); + void navigateTo( std::string url_in, std::string mime_type = "", bool clean_browser = false); void navigateBack(); void navigateHome(); void navigateForward(); @@ -190,8 +184,11 @@ public: void convertInputCoords(S32& x, S32& y); private: - void onVisibilityChange ( const LLSD& new_visibility ); - bool onPopup(const LLSD& notification, const LLSD& response); + void calcOffsetsAndSize(S32 *x_offset, S32 *y_offset, S32 *width, S32 *height); + + private: + void onVisibilityChanged ( const LLSD& new_visibility ); + void onPopup(const LLSD& notification, const LLSD& response); const S32 mTextureDepthBytes; LLUUID mMediaTextureID; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 973ed5ccf..462302873 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1140,9 +1140,7 @@ bool idle_startup() // Load URL History File LLURLHistory::loadFile("url_history.xml"); - // Load media plugin cookies - LLViewerMedia::loadCookieFile(); - + //------------------------------------------------- // Handle startup progress screen //------------------------------------------------- diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 847e5e225..a224b2e22 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -32,9 +32,6 @@ #include "llviewerprecompiledheaders.h" -#include "llviewermedia.h" - - #include "llviewermedia.h" #include "llagent.h" @@ -45,9 +42,10 @@ #include "lldir.h" #include "lldiriterator.h" #include "llevent.h" // LLSimpleListener +#include "aifilepicker.h" +#include "llfloaterdestinations.h" #include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows. #include "llfocusmgr.h" -#include "llhttpclient.h" #include "llkeyboard.h" #include "llmarketplacefunctions.h" #include "llmediaentry.h" @@ -59,7 +57,6 @@ #include "llpanelprofile.h" #include "llparcel.h" #include "llpluginclassmedia.h" -#include "llplugincookiestore.h" #include "llurldispatcher.h" #include "lluuid.h" #include "llvieweraudio.h" @@ -78,13 +75,10 @@ #include "llwebprofile.h" #include "llwindow.h" #include "llvieweraudio.h" +#include "llhttpclient.h" -#include "aifilepicker.h" #include "llstartup.h" -#include // for SkinFolder listener -#include - std::string getProfileURL(const std::string& agent_name); /*static*/ const char* LLViewerMedia::AUTO_PLAY_MEDIA_SETTING = "ParcelMediaAutoPlayEnable"; @@ -176,18 +170,15 @@ public: : mMediaImpl(media_impl), mInitialized(false) { - if(mMediaImpl->mMimeTypeProbe != NULL) + if(mMediaImpl->mMimeProbe) { LL_ERRS() << "impl already has an outstanding responder" << LL_ENDL; } - mMediaImpl->mMimeTypeProbe = this; + mMediaImpl->mMimeProbe = this; } - ~LLMimeDiscoveryResponder() - { - disconnectOwner(); - } + ~LLMimeDiscoveryResponder() { disconnectOwner(); } private: /* virtual */ void completedHeaders() @@ -266,14 +257,14 @@ private: { if(mMediaImpl) { - if(mMediaImpl->mMimeTypeProbe != this) + if(mMediaImpl->mMimeProbe != this) { - LL_ERRS() << "internal error: mMediaImpl->mMimeTypeProbe != this" << LL_ENDL; + LL_ERRS() << "internal error: mMediaImpl->mMimeProbe != this" << LL_ENDL; } - mMediaImpl->mMimeTypeProbe = NULL; + mMediaImpl->mMimeProbe = nullptr; } - mMediaImpl = NULL; + mMediaImpl = nullptr; } @@ -342,8 +333,6 @@ public: for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie) { // *TODO: What about bad status codes? Does this destroy previous cookies? - LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie->second, mHost); - if (cookie->second.substr(0, cookie->second.find('=')) == "_my_secondlife_session") { // Set cookie for snapshot publishing. @@ -362,10 +351,9 @@ public: }; -LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL; LLURL LLViewerMedia::sOpenIDURL; std::string LLViewerMedia::sOpenIDCookie; -LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL; +LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = nullptr; static LLViewerMedia::impl_list sViewerMediaImplList; static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap; static LLTimer sMediaCreateTimer; @@ -376,8 +364,6 @@ static LLUUID sOnlyAudibleTextureID = LLUUID::null; 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) @@ -820,12 +806,6 @@ void LLViewerMedia::updateMedia(void *dummy_arg) createSpareBrowserMediaSource(); sAnyMediaShowing = false; - sUpdatedCookies = getCookieStore()->getChangedCookies(); - if(!sUpdatedCookies.empty()) - { - LL_DEBUGS() << "updated cookies will be sent to all loaded plugins: " << LL_ENDL; - LL_DEBUGS() << sUpdatedCookies << LL_ENDL; - } impl_list::iterator iter = sViewerMediaImplList.begin(); impl_list::iterator end = sViewerMediaImplList.end(); @@ -1176,63 +1156,6 @@ void LLViewerMedia::clearAllCookies() plugin->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: - // /browser_profile/cookies - // /first_last/browser_profile/cookies (note that there may be any number of these!) - // /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; - - LL_DEBUGS() << "base dir = " << base_dir << LL_ENDL; - - // The non-logged-in version is easy - target = base_dir; - target += "browser_profile"; - target += gDirUtilp->getDirDelimiter(); - target += "cookies"; - LL_DEBUGS() << "target = " << target << LL_ENDL; - if(LLFile::isfile(target)) - { - LLFile::remove(target); - } - - // the hard part: iterate over all user directories and delete the cookie file from each one - LLDirIterator dir_iter(base_dir, "*_*"); - while (dir_iter.next(filename)) - { - target = gDirUtilp->add(base_dir, filename); - gDirUtilp->append(target, "browser_profile"); - gDirUtilp->append(target, "cookies"); - LL_DEBUGS() << "target = " << target << LL_ENDL; - if(LLFile::isfile(target)) - { - LLFile::remove(target); - } - - // Other accounts may have new-style cookie files too -- delete them as well - target = gDirUtilp->add(base_dir, filename); - gDirUtilp->append(target, PLUGIN_COOKIE_FILE_NAME); - LL_DEBUGS() << "target = " << target << LL_ENDL; - if(LLFile::isfile(target)) - { - LLFile::remove(target); - } - } - - // If we have an OpenID cookie, re-add it to the cookie store. setOpenIDCookie(); } @@ -1289,128 +1212,7 @@ void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int por ///////////////////////////////////////////////////////////////////////////////////////// // 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()) - { - LL_INFOS() << "can't get path to plugin cookie file - probably not logged in yet." << LL_ENDL; - return; - } - - // open the file for reading - llifstream file(resolved_filename); - if (!file.is_open()) - { - LL_WARNS() << "can't load plugin cookies from file \"" << PLUGIN_COOKIE_FILE_NAME << "\"" << LL_ENDL; - 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; - LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); - if(plugin) - { - plugin->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()) - { - LL_INFOS() << "can't get path to plugin cookie file - probably not logged in yet." << LL_ENDL; - return; - } - - // open a file for writing - llofstream file (resolved_filename); - if (!file.is_open()) - { - LL_WARNS() << "can't open plugin cookie file \"" << PLUGIN_COOKIE_FILE_NAME << "\" for writing" << LL_ENDL; - 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 AIHTTPHeaders LLViewerMedia::getHeaders() { @@ -1427,64 +1229,120 @@ AIHTTPHeaders LLViewerMedia::getHeaders() ///////////////////////////////////////////////////////////////////////////////////////// // static +bool LLViewerMedia::parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure) +{ + std::size_t name_pos = raw_cookie.find_first_of('='); + if (name_pos != std::string::npos) + { + name = raw_cookie.substr(0, name_pos); + std::size_t value_pos = raw_cookie.find_first_of(';', name_pos); + if (value_pos != std::string::npos) + { + value = raw_cookie.substr(name_pos + 1, value_pos - name_pos - 1); + path = "/"; // assume root path for now + + httponly = true; // hard coded for now + secure = true; + + return true; + } + } + + return false; +} + void LLViewerMedia::setOpenIDCookie() { if(!sOpenIDCookie.empty()) { - // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port] - // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that. - // We therefore do it here. - std::string authority = sOpenIDURL.mAuthority; - std::string::size_type host_start = authority.find('@'); - if(host_start == std::string::npos) - { - // no username/password - host_start = 0; - } - else - { - // Hostname starts after the @. - // (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.) - ++host_start; - } - std::string::size_type host_end = authority.rfind(':'); - if((host_end == std::string::npos) || (host_end < host_start)) - { - // no port - host_end = authority.size(); - } - - getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start)); - if (gSavedSettings.getString("WebProfileURL").empty()) return; - // Do a web profile get so we can store the cookie - AIHTTPHeaders headers; - headers.addHeader("Accept", "*/*"); - headers.addHeader("Cookie", sOpenIDCookie); - headers.addHeader("User-Agent", getCurrentUserAgent()); + std::string profileUrl = getProfileURL(""); - std::string profile_url = getProfileURL(""); - LLURL raw_profile_url( profile_url.c_str() ); - - LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << LL_ENDL; - LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; - LLHTTPClient::get(profile_url, - new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), - headers); + getOpenIDCookieCoro(profileUrl); } } +/*static*/ +void LLViewerMedia::getOpenIDCookieCoro(std::string url) +{ + // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port] + // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that. + // We therefore do it here. + std::string authority = sOpenIDURL.mAuthority; + std::string::size_type hostStart = authority.find('@'); + if(hostStart == std::string::npos) + { // no username/password + hostStart = 0; + } + else + { // Hostname starts after the @. + // (If the hostname part is empty, this may put host_start at the end of the string. In that case, it will end up passing through an empty hostname, which is correct.) + ++hostStart; + } + std::string::size_type hostEnd = authority.rfind(':'); + if((hostEnd == std::string::npos) || (hostEnd < hostStart)) + { // no port + hostEnd = authority.size(); + } + + if (url.length()) + { + LLMediaCtrl* media_instance = LLFloaterDestinations::getInstance()->getChild("destination_guide_contents"); + if (media_instance) + { + std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart); + std::string cookie_name = ""; + std::string cookie_value = ""; + std::string cookie_path = ""; + bool httponly = true; + bool secure = true; + if (parseRawCookie(sOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) && + media_instance->getMediaPlugin()) + { + // MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the + // url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked. + // For now, we use the URL for the OpenID POST request since it will have the same authority + // as the domain field. + // (Feels like there must be a less dirty way to construct a URL from component LLURL parts) + // MAINT-6392 - Rider: Do not change, however, the original URI requested, since it is used further + // down. + std::string cefUrl(std::string(sOpenIDURL.mURI) + "://" + std::string(sOpenIDURL.mAuthority)); + + media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host, cookie_path, httponly, secure); + } + } + } + + // Note: Rider: MAINT-6392 - Some viewer code requires access to the my.sl.com openid cookie for such + // actions as posting snapshots to the feed. This is handled through HTTPCore rather than CEF and so + // we must learn to SHARE the cookies. + + // Do a web profile get so we can store the cookie + AIHTTPHeaders headers; + headers.addHeader("Accept", "*/*"); + headers.addHeader("Cookie", sOpenIDCookie); + headers.addHeader("User-Agent", getCurrentUserAgent()); + + LLURL raw_profile_url(url.data()); + + LL_DEBUGS("MediaAuth") << "Requesting " << url << LL_ENDL; + LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; + LLHTTPClient::get(url, + new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), + headers); +} + ///////////////////////////////////////////////////////////////////////////////////////// // static -void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token) +void LLViewerMedia::openIDSetup(const std::string &openidUrl, const std::string &openidToken) { - LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL; + LL_DEBUGS("MediaAuth") << "url = \"" << openidUrl << "\", token = \"" << openidToken << "\"" << 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()); + sOpenIDURL.init(openidUrl.c_str()); // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies. sOpenIDCookie.clear(); @@ -1496,13 +1354,13 @@ void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string headers.addHeader("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(); + size_t size = openidToken.size(); U8* data = new U8[size]; - memcpy(data, openid_token.data(), size); + memcpy(data, openidToken.data(), size); LLHTTPClient::postRaw( - openid_url, - data, + openidUrl, + data, size, new LLViewerMediaOpenIDResponder(), headers); @@ -1570,7 +1428,7 @@ void LLViewerMedia::createSpareBrowserMediaSource() // The null owner will keep the browser plugin from fully initializing // (specifically, it keeps LLPluginClassMedia from negotiating a size change, // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color) - sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0); + sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", nullptr, 0, 0, 1.0); if (!sSpareBrowserMediaSource) failedLoading = true; } } @@ -1580,7 +1438,7 @@ void LLViewerMedia::createSpareBrowserMediaSource() LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() { LLPluginClassMedia* result = sSpareBrowserMediaSource; - sSpareBrowserMediaSource = NULL; + sSpareBrowserMediaSource = nullptr; return result; }; @@ -1626,7 +1484,7 @@ std::string LLViewerMedia::getParcelAudioURL() // static void LLViewerMedia::initClass() { - gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, NULL); + gIdleCallbacks.addFunction(LLViewerMedia::updateMedia, nullptr); sTeleportFinishConnection = LLViewerParcelMgr::getInstance()-> setTeleportFinishedCallback(boost::bind(&LLViewerMedia::onTeleportFinished)); } @@ -1635,8 +1493,13 @@ void LLViewerMedia::initClass() // static void LLViewerMedia::cleanupClass() { - gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, NULL); + gIdleCallbacks.deleteFunction(LLViewerMedia::updateMedia, nullptr); sTeleportFinishConnection.disconnect(); + if (sSpareBrowserMediaSource != nullptr) + { + delete sSpareBrowserMediaSource; + sSpareBrowserMediaSource = nullptr; + } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1645,6 +1508,8 @@ void LLViewerMedia::onTeleportFinished() { // On teleport, clear this setting (i.e. set it to true) gSavedSettings.setBOOL("MediaTentativeAutoPlay", true); + + LLViewerMediaImpl::sMimeTypesFailed.clear(); } @@ -1656,6 +1521,7 @@ void LLViewerMedia::setOnlyAudibleMediaTextureID(const LLUUID& texture_id) sForceUpdate = true; } +std::vector LLViewerMediaImpl::sMimeTypesFailed; ////////////////////////////////////////////////////////////////////////////////////////// // LLViewerMediaImpl ////////////////////////////////////////////////////////////////////////////////////////// @@ -1665,6 +1531,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, U8 media_auto_scale, U8 media_loop) : + mZoomFactor(1.0), mMovieImageHasMips(false), mMediaWidth(media_width), mMediaHeight(media_height), @@ -1685,6 +1552,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mNavigateServerRequest(false), mMediaSourceFailed(false), mRequestedVolume(1.0f), + mPreviousVolume(1.0f), mIsMuted(false), mNeedsMuteCheck(false), mPreviousMediaState(MEDIA_NONE), @@ -1693,16 +1561,16 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id, mIsParcelMedia(false), mProximity(-1), mProximityDistance(0.0f), - mMimeTypeProbe(NULL), mMediaAutoPlay(false), mInNearbyMediaList(false), mClearCache(false), mBackgroundColor(LLColor4::white), mNavigateSuspended(false), mNavigateSuspendedDeferred(false), - mIsUpdated(false), mTrustedBrowser(false), - mZoomFactor(1.0) + mCleanBrowser(false), + mIsUpdated(false), + mMimeProbe(nullptr) { // Set up the mute list observer if it hasn't been set up already. @@ -1770,7 +1638,7 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) mMimeType = mime_type; } - return (mPluginBase != NULL); + return (mPluginBase != nullptr); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1825,15 +1693,16 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) ////////////////////////////////////////////////////////////////////////////////////////// /*static*/ -LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target) +LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target, bool clean_browser) { std::string plugin_basename = LLMIMETypes::implType(media_type); - LLPluginClassMedia* media_source = NULL; + LLPluginClassMedia* media_source = nullptr; // HACK: we always try to keep a spare running webkit plugin around to improve launch times. // If a spare was already created before PluginAttachDebuggerToPlugins was set, don't use it. + // Do not use a spare if launching with full viewer control (e.g. Facebook, Twitter and few others) if ((plugin_basename == "media_plugin_cef") && - !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins")) + !gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins") && !clean_browser) { media_source = LLViewerMedia::getSpareBrowserMediaSource(); if(media_source) @@ -1841,6 +1710,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ media_source->setOwner(owner); media_source->setTarget(target); media_source->setSize(default_width, default_height); + media_source->setZoomFactor(zoom_factor); return media_source; } @@ -1860,7 +1730,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ std::string user_data_path_cookies = gDirUtilp->getOSUserAppDir(); user_data_path_cookies += gDirUtilp->getDirDelimiter(); - std::string user_data_path_logs = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + std::string user_data_path_cef_log = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "cef_log.txt"); // Fix for EXT-5960 - make browser profile specific to user (cache, cookies etc.) // If the linden username returned is blank, that can only mean we are @@ -1870,7 +1740,6 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ std::string linden_user_dir = gDirUtilp->getLindenUserDir(); if ( ! linden_user_dir.empty() ) { - // gDirUtilp->getLindenUserDir() is whole path, not just Linden name user_data_path_cookies = linden_user_dir; user_data_path_cookies += gDirUtilp->getDirDelimiter(); }; @@ -1888,24 +1757,28 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ else { media_source = new LLPluginClassMedia(owner); + media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getS32("BrowserProxyType"), + gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"), + gSavedSettings.getString("BrowserProxyUsername"), gSavedSettings.getString("BrowserProxyPassword")); media_source->setSize(default_width, default_height); - media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies, user_data_path_logs); + media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies, user_data_path_cef_log); media_source->setLanguageCode(LLUI::getLanguage()); + media_source->setZoomFactor(zoom_factor); // collect 'cookies enabled' setting from prefs and send to embedded browser bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" ); - media_source->cookies_enabled( cookies_enabled ); + media_source->cookies_enabled( cookies_enabled || clean_browser); // collect 'plugins enabled' setting from prefs and send to embedded browser bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" ); - media_source->setPluginsEnabled( plugins_enabled ); + media_source->setPluginsEnabled( plugins_enabled || clean_browser); // collect 'javascript enabled' setting from prefs and send to embedded browser bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); - media_source->setJavascriptEnabled( javascript_enabled ); + media_source->setJavascriptEnabled( javascript_enabled || clean_browser); bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); - media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled ); + media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled || clean_browser); // need to set agent string here before instance created media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent()); @@ -1926,12 +1799,18 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL; - /* There is a reason why ^^ is ONCE - LLSD args; - args["MIME_TYPE"] = media_type; - LLNotificationsUtil::add("NoPlugin", args); - */ - return NULL; + + if(gAgent.isInitialized()) + { + if (std::find(sMimeTypesFailed.begin(), sMimeTypesFailed.end(), media_type) == sMimeTypesFailed.end()) + { + LLSD args; + args["MIME_TYPE"] = media_type; + LLNotificationsUtil::add("NoPlugin", args); + sMimeTypesFailed.push_back(media_type); + } + } + return nullptr; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1943,6 +1822,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the previous media source's last set size before destroying it. mMediaWidth = mMediaSource->getSetWidth(); mMediaHeight = mMediaSource->getSetHeight(); + mZoomFactor = mMediaSource->getZoomFactor(); } // Always delete the old media impl first. @@ -1965,7 +1845,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) // Save the MIME type that really caused the plugin to load mCurrentMimeType = mMimeType; - LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mTarget); + LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight, mZoomFactor, mTarget, mCleanBrowser); if (media_source) { @@ -2098,7 +1978,7 @@ void LLViewerMediaImpl::play() LLPluginClassMedia* mMediaSource = getMediaPlugin(); // If the media source isn't there, try to initialize it and load an URL. - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { if(!initializeMedia(mMimeType)) { @@ -2211,6 +2091,20 @@ void LLViewerMediaImpl::setVolume(F32 volume) updateVolume(); } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::setMute(bool mute) +{ + if (mute) + { + mPreviousVolume = mRequestedVolume; + setVolume(0.0); + } + else + { + setVolume(mPreviousVolume); + } +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::updateVolume() { @@ -2620,7 +2514,7 @@ void LLViewerMediaImpl::unload() } ////////////////////////////////////////////////////////////////////////////////////////// -void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request) +void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request, bool clean_browser) { if (url.empty()) { @@ -2639,6 +2533,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi // Always set the current URL and MIME type. mMediaURL = url; mMimeType = mime_type; + mCleanBrowser = clean_browser; // Clear the current media URL, since it will no longer be correct. mCurrentMediaURL.clear(); @@ -2695,7 +2590,7 @@ void LLViewerMediaImpl::navigateInternal() return; } - if(mMimeTypeProbe != NULL) + if(mMimeProbe != nullptr) { LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL; return; @@ -2744,11 +2639,14 @@ void LLViewerMediaImpl::navigateInternal() } else if("data" == scheme || "file" == scheme || "about" == scheme) { - // FIXME: figure out how to really discover the type for these schemes - // We use "data" internally for a text/html url for loading the login screen - if(initializeMedia("text/html")) + if ("blank" != uri.hostName()) { - loadURI(); + // FIXME: figure out how to really discover the type for these schemes + // We use "data" internally for a text/html url for loading the login screen + if(initializeMedia("text/html")) + { + loadURI(); + } } } else @@ -2788,36 +2686,37 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) if (mMediaSource) { - // FIXME: THIS IS SO WRONG. - // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... - if (MASK_CONTROL & mask && key != KEY_LEFT && key != KEY_RIGHT && key != KEY_HOME && key != KEY_END) + switch (mask) { - result = true; - } + case MASK_CONTROL: + { + result = true; // Avoid redundant code, set false for default. + switch(key) + { + // FIXME: THIS IS SO WRONG. + // Menu keys should be handled by the menu system and not passed to UI elements, but this is how LLTextEditor and LLLineEditor do it... + case KEY_LEFT: case KEY_RIGHT: case KEY_HOME: case KEY_END: break; - if( MASK_CONTROL & mask ) - { - if('C' == key) + case 'C': mMediaSource->copy(); break; + case 'V': mMediaSource->paste(); break; + case 'X': mMediaSource->cut(); break; + + default: result = false; break; + } + break; + } + case MASK_SHIFT|MASK_CONTROL: + if (key == 'I') { - mMediaSource->copy(); - result = true; - } - else if('V' == key) - { - mMediaSource->paste(); - result = true; - } - else if('X' == key) - { - mMediaSource->cut(); + mMediaSource->showWebInspector(true); result = true; } + break; } // Singu Note: At the very least, let's allow the login menu to function extern LLMenuBarGL* gLoginMenuBarView; - if (gLoginMenuBarView && gLoginMenuBarView->getVisible() && gLoginMenuBarView->handleAcceleratorKey(key, mask)) - return true; + result = result || (gLoginMenuBarView && gLoginMenuBarView->getVisible() && gLoginMenuBarView->handleAcceleratorKey(key, mask)); if(!result) { @@ -2825,7 +2724,7 @@ bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask) result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN, key, mask, native_key_data); } } - + return result; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2918,7 +2817,7 @@ void LLViewerMediaImpl::update() { // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. } - else if(mMimeTypeProbe != NULL) + else if(mMimeProbe != nullptr) { // this media source is doing a MIME type probe -- don't try loading it again. } @@ -3359,6 +3258,13 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; + case LLViewerMediaObserver::MEDIA_EVENT_FILE_DOWNLOAD: + { + //llinfos << "Media event - file download requested - filename is " << self->getFileDownloadFilename() << llendl; + LLNotificationsUtil::add("MediaFileDownloadUnsupported"); + } + break; + case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN: { LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL; @@ -3457,7 +3363,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; - case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST: { LLNotification::Params auth_request_params("AuthRequest"); @@ -3513,6 +3418,32 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; + case MEDIA_EVENT_DEBUG_MESSAGE: + { + std::string level = plugin->getDebugMessageLevel(); + if (level == "debug") + { + LL_DEBUGS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else if (level == "info") + { + LL_INFOS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else if (level == "warn") + { + LL_WARNS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else if (level == "error") + { + LL_ERRS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + else + { + LL_INFOS("Media") << plugin->getDebugMessageText() << LL_ENDL; + } + }; + break; + default: break; } @@ -3526,9 +3457,46 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla //////////////////////////////////////////////////////////////////////////////// // virtual -void LLViewerMediaImpl::handleCookieSet(LLPluginClassMedia* self, const std::string &cookie) +void +LLViewerMediaImpl::undo() { - LLViewerMedia::getCookieStore()->setCookies(cookie); + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->undo(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canUndo() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canUndo(); + else + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::redo() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->redo(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canRedo() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canRedo(); + else + return FALSE; } //////////////////////////////////////////////////////////////////////////////// @@ -3597,6 +3565,50 @@ LLViewerMediaImpl::canPaste() const return FALSE; } +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::doDelete() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->doDelete(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canDoDelete() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canDoDelete(); + else + return FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +void +LLViewerMediaImpl::selectAll() +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + mMediaSource->selectAll(); +} + +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL +LLViewerMediaImpl::canSelectAll() const +{ + LLPluginClassMedia* mMediaSource = getMediaPlugin(); + if (mMediaSource) + return mMediaSource->canSelectAll(); + else + return FALSE; +} + void LLViewerMediaImpl::setUpdated(BOOL updated) { mIsUpdated = updated ; @@ -3614,7 +3626,7 @@ void LLViewerMediaImpl::calculateInterest() LL_RECORD_BLOCK_TIME(FTM_MEDIA_CALCULATE_INTEREST); LLViewerMediaTexture* texture = LLViewerTextureManager::findMediaTexture( mTextureId ); - if(texture != NULL) + if(texture != nullptr) { mInterest = texture->getMaxVirtualSize(); } @@ -3849,16 +3861,16 @@ void LLViewerMediaImpl::setNavigateSuspended(bool suspend) void LLViewerMediaImpl::cancelMimeTypeProbe() { - if(mMimeTypeProbe != NULL) + if(mMimeProbe) { // There doesn't seem to be a way to actually cancel an outstanding request. // Simulate it by telling the LLMimeDiscoveryResponder not to write back any results. - mMimeTypeProbe->cancelRequest(); + mMimeProbe->cancelRequest(); - // The above should already have set mMimeTypeProbe to NULL. - if(mMimeTypeProbe != NULL) + // The above should already have set mMimeProbe to nullptr. + if (mMimeProbe) { - LL_ERRS() << "internal error: mMimeTypeProbe is not NULL after cancelling request." << LL_ENDL; + LL_ERRS() << "internal error: mMimeProbe is not nullptr after cancelling request." << LL_ENDL; } } } @@ -3891,7 +3903,7 @@ const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const LLVOVolume *LLViewerMediaImpl::getSomeObject() { - LLVOVolume *result = NULL; + LLVOVolume *result = nullptr; std::list< LLVOVolume* >::iterator iter = mObjectList.begin() ; if(iter != mObjectList.end()) @@ -4001,13 +4013,13 @@ bool LLViewerMediaImpl::isObjectAttachedToAnotherAvatar(LLVOVolume *obj) bool result = false; LLXform *xform = obj; // Walk up parent chain - while (NULL != xform) + while (nullptr != xform) { LLViewerObject *object = dynamic_cast (xform); - if (NULL != object) + if (nullptr != object) { LLVOAvatar *avatar = object->asAvatar(); - if ((NULL != avatar) && (avatar != gAgentAvatarp)) + if ((nullptr != avatar) && (avatar != gAgentAvatarp)) { result = true; break; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 0a3485ccf..14dc08fae 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -2,31 +2,25 @@ * @file llviewermedia.h * @brief Client interface to the media engine * - * $LicenseInfo:firstyear=2007&license=viewergpl$ - * - * Copyright (c) 2007-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * 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 + * Copyright (C) 2010, Linden Research, Inc. * - * 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 + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * 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. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -46,7 +40,6 @@ #include "llnotificationptr.h" #include "llurl.h" - #include "llviewerpluginmanager.h" class LLViewerMediaImpl; @@ -55,7 +48,6 @@ class LLViewerMediaTexture; class LLMediaEntry; class LLVOVolume; class LLMimeDiscoveryResponder; -class LLPluginCookieStore; typedef LLPointer viewer_media_t; /////////////////////////////////////////////////////////////////////////////// @@ -111,10 +103,14 @@ public: // Is any media currently "showing"? Includes Parcel Media. Does not include media in the UI. static bool isAnyMediaShowing(); + // Shows if any media is playing, counts visible non time based media as playing. Does not include media in the UI. + static bool isAnyMediaPlaying(); // Set all media enabled or disabled, depending on val. Does not include media in the UI. static void setAllMediaEnabled(bool val); + // Set all media paused(stopped for non time based) or playing, depending on val. Does not include media in the UI. + static void setAllMediaPaused(bool val); - static void updateMedia(void* dummy_arg = NULL); + static void updateMedia(void* dummy_arg = nullptr); static void initClass(); static void cleanupClass(); @@ -151,13 +147,6 @@ public: // Set the proxy config for all loaded plugins static void setProxyConfig(bool enable, const std::string &host, int port); - static LLPluginCookieStore *getCookieStore(); - static void loadCookieFile(); - static void saveCookieFile(); - static void addCookie(const std::string &name, const std::string &value, const std::string &domain, const LLDate &expires, const std::string &path = std::string("/"), bool secure = false ); - static void addSessionCookie(const std::string &name, const std::string &value, const std::string &domain, const std::string &path = std::string("/"), bool secure = false ); - static void removeCookie(const std::string &name, const std::string &domain, const std::string &path = std::string("/") ); - static void openIDSetup(const std::string &openid_url, const std::string &openid_token); static void openIDCookieResponse(const std::string &cookie); @@ -172,10 +161,12 @@ public: static class AIHTTPHeaders getHeaders(); private: + static bool parseRawCookie(const std::string raw_cookie, std::string& name, std::string& value, std::string& path, bool& httponly, bool& secure); static void setOpenIDCookie(); static void onTeleportFinished(); - - static LLPluginCookieStore *sCookieStore; + + static void getOpenIDCookieCoro(std::string url); + static LLURL sOpenIDURL; static std::string sOpenIDCookie; static LLPluginClassMedia* sSpareBrowserMediaSource; @@ -201,7 +192,7 @@ public: ~LLViewerMediaImpl(); // Override inherited version from LLViewerMediaEventEmitter - virtual void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event); + void emitEvent(LLPluginClassMedia* self, LLViewerMediaObserver::EMediaEvent event) override; void createMediaSource(); void destroyMediaSource(); @@ -223,6 +214,7 @@ public: void skipBack(F32 step_scale); void skipForward(F32 step_scale); void setVolume(F32 volume); + void setMute(bool mute); void updateVolume(); F32 getVolume(); void focus(bool focus); @@ -244,7 +236,7 @@ public: void navigateReload(); void navigateHome(); void unload(); - void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false); + void navigateTo(const std::string& url, const std::string& mime_type = "", bool rediscover_type = false, bool server_request = false, bool clean_browser = false); void navigateInternal(); void navigateStop(); bool handleKeyHere(KEY key, MASK mask); @@ -301,7 +293,7 @@ public: void setTarget(const std::string& target) { mTarget = target; } // utility function to create a ready-to-use media instance from a desired media type. - static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target = LLStringUtil::null); + static LLPluginClassMedia* newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, F64 zoom_factor, const std::string target = LLStringUtil::null, bool clean_browser = false); // Internally set our desired browser user agent string, including // the Second Life version and skin name. Used because we can @@ -313,40 +305,51 @@ public: static bool handleSkinCurrentChanged(const LLSD& newvalue); // need these to handle mouseup... - /*virtual*/ void onMouseCaptureLost(); - /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + /*virtual*/ void onMouseCaptureLost() override; + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask) override; // Grr... the only thing I want as an LLMouseHandler are the onMouseCaptureLost and handleMouseUp calls. // Sadly, these are all pure virtual, so I have to supply implementations here: - /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE; }; - /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) { return FALSE; }; - /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) { return FALSE; }; - /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) {return FALSE; }; - /*virtual*/ const std::string& getName() const; - /*virtual*/ BOOL isView() const { return FALSE; }; + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks) override { return FALSE; }; + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) override { return FALSE; }; + /*virtual*/ BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask) override { return FALSE; }; + /*virtual*/ BOOL handleMiddleMouseUp(S32 x, S32 y, MASK mask) override {return FALSE; }; + /*virtual*/ const std::string& getName() const override; + /*virtual*/ BOOL isView() const override { return FALSE; }; - /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {}; - /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const {}; - /*virtual*/ BOOL hasMouseCapture() { return gFocusMgr.getMouseCapture() == this; }; + /*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const override {}; + /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const override {}; + /*virtual*/ BOOL hasMouseCapture() override { return gFocusMgr.getMouseCapture() == this; }; // Inherited from LLPluginClassMediaOwner - /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent); - /*virtual*/ void handleCookieSet(LLPluginClassMedia* self, const std::string &cookie); + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent) override; // LLEditMenuHandler overrides - /*virtual*/ void cut(); - /*virtual*/ BOOL canCut() const; + /*virtual*/ void undo() override; + /*virtual*/ BOOL canUndo() const override; - /*virtual*/ void copy(); - /*virtual*/ BOOL canCopy() const; + /*virtual*/ void redo() override; + /*virtual*/ BOOL canRedo() const override; - /*virtual*/ void paste(); - /*virtual*/ BOOL canPaste() const; + /*virtual*/ void cut() override; + /*virtual*/ BOOL canCut() const override; + + /*virtual*/ void copy() override; + /*virtual*/ BOOL canCopy() const override; + + /*virtual*/ void paste() override; + /*virtual*/ BOOL canPaste() const override; + + /*virtual*/ void doDelete() override; + /*virtual*/ BOOL canDoDelete() const override; + + /*virtual*/ void selectAll() override; + /*virtual*/ BOOL canSelectAll() const override; void addObject(LLVOVolume* obj) ; void removeObject(LLVOVolume* obj) ; @@ -466,6 +469,7 @@ private: bool mNavigateServerRequest; bool mMediaSourceFailed; F32 mRequestedVolume; + F32 mPreviousVolume; bool mIsMuted; bool mNeedsMuteCheck; int mPreviousMediaState; @@ -475,7 +479,6 @@ private: S32 mProximity; F64 mProximityDistance; F64 mProximityCamera; - LLMimeDiscoveryResponder *mMimeTypeProbe; bool mMediaAutoPlay; std::string mMediaEntryURL; bool mInNearbyMediaList; // used by LLPanelNearbyMedia::refreshList() for performance reasons @@ -486,11 +489,15 @@ private: bool mTrustedBrowser; std::string mTarget; LLNotificationPtr mNotification; + bool mCleanBrowser; // force the creation of a clean browsing target with full options enabled + static std::vector sMimeTypesFailed; private: BOOL mIsUpdated ; std::list< LLVOVolume* > mObjectList ; + LLMimeDiscoveryResponder* mMimeProbe; + private: LLViewerMediaTexture *updatePlaceholderImage(); }; diff --git a/indra/newview/llviewermedia_streamingaudio.cpp b/indra/newview/llviewermedia_streamingaudio.cpp index de90c8571..5e72ab348 100644 --- a/indra/newview/llviewermedia_streamingaudio.cpp +++ b/indra/newview/llviewermedia_streamingaudio.cpp @@ -162,7 +162,7 @@ LLPluginClassMedia* LLStreamingAudio_MediaPlugins::initializeMedia(const std::st { LLPluginClassMediaOwner* owner = NULL; S32 default_size = 1; // audio-only - be minimal, doesn't matter - LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size); + LLPluginClassMedia* media_source = LLViewerMediaImpl::newSourceFromMediaType(media_type, owner, default_size, default_size, 1.0); if (media_source) { diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index 51fe6c6d6..768561e19 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -1586,6 +1586,19 @@ Unable to download file fail + + + confirm + You have requested a file download, which is not supported within [SECOND_LIFE]. + + +