summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2004-08-13 00:55:59 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2004-08-13 00:55:59 +0000
commitd7627cecebad4abb64840561d7afa46a62e1dd6d (patch)
treee33a8ec56ebc5463dd5bfb8e60b9a898f72e4c24
parent0a93f2d264080b8c0c748cbe0477123a3eb4b62d (diff)
downloadnetsurf-d7627cecebad4abb64840561d7afa46a62e1dd6d.tar.gz
netsurf-d7627cecebad4abb64840561d7afa46a62e1dd6d.tar.bz2
[project @ 2004-08-13 00:55:59 by jmb]
Rewrite of plugin handling. This is now much nicer than before although it has about the same amount of functionality. Note: This is now configurable via an option (defaults to OFF) This has only really been tested with the Flash plugin and seems to work reasonably. svn path=/import/netsurf/; revision=1216
-rw-r--r--content/content.c2
-rw-r--r--render/box.h11
-rw-r--r--riscos/gui.c25
-rw-r--r--riscos/options.h7
-rw-r--r--riscos/plugin.c2289
-rw-r--r--riscos/plugin.h78
6 files changed, 1145 insertions, 1267 deletions
diff --git a/content/content.c b/content/content.c
index 82e015150..a74892eb9 100644
--- a/content/content.c
+++ b/content/content.c
@@ -200,7 +200,7 @@ static const struct handler_entry handler_map[] = {
#endif
#ifdef WITH_PLUGIN
{plugin_create, 0, plugin_convert,
- 0, plugin_destroy, 0, plugin_redraw,
+ plugin_reformat, plugin_destroy, 0, plugin_redraw,
plugin_open, plugin_close,
true},
#endif
diff --git a/render/box.h b/render/box.h
index 3f69917bf..bb493a323 100644
--- a/render/box.h
+++ b/render/box.h
@@ -102,16 +102,9 @@ struct object_params {
char* codebase;
char* classid;
struct plugin_params* params;
- /* not a parameter, but stored here for convenience */
+ /* not a parameter but stored here for convenience */
char* basehref;
- char* filename;
- bool repeated;
- unsigned int browser;
- unsigned int plugin;
- unsigned int browser_stream;
- unsigned int plugin_stream;
- unsigned int plugin_task;
- unsigned int consumed;
+
};
struct plugin_params {
diff --git a/riscos/gui.c b/riscos/gui.c
index 5cda9a0ee..82cc07f49 100644
--- a/riscos/gui.c
+++ b/riscos/gui.c
@@ -1001,24 +1001,47 @@ void ro_gui_user_message(wimp_event_no event, wimp_message *message)
#endif
#ifdef WITH_PLUGIN
case message_PLUG_IN_OPENING:
+ plugin_opening(message);
+ break;
case message_PLUG_IN_CLOSED:
+ plugin_closed(message);
+ break;
case message_PLUG_IN_RESHAPE_REQUEST:
+ plugin_reshape_request(message);
+ break;
case message_PLUG_IN_FOCUS:
+ break;
case message_PLUG_IN_URL_ACCESS:
+ plugin_url_access(message);
+ break;
case message_PLUG_IN_STATUS:
+ plugin_status(message);
+ break;
case message_PLUG_IN_BUSY:
+ break;
case message_PLUG_IN_STREAM_NEW:
+ plugin_stream_new(message);
+ break;
case message_PLUG_IN_STREAM_WRITE:
+ break;
case message_PLUG_IN_STREAM_WRITTEN:
+ plugin_stream_written(message);
+ break;
case message_PLUG_IN_STREAM_DESTROY:
+ break;
case message_PLUG_IN_OPEN:
+ if (event == wimp_USER_MESSAGE_ACKNOWLEDGE)
+ plugin_open_msg(message);
+ break;
case message_PLUG_IN_CLOSE:
+ if (event == wimp_USER_MESSAGE_ACKNOWLEDGE)
+ plugin_close_msg(message);
+ break;
case message_PLUG_IN_RESHAPE:
case message_PLUG_IN_STREAM_AS_FILE:
case message_PLUG_IN_NOTIFY:
case message_PLUG_IN_ABORT:
case message_PLUG_IN_ACTION:
- plugin_msg_parse(message, event == wimp_USER_MESSAGE_ACKNOWLEDGE);
break;
#endif
#ifdef WITH_PRINT
diff --git a/riscos/options.h b/riscos/options.h
index 71cd06026..34e2b837a 100644
--- a/riscos/options.h
+++ b/riscos/options.h
@@ -47,6 +47,7 @@ extern bool option_buffer_animations;
extern bool option_buffer_everything;
extern char *option_homepage_url;
extern bool option_open_browser_at_startup;
+extern bool option_plugins;
#define EXTRA_OPTION_DEFINE \
bool option_use_mouse_gestures = false;\
@@ -79,7 +80,8 @@ bool option_background_blending = true; \
bool option_buffer_animations = true; \
bool option_buffer_everything = false; \
char *option_homepage_url = 0; \
-bool option_open_browser_at_startup = false;
+bool option_open_browser_at_startup = false; \
+bool option_plugins = false;
#define EXTRA_OPTION_TABLE \
{ "use_mouse_gestures", OPTION_BOOL, &option_use_mouse_gestures },\
@@ -112,5 +114,6 @@ bool option_open_browser_at_startup = false;
{ "buffer_animations", OPTION_BOOL, &option_buffer_animations }, \
{ "buffer_everything", OPTION_BOOL, &option_buffer_everything }, \
{ "homepage_url", OPTION_STRING, &option_homepage_url }, \
-{ "open_browser_at_startup",OPTION_BOOL, &option_open_browser_at_startup }
+{ "open_browser_at_startup",OPTION_BOOL, &option_open_browser_at_startup }, \
+{ "plugins", OPTION_BOOL, &option_plugins }
#endif
diff --git a/riscos/plugin.c b/riscos/plugin.c
index 61e907409..da939d2c8 100644
--- a/riscos/plugin.c
+++ b/riscos/plugin.c
@@ -2,21 +2,34 @@
* This file is part of NetSurf, http://netsurf.sourceforge.net/
* Licensed under the GNU General Public License,
* http://www.opensource.org/licenses/gpl-license
- * Copyright 2003 John M Bell <jmb202@ecs.soton.ac.uk>
+ * Copyright 2003,4 John M Bell <jmb202@ecs.soton.ac.uk>
*/
-/*
- * TODO:
- * - Reshaping plugin by request [Plugin_Reshape_Request (&4d545)]
- * - Finish off stream protocol implementation (data from plugin)
- * - Parse and act upon the rest of the Plugin_Opening flags
- * - Implement remaining messages [Plugin_URL_Access, Plugin_Focus,
- * Plugin_Busy, Plugin_Action, Plugin_Abort, Plugin_Inform(ed)?]
- * - Handle standalone objects
+/** \file
+ * Acorn Plugin protocol (implementation)
+ *
+ * This file implements the Acorn plugin protocol.
+ * See http://www.ecs.soton.ac.uk/~jmb202/riscos/acorn/funcspec.html
+ * for more details.
+ *
+ * The are still a number of outstanding issues:
+ *
+ * Stream Protocol:
+ * Fetching data, then streaming it to a plugin is not supported
+ * Streaming data from a plugin is not supported
+ *
+ * Messages:
+ * Most Plugin_Opening flags not supported
+ * No support for Plugin_Focus, Plugin_Busy, Plugin_Action
+ * No support for Plugin_Abort, Plugin_Inform, Plugin_Informed
+ * Plugin_URL_Access is only part-implemented
+ *
+ * No support for "helper" applications
+ * No support for standalone objects (must be embedded in HTML page)
+ *
+ *
*/
-// #define NDEBUG
-
#include <assert.h>
#include <ctype.h>
#include <stdbool.h>
@@ -24,6 +37,14 @@
#include <stdlib.h>
#include <string.h>
+#include "oslib/mimemap.h"
+#include "oslib/os.h"
+#include "oslib/osfile.h"
+#include "oslib/osfind.h"
+#include "oslib/osgbpb.h"
+#include "oslib/plugin.h"
+#include "oslib/wimp.h"
+
#include "netsurf/utils/config.h"
#include "netsurf/content/content.h"
#include "netsurf/desktop/browser.h"
@@ -31,1386 +52,1242 @@
#include "netsurf/render/html.h"
#include "netsurf/render/box.h"
#include "netsurf/riscos/gui.h"
+#include "netsurf/riscos/options.h"
#include "netsurf/riscos/plugin.h"
#include "netsurf/utils/log.h"
#include "netsurf/utils/messages.h"
#include "netsurf/utils/utils.h"
-#include "oslib/mimemap.h"
-#include "oslib/os.h"
-#include "oslib/osfile.h"
-#include "oslib/osfind.h"
-#include "oslib/osgbpb.h"
-#include "oslib/plugin.h"
-#include "oslib/wimp.h"
#ifdef WITH_PLUGIN
-/* parameters file creation */
-void plugin_write_parameters_file(struct object_params *params);
-int plugin_calculate_rsize(char* name, char* data, char* mime);
-struct plugin_param_item *plugin_add_item_to_pilist(struct plugin_param_item *pilist, int type, char* name, char* value, char* mime_type);
-
-/* stream handling */
-void plugin_create_stream(struct browser_window *bw,
- struct object_params *params, struct content *c);
-void plugin_write_stream(struct browser_window *bw, struct object_params *params, struct content *c);
-void plugin_write_stream_as_file(struct browser_window *bw,
- struct object_params *params,
- struct content *c);
-void plugin_destroy_stream(struct browser_window *bw,
- struct object_params *params, struct content *c);
-
-/* linked list handling */
-struct plugin_message *plugin_add_message_to_linked_list(plugin_b browser,
- plugin_p plugin,
- wimp_message *m,
- struct plugin_message *reply);
-void plugin_remove_message_from_linked_list(struct plugin_message* m);
-struct plugin_message *plugin_get_message_from_linked_list(int ref);
-void plugin_add_instance_to_list(struct content *c,
- struct browser_window *bw,
- struct content *page, struct box *box,
- struct object_params *params, void **state);
-void plugin_remove_instance_from_list(struct object_params *params);
-struct plugin_list *plugin_get_instance_from_list(plugin_b browser,
- plugin_p plugin);
-
-/* message handling */
-void plugin_open_msg(wimp_message *message);
-void plugin_opening(wimp_message *message);
-void plugin_close_msg(wimp_message *message);
-void plugin_closed(wimp_message *message);
-void plugin_reshape_request(wimp_message *message);
-void plugin_stream_new(wimp_message *message);
-void plugin_stream_written(wimp_message *message);
-void plugin_url_access(wimp_message *message);
-void plugin_status(wimp_message *message);
-char *plugin_get_string_value(os_string_value string, char *msg);
-
-/* others */
-void plugin_create_sysvar(const char *mime_type, char *sysvar);
-int plugin_process_opening(struct object_params *params,
- struct plugin_message *message);
-void plugin_force_redraw(struct content *object, struct content *c,
- unsigned int i);
-
-/*-------------------------------------------------------------------------*/
-/* Linked List pointers */
-/*-------------------------------------------------------------------------*/
-
-static struct plugin_message pm = {0, 0, 0, 0, 0, &pm, &pm};
-static struct plugin_message *pmlist = &pm;
-
-static struct plugin_list pl = {0, 0, 0, 0, 0, 0, &pl, &pl};
-static struct plugin_list *plist = &pl;
-
-static int need_reformat = 0;
-
-/*-------------------------------------------------------------------------*/
-/* Externally visible functions */
-/*-------------------------------------------------------------------------*/
+static const char * const ALIAS_PREFIX = "Alias$@PlugInType_";
+
+typedef enum {
+ PLUGIN_PARAMETER_DATA = 1,
+ PLUGIN_PARAMETER_URL = 2,
+ PLUGIN_PARAMETER_OBJECT = 3,
+ PLUGIN_PARAMETER_SPECIAL = 4
+} plugin_parameter_type;
+
+struct plugin_param_item {
+
+ plugin_parameter_type type;
+ int rsize;
+ int nsize;
+ char *name;
+ int npad;
+ int vsize;
+ char *value;
+ int vpad;
+ int msize;
+ char *mime_type;
+ int mpad;
+
+ struct plugin_param_item *next;
+};
+
+static bool plugin_create_sysvar(const char *mime_type, char* sysvar);
+static void plugin_create_stream(struct content *c);
+static void plugin_write_stream(struct content *c, unsigned int consumed);
+static void plugin_write_stream_as_file(struct content *c);
+static void plugin_destroy_stream(struct content *c);
+static bool plugin_write_parameters_file(struct content *c,
+ struct object_params *params);
+static int plugin_calculate_rsize(const char* name, const char* data,
+ const char* mime);
+static bool plugin_add_item_to_pilist(struct plugin_param_item **pilist,
+ plugin_parameter_type type, const char* name,
+ const char* value, const char* mime_type);
+static char *plugin_get_string_value(os_string_value string, char *msg);
+static bool plugin_active(struct content *c);
/**
* Initialises plugin system in readiness for receiving object data
+ *
+ * \param c The content to hold the data
+ * \param params Parameters associated with the content
+ * \return true on success, false otherwise
*/
bool plugin_create(struct content *c, const char *params[])
{
- union content_msg_data msg_data;
-
- c->data.plugin.data = calloc(0, 1);
- if (!c->data.plugin.data) {
- msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- warn_user("NoMemory", 0);
- return false;
- }
- c->data.plugin.length = 0;
- /* we can't create the plugin here, because this is only called
- * once, even if the object appears several times */
+ LOG(("plugin_create"));
+ c->data.plugin.bw = 0;
+ c->data.plugin.page = 0;
+ c->data.plugin.box = 0;
+ c->data.plugin.taskname = 0;
+ c->data.plugin.filename = 0;
+ c->data.plugin.datafile = 0;
+ c->data.plugin.opened = false;
+ c->data.plugin.repeated = 0;
+ c->data.plugin.browser = 0;
+ c->data.plugin.plugin = 0;
+ c->data.plugin.browser_stream = 0;
+ c->data.plugin.plugin_stream = 0;
+ c->data.plugin.plugin_task = 0;
+ c->data.plugin.consumed = 0;
+ c->data.plugin.reformat_pending = false;
+ c->data.plugin.width = 0;
+ c->data.plugin.height = 0;
+ c->data.plugin.stream_waiting = false;
+ c->data.plugin.file_stream_waiting = false;
return true;
}
/**
- * The content has been added to a page somewhere: launch the plugin.
- * This may be called anytime after plugin_create any number of times.
- * Each must launch a new plugin.
+ * Convert a plugin ready for display (does nothing)
*
- * bw is the window which the plugin is in
- * page, box, params are 0 if the object is standalone
- * state may be use to store a pointer to state data
+ * \param c The content to convert
+ * \param width Width of available space
+ * \param height Height of available space
+ * \return true on success, false otherwise
*/
-void plugin_add_instance(struct content *c, struct browser_window *bw,
- struct content *page, struct box *box,
- struct object_params *params, void **state)
+bool plugin_convert(struct content *c, int width, int height)
{
- char sysvar[40];
- char *varval, *filename, *p;
- os_error *e;
- wimp_message m;
- plugin_message_open *pmo;
- os_box b;
- struct plugin_message *npm = xcalloc(1, sizeof(*npm));
- struct plugin_message *temp;
- struct plugin_list *npl = xcalloc(1, sizeof(*npl));
- int flags = 0;
-
- if (params == 0) {
- /* create object_params struct */
-/* struct object_params *nparams = xcalloc(1, sizeof(*nparams));
- params = nparams;
- params->basehref = xstrdup(c->url);
-*/ fprintf(stderr,
- "Cannot handle standalone objects\n");
- gui_window_set_status(bw->window,
- "Plugin Error: Cannot handle standalone objects");
- xfree(npm);
- xfree(npl);
- return;
- }
-
- /* write parameters file */
- plugin_write_parameters_file(params);
-
- /* Get contents of Alias$@PlugInType_xxx system variable. */
- plugin_create_sysvar(c->mime_type, sysvar);
- varval = getenv(sysvar);
- LOG(("%s: %s", sysvar, varval));
-
- /* Broadcast Message_PlugIn_Open (&4D540) and listen for response
- * Message_PlugIn_Opening (&4D541). If no response, try to launch
- * plugin by Wimp_StartTask(sysvar). Then re-broadcast Message_PlugIn_Open
- * and listen for response. If there is still no response, give up.
- * NB: For the bounding box in Message_PlugIn_Open, we choose arbitrary
- * values outside the area displayed. This is corrected when
- * plugin_reshape_instance is called.
- */
- /* Initialise bounding box */
- b.x0 = -100;
- b.x1 = 0;
- b.y0 = 0;
- b.y1 = 100;
-
- /* populate plugin_message_open struct */
- pmo = (plugin_message_open*)&m.data;
- pmo->flags = 0;
- pmo->reserved = 0;
- pmo->browser = (plugin_b)params->browser;
- pmo->parent_window = bw->window->window;
- pmo->bbox = b;
- xmimemaptranslate_mime_type_to_filetype(c->mime_type, &pmo->file_type);
- pmo->filename.pointer = params->filename;
-
- m.size = 60;
- m.your_ref = 0;
- m.action = message_PLUG_IN_OPEN;
-
- /* add message to list */
- temp = plugin_add_message_to_linked_list((plugin_b)params->browser, (plugin_p)0, &m, (struct plugin_message*)0);
-
- LOG(("Sending Message: &4D540"));
- e = xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m, wimp_BROADCAST);
-
- if (e) {
- LOG(("Error: %s", e->errmess));
- plugin_remove_message_from_linked_list(temp);
- xfree(npm);
- xfree(npl);
- return;
- }
-
- /* wait for wimp poll */
- while(temp->poll == 0)
- gui_poll(true);
-
- if(temp->plugin != 0 && temp->reply != 0) {
-
- /* ok, we got a reply */
- LOG(("Reply to message %p: %p", temp, temp->reply));
- flags = plugin_process_opening(params, temp);
- plugin_remove_message_from_linked_list(temp->reply);
- plugin_remove_message_from_linked_list(temp);
- xfree(npm);
- xfree(npl);
- } else {
-
- /* no reply so issue Wimp_StartTask(varval) */
- LOG(("No reply to message %p", temp));
- plugin_remove_message_from_linked_list(temp);
-
- LOG(("Starting task: %s", varval));
- e = xwimp_start_task((char const*)varval, NULL);
-
- if (e) {
- LOG(("Error: %s", e->errmess));
- xfree(npm);
- xfree(npl);
- return;
- }
-
- /* hmm, deja-vu */
- temp = plugin_add_message_to_linked_list((plugin_b)params->browser, (plugin_p)0, &m, (struct plugin_message*)0);
- LOG(("Re-Sending Message &4D540"));
- e = xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m,
- wimp_BROADCAST);
-
- if (e) {
- LOG(("Error: %s", e->errmess));
- xfree(npm);
- xfree(npl);
- return;
- }
-
- /* wait for wimp poll */
- while(temp->poll == 0)
- gui_poll(true);
-
- if(temp->plugin != 0 && temp->reply != 0) {
-
- /* ok, we got a reply */
- LOG(("Reply to message %p: %p", temp, temp->reply));
- flags = plugin_process_opening(params, temp);
- plugin_remove_message_from_linked_list(temp->reply);
- plugin_remove_message_from_linked_list(temp);
- xfree(npm);
- xfree(npl);
- } else {
-
- /* no reply so give up */
- LOG(("No reply to message %p", temp));
- plugin_remove_message_from_linked_list(temp);
- xfree(npm);
- xfree(npl);
- return;
- }
- }
-
- /* At this point, it's certain that we can handle this object so
- * add it to the list of plugin instances.
- */
- plugin_add_instance_to_list(c, bw, page, box, params, state);
-
- /* TODO - handle other flags (see below) */
- if(flags & 0x4) { /* wants data fetching */
- plugin_create_stream(bw, params, c);
- plugin_destroy_stream(bw, params, c);
-
- /* delete file_as_stream file
- * (we don't care if the file doesn't exist)
- */
- filename = strdup(params->filename);
- p = strrchr((const char*)filename, 'p');
- filename[(p-filename)] = 'd';
- xosfile_delete((char const*)filename, NULL, NULL,
- NULL, NULL, NULL);
- }
-
- if (!(flags & 0x08)) /* will delete parameters file */
- xosfile_delete((char const*)params->filename, NULL, NULL,
- NULL, NULL, NULL);
+ LOG(("plugin_convert"));
+ c->width = width;
+ c->height = height;
+
+ /* deal with a plugin waiting for a normal stream */
+ /** \todo I can see no reason for waiting for all the data
+ * If the plugin app wants to be streamed to, then it should
+ * be able to cope with repeated PLUG_IN_WRITE/PLUG_IN_WRITTEN
+ * message pairs (until all the data has been streamed.
+ * (In fact, the only reason we wait at all is because !Flash
+ * dies otherwise)
+ */
+ if (c->data.plugin.stream_waiting) {
+ c->data.plugin.stream_waiting = false;
+ plugin_write_stream(c, 0);
+ }
-}
+ /* deal with a plugin waiting for a file stream */
+ if (c->data.plugin.file_stream_waiting) {
+ c->data.plugin.file_stream_waiting = false;
+ plugin_write_stream_as_file(c);
+ }
+ c->status = CONTENT_STATUS_DONE;
+ return true;
+}
/**
- * Handle a window containing a CONTENT_PLUGIN being opened.
+ * Destroy a plugin content
+ *
+ * \param c The content to destroy
*/
-
-void plugin_open(struct content *c, struct browser_window *bw,
- struct content *page, struct box *box,
- struct object_params *params)
+void plugin_destroy(struct content *c)
{
+ LOG(("plugin_destroy"));
+ if (c->data.plugin.taskname)
+ free(c->data.plugin.taskname);
+ if (c->data.plugin.filename)
+ free(c->data.plugin.filename);
+ if (c->data.plugin.datafile)
+ free(c->data.plugin.datafile);
}
-
/**
- * Process plugin_opening message flags
- * NB: this is NOT externally visible.
- * it's just here because it's referred to in the TODO above
+ * Redraw a content
+ *
+ * \param c The content to redraw
+ * \param x Left of content box
+ * \param y Top of content box
+ * \param width Width of content box
+ * \param height Height of content box
+ * \param clip[xy][01] Clipping rectangle
+ * \param scale Scale of page (1.0 = 100%)
*/
-int plugin_process_opening(struct object_params *params,
- struct plugin_message *message) {
-
- plugin_message_opening *pmo;
-
- params->plugin = (int)message->reply->plugin;
- params->plugin_task = (unsigned int)message->reply->m->sender;
-
- pmo = (plugin_message_opening*)&message->reply->m->data;
-/* LOG(("pmo->flags = %x", pmo->flags));
- if(pmo->flags & 0x1)
- LOG(("accepts input focus"));
- if(pmo->flags & 0x2)
- LOG(("wants code fetching"));
- if(pmo->flags & 0x10)
- LOG(("still busy"));
- if(pmo->flags & 0x20)
- LOG(("supports extended actions"));
- if(pmo->flags & 0x40)
- LOG(("has helper window"));
-*/
- return (int)pmo->flags;
+bool plugin_redraw(struct content *c, int x, int y,
+ int width, int height,
+ int clip_x0, int clip_y0, int clip_x1, int clip_y1,
+ float scale)
+{
+ /* do nothing */
+ LOG(("plugin_redraw"));
+ return true;
}
+
/**
- * A plugin is no longer required, eg. the page containing it has
- * been closed.
+ * Handle a window containing a CONTENT_PLUGIN being opened
*
- * Any storage associated with state must be freed.
+ * \param c The content to open
+ * \param bw The window to add the content to
+ * \param page The containing content
+ * \param box The containing box
+ * \param params Any parameters associated with the content
+ * \param state State data pointer
*/
-void plugin_remove_instance(struct content *c, struct browser_window *bw,
- struct content *page, struct box *box,
- struct object_params *params, void **state)
+void plugin_open(struct content *c, struct browser_window *bw,
+ struct content *page, struct box *box,
+ struct object_params *params)
{
- wimp_message m;
- plugin_message_close *pmc;
- struct plugin_message *temp;
+ char sysvar[25];
+ char *varval;
+ plugin_full_message_open pmo;
+ os_error *error;
- if (params == 0) {
- return;
- }
+ if (!option_plugins)
+ return;
- pmc = (plugin_message_close*)&m.data;
- pmc->flags = 0;
- pmc->plugin = (plugin_p)params->plugin;
- pmc->browser = (plugin_b)params->browser;
- m.size = 32;
- m.your_ref = 0;
- m.action = message_PLUG_IN_CLOSE;
-
- temp = plugin_add_message_to_linked_list(pmc->browser, pmc->plugin, &m, 0);
- LOG(("Sending message &4D542"));
- xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m,
- (wimp_t)params->plugin_task);
-
- /* wait for wimp poll */
- while (temp == 0)
- gui_poll(true);
-
- if (temp->reply != 0){
-
- plugin_remove_message_from_linked_list(temp->reply);
- plugin_remove_message_from_linked_list(temp);
- }
- else {
- LOG(("message_PLUG_IN_CLOSE bounced"));
- plugin_remove_message_from_linked_list(temp);
- }
-
- /* delete instance from list */
- plugin_remove_instance_from_list(params);
-}
+ /** \todo Standalone plugins */
+ if (!params) {
+ LOG(("cannot handle standalone plugins"));
+ return;
+ }
+ /* we only do this here cos the box is needed by
+ * write_parameters_file. Ideally it would be at the
+ * end of this function with the other writes to c->data.plugin
+ */
+ c->data.plugin.box = box;
+
+ LOG(("writing parameters file"));
+ if (!plugin_write_parameters_file(c, params))
+ return;
+
+ LOG(("creating sysvar"));
+ /* get contents of Alias$@PlugInType_xxx variable */
+ if (!plugin_create_sysvar(c->mime_type, sysvar))
+ return;
+
+ LOG(("getenv"));
+ varval = getenv(sysvar);
+ LOG(("%s: '%s'", sysvar, varval));
+ if(!varval) {
+ return;
+ }
-/**
- * Handle a window containing a CONTENT_PLUGIN being closed.
- */
+ /* The browser instance handle is the content struct pointer */
+ c->data.plugin.browser = (unsigned int)c;
+
+ pmo.size = 60;
+ pmo.your_ref = 0;
+ pmo.action = message_PLUG_IN_OPEN;
+ pmo.flags = 0;
+ pmo.reserved = 0;
+ pmo.browser = (plugin_b)c->data.plugin.browser;
+ pmo.parent_window = bw->window->window;
+ pmo.bbox.x0 = -100;
+ pmo.bbox.x1 = pmo.bbox.y0 = 0;
+ pmo.bbox.y1 = 100;
+ error = xmimemaptranslate_mime_type_to_filetype(c->mime_type,
+ &pmo.file_type);
+ if (error) {
+ return;
+ }
+ pmo.filename.pointer = c->data.plugin.filename;
-void plugin_close(struct content *c)
-{
-}
+ c->data.plugin.repeated = 0;
+ LOG(("sending message"));
+ error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message *)&pmo, wimp_BROADCAST);
+ if (error) {
+ LOG(("xwimp_send_message: 0x%x: %s",
+ error->errnum, error->errmess));
+ return;
+ }
-/**
- * The box containing the plugin has moved or resized,
- * or the window containing the plugin has resized if standalone.
- */
-void plugin_reshape_instance(struct content *c, struct browser_window *bw,
- struct content *page, struct box *box,
- struct object_params *params, void **state)
-{
- /* By now, we've got the plugin up and running in a nested window
- * off the viewable page area. Now we want to display it in its place.
- * Therefore, broadcast a Message_PlugIn_Reshape (&4D544) with the values
- * given to us.
- */
- wimp_message m;
- plugin_message_reshape *pmr;
- os_box bbox;
- int x, y;
-
- if (params == 0) {
- return;
- }
-
- box_coords(box, (int*)&x, (int*)&y);
- bbox.x0 = (x << 1);
- bbox.y1 = -(y << 1);
- bbox.x1 = (bbox.x0 + (box->width << 1));
- bbox.y0 = (bbox.y1 - (box->height << 1));
-
- LOG(("Box w, h: %d %d", box->width, box->height));
- LOG(("BBox: [(%d,%d),(%d,%d)]", bbox.x0, bbox.y0, bbox.x1, bbox.y1));
-
- pmr = (plugin_message_reshape*)&m.data;
- pmr->flags = 0;
- pmr->plugin = (plugin_p) params->plugin;
- pmr->browser = (plugin_b) params->browser;
- pmr->parent_window = (wimp_w) bw->window->window;
- pmr->bbox = bbox;
-
- m.size = 52;
- m.your_ref = 0;
- m.action = message_PLUG_IN_RESHAPE;
-
- LOG(("Sending Message &4D544"));
- xwimp_send_message(wimp_USER_MESSAGE, &m, (wimp_t)params->plugin_task);
+ c->data.plugin.bw = bw;
+ c->data.plugin.page = page;
+ c->data.plugin.taskname = strdup(varval);
+ LOG(("done"));
}
-static const char * const ALIAS_PREFIX = "Alias$@PlugInType_";
-
/**
- * Creates system variable from mime type
- * NB: this is NOT externally visible
- * it just makes sense to keep it with the ALIAS_PREFIX definition above.
+ * Handle a window containing a CONTENT_PLUGIN being closed.
+ *
+ * \param c The content to close
*/
-void plugin_create_sysvar(const char *mime_type, char* sysvar)
+void plugin_close(struct content *c)
{
- unsigned int *fv;
- os_error *e;
-
- e = xmimemaptranslate_mime_type_to_filetype(mime_type, (bits *) &fv);
+ plugin_full_message_close pmc;
+ os_error *error;
+
+ LOG(("plugin_close"));
+
+ if (!plugin_active(c) || !c->data.plugin.opened)
+ return;
+
+ pmc.size = 32;
+ pmc.your_ref = 0;
+ pmc.action = message_PLUG_IN_CLOSE;
+ pmc.flags = 0;
+ pmc.browser = (plugin_b)c->data.plugin.browser;
+ pmc.plugin = (plugin_p)c->data.plugin.plugin;
+
+ LOG(("sending message"));
+ error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message *)&pmc, (wimp_t)c->data.plugin.plugin_task);
+ if (error) {
+ return;
+ }
- sprintf(sysvar, "%s%x", ALIAS_PREFIX, (unsigned int)fv);
+ /* delete the data file used to send the data to the plugin */
+ if (c->data.plugin.datafile != 0)
+ xosfile_delete(c->data.plugin.datafile, 0, 0, 0, 0, 0);
}
/**
- * Tests whether we can handle an object using a browser plugin
- * returns true if we can handle it, false if we can't.
+ * Reformat a plugin content on a page
+ *
+ * \param c The content to reformat
+ * \param width New width
+ * \param height New height
*/
-bool plugin_handleable(const char *mime_type)
+void plugin_reformat(struct content *c, int width, int height)
{
- char sysvar[40];
- unsigned int *fv;
- os_error *e;
-
- e = xmimemaptranslate_mime_type_to_filetype(mime_type, (bits *) &fv);
- if (e) {
- LOG(("xmimemaptranslate_mime_type_to_filetype failed: %s", e->errmess));
- return false;
- }
-
- sprintf(sysvar, "%s%x", ALIAS_PREFIX, (unsigned int)fv);
- LOG(("%s, %s", mime_type, sysvar));
- if (getenv(sysvar) == 0)
- return false;
- return true;
+ plugin_full_message_reshape pmr;
+ int x, y;
+ os_error *error;
+
+ LOG(("plugin_reformat"));
+
+ if (!plugin_active(c))
+ return;
+
+ /* if the plugin hasn't yet been opened, queue the reformat */
+ if (!c->data.plugin.opened) {
+ LOG(("queuing"));
+ c->data.plugin.reformat_pending = true;
+ c->data.plugin.width = width;
+ c->data.plugin.height = height;
+ return;
+ }
+
+ box_coords(c->data.plugin.box, &x, &y);
+ pmr.size = 52;
+ pmr.your_ref = 0;
+ pmr.action = message_PLUG_IN_RESHAPE;
+ pmr.flags = 0;
+
+ pmr.plugin = (plugin_p)c->data.plugin.plugin;
+ pmr.browser = (plugin_b)c->data.plugin.browser;
+ pmr.parent_window = c->data.plugin.bw->window->window;
+ pmr.bbox.x0 = x * 2;
+ pmr.bbox.y1 = -y * 2;
+ pmr.bbox.x1 = pmr.bbox.x0 + c->data.plugin.box->width * 2;
+ pmr.bbox.y0 = pmr.bbox.y1 - c->data.plugin.box->height * 2;
+
+ LOG(("sending message"));
+ error = xwimp_send_message(wimp_USER_MESSAGE, (wimp_message *) &pmr,
+ (wimp_t)c->data.plugin.plugin_task);
+ if (error) {
+ return;
+ }
}
/**
- * processes data retrieved by the fetch process
+ * Creates a system variable from the mimetype
+ *
+ * \param mime_type The mime type
+ * \param sysvar Pointer to buffer into which the string should be written
+ * \return true on success, false otherwise.
*/
-bool plugin_process_data(struct content *c, char *data, unsigned int size)
+bool plugin_create_sysvar(const char *mime_type, char* sysvar)
{
+ unsigned int *fv;
+ os_error *e;
- /* If the plugin requests, we send the data to it via the
- * plugin stream protocol.
- * Also, we should listen for Message_PlugIn_URL_Access (&4D54D)
- * as the plugin may need us to retrieve URLs for it.
- * We should also listen for Message_PlugIn_Closed (&4D543).
- * If this occurs, the plugin has exited with an error.
- * Therefore, we need to stop the fetch and exit.
- */
-
- /* I think we should just buffer the data here, in case the
- * plugin requests it sometime in the future. - James */
-
- char *plugin_data;
- union content_msg_data msg_data;
-
- plugin_data = realloc(c->data.plugin.data, c->data.plugin.length + size);
- if (!plugin_data) {
- msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- warn_user("NoMemory", 0);
- return false;
- }
- c->data.plugin.data = plugin_data;
- memcpy(c->data.plugin.data + c->data.plugin.length, data, size);
- c->data.plugin.length += size;
- c->size += size;
- return true;
-}
+ e = xmimemaptranslate_mime_type_to_filetype(mime_type, (bits *) &fv);
+ if (e) {
+ return false;
+ }
-/**
- * This isn't needed by the plugin system as all the data processing is done
- * externally. Therefore, just tell NetSurf that everything's OK.
- */
-bool plugin_convert(struct content *c, int width, int height)
-{
- c->status=CONTENT_STATUS_DONE;
- return true;
-}
+ sprintf(sysvar, "%s%03x", ALIAS_PREFIX, (unsigned int)fv);
-void plugin_reformat(struct content *c, int width, int height)
-{
+ return true;
}
/**
- * Called when completely finished with an object.
- * Simply frees buffered data
+ * Determines whether a content is handleable by a plugin
+ *
+ * \param mime_type The mime type of the content
+ * \return true if the content is handleable, false otherwise
*/
-void plugin_destroy(struct content *c)
+bool plugin_handleable(const char *mime_type)
{
- /* simply free buffered data */
- free(c->data.plugin.data);
-}
+ char sysvar[25];
-/**
- * Redraw plugin on page.
- */
-bool plugin_redraw(struct content *c, int x, int y,
- int width, int height,
- int clip_x0, int clip_y0, int clip_x1, int clip_y1,
- float scale)
-{
- struct plugin_list *npl;
-
- if(need_reformat) {
- content_reformat(c, c->available_width, 0);
- for(npl = plist->next; npl != plist; npl = npl->next)
- plugin_reshape_instance(npl->c, npl->bw, npl->page,
- npl->box, npl->params,
- npl->state);
- need_reformat = 0;
- }
- return true;
+ if (plugin_create_sysvar(mime_type, sysvar)) {
+ if (getenv(sysvar) != 0) {
+ return true;
+ }
+ }
+
+ return false;
}
-/*-------------------------------------------------------------------------*/
-/* Parameters file handling functions */
-/*-------------------------------------------------------------------------*/
/**
- * Writes the parameters file.
+ * Handle a bounced plugin_open message
+ *
+ * \param message The message to handle
*/
-void plugin_write_parameters_file(struct object_params *params)
+void plugin_open_msg(wimp_message *message)
{
- struct plugin_params* temp;
- struct plugin_param_item* ppi;
- struct plugin_param_item* pilist = 0;
- int *time;
- char *tstr;
- FILE *fp;
-
- /* Create the file */
- xosfile_create_dir("<Wimp$ScrapDir>.WWW", 77);
- xosfile_create_dir("<Wimp$ScrapDir>.WWW.NetSurf", 77);
- /* path + filename + terminating NUL */
- params->filename = xcalloc(strlen(getenv("Wimp$ScrapDir"))+13+10+1,
- sizeof(char));
- xos_read_monotonic_time((int*)&time);
- tstr = xcalloc(40, sizeof(char));
- sprintf(tstr, "%01u", (unsigned int)time<<8);
- sprintf(params->filename, "%s.WWW.NetSurf.p%1.9s",
- getenv("Wimp$ScrapDir"), tstr);
- params->browser = (unsigned int)time<<8;
- xfree(tstr);
- LOG(("filename: %s", params->filename));
-
- /* Write object attributes first */
-
- /* classid is checked first */
- if(params->classid != 0 && params->codetype != 0) {
-
- pilist = plugin_add_item_to_pilist(pilist, 1, "CLASSID",
- params->classid,
- params->codetype);
- }
- /* otherwise, we check the data attribute */
- else if(params->data !=0 && params->type != 0) {
-
- pilist = plugin_add_item_to_pilist(pilist, 1, "DATA",
- params->data,
- params->type);
- }
-
- /* if codebase is specified, write it as well */
- if(params->codebase != 0) {
-
- pilist = plugin_add_item_to_pilist(pilist, 1,
- "CODEBASE",
- params->codebase, NULL);
-
- }
-
- /* Iterate through the parameter list, creating the parameters
- * file as we go. We can free up the memory as we go.
- */
- while(params->params != 0) {
-
- LOG(("name: %s", params->params->name == 0 ? "not set" : params->params->name));
- LOG(("value: %s", params->params->value == 0 ? "not set" : params->params->value));
- LOG(("type: %s", params->params->type == 0 ? "not set" : params->params->type));
- LOG(("valuetype: %s", params->params->valuetype));
-
-
- if(strcasecmp(params->params->valuetype, "data") == 0)
- pilist = plugin_add_item_to_pilist(pilist, 1,
- params->params->name,
- params->params->value,
- params->params->type);
- if(strcasecmp(params->params->valuetype, "ref") == 0)
- pilist = plugin_add_item_to_pilist(pilist, 2,
- params->params->name,
- params->params->value,
- params->params->type);
- if(strcasecmp(params->params->valuetype, "object") == 0)
- pilist = plugin_add_item_to_pilist(pilist, 3,
- params->params->name,
- params->params->value,
- params->params->type);
-
- temp = params->params;
- params->params = params->params->next;
- xfree(temp);
- }
-
- /* Now write mandatory special parameters */
-
- /* BASEHREF */
- pilist = plugin_add_item_to_pilist(pilist, 4, "BASEHREF",
- params->basehref, NULL);
-
- /* USERAGENT */
- pilist = plugin_add_item_to_pilist(pilist, 4, "USERAGENT",
- "NetSurf", NULL);
-
- /* UAVERSION */
- pilist = plugin_add_item_to_pilist(pilist, 4, "UAVERSION",
- "0.01", NULL);
-
- /* APIVERSION */
- pilist = plugin_add_item_to_pilist(pilist, 4, "APIVERSION",
- "1.10", NULL);
-
- /* BGCOLOR - needs fixing to work properly.
- * Currently, it assumes FFFFFF00 (BBGGRR00) */
- pilist = plugin_add_item_to_pilist(pilist, 4, "BGCOLOR",
- "FFFFFF00", NULL);
-
- /* Write file */
- fp = fopen(params->filename, "wb+");
-
- while (pilist != 0) {
-
- fwrite(&pilist->type, (unsigned int)sizeof(int), 1, fp);
- fwrite(&pilist->rsize, (unsigned int)sizeof(int), 1, fp);
-
- fwrite(&pilist->nsize, (unsigned int)sizeof(int), 1, fp);
- fwrite(pilist->name, (unsigned int)strlen(pilist->name), 1, fp);
- for(; pilist->npad != 0; pilist->npad--)
- fputc('\0', fp);
-
- fwrite(&pilist->vsize, (unsigned int)sizeof(int), 1, fp);
- fwrite(pilist->value, (unsigned int)strlen(pilist->value), 1, fp);
- for(; pilist->vpad != 0; pilist->vpad--)
- fputc('\0', fp);
-
- fwrite(&pilist->msize, (unsigned int)sizeof(int), 1, fp);
- if(pilist->msize > 0) {
- fwrite(pilist->mime_type,
- (unsigned int)strlen(pilist->mime_type), 1, fp);
- for(; pilist->mpad != 0; pilist->mpad--)
- fputc('\0', fp);
- }
-
- ppi = pilist;
- pilist = pilist->next;
-
- xfree(ppi);
- }
-
- fwrite("\0", sizeof(char), 4, fp);
-
- fclose(fp);
-}
+ struct content *c;
+ os_error *error;
+ plugin_message_open *pmo = (plugin_message_open *)&message->data;
-/**
- * Calculates the size of a parameter file record
- */
-int plugin_calculate_rsize(char* name, char* data, char* mime) {
+ /* retrieve our content */
+ c = (struct content *)pmo->browser;
- int ret = 0;
- ret += (4 + strlen(name) + 3) / 4 * 4; /* name */
- ret += (4 + strlen(data) + 3) / 4 * 4; /* data */
+ /* check we expect this message */
+ if (!c || !plugin_active(c))
+ return;
- if (mime != NULL)
- ret += (4 + strlen(mime) + 3) / 4 * 4; /* mime type */
- else
- ret += 4;
+ LOG(("bounced"));
- return ret;
-}
-
-/**
- * Adds an item to the list of parameter file records
- */
-struct plugin_param_item *plugin_add_item_to_pilist(struct plugin_param_item *pilist, int type, char* name, char* value, char* mime_type) {
-
- struct plugin_param_item *ppi = xcalloc(1, sizeof(*ppi));
-
- /* initialise struct */
- ppi->type = 0;
- ppi->rsize = 0;
- ppi->nsize = 0;
- ppi->name = 0;
- ppi->npad = 0;
- ppi->vsize = 0;
- ppi->value = 0;
- ppi->vpad = 0;
- ppi->msize = 0;
- ppi->mime_type = 0;
- ppi->mpad = 0;
-
- ppi->type = type;
- ppi->rsize = plugin_calculate_rsize(name, value, mime_type);
- ppi->nsize = strlen(name);
- ppi->name = xstrdup(name);
- ppi->npad = 4 - (ppi->nsize%4 == 0 ? 4 : ppi->nsize%4);
- ppi->vsize = strlen(value);
- ppi->value = xstrdup(value);
- ppi->vpad = 4 - (ppi->vsize%4 == 0 ? 4 : ppi->vsize%4);
- if(mime_type != 0) {
- ppi->msize = strlen(mime_type);
- ppi->mime_type = xstrdup(mime_type);
- ppi->mpad = 4 - (ppi->msize%4 == 0 ? 4 : ppi->msize%4);
- }
-
- ppi->next = pilist;
- return ppi;
-}
+ /* bail if we've already tried twice */
+ if (c->data.plugin.repeated >= 1)
+ return;
-/*-------------------------------------------------------------------------*/
-/* Plugin Stream handling functions */
-/*-------------------------------------------------------------------------*/
+ /* start plugin app */
+ error = xwimp_start_task((char const*)c->data.plugin.taskname, 0);
+ if (error) {
+ return;
+ }
-/**
- * Creates a plugin stream
- */
-void plugin_create_stream(struct browser_window *bw, struct object_params *params, struct content *c) {
-
- wimp_message m;
- plugin_message_stream_new *pmsn;
- struct plugin_message *temp;
-
- pmsn = (plugin_message_stream_new*)&m.data;
- pmsn->flags = 0;
- pmsn->plugin = (plugin_p)params->plugin;
- pmsn->browser = (plugin_b)params->browser;
- pmsn->stream = (plugin_s)0;
- pmsn->browser_stream = (plugin_bs)params->browser;
- pmsn->url.pointer = c->url;
- pmsn->end = c->data.plugin.length;
- pmsn->last_modified_date = 0;
- pmsn->notify_data = 0;
- pmsn->mime_type.pointer = c->mime_type;
- pmsn->target_window.offset = 0;
-
- m.size = 64;
- m.your_ref = 0;
- m.action = message_PLUG_IN_STREAM_NEW;
-
- temp = plugin_add_message_to_linked_list(pmsn->browser, pmsn->plugin, &m, 0);
-
- LOG(("Sending message &4D548"));
- xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m, (wimp_t)params->plugin_task);
-
- /* wait for wimp poll */
- while(temp->poll == 0)
- gui_poll(true);
-
- pmsn = (plugin_message_stream_new*)&temp->reply->m->data;
- params->browser_stream = params->browser;
- params->plugin_stream = (int)pmsn->stream;
-
- if((pmsn->flags == 0) || (pmsn->flags == 1) || (pmsn->flags == 2)) {
- plugin_write_stream(bw, params, c);
- }
- else if((pmsn->flags == 3)) {
- plugin_write_stream_as_file(bw, params, c);
- }
-
- /* clean up */
- plugin_remove_message_from_linked_list(temp->reply);
- plugin_remove_message_from_linked_list(temp);
-}
+ /* indicate we've already sent this message once */
+ c->data.plugin.repeated++;
-/**
- * Writes to an open stream
- */
-void plugin_write_stream(struct browser_window *bw, struct object_params *params, struct content *c) {
-
- wimp_message m;
- plugin_message_stream_write *pmsw;
- plugin_message_stream_written *pmswt;
- struct plugin_message *temp;
- unsigned int consumed = 0;
-
- pmsw = (plugin_message_stream_write*)&m.data;
-
- pmsw->flags = 0;
- pmsw->plugin = (plugin_p)params->plugin;
- pmsw->browser = (plugin_b)params->browser;
- pmsw->stream = (plugin_s)params->plugin_stream;
- pmsw->browser_stream = (plugin_bs)params->browser_stream;
- pmsw->url.pointer = c->url;
- pmsw->end = c->data.plugin.length;
- pmsw->last_modified_date = 0;
- pmsw->notify_data = 0;
- pmsw->offset = 0;
- pmsw->length = c->data.plugin.length;
- pmsw->data = (byte*)c->data.plugin.data;
-
- m.size = 68;
- m.your_ref = 0;
- m.action = message_PLUG_IN_STREAM_WRITE;
-
- while (consumed < c->data.plugin.length) {
-
- pmsw->length = c->data.plugin.length;
-
- temp = plugin_add_message_to_linked_list(pmsw->browser, pmsw->plugin, &m, 0);
-
- LOG(("Sending message &4D54A"));
- xwimp_send_message(wimp_USER_MESSAGE_RECORDED, &m, (wimp_t)params->plugin_task);
-
- /* wait for wimp poll */
- while(temp->poll == 0)
- gui_poll(true);
-
- pmswt = (plugin_message_stream_written*)&temp->reply->m->data;
- if(pmswt->length > 0) {
- consumed += pmswt->length;
- pmsw->offset += pmswt->length + 1;
- plugin_remove_message_from_linked_list(temp->reply);
- plugin_remove_message_from_linked_list(temp);
- }
- else {
- plugin_remove_message_from_linked_list(temp->reply);
- plugin_remove_message_from_linked_list(temp);
- return;
- }
- }
+ /* and resend the message */
+ LOG(("resending"));
+ message->your_ref = 0;
+ error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED, message,
+ wimp_BROADCAST);
+ if (error) {
+ return;
+ }
}
/**
- * Writes a stream as a file
+ * Handle a plugin_opening message
+ *
+ * \param message The message to handle
*/
-void plugin_write_stream_as_file(struct browser_window *bw, struct object_params *params, struct content *c) {
-
- wimp_message m;
- plugin_message_stream_as_file *pmsaf;
- unsigned int filetype;
- char *filename = strdup(params->filename), *p;
-
- pmsaf = (plugin_message_stream_as_file*)&m.data;
-
- pmsaf->flags = 0;
- pmsaf->plugin = (plugin_p)params->plugin;
- pmsaf->browser = (plugin_b)params->browser;
- pmsaf->stream = (plugin_s)params->plugin_stream;
- pmsaf->browser_stream = (plugin_bs)params->browser_stream;
- pmsaf->url.pointer = c->url;
- pmsaf->end = 0;
- pmsaf->last_modified_date = 0;
- pmsaf->notify_data = 0;
-
- p = strrchr((const char*)filename, 'p');
- filename[(p-filename)] = 'd';
- pmsaf->filename.pointer = filename;
-
- m.size = 60;
- m.your_ref = 0;
- m.action = message_PLUG_IN_STREAM_AS_FILE;
-
- xmimemaptranslate_mime_type_to_filetype(c->mime_type, (bits *) &filetype);
- xosfile_save_stamped((char const*)filename, filetype, c->data.plugin.data, c->data.plugin.data + c->data.plugin.length);
-
- LOG(("Sending message &4D54C"));
- xwimp_send_message(wimp_USER_MESSAGE, &m, (wimp_t)params->plugin_task);
-}
+void plugin_opening(wimp_message *message)
+{
+ struct content *c;
+ plugin_message_opening *pmo =
+ (plugin_message_opening *)&message->data;
-/**
- * Destroys a plugin stream
- */
-void plugin_destroy_stream(struct browser_window *bw, struct object_params *params, struct content *c) {
-
- wimp_message m;
- plugin_message_stream_destroy *pmsd;
-
- pmsd = (plugin_message_stream_destroy*)&m.data;
-
- pmsd->flags = 0;
- pmsd->plugin = (plugin_p)params->plugin;
- pmsd->browser = (plugin_b)params->browser;
- pmsd->stream = (plugin_s)params->plugin_stream;
- pmsd->browser_stream = (plugin_bs)params->browser_stream;
- pmsd->url.pointer = c->url;
- pmsd->end = 0;
- pmsd->last_modified_date = 0;
- pmsd->notify_data = 0;
- pmsd->reason = plugin_STREAM_DESTROY_FINISHED;
-
- m.size = 60;
- m.your_ref = 0;
- m.action = message_PLUG_IN_STREAM_DESTROY;
-
- LOG(("Sending message &4D549"));
- xwimp_send_message(wimp_USER_MESSAGE, &m, (wimp_t)params->plugin_task);
-}
+ /* retrieve our content */
+ c = (struct content *)pmo->browser;
-/*-------------------------------------------------------------------------*/
-/* Linked List handling functions */
-/*-------------------------------------------------------------------------*/
+ /* check we expect this message */
+ if (!c || !plugin_active(c))
+ return;
-/**
- * Adds a message to the list of pending messages
- */
-struct plugin_message *plugin_add_message_to_linked_list(plugin_b browser, plugin_p plugin, wimp_message *m, struct plugin_message *reply) {
+ c->data.plugin.repeated = 2; /* make sure open_msg does nothing */
+ c->data.plugin.plugin = (unsigned int)pmo->plugin;
+ c->data.plugin.plugin_task = (unsigned int)message->sender;
+ c->data.plugin.opened = true;
- struct plugin_message *npm = xcalloc(1, sizeof(*npm));
+ LOG(("opening"));
- npm->poll = 0;
- npm->browser = browser;
- npm->plugin = plugin;
- npm->m = m;
- npm->reply = reply;
- npm->prev = pmlist->prev;
- npm->next = pmlist;
- pmlist->prev->next = npm;
- pmlist->prev = npm;
+ /* if there's a reformat pending, do so now */
+ if (c->data.plugin.reformat_pending) {
+ LOG(("do pending reformat"));
+ plugin_reformat(c, c->data.plugin.width,
+ c->data.plugin.height);
+ }
- LOG(("Added Message: %p", npm));
+ if (pmo->flags & 0x04) { /* plugin wants the data fetching */
+ LOG(("wants stream"));
+ plugin_create_stream(c);
+ }
- return pmlist->prev;
+ if (!(pmo->flags & 0x08)) {
+ LOG(("we delete file"));
+ /* we don't care if this fails */
+ xosfile_delete(c->data.plugin.filename, 0, 0, 0, 0, 0);
+ }
}
/**
- * Removes a message from the list of pending messages
+ * Handle a bounced plugin_close message
+ *
+ * \param message The message to handle
*/
-void plugin_remove_message_from_linked_list(struct plugin_message* m) {
-
- m->prev->next = m->next;
- m->next->prev = m->prev;
- LOG(("Deleted Message: %p", m));
- xfree(m);
+void plugin_close_msg(wimp_message *message)
+{
+ plugin_message_close *pmc = (plugin_message_close *)&message->data;
+ /* not necessarily true - some plugins don't stop this bouncing */
+ LOG(("failed to close plugin: %p", pmc->plugin));
}
/**
- * Retrieves a message from the list of pending messages
- * returns NULL if no message is found
+ * Handle a plugin_closed message
+ *
+ * \param message The message to handle
*/
-struct plugin_message *plugin_get_message_from_linked_list(int ref) {
-
- struct plugin_message *npm;
+void plugin_closed(wimp_message *message)
+{
+ struct content *c;
+ plugin_message_closed *pmc = (plugin_message_closed *)&message->data;
- if(ref == 0)
- return NULL;
+ /* retrieve our content */
+ c = (struct content*)pmc->browser;
- for(npm = pmlist->next; npm != pmlist && npm->m->my_ref != ref;
- npm = npm->next)
- ;
+ /* check we expect this message */
+ if (!c || !plugin_active(c))
+ return;
- if(npm != pmlist) {
- LOG(("Got message: %p", npm));
- return npm;
- }
+ LOG(("died"));
+ c->data.plugin.opened = false;
- return NULL;
+ if (pmc->flags & 0x4) {
+ LOG(("plugin_closed: 0x%x: %s", pmc->error_number,
+ pmc->error_text));
+ /* not really important enough to do a warn_user */
+ gui_window_set_status(c->data.plugin.bw->window,
+ pmc->error_text);
+ }
}
/**
- * Adds a plugin instance to the list of plugin instances.
+ * Handles receipt of plugin_reshape_request messages
+ *
+ * \param message The message to handle
*/
-void plugin_add_instance_to_list(struct content *c, struct browser_window *bw, struct content *page, struct box *box, struct object_params *params, void **state) {
-
- struct plugin_list *npl = xcalloc(1, sizeof(*npl));
-
- npl->c = c;
- npl->bw = bw;
- npl->page = page;
- npl->box = box;
- npl->params = params;
- npl->state = state;
- npl->prev = plist->prev;
- npl->next = plist;
- plist->prev->next = npl;
- plist->prev = npl;
+void plugin_reshape_request(wimp_message *message)
+{
+ struct content *c;
+ union content_msg_data data;
+ plugin_message_reshape_request *pmrr = (plugin_message_reshape_request*)&message->data;
+
+ /* retrieve our content */
+ c = (struct content *)pmrr->browser;
+
+ /* check we expect this message */
+ if (!c || !plugin_active(c))
+ return;
+
+ LOG(("handling reshape request"));
+
+ /* should probably shift by x and y eig values here */
+ c->width = pmrr->size.x / 2;
+ c->height = pmrr->size.y / 2;
+ c->data.plugin.box->style->width.width = CSS_WIDTH_AUTO;
+ c->data.plugin.box->style->height.height = CSS_HEIGHT_AUTO;
+
+ /* force a reformat of the parent */
+ content_reformat(c->data.plugin.page,
+ c->data.plugin.page->available_width, 0);
+ /* redraw the window */
+ content_broadcast(c->data.plugin.bw->current_content,
+ CONTENT_MSG_REFORMAT, data);
+ /* reshape the plugin */
+ plugin_reformat(c, c->width, c->height);
}
/**
- * Removes a plugin instance from the list of plugin instances
+ * Handles receipt of plugin_status messages
+ *
+ * \param message The message to handle
*/
-void plugin_remove_instance_from_list(struct object_params *params) {
+void plugin_status(wimp_message *message)
+{
+ struct content *c;
+ plugin_message_status *pms = (plugin_message_status*)&message->data;
+
+ /* retrieve our content */
+ c = (struct content *)pms->browser;
- struct plugin_list *temp =
- plugin_get_instance_from_list((plugin_b)params->browser,
- (plugin_p)params->plugin);
- if(temp != NULL) {
+ /* check we expect this message */
+ if (!c || !plugin_active(c))
+ return;
+
+ gui_window_set_status(c->data.plugin.bw->window,
+ (const char*)plugin_get_string_value(pms->message,
+ (char*)pms));
+}
- temp->prev->next = temp->next;
- temp->next->prev = temp->prev;
- xfree(temp);
- }
+/**
+ * Handles receipt of plugin_stream_new messages
+ *
+ * \param message The message to handle
+ */
+void plugin_stream_new(wimp_message *message)
+{
+ struct content *c;
+ int stream_type;
+ plugin_message_stream_new *pmsn =
+ (plugin_message_stream_new*)&message->data;
+
+ LOG(("plugin_stream_new"));
+
+ /* retrieve our content */
+ c = (struct content *)pmsn->browser;
+
+ /* check we expect this message */
+ if (!c || !plugin_active(c))
+ return;
+
+ /* response to a message we sent */
+ if (message->my_ref != 0) {
+ c->data.plugin.browser_stream = (unsigned int)pmsn->browser;
+ c->data.plugin.plugin_stream = (unsigned int)pmsn->stream;
+
+ LOG(("flags: %x", pmsn->flags));
+
+ stream_type = pmsn->flags & 0xF; /* bottom four bits */
+
+ if (stream_type == 3) {
+ LOG(("as file"));
+ if (c->source_size == c->total_size)
+ plugin_write_stream_as_file(c);
+ else {
+ LOG(("waiting for data"));
+ c->data.plugin.file_stream_waiting = true;
+ }
+ }
+ else if (stream_type < 3) {
+ LOG(("write stream"));
+ /* this sucks - see plugin_convert for why */
+ if (c->source_size == c->total_size)
+ plugin_write_stream(c, 0);
+ else {
+ LOG(("waiting for data"));
+ c->data.plugin.stream_waiting = true;
+ }
+ }
+ }
+ /* new stream, initiated by plugin */
+ else {
+ /** \todo plugin-initiated streams */
+ }
}
/**
- * Retrieves an instance of a plugin from the list of plugin instances
- * returns NULL if no instance is found
+ * Handles receipt of plugin_stream_written messages
+ *
+ * \param message The message to handle
*/
-struct plugin_list *plugin_get_instance_from_list(plugin_b browser, plugin_p plugin) {
+void plugin_stream_written(wimp_message *message)
+{
+ struct content *c;
+ plugin_message_stream_written *pmsw =
+ (plugin_message_stream_written*)&message->data;
- struct plugin_list *npl;
+ /* retrieve our box */
+ c = (struct content *)pmsw->browser;
- for(npl = plist->next; (npl != plist)
- && (((plugin_b)npl->params->browser != browser)
- && ((plugin_p)npl->params->plugin != plugin));
- npl = npl->next)
- ;
+ /* check we expect this message */
+ if (!c || !plugin_active(c))
+ return;
- if(npl != plist)
- return npl;
+ LOG(("got written"));
- return NULL;
+ plugin_write_stream(c, pmsw->length);
}
-/*-------------------------------------------------------------------------*/
-/* WIMP Message processing functions */
-/*-------------------------------------------------------------------------*/
-
/**
- * Parses wimp messages
+ * Handles plugin_url_access messages
+ *
+ * \param message The message to handle
*/
-void plugin_msg_parse(wimp_message *message, int ack)
+void plugin_url_access(wimp_message *message)
{
- LOG(("Parsing message"));
- switch(message->action) {
-
- case message_PLUG_IN_OPENING:
- plugin_opening(message);
- break;
- case message_PLUG_IN_CLOSED:
- plugin_closed(message);
- break;
- case message_PLUG_IN_RESHAPE_REQUEST:
- plugin_reshape_request(message);
- break;
- case message_PLUG_IN_FOCUS:
- // plugin_focus();
- break;
- case message_PLUG_IN_URL_ACCESS:
- plugin_url_access(message);
- break;
- case message_PLUG_IN_STATUS:
- plugin_status(message);
- break;
- case message_PLUG_IN_BUSY:
- // plugin_busy();
- break;
- /* OSLib doesn't provide this, as it's
- * reasonably new and not obviously documented.
- * We ignore it for now.
-
- case message_PLUG_IN_INFORMED:
- */
- case message_PLUG_IN_STREAM_NEW:
- plugin_stream_new(message);
- break;
- case message_PLUG_IN_STREAM_WRITE:
- // plugin_stream_write();
- break;
- case message_PLUG_IN_STREAM_WRITTEN:
- plugin_stream_written(message);
- break;
- case message_PLUG_IN_STREAM_DESTROY:
- // plugin_stream_destroy();
- break;
-
- /* These cases occur when a message is bounced
- * For simplicity, we do nothing unless the message came in
- * a wimp_USER_MESSAGE_ACKNOWLEDGE (ie ack = 1)
- */
- case message_PLUG_IN_OPEN:
- if(ack)
- plugin_open_msg(message);
- break;
- case message_PLUG_IN_CLOSE:
- if(ack)
- plugin_close_msg(message);
- break;
- case message_PLUG_IN_RESHAPE:
- case message_PLUG_IN_STREAM_AS_FILE:
- case message_PLUG_IN_NOTIFY:
- case message_PLUG_IN_ABORT:
- case message_PLUG_IN_ACTION:
- default:
- break;
- }
+ struct content *c;
+ plugin_full_message_notify pmn;
+ os_error *error;
+ plugin_message_url_access *pmua =
+ (plugin_message_url_access*)&message->data;
+ bool notify = false, post = false, file = false;
+ char *url = plugin_get_string_value(pmua->url, (char*)pmua);
+ char *window;
+
+ if (pmua->flags & 0x01) notify = true;
+ if (pmua->flags & 0x02) post = true;
+ if (pmua->flags & 0x04) file = true;
+
+ /* retrieve our content */
+ c = (struct content *)pmua->browser;
+
+ /* check we expect this message */
+ if (!c || !plugin_active(c))
+ return;
+
+ /* fetch url to window */
+ if (pmua->target_window.offset != 0 &&
+ pmua->target_window.pointer != 0) {
+ window = plugin_get_string_value(pmua->target_window,
+ (char*)pmua);
+ LOG(("flags: %d, url: %s, window: %s", pmua->flags, url, window));
+ /** \todo proper _parent and _self support (needs frames)
+ * other window names
+ */
+ if (!post) { /* GET request */
+ if (strcasecmp(window, "_self") == 0 ||
+ strcasecmp(window, "_parent") == 0 ||
+ strcasecmp(window, "_top") == 0 ||
+ strcasecmp(window, "") == 0) {
+ browser_window_go(c->data.plugin.bw, url);
+ }
+ else if (strcasecmp(window, "_blank") == 0) {
+ browser_window_create(url, NULL);
+ }
+ }
+ else { /* POST request */
+ /* fetch URL */
+ }
+ }
+ /* fetch data and stream to plugin */
+ else {
+ if (!post) { /* GET request */
+ /* fetch URL */
+ }
+ else { /* POST request */
+ /* fetch URL */
+ }
+
+ /* stream data to plugin */
+ }
+
+ if (notify) {
+ /* send message_plugin_notify to plugin task */
+ pmn.size = 44;
+ pmn.your_ref = message->my_ref;
+ pmn.action = message_PLUG_IN_NOTIFY;
+ pmn.flags = 0;
+ pmn.plugin = pmua->plugin;
+ pmn.browser = pmua->browser;
+ pmn.url.pointer = url;
+ pmn.reason = (plugin_notify_reason)0;
+ pmn.notify_data = pmua->notify_data;
+
+ error = xwimp_send_message(wimp_USER_MESSAGE,
+ (wimp_message*)&pmn, message->sender);
+ if (error) {
+ return;
+ }
+ }
}
/**
- * Handles receipt of plugin_open messages
+ * Creates a plugin stream
+ *
+ * \param c The content to fetch the data for
*/
-void plugin_open_msg(wimp_message *message) {
-
- struct plugin_message *npm = plugin_get_message_from_linked_list(message->my_ref);
-
- LOG(("Acknowledgement of %p", npm));
- /* notify plugin_open message entry in list */
- if (npm != NULL)
- npm->poll = 1;
+void plugin_create_stream(struct content *c)
+{
+ plugin_full_message_stream_new pmsn;
+ os_error *error;
+
+ pmsn.size = 64;
+ pmsn.your_ref = 0;
+ pmsn.action = message_PLUG_IN_STREAM_NEW;
+ pmsn.flags = 0;
+ pmsn.plugin = (plugin_p)c->data.plugin.plugin;
+ pmsn.browser = (plugin_b)c->data.plugin.browser;
+ pmsn.stream = (plugin_s)0;
+ pmsn.browser_stream = (plugin_bs)c->data.plugin.browser;
+ pmsn.url.pointer = c->url;
+ pmsn.end = c->total_size;
+ pmsn.last_modified_date = 0;
+ pmsn.notify_data = 0;
+ pmsn.mime_type.pointer = c->mime_type;
+ pmsn.target_window.offset = 0;
+
+ LOG(("Sending message &4D548"));
+ error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message*)&pmsn, (wimp_t)c->data.plugin.plugin_task);
+ if (error) {
+ return;
+ }
}
/**
- * Handles receipt of plugin_open messages
+ * Writes to an open stream
+ *
+ * \param c The content to write data to
+ * \param consumed The amount of data consumed
*/
-void plugin_opening(wimp_message *message) {
-
- struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
- struct plugin_message *reply;
- plugin_message_opening *pmo = (plugin_message_opening*)&message->data;
-
- /* add this message to linked list */
- reply = plugin_add_message_to_linked_list(pmo->browser, pmo->plugin, message, 0);
-
- /* notify plugin_open message entry in list */
- if (npm != NULL) {
-
- npm->poll = 1;
- npm->plugin = pmo->plugin;
- npm->reply = reply;
- }
+void plugin_write_stream(struct content *c, unsigned int consumed)
+{
+ plugin_full_message_stream_write pmsw;
+ os_error *error;
+
+ c->data.plugin.consumed += consumed;
+
+ pmsw.size = 68;
+ pmsw.your_ref = 0;
+ pmsw.action = message_PLUG_IN_STREAM_WRITE;
+ pmsw.flags = 0;
+ pmsw.plugin = (plugin_p)c->data.plugin.plugin;
+ pmsw.browser = (plugin_b)c->data.plugin.browser;
+ pmsw.stream = (plugin_s)c->data.plugin.plugin_stream;
+ pmsw.browser_stream = (plugin_bs)c->data.plugin.browser_stream;
+ pmsw.url.pointer = c->url;
+ /* end of stream is total_size
+ * (which is conveniently 0 if unknown)
+ */
+ pmsw.end = c->total_size;
+ pmsw.last_modified_date = 0;
+ pmsw.notify_data = 0;
+ /* offset into data is amount of data consumed by plugin already */
+ pmsw.offset = c->data.plugin.consumed;
+ /* length of data available */
+ pmsw.length = c->source_size - c->data.plugin.consumed;
+ /* pointer to available data */
+ pmsw.data = (byte*)c->source_data + c->data.plugin.consumed;
+
+ /* still have data to send */
+ if (c->data.plugin.consumed < c->source_size) {
+ LOG(("Sending message &4D54A"));
+ error = xwimp_send_message(wimp_USER_MESSAGE_RECORDED,
+ (wimp_message *)&pmsw,
+ (wimp_t)c->data.plugin.plugin_task);
+ if (error) {
+ return;
+ }
+ }
+ /* no further data => destroy stream */
+ else {
+ plugin_destroy_stream(c);
+ }
}
/**
- * Handles receipt of plugin_close messages
+ * Writes a stream as a file
+ *
+ * \param c The content to write data to
*/
-void plugin_close_msg(wimp_message *message) {
+void plugin_write_stream_as_file(struct content *c)
+{
+ plugin_full_message_stream_as_file pmsaf;
+ unsigned int filetype;
+ os_error *error;
+
+ c->data.plugin.datafile =
+ calloc(strlen(getenv("Wimp$ScrapDir"))+13+10, sizeof(char));
+
+ if (!c->data.plugin.datafile) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ plugin_destroy_stream(c);
+ return;
+ }
- struct plugin_message *npm = plugin_get_message_from_linked_list(message->my_ref);
+ /* create filename */
+ sprintf(c->data.plugin.datafile, "%s.WWW.NetSurf.d%x",
+ getenv("Wimp$ScrapDir"),
+ (unsigned int)c->data.plugin.box->object_params);
+
+ pmsaf.size = 60;
+ pmsaf.your_ref = 0;
+ pmsaf.action = message_PLUG_IN_STREAM_AS_FILE;
+ pmsaf.flags = 0;
+ pmsaf.plugin = (plugin_p)c->data.plugin.plugin;
+ pmsaf.browser = (plugin_b)c->data.plugin.browser;
+ pmsaf.stream = (plugin_s)c->data.plugin.plugin_stream;
+ pmsaf.browser_stream = (plugin_bs)c->data.plugin.browser_stream;
+ pmsaf.url.pointer = c->url;
+ pmsaf.end = 0;
+ pmsaf.last_modified_date = 0;
+ pmsaf.notify_data = 0;
+ pmsaf.filename.pointer = c->data.plugin.datafile;
+
+ error = xmimemaptranslate_mime_type_to_filetype(c->mime_type,
+ (bits *) &filetype);
+ if (error) {
+ return;
+ }
+
+ error = xosfile_save_stamped((char const*)c->data.plugin.datafile,
+ filetype, c->source_data,
+ c->source_data + c->source_size);
+ if (error) {
+ return;
+ }
- /* notify plugin_open message entry in list */
- if (npm != NULL)
- npm->poll = 1;
+ LOG(("Sending message &4D54C"));
+ error = xwimp_send_message(wimp_USER_MESSAGE,
+ (wimp_message *)&pmsaf, (wimp_t)c->data.plugin.plugin_task);
+ if (error) {
+ return;
+ }
}
/**
- * Handles receipt of plugin_closed messages
+ * Destroys a plugin stream
+ *
+ * \param c The content to destroy
*/
-void plugin_closed(wimp_message *message) {
-
- struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
- struct plugin_message *reply;
- plugin_message_closed *pmc = (plugin_message_closed*)&message->data;
- struct plugin_list *npl = plugin_get_instance_from_list(pmc->browser, pmc->plugin);
-
- /* add this message to linked list */
- reply = plugin_add_message_to_linked_list(pmc->browser, pmc->plugin, message, 0);
-
- /* notify plugin_open message entry in list */
- if (npm != NULL) {
-
- npm->poll = 1;
- npm->reply = reply;
- }
- /* This is not the result of a plugin_open message */
- else {
- if(pmc->flags & 0x2) {
- LOG(("Err Mess: %s", pmc->error_text));
- gui_window_set_status(npl->bw->window,
- (const char*)pmc->error_text);
- }
- plugin_remove_message_from_linked_list(reply);
- }
+void plugin_destroy_stream(struct content *c)
+{
+ plugin_full_message_stream_destroy pmsd;
+ os_error *error;
+
+ pmsd.size = 60;
+ pmsd.your_ref = 0;
+ pmsd.action = message_PLUG_IN_STREAM_DESTROY;
+ pmsd.flags = 0;
+ pmsd.plugin = (plugin_p)c->data.plugin.plugin;
+ pmsd.browser = (plugin_b)c->data.plugin.browser;
+ pmsd.stream = (plugin_s)c->data.plugin.plugin_stream;
+ pmsd.browser_stream = (plugin_bs)c->data.plugin.browser_stream;
+ pmsd.url.pointer = c->url;
+ pmsd.end = 0;
+ pmsd.last_modified_date = 0;
+ pmsd.notify_data = 0;
+ pmsd.reason = plugin_STREAM_DESTROY_FINISHED;
+
+ LOG(("Sending message &4D549"));
+ error = xwimp_send_message(wimp_USER_MESSAGE,
+ (wimp_message *)&pmsd, (wimp_t)c->data.plugin.plugin_task);
+ if (error) {
+ return;
+ }
}
/**
- * Handles receipt of plugin_reshape_request messages
+ * Writes the plugin parameters file
+ *
+ * \param c Content to write parameters for
+ * \param params Plugin parameters struct
+ * \return true on success, false otherwise
*/
-void plugin_reshape_request(wimp_message *message) {
-
- struct plugin_list *npl;
- plugin_message_reshape_request *pmrr = (plugin_message_reshape_request*)&message->data;
- unsigned int i;
+bool plugin_write_parameters_file(struct content *c,
+ struct object_params *params)
+{
+ struct plugin_params *temp;
+ struct plugin_param_item *ppi;
+ struct plugin_param_item *pilist = 0;
+ char bgcolor[10] = {0};
+ FILE *fp;
+
+ /* Create the file */
+ xosfile_create_dir("<Wimp$ScrapDir>.WWW", 77);
+ xosfile_create_dir("<Wimp$ScrapDir>.WWW.NetSurf", 77);
+ /* path + filename + terminating NUL */
+ c->data.plugin.filename =
+ calloc(strlen(getenv("Wimp$ScrapDir"))+13+10, sizeof(char));
+
+ if (!c->data.plugin.filename) {
+ LOG(("malloc failed"));
+ warn_user("NoMemory", 0);
+ return false;
+ }
+ sprintf(c->data.plugin.filename, "%s.WWW.NetSurf.p%x",
+ getenv("Wimp$ScrapDir"), (unsigned int)params);
+ LOG(("filename: %s", c->data.plugin.filename));
+
+ /* Write object attributes first */
+
+ /* classid is checked first */
+ if (params->classid != 0 && params->codetype != 0) {
+ if (!plugin_add_item_to_pilist(&pilist,
+ PLUGIN_PARAMETER_DATA, "CLASSID",
+ (const char*)params->classid,
+ (const char*)params->codetype))
+ goto error;
+ }
+ /* otherwise, we check the data attribute */
+ else if (params->data !=0 && params->type != 0) {
+ if (!plugin_add_item_to_pilist(&pilist,
+ PLUGIN_PARAMETER_DATA, "DATA",
+ (const char *)params->data,
+ (const char *)params->type))
+ goto error;
+ }
- npl = plugin_get_instance_from_list(pmrr->browser, pmrr->plugin);
+ /* if codebase is specified, write it as well */
+ if (params->codebase != 0) {
+ if (!plugin_add_item_to_pilist(&pilist,
+ PLUGIN_PARAMETER_DATA, "CODEBASE",
+ (const char *)params->codebase,
+ NULL))
+ goto error;
+ }
- for (i = 0; i != npl->page->data.html.object_count &&
- npl->page->data.html.object[i].content != npl->c;
- i++) ;
+ /* Iterate through the parameter list, creating the parameters
+ * file as we go. We can free up the memory as we go.
+ */
+ while (params->params != 0) {
+ LOG(("name: %s", params->params->name == 0 ? "not set" : params->params->name));
+ LOG(("value: %s", params->params->value == 0 ? "not set" : params->params->value));
+ LOG(("type: %s", params->params->type == 0 ? "not set" : params->params->type));
+ LOG(("valuetype: %s", params->params->valuetype));
+
+
+ if (strcasecmp(params->params->valuetype, "data") == 0)
+ if (!plugin_add_item_to_pilist(&pilist,
+ PLUGIN_PARAMETER_DATA,
+ (const char *)params->params->name,
+ (const char *)params->params->value,
+ (const char *)params->params->type))
+ goto error;
+ if (strcasecmp(params->params->valuetype, "ref") == 0)
+ if (!plugin_add_item_to_pilist(&pilist,
+ PLUGIN_PARAMETER_URL,
+ (const char *)params->params->name,
+ (const char *)params->params->value,
+ (const char *)params->params->type))
+ goto error;
+ if (strcasecmp(params->params->valuetype, "object") == 0)
+ if (!plugin_add_item_to_pilist(&pilist,
+ PLUGIN_PARAMETER_OBJECT,
+ (const char *)params->params->name,
+ (const char *)params->params->value,
+ (const char *)params->params->type))
+ goto error;
+
+ temp = params->params;
+ params->params = params->params->next;
+
+ free(temp->name);
+ free(temp->value);
+ free(temp->type);
+ free(temp->valuetype);
+ temp->name = temp->value = temp->type = temp->valuetype = 0;
+ free(temp);
+ temp = 0;
+ }
- if (i != npl->page->data.html.object_count) {
- /* should probably shift by x and y eigen values here */
- npl->c->width = pmrr->size.x >> 1;
- npl->c->height = pmrr->size.y >> 1;
- plugin_force_redraw(npl->c, npl->page, i);
- }
+ /* Now write mandatory special parameters */
+
+ /* BASEHREF */
+ if (!plugin_add_item_to_pilist(&pilist, PLUGIN_PARAMETER_SPECIAL,
+ "BASEHREF",
+ (const char *)params->basehref,
+ NULL))
+ goto error;
+
+ /* USERAGENT */
+ if (!plugin_add_item_to_pilist(&pilist, PLUGIN_PARAMETER_SPECIAL,
+ "USERAGENT", "NetSurf", NULL))
+ goto error;
+
+ /* UAVERSION */
+ if (!plugin_add_item_to_pilist(&pilist, PLUGIN_PARAMETER_SPECIAL,
+ "UAVERSION", "0.01", NULL))
+ goto error;
+
+ /* APIVERSION */
+ if (!plugin_add_item_to_pilist(&pilist, PLUGIN_PARAMETER_SPECIAL,
+ "APIVERSION", "1.10", NULL))
+ goto error;
+
+ /* BGCOLOR */
+ if (c->data.plugin.box->style->background_color <= 0xFFFFFF)
+ sprintf(bgcolor, "%X00",
+ (unsigned int)c->data.plugin.box->style->background_color);
+ else
+ sprintf(bgcolor, "FFFFFF");
+ if (!plugin_add_item_to_pilist(&pilist, PLUGIN_PARAMETER_SPECIAL,
+ "BGCOLOR",
+ (const char *)bgcolor,
+ NULL))
+ goto error;
+
+ /* Write file */
+ fp = fopen(c->data.plugin.filename, "wb+");
+
+ while (pilist != 0) {
+ fwrite(&pilist->type, (unsigned int)sizeof(int), 1, fp);
+ fwrite(&pilist->rsize, (unsigned int)sizeof(int), 1, fp);
+
+ fwrite(&pilist->nsize, (unsigned int)sizeof(int), 1, fp);
+ fwrite(pilist->name, (unsigned int)strlen(pilist->name), 1, fp);
+ for (; pilist->npad != 0; pilist->npad--)
+ fputc('\0', fp);
+
+ fwrite(&pilist->vsize, (unsigned int)sizeof(int), 1, fp);
+ fwrite(pilist->value, (unsigned int)strlen(pilist->value), 1, fp);
+ for(; pilist->vpad != 0; pilist->vpad--)
+ fputc('\0', fp);
+
+ fwrite(&pilist->msize, (unsigned int)sizeof(int), 1, fp);
+ if (pilist->msize > 0) {
+ fwrite(pilist->mime_type,
+ (unsigned int)strlen(pilist->mime_type), 1, fp);
+ for (; pilist->mpad != 0; pilist->mpad--)
+ fputc('\0', fp);
+ }
+
+ ppi = pilist;
+ pilist = pilist->next;
+
+ free(ppi->name);
+ free(ppi->value);
+ free(ppi->mime_type);
+ ppi->name = ppi->value = ppi->mime_type = 0;
+ free(ppi);
+ ppi = 0;
+ }
- LOG(("requested (width, height): (%d, %d)", pmrr->size.x, pmrr->size.y));
-}
+ fwrite("\0", sizeof(char), 4, fp);
-/**
- * Handles receipt of plugin_stream_new messages
- */
-void plugin_stream_new(wimp_message *message) {
+ fclose(fp);
- struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
- struct plugin_message *reply;
- plugin_message_stream_new *pmsn = (plugin_message_stream_new*)&message->data;
+ return true;
- /* add this message to linked list */
- reply = plugin_add_message_to_linked_list(pmsn->browser, pmsn->plugin, message, 0);
+error:
+ while (pilist != 0) {
+ ppi = pilist;
+ pilist = pilist->next;
+
+ free(ppi->name);
+ free(ppi->value);
+ free(ppi->mime_type);
+ ppi->name = ppi->value = ppi->mime_type = 0;
+ free(ppi);
+ ppi = 0;
+ }
- /* notify plugin_open message entry in list */
- if(npm != NULL) {
+ while (params->params) {
+ temp = params->params;
+ params->params = params->params->next;
+
+ free(temp->name);
+ free(temp->value);
+ free(temp->type);
+ free(temp->valuetype);
+ temp->name = temp->value = temp->type = temp->valuetype = 0;
+ free(temp);
+ temp = 0;
+ }
- npm->poll = 1;
- npm->plugin = pmsn->plugin;
- npm->reply = reply;
- }
+ free(c->data.plugin.filename);
+ c->data.plugin.filename = 0;
+ return false;
}
/**
- * Handles receipt of plugin_stream_written messages
+ * Calculates the size of a parameter file record
+ *
+ * \param name Record name
+ * \param data Record data
+ * \param mime Record mime type
+ * \return length of record
*/
-void plugin_stream_written(wimp_message *message) {
-
- struct plugin_message *npm = plugin_get_message_from_linked_list(message->your_ref);
- struct plugin_message *reply;
- plugin_message_stream_written *pmswt = (plugin_message_stream_written*)&message->data;
+int plugin_calculate_rsize(const char* name, const char* data,
+ const char* mime)
+{
+ int ret = 0;
- /* add this message to linked list */
- reply = plugin_add_message_to_linked_list(pmswt->browser, pmswt->plugin, message, 0);
+ ret += (4 + strlen(name) + 3) / 4 * 4; /* name */
+ ret += (4 + strlen(data) + 3) / 4 * 4; /* data */
- /* notify plugin_open message entry in list */
- if(npm != NULL) {
+ if (mime != NULL)
+ ret += (4 + strlen(mime) + 3) / 4 * 4; /* mime type */
+ else
+ ret += 4;
- npm->poll = 1;
- npm->plugin = pmswt->plugin;
- npm->reply = reply;
- }
+ return ret;
}
/**
- * Handles plugin_url_access messages
+ * Adds an item to the list of parameter file records
+ *
+ * \param pilist Pointer to list of parameters
+ * \param type Type of record to add
+ * \param name Name of record
+ * \param value Value of record
+ * \param mime_type Mime type of record
+ * \return true on success, false otherwise
*/
-void plugin_url_access(wimp_message *message) {
-
- wimp_message m;
- struct plugin_list *npl;
- plugin_message_url_access *pmua = (plugin_message_url_access*)&message->data;
- plugin_message_notify *pmn = (plugin_message_notify*)&m.data;
- int notify = 0, post = 0, file = 0;
- char *url = plugin_get_string_value(pmua->url, (char*)pmua);
- char *window;
-
- npl = plugin_get_instance_from_list(pmua->browser, pmua->plugin);
-
- if (pmua->flags & 0x01) notify = 1;
- if (pmua->flags & 0x02) post = 1;
- if (pmua->flags & 0x04) file = 1;
-
- /* fetch url to window */
- if (pmua->target_window.offset != 0 &&
- pmua->target_window.pointer != 0) {
- window = plugin_get_string_value(pmua->target_window,
- (char*)pmua);
- LOG(("flags: %d, url: %s, window: %s", pmua->flags, url, window));
- /* TODO: proper _parent and _self support (needs frames)
- * other window names
- */
- if (!post) { /* GET request */
- if (strcasecmp(window, "_self") == 0 ||
- strcasecmp(window, "_parent") == 0 ||
- strcasecmp(window, "_top") == 0 ||
- strcasecmp(window, "") == 0) {
- browser_window_go(npl->bw, url);
- }
- else if (strcasecmp(window, "_blank") == 0) {
- browser_window_create(url, NULL);
- }
- }
- else { /* POST request */
- /* fetch URL */
- }
- }
- /* fetch data and stream to plugin */
- else {
- if (!post) { /* GET request */
- /* fetch URL */
- }
- else { /* POST request */
- /* fetch URL */
- }
-
- /* stream data to plugin */
- }
-
- if (notify) {
- /* send message_plugin_notify to plugin task */
- pmn->flags = 0;
- pmn->plugin = pmua->plugin;
- pmn->browser = pmua->browser;
- pmn->url.pointer = url;
- pmn->reason = (plugin_notify_reason)0;
- pmn->notify_data = pmua->notify_data;
-
- m.size = 44;
- m.your_ref = message->my_ref;
- m.action = message_PLUG_IN_NOTIFY;
- xwimp_send_message(wimp_USER_MESSAGE, &m, message->sender);
- }
-}
+bool plugin_add_item_to_pilist(struct plugin_param_item **pilist,
+ plugin_parameter_type type, const char* name,
+ const char* value, const char* mime_type)
+{
+ struct plugin_param_item *ppi = calloc(1, sizeof(*ppi));
+
+ if (!ppi)
+ return false;
+
+ /* initialise struct */
+ ppi->type = 0;
+ ppi->rsize = 0;
+ ppi->nsize = 0;
+ ppi->name = 0;
+ ppi->npad = 0;
+ ppi->vsize = 0;
+ ppi->value = 0;
+ ppi->vpad = 0;
+ ppi->msize = 0;
+ ppi->mime_type = 0;
+ ppi->mpad = 0;
+
+ ppi->type = type;
+ ppi->rsize = plugin_calculate_rsize(name, value, mime_type);
+ ppi->nsize = strlen(name);
+ ppi->name = strdup(name);
+ if (!ppi->name) {
+ free(ppi);
+ return false;
+ }
-/**
- * Handles receipt of plugin_status messages
- */
-void plugin_status(wimp_message *message) {
+ ppi->npad = 4 - (ppi->nsize%4 == 0 ? 4 : ppi->nsize%4);
+ ppi->vsize = strlen(value);
+ ppi->value = strdup(value);
+ if (!ppi->value) {
+ free(ppi->name);
+ free(ppi);
+ return false;
+ }
- plugin_message_status *pms = (plugin_message_status*)&message->data;
- struct plugin_list *npl = plugin_get_instance_from_list(pms->browser, pms->plugin);
+ ppi->vpad = 4 - (ppi->vsize%4 == 0 ? 4 : ppi->vsize%4);
+ if(mime_type != 0) {
+ ppi->msize = strlen(mime_type);
+ ppi->mime_type = strdup(mime_type);
+ if (!ppi->mime_type) {
+ free(ppi->name);
+ free(ppi->value);
+ free(ppi);
+ return false;
+ }
+
+ ppi->mpad = 4 - (ppi->msize%4 == 0 ? 4 : ppi->msize%4);
+ }
- gui_window_set_status(npl->bw->window,
- (const char*)plugin_get_string_value(pms->message,
- (char*)pms));
+ ppi->next = (*pilist);
+ (*pilist) = ppi;
+ return true;
}
/**
* Utility function to grab string data from plugin message blocks
+ *
+ * \param string Containing structure
+ * \param msg Containing message
+ * \return the string data
*/
-char *plugin_get_string_value(os_string_value string, char *msg) {
-
- if(string.offset == 0 || string.offset > 256) {
- return string.pointer;
- }
- return &msg[string.offset];
+char *plugin_get_string_value(os_string_value string, char *msg)
+{
+ if(string.offset == 0 || string.offset > 256) {
+ return string.pointer;
+ }
+ return &msg[string.offset];
}
-void plugin_force_redraw(struct content *object, struct content *c,
- unsigned int i) {
-
- struct box *box = c->data.html.object[i].box;
-
- box->object = object;
-
- box->width = box->min_width = box->max_width = object->width;
- box->height = object->height;
+/**
+ * Determines whether a content is still active
+ *
+ * \param c The content to examine
+ * \return true if active, false otherwise
+ */
+bool plugin_active(struct content *c)
+{
+ struct content *d;
- box->style->width.width = CSS_WIDTH_LENGTH;
- box->style->width.value.length.unit = CSS_UNIT_PX;
- box->style->width.value.length.value = object->width;
+ if (c->user_list == 0)
+ return false;
- box->style->height.height = CSS_HEIGHT_LENGTH;
- box->style->height.length.unit = CSS_UNIT_PX;
- box->style->height.length.value = object->height;
+ for (d = content_list; d; d = d->next) {
+ if (d == c)
+ return true;
+ }
- need_reformat = 1;
- /* We don't call content_reformat here
- because doing so breaks things :-)
- */
+ return false;
}
#endif
diff --git a/riscos/plugin.h b/riscos/plugin.h
index 72ff798f5..8d3bfd798 100644
--- a/riscos/plugin.h
+++ b/riscos/plugin.h
@@ -18,60 +18,30 @@ struct content;
struct object_params;
struct content_plugin_data {
- char *data; /* object data */
- unsigned long length; /* object length */
- char *sysvar; /* system variable set by plugin */
-};
-
-struct plugin_state {
- int dummy;
-};
-
-struct plugin_message {
-
- int poll;
- plugin_b browser;
- plugin_p plugin;
- wimp_message *m;
- struct plugin_message *reply;
- struct plugin_message *next;
- struct plugin_message *prev;
-};
-
-struct plugin_list {
-
- struct content *c;
- struct browser_window *bw;
- struct content *page;
- struct box *box;
- struct object_params *params;
- void **state;
- struct plugin_list *next;
- struct plugin_list *prev;
-};
-
-struct plugin_param_item {
-
- int type;
- int rsize;
- int nsize;
- char *name;
- int npad;
- int vsize;
- char *value;
- int vpad;
- int msize;
- char *mime_type;
- int mpad;
-
- struct plugin_param_item *next;
+ struct browser_window *bw; /* window containing this content */
+ struct content *page; /* parent content */
+ struct box *box; /* box containing this content */
+ char *taskname; /* plugin task to launch */
+ char *filename; /* filename of parameters file */
+ char *datafile; /* filename of filestreamed file */
+ bool opened; /* has this plugin been opened? */
+ int repeated; /* indication of opening state */
+ unsigned int browser; /* browser handle */
+ unsigned int plugin; /* plugin handle */
+ unsigned int browser_stream; /* browser stream handle */
+ unsigned int plugin_stream; /* plugin stream handle */
+ unsigned int plugin_task; /* plugin task handle */
+ unsigned int consumed; /* size of data consumed by plugin */
+ bool reformat_pending; /* is a reformat pending? */
+ int width, height; /* reformat width & height */
+ bool stream_waiting; /* waiting to stream a datastream */
+ bool file_stream_waiting; /* waiting to stream as file */
};
/* function definitions */
bool plugin_handleable(const char *mime_type);
void plugin_msg_parse(wimp_message *message, int ack);
bool plugin_create(struct content *c, const char *params[]);
-bool plugin_process_data(struct content *c, char *data, unsigned int size);
bool plugin_convert(struct content *c, int width, int height);
void plugin_reformat(struct content *c, int width, int height);
void plugin_destroy(struct content *c);
@@ -84,5 +54,17 @@ void plugin_open(struct content *c, struct browser_window *bw,
struct object_params *params);
void plugin_close(struct content *c);
+/* message handlers */
+void plugin_open_msg(wimp_message *message);
+void plugin_opening(wimp_message *message);
+void plugin_close_msg(wimp_message *message);
+void plugin_closed(wimp_message *message);
+void plugin_reshape_request(wimp_message *message);
+void plugin_status(wimp_message *message);
+void plugin_stream_new(wimp_message *message);
+void plugin_stream_written(wimp_message *message);
+void plugin_url_access(wimp_message *message);
+
+
#endif