diff --git a/indra/llplugin/llpluginclassbasic.cpp b/indra/llplugin/llpluginclassbasic.cpp index 0567b157f..e3c587642 100644 --- a/indra/llplugin/llpluginclassbasic.cpp +++ b/indra/llplugin/llpluginclassbasic.cpp @@ -52,15 +52,16 @@ LLPluginClassBasic::~LLPluginClassBasic() delete mPlugin; } -bool LLPluginClassBasic::init(std::string const& launcher_filename, std::string const& plugin_filename, bool debug) +bool LLPluginClassBasic::init(std::string const& launcher_filename, std::string const& plugin_dir, std::string const& plugin_filename, bool debug) { LL_DEBUGS("Plugin") << "launcher: " << launcher_filename << LL_ENDL; + LL_DEBUGS("Plugin") << "dir: " << plugin_dir << LL_ENDL; LL_DEBUGS("Plugin") << "plugin: " << plugin_filename << LL_ENDL; mPlugin = new LLPluginProcessParent(this); mPlugin->setSleepTime(mSleepTime); - mPlugin->init(launcher_filename, plugin_filename, debug); + mPlugin->init(launcher_filename, plugin_dir, plugin_filename, debug); return init_impl(); } diff --git a/indra/llplugin/llpluginclassbasic.h b/indra/llplugin/llpluginclassbasic.h index 6c0602608..b7f9a3a86 100644 --- a/indra/llplugin/llpluginclassbasic.h +++ b/indra/llplugin/llpluginclassbasic.h @@ -53,7 +53,10 @@ public: virtual ~LLPluginClassBasic(); // Local initialization, called when creating a plugin process. Return true if successful. - bool init(std::string const& launcher_filename, std::string const& plugin_filename, bool debug); + bool init(std::string const& launcher_filename, + std::string const& plugin_dir, + std::string const& plugin_filename, + bool debug); // Undoes everything init did. Called when destroying a plugin process. void reset(void); diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index de208cb44..c71515496 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -484,6 +484,7 @@ void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity ) message.setValue( "maturity", maturity ); sendMessage( message ); } + void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers) { if(type == MOUSE_EVENT_MOVE) @@ -573,7 +574,15 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie } break; } - + +#if LL_DARWIN + if(modifiers & MASK_ALT) + { + // Option-key modified characters should be handled by the unicode input path instead of this one. + result = false; + } +#endif + if(result) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event"); @@ -731,6 +740,14 @@ void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) sendMessage(message); } + +void LLPluginClassMedia::enableMediaPluginDebugging( bool enable ) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "enable_media_plugin_debugging"); + message.setValueBoolean( "enable", enable ); + sendMessage( message ); +} + void LLPluginClassMedia::setTarget(const std::string &target) { mTarget = target; @@ -795,7 +812,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mDirtyRect.unionWith(newDirtyRect); } - LL_DEBUGS("PluginUpdated") << "adjusted incoming rect is: (" + LL_DEBUGS("PluginUpdated") << "adjusted incoming rect is: (" << newDirtyRect.mLeft << ", " << newDirtyRect.mTop << ", " << newDirtyRect.mRight << ", " @@ -958,6 +975,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mAuthURL = message.getValue("url"); mAuthRealm = message.getValue("realm"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST); + } + else if(message_name == "debug_message") + { + mDebugMessageText = message.getValue("message_text"); + mDebugMessageLevel = message.getValue("message_level"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_DEBUG_MESSAGE); } else { @@ -1103,6 +1126,14 @@ void LLPluginClassMedia::focus(bool focused) sendMessage(message); } +void LLPluginClassMedia::set_page_zoom_factor( double factor ) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_page_zoom_factor"); + + message.setValueReal("factor", factor); + sendMessage(message); +} + void LLPluginClassMedia::clear_cache() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "clear_cache"); @@ -1186,6 +1217,13 @@ void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent) sendMessage(message); } +void LLPluginClassMedia::showWebInspector( bool show ) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "show_web_inspector"); + message.setValueBoolean("show", true); // only open for now - closed manually by user + sendMessage(message); +} + void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 8136e9cb7..b58d0c95f 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -112,6 +112,9 @@ public: void scrollEvent(int x, int y, MASK modifiers); + // enable/disable media plugin debugging messages and info spam + void enableMediaPluginDebugging( bool enable ); + // Javascript <-> viewer events void jsEnableObject( bool enable ); void jsAgentLocationEvent( double x, double y, double z ); @@ -167,6 +170,7 @@ public: bool pluginSupportsMediaBrowser(void); void focus(bool focused); + void set_page_zoom_factor( double factor ); void clear_cache(); void clear_cookies(); void set_cookies(const std::string &cookies); @@ -178,6 +182,7 @@ public: 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); void proxyWindowClosed(const std::string &uuid); void ignore_ssl_cert_errors(bool ignore); @@ -213,6 +218,10 @@ public: // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE std::string getClickUUID() const { return mClickUUID; }; + // These are valid during MEDIA_EVENT_DEBUG_MESSAGE + std::string getDebugMessageText() const { return mDebugMessageText; }; + std::string getDebugMessageLevel() const { return mDebugMessageLevel; }; + // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE S32 getStatusCode() const { return mStatusCode; }; @@ -271,7 +280,7 @@ protected: protected: LLPluginClassMediaOwner *mOwner; - + bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true S32 mRequestedTextureDepth; LLGLenum mRequestedTextureInternalFormat; @@ -358,6 +367,8 @@ protected: std::string mClickNavType; std::string mClickTarget; std::string mClickUUID; + std::string mDebugMessageText; + std::string mDebugMessageLevel; S32 mGeometryX; S32 mGeometryY; S32 mGeometryWidth; diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index 0083e0c41..4a739cf86 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -71,6 +71,8 @@ public: MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog + 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; diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp index 793c8bb97..a53f67087 100644 --- a/indra/llplugin/llplugininstance.cpp +++ b/indra/llplugin/llplugininstance.cpp @@ -40,8 +40,13 @@ #include "linden_common.h" #include "llplugininstance.h" + #include "llaprpool.h" +#if LL_WINDOWS +#include "direct.h" // needed for _chdir() +#endif + /** Virtual destructor. */ LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener() { @@ -83,10 +88,24 @@ LLPluginInstance::~LLPluginInstance() * @param[in] plugin_file Name of plugin dll/dylib/so. TODO:DOC is this correct? see .h * @return 0 if successful, APR error code or error code from the plugin's init function on failure. */ -int LLPluginInstance::load(std::string &plugin_file) +int LLPluginInstance::load(const std::string& plugin_dir, std::string &plugin_file) { pluginInitFunction init_function = NULL; + if ( plugin_dir.length() ) + { +#if LL_WINDOWS + // VWR-21275: + // *SOME* Windows systems fail to load the Qt plugins if the current working + // directory is not the same as the directory with the Qt DLLs in. + // This should not cause any run time issues since we are changing the cwd for the + // plugin shell process and not the viewer. + // Changing back to the previous directory is not necessary since the plugin shell + // quits once the plugin exits. + _chdir( plugin_dir.c_str() ); +#endif + }; + #if LL_LINUX && defined(LL_STANDALONE) void *dso_handle = dlopen(plugin_file.c_str(), RTLD_NOW | RTLD_GLOBAL); int result = (!dso_handle)?APR_EDSOOPEN:apr_os_dso_handle_put(&mDSOHandle, diff --git a/indra/llplugin/llplugininstance.h b/indra/llplugin/llplugininstance.h index b2b107bab..c77da97ba 100644 --- a/indra/llplugin/llplugininstance.h +++ b/indra/llplugin/llplugininstance.h @@ -64,7 +64,7 @@ public: // Load a plugin dll/dylib/so // Returns 0 if successful, APR error code or error code returned from the plugin's init function on failure. - int load(std::string &plugin_file); + int load(const std::string& plugin_dir, std::string &plugin_file); // Sends a message to the plugin. void sendMessage(const std::string &message); diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index d014cf9bb..a85a0343d 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -146,7 +146,7 @@ void LLPluginProcessChild::idle(void) if(!mPluginFile.empty()) { mInstance = new LLPluginInstance(this); - if(mInstance->load(mPluginFile) == 0) + if(mInstance->load(mPluginDir, mPluginFile) == 0) { mHeartbeat.start(); mHeartbeat.setTimerExpirySec(HEARTBEAT_SECONDS); @@ -372,6 +372,7 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) if(message_name == "load_plugin") { mPluginFile = parsed.getValue("file"); + mPluginDir = parsed.getValue("dir"); } else if(message_name == "shm_add") { diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h index 66082db7c..53dcccb81 100644 --- a/indra/llplugin/llpluginprocesschild.h +++ b/indra/llplugin/llpluginprocesschild.h @@ -101,6 +101,7 @@ private: LLSocket::ptr_t mSocket; std::string mPluginFile; + std::string mPluginDir; LLPluginInstance *mInstance; diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 685485fc1..cdb8ec88a 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -114,7 +114,6 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner) // Don't start the timer here -- start it when we actually launch the plugin process. mHeartbeat.stop(); - // Don't add to the global list until fully constructed. { @@ -173,10 +172,12 @@ void LLPluginProcessParent::errorState(void) setState(STATE_ERROR); } -void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_filename, bool debug) +void LLPluginProcessParent::init(const std::string &launcher_filename, const std::string &plugin_dir, const std::string &plugin_filename, bool debug) { mProcess.setExecutable(launcher_filename); + mProcess.setWorkingDirectory(plugin_dir); mPluginFile = plugin_filename; + mPluginDir = plugin_dir; mCPUUsage = 0.0f; mDebug = debug; setState(STATE_INITIALIZED); @@ -483,6 +484,7 @@ void LLPluginProcessParent::idle(void) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin"); message.setValue("file", mPluginFile); + message.setValue("dir", mPluginDir); sendMessage(message); } diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index 28e8edd19..d5a08c435 100644 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -67,6 +67,7 @@ public: ~LLPluginProcessParent(); void init(const std::string &launcher_filename, + const std::string &plugin_dir, const std::string &plugin_filename, bool debug); @@ -166,12 +167,13 @@ private: LLProcessLauncher mProcess; std::string mPluginFile; + std::string mPluginDir; LLPluginProcessParentOwner *mOwner; - + typedef std::map sharedMemoryRegionsType; sharedMemoryRegionsType mSharedMemoryRegions; - + LLSD mMessageClassVersions; std::string mPluginVersionString; @@ -194,7 +196,7 @@ private: apr_pollfd_t mPollFD; LLAPRPool mPollFDPool; static apr_pollset_t *sPollSet; - static LLAPRPool sPollSetPool; + static LLAPRPool sPollSetPool; static bool sPollsetNeedsRebuild; static LLMutex *sInstancesMutex; static std::list sInstances; diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f4885b9ac..2eca82c95 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -2189,38 +2189,16 @@ Value http://www.singularityviewer.org - BrowserCookiesEnabled + BrowserIgnoreSSLCertErrors Comment - Enable Cookes in WebKit + FOR TESTING ONLY: Tell the built-in web browser to ignore SSL cert errors. Persist 1 Type Boolean Value - 1 - - BrowserPluginsEnabled - - Comment - Enable Mozilla Plug-Ins in WebKit - Persist - 1 - Type - Boolean - Value - 1 - - BrowserJavascriptEnabled - - Comment - Enable JavaScript execution in WebKit - Persist - 1 - Type - Boolean - Value - 1 + 0 PluginAttachDebuggerToPlugins @@ -3927,6 +3905,28 @@ Value 1 + BrowserJavascriptEnabled + + Comment + Enable Javascript in the built-in Web browser? + Persist + 1 + Type + Boolean + Value + 1 + + BrowserPluginsEnabled + + Comment + Enable Web plugins in the built-in Web browser? + Persist + 1 + Type + Boolean + Value + 1 + CreateToolCopyCenters Comment @@ -8196,6 +8196,17 @@ Value 0 + MediaPluginDebugging + + Comment + Turn on debugging messages that may help diagnosing media issues (WARNING: May reduce performance). + Persist + 1 + Type + Boolean + Value + 0 + MediaControlFadeTime Comment @@ -8260,7 +8271,7 @@ Type Boolean Value - 0 + 0 MemoryPrivatePoolSize diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 1adccc92b..315afe84a 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -345,6 +345,10 @@ BOOL LLMediaCtrl::postBuild () return true; } +void LLMediaCtrl::onOpenWebInspector() + if (mMediaSource && mMediaSource->hasMedia()) + mMediaSource->getMediaPlugin()->showWebInspector( true ); +} //////////////////////////////////////////////////////////////////////////////// // BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) @@ -947,6 +951,12 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) }; break; + case MEDIA_EVENT_NAVIGATE_ERROR_PAGE: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL; + }; + break; + case MEDIA_EVENT_CLICK_LINK_HREF: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL; @@ -978,31 +988,25 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL; }; break; - - case MEDIA_EVENT_NAVIGATE_ERROR_PAGE: - { - LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL; - }; - break; - + case MEDIA_EVENT_CLOSE_REQUEST: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLOSE_REQUEST" << LL_ENDL; }; break; - + case MEDIA_EVENT_PICK_FILE_REQUEST: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL; }; break; - + case MEDIA_EVENT_GEOMETRY_CHANGE: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE" << LL_ENDL; }; break; - + case MEDIA_EVENT_AUTH_REQUEST: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_AUTH_REQUEST" << LL_ENDL; @@ -1014,6 +1018,12 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED" << LL_ENDL; }; break; + + case MEDIA_EVENT_DEBUG_MESSAGE: + { + LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL; + }; + break; default: { diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 341ea1407..602a1f153 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -144,8 +144,12 @@ class LLMediaCtrl : // handlers for individual events (could be done inside the switch in handleMediaEvent, they're just individual functions for clarity) void onClickLinkHref( LLPluginClassMedia* self ); + void onClickLinkNoFollow( LLPluginClassMedia* self ); - + + // right click debugging item + void onOpenWebInspector(); + protected: void convertInputCoords(S32& x, S32& y); diff --git a/indra/newview/llmimetypes.cpp b/indra/newview/llmimetypes.cpp index c45e0abf5..3825c2bcb 100644 --- a/indra/newview/llmimetypes.cpp +++ b/indra/newview/llmimetypes.cpp @@ -34,6 +34,7 @@ #include "llviewerprecompiledheaders.h" #include "llmimetypes.h" +#include "lltrans.h" #include "lluictrlfactory.h" @@ -48,6 +49,7 @@ std::string sDefaultImpl; // Returned when we don't know what impl to use std::string sXMLFilename; // Squirrel away XML filename so we know how to reset +std::string DEFAULT_MIME_TYPE = "none/none"; ///////////////////////////////////////////////////////////////////////////// @@ -229,7 +231,7 @@ std::string LLMIMETypes::findIcon(const std::string& mime_type) // static std::string LLMIMETypes::findDefaultMimeType(const std::string& widget_type) { - std::string mime_type = "none/none"; + std::string mime_type = getDefaultMimeType(); mime_widget_set_map_t::iterator it = sWidgetMap.find(widget_type); if(it != sWidgetMap.end()) { @@ -238,6 +240,18 @@ std::string LLMIMETypes::findDefaultMimeType(const std::string& widget_type) return mime_type; } +// static +const std::string& LLMIMETypes::getDefaultMimeType() +{ + return DEFAULT_MIME_TYPE; +} + +const std::string& LLMIMETypes::getDefaultMimeTypeTranslation() +{ + static std::string mime_type = LLTrans::getString("DefaultMimeType"); + return mime_type; +} + // static std::string LLMIMETypes::findToolTip(const std::string& mime_type) { diff --git a/indra/newview/llmimetypes.h b/indra/newview/llmimetypes.h index b217ce7a8..3461769ff 100644 --- a/indra/newview/llmimetypes.h +++ b/indra/newview/llmimetypes.h @@ -66,6 +66,10 @@ public: static std::string findDefaultMimeType(const std::string& widget_type); // Canonical mime type associated with this widget set + static const std::string& getDefaultMimeType(); + + static const std::string& getDefaultMimeTypeTranslation(); + static bool findAllowResize(const std::string& mime_type); // accessor for flag to enable/disable media size edit fields diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 727e19578..7bd2ff41e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -411,7 +411,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ media_source->setLanguageCode(LLUI::getLanguage()); // collect 'cookies enabled' setting from prefs and send to embedded browser - bool cookies_enabled = gSavedSettings.getBOOL( "BrowserCookiesEnabled" ); + bool cookies_enabled = gSavedSettings.getBOOL( "CookiesEnabled" ); media_source->enable_cookies( cookies_enabled ); // collect 'plugins enabled' setting from prefs and send to embedded browser @@ -421,8 +421,12 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ // collect 'javascript enabled' setting from prefs and send to embedded browser bool javascript_enabled = gSavedSettings.getBOOL( "BrowserJavascriptEnabled" ); media_source->setJavascriptEnabled( javascript_enabled ); + + bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); + media_source->enableMediaPluginDebugging( media_plugin_debugging_enabled ); - if (media_source->init(launcher_name, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) + const std::string plugin_dir = gDirUtilp->getLLPluginDir(); + if (media_source->init(launcher_name, plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) { return media_source; } @@ -433,8 +437,8 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } } } - - LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL; + + LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL; LLSD args; args["MIME_TYPE"] = media_type; LLNotificationsUtil::add("NoPlugin", args); @@ -467,8 +471,36 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) media_source->setLoop(mMediaLoop); media_source->setAutoScale(mMediaAutoScale); media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent()); - + + if(gSavedSettings.getBOOL("BrowserIgnoreSSLCertErrors")) + { + media_source->ignore_ssl_cert_errors(true); + } + + // start by assuming the default CA file will be used + std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "CA.pem" ); + + // default turned off so pick up the user specified path + if( ! gSavedSettings.getBOOL("BrowserUseDefaultCAFile")) + { + ca_path = gSavedSettings.getString("BrowserCAFilePath"); + } + // set the path to the CA.pem file + media_source->addCertificateFilePath( ca_path ); + + // TODO: Only send cookies to plugins that need them + // Ideally, the plugin should tell us whether it handles cookies or not -- either via the init response or through a separate message. + // Due to the ordering of messages, it's possible we wouldn't get that information back in time to send cookies before sending a navigate message, + // which could cause odd race conditions. + std::string all_cookies = LLViewerMedia::getCookieStore()->getAllCookies(); + lldebugs << "setting cookies: " << all_cookies << llendl; + if(!all_cookies.empty()) + { + media_source->set_cookies(all_cookies); + } + mPluginBase = media_source; + return true; } diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 149549c0f..9e7df265e 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -34,6 +34,8 @@ #include "llviewerparcelmedia.h" #include "llagent.h" +#include "llaudioengine.h" +#include "llmimetypes.h" #include "llviewercontrol.h" #include "llviewermedia.h" #include "llviewerregion.h" @@ -323,12 +325,14 @@ LLViewerMediaImpl::EMediaStatus LLViewerParcelMedia::getStatus() // static std::string LLViewerParcelMedia::getMimeType() { - return sMediaImpl.notNull() ? sMediaImpl->getMimeType() : "none/none"; + return sMediaImpl.notNull() ? sMediaImpl->getMimeType() : LLMIMETypes::getDefaultMimeType(); } + viewer_media_t LLViewerParcelMedia::getParcelMedia() { return sMediaImpl; } + ////////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerParcelMedia::processParcelMediaCommandMessage( LLMessageSystem *msg, void ** ) @@ -478,6 +482,12 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent { switch(event) { + case MEDIA_EVENT_DEBUG_MESSAGE: + { + // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_DEBUG_MESSAGE " << LL_ENDL; + }; + break; + case MEDIA_EVENT_CONTENT_UPDATED: { // LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL; @@ -532,6 +542,12 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent }; break; + case MEDIA_EVENT_NAVIGATE_ERROR_PAGE: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL; + }; + break; + case MEDIA_EVENT_CLICK_LINK_HREF: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL; @@ -562,18 +578,12 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent }; break; - case MEDIA_EVENT_NAVIGATE_ERROR_PAGE: - { - LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL; - }; - break; - case MEDIA_EVENT_CLOSE_REQUEST: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLOSE_REQUEST" << LL_ENDL; }; break; - + case MEDIA_EVENT_PICK_FILE_REQUEST: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL; @@ -582,10 +592,10 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent case MEDIA_EVENT_GEOMETRY_CHANGE: { - LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE" << LL_ENDL; + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE" << LL_ENDL; }; break; - + case MEDIA_EVENT_AUTH_REQUEST: { LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_AUTH_REQUEST" << LL_ENDL; @@ -597,7 +607,7 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED" << LL_ENDL; }; break; - + default: { LL_WARNS("Media") << "Media event: unknown event type" << LL_ENDL; diff --git a/indra/newview/llviewerpluginmanager.h b/indra/newview/llviewerpluginmanager.h index 6525a5403..e10a56728 100644 --- a/indra/newview/llviewerpluginmanager.h +++ b/indra/newview/llviewerpluginmanager.h @@ -77,7 +77,8 @@ LLPluginClassBasic* LLViewerPluginManager::createPlugin(T* user_data) { // Always delete the old plugin first. destroyPlugin(); - + + std::string plugin_dir = gDirUtilp->getLLPluginDir(); std::string plugin_name = gDirUtilp->getLLPluginFilename(PLUGIN_TYPE::plugin_basename()); // See if the plugin executable exists. @@ -93,7 +94,7 @@ LLPluginClassBasic* LLViewerPluginManager::createPlugin(T* user_data) else { LLPluginClassBasic* plugin = new PLUGIN_TYPE(user_data); - if (plugin->init(PLUGIN_TYPE::launcher_name(), plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) + if (plugin->init(PLUGIN_TYPE::launcher_name(), plugin_dir, plugin_name, gSavedSettings.getBOOL("PluginAttachDebuggerToPlugins"))) { mPluginBase = plugin; } diff --git a/indra/newview/skins/default/xui/en-us/strings.xml b/indra/newview/skins/default/xui/en-us/strings.xml index abbc43de0..863827baa 100644 --- a/indra/newview/skins/default/xui/en-us/strings.xml +++ b/indra/newview/skins/default/xui/en-us/strings.xml @@ -1956,6 +1956,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Chat + none/none + Select an editor using the ExternalEditor setting. Cannot find the external editor you specified. diff --git a/indra/plugins/webkit/media_plugin_webkit.cpp b/indra/plugins/webkit/media_plugin_webkit.cpp old mode 100755 new mode 100644 index 95b0dae74..64a81c267 --- a/indra/plugins/webkit/media_plugin_webkit.cpp +++ b/indra/plugins/webkit/media_plugin_webkit.cpp @@ -90,6 +90,7 @@ private: bool mCookiesEnabled; bool mJavascriptEnabled; bool mPluginsEnabled; + bool mEnableMediaPluginDebugging; enum { @@ -116,9 +117,24 @@ private: F32 mBackgroundG; F32 mBackgroundB; std::string mTarget; - + LLTimer mElapsedTime; + VolumeCatcher mVolumeCatcher; + void postDebugMessage( const std::string& msg ) + { + if ( mEnableMediaPluginDebugging ) + { + std::stringstream str; + str << "@Media Msg> " << "[" << (double)mElapsedTime.getElapsedTimeF32() << "] -- " << msg; + + LLPluginMessage debug_message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "debug_message"); + debug_message.setValue("message_text", str.str()); + debug_message.setValue("message_level", "info"); + sendMessage(debug_message); + } + } + void setInitState(int state) { // std::cerr << "changing init state to " << state << std::endl; @@ -144,7 +160,7 @@ private: mVolumeCatcher.pump(); checkEditState(); - + if(mInitState == INIT_STATE_NAVIGATE_COMPLETE) { if(!mInitialNavigateURL.empty()) @@ -228,7 +244,7 @@ private: #endif #if LL_WINDOWS - // *NOTE:Mani - On windows, at least, the component path is the + //*NOTE:Mani - On windows, at least, the component path is the // location of this dll's image file. std::string component_dir; char dll_path[_MAX_PATH]; @@ -252,6 +268,9 @@ private: std::string component_dir = application_dir; #endif + // debug spam sent to viewer and displayed in the log as usual + postDebugMessage( "Component dir set to: " + component_dir ); + // window handle - needed on Windows and must be app window. #if LL_WINDOWS char window_title[ MAX_PATH ]; @@ -266,10 +285,16 @@ private: if ( result ) { mInitState = INIT_STATE_INITIALIZED; - + + // debug spam sent to viewer and displayed in the log as usual + postDebugMessage( "browser initialized okay" ); + return true; }; + // debug spam sent to viewer and displayed in the log as usual + postDebugMessage( "browser nOT initialized." ); + return false; }; @@ -292,6 +317,7 @@ private: if(!mHostLanguage.empty()) { LLQtWebKit::getInstance()->setHostLanguage(mHostLanguage); + postDebugMessage( "Setting language to " + mHostLanguage ); } // turn on/off cookies based on what host app tells us @@ -307,8 +333,17 @@ private: LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled ); #endif + std::stringstream str; + str << "Cookies enabled = " << mCookiesEnabled << ", plugins enabled = " << mPluginsEnabled << ", Javascript enabled = " << mJavascriptEnabled; + postDebugMessage( str.str() ); + // create single browser window - mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow(mWidth, mHeight, mTarget); + mBrowserWindowId = LLQtWebKit::getInstance()->createBrowserWindow( mWidth, mHeight, mTarget); + + str.str(""); + str.clear(); + str << "Setting browser window size to " << mWidth << " x " << mHeight; + postDebugMessage( str.str() ); // tell LLQtWebKit about the size of the browser window LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight ); @@ -318,6 +353,7 @@ private: // append details to agent string LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); + postDebugMessage( "Updating user agent with " + mUserAgent ); #if !LL_QTWEBKIT_USES_PIXMAPS // don't flip bitmap @@ -345,8 +381,18 @@ private: url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f); url << "%22%3E%3C/body%3E%3C/html%3E"; - lldebugs << "data url is: " << url.str() << llendl; - + //lldebugs << "data url is: " << url.str() << llendl; + + // always display loading overlay now +#if LLQTWEBKIT_API_VERSION >= 16 + LLQtWebKit::getInstance()->enableLoadingOverlay(mBrowserWindowId, true); +#else + llwarns << "Ignoring enableLoadingOverlay() call (llqtwebkit version is too old)." << llendl; +#endif + str.clear(); + str << "Loading overlay enabled = " << mEnableMediaPluginDebugging << " for mBrowserWindowId = " << mBrowserWindowId; + postDebugMessage( str.str() ); + LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() ); // LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); @@ -413,9 +459,11 @@ private: message.setValue("uri", event.getEventUri()); message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK)); message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD)); - sendMessage(message); - + + // debug spam sent to viewer and displayed in the log as usual + postDebugMessage( "Navigate begin event at: " + event.getEventUri() ); + setStatus(STATUS_LOADING); } @@ -457,6 +505,8 @@ private: setInitState(INIT_STATE_NAVIGATE_COMPLETE); } + // debug spam sent to viewer and displayed in the log as usual + postDebugMessage( "Navigate complete event at: " + event.getEventUri() ); } //////////////////////////////////////////////////////////////////////////////// @@ -494,7 +544,7 @@ private: sendMessage(message); } } - + //////////////////////////////////////////////////////////////////////////////// // virtual void onNavigateErrorPage(const EventType& event) @@ -503,7 +553,7 @@ private: message.setValueS32("status_code", event.getIntValue()); sendMessage(message); } - + //////////////////////////////////////////////////////////////////////////////// // virtual void onLocationChange(const EventType& event) @@ -540,6 +590,7 @@ private: #endif sendMessage(message); } + //////////////////////////////////////////////////////////////////////////////// // virtual @@ -550,10 +601,14 @@ private: // These could be passed through as well, but aren't really needed. // message.setValue("uri", event.getEventUri()); // message.setValueBoolean("dead", (event.getIntValue() != 0)) + + // debug spam + postDebugMessage( "Sending cookie_set message from plugin: " + event.getStringValue() ); + sendMessage(message); } - - //////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////// // virtual void onWindowCloseRequested(const EventType& event) { @@ -581,7 +636,7 @@ private: sendMessage(message); } } - + std::string mAuthUsername; std::string mAuthPassword; bool mAuthOK; @@ -632,7 +687,7 @@ private: sendMessage(message); } } - + LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers) { int result = 0; @@ -801,7 +856,10 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction send_ mHostLanguage = "en"; // default to english mJavascriptEnabled = true; // default to on mPluginsEnabled = true; // default to on + mEnableMediaPluginDebugging = false; mUserAgent = "LLPluginMedia Web Browser"; + + mElapsedTime.reset(); } MediaPluginWebKit::~MediaPluginWebKit() @@ -828,8 +886,6 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) { if(message_name == "init") { - mTarget = message_in.getValue("target"); - LLPluginMessage message("base", "init_response"); LLSD versions = LLSD::emptyMap(); versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; @@ -909,7 +965,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) { if(message_name == "set_volume") { - F32 volume = message_in.getValueReal("volume"); + F32 volume = (F32)message_in.getValueReal("volume"); setVolume(volume); } } @@ -917,6 +973,8 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) { if(message_name == "init") { + mTarget = message_in.getValue("target"); + // This is the media init message -- all necessary data for initialization should have been received. if(initBrowser()) { @@ -1139,7 +1197,78 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) if(message_name == "auth_response") { authResponse(message_in); - } + } + else + if(message_name == "enable_media_plugin_debugging") + { + mEnableMediaPluginDebugging = message_in.getValueBoolean( "enable" ); + } + else + if(message_name == "js_enable_object") + { +#if LLQTWEBKIT_API_VERSION >= 9 + bool enable = message_in.getValueBoolean( "enable" ); + LLQtWebKit::getInstance()->setSLObjectEnabled( enable ); +#endif + } + else + if(message_name == "js_agent_location") + { +#if LLQTWEBKIT_API_VERSION >= 9 + F32 x = (F32)message_in.getValueReal("x"); + F32 y = (F32)message_in.getValueReal("y"); + F32 z = (F32)message_in.getValueReal("z"); + LLQtWebKit::getInstance()->setAgentLocation( x, y, z ); + LLQtWebKit::getInstance()->emitLocation(); +#endif + } + else + if(message_name == "js_agent_global_location") + { +#if LLQTWEBKIT_API_VERSION >= 9 + F32 x = (F32)message_in.getValueReal("x"); + F32 y = (F32)message_in.getValueReal("y"); + F32 z = (F32)message_in.getValueReal("z"); + LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z ); + LLQtWebKit::getInstance()->emitLocation(); +#endif + } + else + if(message_name == "js_agent_orientation") + { +#if LLQTWEBKIT_API_VERSION >= 9 + F32 angle = (F32)message_in.getValueReal("angle"); + LLQtWebKit::getInstance()->setAgentOrientation( angle ); + LLQtWebKit::getInstance()->emitLocation(); +#endif + } + else + if(message_name == "js_agent_region") + { +#if LLQTWEBKIT_API_VERSION >= 9 + const std::string& region = message_in.getValue("region"); + LLQtWebKit::getInstance()->setAgentRegion( region ); + LLQtWebKit::getInstance()->emitLocation(); +#endif + } + else + if(message_name == "js_agent_maturity") + { +#if LLQTWEBKIT_API_VERSION >= 9 + const std::string& maturity = message_in.getValue("maturity"); + LLQtWebKit::getInstance()->setAgentMaturity( maturity ); + LLQtWebKit::getInstance()->emitMaturity(); +#endif + } + else + if(message_name == "js_agent_language") + { +#if LLQTWEBKIT_API_VERSION >= 9 + const std::string& language = message_in.getValue("language"); + LLQtWebKit::getInstance()->setAgentLanguage( language ); + LLQtWebKit::getInstance()->emitLanguage(); +#endif + } else { // std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl; @@ -1161,6 +1290,15 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) mFirstFocus = false; } } + else if(message_name == "set_page_zoom_factor") + { +#if LLQTWEBKIT_API_VERSION >= 15 + F32 factor = (F32)message_in.getValueReal("factor"); + LLQtWebKit::getInstance()->setPageZoomFactor(factor); +#else + llwarns << "Ignoring setPageZoomFactor message (llqtwebkit version is too old)." << llendl; +#endif + } else if(message_name == "clear_cache") { LLQtWebKit::getInstance()->clearCache(); @@ -1187,6 +1325,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) else if(message_name == "set_cookies") { LLQtWebKit::getInstance()->setCookies(message_in.getValue("cookies")); + + // debug spam + postDebugMessage( "Plugin setting cookie: " + message_in.getValue("cookies") ); } else if(message_name == "proxy_setup") { @@ -1248,7 +1389,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) else if(message_name == "add_certificate_file_path") { #if LLQTWEBKIT_API_VERSION >= 6 - LLQtWebKit::getInstance()->addCAFile( message_in.getValue("path") ); + LLQtWebKit::getInstance()->setCAFile( message_in.getValue("path") ); #else llwarns << "Ignoring add_certificate_file_path message (llqtwebkit version is too old)." << llendl; #endif