void MediaPluginCEF::receiveMessage(const char* message_string)
{
	//  std::cerr << "MediaPluginCEF::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
	LLPluginMessage message_in;

	if (message_in.parse(message_string) >= 0)
	{
		std::string message_class = message_in.getClass();
		std::string message_name = message_in.getName();
		if (message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
		{
			if (message_name == "init")
			{
				LLPluginMessage message("base", "init_response");
				LLSD versions = LLSD::emptyMap();
				versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
				versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
				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";
				message.setValue("plugin_version", plugin_version);
				sendMessage(message);
			}
			else if (message_name == "idle")
			{
				mLLCEFLib->update();

                mVolumeCatcher.pump();
				// this seems bad but unless the state changes (it won't until we figure out
				// how to get CEF to tell us if copy/cut/paste is available) then this function
				// will return immediately
				checkEditState();
			}
			else if (message_name == "cleanup")
			{
				mLLCEFLib->requestExit();
			}
			else if (message_name == "shm_added")
			{
				SharedSegmentInfo info;
				info.mAddress = message_in.getValuePointer("address");
				info.mSize = (size_t)message_in.getValueS32("size");
				std::string name = message_in.getValue("name");

				mSharedSegments.insert(SharedSegmentMap::value_type(name, info));

			}
			else if (message_name == "shm_remove")
			{
				std::string name = message_in.getValue("name");

				SharedSegmentMap::iterator iter = mSharedSegments.find(name);
				if (iter != mSharedSegments.end())
				{
					if (mPixels == iter->second.mAddress)
					{
						mPixels = NULL;
						mTextureSegmentName.clear();
					}
					mSharedSegments.erase(iter);
				}
				else
				{
				}

				LLPluginMessage message("base", "shm_remove_response");
				message.setValue("name", name);
				sendMessage(message);
			}
			else
			{
			}
		}
		else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
		{
			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));

				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;
				settings.cache_enabled = true;
				settings.cache_path = mCachePath;
				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;

				bool result = mLLCEFLib->init(settings);
				if (!result)
				{
					// if this fails, the media system in viewer will put up a message
				}

				// Plugin gets to decide the texture parameters to use.
				mDepth = 4;
				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
				message.setValueS32("default_width", 1024);
				message.setValueS32("default_height", 1024);
				message.setValueS32("depth", mDepth);
				message.setValueU32("internalformat", GL_RGB);
				message.setValueU32("format", GL_BGRA);
				message.setValueU32("type", GL_UNSIGNED_BYTE);
				message.setValueBoolean("coords_opengl", true);
				sendMessage(message);
			}
			else if (message_name == "set_user_data_path")
			{
				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");
				mCachePath = user_data_path_cache + "cef_cache";
				mCookiePath = user_data_path_cookies + "cef_cookies";
				mLogFile = user_data_path_logs + "cef.log";
			}
			else if (message_name == "size_change")
			{
				std::string name = message_in.getValue("name");
				S32 width = message_in.getValueS32("width");
				S32 height = message_in.getValueS32("height");
				S32 texture_width = message_in.getValueS32("texture_width");
				S32 texture_height = message_in.getValueS32("texture_height");

				if (!name.empty())
				{
					// Find the shared memory region with this name
					SharedSegmentMap::iterator iter = mSharedSegments.find(name);
					if (iter != mSharedSegments.end())
					{
						mPixels = (unsigned char*)iter->second.mAddress;
						mWidth = width;
						mHeight = height;

						mTextureWidth = texture_width;
						mTextureHeight = texture_height;
					};
				};

				mLLCEFLib->setSize(mWidth, mHeight);

				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
				message.setValue("name", name);
				message.setValueS32("width", width);
				message.setValueS32("height", height);
				message.setValueS32("texture_width", texture_width);
				message.setValueS32("texture_height", texture_height);
				sendMessage(message);

			}
			else if (message_name == "set_language_code")
			{
				mHostLanguage = message_in.getValue("language");
			}
			else if (message_name == "load_uri")
			{
				std::string uri = message_in.getValue("uri");
				mLLCEFLib->navigate(uri);
			}
			else if (message_name == "set_cookie")
			{
				std::string uri = message_in.getValue("uri");
				std::string name = message_in.getValue("name");
				std::string value = message_in.getValue("value");
				std::string domain = message_in.getValue("domain");
				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);
			}
			else if (message_name == "mouse_event")
			{
				std::string event = message_in.getValue("event");

				S32 x = message_in.getValueS32("x");
				S32 y = message_in.getValueS32("y");

				// only even send left mouse button events to LLCEFLib
				// (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;

				if (event == "down" && button == 0)
				{
					mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOWN, x, y);
					mLLCEFLib->setFocus(true);

					std::stringstream str;
					str << "Mouse down at = " << x << ", " << y;
					postDebugMessage(str.str());
				}
				else if (event == "up" && button == 0)
				{
					mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_UP, x, y);

					std::stringstream str;
					str << "Mouse up at = " << x << ", " << y;
					postDebugMessage(str.str());
				}
				else if (event == "double_click")
				{
					mLLCEFLib->mouseButton(btn, LLCEFLib::ME_MOUSE_DOUBLE_CLICK, x, y);
				}
				else
				{
					mLLCEFLib->mouseMove(x, y);
				}
			}
			else if (message_name == "scroll_event")
			{
				S32 x = message_in.getValueS32("x");
				S32 y = message_in.getValueS32("y");
				const int scaling_factor = 40;
				y *= -scaling_factor;

				mLLCEFLib->mouseWheel(x, y);
			}
			else if (message_name == "text_event")
			{
				std::string text = message_in.getValue("text");
				std::string modifiers = message_in.getValue("modifiers");
				LLSD native_key_data = message_in.getValueLLSD("native_key_data");

				unicodeInput(text, decodeModifiers(modifiers), 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;
                if (event == "down")
                {
                    key_event = LLCEFLib::KE_KEY_DOWN;
                }
                else if (event == "repeat")
                {
                    key_event = LLCEFLib::KE_KEY_REPEAT;
                }

                keyEvent(key_event, key, LLCEFLib::KM_MODIFIER_NONE, 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;
				if (event == "down")
				{
					key_event = LLCEFLib::KE_KEY_DOWN;
				}
				else if (event == "repeat")
				{
					key_event = LLCEFLib::KE_KEY_REPEAT;
				}

				keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data);
#endif
			}
			else if (message_name == "enable_media_plugin_debugging")
			{
				mEnableMediaPluginDebugging = message_in.getValueBoolean("enable");
			}
			if (message_name == "auth_response")
			{
				authResponse(message_in);
			}
			if (message_name == "edit_cut")
			{
				mLLCEFLib->editCut();
			}
			if (message_name == "edit_copy")
			{
				mLLCEFLib->editCopy();
			}
			if (message_name == "edit_paste")
			{
				mLLCEFLib->editPaste();
			}
		}
		else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
		{
			if (message_name == "set_page_zoom_factor")
			{
				F32 factor = (F32)message_in.getValueReal("factor");
				mLLCEFLib->setPageZoom(factor);
			}
			if (message_name == "browse_stop")
			{
				mLLCEFLib->stop();
			}
			else if (message_name == "browse_reload")
			{
				bool ignore_cache = true;
				mLLCEFLib->reload(ignore_cache);
			}
			else if (message_name == "browse_forward")
			{
				mLLCEFLib->goForward();
			}
			else if (message_name == "browse_back")
			{
				mLLCEFLib->goBack();
			}
			else if (message_name == "cookies_enabled")
			{
				mCookiesEnabled = message_in.getValueBoolean("enable");
			}
			else if (message_name == "set_user_agent")
			{
				mUserAgentSubtring = message_in.getValue("user_agent");
			}
			else if (message_name == "show_web_inspector")
			{
				mLLCEFLib->showDevTools(true);
			}
			else if (message_name == "plugins_enabled")
			{
				mPluginsEnabled = message_in.getValueBoolean("enable");
			}
			else if (message_name == "javascript_enabled")
			{
				mJavascriptEnabled = message_in.getValueBoolean("enable");
			}
		}
        else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
        {
            if (message_name == "set_volume")
            {
                F32 volume = (F32)message_in.getValueReal("volume");
                setVolume(volume);
            }
        }
        else
		{
		};
	}
}
void MediaPluginWebKit::receiveMessage(const char *message_string)
{
//	std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl;
    LLPluginMessage message_in;

    if(message_in.parse(message_string) >= 0)
    {
        std::string message_class = message_in.getClass();
        std::string message_name = message_in.getName();
        if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE)
        {
            if(message_name == "init")
            {
                LLPluginMessage message("base", "init_response");
                LLSD versions = LLSD::emptyMap();
                versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION;
                versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION;
                versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
                message.setValueLLSD("versions", versions);

                std::string plugin_version = "Webkit media plugin, Webkit version ";
                plugin_version += LLQtWebKit::getInstance()->getVersion();
                message.setValue("plugin_version", plugin_version);
                sendMessage(message);
            }
            else if(message_name == "idle")
            {
                // no response is necessary here.
                F64 time = message_in.getValueReal("time");

                // Convert time to milliseconds for update()
                update((int)(time * 1000.0f));
            }
            else if(message_name == "cleanup")
            {
                // DTOR most likely won't be called but the recent change to the way this process
                // is (not) killed means we see this message and can do what we need to here.
                // Note: this cleanup is ultimately what writes cookies to the disk
                LLQtWebKit::getInstance()->remObserver( mBrowserWindowId, this );
                LLQtWebKit::getInstance()->reset();
            }
            else if(message_name == "shm_added")
            {
                SharedSegmentInfo info;
                info.mAddress = message_in.getValuePointer("address");
                info.mSize = (size_t)message_in.getValueS32("size");
                std::string name = message_in.getValue("name");

//				std::cerr << "MediaPluginWebKit::receiveMessage: shared memory added, name: " << name
//					<< ", size: " << info.mSize
//					<< ", address: " << info.mAddress
//					<< std::endl;

                mSharedSegments.insert(SharedSegmentMap::value_type(name, info));

            }
            else if(message_name == "shm_remove")
            {
                std::string name = message_in.getValue("name");

//				std::cerr << "MediaPluginWebKit::receiveMessage: shared memory remove, name = " << name << std::endl;

                SharedSegmentMap::iterator iter = mSharedSegments.find(name);
                if(iter != mSharedSegments.end())
                {
                    if(mPixels == iter->second.mAddress)
                    {
                        // This is the currently active pixel buffer.  Make sure we stop drawing to it.
                        mPixels = NULL;
                        mTextureSegmentName.clear();
                    }
                    mSharedSegments.erase(iter);
                }
                else
                {
//					std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl;
                }

                // Send the response so it can be cleaned up.
                LLPluginMessage message("base", "shm_remove_response");
                message.setValue("name", name);
                sendMessage(message);
            }
            else
            {
//				std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl;
            }
        }
        else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
        {
            if(message_name == "set_volume")
            {
                F32 volume = message_in.getValueReal("volume");
                setVolume(volume);
            }
        }
        else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA)
        {
            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())
                {

                    // Plugin gets to decide the texture parameters to use.
                    mDepth = 4;

                    LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
                    message.setValueS32("default_width", 1024);
                    message.setValueS32("default_height", 1024);
                    message.setValueS32("depth", mDepth);
                    message.setValueU32("internalformat", GL_RGBA);
#if LL_QTWEBKIT_USES_PIXMAPS
                    message.setValueU32("format", GL_BGRA_EXT); // I hope this isn't system-dependant... is it?  If so, we'll have to check the root window's pixel layout or something... yuck.
#else
                    message.setValueU32("format", GL_RGBA);
#endif // LL_QTWEBKIT_USES_PIXMAPS
                    message.setValueU32("type", GL_UNSIGNED_BYTE);
                    message.setValueBoolean("coords_opengl", true);
                    sendMessage(message);
                }
                else
                {
                    // if initialization failed, we're done.
                    mDeleteMe = true;
                }

            }
            else if(message_name == "set_user_data_path")
            {
                std::string user_data_path = message_in.getValue("path"); // n.b. always has trailing platform-specific dir-delimiter
                mProfileDir = user_data_path + "browser_profile";

                // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
            }
            else if(message_name == "set_language_code")
            {
                mHostLanguage = message_in.getValue("language");

                // FIXME: Should we do anything with this if it comes in after the browser has been initialized?
            }
            else if(message_name == "plugins_enabled")
            {
                mPluginsEnabled = message_in.getValueBoolean("enable");
            }
            else if(message_name == "javascript_enabled")
            {
                mJavascriptEnabled = message_in.getValueBoolean("enable");
            }
            else if(message_name == "size_change")
            {
                std::string name = message_in.getValue("name");
                S32 width = message_in.getValueS32("width");
                S32 height = message_in.getValueS32("height");
                S32 texture_width = message_in.getValueS32("texture_width");
                S32 texture_height = message_in.getValueS32("texture_height");
                mBackgroundR = message_in.getValueReal("background_r");
                mBackgroundG = message_in.getValueReal("background_g");
                mBackgroundB = message_in.getValueReal("background_b");
//				mBackgroundA = message_in.setValueReal("background_a");		// Ignore any alpha

                if(!name.empty())
                {
                    // Find the shared memory region with this name
                    SharedSegmentMap::iterator iter = mSharedSegments.find(name);
                    if(iter != mSharedSegments.end())
                    {
                        mPixels = (unsigned char*)iter->second.mAddress;
                        mWidth = width;
                        mHeight = height;

                        if(initBrowserWindow())
                        {

                            // size changed so tell the browser
                            LLQtWebKit::getInstance()->setSize( mBrowserWindowId, mWidth, mHeight );

                            //						std::cerr << "webkit plugin: set size to " << mWidth << " x " << mHeight
                            //								<< ", rowspan is " << LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) << std::endl;

                            S32 real_width = LLQtWebKit::getInstance()->getBrowserRowSpan(mBrowserWindowId) / LLQtWebKit::getInstance()->getBrowserDepth(mBrowserWindowId);

                            // The actual width the browser will be drawing to is probably smaller... let the host know by modifying texture_width in the response.
                            if(real_width <= texture_width)
                            {
                                texture_width = real_width;
                            }
                            else
                            {
                                // This won't work -- it'll be bigger than the allocated memory.  This is a fatal error.
                                //							std::cerr << "Fatal error: browser rowbytes greater than texture width" << std::endl;
                                mDeleteMe = true;
                                return;
                            }
                        }
                        else
                        {
                            // Setting up the browser window failed.  This is a fatal error.
                            mDeleteMe = true;
                        }


                        mTextureWidth = texture_width;
                        mTextureHeight = texture_height;

                    };
                };

                LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response");
                message.setValue("name", name);
                message.setValueS32("width", width);
                message.setValueS32("height", height);
                message.setValueS32("texture_width", texture_width);
                message.setValueS32("texture_height", texture_height);
                sendMessage(message);

            }
            else if(message_name == "load_uri")
            {
                std::string uri = message_in.getValue("uri");

//				std::cout << "loading URI: " << uri << std::endl;

                if(!uri.empty())
                {
                    if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE)
                    {
                        LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, uri );
                    }
                    else
                    {
                        mInitialNavigateURL = uri;
                    }
                }
            }
            else if(message_name == "mouse_event")
            {
                std::string event = message_in.getValue("event");
                S32 button = message_in.getValueS32("button");
                mLastMouseX = message_in.getValueS32("x");
                mLastMouseY = message_in.getValueS32("y");
                std::string modifiers = message_in.getValue("modifiers");

                // Treat unknown mouse events as mouse-moves.
                LLQtWebKit::EMouseEvent mouse_event = LLQtWebKit::ME_MOUSE_MOVE;
                if(event == "down")
                {
                    mouse_event = LLQtWebKit::ME_MOUSE_DOWN;
                }
                else if(event == "up")
                {
                    mouse_event = LLQtWebKit::ME_MOUSE_UP;
                }
                else if(event == "double_click")
                {
                    mouse_event = LLQtWebKit::ME_MOUSE_DOUBLE_CLICK;
                }

                LLQtWebKit::getInstance()->mouseEvent( mBrowserWindowId, mouse_event, button, mLastMouseX, mLastMouseY, decodeModifiers(modifiers));
                checkEditState();
            }
            else if(message_name == "scroll_event")
            {
                S32 x = message_in.getValueS32("x");
                S32 y = message_in.getValueS32("y");
                std::string modifiers = message_in.getValue("modifiers");

                // Incoming scroll events are adjusted so that 1 detent is approximately 1 unit.
                // Qt expects 1 detent to be 120 units.
                // It also seems that our y scroll direction is inverted vs. what Qt expects.

                x *= 120;
                y *= -120;

                LLQtWebKit::getInstance()->scrollWheelEvent(mBrowserWindowId, mLastMouseX, mLastMouseY, x, y, decodeModifiers(modifiers));
            }
            else if(message_name == "key_event")
            {
                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.
                LLQtWebKit::EKeyEvent key_event = LLQtWebKit::KE_KEY_UP;
                if(event == "down")
                {
                    key_event = LLQtWebKit::KE_KEY_DOWN;
                }
                else if(event == "repeat")
                {
                    key_event = LLQtWebKit::KE_KEY_REPEAT;
                }

                keyEvent(key_event, key, decodeModifiers(modifiers), native_key_data);
            }
            else if(message_name == "text_event")
            {
                std::string text = message_in.getValue("text");
                std::string modifiers = message_in.getValue("modifiers");
                LLSD native_key_data = message_in.getValueLLSD("native_key_data");

                unicodeInput(text, decodeModifiers(modifiers), native_key_data);
            }
            if(message_name == "edit_cut")
            {
                LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_CUT );
                checkEditState();
            }
            if(message_name == "edit_copy")
            {
                LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_COPY );
                checkEditState();
            }
            if(message_name == "edit_paste")
            {
                LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_EDIT_PASTE );
                checkEditState();
            }
            if(message_name == "pick_file_response")
            {
                onPickFileResponse(message_in.getValue("file"));
            }
            else
            {
//				std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl;
            }
        }
        else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER)
        {
            if(message_name == "focus")
            {
                bool val = message_in.getValueBoolean("focused");
                LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, val );

                if(mFirstFocus && val)
                {
                    // On the first focus, post a tab key event.  This fixes a problem with initial focus.
                    std::string empty;
                    keyEvent(LLQtWebKit::KE_KEY_DOWN, KEY_TAB, decodeModifiers(empty));
                    keyEvent(LLQtWebKit::KE_KEY_UP, KEY_TAB, decodeModifiers(empty));
                    mFirstFocus = false;
                }
            }
            else if(message_name == "clear_cache")
            {
                LLQtWebKit::getInstance()->clearCache();
            }
            else if(message_name == "clear_cookies")
            {
                LLQtWebKit::getInstance()->clearAllCookies();
            }
            else if(message_name == "enable_cookies")
            {
                mCookiesEnabled = message_in.getValueBoolean("enable");
                LLQtWebKit::getInstance()->enableCookies( mCookiesEnabled );
            }
            else if(message_name == "enable_plugins")
            {
                mPluginsEnabled = message_in.getValueBoolean("enable");
                LLQtWebKit::getInstance()->enablePlugins( mPluginsEnabled );
            }
            else if(message_name == "enable_javascript")
            {
                mJavascriptEnabled = message_in.getValueBoolean("enable");
                //LLQtWebKit::getInstance()->enableJavascript( mJavascriptEnabled );
            }
            else if(message_name == "set_cookies")
            {
                LLQtWebKit::getInstance()->setCookies(message_in.getValue("cookies"));
            }
            else if(message_name == "proxy_setup")
            {
                bool val = message_in.getValueBoolean("enable");
                std::string host = message_in.getValue("host");
                int port = message_in.getValueS32("port");
                LLQtWebKit::getInstance()->enableProxy( val, host, port );
            }
            else if(message_name == "browse_stop")
            {
                LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_STOP );
            }
            else if(message_name == "browse_reload")
            {
                // foo = message_in.getValueBoolean("ignore_cache");
                LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_RELOAD );
            }
            else if(message_name == "browse_forward")
            {
                LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD );
            }
            else if(message_name == "browse_back")
            {
                LLQtWebKit::getInstance()->userAction( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK );
            }
            else if(message_name == "set_status_redirect")
            {
                int code = message_in.getValueS32("code");
                std::string url = message_in.getValue("url");
                if ( 404 == code )	// browser lib only supports 404 right now
                {
                    LLQtWebKit::getInstance()->set404RedirectUrl( mBrowserWindowId, url );
                };
            }
            else if(message_name == "set_user_agent")
            {
                mUserAgent = message_in.getValue("user_agent");
                LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent );
            }
            else if(message_name == "init_history")
            {
                // Initialize browser history
                LLSD history = message_in.getValueLLSD("history");
                // First, clear the URL history
                LLQtWebKit::getInstance()->clearHistory(mBrowserWindowId);
                // Then, add the history items in order
                LLSD::array_iterator iter_history = history.beginArray();
                LLSD::array_iterator end_history = history.endArray();
                for(; iter_history != end_history; ++iter_history)
                {
                    std::string url = (*iter_history).asString();
                    if(! url.empty()) {
                        LLQtWebKit::getInstance()->prependHistoryUrl(mBrowserWindowId, url);
                    }
                }
            }
            else if(message_name == "proxy_window_opened")
            {
                std::string target = message_in.getValue("target");
                std::string uuid = message_in.getValue("uuid");
                LLQtWebKit::getInstance()->proxyWindowOpened(mBrowserWindowId, target, uuid);
            }
            else if(message_name == "proxy_window_closed")
            {
                std::string uuid = message_in.getValue("uuid");
                LLQtWebKit::getInstance()->proxyWindowClosed(mBrowserWindowId, uuid);
            }
            else
            {
//				std::cerr << "MediaPluginWebKit::receiveMessage: unknown media_browser message: " << message_string << std::endl;
            };
        }
        else
        {
//			std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl;
        };
    }
}