diff options
27 files changed, 234 insertions, 1568 deletions
@@ -534,3 +534,4 @@ abcab37e1b29414ab8c03af9ca2ab489d809788a 5.0.7-release ad0e15543836d64d6399d28b32852510435e344a 5.1.0-release 26d9e9bb166a9a417f35b1863223a597af8185fd 5.1.1-release 2eb917875efdfe920680b9049302d0f03721245d 5.1.2-release +7c00e5b6cb3d95712e9d8e29277c805bca2bda90 5.1.3-release diff --git a/autobuild.xml b/autobuild.xml index c63b7ff9c6..cea8b51ec5 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -556,9 +556,9 @@ <key>archive</key> <map> <key>hash</key> - <string>bbdea742f2a89bcd6360e61e01d6be93</string> + <string>118987b1a5b56214cfdbd0c763e180da</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/8207/32592/dullahan-1.1.820_3.3071.1637.gcb6cf75-darwin64-508196.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15127/97748/dullahan-1.1.1080_3.3325.1750.gaabe4c4-darwin64-513449.tar.bz2</string> </map> <key>name</key> <string>darwin64</string> @@ -568,9 +568,9 @@ <key>archive</key> <map> <key>hash</key> - <string>31e11a74e0d3f1e5e4036cb5fea8d944</string> + <string>2ecc71350b30a1057091b9cd7af18b1c</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/8209/32599/dullahan-1.1.820_3.3071.1634.g9cc59c8-windows-508196.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15128/97755/dullahan-1.1.1080_3.3325.1750.gaabe4c4-windows-513449.tar.bz2</string> </map> <key>name</key> <string>windows</string> @@ -580,16 +580,16 @@ <key>archive</key> <map> <key>hash</key> - <string>f965d244e7921c06ee79b68a4abcea3b</string> + <string>2ed3e49388514dafb907c59a209d580e</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/8208/32602/dullahan-1.1.820_3.3071.1634.g9cc59c8-windows64-508196.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15129/97760/dullahan-1.1.1080_3.3325.1750.gaabe4c4-windows64-513449.tar.bz2</string> </map> <key>name</key> <string>windows64</string> </map> </map> <key>version</key> - <string>1.1.820_3.3071.1634.g9cc59c8</string> + <string>1.1.1080_3.3325.1750.gaabe4c4</string> </map> <key>elfio</key> <map> @@ -3260,9 +3260,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>f1248b6692dcbb1a42db87ca8d9fed93</string> + <string>4aefe12a3825d1b4b8370986d84792a2</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/13982/87166/viewer_manager-1.0.512801-darwin64-512801.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15295/98583/viewer_manager-1.0.513540-darwin64-513540.tar.bz2</string> </map> <key>name</key> <string>darwin64</string> @@ -3284,9 +3284,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>c174ecc0893f8c193571b1dc80b823ad</string> + <string>db96bc8a83e6577d31657586100bfc35</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/13983/87172/viewer_manager-1.0.512801-windows-512801.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/15298/98589/viewer_manager-1.0.513540-windows-513540.tar.bz2</string> </map> <key>name</key> <string>windows</string> @@ -3297,7 +3297,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>source_type</key> <string>hg</string> <key>version</key> - <string>1.0.512801</string> + <string>1.0.513540</string> </map> <key>vlc-bin</key> <map> @@ -3316,9 +3316,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>c5e6d9440e3a4a12102dd2bbb703963e</string> + <string>e5635e173c75dc0675b48ab5f5e4868b</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/2225/4736/vlc_bin-2.2.4.502214-darwin64-502214.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12143/71451/vlc_bin-2.2.8.511703-darwin64-511703.tar.bz2</string> </map> <key>name</key> <string>darwin64</string> @@ -3340,9 +3340,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>dc37f7cc77a62891bb9ae46c9e19f95e</string> + <string>add560654a53cb1c554044a4fac3c718</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1219/2834/vlc_bin-2.2.4.501207-windows-501207.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12144/71458/vlc_bin-2.2.8.511703-windows-511703.tar.bz2</string> </map> <key>name</key> <string>windows</string> @@ -3352,16 +3352,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string> <key>archive</key> <map> <key>hash</key> - <string>148ee599afeba9794de14ca433389504</string> + <string>94bf04b49acc1e1bf2c06e2232f8a083</string> <key>url</key> - <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/1218/2829/vlc_bin-2.2.4.501207-windows64-501207.tar.bz2</string> + <string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/12145/71463/vlc_bin-2.2.8.511703-windows64-511703.tar.bz2</string> </map> <key>name</key> <string>windows64</string> </map> </map> <key>version</key> - <string>2.2.4.502214</string> + <string>2.2.8.511703</string> </map> <key>xmlrpc-epi</key> <map> diff --git a/indra/llplugin/CMakeLists.txt b/indra/llplugin/CMakeLists.txt index 129efeb529..5cc129a267 100644 --- a/indra/llplugin/CMakeLists.txt +++ b/indra/llplugin/CMakeLists.txt @@ -29,7 +29,6 @@ include_directories(SYSTEM set(llplugin_SOURCE_FILES llpluginclassmedia.cpp - llplugincookiestore.cpp llplugininstance.cpp llpluginmessage.cpp llpluginmessagepipe.cpp @@ -43,7 +42,6 @@ set(llplugin_HEADER_FILES llpluginclassmedia.h llpluginclassmediaowner.h - llplugincookiestore.h llplugininstance.h llpluginmessage.h llpluginmessageclasses.h @@ -70,20 +68,3 @@ add_library (llplugin ${llplugin_SOURCE_FILES}) add_subdirectory(slplugin) -# Add tests -if (LL_TESTS) - include(LLAddBuildTest) - # UNIT TESTS - SET(llplugin_TEST_SOURCE_FILES - llplugincookiestore.cpp - ) - - # llplugincookiestore has a dependency on curl, so we need to link the curl library into the test. - set_source_files_properties( - llplugincookiestore.cpp - PROPERTIES - LL_TEST_ADDITIONAL_LIBRARIES "${CURL_LIBRARIES};${NGHTTP2_LIBRARIES}" - ) - - LL_ADD_PROJECT_UNIT_TESTS(llplugin "${llplugin_TEST_SOURCE_FILES}") -endif (LL_TESTS) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 680017204c..78eb6e75bb 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -31,6 +31,9 @@ #include "llpluginclassmedia.h" #include "llpluginmessageclasses.h" +#include "llcontrol.h" + +extern LLControlGroup gSavedSettings; static int LOW_PRIORITY_TEXTURE_SIZE_DEFAULT = 256; @@ -792,15 +795,22 @@ F64 LLPluginClassMedia::getCPUUsage() return result; } -void LLPluginClassMedia::sendPickFileResponse(const std::string &file) +void LLPluginClassMedia::sendPickFileResponse(const std::vector<std::string> files) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response"); - message.setValue("file", file); if(mPlugin && mPlugin->isBlocked()) { // If the plugin sent a blocking pick-file request, the response should unblock it. message.setValueBoolean("blocking_response", true); } + + LLSD file_list = LLSD::emptyArray(); + for (std::vector<std::string>::const_iterator in_iter = files.begin(); in_iter != files.end(); ++in_iter) + { + file_list.append(LLSD::String(*in_iter)); + } + message.setValueLLSD("file_list", file_list); + sendMessage(message); } @@ -836,11 +846,17 @@ void LLPluginClassMedia::paste() sendMessage(message); } -void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies) +void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache, + const std::string &user_data_path_cookies, + const std::string &user_data_path_cef_log) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_user_data_path"); message.setValue("cache_path", user_data_path_cache); message.setValue("cookies_path", user_data_path_cookies); + message.setValue("cef_log_file", user_data_path_cef_log); + + bool cef_verbose_log = gSavedSettings.getBOOL("CefVerboseLog"); + message.setValueBoolean("cef_verbose_log", cef_verbose_log); sendMessage(message); } @@ -1090,6 +1106,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) } else if(message_name == "pick_file") { + mIsMultipleFilePick = message.getValueBoolean("multiple_files"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST); } else if(message_name == "auth_request") @@ -1151,7 +1168,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mClickURL = message.getValue("uri"); mClickTarget = message.getValue("target"); - mClickUUID = message.getValue("uuid"); + + // need a link to have a UUID that identifies it to a system further + // upstream - plugin could make it but we have access to LLUUID here + // so why don't we use it + mClickUUID = LLUUID::generateNewID().asString(); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF); } else if(message_name == "click_nofollow") @@ -1166,13 +1188,6 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mStatusCode = message.getValueS32("status_code"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE); } - else if(message_name == "cookie_set") - { - if(mOwner) - { - mOwner->handleCookieSet(this, message.getValue("cookie")); - } - } else if(message_name == "close_request") { mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST); @@ -1287,16 +1302,9 @@ void LLPluginClassMedia::clear_cookies() sendMessage(message); } -void LLPluginClassMedia::set_cookies(const std::string &cookies) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies"); - message.setValue("cookies", cookies); - sendMessage(message); -} - -void LLPluginClassMedia::enable_cookies(bool enable) +void LLPluginClassMedia::cookies_enabled(bool enable) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "enable_cookies"); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "cookies_enabled"); message.setValueBoolean("enable", enable); sendMessage(message); } diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 3b0739d044..3b3075c6bd 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -176,7 +176,7 @@ public: F64 getCPUUsage(); - void sendPickFileResponse(const std::string &file); + void sendPickFileResponse(const std::vector<std::string> files); void sendAuthResponse(bool ok, const std::string &username, const std::string &password); @@ -195,7 +195,7 @@ public: bool canPaste() const { return mCanPaste; }; // These can be called before init(), and they will be queued and sent before the media init message. - void setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies); + void setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies, const std::string &user_data_path_cef_log); void setLanguageCode(const std::string &language_code); void setPluginsEnabled(const bool enabled); void setJavascriptEnabled(const bool enabled); @@ -210,7 +210,7 @@ public: void clear_cache(); void clear_cookies(); void set_cookies(const std::string &cookies); - void enable_cookies(bool enable); + void cookies_enabled(bool enable); void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0); void browse_stop(); void browse_reload(bool ignore_cache = false); @@ -277,6 +277,9 @@ public: std::string getAuthURL() const { return mAuthURL; }; std::string getAuthRealm() const { return mAuthRealm; }; + // These are valid during MEDIA_EVENT_PICK_FILE_REQUEST + bool getIsMultipleFilePick() const { return mIsMultipleFilePick; } + // These are valid during MEDIA_EVENT_LINK_HOVERED std::string getHoverText() const { return mHoverText; }; std::string getHoverLink() const { return mHoverLink; }; @@ -435,6 +438,7 @@ protected: std::string mHoverText; std::string mHoverLink; std::string mFileDownloadFilename; + bool mIsMultipleFilePick; ///////////////////////////////////////// // media_time class diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index 391c23d883..89f55eaf71 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -1,4 +1,4 @@ -/** +/** * @file llpluginclassmediaowner.h * @brief LLPluginClassMedia handles interaction with a plugin which knows about the "media" message class. * @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. - * + * * 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. - * + * * 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. - * + * * 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$ * @endcond @@ -34,18 +34,17 @@ #include <queue> class LLPluginClassMedia; -class LLPluginCookieStore; class LLPluginClassMediaOwner { public: typedef enum { - MEDIA_EVENT_CONTENT_UPDATED, // contents/dirty rect have updated + MEDIA_EVENT_CONTENT_UPDATED, // contents/dirty rect have updated MEDIA_EVENT_TIME_DURATION_UPDATED, // current time and/or duration have updated MEDIA_EVENT_SIZE_CHANGED, // media size has changed MEDIA_EVENT_CURSOR_CHANGED, // plugin has requested a cursor change - + MEDIA_EVENT_NAVIGATE_BEGIN, // browser has begun navigation MEDIA_EVENT_NAVIGATE_COMPLETE, // browser has finished navigation MEDIA_EVENT_PROGRESS_UPDATED, // browser has updated loading progress @@ -58,8 +57,8 @@ public: MEDIA_EVENT_CLOSE_REQUEST, // The plugin requested its window be closed (currently hooked up to javascript window.close in webkit) MEDIA_EVENT_PICK_FILE_REQUEST, // The plugin wants the user to pick a file MEDIA_EVENT_GEOMETRY_CHANGE, // The plugin requested its window geometry be changed (per the javascript window interface) - - MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch + + MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch MEDIA_EVENT_PLUGIN_FAILED, // The plugin died unexpectedly MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog @@ -69,9 +68,9 @@ public: MEDIA_EVENT_DEBUG_MESSAGE, // plugin sending back debug information for host to process MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin - + } EMediaEvent; - + typedef enum { MEDIA_NONE, // Uninitialized -- no useful state @@ -81,12 +80,11 @@ public: MEDIA_PLAYING, // playing (only for time-based media) MEDIA_PAUSED, // paused (only for time-based media) MEDIA_DONE // finished playing (only for time-based media) - + } EMediaStatus; - + virtual ~LLPluginClassMediaOwner() {}; virtual void handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent /*event*/) {}; - virtual void handleCookieSet(LLPluginClassMedia* /*self*/, const std::string &/*cookie*/) {}; }; #endif // LL_LLPLUGINCLASSMEDIAOWNER_H diff --git a/indra/llplugin/llplugincookiestore.cpp b/indra/llplugin/llplugincookiestore.cpp deleted file mode 100644 index a5d717389d..0000000000 --- a/indra/llplugin/llplugincookiestore.cpp +++ /dev/null @@ -1,689 +0,0 @@ -/** - * @file llplugincookiestore.cpp - * @brief LLPluginCookieStore provides central storage for http cookies used by plugins - * - * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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. - * - * 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. - * - * 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$ - * @endcond - */ - -#include "linden_common.h" -#include "llstl.h" -#include "indra_constants.h" - -#include "llplugincookiestore.h" -#include <iostream> - -// for curl_getdate() (apparently parsing RFC 1123 dates is hard) -#include <curl/curl.h> - -LLPluginCookieStore::LLPluginCookieStore(): - mHasChangedCookies(false) -{ -} - - -LLPluginCookieStore::~LLPluginCookieStore() -{ - clearCookies(); -} - - -LLPluginCookieStore::Cookie::Cookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end): - mCookie(s, cookie_start, cookie_end - cookie_start), - mNameStart(0), mNameEnd(0), - mValueStart(0), mValueEnd(0), - mDomainStart(0), mDomainEnd(0), - mPathStart(0), mPathEnd(0), - mDead(false), mChanged(true) -{ -} - -LLPluginCookieStore::Cookie *LLPluginCookieStore::Cookie::createFromString(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, const std::string &host) -{ - Cookie *result = new Cookie(s, cookie_start, cookie_end); - - if(!result->parse(host)) - { - delete result; - result = NULL; - } - - return result; -} - -std::string LLPluginCookieStore::Cookie::getKey() const -{ - std::string result; - if(mDomainEnd > mDomainStart) - { - result += mCookie.substr(mDomainStart, mDomainEnd - mDomainStart); - } - result += ';'; - if(mPathEnd > mPathStart) - { - result += mCookie.substr(mPathStart, mPathEnd - mPathStart); - } - result += ';'; - result += mCookie.substr(mNameStart, mNameEnd - mNameStart); - return result; -} - -std::string LLPluginCookieStore::Cookie::getDomain() const -{ - std::string result; - if(mDomainEnd > mDomainStart) - { - result += mCookie.substr(mDomainStart, mDomainEnd - mDomainStart); - } - return result; -} - -bool LLPluginCookieStore::Cookie::parse(const std::string &host) -{ - bool first_field = true; - - std::string::size_type cookie_end = mCookie.size(); - std::string::size_type field_start = 0; - - LL_DEBUGS("CookieStoreParse") << "parsing cookie: " << mCookie << LL_ENDL; - while(field_start < cookie_end) - { - // Finding the start of the next field requires honoring special quoting rules - // see the definition of 'quoted-string' in rfc2616 for details - std::string::size_type next_field_start = findFieldEnd(field_start); - - // The end of this field should not include the terminating ';' or any trailing whitespace - std::string::size_type field_end = mCookie.find_last_not_of("; ", next_field_start); - if(field_end == std::string::npos || field_end < field_start) - { - // This field was empty or all whitespace. Set end = start so it shows as empty. - field_end = field_start; - } - else if (field_end < next_field_start) - { - // we actually want the index of the char _after_ what 'last not of' found - ++field_end; - } - - // find the start of the actual name (skip separator and possible whitespace) - std::string::size_type name_start = mCookie.find_first_not_of("; ", field_start); - if(name_start == std::string::npos || name_start > next_field_start) - { - // Again, nothing but whitespace. - name_start = field_start; - } - - // the name and value are separated by the first equals sign - std::string::size_type name_value_sep = mCookie.find_first_of("=", name_start); - if(name_value_sep == std::string::npos || name_value_sep > field_end) - { - // No separator found, so this is a field without an = - name_value_sep = field_end; - } - - // the name end is before the name-value separator - std::string::size_type name_end = mCookie.find_last_not_of("= ", name_value_sep); - if(name_end == std::string::npos || name_end < name_start) - { - // I'm not sure how we'd hit this case... it seems like it would have to be an empty name. - name_end = name_start; - } - else if (name_end < name_value_sep) - { - // we actually want the index of the char _after_ what 'last not of' found - ++name_end; - } - - // Value is between the name-value sep and the end of the field. - std::string::size_type value_start = mCookie.find_first_not_of("= ", name_value_sep); - if(value_start == std::string::npos || value_start > field_end) - { - // All whitespace or empty value - value_start = field_end; - } - std::string::size_type value_end = mCookie.find_last_not_of("; ", field_end); - if(value_end == std::string::npos || value_end < value_start) - { - // All whitespace or empty value - value_end = value_start; - } - else if (value_end < field_end) - { - // we actually want the index of the char _after_ what 'last not of' found - ++value_end; - } - - LL_DEBUGS("CookieStoreParse") - << " field name: \"" << mCookie.substr(name_start, name_end - name_start) - << "\", value: \"" << mCookie.substr(value_start, value_end - value_start) << "\"" - << LL_ENDL; - - // See whether this field is one we know - if(first_field) - { - // The first field is the name=value pair - mNameStart = name_start; - mNameEnd = name_end; - mValueStart = value_start; - mValueEnd = value_end; - first_field = false; - } - else - { - // Subsequent fields must come from the set in rfc2109 - if(matchName(name_start, name_end, "expires")) - { - std::string date_string(mCookie, value_start, value_end - value_start); - // If the cookie contains an "expires" field, it MUST contain a parsable date. - - // HACK: LLDate apparently can't PARSE an rfc1123-format date, even though it can GENERATE one. - // The curl function curl_getdate can do this, but I'm hesitant to unilaterally introduce a curl dependency in LLDate. -#if 1 - time_t date = curl_getdate(date_string.c_str(), NULL ); - mDate.secondsSinceEpoch((F64)date); - LL_DEBUGS("CookieStoreParse") << " expire date parsed to: " << mDate.asRFC1123() << LL_ENDL; -#else - // This doesn't work (rfc1123-format dates cause it to fail) - if(!mDate.fromString(date_string)) - { - // Date failed to parse. - LL_WARNS("CookieStoreParse") << "failed to parse cookie's expire date: " << date << LL_ENDL; - return false; - } -#endif - } - else if(matchName(name_start, name_end, "domain")) - { - mDomainStart = value_start; - mDomainEnd = value_end; - } - else if(matchName(name_start, name_end, "path")) - { - mPathStart = value_start; - mPathEnd = value_end; - } - else if(matchName(name_start, name_end, "max-age")) - { - // TODO: how should we handle this? - } - else if(matchName(name_start, name_end, "secure")) - { - // We don't care about the value of this field (yet) - } - else if(matchName(name_start, name_end, "version")) - { - // We don't care about the value of this field (yet) - } - else if(matchName(name_start, name_end, "comment")) - { - // We don't care about the value of this field (yet) - } - else if(matchName(name_start, name_end, "httponly")) - { - // We don't care about the value of this field (yet) - } - else - { - // An unknown field is a parse failure - LL_WARNS("CookieStoreParse") << "unexpected field name: " << mCookie.substr(name_start, name_end - name_start) << LL_ENDL; - return false; - } - - } - - - // move on to the next field, skipping this field's separator and any leading whitespace - field_start = mCookie.find_first_not_of("; ", next_field_start); - } - - // The cookie MUST have a name - if(mNameEnd <= mNameStart) - return false; - - // If the cookie doesn't have a domain, add the current host as the domain. - if(mDomainEnd <= mDomainStart) - { - if(host.empty()) - { - // no domain and no current host -- this is a parse failure. - return false; - } - - // Figure out whether this cookie ended with a ";" or not... - std::string::size_type last_char = mCookie.find_last_not_of(" "); - if((last_char != std::string::npos) && (mCookie[last_char] != ';')) - { - mCookie += ";"; - } - - mCookie += " domain="; - mDomainStart = mCookie.size(); - mCookie += host; - mDomainEnd = mCookie.size(); - - LL_DEBUGS("CookieStoreParse") << "added domain (" << mDomainStart << " to " << mDomainEnd << "), new cookie is: " << mCookie << LL_ENDL; - } - - // If the cookie doesn't have a path, add "/". - if(mPathEnd <= mPathStart) - { - // Figure out whether this cookie ended with a ";" or not... - std::string::size_type last_char = mCookie.find_last_not_of(" "); - if((last_char != std::string::npos) && (mCookie[last_char] != ';')) - { - mCookie += ";"; - } - - mCookie += " path="; - mPathStart = mCookie.size(); - mCookie += "/"; - mPathEnd = mCookie.size(); - - LL_DEBUGS("CookieStoreParse") << "added path (" << mPathStart << " to " << mPathEnd << "), new cookie is: " << mCookie << LL_ENDL; - } - - - return true; -} - -std::string::size_type LLPluginCookieStore::Cookie::findFieldEnd(std::string::size_type start, std::string::size_type end) -{ - std::string::size_type result = start; - - if(end == std::string::npos) - end = mCookie.size(); - - bool in_quotes = false; - for(; (result < end); result++) - { - switch(mCookie[result]) - { - case '\\': - if(in_quotes) - result++; // The next character is backslash-quoted. Skip over it. - break; - case '"': - in_quotes = !in_quotes; - break; - case ';': - if(!in_quotes) - return result; - break; - } - } - - // If we got here, no ';' was found. - return end; -} - -bool LLPluginCookieStore::Cookie::matchName(std::string::size_type start, std::string::size_type end, const char *name) -{ - // NOTE: this assumes 'name' is already in lowercase. The code which uses it should be able to arrange this... - - while((start < end) && (*name != '\0')) - { - if(tolower(mCookie[start]) != *name) - return false; - - start++; - name++; - } - - // iff both strings hit the end at the same time, they're equal. - return ((start == end) && (*name == '\0')); -} - -std::string LLPluginCookieStore::getAllCookies() -{ - std::stringstream result; - writeAllCookies(result); - return result.str(); -} - -void LLPluginCookieStore::writeAllCookies(std::ostream& s) -{ - cookie_map_t::iterator iter; - for(iter = mCookies.begin(); iter != mCookies.end(); iter++) - { - // Don't return expired cookies - if(!iter->second->isDead()) - { - s << (iter->second->getCookie()) << "\n"; - } - } - -} - -std::string LLPluginCookieStore::getPersistentCookies() -{ - std::stringstream result; - writePersistentCookies(result); - return result.str(); -} - -void LLPluginCookieStore::writePersistentCookies(std::ostream& s) -{ - cookie_map_t::iterator iter; - for(iter = mCookies.begin(); iter != mCookies.end(); iter++) - { - // Don't return expired cookies or session cookies - if(!iter->second->isDead() && !iter->second->isSessionCookie()) - { - s << iter->second->getCookie() << "\n"; - } - } -} - -std::string LLPluginCookieStore::getChangedCookies(bool clear_changed) -{ - std::stringstream result; - writeChangedCookies(result, clear_changed); - - return result.str(); -} - -void LLPluginCookieStore::writeChangedCookies(std::ostream& s, bool clear_changed) -{ - if(mHasChangedCookies) - { - LL_DEBUGS() << "returning changed cookies: " << LL_ENDL; - cookie_map_t::iterator iter; - for(iter = mCookies.begin(); iter != mCookies.end(); ) - { - cookie_map_t::iterator next = iter; - next++; - - // Only return cookies marked as "changed" - if(iter->second->isChanged()) - { - s << iter->second->getCookie() << "\n"; - - LL_DEBUGS() << " " << iter->second->getCookie() << LL_ENDL; - - // If requested, clear the changed mark - if(clear_changed) - { - if(iter->second->isDead()) - { - // If this cookie was previously marked dead, it needs to be removed entirely. - delete iter->second; - mCookies.erase(iter); - } - else - { - // Not dead, just mark as not changed. - iter->second->setChanged(false); - } - } - } - - iter = next; - } - } - - if(clear_changed) - mHasChangedCookies = false; -} - -void LLPluginCookieStore::setAllCookies(const std::string &cookies, bool mark_changed) -{ - clearCookies(); - setCookies(cookies, mark_changed); -} - -void LLPluginCookieStore::readAllCookies(std::istream& s, bool mark_changed) -{ - clearCookies(); - readCookies(s, mark_changed); -} - -void LLPluginCookieStore::setCookies(const std::string &cookies, bool mark_changed) -{ - std::string::size_type start = 0; - - while(start != std::string::npos) - { - std::string::size_type end = cookies.find_first_of("\r\n", start); - if(end > start) - { - // The line is non-empty. Try to create a cookie from it. - setOneCookie(cookies, start, end, mark_changed); - } - start = cookies.find_first_not_of("\r\n ", end); - } -} - -void LLPluginCookieStore::setCookiesFromHost(const std::string &cookies, const std::string &host, bool mark_changed) -{ - std::string::size_type start = 0; - - while(start != std::string::npos) - { - std::string::size_type end = cookies.find_first_of("\r\n", start); - if(end > start) - { - // The line is non-empty. Try to create a cookie from it. - setOneCookie(cookies, start, end, mark_changed, host); - } - start = cookies.find_first_not_of("\r\n ", end); - } -} - -void LLPluginCookieStore::readCookies(std::istream& s, bool mark_changed) -{ - std::string line; - while(s.good() && !s.eof()) - { - std::getline(s, line); - if(!line.empty()) - { - // Try to create a cookie from this line. - setOneCookie(line, 0, std::string::npos, mark_changed); - } - } -} - -std::string LLPluginCookieStore::quoteString(const std::string &s) -{ - std::stringstream result; - - result << '"'; - - for(std::string::size_type i = 0; i < s.size(); ++i) - { - char c = s[i]; - switch(c) - { - // All these separators need to be quoted in HTTP headers, according to section 2.2 of rfc 2616: - case '(': case ')': case '<': case '>': case '@': - case ',': case ';': case ':': case '\\': case '"': - case '/': case '[': case ']': case '?': case '=': - case '{': case '}': case ' ': case '\t': - result << '\\'; - break; - } - - result << c; - } - - result << '"'; - - return result.str(); -} - -std::string LLPluginCookieStore::unquoteString(const std::string &s) -{ - std::stringstream result; - - bool in_quotes = false; - - for(std::string::size_type i = 0; i < s.size(); ++i) - { - char c = s[i]; - switch(c) - { - case '\\': - if(in_quotes) - { - // The next character is backslash-quoted. Pass it through untouched. - ++i; - if(i < s.size()) - { - result << s[i]; - } - continue; - } - break; - case '"': - in_quotes = !in_quotes; - continue; - break; - } - - result << c; - } - - return result.str(); -} - -// The flow for deleting a cookie is non-obvious enough that I should call it out here... -// Deleting a cookie is done by setting a cookie with the same name, path, and domain, but with an expire timestamp in the past. -// (This is exactly how a web server tells a browser to delete a cookie.) -// When deleting with mark_changed set to true, this replaces the existing cookie in the list with an entry that's marked both dead and changed. -// Some time later when writeChangedCookies() is called with clear_changed set to true, the dead cookie is deleted from the list after being returned, so that the -// delete operation (in the form of the expired cookie) is passed along. -void LLPluginCookieStore::setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed, const std::string &host) -{ - Cookie *cookie = Cookie::createFromString(s, cookie_start, cookie_end, host); - if(cookie) - { - LL_DEBUGS("CookieStoreUpdate") << "setting cookie: " << cookie->getCookie() << LL_ENDL; - - // Create a key for this cookie - std::string key = cookie->getKey(); - - // Check to see whether this cookie should have expired - if(!cookie->isSessionCookie() && (cookie->getDate() < LLDate::now())) - { - // This cookie has expired. - if(mark_changed) - { - // If we're marking cookies as changed, we should keep it anyway since we'll need to send it out with deltas. - cookie->setDead(true); - LL_DEBUGS("CookieStoreUpdate") << " marking dead" << LL_ENDL; - } - else - { - // If we're not marking cookies as changed, we don't need to keep this cookie at all. - // If the cookie was already in the list, delete it. - removeCookie(key); - - delete cookie; - cookie = NULL; - - LL_DEBUGS("CookieStoreUpdate") << " removing" << LL_ENDL; - } - } - - if(cookie) - { - // If it already exists in the map, replace it. - cookie_map_t::iterator iter = mCookies.find(key); - if(iter != mCookies.end()) - { - if(iter->second->getCookie() == cookie->getCookie()) - { - // The new cookie is identical to the old -- don't mark as changed. - // Just leave the old one in the map. - delete cookie; - cookie = NULL; - - LL_DEBUGS("CookieStoreUpdate") << " unchanged" << LL_ENDL; - } - else - { - // A matching cookie was already in the map. Replace it. - delete iter->second; - iter->second = cookie; - - cookie->setChanged(mark_changed); - if(mark_changed) - mHasChangedCookies = true; - - LL_DEBUGS("CookieStoreUpdate") << " replacing" << LL_ENDL; - } - } - else - { - // The cookie wasn't in the map. Insert it. - mCookies.insert(std::make_pair(key, cookie)); - - cookie->setChanged(mark_changed); - if(mark_changed) - mHasChangedCookies = true; - - LL_DEBUGS("CookieStoreUpdate") << " adding" << LL_ENDL; - } - } - } - else - { - LL_WARNS("CookieStoreUpdate") << "failed to parse cookie: " << s.substr(cookie_start, cookie_end - cookie_start) << LL_ENDL; - } - -} - -void LLPluginCookieStore::clearCookies() -{ - std::for_each(mCookies.begin(), mCookies.end(), DeletePairedPointer()); - mCookies.clear(); -} - -void LLPluginCookieStore::removeCookie(const std::string &key) -{ - cookie_map_t::iterator iter = mCookies.find(key); - if(iter != mCookies.end()) - { - delete iter->second; - mCookies.erase(iter); - } -} - -void LLPluginCookieStore::removeCookiesByDomain(const std::string &domain) -{ - cookie_map_t::iterator iter = mCookies.begin(); - while(iter != mCookies.end()) - { - if(iter->second->getDomain() == domain) - { - cookie_map_t::iterator doErase = iter; - iter++; - delete doErase->second; - mCookies.erase(doErase); - } - else - { - iter++; - } - } -} diff --git a/indra/llplugin/llplugincookiestore.h b/indra/llplugin/llplugincookiestore.h deleted file mode 100644 index a2fdeab647..0000000000 --- a/indra/llplugin/llplugincookiestore.h +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @file llplugincookiestore.h - * @brief LLPluginCookieStore provides central storage for http cookies used by plugins - * - * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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. - * - * 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. - * - * 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$ - * @endcond - */ - -#ifndef LL_LLPLUGINCOOKIESTORE_H -#define LL_LLPLUGINCOOKIESTORE_H - -#include "lldate.h" -#include <map> -#include <string> -#include <iostream> - -class LLPluginCookieStore -{ - LOG_CLASS(LLPluginCookieStore); -public: - LLPluginCookieStore(); - ~LLPluginCookieStore(); - - // gets all cookies currently in storage -- use when initializing a plugin - std::string getAllCookies(); - void writeAllCookies(std::ostream& s); - - // gets only persistent cookies (i.e. not session cookies) -- use when writing cookies to a file - std::string getPersistentCookies(); - void writePersistentCookies(std::ostream& s); - - // gets cookies which are marked as "changed" -- use when sending periodic updates to plugins - std::string getChangedCookies(bool clear_changed = true); - void writeChangedCookies(std::ostream& s, bool clear_changed = true); - - // (re)initializes internal data structures and bulk-sets cookies -- use when reading cookies from a file - void setAllCookies(const std::string &cookies, bool mark_changed = false); - void readAllCookies(std::istream& s, bool mark_changed = false); - - // sets one or more cookies (without reinitializing anything) -- use when receiving cookies from a plugin - void setCookies(const std::string &cookies, bool mark_changed = true); - void readCookies(std::istream& s, bool mark_changed = true); - - // sets one or more cookies (without reinitializing anything), supplying a hostname the cookies came from -- use when setting a cookie manually - void setCookiesFromHost(const std::string &cookies, const std::string &host, bool mark_changed = true); - - // quote or unquote a string as per the definition of 'quoted-string' in rfc2616 - static std::string quoteString(const std::string &s); - static std::string unquoteString(const std::string &s); - - void removeCookiesByDomain(const std::string &domain); - -private: - - void setOneCookie(const std::string &s, std::string::size_type cookie_start, std::string::size_type cookie_end, bool mark_changed, const std::string &host = LLStringUtil::null); - - class Cookie - { - public: - static Cookie *createFromString(const std::string &s, std::string::size_type cookie_start = 0, std::string::size_type cookie_end = std::string::npos, const std::string &host = LLStringUtil::null); - - // Construct a string from the cookie that uniquely represents it, to be used as a key in a std::map. - std::string getKey() const; - std::string getDomain() const; - - const std::string &getCookie() const { return mCookie; }; - bool isSessionCookie() const { return mDate.isNull(); }; - - bool isDead() const { return mDead; }; - void setDead(bool dead) { mDead = dead; }; - - bool isChanged() const { return mChanged; }; - void setChanged(bool changed) { mChanged = changed; }; - - const LLDate &getDate() const { return mDate; }; - - private: - Cookie(const std::string &s, std::string::size_type cookie_start = 0, std::string::size_type cookie_end = std::string::npos); - bool parse(const std::string &host); - std::string::size_type findFieldEnd(std::string::size_type start = 0, std::string::size_type end = std::string::npos); - bool matchName(std::string::size_type start, std::string::size_type end, const char *name); - - std::string mCookie; // The full cookie, in RFC 2109 string format - LLDate mDate; // The expiration date of the cookie. For session cookies, this will be a null date (mDate.isNull() is true). - // Start/end indices of various parts of the cookie string. Stored as indices into the string to save space and time. - std::string::size_type mNameStart, mNameEnd; - std::string::size_type mValueStart, mValueEnd; - std::string::size_type mDomainStart, mDomainEnd; - std::string::size_type mPathStart, mPathEnd; - bool mDead; - bool mChanged; - }; - - typedef std::map<std::string, Cookie*> cookie_map_t; - - cookie_map_t mCookies; - bool mHasChangedCookies; - - void clearCookies(); - void removeCookie(const std::string &key); -}; - -#endif // LL_LLPLUGINCOOKIESTORE_H diff --git a/indra/llplugin/tests/llplugincookiestore_test.cpp b/indra/llplugin/tests/llplugincookiestore_test.cpp deleted file mode 100644 index c2cb236cba..0000000000 --- a/indra/llplugin/tests/llplugincookiestore_test.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/** - * @file llplugincookiestore_test.cpp - * @brief Unit tests for LLPluginCookieStore. - * - * @cond - * $LicenseInfo:firstyear=2010&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * 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. - * - * 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. - * - * 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$ - * @endcond - */ - -#include "linden_common.h" -#include <list> -#include "../test/lltut.h" - -#include "../llplugincookiestore.h" - - -namespace tut -{ - // Main Setup - struct LLPluginCookieStoreFixture - { - LLPluginCookieStoreFixture() - { - // We need dates definitively in the past and the future to properly test cookie expiration. - LLDate now = LLDate::now(); - LLDate past(now.secondsSinceEpoch() - (60.0 * 60.0 * 24.0)); // 1 day in the past - LLDate future(now.secondsSinceEpoch() + (60.0 * 60.0 * 24.0)); // 1 day in the future - - mPastString = past.asRFC1123(); - mFutureString = future.asRFC1123(); - } - - std::string mPastString; - std::string mFutureString; - LLPluginCookieStore mCookieStore; - - // List of cookies used for validation - std::list<std::string> mCookies; - - // This sets up mCookies from a string returned by one of the functions in LLPluginCookieStore - void setCookies(const std::string &cookies) - { - mCookies.clear(); - std::string::size_type start = 0; - - while(start != std::string::npos) - { - std::string::size_type end = cookies.find_first_of("\r\n", start); - if(end > start) - { - std::string line(cookies, start, end - start); - if(line.find_first_not_of("\r\n\t ") != std::string::npos) - { - // The line has some non-whitespace characters. Save it to the list. - mCookies.push_back(std::string(cookies, start, end - start)); - } - } - start = cookies.find_first_not_of("\r\n ", end); - } - } - - // This ensures that a cookie matching the one passed is in the list. - void ensureCookie(const std::string &cookie) - { - std::list<std::string>::iterator iter; - for(iter = mCookies.begin(); iter != mCookies.end(); iter++) - { - if(*iter == cookie) - { - // Found the cookie - // TODO: this should do a smarter equality comparison on the two cookies, instead of just a string compare. - return; - } - } - - // Didn't find this cookie - std::string message = "cookie not found: "; - message += cookie; - ensure(message, false); - } - - // This ensures that the number of cookies in the list matches what's expected. - void ensureSize(const std::string &message, size_t size) - { - if(mCookies.size() != size) - { - std::stringstream full_message; - - full_message << message << " (expected " << size << ", actual " << mCookies.size() << ")"; - ensure(full_message.str(), false); - } - } - }; - - typedef test_group<LLPluginCookieStoreFixture> factory; - typedef factory::object object; - factory tf("LLPluginCookieStore"); - - // Tests - template<> template<> - void object::test<1>() - { - // Test 1: cookie uniqueness and update lists. - // Valid, distinct cookies: - - std::string cookie01 = "cookieA=value; domain=example.com; path=/"; - std::string cookie02 = "cookieB=value; Domain=example.com; Path=/; Max-Age=10; Secure; Version=1; Comment=foo!; HTTPOnly"; // cookie with every supported field, in different cases. - std::string cookie03 = "cookieA=value; domain=foo.example.com; path=/"; // different domain - std::string cookie04 = "cookieA=value; domain=example.com; path=/bar/"; // different path - std::string cookie05 = "cookieC; domain=example.com; path=/"; // empty value - std::string cookie06 = "cookieD=value; domain=example.com; path=/; expires="; // different name, persistent cookie - cookie06 += mFutureString; - - mCookieStore.setCookies(cookie01); - mCookieStore.setCookies(cookie02); - mCookieStore.setCookies(cookie03); - mCookieStore.setCookies(cookie04); - mCookieStore.setCookies(cookie05); - mCookieStore.setCookies(cookie06); - - // Invalid cookies (these will get parse errors and not be added to the store) - - std::string badcookie01 = "cookieD=value; domain=example.com; path=/; foo=bar"; // invalid field name - std::string badcookie02 = "cookieE=value; path=/"; // no domain - - mCookieStore.setCookies(badcookie01); - mCookieStore.setCookies(badcookie02); - - // All cookies added so far should have been marked as "changed" - setCookies(mCookieStore.getChangedCookies()); - ensureSize("count of changed cookies", 6); - ensureCookie(cookie01); - ensureCookie(cookie02); - ensureCookie(cookie03); - ensureCookie(cookie04); - ensureCookie(cookie05); - ensureCookie(cookie06); - - // Save off the current state of the cookie store (we'll restore it later) - std::string savedCookies = mCookieStore.getAllCookies(); - - // Test replacing cookies - std::string cookie01a = "cookieA=newvalue; domain=example.com; path=/"; // updated value - std::string cookie02a = "cookieB=newvalue; domain=example.com; path=/; expires="; // remove cookie (by setting an expire date in the past) - cookie02a += mPastString; - - mCookieStore.setCookies(cookie01a); - mCookieStore.setCookies(cookie02a); - - // test for getting changed cookies - setCookies(mCookieStore.getChangedCookies()); - ensureSize("count of updated cookies", 2); - ensureCookie(cookie01a); - ensureCookie(cookie02a); - - // and for the state of the store after getting changed cookies - setCookies(mCookieStore.getAllCookies()); - ensureSize("count of valid cookies", 5); - ensureCookie(cookie01a); - ensureCookie(cookie03); - ensureCookie(cookie04); - ensureCookie(cookie05); - ensureCookie(cookie06); - - // Check that only the persistent cookie is returned here - setCookies(mCookieStore.getPersistentCookies()); - ensureSize("count of persistent cookies", 1); - ensureCookie(cookie06); - - // Restore the cookie store to a previous state and verify - mCookieStore.setAllCookies(savedCookies); - - // Since setAllCookies defaults to not marking cookies as changed, this list should be empty. - setCookies(mCookieStore.getChangedCookies()); - ensureSize("count of changed cookies after restore", 0); - - // Verify that the restore worked as it should have. - setCookies(mCookieStore.getAllCookies()); - ensureSize("count of restored cookies", 6); - ensureCookie(cookie01); - ensureCookie(cookie02); - ensureCookie(cookie03); - ensureCookie(cookie04); - ensureCookie(cookie05); - ensureCookie(cookie06); - } - -} diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp index f3d7762a08..189beb75ba 100644 --- a/indra/media_plugins/cef/media_plugin_cef.cpp +++ b/indra/media_plugins/cef/media_plugin_cef.cpp @@ -38,6 +38,7 @@ #include "media_plugin_base.h" #include <functional> +#include <chrono> #include "dullahan.h" @@ -64,12 +65,12 @@ private: void onLoadStartCallback(); void onRequestExitCallback(); void onLoadEndCallback(int httpStatusCode); + void onLoadError(int status, const std::string error_text); void onAddressChangeCallback(std::string url); - void onNavigateURLCallback(std::string url, std::string target); + void onOpenPopupCallback(std::string url, std::string target); bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); void onCursorChangedCallback(dullahan::ECursorType type); - void onFileDownloadCallback(std::string filename); - const std::string onFileDialogCallback(); + const std::vector<std::string> onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, const std::string dialog_accept_filter, bool& use_default); void postDebugMessage(const std::string& msg); void authResponse(LLPluginMessage &message); @@ -95,7 +96,9 @@ private: bool mCanPaste; std::string mCachePath; std::string mCookiePath; - std::string mPickedFile; + std::string mCefLogFile; + bool mCefLogVerbose; + std::vector<std::string> mPickedFiles; VolumeCatcher mVolumeCatcher; F32 mCurVolume; dullahan* mCEFLib; @@ -115,7 +118,7 @@ MediaPluginBase(host_send_func, host_user_data) mCookiesEnabled = true; mPluginsEnabled = false; mJavascriptEnabled = true; - mDisableGPU = true; + mDisableGPU = false; mUserAgentSubtring = ""; mAuthUsername = ""; mAuthPassword = ""; @@ -125,7 +128,9 @@ MediaPluginBase(host_send_func, host_user_data) mCanPaste = false; mCachePath = ""; mCookiePath = ""; - mPickedFile = ""; + mCefLogFile = ""; + mCefLogVerbose = false; + mPickedFiles.clear(); mCurVolume = 0.0; mCEFLib = new dullahan(); @@ -166,6 +171,10 @@ void MediaPluginCEF::onPageChangedCallback(const unsigned char* pixels, int x, i { memcpy(mPixels, pixels, mWidth * mHeight * mDepth); } + else + { + mCEFLib->setSize(mWidth, mHeight); + } setDirty(0, 0, mWidth, mHeight); } } @@ -208,6 +217,21 @@ void MediaPluginCEF::onLoadStartCallback() sendMessage(message); } +///////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onLoadError(int status, const std::string error_text) +{ + std::stringstream msg; + + msg << "<b>Loading error!</b>"; + msg << "<p>"; + msg << "Message: " << error_text; + msg << "<br>"; + msg << "Code: " << status; + + mCEFLib->showBrowserMessage(msg.str()); +} + //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onRequestExitCallback() @@ -241,12 +265,11 @@ void MediaPluginCEF::onAddressChangeCallback(std::string url) //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::onNavigateURLCallback(std::string url, std::string target) +void MediaPluginCEF::onOpenPopupCallback(std::string url, std::string target) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "click_href"); message.setValue("uri", url); message.setValue("target", target); - message.setValue("uuid", ""); // not used right now sendMessage(message); } @@ -285,30 +308,52 @@ bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::strin //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::onFileDownloadCallback(const std::string filename) +const std::vector<std::string> MediaPluginCEF::onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, std::string dialog_accept_filter, bool& use_default) { - mAuthOK = false; + // do not use the default CEF file picker + use_default = false; - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download"); - message.setValue("filename", filename); + if (dialog_type == dullahan::FD_OPEN_FILE) + { + mPickedFiles.clear(); - sendMessage(message); -} + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); + message.setValueBoolean("blocking_request", true); + message.setValueBoolean("multiple_files", false); -//////////////////////////////////////////////////////////////////////////////// -// -const std::string MediaPluginCEF::onFileDialogCallback() -{ - mPickedFile.clear(); + sendMessage(message); - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); - message.setValueBoolean("blocking_request", true); + return mPickedFiles; + } + else if (dialog_type == dullahan::FD_OPEN_MULTIPLE_FILES) + { + mPickedFiles.clear(); - sendMessage(message); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); + message.setValueBoolean("blocking_request", true); + message.setValueBoolean("multiple_files", true); + + sendMessage(message); + + return mPickedFiles; + } + else if (dialog_type == dullahan::FD_SAVE_FILE) + { + mAuthOK = false; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download"); + message.setValue("filename", default_file); - return mPickedFile; + sendMessage(message); + + return std::vector<std::string>(); + } + + return std::vector<std::string>(); } +//////////////////////////////////////////////////////////////////////////////// +// void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type) { std::string name = ""; @@ -341,6 +386,8 @@ void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type) sendMessage(message); } +//////////////////////////////////////////////////////////////////////////////// +// void MediaPluginCEF::authResponse(LLPluginMessage &message) { mAuthOK = message.getValueBoolean("ok"); @@ -373,7 +420,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; message.setValueLLSD("versions", versions); - std::string plugin_version = "CEF plugin 1.1.3"; + std::string plugin_version = "CEF plugin 1.1.412"; message.setValue("plugin_version", plugin_version); sendMessage(message); } @@ -439,17 +486,17 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1)); mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this)); mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1)); + mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2)); mCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1)); - mCEFLib->setOnNavigateURLCallback(std::bind(&MediaPluginCEF::onNavigateURLCallback, this, std::placeholders::_1, std::placeholders::_2)); + mCEFLib->setOnOpenPopupCallback(std::bind(&MediaPluginCEF::onOpenPopupCallback, this, std::placeholders::_1, std::placeholders::_2)); mCEFLib->setOnHTTPAuthCallback(std::bind(&MediaPluginCEF::onHTTPAuthCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); - mCEFLib->setOnFileDownloadCallback(std::bind(&MediaPluginCEF::onFileDownloadCallback, this, std::placeholders::_1)); - mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialogCallback, this)); + mCEFLib->setOnFileDialogCallback(std::bind(&MediaPluginCEF::onFileDialog, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); mCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1)); mCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this)); dullahan::dullahan_settings settings; settings.accept_language_list = mHostLanguage; - settings.background_color = 0xffffffff; + settings.background_color = 0xff282828; settings.cache_enabled = true; settings.cache_path = mCachePath; settings.cookie_store_path = mCookiePath; @@ -468,6 +515,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string) settings.plugins_enabled = mPluginsEnabled; settings.user_agent_substring = mCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring); settings.webgl_enabled = true; + settings.log_file = mCefLogFile; + settings.log_verbose = mCefLogVerbose; std::vector<std::string> custom_schemes(1, "secondlife"); mCEFLib->setCustomSchemes(custom_schemes); @@ -497,8 +546,11 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { std::string user_data_path_cache = message_in.getValue("cache_path"); std::string user_data_path_cookies = message_in.getValue("cookies_path"); + mCachePath = user_data_path_cache + "cef_cache"; mCookiePath = user_data_path_cookies + "cef_cookies"; + mCefLogFile = message_in.getValue("cef_log_file"); + mCefLogVerbose = message_in.getValueBoolean("cef_verbose_log"); } else if (message_name == "size_change") { @@ -520,11 +572,11 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mTextureWidth = texture_width; mTextureHeight = texture_height; + + mCEFLib->setSize(mWidth, mHeight); }; }; - mCEFLib->setSize(mWidth, mHeight); - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); message.setValue("name", name); message.setValueS32("width", width); @@ -650,7 +702,14 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } if (message_name == "pick_file_response") { - mPickedFile = message_in.getValue("file"); + LLSD file_list_llsd = message_in.getValueLLSD("file_list"); + + LLSD::array_const_iterator iter = file_list_llsd.beginArray(); + LLSD::array_const_iterator end = file_list_llsd.endArray(); + for (; iter != end; ++iter) + { + mPickedFiles.push_back(((*iter).asString())); + } } if (message_name == "auth_response") { @@ -697,6 +756,10 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { mCookiesEnabled = message_in.getValueBoolean("enable"); } + else if (message_name == "clear_cookies") + { + mCEFLib->deleteAllCookies(); + } else if (message_name == "set_user_agent") { mUserAgentSubtring = message_in.getValue("user_agent"); diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index cdb98d26e4..76e9e619d6 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -5.1.3 +5.1.4 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index dd07972249..1689f66e8b 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -16155,6 +16155,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>CefVerboseLog</key> + <map> + <key>Comment</key> + <string>Enable/disable CEF verbose loggingk</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> </map> </llsd> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 464e216cf0..eed052b82a 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1940,8 +1940,6 @@ bool LLAppViewer::cleanup() LLAvatarIconIDCache::getInstance()->save(); - LLViewerMedia::saveCookieFile(); - // Stop the plugin read thread if it's running. LLPluginProcessParent::setUseReadThread(false); @@ -3179,8 +3177,14 @@ LLSD LLAppViewer::getViewerInfo() const cef_ver_codec << " / CEF: "; cef_ver_codec << CEF_VERSION; - cef_ver_codec << " / Chrome: "; + cef_ver_codec << " / Chromium: "; cef_ver_codec << CHROME_VERSION_MAJOR; + cef_ver_codec << "."; + cef_ver_codec << CHROME_VERSION_MINOR; + cef_ver_codec << "."; + cef_ver_codec << CHROME_VERSION_BUILD; + cef_ver_codec << "."; + cef_ver_codec << CHROME_VERSION_PATCH; info["LIBCEF_VERSION"] = cef_ver_codec.str(); #else diff --git a/indra/newview/llfloaterfacebook.cpp b/indra/newview/llfloaterfacebook.cpp index b1d6d8be82..e84cbc289f 100644 --- a/indra/newview/llfloaterfacebook.cpp +++ b/indra/newview/llfloaterfacebook.cpp @@ -1,4 +1,4 @@ -/** +/** * @file llfloaterfacebook.cpp * @brief Implementation of llfloaterfacebook * @author Gilbert@lindenlab.com @@ -41,7 +41,6 @@ #include "llresmgr.h" // LLLocale #include "llsdserialize.h" #include "llloadingindicator.h" -#include "llplugincookiestore.h" #include "llslurl.h" #include "lltrans.h" #include "llsnapshotlivepreview.h" @@ -296,16 +295,11 @@ void LLFacebookStatusPanel::showConnectedLayout() void LLFacebookStatusPanel::onConnect() { LLFacebookConnect::instance().checkConnectionToFacebook(true); - - //Clear only the facebook browser cookies so that the facebook login screen appears - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); } void LLFacebookStatusPanel::onDisconnect() { LLFacebookConnect::instance().disconnectFromFacebook(); - - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".facebook.com"); } void LLFacebookStatusPanel::clearAndClose() @@ -810,7 +804,7 @@ void LLFacebookCheckinPanel::sendCheckin() LLAgentUI::buildSLURL(slurl); std::string slurl_string = slurl.getSLURLString(); - // Use a valid http:// URL if the scheme is secondlife:// + // Use a valid http:// URL if the scheme is secondlife:// LLURI slurl_uri(slurl_string); if (slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME) { diff --git a/indra/newview/llfloaterflickr.cpp b/indra/newview/llfloaterflickr.cpp index 15b7c7fafa..69a92b2b54 100644 --- a/indra/newview/llfloaterflickr.cpp +++ b/indra/newview/llfloaterflickr.cpp @@ -40,7 +40,6 @@ #include "llresmgr.h" // LLLocale #include "llsdserialize.h" #include "llloadingindicator.h" -#include "llplugincookiestore.h" #include "llslurl.h" #include "lltrans.h" #include "llsnapshotlivepreview.h" @@ -660,16 +659,11 @@ void LLFlickrAccountPanel::showConnectedLayout() void LLFlickrAccountPanel::onConnect() { LLFlickrConnect::instance().checkConnectionToFlickr(true); - - //Clear only the flickr browser cookies so that the flickr login screen appears - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com"); } void LLFlickrAccountPanel::onDisconnect() { LLFlickrConnect::instance().disconnectFromFlickr(); - - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".flickr.com"); } //////////////////////// diff --git a/indra/newview/llfloatertwitter.cpp b/indra/newview/llfloatertwitter.cpp index 803c80ac1a..2b33bc6935 100644 --- a/indra/newview/llfloatertwitter.cpp +++ b/indra/newview/llfloatertwitter.cpp @@ -41,7 +41,6 @@ #include "llresmgr.h" // LLLocale #include "llsdserialize.h" #include "llloadingindicator.h" -#include "llplugincookiestore.h" #include "llslurl.h" #include "lltrans.h" #include "llsnapshotlivepreview.h" @@ -683,16 +682,11 @@ void LLTwitterAccountPanel::showConnectedLayout() void LLTwitterAccountPanel::onConnect() { LLTwitterConnect::instance().checkConnectionToTwitter(true); - - //Clear only the twitter browser cookies so that the twitter login screen appears - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com"); } void LLTwitterAccountPanel::onDisconnect() { LLTwitterConnect::instance().disconnectFromTwitter(); - - LLViewerMedia::getCookieStore()->removeCookiesByDomain(".twitter.com"); } //////////////////////// diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index a8025906c7..7f6955d08c 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -1022,7 +1022,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) // try as slurl first if (!LLURLDispatcher::dispatch(url, "clicked", NULL, mTrusted)) { - LLWeb::loadURL(url, target, std::string()); + LLWeb::loadURL(url, target, uuid); } // CP: removing this code because we no longer support popups so this breaks the flow. diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 7ea6a14e6b..8c5cad5af0 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -965,9 +965,6 @@ bool idle_startup() // Load Avatars icons cache LLAvatarIconIDCache::getInstance()->load(); - // Load media plugin cookies - LLViewerMedia::loadCookieFile(); - LLRenderMuteList::getInstance()->loadFromFile(); //------------------------------------------------- diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 474f3de664..422c1a2328 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -50,7 +50,6 @@ #include "llpanelprofile.h" #include "llparcel.h" #include "llpluginclassmedia.h" -#include "llplugincookiestore.h" #include "llurldispatcher.h" #include "lluuid.h" #include "llversioninfo.h" @@ -154,7 +153,6 @@ LLViewerMediaObserver::~LLViewerMediaObserver() } -LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL; LLURL LLViewerMedia::sOpenIDURL; std::string LLViewerMedia::sOpenIDCookie; LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL; @@ -169,8 +167,6 @@ static F64 sLowestLoadableImplInterest = 0.0f; static bool sAnyMediaShowing = false; static bool sAnyMediaPlaying = 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) @@ -610,12 +606,6 @@ void LLViewerMedia::updateMedia(void *dummy_arg) sAnyMediaShowing = false; sAnyMediaPlaying = 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(); @@ -1059,64 +1049,6 @@ void LLViewerMedia::clearAllCookies() 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; - - 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(std::string()); } ///////////////////////////////////////////////////////////////////////////////////////// @@ -1145,7 +1077,7 @@ void LLViewerMedia::setCookiesEnabled(bool enabled) LLViewerMediaImpl* pimpl = *iter; if(pimpl->mMediaSource) { - pimpl->mMediaSource->enable_cookies(enabled); + pimpl->mMediaSource->cookies_enabled(enabled); } } } @@ -1170,127 +1102,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.c_str()); - 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; - if(pimpl->mMediaSource) - { - pimpl->mMediaSource->clear_cookies(); - } - } - - // If we have an OpenID cookie, re-add it to the cookie store. - setOpenIDCookie(std::string()); -} - - -///////////////////////////////////////////////////////////////////////////////////////// -// 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.c_str()); - 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 LLSD LLViewerMedia::getHeaders() { @@ -1395,8 +1207,6 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url) hostEnd = authority.size(); } - getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(hostStart, hostEnd - hostStart)); - if (url.length()) { LLMediaCtrl* media_instance = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents"); @@ -1434,7 +1244,6 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url) httpHeaders->append(HTTP_OUT_HEADER_COOKIE, sOpenIDCookie); httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, getCurrentUserAgent()); - LL_DEBUGS("MediaAuth") << "Requesting " << url << LL_ENDL; LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL; @@ -1459,13 +1268,9 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url) const std::string& cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE].asStringRef(); LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL; - // *TODO: What about bad status codes? Does this destroy previous cookies? - LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, hostAuth); - // Set cookie for snapshot publishing. std::string authCookie = cookie.substr(0, cookie.find(";")); // strip path LLWebProfile::setAuthCookie(authCookie); - } ///////////////////////////////////////////////////////////////////////////////////////// @@ -1660,12 +1465,6 @@ void LLViewerMedia::cleanupClass() delete sSpareBrowserMediaSource; sSpareBrowserMediaSource = NULL; } - - if (sCookieStore != NULL) - { - delete sCookieStore; - sCookieStore = NULL; - } } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1898,6 +1697,8 @@ 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_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 // at the login page displaying login Web page or Web browser test via Develop menu. @@ -1906,7 +1707,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(); }; @@ -1927,13 +1727,13 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ { media_source = new LLPluginClassMedia(owner); media_source->setSize(default_width, default_height); - media_source->setUserDataPath(user_data_path_cache, user_data_path_cookies); + 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->enable_cookies( cookies_enabled || clean_browser); + 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" ); @@ -2040,17 +1840,6 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) 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(); - LL_DEBUGS() << "setting cookies: " << all_cookies << LL_ENDL; - if(!all_cookies.empty()) - { - media_source->set_cookies(all_cookies); - } - mMediaSource = media_source; mMediaSource->setDeleteOK(false) ; updateVolume(); @@ -2992,14 +2781,10 @@ void LLViewerMediaImpl::update() updateVolume(); // TODO: this is updated every frame - is this bad? - updateJavascriptObject(); - - // 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); - } + // Removing this as part of the post viewer64 media update + // Removed as not implemented in CEF embedded browser + // See MAINT-8194 for a more fuller description + // updateJavascriptObject(); } @@ -3489,22 +3274,40 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla case LLViewerMediaObserver::MEDIA_EVENT_PICK_FILE_REQUEST: { - // Display a file picker - std::string response; - LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getOpenFile(LLFilePicker::FFLOAD_ALL)) + std::vector<std::string> responses; + + bool pick_multiple_files = plugin->getIsMultipleFilePick(); + if (pick_multiple_files == false) { - // The user didn't pick a file -- the empty response string will indicate this. + picker.getOpenFile(LLFilePicker::FFLOAD_ALL); + + std::string filename = picker.getFirstFile(); + responses.push_back(filename); } + else + { + if (picker.getMultipleOpenFiles()) + { + std::string filename = picker.getFirstFile(); - response = picker.getFirstFile(); + responses.push_back(filename); - plugin->sendPickFileResponse(response); + while (!filename.empty()) + { + filename = picker.getNextFile(); + + if (!filename.empty()) + { + responses.push_back(filename); + } + } + } + } + plugin->sendPickFileResponse(responses); } break; - case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST: { LLNotification::Params auth_request_params; @@ -3574,13 +3377,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla //////////////////////////////////////////////////////////////////////////////// // virtual -void LLViewerMediaImpl::handleCookieSet(LLPluginClassMedia* self, const std::string &cookie) -{ - LLViewerMedia::getCookieStore()->setCookies(cookie); -} - -//////////////////////////////////////////////////////////////////////////////// -// virtual void LLViewerMediaImpl::cut() { diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 0212bf88bf..6e18c4fecb 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -50,7 +50,6 @@ class LLViewerMediaTexture; class LLMediaEntry; class LLVOVolume; class LLMimeDiscoveryResponder; -class LLPluginCookieStore; typedef LLPointer<LLViewerMediaImpl> viewer_media_t; /////////////////////////////////////////////////////////////////////////////// @@ -149,13 +148,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& url, const std::string &cookie); @@ -178,7 +170,6 @@ private: static void openIDSetupCoro(std::string openidUrl, std::string openidToken); static void getOpenIDCookieCoro(std::string url); - static LLPluginCookieStore *sCookieStore; static LLURL sOpenIDURL; static std::string sOpenIDCookie; static LLPluginClassMedia* sSpareBrowserMediaSource; @@ -337,7 +328,6 @@ public: // Inherited from LLPluginClassMediaOwner /*virtual*/ void handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent); - /*virtual*/ void handleCookieSet(LLPluginClassMedia* self, const std::string &cookie); // LLEditMenuHandler overrides /*virtual*/ void cut(); diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp index 06ce497510..81d4e30a7a 100644 --- a/indra/newview/llwebprofile.cpp +++ b/indra/newview/llwebprofile.cpp @@ -31,7 +31,6 @@ // libs #include "llbufferstream.h" #include "llimagepng.h" -#include "llplugincookiestore.h" #include "llsdserialize.h" diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 60f36770bb..71f4d81195 100644 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -8,14 +8,14 @@ help_topic="floater_about" save_rect="true" title="ABOUT [CAPITALIZED_APP_NAME]" - width="470"> + width="500"> <tab_container follows="all" top="25" left="10" height="405" - width="450" + width="480" name="about_tab" tab_position="top"> <panel @@ -33,7 +33,7 @@ max_length="65536" name="support_editor" top="5" - width="435" + width="465" word_wrap="true" /> <button follows="left|top" @@ -56,7 +56,7 @@ left="5" name="linden_intro" top="10" - width="435" + width="465" wrap="true"> Second Life is brought to you by the Lindens, with open source contributions from: @@ -71,7 +71,7 @@ with open source contributions from: max_length="65536" name="contrib_names" top_pad="10" - width="435" + width="465" word_wrap="true"> Dummy Name replaced at run time </text_editor> @@ -91,7 +91,7 @@ Dummy Name replaced at run time max_length="65536" name="licenses_editor" top="5" - width="435" + width="465" word_wrap="true"> 3Dconnexion SDK Copyright (C) 1992-2009 3Dconnexion APR Copyright (C) 2011 The Apache Software Foundation diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index fe9ffba6cd..9a097d933b 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -178,108 +178,7 @@ width="22"> <button.commit_callback function="WebContent.TestURL" - parameter="https://callum-linden.s3.amazonaws.com/ceftests.html"/> - </button> - - <button - image_overlay="Video_URL_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - chrome="true" - tool_tip="MPEG4 Video Test" - enabled="true" - follows="left|top" - height="22" - layout="topleft" - left="27" - name="VLC Plugin Test" - top="0" - width="22"> - <button.commit_callback - function="WebContent.TestURL" - parameter="https://callum-linden.s3.amazonaws.com/sample_media/ss.mp4"/> - </button> - <button - image_overlay="Video_URL_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - chrome="true" - tool_tip="MKV Video Test" - enabled="true" - follows="left|top" - height="22" - layout="topleft" - left="51" - name="VLC Plugin Test" - top="0" - width="22"> - <button.commit_callback - function="WebContent.TestURL" - parameter="https://callum-linden.s3.amazonaws.com/sample_media/jellyfish.mkv"/> - </button> - <button - image_overlay="Video_URL_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - chrome="true" - tool_tip="WebM Video Test" - enabled="true" - follows="left|top" - height="22" - layout="topleft" - left="75" - name="VLC Plugin Test" - top="0" - width="22"> - <button.commit_callback - function="WebContent.TestURL" - parameter="https://callum-linden.s3.amazonaws.com/sample_media/jumprope.webm"/> - </button> - <button - image_overlay="Video_URL_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - chrome="true" - tool_tip="MP3 audio Test" - enabled="true" - follows="left|top" - height="22" - layout="topleft" - left="99" - name="VLC Plugin Test" - top="0" - width="22"> - <button.commit_callback - function="WebContent.TestURL" - parameter="https://callum-linden.s3.amazonaws.com/alegria.mp3"/> - </button> - <button - image_overlay="Video_URL_Off" - image_disabled="PushButton_Disabled" - image_disabled_selected="PushButton_Disabled" - image_selected="PushButton_Selected" - image_unselected="PushButton_Off" - chrome="true" - tool_tip="FLV Test" - enabled="true" - follows="left|top" - height="22" - layout="topleft" - left="123" - name="VLC Plugin Test" - top="0" - width="22"> - <button.commit_callback - function="WebContent.TestURL" - parameter="https://callum-linden.s3.amazonaws.com/sample_media/vandal.flv"/> + parameter="https://sl-viewer-media-system.s3.amazonaws.com/index.html"/> </button> </layout_panel> <layout_panel diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 4e2f819023..07b3cc3bd8 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -245,7 +245,7 @@ name="Media Browser"> <menu_item_call.on_click function="Advanced.WebContentTest" - parameter="http://google.com"/> + parameter="http://duckduckgo.com"/> </menu_item_call> <menu create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 92511167c0..81bb83f133 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -3173,7 +3173,7 @@ shortcut="control|alt|shift|Z"> <menu_item_call.on_click function="Advanced.WebContentTest" - parameter="http://google.com"/> + parameter="http://duckduckgo.com"/> </menu_item_call> <menu_item_call label="FB Connect Test" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 284688d4d1..2ec5cef640 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -19,7 +19,7 @@ follows="left|top" height="23" label="Clear History" - tool_tip="Clear login image, last location, teleport history, web, and texture cache" + tool_tip="Clear login image, last location, teleport history, web and texture cache" layout="topleft" left="30" name="clear_cache" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 1d4cbca1a5..6732f4ff1c 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -106,38 +106,6 @@ width="300"> Web: </text> - <!-- <radio_group - control_name="UseExternalBrowser" - draw_border="false" - follows="top|left" - height="40" - layout="topleft" - left_delta="50" - name="use_external_browser" - top_pad="-2" - width="480"> - <radio_item - height="20" - label="Use my browser (IE, Firefox, Safari)" - layout="topleft" - left_delta="0" - name="external" - value="true" - top="0" - tool_tip="Use the default system web browser for help, web links, etc. Not recommended if running full screen." - width="480" /> - <radio_item - height="20" - label="Use built-in browser" - layout="topleft" - left="0" - name="internal" - value="" - tool_tip="Use the built-in web browser for help, web links, etc. This browser opens as a new window inside [APP_NAME]." - top_delta="20" - width="480" /> - </radio_group> --> - <radio_group control_name="PreferredBrowserBehavior" follows="left|top" @@ -149,7 +117,7 @@ width="480"> <radio_item height="20" - label="Use my browser (Chrome, Firefox, IE) for all links" + label="Use the default system browser for all links" layout="topleft" left="0" name="internal" @@ -159,17 +127,17 @@ width="480" /> <radio_item height="20" - label="Use built-in browser for Second Life links only" + label="Use the built-in browser for Second Life links only" layout="topleft" left_delta="0" name="external" value="1" - tool_tip="Use the default system web browser for help, web links, etc. Builtin browser will be used only for LindenLab/SecondLife links." + tool_tip="Use the default system web browser for help, web links, etc. The built-in browser will be used only for LindenLab/Second Life links." top_delta="20" width="480" /> <radio_item height="20" - label="Use built-in browser for all links" + label="Use the built-in browser for all links" layout="topleft" left="0" name="external_all" @@ -193,22 +161,6 @@ radio_style="false" width="400" top_pad="5"/> - - <check_box - top_delta="4" - enabled="true" - follows="left|top" - height="14" - initial_value="true" - control_name="CookiesEnabled" - label="Accept cookies" - left_delta="0" - mouse_opaque="true" - name="cookies_enabled" - radio_style="false" - width="400" - top_pad="5"/> - <check_box top_delta="4" enabled="true" |