diff options
author | Jiri Vanek <[email protected]> | 2013-12-15 11:07:05 +0100 |
---|---|---|
committer | Jiri Vanek <[email protected]> | 2013-12-15 11:07:05 +0100 |
commit | d91bf9ee53eebc7028f4143e03881ee350e4ebef (patch) | |
tree | d1886733f58835ff3a9ae5d51a5411139ae55ce5 /plugin | |
parent | 3c5836190bd9954c56c7d4180bfc2e7ed9a0d82d (diff) |
Console made aware of plugin messages
Diffstat (limited to 'plugin')
-rw-r--r-- | plugin/icedteanp/IcedTeaNPPlugin.cc | 153 | ||||
-rw-r--r-- | plugin/icedteanp/IcedTeaNPPlugin.h | 9 | ||||
-rw-r--r-- | plugin/icedteanp/IcedTeaPluginUtils.cc | 33 | ||||
-rw-r--r-- | plugin/icedteanp/IcedTeaPluginUtils.h | 39 | ||||
-rw-r--r-- | plugin/icedteanp/java/sun/applet/PluginMain.java | 17 |
5 files changed, 245 insertions, 6 deletions
diff --git a/plugin/icedteanp/IcedTeaNPPlugin.cc b/plugin/icedteanp/IcedTeaNPPlugin.cc index 9a0d0c4..1317831 100644 --- a/plugin/icedteanp/IcedTeaNPPlugin.cc +++ b/plugin/icedteanp/IcedTeaNPPlugin.cc @@ -138,6 +138,9 @@ gint in_watch_source; // Applet viewer output pipe name. gchar* out_pipe_name; +// Applet viewer debug pipe name. +gchar* debug_pipe_name = NULL; + // Applet viewer output watch source. gint out_watch_source; @@ -147,9 +150,15 @@ pthread_t itnp_plugin_thread_id; // Mutex to lock async call queue pthread_mutex_t pluginAsyncCallMutex; +/*to sync pipe to apletviewer console*/ +pthread_mutex_t debug_pipe_lock = PTHREAD_MUTEX_INITIALIZER; + // Applet viewer output channel. GIOChannel* out_to_appletviewer; +// Applet viewer debug channel. +GIOChannel* debug_to_appletviewer = NULL; + // Tracks jvm status gboolean jvm_up = FALSE; @@ -488,6 +497,34 @@ void start_jvm_if_needed() } PLUGIN_DEBUG ("ITNP_New: created output fifo: %s\n", out_pipe_name); + // Create plugin-debug-to-appletviewer pipe which we refer to as the + // debug pipe. + initialize_debug();//should be already initialized, but... + if (plugin_debug_to_console){ + // debug_pipe_name + debug_pipe_name = g_strdup_printf ("%s/%d-icedteanp-plugin-debug-to-appletviewer", + data_directory.c_str(), getpid()); + + if (!debug_pipe_name) + { + PLUGIN_ERROR ("Failed to create debug pipe name.\n"); + np_error = NPERR_OUT_OF_MEMORY_ERROR; + goto cleanup_debug_pipe_name; + } + + // clean up any older pip + unlink (debug_pipe_name); + + PLUGIN_DEBUG ("ITNP_New: creating debug fifo: %s\n", debug_pipe_name); + if (mkfifo (debug_pipe_name, 0600) == -1 && errno != EEXIST) + { + PLUGIN_ERROR ("Failed to create debug pipe\n", strerror (errno)); + np_error = NPERR_GENERIC_ERROR; + goto cleanup_debug_pipe_name; + } + PLUGIN_DEBUG ("ITNP_New: created debug fifo: %s\n", debug_pipe_name); + } + // Start a separate appletviewer process for each applet, even if // there are multiple applets in the same page. We may need to // change this behaviour if we find pages with multiple applets that @@ -548,12 +585,46 @@ void start_jvm_if_needed() g_io_add_watch (in_from_appletviewer, (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_HUP), plugin_in_pipe_callback, (gpointer) in_from_appletviewer); + + // Create plugin-to-appletviewer console debug channel. The default encoding for + // the file is UTF-8. + // debug_to_appletviewer + if (plugin_debug_to_console){ + debug_to_appletviewer = g_io_channel_new_file (debug_pipe_name, + "w", &channel_error); + if (!debug_to_appletviewer) + { + if (channel_error) + { + PLUGIN_ERROR ("Failed to debug output channel, '%s'\n", + channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to create debug channel\n"); + + np_error = NPERR_GENERIC_ERROR; + goto cleanup_debug_to_appletviewer; + } + } jvm_up = TRUE; - + + if (plugin_debug_to_console){ + //jvm is up, we can start console producer thread + pthread_t debug_to_console_consumer; + pthread_create(&debug_to_console_consumer,NULL,&flush_pre_init_messages,NULL); + } goto done; // Free allocated data in case of error + cleanup_debug_to_appletviewer: + if (plugin_debug_to_console){ + if (debug_to_appletviewer) + g_io_channel_unref (debug_to_appletviewer); + debug_to_appletviewer = NULL; + } cleanup_in_watch_source: // Removing a source is harmless if it fails since it just means the @@ -575,6 +646,21 @@ void start_jvm_if_needed() g_io_channel_unref (out_to_appletviewer); out_to_appletviewer = NULL; + if (plugin_debug_to_console){ + // cleanup_debug_pipe: + // Delete output pipe. + PLUGIN_DEBUG ("ITNP_New: deleting debug fifo: %s\n", debug_pipe_name); + unlink (debug_pipe_name); + PLUGIN_DEBUG ("ITNP_New: deleted debug fifo: %s\n", debug_pipe_name); + } + cleanup_debug_pipe_name: + if (plugin_debug_to_console){ + g_free (debug_pipe_name); + debug_pipe_name = NULL; + } + + + // cleanup_out_pipe: // Delete output pipe. PLUGIN_DEBUG ("ITNP_New: deleting input fifo: %s\n", in_pipe_name); @@ -1401,6 +1487,9 @@ plugin_start_appletviewer (ITNPPluginData* data) command_line.push_back("sun.applet.PluginMain"); command_line.push_back(out_pipe_name); command_line.push_back(in_pipe_name); + if (plugin_debug_to_console){ + command_line.push_back(debug_pipe_name); + } // Finished command line parameters @@ -1576,6 +1665,38 @@ plugin_send_message_to_appletviewer (gchar const* message) PLUGIN_DEBUG ("plugin_send_message_to_appletviewer return\n"); } +// unlike like plugin_send_message_to_appletviewer +// do not debug +// do not error +// do not have its own line end +// is accesed by only one thread +// have own pipe +// jvm must be up +void +plugin_send_message_to_appletviewer_console (gchar const* newline_message) +{ + gsize bytes_written = 0; + if (g_io_channel_write_chars (debug_to_appletviewer, + newline_message, -1, &bytes_written, + &channel_error) != G_IO_STATUS_NORMAL) { + if (channel_error) { + //error must be freed + g_error_free (channel_error); + channel_error = NULL; + } + } +} +//flush only when its full +void flush_plugin_send_message_to_appletviewer_console (){ + if (g_io_channel_flush (debug_to_appletviewer, &channel_error) + != G_IO_STATUS_NORMAL) { + if (channel_error) { + g_error_free (channel_error); + channel_error = NULL; + } + } +} + /* * Sends the initialization message (handle/size/url) to the plugin */ @@ -2046,6 +2167,36 @@ NP_Shutdown (void) g_free (in_pipe_name); in_pipe_name = NULL; + if (plugin_debug_to_console){ + //jvm_up is now false + if (g_io_channel_shutdown (debug_to_appletviewer, + TRUE, &channel_error) + != G_IO_STATUS_NORMAL) + { + if (channel_error) + { + PLUGIN_ERROR ("Failed to shut down appletviewer" + " debug channel\n", channel_error->message); + g_error_free (channel_error); + channel_error = NULL; + } + else + PLUGIN_ERROR ("Failed to shut down debug to appletviewer\n"); + } + // cleanup_out_to_appletviewer: + if (debug_to_appletviewer) + g_io_channel_unref (debug_to_appletviewer); + out_to_appletviewer = NULL; + // cleanup_debug_pipe: + // Delete debug pipe. + PLUGIN_DEBUG ("NP_Shutdown: deleting debug fifo: %s\n", debug_pipe_name); + unlink (debug_pipe_name); + PLUGIN_DEBUG ("NP_Shutdown: deleted debug fifo: %s\n", debug_pipe_name); + // cleanup_out_pipe_name: + g_free (debug_pipe_name); + debug_pipe_name = NULL; + } + // Destroy the call queue mutex pthread_mutex_destroy(&pluginAsyncCallMutex); diff --git a/plugin/icedteanp/IcedTeaNPPlugin.h b/plugin/icedteanp/IcedTeaNPPlugin.h index 6e1465b..3e66599 100644 --- a/plugin/icedteanp/IcedTeaNPPlugin.h +++ b/plugin/icedteanp/IcedTeaNPPlugin.h @@ -115,6 +115,9 @@ extern pthread_t itnp_plugin_thread_id; /* Mutex around plugin async call queue ops */ extern pthread_mutex_t pluginAsyncCallMutex; +/*to sync pipe to apletviewer console*/ +extern pthread_mutex_t debug_pipe_lock; + // debug switches extern bool debug_initiated; extern int plugin_debug; @@ -125,6 +128,9 @@ extern bool plugin_debug_to_system; extern bool plugin_debug_to_console; extern FILE * plugin_file_log; extern std::string plugin_file_log_name; +extern gchar* debug_pipe_name; + +extern gboolean jvm_up; // Browser function table. extern NPNetscapeFuncs browser_functions; @@ -152,6 +158,9 @@ int get_id_from_instance(NPP instance); /* Sends a message to the appletviewer */ void plugin_send_message_to_appletviewer(gchar const* message); +/*this method is not logging, do not add \n and is using different pipe*/ +void plugin_send_message_to_appletviewer_console(gchar const* message); +void flush_plugin_send_message_to_appletviewer_console(); /* Returns an appropriate (package/object) scriptable npobject */ NPObject* get_scriptable_object(NPP instance); diff --git a/plugin/icedteanp/IcedTeaPluginUtils.cc b/plugin/icedteanp/IcedTeaPluginUtils.cc index 0986aa8..5cd4231 100644 --- a/plugin/icedteanp/IcedTeaPluginUtils.cc +++ b/plugin/icedteanp/IcedTeaPluginUtils.cc @@ -54,10 +54,37 @@ int IcedTeaPluginUtilities::reference = -1; pthread_mutex_t IcedTeaPluginUtilities::reference_mutex = PTHREAD_MUTEX_INITIALIZER; std::map<void*, NPP>* IcedTeaPluginUtilities::instance_map = new std::map<void*, NPP>(); std::map<std::string, NPObject*>* IcedTeaPluginUtilities::object_map = new std::map<std::string, NPObject*>(); +std::queue<std::string> pre_jvm_message; /* Plugin async call queue */ static std::vector< PluginThreadCall* >* pendingPluginThreadRequests = new std::vector< PluginThreadCall* >(); +void *flush_pre_init_messages(void* data) { +while (true){ + struct timespec ts; + ts.tv_sec = 1; + ts.tv_nsec = 0; + nanosleep(&ts ,0); + if (jvm_up) { + while (!pre_jvm_message.empty()) { + pthread_mutex_lock(&debug_pipe_lock); + std::string message = pre_jvm_message.front(); + pre_jvm_message.pop(); + pthread_mutex_unlock(&debug_pipe_lock); + plugin_send_message_to_appletviewer_console(message.c_str()); + + } + flush_plugin_send_message_to_appletviewer_console(); + } + +} +} +void push_pre_init_messages(char * ldm){ + pthread_mutex_lock(&debug_pipe_lock); + pre_jvm_message.push(std::string(ldm)); + pthread_mutex_unlock(&debug_pipe_lock); +} + /** * Given a context number, constructs a message prefix to send to Java * @@ -1161,7 +1188,11 @@ void IcedTeaPluginUtilities::printDebugStatus(){ PLUGIN_DEBUG("plugin_debug_to_system: false\n"); } if (plugin_debug_to_console){ - PLUGIN_DEBUG("plugin_debug_to_console: true\n"); + if (debug_pipe_name){ + PLUGIN_DEBUG("plugin_debug_to_console: true, pipe %s\n", debug_pipe_name); + } else { + PLUGIN_DEBUG("plugin_debug_to_console: true, pipe not yet known or broken\n"); + } } else { PLUGIN_DEBUG("plugin_debug_to_console: false\n"); } diff --git a/plugin/icedteanp/IcedTeaPluginUtils.h b/plugin/icedteanp/IcedTeaPluginUtils.h index f0f52d7..6967793 100644 --- a/plugin/icedteanp/IcedTeaPluginUtils.h +++ b/plugin/icedteanp/IcedTeaPluginUtils.h @@ -58,6 +58,7 @@ exception statement from your version. */ #include <sstream> #include <string> #include <vector> +#include <queue> #include <npapi.h> #include <glib.h> @@ -65,6 +66,9 @@ exception statement from your version. */ #include "IcedTeaParseProperties.h" +void *flush_pre_init_messages(void* data); +void push_pre_init_messages(char * ldm); + // debugging macro. #define initialize_debug() \ do \ @@ -81,7 +85,7 @@ exception statement from your version. */ IcedTeaPluginUtilities::initFileLog(); \ } \ if (plugin_debug_to_console) { \ - /*no op now*/ \ + /*initialisation done during jvm startup*/ \ } \ IcedTeaPluginUtilities::printDebugStatus(); \ } \ @@ -91,6 +95,7 @@ exception statement from your version. */ #define HEADER_SIZE 500 #define BODY_SIZE 500 #define MESSAGE_SIZE HEADER_SIZE + BODY_SIZE +#define LDEBUG_MESSAGE_SIZE MESSAGE_SIZE+50 //header is destination char array #define CREATE_HEADER(ldebug_header) \ @@ -132,7 +137,21 @@ exception statement from your version. */ fflush(plugin_file_log); \ } \ if (plugin_debug_to_console) { \ - /*no op now*/ \ + /*headers are always going to console*/ \ + if (!plugin_debug_headers){ \ + CREATE_HEADER(ldebug_header); \ + } \ + snprintf(ldebug_message, MESSAGE_SIZE, "%s%s", ldebug_header, ldebug_body); \ + char ldebug_channel_message[LDEBUG_MESSAGE_SIZE]; \ + struct timeval current_time; \ + gettimeofday (¤t_time, NULL);\ + if (jvm_up) { \ + snprintf(ldebug_channel_message, LDEBUG_MESSAGE_SIZE, "%s %ld %s", "plugindebug", current_time.tv_sec*1000000L+current_time.tv_usec, ldebug_message); \ + push_pre_init_messages(ldebug_channel_message); \ + } else { \ + snprintf(ldebug_channel_message, LDEBUG_MESSAGE_SIZE, "%s %ld %s", "preinit_plugindebug", current_time.tv_sec*1000000L+current_time.tv_usec, ldebug_message); \ + push_pre_init_messages(ldebug_channel_message); \ + } \ } \ } \ } while (0) @@ -161,7 +180,21 @@ exception statement from your version. */ fflush(plugin_file_log); \ } \ if (plugin_debug_to_console) { \ - /*no op now*/ \ + /*headers are always going to console*/ \ + if (!plugin_debug_headers){ \ + CREATE_HEADER(ldebug_header); \ + } \ + snprintf(ldebug_message, MESSAGE_SIZE, "%s%s", ldebug_header, ldebug_body); \ + char ldebug_channel_message[LDEBUG_MESSAGE_SIZE]; \ + struct timeval current_time; \ + gettimeofday (¤t_time, NULL);\ + if (jvm_up) { \ + snprintf(ldebug_channel_message, LDEBUG_MESSAGE_SIZE, "%s %ld %s", "pluginerror", current_time.tv_sec*1000000L+current_time.tv_usec, ldebug_message); \ + push_pre_init_messages(ldebug_channel_message); \ + } else { \ + snprintf(ldebug_channel_message, LDEBUG_MESSAGE_SIZE, "%s %ld %s", "preinit_pluginerror", current_time.tv_sec*1000000L+current_time.tv_usec, ldebug_message); \ + push_pre_init_messages(ldebug_channel_message); \ + } \ } \ } while (0) diff --git a/plugin/icedteanp/java/sun/applet/PluginMain.java b/plugin/icedteanp/java/sun/applet/PluginMain.java index e6ba080..421edb5 100644 --- a/plugin/icedteanp/java/sun/applet/PluginMain.java +++ b/plugin/icedteanp/java/sun/applet/PluginMain.java @@ -84,6 +84,7 @@ import net.sourceforge.jnlp.config.DeploymentConfiguration; import net.sourceforge.jnlp.runtime.JNLPRuntime; import net.sourceforge.jnlp.security.JNLPAuthenticator; import net.sourceforge.jnlp.util.logging.JavaConsole; +import net.sourceforge.jnlp.util.logging.LogConfig; import net.sourceforge.jnlp.util.logging.OutputController; /** @@ -119,16 +120,30 @@ public class PluginMain { */ public static void main(String args[]) throws IOException { + //we are polite, we reprint start arguments + OutputController.getLogger().log("startup arguments: "); + for (int i = 0; i < args.length; i++) { + String string = args[i]; + OutputController.getLogger().log(i + ": "+string); + + } if (AppContext.getAppContext() == null) { SunToolkit.createNewAppContext(); } installDummyJavascriptProtocolHandler(); - if (args.length != 2 || !(new File(args[0]).exists()) || !(new File(args[1]).exists())) { + if (args.length < 2 || !(new File(args[0]).exists()) || !(new File(args[1]).exists())) { OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Invalid pipe names provided. Refusing to proceed."); JNLPRuntime.exit(1); } DeploymentConfiguration.move14AndOlderFilesTo15StructureCatched(); + if (JavaConsole.isEnabled()) { + if ((args.length < 3) || !new File(args[2]).exists()) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, "Warning, although console is on, plugin debug connection do not exists. No plugin information will be displayed in console (only java ones)."); + } else { + JavaConsole.getConsole().createPluginReader(new File(args[2])); + } + } try { PluginStreamHandler streamHandler = connect(args[0], args[1]); |