From c848af39605230043dd4d09d83694bf7eda378af Mon Sep 17 00:00:00 2001 From: Lirusaito Date: Mon, 1 Apr 2019 01:26:16 -0400 Subject: [PATCH] Merge in Dullahan support from future branch! --- autobuild.xml | 148 ++--- indra/cmake/CEFPlugin.cmake | 8 +- indra/llplugin/llpluginclassmedia.cpp | 158 +++-- indra/llplugin/llpluginclassmedia.h | 59 +- indra/llplugin/llpluginclassmediaowner.h | 2 - indra/newview/app_settings/settings.xml | 33 + indra/newview/llfloaterabout.cpp | 15 +- indra/newview/llmediactrl.cpp | 69 +- indra/newview/llmediactrl.h | 54 +- indra/newview/llpaneldirfind.cpp | 3 - indra/newview/llviewermedia.cpp | 44 +- indra/newview/llviewermenu.cpp | 29 + .../default/xui/en-us/floater_directory.xml | 6 - .../default/xui/en-us/menu_media_ctrl.xml | 62 ++ indra/newview/viewer_manifest.py | 31 +- indra/plugins/cef/media_plugin_cef.cpp | 601 +++++++++++------- 16 files changed, 830 insertions(+), 492 deletions(-) diff --git a/autobuild.xml b/autobuild.xml index 3ea23a13e..81f1c0db0 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -551,6 +551,80 @@ version 1 + dullahan + + copyright + Copyright (c) 2017, Linden Research, Inc. + description + A headless browser SDK that uses the Chromium Embedded Framework (CEF). It is designed to make it easier to write applications that render modern web content directly to a memory buffer, inject synthesized mouse and keyboard events as well as interact with web based features like JavaScript or cookies. + license + MPL + license_file + LICENSES/dullahan.txt + name + dullahan + platforms + + darwin + + archive + + hash + e447c0799438b1be850d7b589308d394 + hash_algorithm + md5 + url + https://bitbucket.org/SingularityViewer/libraries/downloads/dullahan-1.1.1085-3.3497.1833.g13f506f-darwin-201902131231.tar.bz2 + + name + darwin + + linux64 + + archive + + hash + 2f44b376e436f37cbad5c7567edddebd + hash_algorithm + md5 + url + https://bitbucket.org/router_gray/rg_3p-dullahan/downloads/dullahan-1.1.1085-3.3497.1833.g13f506f-linux64-201902042123.tar.bz2 + + name + linux64 + + windows + + archive + + hash + c3e093d40e93ff242e9b9c953ae7316c + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows/lib-vc142/dullahan-1.1.930-3.3282.1733.g9091548-windows-201802202358.tar.bz2 + + name + windows + + windows64 + + archive + + hash + 9c9696168fcb640feb7d64988a759b25 + hash_algorithm + md5 + url + https://depot.alchemyviewer.org/pub/windows64/lib-vc1415/dullahan-1.1.1085-3.3497.1833.g13f506f-windows64-201809230539.tar.bz2 + + name + windows64 + + + version + 1.1.1085-3.3497.1833.g13f506f + expat copyright @@ -1747,80 +1821,6 @@ version 2.9.3 - llceflib - - copyright - Copyright (c) 2014-2015, Linden Research, Inc. - description - LLCefLib implements a headless web browser, rendering modern web content to a memory buffer and providing an API for injecting mouse and keyboard events. It uses the Chromium Embedded Framework (https://bitbucket.org/chromiumembedded/cef) - license - LGPL - license_file - LICENSES/llceflib.txt - name - llceflib - platforms - - darwin - - archive - - hash - 9551150830531abc405888066437e2c2 - hash_algorithm - md5 - url - https://bitbucket.org/alchemyviewer/publiclibs-darwin/downloads/llceflib-3.2526.1364.gf6bf57b-darwin-201601160847.tar.bz2 - - name - darwin - - linux64 - - archive - - hash - 0e7613b2e038e18488452c2a9882144d - hash_algorithm - md5 - url - http://depot.alchemyviewer.org/pub/linux64/lib-trusty/llceflib-3.2526.1373.gb660893-linux64-201603281900.tar.bz2 - - name - linux64 - - windows - - archive - - hash - 30bbc702d7533f8e2c56bdd0f5f22b59 - hash_algorithm - md5 - url - http://depot.alchemyviewer.org/pub/windows/lib-vc14/llceflib-3.2526.1364.gf6bf57b-windows-201601160235.tar.bz2 - - name - windows - - windows64 - - archive - - hash - 230e4ccb442bd538eabe2167f351a20d - hash_algorithm - md5 - url - http://depot.alchemyviewer.org/pub/windows64/lib-vc14/llceflib-3.2526.1364.gf6bf57b-windows64-201601160304.tar.bz2 - - name - windows64 - - - version - 3.2526.1373.gb660893 - llphysicsextensions_stub copyright diff --git a/indra/cmake/CEFPlugin.cmake b/indra/cmake/CEFPlugin.cmake index 1b4c20ed3..f19e38254 100644 --- a/indra/cmake/CEFPlugin.cmake +++ b/indra/cmake/CEFPlugin.cmake @@ -6,7 +6,7 @@ if (USESYSTEMLIBS) set(CEFPLUGIN OFF CACHE BOOL "CEFPLUGIN support for the llplugin/llmedia test apps.") else (USESYSTEMLIBS) - use_prebuilt_binary(llceflib) + use_prebuilt_binary(dullahan) set(CEFPLUGIN ON CACHE BOOL "CEFPLUGIN support for the llplugin/llmedia test apps.") set(CEF_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/cef) @@ -16,7 +16,7 @@ if (WINDOWS) set(CEF_PLUGIN_LIBRARIES libcef.lib libcef_dll_wrapper.lib - llceflib.lib + dullahan.lib ) elseif (DARWIN) FIND_LIBRARY(APPKIT_LIBRARY AppKit) @@ -31,14 +31,14 @@ elseif (DARWIN) set(CEF_PLUGIN_LIBRARIES ${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a - ${ARCH_PREBUILT_DIRS_RELEASE}/libLLCefLib.a + ${ARCH_PREBUILT_DIRS_RELEASE}/libdullahan.a ${APPKIT_LIBRARY} ${CEF_LIBRARY} ) elseif (LINUX) set(CEF_PLUGIN_LIBRARIES - llceflib + dullahan cef_dll_wrapper cef ) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 75de5393f..873d02cde 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -62,6 +62,7 @@ bool LLPluginClassMedia::init_impl(void) return true; } + void LLPluginClassMedia::reset_impl(void) { mTextureParamsReceived = false; @@ -91,16 +92,22 @@ void LLPluginClassMedia::reset_impl(void) mMediaHeight = 0; mDirtyRect = LLRect::null; mAutoScaleMedia = false; - mRequestedVolume = 1.0f; + mRequestedVolume = 0.0f; + mPriority = PRIORITY_NORMAL; mLowPrioritySizeLimit = LOW_PRIORITY_TEXTURE_SIZE_DEFAULT; mAllowDownsample = false; mPadding = 0; mLastMouseX = 0; mLastMouseY = 0; mStatus = LLPluginClassMediaOwner::MEDIA_NONE; + mSleepTime = 1.0f / 100.0f; + mCanUndo = false; + mCanRedo = false; mCanCut = false; mCanCopy = false; mCanPaste = false; + mCanDoDelete = false; + mCanSelectAll = false; mMediaName.clear(); mMediaDescription.clear(); mBackgroundColor = LLColor4(1.0f, 1.0f, 1.0f, 1.0f); @@ -119,6 +126,8 @@ void LLPluginClassMedia::reset_impl(void) mClickUUID.clear(); mStatusCode = 0; + mClickEnforceTarget = false; + // media_time class mCurrentTime = 0.0f; mDuration = 0.0f; @@ -128,7 +137,12 @@ void LLPluginClassMedia::reset_impl(void) void LLPluginClassMedia::idle_impl(void) { - if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL)) + if(mPlugin) + { + mPlugin->idle(); + } + + if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == nullptr) || (mPlugin->isBlocked()) || (mOwner == nullptr)) { // Can't process a size change at this time } @@ -189,7 +203,14 @@ void LLPluginClassMedia::idle_impl(void) void *addr = mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); // clear texture memory to avoid random screen visual fuzz from uninitialized texture data - memset( addr, 0x00, newsize ); + if (addr) + { + memset( addr, 0x00, newsize ); + } + else + { + LL_WARNS("Plugin") << "Failed to get previously created shared memory address: " << mTextureSharedMemoryName << " size: " << mTextureSharedMemorySize << LL_ENDL; + } // We could do this to force an update, but textureValid() will still be returning false until the first roundtrip to the plugin, // so it may not be worthwhile. @@ -237,8 +258,8 @@ int LLPluginClassMedia::getTextureHeight() const unsigned char* LLPluginClassMedia::getBitsData() { - unsigned char *result = NULL; - if((mPlugin != NULL) && !mTextureSharedMemoryName.empty()) + unsigned char *result = nullptr; + if((mPlugin != nullptr) && !mTextureSharedMemoryName.empty()) { result = (unsigned char*)mPlugin->getSharedMemoryAddress(mTextureSharedMemoryName); } @@ -335,7 +356,7 @@ bool LLPluginClassMedia::textureValid(void) mMediaHeight <= 0 || mRequestedMediaWidth != mMediaWidth || mRequestedMediaHeight != mMediaHeight || - getBitsData() == NULL + getBitsData() == nullptr ) return false; @@ -346,7 +367,7 @@ bool LLPluginClassMedia::getDirty(LLRect *dirty_rect) { bool result = !mDirtyRect.isEmpty(); - if(dirty_rect != NULL) + if(dirty_rect != nullptr) { *dirty_rect = mDirtyRect; } @@ -678,15 +699,22 @@ F64 LLPluginClassMedia::getCPUUsage() return result; } -void LLPluginClassMedia::sendPickFileResponse(const std::string &file) +void LLPluginClassMedia::sendPickFileResponse(const std::vector 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::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); } @@ -704,6 +732,18 @@ void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, sendMessage(message); } +void LLPluginClassMedia::undo() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_undo"); + sendMessage(message); +} + +void LLPluginClassMedia::redo() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_redo"); + sendMessage(message); +} + void LLPluginClassMedia::cut() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut"); @@ -722,12 +762,33 @@ void LLPluginClassMedia::paste() sendMessage(message); } -void LLPluginClassMedia::setUserDataPath(const std::string &user_data_path_cache, const std::string &user_data_path_cookies, const std::string &user_data_path_logs) +void LLPluginClassMedia::doDelete() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_delete"); + sendMessage(message); +} + +void LLPluginClassMedia::selectAll() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_select_all"); + sendMessage(message); +} + +void LLPluginClassMedia::showPageSource() +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_show_source"); + sendMessage(message); +} + +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("logs_path", user_data_path_logs); + message.setValue("cef_log_file", user_data_path_cef_log); + sendMessage(message); } @@ -825,7 +886,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mDirtyRect.unionWith(newDirtyRect); } - LL_DEBUGS("PluginUpdated") << "adjusted incoming rect is: (" + LL_DEBUGS("Plugin") << "adjusted incoming rect is: (" << newDirtyRect.mLeft << ", " << newDirtyRect.mTop << ", " << newDirtyRect.mRight << ", " @@ -926,7 +987,6 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { S32 width = message.getValueS32("width"); S32 height = message.getValueS32("height"); - std::string name = message.getValue("name"); // TODO: check that name matches? mNaturalMediaWidth = width; @@ -936,10 +996,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) } else if(message_name == "size_change_response") { - std::string name = message.getValue("name"); - // TODO: check that name matches? - mTextureWidth = message.getValueS32("texture_width"); mTextureHeight = message.getValueS32("texture_height"); mMediaWidth = message.getValueS32("width"); @@ -961,6 +1018,14 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) } else if(message_name == "edit_state") { + if(message.hasValue("undo")) + { + mCanUndo = message.getValueBoolean("undo"); + } + if(message.hasValue("redo")) + { + mCanRedo = message.getValueBoolean("redo"); + } if(message.hasValue("cut")) { mCanCut = message.getValueBoolean("cut"); @@ -973,14 +1038,25 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mCanPaste = message.getValueBoolean("paste"); } + if (message.hasValue("delete")) + { + mCanDoDelete = message.getValueBoolean("delete"); + } + if (message.hasValue("select_all")) + { + mCanSelectAll = message.getValueBoolean("select_all"); + } } else if(message_name == "name_text") { + mHistoryBackAvailable = message.getValueBoolean("history_back_available"); + mHistoryForwardAvailable = message.getValueBoolean("history_forward_available"); mMediaName = message.getValue("name"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED); } else if(message_name == "pick_file") { + mIsMultipleFilePick = message.getValueBoolean("multiple_files"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST); } else if(message_name == "auth_request") @@ -1042,7 +1118,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") @@ -1057,13 +1138,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); @@ -1102,7 +1176,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) // } // else { - LL_WARNS("Plugin") << "Unknown " << message_class << " class message: " << message_name << LL_ENDL; + LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; } } @@ -1145,7 +1219,7 @@ void LLPluginClassMedia::focus(bool focused) sendMessage(message); } -void LLPluginClassMedia::set_page_zoom_factor( double factor ) +void LLPluginClassMedia::set_page_zoom_factor( F64 factor ) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_page_zoom_factor"); @@ -1165,27 +1239,23 @@ void LLPluginClassMedia::clear_cookies() sendMessage(message); } -void LLPluginClassMedia::set_cookies(const std::string &cookies) +void LLPluginClassMedia::cookies_enabled(bool enable) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_cookies"); - message.setValue("cookies", cookies); - sendMessage(message); -} - -void LLPluginClassMedia::enable_cookies(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); } -void LLPluginClassMedia::proxy_setup(bool enable, const std::string &host, int port) +void LLPluginClassMedia::proxy_setup(bool enable, int type, const std::string &host, int port, const std::string &user, const std::string &pass) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_setup"); message.setValueBoolean("enable", enable); + message.setValueS32("proxy_type", type); message.setValue("host", host); message.setValueS32("port", port); + message.setValue("username", user); + message.setValue("password", pass); sendMessage(message); } @@ -1217,16 +1287,6 @@ void LLPluginClassMedia::browse_back() sendMessage(message); } -void LLPluginClassMedia::set_status_redirect(int code, const std::string &url) -{ - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_status_redirect"); - - message.setValueS32("code", code); - message.setValue("url", url); - - sendMessage(message); -} - void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_user_agent"); @@ -1276,6 +1336,12 @@ void LLPluginClassMedia::addCertificateFilePath(const std::string& path) sendMessage(message); } +void LLPluginClassMedia::setOverrideClickTarget(const std::string &target) +{ + mClickEnforceTarget = true; + mOverrideClickTarget = target; +} + void LLPluginClassMedia::crashPlugin() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index c2b993488..ebb9a36b5 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -57,6 +57,7 @@ public: int getTextureHeight() const; int getFullWidth() const { return mFullMediaWidth; }; int getFullHeight() const { return mFullMediaHeight; }; + F64 getZoomFactor() const { return mZoomFactor; }; // This may return NULL. Callers need to check for and handle this case. unsigned char* getBitsData(); @@ -72,6 +73,7 @@ public: void setSize(int width, int height); void setAutoScale(bool auto_scale); + void setZoomFactor(F64 zoom_factor) { mZoomFactor = zoom_factor; } void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; }; @@ -83,7 +85,7 @@ public: // until you call idle() again. bool textureValid(void); - bool getDirty(LLRect *dirty_rect = NULL); + bool getDirty(LLRect *dirty_rect = nullptr); void resetDirty(void); typedef enum @@ -127,9 +129,9 @@ public: void loadURI(const std::string &uri); // Inherited from LLPluginProcessParentOwner - /* virtual */ void receivePluginMessage(const LLPluginMessage &message); - /* virtual */ void pluginLaunchFailed(); - /* virtual */ void pluginDied(); + /* virtual */ void receivePluginMessage(const LLPluginMessage &message) override; + /* virtual */ void pluginLaunchFailed() override; + /* virtual */ void pluginDied() override; // Inherited from LLPluginClassBasic /* virtual */ void priorityChanged(EPriority priority); @@ -137,7 +139,7 @@ public: F64 getCPUUsage(); - void sendPickFileResponse(const std::string &file); + void sendPickFileResponse(const std::vector files); void sendAuthResponse(bool ok, const std::string &username, const std::string &password); @@ -146,6 +148,12 @@ public: LLPluginClassMediaOwner::EMediaStatus getStatus() const { return mStatus; } + void undo(); + bool canUndo() const { return mCanUndo; }; + + void redo(); + bool canRedo() const { return mCanRedo; }; + void cut(); bool canCut() const { return mCanCut; }; @@ -155,8 +163,16 @@ public: void paste(); bool canPaste() const { return mCanPaste; }; + void doDelete(); + bool canDoDelete() const { return mCanDoDelete; }; + + void selectAll(); + bool canSelectAll() const { return mCanSelectAll; }; + + void showPageSource(); + // 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, const std::string &user_data_path_logs); + 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); @@ -167,17 +183,15 @@ public: bool pluginSupportsMediaBrowser(void); void focus(bool focused); - void set_page_zoom_factor( double factor ); + void set_page_zoom_factor( F64 factor ); void clear_cache(); void clear_cookies(); - void set_cookies(const std::string &cookies); - void enable_cookies(bool enable); - void proxy_setup(bool enable, const std::string &host = LLStringUtil::null, int port = 0); + void cookies_enabled(bool enable); + void proxy_setup(bool enable, int type = 0, const std::string &host = LLStringUtil::null, int port = 0, const std::string &user = LLStringUtil::null, const std::string &pass = LLStringUtil::null); void browse_stop(); void browse_reload(bool ignore_cache = false); void browse_forward(); void browse_back(); - void set_status_redirect(int code, const std::string &url); void setBrowserUserAgent(const std::string& user_agent); void showWebInspector( bool show ); void proxyWindowOpened(const std::string &target, const std::string &uuid); @@ -215,6 +229,13 @@ public: // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE std::string getClickUUID() const { return mClickUUID; }; + // mClickTarget is received from message and governs how link will be opened + // use this to enforce your own way of opening links inside plugins + void setOverrideClickTarget(const std::string &target); + void resetOverrideClickTarget() { mClickEnforceTarget = false; }; + bool isOverrideClickTarget() const { return mClickEnforceTarget; } + std::string getOverrideClickTarget() const { return mOverrideClickTarget; }; + // These are valid during MEDIA_EVENT_DEBUG_MESSAGE std::string getDebugMessageText() const { return mDebugMessageText; }; std::string getDebugMessageLevel() const { return mDebugMessageLevel; }; @@ -232,6 +253,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; }; @@ -326,8 +350,12 @@ protected: int mMediaWidth; int mMediaHeight; + F64 mZoomFactor; + float mRequestedVolume; + // Priority of this media stream + EPriority mPriority; int mLowPrioritySizeLimit; bool mAllowDownsample; @@ -343,9 +371,15 @@ protected: LLPluginClassMediaOwner::EMediaStatus mStatus; + F64 mSleepTime; + + bool mCanUndo; + bool mCanRedo; bool mCanCut; bool mCanCopy; bool mCanPaste; + bool mCanDoDelete; + bool mCanSelectAll; std::string mMediaName; std::string mMediaDescription; @@ -368,6 +402,8 @@ protected: std::string mClickNavType; std::string mClickTarget; std::string mClickUUID; + bool mClickEnforceTarget; + std::string mOverrideClickTarget; std::string mDebugMessageText; std::string mDebugMessageLevel; S32 mGeometryX; @@ -380,6 +416,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 391c23d88..010f54c8f 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -34,7 +34,6 @@ #include class LLPluginClassMedia; -class LLPluginCookieStore; class LLPluginClassMediaOwner { @@ -86,7 +85,6 @@ public: 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/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e1b251023..e0be85ca3 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3477,6 +3477,39 @@ This should be as low as possible, but too low may break functionality Value 3128 + BrowserProxyType + + Comment + Type of proxy for Web Browser + Persist + 1 + Type + S32 + Value + 0 + + BrowserProxyUsername + + Comment + Username for Web Proxy authentication + Persist + 1 + Type + String + Value + + + BrowserProxyPassword + + Comment + Password for Web Proxy authentication + Persist + 1 + Type + String + Value + + BrowserProxySocks45 Comment diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 7c991e4d4..cc9628d2a 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -70,7 +70,7 @@ #include "lldxhardware.h" #endif -#include "cef/llceflib.h" +#include "cef/dullahan.h" extern LLMemoryInfo gSysMemory; extern U32 gPacketsIn; @@ -286,8 +286,17 @@ LLFloaterAbout::LLFloaterAbout() support.append( gAudiop ? gAudiop->getDriverName(want_fullname) : "(none)" ); support += '\n'; - support.append("LLCEFLib/CEF Version: "); - support.append(LLCEFLIB_VERSION); + std::stringstream supportstrm; + supportstrm << "Dullahan: " + << DULLAHAN_VERSION_MAJOR + << '.' + << DULLAHAN_VERSION_MINOR + << '.' + << DULLAHAN_VERSION_BUILD + + << " / CEF: " << CEF_VERSION + << " / Chrome: " << CHROME_VERSION_MAJOR; + support += supportstrm.str(); support += '\n'; if (gPacketsIn > 0) diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 577d2a4b6..a65c25338 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -99,6 +99,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : mTextureWidth ( 1024 ), mTextureHeight ( 1024 ), mClearCache(false), + mUpdateScrolls( false ), mHomePageMimeType(p.initial_mime_type), mErrorPageURL(p.error_page_url), mTrusted(p.trusted_content), @@ -143,7 +144,7 @@ LLMediaCtrl::~LLMediaCtrl() if (mMediaSource) { mMediaSource->remObserver( this ); - mMediaSource = NULL; + mMediaSource = nullptr; } } @@ -395,6 +396,12 @@ void LLMediaCtrl::onOpenWebInspector() mMediaSource->getMediaPlugin()->showWebInspector( true ); } +void LLMediaCtrl::onShowSource() +{ + if (mMediaSource && mMediaSource->hasMedia()) + mMediaSource->getMediaPlugin()->showPageSource(); +} + //////////////////////////////////////////////////////////////////////////////// // BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) @@ -514,6 +521,16 @@ void LLMediaCtrl::navigateForward() } } +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::navigateStop() +{ + if (mMediaSource && mMediaSource->hasMedia()) + { + mMediaSource->getMediaPlugin()->browse_stop(); + } +} + //////////////////////////////////////////////////////////////////////////////// // bool LLMediaCtrl::canNavigateBack() @@ -549,22 +566,6 @@ void LLMediaCtrl::clearCache() } -//////////////////////////////////////////////////////////////////////////////// -// -void LLMediaCtrl::set404RedirectUrl( std::string redirect_url ) -{ - if(mMediaSource && mMediaSource->hasMedia()) - mMediaSource->getMediaPlugin()->set_status_redirect( 404, redirect_url ); -} - -//////////////////////////////////////////////////////////////////////////////// -// -void LLMediaCtrl::clr404RedirectUrl() -{ - if(mMediaSource && mMediaSource->hasMedia()) - mMediaSource->getMediaPlugin()->set_status_redirect(404, ""); -} - //////////////////////////////////////////////////////////////////////////////// // void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) @@ -582,12 +583,9 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) if (ensureMediaSourceExists()) { - if (mCurrentNavUrl != url_in) - { - mCurrentNavUrl = url_in; - mMediaSource->setSize(mTextureWidth, mTextureHeight); - mMediaSource->navigateTo(url_in, mime_type, mime_type.empty()); - } + mCurrentNavUrl = url_in; + mMediaSource->setSize(mTextureWidth, mTextureHeight); + mMediaSource->navigateTo(url_in, mime_type, mime_type.empty()); } } @@ -609,7 +607,6 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str mMediaSource->setSize(mTextureWidth, mTextureHeight); mMediaSource->navigateTo(LLWeb::escapeURL(expanded_filename), "text/html", false); } - } //////////////////////////////////////////////////////////////////////////////// @@ -699,7 +696,13 @@ bool LLMediaCtrl::ensureMediaSourceExists() mMediaSource->addObserver( this ); mMediaSource->setBackgroundColor( getBackgroundColor() ); mMediaSource->setTrustedBrowser(mTrusted); - mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); + + F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; + if (scale_factor != mMediaSource->getPageZoomFactor()) + { + mMediaSource->setPageZoomFactor( scale_factor ); + mUpdateScrolls = true; + } if(mClearCache) { @@ -721,7 +724,11 @@ bool LLMediaCtrl::ensureMediaSourceExists() // void LLMediaCtrl::unloadMediaSource() { - mMediaSource = NULL; + if (mMediaSource) + { + mMediaSource->remObserver(this); + mMediaSource = nullptr; + } } //////////////////////////////////////////////////////////////////////////////// @@ -735,10 +742,11 @@ LLPluginClassMedia* LLMediaCtrl::getMediaPlugin() // void LLMediaCtrl::draw() { - if ( gRestoreGL == 1 ) + if ( gRestoreGL == 1 || mUpdateScrolls) { LLRect r = getRect(); reshape( r.getWidth(), r.getHeight(), FALSE ); + mUpdateScrolls = false; return; } @@ -784,7 +792,12 @@ void LLMediaCtrl::draw() { gGL.pushUIMatrix(); { - mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] ); + F32 scale_factor = LLUI::getScaleFactor().mV[ VX ]; + if (scale_factor != mMediaSource->getPageZoomFactor()) + { + mMediaSource->setPageZoomFactor( scale_factor ); + mUpdateScrolls = true; + } // scale texture to fit the space using texture coords gGL.getTexUnit(0)->bind(media_texture); diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 02f4558d0..7c4c785ca 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -37,6 +37,7 @@ #include "lluictrl.h" #include "llframetimer.h" +#include "llnotificationptr.h" class LLViewBorder; class LLUICtrlFactory; @@ -51,6 +52,7 @@ class LLMediaCtrl : { LOG_CLASS(LLMediaCtrl); public: + struct Params : public LLInitParam::Block { Optional start_url; @@ -92,20 +94,21 @@ public: static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); // handle mouse related methods - virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); - virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); - virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); - virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); - virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); - virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); - virtual BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen); + BOOL handleHover( S32 x, S32 y, MASK mask ) override; + BOOL handleMouseUp( S32 x, S32 y, MASK mask ) override; + BOOL handleMouseDown( S32 x, S32 y, MASK mask ) override; + BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override; + BOOL handleRightMouseUp(S32 x, S32 y, MASK mask) override; + BOOL handleDoubleClick( S32 x, S32 y, MASK mask ) override; + BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ) override; + 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 navigateBack(); void navigateHome(); void navigateForward(); + void navigateStop(); void navigateToLocalPage( const std::string& subdir, const std::string& filename_in ); bool canNavigateBack(); bool canNavigateForward(); @@ -128,9 +131,6 @@ public: // Clear the browser cache when the instance gets loaded void clearCache(); - void set404RedirectUrl( std::string redirect_url ); - void clr404RedirectUrl(); - // accessor/mutator for flag that indicates if frequent updates to texture happen bool getFrequentUpdates() { return mFrequentUpdates; }; void setFrequentUpdates( bool frequentUpdatesIn ) { mFrequentUpdates = frequentUpdatesIn; }; @@ -153,35 +153,38 @@ public: void setTextureSize(S32 width, S32 height); - void showNotification(boost::shared_ptr notify); + void showNotification(LLNotificationPtr notify); void hideNotification(); void setTrustedContent(bool trusted); // over-rides - virtual BOOL handleKeyHere( KEY key, MASK mask); - virtual BOOL handleKeyUpHere(KEY key, MASK mask); - virtual void handleVisibilityChange ( BOOL new_visibility ); - virtual BOOL handleUnicodeCharHere(llwchar uni_char); - virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE); - virtual void draw(); - virtual BOOL postBuild(); + BOOL handleKeyHere( KEY key, MASK mask) override; + BOOL handleKeyUpHere(KEY key, MASK mask) override; + void handleVisibilityChange ( BOOL new_visibility ) override; + BOOL handleUnicodeCharHere(llwchar uni_char) override; + void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE) override; + void draw() override; + BOOL postBuild() override; // focus overrides - void onFocusLost(); - void onFocusReceived(); + void onFocusLost() override; + void onFocusReceived() override; // Incoming media event dispatcher - virtual void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override; // right click debugging item void onOpenWebInspector(); + void onShowSource(); LLUUID getTextureID() {return mMediaTextureID;} // The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true. - virtual bool wantsKeyUpKeyDown() const; - virtual bool wantsReturnKey() const; + bool wantsKeyUpKeyDown() const override; + bool wantsReturnKey() const override; + + virtual BOOL acceptsTextInput() const override { return TRUE; } protected: void convertInputCoords(S32& x, S32& y); @@ -204,7 +207,8 @@ public: mHidingInitialLoad, mClearCache, mHoverTextChanged, - mDecoupleTextureSize; + mDecoupleTextureSize, + mUpdateScrolls; std::string mHomePageUrl, mHomePageMimeType, diff --git a/indra/newview/llpaneldirfind.cpp b/indra/newview/llpaneldirfind.cpp index 7c7a7c21c..2cd261ae5 100644 --- a/indra/newview/llpaneldirfind.cpp +++ b/indra/newview/llpaneldirfind.cpp @@ -243,9 +243,6 @@ BOOL LLPanelDirFind::postBuild() // need to handle secondlife:///app/ URLs for direct teleports mWebBrowser->setTrustedContent( true ); - // redirect 404 pages from S3 somewhere else - mWebBrowser->set404RedirectUrl( getString("redirect_404_url") ); - navigateToDefaultPage(); } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 7dc6e325c..847e5e225 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1263,7 +1263,7 @@ void LLViewerMedia::setCookiesEnabled(bool enabled) LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); if(plugin) { - plugin->enable_cookies(enabled); + plugin->cookies_enabled(enabled); } } } @@ -1281,7 +1281,7 @@ void LLViewerMedia::setProxyConfig(bool enable, const std::string &host, int por LLPluginClassMedia* plugin = pimpl->getMediaPlugin(); if(plugin) { - plugin->proxy_setup(enable, host, port); + //pimpl->mMediaSource->proxy_setup(enable, host, port); } } } @@ -1894,7 +1894,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ // collect 'cookies enabled' setting from prefs and send to embedded browser bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" ); - media_source->enable_cookies( cookies_enabled ); + media_source->cookies_enabled( cookies_enabled ); // collect 'plugins enabled' setting from prefs and send to embedded browser bool plugins_enabled = gSavedSettings.getBOOL( "BrowserPluginsEnabled" ); @@ -1988,24 +1988,14 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "ca-bundle.crt" ); media_source->addCertificateFilePath( ca_path ); - media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); + media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getS32("BrowserProxyType"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort"), + gSavedSettings.getString("BrowserProxyUsername"), gSavedSettings.getString("BrowserProxyPassword")); if(mClearCache) { mClearCache = false; media_source->clear_cache(); } - - // TODO: Only send cookies to plugins that need them - // Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message. - // Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message, - // which could cause odd race conditions. - std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies(); - LL_DEBUGS() << "setting cookies: " << all_cookies << LL_ENDL; - if(!all_cookies.empty()) - { - media_source->set_cookies(all_cookies); - } mPluginBase = media_source; mPluginBase->setDeleteOK(false) ; @@ -2918,7 +2908,7 @@ void LLViewerMediaImpl::update() { LL_RECORD_BLOCK_TIME(FTM_MEDIA_DO_UPDATE); LLPluginClassMedia* mMediaSource = getMediaPlugin(); - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { if(mPriority == PRIORITY_UNLOADED) { @@ -2953,17 +2943,10 @@ void LLViewerMediaImpl::update() // 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); - } } - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { return; } @@ -2976,7 +2959,7 @@ void LLViewerMediaImpl::update() setNavigateSuspended(false); mMediaSource = getMediaPlugin(); - if(mMediaSource == NULL) + if(mMediaSource == nullptr) { return; } @@ -3018,12 +3001,14 @@ void LLViewerMediaImpl::update() if(width > 0 && height > 0) { - U8* data = NULL; + U8* data = nullptr; { LL_RECORD_BLOCK_TIME(FTM_MEDIA_GET_DATA); data = mMediaSource->getBitsData(); } + if(data != NULL) + { // Offset the pixels pointer to match x_pos and y_pos data += ( x_pos * mMediaSource->getTextureDepth() * mMediaSource->getBitsWidth() ); data += ( y_pos * mMediaSource->getTextureDepth() ); @@ -3039,6 +3024,7 @@ void LLViewerMediaImpl::update() width, height, TRUE); // + } } } @@ -3061,7 +3047,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage() if(mTextureId.isNull()) { // The code that created this instance will read from the plugin's bits. - return NULL; + return nullptr; } LLViewerMediaTexture* placeholder_image = LLViewerTextureManager::getMediaTexture( mTextureId ); @@ -3299,7 +3285,7 @@ bool LLViewerMediaImpl::isPlayable() const static void handle_pick_file_request_continued(LLPluginClassMedia* plugin, AIFilePicker* filepicker) { - plugin->sendPickFileResponse(filepicker->hasFilename() ? filepicker->getFilename() : LLStringUtil::null); + plugin->sendPickFileResponse(filepicker->hasFilename() ? filepicker->getFilenames() : std::vector()); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -3313,7 +3299,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL; std::string url = plugin->getClickURL(); std::string nav_type = plugin->getClickNavType(); - LLURLDispatcher::dispatch(url, nav_type, NULL, mTrustedBrowser); + LLURLDispatcher::dispatch(url, nav_type, nullptr, mTrustedBrowser); } break; case MEDIA_EVENT_CLICK_LINK_HREF: diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 4b552ca10..81eacc728 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -9342,6 +9342,31 @@ class ListToggleMute : public view_listener_t } }; +LLMediaCtrl* get_focused_media_ctrl() +{ + auto media_ctrl = dynamic_cast(gFocusMgr.getKeyboardFocus()); + llassert(media_ctrl); // This listener only applies to media_ctrls + return media_ctrl; +} + +class MediaCtrlWebInspector : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + get_focused_media_ctrl()->onOpenWebInspector(); + return true; + } +}; + +class MediaCtrlViewSource : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + get_focused_media_ctrl()->onShowSource(); + return true; + } +}; + struct MarketplaceViewSortAction : view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -9693,6 +9718,10 @@ void initialize_menus() LLTextEditor::setIsFriendCallback(LLAvatarActions::isFriend); LLTextEditor::addMenuListeners(); + // Media Ctrl menus + addMenu(new MediaCtrlWebInspector(), "Open.WebInspector"); + addMenu(new MediaCtrlViewSource(), "Open.ViewSource"); + addMenu(new MarketplaceViewSortAction, "Marketplace.ViewSort.Action"); addMenu(new MarketplaceViewSortCheckItem, "Marketplace.ViewSort.CheckItem"); diff --git a/indra/newview/skins/default/xui/en-us/floater_directory.xml b/indra/newview/skins/default/xui/en-us/floater_directory.xml index e28adc65e..bb1c73401 100644 --- a/indra/newview/skins/default/xui/en-us/floater_directory.xml +++ b/indra/newview/skins/default/xui/en-us/floater_directory.xml @@ -142,9 +142,6 @@ Done - - http://secondlife.com/app/search/notfound.html - "http://secondlife.com/app/search/index.php?" @@ -158,7 +155,6 @@ Loading... Done - [APP_SITE]/404 http://search.secondlife.com/ Loading... Done - http://secondlife.com/app/search/notfound.html "http://secondlife.com/app/showcase/index.php?" Loading... Done - [APP_SITE]/404 https://marketplace.secondlife.com/ diff --git a/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml b/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml index ca9deedcc..51bd82c17 100644 --- a/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml +++ b/indra/newview/skins/default/xui/en-us/menu_media_ctrl.xml @@ -1,6 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index bfe32112c..e74dbd377 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -370,32 +370,30 @@ class WindowsManifest(ViewerManifest): self.end_prefix() # CEF runtime files - debug - if self.args['configuration'].lower() == 'debug': - if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'debug'), dst="llplugin"): - self.path("d3dcompiler_47.dll") - self.path("libcef.dll") - self.path("libEGL.dll") - self.path("libGLESv2.dll") - self.path("llceflib_host.exe") - self.path("natives_blob.bin") - self.path("snapshot_blob.bin") - self.path("widevinecdmadapter.dll") - self.path("wow_helper.exe") - self.end_prefix() - else: # CEF runtime files - not debug (release, relwithdebinfo etc.) - if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', 'release'), dst="llplugin"): + config = 'debug' if self.args['configuration'].lower() == 'debug' else 'release' + if self.prefix(src=os.path.join(os.pardir, 'packages', 'bin', config), dst="llplugin"): + self.path("chrome_elf.dll") self.path("d3dcompiler_47.dll") self.path("libcef.dll") self.path("libEGL.dll") self.path("libGLESv2.dll") - self.path("llceflib_host.exe") + self.path("dullahan_host.exe") self.path("natives_blob.bin") self.path("snapshot_blob.bin") + self.path("v8_context_snapshot.bin") self.path("widevinecdmadapter.dll") - self.path("wow_helper.exe") + self.end_prefix() + # CEF runtime files for software rendering - debug + # CEF runtime files for software rendering - not debug (release, relwithdebinfo etc.) + if self.prefix(src=os.path.join(pkgdir, 'bin', config, 'swiftshader'), dst=os.path.join("llplugin", 'swiftshader')): + self.path("libEGL.dll") + self.path("libGLESv2.dll") + self.end_prefix() + + # CEF files common to all configurations if self.prefix(src=os.path.join(os.pardir, 'packages', 'resources'), dst="llplugin"): self.path("cef.pak") @@ -462,6 +460,7 @@ class WindowsManifest(ViewerManifest): self.path("zh-TW.pak") self.end_prefix() + if not self.is_packaging_viewer(): self.package_file = "copied_deps" diff --git a/indra/plugins/cef/media_plugin_cef.cpp b/indra/plugins/cef/media_plugin_cef.cpp index 49101214f..7e6064c87 100644 --- a/indra/plugins/cef/media_plugin_cef.cpp +++ b/indra/plugins/cef/media_plugin_cef.cpp @@ -39,11 +39,13 @@ #include "llplugininstance.h" #include "llpluginmessage.h" #include "llpluginmessageclasses.h" +#include "volume_catcher.h" #include "media_plugin_base.h" #include -#include "llceflib.h" -#include "volume_catcher.h" +#include + +#include "dullahan.h" //////////////////////////////////////////////////////////////////////////////// // @@ -60,7 +62,7 @@ public: private: bool init(); - void onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup); + void onPageChangedCallback(const unsigned char* pixels, int x, int y, const int width, const int height); void onCustomSchemeURLCallback(std::string url); void onConsoleMessageCallback(std::string message, std::string source, int line); void onStatusMessageCallback(std::string value); @@ -68,41 +70,54 @@ 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); - bool onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password); - void onCursorChangedCallback(LLCEFLib::ECursorType type, unsigned int handle); - void onFileDownloadCallback(std::string filename); + void onOpenPopupCallback(std::string url, std::string target); + bool onHTTPAuthCallback(const std::string host, const std::string realm, bool isproxy, std::string& username, std::string& password); + void onCursorChangedCallback(dullahan::ECursorType type); + const std::vector 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); - LLCEFLib::EKeyboardModifier decodeModifiers(std::string &modifiers); - void deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers); - void keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data); - void unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data); + void keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_data); + void unicodeInput(std::string event, LLSD native_key_data); void checkEditState(); - void setVolume(F32 vol); + void setVolume(); bool mEnableMediaPluginDebugging; std::string mHostLanguage; bool mCookiesEnabled; bool mPluginsEnabled; bool mJavascriptEnabled; + bool mDisableGPU; std::string mUserAgentSubtring; std::string mAuthUsername; std::string mAuthPassword; bool mAuthOK; + bool mCanUndo; + bool mCanRedo; bool mCanCut; bool mCanCopy; bool mCanPaste; + bool mCanDelete; + bool mCanSelectAll; + std::string mUserDataPath; std::string mCachePath; std::string mCookiePath; - std::string mLogFile; - LLCEFLib* mLLCEFLib; - + std::string mCefLogFile; + bool mCefLogVerbose; + std::vector mPickedFiles; + bool mProxyEnabled; + int mProxyType; + std::string mProxyHost; + int mProxyPort; + std::string mProxyUsername; + std::string mProxyPassword; VolumeCatcher mVolumeCatcher; + F32 mCurVolume; + dullahan* mCEFLib; }; //////////////////////////////////////////////////////////////////////////////// @@ -119,17 +134,33 @@ MediaPluginCEF::MediaPluginCEF(LLPluginInstance::sendMessageFunction send_messag mCookiesEnabled = true; mPluginsEnabled = false; mJavascriptEnabled = true; + mDisableGPU = false; mUserAgentSubtring = ""; mAuthUsername = ""; mAuthPassword = ""; mAuthOK = false; + mCanUndo = false; + mCanRedo = false; mCanCut = false; mCanCopy = false; mCanPaste = false; + mCanDelete = false; + mCanSelectAll = false; + mUserDataPath = ""; mCachePath = ""; mCookiePath = ""; - mLogFile = ""; - mLLCEFLib = new LLCEFLib(); + mCefLogFile = ""; + mCefLogVerbose = false; + mPickedFiles.clear(); + mCurVolume = 0.0f; + + mProxyEnabled = false; + mProxyType = 0; + mProxyPort = 3128; + + mCEFLib = new dullahan(); + + setVolume(); } //////////////////////////////////////////////////////////////////////////////// @@ -156,31 +187,17 @@ void MediaPluginCEF::postDebugMessage(const std::string& msg) //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::onPageChangedCallback(unsigned char* pixels, int x, int y, int width, int height, bool is_popup) +void MediaPluginCEF::onPageChangedCallback(const unsigned char* pixels, int x, int y, const int width, const int height) { if (mPixels && pixels) { - if (is_popup) + if (mWidth == width && mHeight == height) { - for (int line = 0; line < height; ++line) - { - int inverted_y = mHeight - y - height; - int src = line * width * mDepth; - int dst = (inverted_y + line) * mWidth * mDepth + x * mDepth; - - if (dst + width * mDepth < mWidth * mHeight * mDepth) - { - memcpy(mPixels + dst, pixels + src, width * mDepth); - } - } + memcpy(mPixels, pixels, mWidth * mHeight * mDepth); } else { - if (mWidth == width && mHeight == height) - { - memcpy(mPixels, pixels, mWidth * mHeight * mDepth); - } - + mCEFLib->setSize(mWidth, mHeight); } setDirty(0, 0, mWidth, mHeight); } @@ -210,6 +227,8 @@ void MediaPluginCEF::onTitleChangeCallback(std::string title) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text"); message.setValue("name", title); + message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); sendMessage(message); } @@ -219,16 +238,31 @@ void MediaPluginCEF::onLoadStartCallback() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? - message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); sendMessage(message); } +///////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onLoadError(int status, const std::string error_text) +{ + std::stringstream msg; + + msg << "Loading error!"; + msg << "

"; + msg << "Message: " << error_text; + msg << "
"; + msg << "Code: " << status; + + mCEFLib->showBrowserMessage(msg.str()); +} + //////////////////////////////////////////////////////////////////////////////// // void MediaPluginCEF::onRequestExitCallback() { - mLLCEFLib->shutdown(); + mCEFLib->shutdown(); LLPluginMessage message("base", "goodbye"); sendMessage(message); @@ -241,8 +275,8 @@ void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? message.setValueS32("result_code", httpStatusCode); - message.setValueBoolean("history_back_available", mLLCEFLib->canGoBack()); - message.setValueBoolean("history_forward_available", mLLCEFLib->canGoForward()); + message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); + message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); sendMessage(message); } @@ -257,12 +291,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); } @@ -278,8 +311,16 @@ void MediaPluginCEF::onCustomSchemeURLCallback(std::string url) //////////////////////////////////////////////////////////////////////////////// // -bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::string realm, std::string& username, std::string& password) +bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::string realm, bool isproxy, std::string& username, std::string& password) { + // For proxy auth + if (isproxy) + { + username = mProxyUsername; + password = mProxyPassword; + return true; + } + // Otherwise fall through for other auth routines mAuthOK = false; LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request"); @@ -301,35 +342,71 @@ bool MediaPluginCEF::onHTTPAuthCallback(const std::string host, const std::strin //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::onFileDownloadCallback(const std::string filename) +const std::vector MediaPluginCEF::onFileDialog(dullahan::EFileDialogType dialog_type, const std::string dialog_title, const std::string default_file, std::string dialog_accept_filter, bool& use_default) { + // do not use the default CEF file picker + use_default = false; + + if (dialog_type == dullahan::FD_OPEN_FILE) + { + mPickedFiles.clear(); + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file"); + message.setValueBoolean("blocking_request", true); + message.setValueBoolean("multiple_files", false); + + sendMessage(message); + + return mPickedFiles; + } + else if (dialog_type == dullahan::FD_OPEN_MULTIPLE_FILES) + { + mPickedFiles.clear(); + + 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", filename); + message.setValue("filename", default_file); sendMessage(message); + + return std::vector(); + } + + return std::vector(); } -void MediaPluginCEF::onCursorChangedCallback(LLCEFLib::ECursorType type, unsigned int handle) +//////////////////////////////////////////////////////////////////////////////// +// +void MediaPluginCEF::onCursorChangedCallback(dullahan::ECursorType type) { std::string name = ""; switch (type) { - case LLCEFLib::CT_POINTER: + case dullahan::CT_POINTER: name = "arrow"; break; - case LLCEFLib::CT_IBEAM: + case dullahan::CT_IBEAM: name = "ibeam"; break; - case LLCEFLib::CT_NORTHSOUTHRESIZE: + case dullahan::CT_NORTHSOUTHRESIZE: name = "splitv"; break; - case LLCEFLib::CT_EASTWESTRESIZE: + case dullahan::CT_EASTWESTRESIZE: name = "splith"; break; - case LLCEFLib::CT_HAND: + case dullahan::CT_HAND: name = "hand"; break; @@ -343,6 +420,8 @@ void MediaPluginCEF::onCursorChangedCallback(LLCEFLib::ECursorType type, unsigne sendMessage(message); } +//////////////////////////////////////////////////////////////////////////////// +// void MediaPluginCEF::authResponse(LLPluginMessage &message) { mAuthOK = message.getValueBoolean("ok"); @@ -353,21 +432,20 @@ void MediaPluginCEF::authResponse(LLPluginMessage &message) } } -//////////////////////////////////////////////////////////////////////////////// -// std::string generate_cef_locale(std::string in) { if (in == "en") in = "en-US"; else if (in == "pt") - in = "pt-BR"; + in = "pt-PT"; else if (in == "zh") in = "zh-CN"; return in; } - +//////////////////////////////////////////////////////////////////////////////// +// void MediaPluginCEF::receiveMessage(const char* message_string) { // std::cerr << "MediaPluginCEF::receiveMessage: received message: \"" << message_string << "\"" << std::endl; @@ -388,13 +466,13 @@ 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); } else if (message_name == "idle") { - mLLCEFLib->update(); + mCEFLib->update(); mVolumeCatcher.pump(); // this seems bad but unless the state changes (it won't until we figure out @@ -404,7 +482,8 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (message_name == "cleanup") { - mLLCEFLib->requestExit(); + mVolumeCatcher.setVolume(0); + mCEFLib->requestExit(); } else if (message_name == "shm_added") { @@ -446,43 +525,67 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { if (message_name == "init") { - // event callbacks from LLCefLib - mLLCEFLib->setOnPageChangedCallback(std::bind(&MediaPluginCEF::onPageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5, std::placeholders::_6)); - mLLCEFLib->setOnCustomSchemeURLCallback(std::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, std::placeholders::_1)); - mLLCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); - mLLCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1)); - mLLCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1)); - mLLCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this)); - mLLCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1)); - mLLCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1)); - mLLCEFLib->setOnNavigateURLCallback(std::bind(&MediaPluginCEF::onNavigateURLCallback, this, std::placeholders::_1, std::placeholders::_2)); - mLLCEFLib->setOnHTTPAuthCallback(std::bind(&MediaPluginCEF::onHTTPAuthCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4)); - mLLCEFLib->setOnFileDownloadCallback(std::bind(&MediaPluginCEF::onFileDownloadCallback, this, std::placeholders::_1)); - mLLCEFLib->setOnCursorChangedCallback(std::bind(&MediaPluginCEF::onCursorChangedCallback, this, std::placeholders::_1, std::placeholders::_2)); - mLLCEFLib->setOnRequestExitCallback(std::bind(&MediaPluginCEF::onRequestExitCallback, this)); + // event callbacks from Dullahan + mCEFLib->setOnPageChangedCallback(std::bind(&MediaPluginCEF::onPageChangedCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); + mCEFLib->setOnCustomSchemeURLCallback(std::bind(&MediaPluginCEF::onCustomSchemeURLCallback, this, std::placeholders::_1)); + mCEFLib->setOnConsoleMessageCallback(std::bind(&MediaPluginCEF::onConsoleMessageCallback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + mCEFLib->setOnStatusMessageCallback(std::bind(&MediaPluginCEF::onStatusMessageCallback, this, std::placeholders::_1)); + 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->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, std::placeholders::_5)); + 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)); - LLCEFLib::LLCEFLibSettings settings; - settings.initial_width = 1024; - settings.initial_height = 1024; - settings.plugins_enabled = mPluginsEnabled; - settings.media_stream_enabled = false; // MAINT-6060 - WebRTC media removed until we can add granualrity/query UI - settings.javascript_enabled = mJavascriptEnabled; - settings.cookies_enabled = mCookiesEnabled; - settings.cookie_store_path = mCookiePath; + dullahan::dullahan_settings settings; + settings.accept_language_list = generate_cef_locale(mHostLanguage); + settings.background_color = 0xff282828; settings.cache_enabled = true; settings.cache_path = mCachePath; + settings.cookie_store_path = mCookiePath; + settings.cookies_enabled = mCookiesEnabled; + settings.disable_gpu = mDisableGPU; + settings.flash_enabled = mPluginsEnabled; + settings.flip_mouse_y = false; + settings.flip_pixels_y = true; + settings.frame_rate = 60; + settings.force_wave_audio = true; + settings.initial_height = 1024; + settings.initial_width = 1024; + settings.java_enabled = false; + settings.javascript_enabled = mJavascriptEnabled; settings.locale = generate_cef_locale(mHostLanguage); - settings.accept_language_list = mHostLanguage; - settings.user_agent_substring = mLLCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring); - settings.debug_output = mEnableMediaPluginDebugging; - settings.log_file = mLogFile; + settings.media_stream_enabled = false; // MAINT-6060 - WebRTC media removed until we can add granualrity/query UI + settings.plugins_enabled = mPluginsEnabled; + settings.user_agent_substring = mCEFLib->makeCompatibleUserAgentString(mUserAgentSubtring); + settings.user_data_path = mUserDataPath; + settings.webgl_enabled = true; + settings.log_file = mCefLogFile; + settings.log_verbose = mEnableMediaPluginDebugging; + settings.proxy_enabled = mProxyEnabled; + settings.proxy_type = mProxyType; + settings.proxy_host = mProxyHost; + settings.proxy_port = mProxyPort; - bool result = mLLCEFLib->init(settings); + std::vector custom_schemes; + custom_schemes.emplace_back("secondlife"); + custom_schemes.emplace_back("x-grid-info"); + custom_schemes.emplace_back("x-grid-location-info"); + mCEFLib->setCustomSchemes(custom_schemes); + + bool result = mCEFLib->init(settings); if (!result) { // if this fails, the media system in viewer will put up a message } + // now we can set page zoom factor + mCEFLib->setPageZoom(message_in.getValueReal("factor")); + // Plugin gets to decide the texture parameters to use. mDepth = 4; LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); @@ -499,10 +602,12 @@ 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"); - std::string user_data_path_logs = message_in.getValue("logs_path"); + + + mUserDataPath = user_data_path_cache + "cef_data"; mCachePath = user_data_path_cache + "cef_cache"; mCookiePath = user_data_path_cookies + "cef_cookies"; - mLogFile = user_data_path_logs + "cef.log"; + mCefLogFile = message_in.getValue("cef_log_file"); } else if (message_name == "size_change") { @@ -524,11 +629,11 @@ void MediaPluginCEF::receiveMessage(const char* message_string) mTextureWidth = texture_width; mTextureHeight = texture_height; + + mCEFLib->setSize(mWidth, mHeight); }; }; - mLLCEFLib->setSize(mWidth, mHeight); - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); message.setValue("name", name); message.setValueS32("width", width); @@ -545,7 +650,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) else if (message_name == "load_uri") { std::string uri = message_in.getValue("uri"); - mLLCEFLib->navigate(uri); + mCEFLib->navigate(uri); } else if (message_name == "set_cookie") { @@ -556,7 +661,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) std::string path = message_in.getValue("path"); bool httponly = message_in.getValueBoolean("httponly"); bool secure = message_in.getValueBoolean("secure"); - mLLCEFLib->setCookie(uri, name, value, domain, path, httponly, secure); + mCEFLib->setCookie(uri, name, value, domain, path, httponly, secure); } else if (message_name == "mouse_event") { @@ -565,16 +670,16 @@ void MediaPluginCEF::receiveMessage(const char* message_string) S32 x = message_in.getValueS32("x"); S32 y = message_in.getValueS32("y"); - // only even send left mouse button events to LLCEFLib + // only even send left mouse button events to the CEF library // (partially prompted by crash in OS X CEF when sending right button events) // we catch the right click in viewer and display our own context menu anyway S32 button = message_in.getValueS32("button"); - LLCEFLib::EMouseButton btn = LLCEFLib::MB_MOUSE_BUTTON_LEFT; + dullahan::EMouseButton btn = dullahan::MB_MOUSE_BUTTON_LEFT; if (event == "down" && button == 0) { - mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOWN, x, y); - mLLCEFLib->setFocus(true); + mCEFLib->mouseButton(btn, dullahan::ME_MOUSE_DOWN, x, y); + mCEFLib->setFocus(); std::stringstream str; str << "Mouse down at = " << x << ", " << y; @@ -582,7 +687,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (event == "up" && button == 0) { - mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_UP, x, y); + mCEFLib->mouseButton(btn, dullahan::ME_MOUSE_UP, x, y); std::stringstream str; str << "Mouse up at = " << x << ", " << y; @@ -590,11 +695,11 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } else if (event == "double_click") { - mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOUBLE_CLICK, x, y); + mCEFLib->mouseButton(btn, dullahan::ME_MOUSE_DOUBLE_CLICK, x, y); } else { - mLLCEFLib->mouseMove(x, y); + mCEFLib->mouseMove(x, y); } } else if (message_name == "scroll_event") @@ -604,89 +709,100 @@ void MediaPluginCEF::receiveMessage(const char* message_string) const int scaling_factor = 40; y *= -scaling_factor; - mLLCEFLib->mouseWheel(x, y); + mCEFLib->mouseWheel(x, y); } else if (message_name == "text_event") { - std::string text = message_in.getValue("text"); - std::string modifiers = message_in.getValue("modifiers"); + std::string event = message_in.getValue("event"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); - - unicodeInput(text, decodeModifiers(modifiers), native_key_data); + unicodeInput(event, native_key_data); } else if (message_name == "key_event") { #if LL_DARWIN std::string event = message_in.getValue("event"); - S32 key = message_in.getValueS32("key"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); -#if 0 - if (event == "down") - { - //mLLCEFLib->keyPress(key, true); - mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)key, 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); - - } - else if (event == "up") - { - //mLLCEFLib->keyPress(key, false); - mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_UP, (uint32_t)key, 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); - } -#else - // Treat unknown events as key-up for safety. - LLCEFLib::EKeyEvent key_event = LLCEFLib::KE_KEY_UP; + dullahan::EKeyEvent key_event = dullahan::KE_KEY_UP; if (event == "down") { - key_event = LLCEFLib::KE_KEY_DOWN; + key_event = dullahan::KE_KEY_DOWN; } else if (event == "repeat") { - key_event = LLCEFLib::KE_KEY_REPEAT; + key_event = dullahan::KE_KEY_REPEAT; } - keyEvent(key_event, key, LLCEFLib::KM_MODIFIER_NONE, native_key_data); + keyEvent(key_event, native_key_data); -#endif #else std::string event = message_in.getValue("event"); - S32 key = message_in.getValueS32("key"); - std::string modifiers = message_in.getValue("modifiers"); LLSD native_key_data = message_in.getValueLLSD("native_key_data"); // Treat unknown events as key-up for safety. - LLCEFLib::EKeyEvent key_event = LLCEFLib::KE_KEY_UP; + dullahan::EKeyEvent key_event = dullahan::KE_KEY_UP; if (event == "down") { - key_event = LLCEFLib::KE_KEY_DOWN; + key_event = dullahan::KE_KEY_DOWN; } else if (event == "repeat") { - key_event = LLCEFLib::KE_KEY_REPEAT; + key_event = dullahan::KE_KEY_REPEAT; } - keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data); + keyEvent(key_event, native_key_data); #endif } else if (message_name == "enable_media_plugin_debugging") { mEnableMediaPluginDebugging = message_in.getValueBoolean("enable"); } + if (message_name == "pick_file_response") + { + 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") { authResponse(message_in); } + if (message_name == "edit_undo") + { + mCEFLib->editUndo(); + } + if (message_name == "edit_redo") + { + mCEFLib->editRedo(); + } if (message_name == "edit_cut") { - mLLCEFLib->editCut(); + mCEFLib->editCut(); } if (message_name == "edit_copy") { - mLLCEFLib->editCopy(); + mCEFLib->editCopy(); } if (message_name == "edit_paste") { - mLLCEFLib->editPaste(); + mCEFLib->editPaste(); + } + if (message_name == "edit_delete") + { + mCEFLib->editDelete(); + } + if (message_name == "edit_select_all") + { + mCEFLib->editSelectAll(); + } + if (message_name == "edit_show_source") + { + mCEFLib->viewSource(); } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER) @@ -694,36 +810,40 @@ void MediaPluginCEF::receiveMessage(const char* message_string) if (message_name == "set_page_zoom_factor") { F32 factor = (F32)message_in.getValueReal("factor"); - mLLCEFLib->setPageZoom(factor); + mCEFLib->setPageZoom(factor); } if (message_name == "browse_stop") { - mLLCEFLib->stop(); + mCEFLib->stop(); } else if (message_name == "browse_reload") { bool ignore_cache = true; - mLLCEFLib->reload(ignore_cache); + mCEFLib->reload(ignore_cache); } else if (message_name == "browse_forward") { - mLLCEFLib->goForward(); + mCEFLib->goForward(); } else if (message_name == "browse_back") { - mLLCEFLib->goBack(); + mCEFLib->goBack(); } else if (message_name == "cookies_enabled") { 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"); } else if (message_name == "show_web_inspector") { - mLLCEFLib->showDevTools(true); + mCEFLib->showDevTools(); } else if (message_name == "plugins_enabled") { @@ -733,13 +853,27 @@ void MediaPluginCEF::receiveMessage(const char* message_string) { mJavascriptEnabled = message_in.getValueBoolean("enable"); } + else if (message_name == "gpu_disabled") + { + mDisableGPU = message_in.getValueBoolean("disable"); + } + else if (message_name == "proxy_setup") + { + mProxyEnabled = message_in.getValueBoolean("enable"); + mProxyType = message_in.getValueS32("proxy_type"); + mProxyHost = message_in.getValue("host"); + mProxyPort = message_in.getValueS32("port"); + mProxyUsername = message_in.getValue("username"); + mProxyPassword = message_in.getValue("password"); + } } else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) { if (message_name == "set_volume") { F32 volume = (F32)message_in.getValueReal("volume"); - setVolume(volume); + mCurVolume = volume; + setVolume(); } } else @@ -748,122 +882,70 @@ void MediaPluginCEF::receiveMessage(const char* message_string) } } -LLCEFLib::EKeyboardModifier MediaPluginCEF::decodeModifiers(std::string &modifiers) -{ - int result = 0; - - if (modifiers.find("shift") != std::string::npos) - result |= LLCEFLib::KM_MODIFIER_SHIFT; - - if (modifiers.find("alt") != std::string::npos) - result |= LLCEFLib::KM_MODIFIER_ALT; - - if (modifiers.find("control") != std::string::npos) - result |= LLCEFLib::KM_MODIFIER_CONTROL; - - if (modifiers.find("meta") != std::string::npos) - result |= LLCEFLib::KM_MODIFIER_META; - - return (LLCEFLib::EKeyboardModifier)result; -} - //////////////////////////////////////////////////////////////////////////////// // -void MediaPluginCEF::deserializeKeyboardData(LLSD native_key_data, uint32_t& native_scan_code, uint32_t& native_virtual_key, uint32_t& native_modifiers) +void MediaPluginCEF::keyEvent(dullahan::EKeyEvent key_event, LLSD native_key_data = LLSD::emptyMap()) { - native_scan_code = 0; - native_virtual_key = 0; - native_modifiers = 0; - - if (native_key_data.isMap()) - { #if LL_DARWIN - native_scan_code = (uint32_t)(native_key_data["char_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["key_code"].asInteger()); - native_modifiers = (uint32_t)(native_key_data["modifiers"].asInteger()); -#elif LL_WINDOWS - native_scan_code = (uint32_t)(native_key_data["scan_code"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); - // TODO: I don't think we need to do anything with native modifiers here -- please verify -#elif LL_LINUX - native_scan_code = (uint32_t)(native_key_data["sdl_sym"].asInteger()); - native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); - native_modifiers = (uint32_t)(native_key_data["cef_modifiers"].asInteger()); + U32 event_modifiers = native_key_data["event_modifiers"].asInteger(); + U32 event_keycode = native_key_data["event_keycode"].asInteger(); + U32 event_chars = native_key_data["event_chars"].asInteger(); + U32 event_umodchars = native_key_data["event_umodchars"].asInteger(); + bool event_isrepeat = native_key_data["event_isrepeat"].asBoolean(); - if( native_scan_code == '\n' ) - native_scan_code = '\r'; + // adding new code below in unicodeInput means we don't send ascii chars + // here too or we get double key presses on a mac. + bool esc_key = (event_umodchars == 27); + if (esc_key || ((unsigned char)event_chars < 0x10 || (unsigned char)event_chars >= 0x7f )) + { + mCEFLib->nativeKeyboardEventOSX(key_event, event_modifiers, + event_keycode, event_chars, + event_umodchars, event_isrepeat); + } +#elif LL_WINDOWS + U32 msg = ll_U32_from_sd(native_key_data["msg"]); + U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); + U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); + + mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam); +#elif LL_LINUX + uint32_t native_scan_code = (uint32_t)(native_key_data["sdl_sym"].asInteger()); + uint32_t native_virtual_key = (uint32_t)(native_key_data["virtual_key"].asInteger()); + uint32_t native_modifiers = (uint32_t)(native_key_data["cef_modifiers"].asInteger()); + if(native_scan_code == '\n') + native_scan_code = '\r'; + mCEFLib->nativeKeyboardEventLinux(key_event, native_scan_code, + native_virtual_key, native_modifiers); #endif - }; }; -//////////////////////////////////////////////////////////////////////////////// -// -void MediaPluginCEF::keyEvent(LLCEFLib::EKeyEvent key_event, int key, LLCEFLib::EKeyboardModifier modifiers_x, LLSD native_key_data = LLSD::emptyMap()) +void MediaPluginCEF::unicodeInput(std::string event, LLSD native_key_data = LLSD::emptyMap()) { #if LL_DARWIN + // i didn't think this code was needed for macOS but without it, the IME + // input in japanese (and likely others too) doesn't work correctly. + // see maint-7654 + U32 event_modifiers = native_key_data["event_modifiers"].asInteger(); + U32 event_keycode = native_key_data["event_keycode"].asInteger(); + U32 event_chars = native_key_data["event_chars"].asInteger(); + U32 event_umodchars = native_key_data["event_umodchars"].asInteger(); + bool event_isrepeat = native_key_data["event_isrepeat"].asBoolean(); - if (!native_key_data.has("event_type") || - !native_key_data.has("event_modifiers") || - !native_key_data.has("event_keycode") || - !native_key_data.has("event_isrepeat")) - return; - - uint32_t eventType = native_key_data["event_type"].asInteger(); - if (!eventType) - return; - uint32_t eventModifiers = native_key_data["event_modifiers"].asInteger(); - uint32_t eventKeycode = native_key_data["event_keycode"].asInteger(); - char eventChars = static_cast(native_key_data["event_chars"].isUndefined() ? 0 : native_key_data["event_chars"].asInteger()); - char eventUChars = static_cast(native_key_data["event_umodchars"].isUndefined() ? 0 : native_key_data["event_umodchars"].asInteger()); - bool eventIsRepeat = native_key_data["event_isrepeat"].asBoolean(); - - mLLCEFLib->keyboardEventOSX(eventType, eventModifiers, (eventChars) ? &eventChars : NULL, - (eventUChars) ? &eventUChars : NULL, eventIsRepeat, eventKeycode); + dullahan::EKeyEvent key_event = dullahan::KE_KEY_UP; + if (event == "down") + { + key_event = dullahan::KE_KEY_DOWN; + } + mCEFLib->nativeKeyboardEventOSX(key_event, event_modifiers, + event_keycode, event_chars, + event_umodchars, event_isrepeat); #elif LL_WINDOWS + event = ""; // not needed here but prevents unused var warning as error U32 msg = ll_U32_from_sd(native_key_data["msg"]); U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - - mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); -#elif LL_LINUX - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); - - mLLCEFLib->nativeKeyboardEvent(key_event, native_scan_code, native_virtual_key, native_modifiers); -#endif -} - -void MediaPluginCEF::unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboardModifier modifiers, LLSD native_key_data = LLSD::emptyMap()) -{ -#if LL_DARWIN - //mLLCEFLib->keyPress(utf8str[0], true); - //mLLCEFLib->keyboardEvent(LLCEFLib::KE_KEY_DOWN, (uint32_t)(utf8str[0]), 0, LLCEFLib::KM_MODIFIER_NONE, 0, 0, 0); - if (!native_key_data.has("event_chars") || !native_key_data.has("event_umodchars") || - !native_key_data.has("event_keycode") || !native_key_data.has("event_modifiers")) - return; - uint32_t unicodeChar = native_key_data["event_chars"].asInteger(); - uint32_t unmodifiedChar = native_key_data["event_umodchars"].asInteger(); - uint32_t keyCode = native_key_data["event_keycode"].asInteger(); - uint32_t rawmodifiers = native_key_data["event_modifiers"].asInteger(); - - mLLCEFLib->injectUnicodeText(unicodeChar, unmodifiedChar, keyCode, rawmodifiers); - -#elif LL_WINDOWS - U32 msg = ll_U32_from_sd(native_key_data["msg"]); - U32 wparam = ll_U32_from_sd(native_key_data["w_param"]); - U64 lparam = ll_U32_from_sd(native_key_data["l_param"]); - mLLCEFLib->nativeKeyboardEvent(msg, wparam, lparam); -#elif LL_LINUX - uint32_t native_scan_code = 0; - uint32_t native_virtual_key = 0; - uint32_t native_modifiers = 0; - deserializeKeyboardData(native_key_data, native_scan_code, native_virtual_key, native_modifiers); - - mLLCEFLib->nativeKeyboardEvent(LLCEFLib::KE_KEY_DOWN, native_scan_code, native_virtual_key, native_modifiers); - mLLCEFLib->nativeKeyboardEvent(LLCEFLib::KE_KEY_UP, native_scan_code, native_virtual_key, native_modifiers); + mCEFLib->nativeKeyboardEventWin(msg, wparam, lparam); #endif }; @@ -871,14 +953,31 @@ void MediaPluginCEF::unicodeInput(const std::string &utf8str, LLCEFLib::EKeyboar // void MediaPluginCEF::checkEditState() { - bool can_cut = mLLCEFLib->editCanCut(); - bool can_copy = mLLCEFLib->editCanCopy(); - bool can_paste = mLLCEFLib->editCanPaste(); + bool can_undo = mCEFLib->editCanUndo(); + bool can_redo = mCEFLib->editCanRedo(); + bool can_cut = mCEFLib->editCanCut(); + bool can_copy = mCEFLib->editCanCopy(); + bool can_paste = mCEFLib->editCanPaste(); + bool can_delete = mCEFLib->editCanDelete(); + bool can_select_all = mCEFLib->editCanSelectAll(); - if ((can_cut != mCanCut) || (can_copy != mCanCopy) || (can_paste != mCanPaste)) + if ((can_undo != mCanUndo) || (can_redo != mCanRedo) || (can_cut != mCanCut) || (can_copy != mCanCopy) + || (can_paste != mCanPaste) || (can_delete != mCanDelete) || (can_select_all != mCanSelectAll)) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_state"); + if (can_undo != mCanUndo) + { + mCanUndo = can_undo; + message.setValueBoolean("undo", can_undo); + } + + if (can_redo != mCanRedo) + { + mCanRedo = can_redo; + message.setValueBoolean("redo", can_redo); + } + if (can_cut != mCanCut) { mCanCut = can_cut; @@ -897,13 +996,25 @@ void MediaPluginCEF::checkEditState() message.setValueBoolean("paste", can_paste); } + if (can_delete != mCanDelete) + { + mCanDelete = can_delete; + message.setValueBoolean("delete", can_delete); + } + + if (can_select_all != mCanSelectAll) + { + mCanSelectAll = can_select_all; + message.setValueBoolean("select_all", can_select_all); + } + sendMessage(message); } } -void MediaPluginCEF::setVolume(F32 vol) +void MediaPluginCEF::setVolume() { - mVolumeCatcher.setVolume(vol); + mVolumeCatcher.setVolume(mCurVolume); } ////////////////////////////////////////////////////////////////////////////////