/* Copyright 1997 Acorn Computers Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /***************************************************/ /* File : PlugIn.c */ /* */ /* Purpose: Supporting the generic RISC OS browser */ /* Plug-In interface. */ /* */ /* Author : A.D.Hodgkinson */ /* */ /* History: 05-Oct-97: Created. */ /***************************************************/ #include #include #include #include "swis.h" #include "flex.h" #include "HTMLLib.h" /* HTML library API, Which will include html2_ext.h, tags.h and struct.h */ #include "wimp.h" #include "wimplib.h" #include "event.h" #include "toolbox.h" #include "svcprint.h" #include "Global.h" #include "FromROSLib.h" #include "Utils.h" #include "Browser.h" #include "Fetch.h" /* (Which itself includes URLstat.h) */ #include "FetchHTML.h" #include "FetchPage.h" #include "Filetypes.h" #include "Frames.h" #include "Handlers.h" #include "Images.h" #include "MimeMap.h" #include "MiscDefs.h" #include "Object.h" #include "Protocols.h" #include "Redraw.h" #include "Reformat.h" #include "TokenUtils.h" #include "URLveneer.h" #include "Windows.h" #include "PlugIn.h" /* Statics */ static plugin_queue * plugin_queue_head = NULL; static int plugin_open_reference = 0; static int plugin_open_tried_once = 0; static char * plugin_open_filename = NULL; static HStream * plugin_open_token = NULL; static int plugin_close_reference = 0; /* Static function prototypes */ static _kernel_oserror * plugin_write_params_word (int fh, int word); static _kernel_oserror * plugin_write_params_string (int fh, const char * string); static _kernel_oserror * plugin_write_params_entry (int fh, int type, const char * name, const char * data, const char * mime); static _kernel_oserror * plugin_broadcast_plugin_open (void); static _kernel_oserror * plugin_remove_head_item (void); /*************************************************/ /* plugin_return_string() */ /* */ /* Takes a message block and string_value from */ /* within it, and returns the string it points */ /* to. */ /* */ /* Parameters: Pointer to a WimpMessage struct */ /* holding the string_value field; */ /* */ /* Pointer to the string_value field */ /* inside that message. */ /* */ /* Returns: Pointer to the string the */ /* string_value references, or NULL */ /* if the value seems invalid. */ /*************************************************/ const char * plugin_return_string(WimpMessage * m, string_value * sv) { int offset = ((char *) sv) - ((char *) m); if (!m || !sv || !sv->offset) return NULL; /* Is the offset of the string_value field within the message */ /* block out of range (i.e. the string_value does not appear */ /* to lie in the given message block)? */ if (offset >= m->hdr.size || offset < sizeof(m->hdr)) return NULL; /* Now read the string_value field itself */ if (sv->offset < 256) { if (sizeof(m->hdr) + offset >= m->hdr.size) return NULL; else return (const char *) (((char *) m) + sizeof(m->hdr) + sv->offset); } else return (const char *) sv->offset; } /*************************************************/ /* plugin_write_params_word() */ /* */ /* Writes a word to a given parameters file, */ /* in little-endian order. */ /* */ /* Parameters: RISC OS file handle of the file; */ /* */ /* Word to write. */ /*************************************************/ static _kernel_oserror * plugin_write_params_word(int fh, int word) { _kernel_oserror * e; char integer[4]; /* #define Brain_Off... */ integer[0] = (word & 0xff); integer[1] = ((word & 0xff00) >> 8); integer[2] = ((word & 0xff0000) >> 16); integer[3] = ((word & 0xff000000) >> 24); RetError(_swix(OS_BPut, _INR(0,1), integer[0], fh)); RetError(_swix(OS_BPut, _INR(0,1), integer[1], fh)); RetError(_swix(OS_BPut, _INR(0,1), integer[2], fh)); RetError(_swix(OS_BPut, _INR(0,1), integer[3], fh)); return NULL; } /*************************************************/ /* plugin_write_params_string() */ /* */ /* Writes a string to a given parameters file, */ /* padding with zeros to a length which is a */ /* multiple of 4. If the string length, not */ /* including terminator, is already a multiple */ /* of four, no extra bytes are written. */ /* */ /* Parameters: RISC OS file handle of the file; */ /* */ /* Pointer to the string. */ /*************************************************/ static _kernel_oserror * plugin_write_params_string(int fh, const char * string) { _kernel_oserror * e; const char * s; int i = 0; int pad; /* Write the main string */ s = string ? string : ""; while (s[i]) { RetError(_swix(OS_BPut, _INR(0,1), s[i], fh)); i++; } /* Pad if necessary */ pad = 4 - (strlen(s) % 4); if (pad < 4) { for (i = 0; i < pad; i ++) { RetError(_swix(OS_BPut, _INR(0,1), '\0', fh)); } } return NULL; } /*************************************************/ /* plugin_write_params_entry() */ /* */ /* Writes an entry to the given parameters file. */ /* */ /* Parameters: RISC OS file handle of the file; */ /* */ /* Type of the entry (see */ /* PlugIn.h); */ /* */ /* Pointer to the name string; */ /* */ /* Pointer to the data string; */ /* */ /* Pointer to the Mime string. */ /* */ /* Assumes: Any of the pointers may be NULL */ /* or a zero length string to write */ /* a zero length field for that */ /* item. */ /*************************************************/ static _kernel_oserror * plugin_write_params_entry(int fh, int type, const char * name, const char * data, const char * mime) { _kernel_oserror * e; int length; const char * n; const char * d; const char * m; /* Make life easier */ n = name ? name : ""; d = data ? data : ""; m = mime ? mime : ""; /* Write the type */ RetError(plugin_write_params_word(fh, type)); /* Calculate and write the entry length */ length = 4 + strlen(n); length = (int) WordAlign(length); length += 4 + strlen(d); length = (int) WordAlign(length); length += 4 + strlen(m); length = (int) WordAlign(length); RetError(plugin_write_params_word(fh, length)); /* The name field */ RetError(plugin_write_params_word(fh, strlen(n))); RetError(plugin_write_params_string(fh, n)); /* The data field */ RetError(plugin_write_params_word(fh, strlen(d))); RetError(plugin_write_params_string(fh, d)); /* The mime type field */ RetError(plugin_write_params_word(fh, strlen(m))); RetError(plugin_write_params_string(fh, m)); return NULL; } /*************************************************/ /* plugin_write_params() */ /* */ /* Writes a parameters file to a unique filename */ /* based on the given HStream. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the HStream; */ /* */ /* Pointer to the HStream struct */ /* representing the OBJECT, APPLET */ /* or EMBED tag that the parameters */ /* file is for; */ /* */ /* Buffer for the filename that was */ /* used, or if the buffer size given */ /* is zero, pointer to the filename */ /* to use; */ /* */ /* Size of the buffer, or zero if */ /* the above parameter is a pointer */ /* to the filename to use instead of */ /* a pointer to a buffer to receive */ /* a locally generated system unique */ /* filename; */ /* */ /* Pointer to a BBox describing the */ /* size of the Plug-In window. */ /*************************************************/ _kernel_oserror * plugin_write_params(browser_data * b, HStream * t, char * buffer, int buffer_size, BBox * position) { _kernel_oserror * e = NULL; int fh = 0; char * data; char version[5]; if (buffer_size) protocols_util_make_unique_name(buffer, buffer_size); RetError(_swix(OS_Find, _INR(0,1) | _OUT(0), 0x8c, /* Create empty file with r/w access, return errors */ buffer, &fh)); /* Write the browser special fields */ data = browser_current_url(b); if (!data) data = browser_fetch_url(b); e = plugin_write_params_entry(fh, PlugIn_ParamType_BrowserSpecial, "BASEHREF", data, NULL); if (e) goto plugin_write_params_exit; data = lookup_token("_TaskName", 1, 0); e = plugin_write_params_entry(fh, PlugIn_ParamType_BrowserSpecial, "USERAGENT", data, NULL); if (e) goto plugin_write_params_exit; data = lookup_token("Version", 1, 0); StrNCpy0(version, data); e = plugin_write_params_entry(fh, PlugIn_ParamType_BrowserSpecial, "UAVERSION", version, NULL); if (e) goto plugin_write_params_exit; e = plugin_write_params_entry(fh, PlugIn_ParamType_BrowserSpecial, "APIVERSION", "1.10", NULL); if (e) goto plugin_write_params_exit; /* Now write details based on the Object type */ if ( ( HtmlOBJECTclassid(t) && !strncmp(HtmlOBJECTclassid(t), "java:", 5) ) || ( HtmlOBJECTcodetype(t) && !strcmp(HtmlOBJECTcodetype(t), "application/java-vm") ) ) { char number[64]; const char * cis = HtmlOBJECTclassid(t); const char * cie; /* A Java applet. First entry should be called 'code' to match */ /* an APPLET tag; we get the details from the ClassID attribute, */ /* giving just the leafname. */ cie = cis + strlen(cis) - 1; while (cie > cis && *cie != '/') cie --; if (*cie == '/') cie++; e = plugin_write_params_entry(fh, PlugIn_ParamType_URLFromOBJECT, "CLASSID", cie, HtmlOBJECTcodetype(t)); if (e) goto plugin_write_params_exit; /* Codebase, if we have it */ if (HtmlOBJECTcodebase(t) && *HtmlOBJECTcodebase(t)) { e = plugin_write_params_entry(fh, PlugIn_ParamType_DataFromOBJECT, "CODEBASE", HtmlOBJECTcodebase(t), NULL); if (e) goto plugin_write_params_exit; } /* Write 'alt' for the 'standby' text */ e = plugin_write_params_entry(fh, PlugIn_ParamType_DataFromOBJECT, "STANDBY", HtmlOBJECTstandby(t) ? HtmlOBJECTstandby(t) : "Java", NULL); if (e) goto plugin_write_params_exit; /* Width and height */ sprintf(number, "%d", (position->ymax - position->ymin) / 2); e = plugin_write_params_entry(fh, PlugIn_ParamType_DataFromOBJECT, "HEIGHT", number, NULL); if (e) goto plugin_write_params_exit; sprintf(number, "%d", (position->xmax - position->xmin) / 2); e = plugin_write_params_entry(fh, PlugIn_ParamType_DataFromOBJECT, "WIDTH", number, NULL); if (e) goto plugin_write_params_exit; } /* If we have a child token stream, look for PARAM tags */ if (HtmlOBJECTstream(t)) { HStream * child = HtmlOBJECTstream(t); while (child) { if (child->tagno == TAG_PARAM) { int type; /* Get the entry type from the valuetype field of the tag */ switch (HtmlPARAMvaluetype(child)) { default: case paramtype_DATA: type = PlugIn_ParamType_DataFromPARAM; break; case paramtype_OBJECT: type = PlugIn_ParamType_ObjectFromPARAM; break; case paramtype_REF: type = PlugIn_ParamType_URLFromPARAM; break; } /* Write the entry */ e = plugin_write_params_entry(fh, type, HtmlPARAMname(child), HtmlPARAMvalue(child), HtmlPARAMtype(child)); if (e) goto plugin_write_params_exit; } child = child->next; } } /* Various actions for different builds, if we don't understand */ /* the token at all. */ else { #ifdef TRACE erb.errnum = Utils_Error_Custom_Message; strcpy(erb.errmess, "OBJECT tag type not understood in plugin_write_params"); e = &erb; #else data = data; #endif } /* Write the terminating entry */ RetError(plugin_write_params_word(fh, PlugIn_ParamType_Terminator)); plugin_write_params_exit: /* Exit by closing the file and returning any */ /* generated error. */ if (fh) { _swix(OS_Find, _INR(0,1), 0, /* Close file */ fh); /* Set the filetype */ _swix(OS_File, _INR(0,2), 18, buffer, FileType_DATA); } return e; } /*************************************************/ /* plugin_broadcast_plugin_open() */ /* */ /* Where it all starts - broadcast a */ /* Message_PlugIn_Open for the Plug-In at the */ /* head of the queue. */ /* */ /* External functions should invoke this by */ /* adding to the Plug-In queue, not by a direct */ /* call here. */ /*************************************************/ static _kernel_oserror * plugin_broadcast_plugin_open(void) { _kernel_oserror * e; char params[Limits_OS_Pathname]; WimpMessage m; MPlugIn_Open * open = (MPlugIn_Open *) &m.data; browser_data * b; HStream * t; BBox * position; #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_broadcast_plugin_open: Called, head item is %p\n", plugin_queue_head); #endif /* Can't do anything if there are no queue items */ if (!plugin_queue_head) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; strcpy(erb.errmess, "NULL queue head in plugin_broadcast_plugin_open"); return &erb; #endif return NULL; } /* Make life a bit less verbose... */ b = plugin_queue_head->browser; t = plugin_queue_head->token; position = &plugin_queue_head->position; #ifdef TRACE if (tl & (1u<<30)) { char debugbuf[1024]; sprintf(debugbuf,"plugin_broadcast_plugin_open: Open at BBox %d, %d, %d, %d",position->xmin,position->ymin,position->xmax,position->ymax); Printf("%s\n",debugbuf); } #endif /* Write the parameters file */ RetError(plugin_write_params(b, t, params, sizeof(params), position)); // For debugging, this may be useful... // // plugin_write_params(b, t, "ADFS::4.$.DebugParam", 0, position); #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_broadcast_plugin_open: Params file is at '%s'\n",params); #endif /* Fill in the header */ m.hdr.size = sizeof(MPlugIn_Open) + sizeof(m.hdr); m.hdr.your_ref = 0; m.hdr.action_code = Message_PlugIn_Open; /* Fill in the body */ open->flags = 0; open->reserved = 0; open->browser_instance_handle = (int) b; open->parent_window_handle = b->window_handle; open->parent_area = *position; plugin_open_token = t; open->file_type = 0; mimemap_mime_to_riscos(HtmlOBJECTcodetype(t), &open->file_type); if (!open->file_type) open->file_type = FileType_DATA; #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_broadcast_plugin_open: Filetype to use: %03x\n", open->file_type); #endif /* If we already have RMA space for the filename, free it */ _swix(OS_Module, _IN(0) | _IN(2), 7, plugin_open_filename); plugin_open_filename = NULL; /* (Re)claim RMA space for the filename */ e = _swix(OS_Module, _IN(0) | _IN(3) | _OUT(2), 6, strlen(params) + 1, &plugin_open_filename); if (e) return e; if (!plugin_open_filename) return NULL; /* Copy it in and fill in the message field */ strcpy(plugin_open_filename, params); open->file_name.ptr = plugin_open_filename; /* Broadcast the message */ RetError(wimp_send_message(Wimp_EUserMessageRecorded, &m, 0, 0, NULL)); /* Record my_ref in case it bounces */ plugin_open_reference = m.hdr.my_ref; plugin_open_tried_once = 0; /* We haven't tried once until we get the first bounce */ #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_broadcast_plugin_open: Successful\n",b,t); #endif return NULL; } /*************************************************/ /* plugin_plugin_open_bounced() */ /* */ /* Handle a Message_PlugIn_Open bounce. */ /* */ /* Parameters: Pointer to a Wimp_Message struct */ /* holding the bounced message. */ /*************************************************/ _kernel_oserror * plugin_plugin_open_bounced(WimpMessage * m) { _kernel_oserror * e; MPlugIn_Open * open = (MPlugIn_Open *) &m->data; #ifdef TRACE if (!plugin_open_tried_once) { if (tl & (1u<<30)) Printf("plugin_plugin_open_bounced: Called\n"); } else { if (tl & (1u<<30)) Printf("plugin_plugin_open_bounced: Called again\n"); } #endif if (m->hdr.my_ref == plugin_open_reference) { #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_plugin_open_bounced: Message reference %x is known\n", m->hdr.my_ref); #endif if (plugin_open_tried_once) { /* Yuk, everything collapsed in a nasty great heap */ #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_plugin_open_bounced: Plug-In launch failed\n"); #endif /* Delete the parameters file */ remove(plugin_open_filename); /* Need to free up the RMA space used for the filename */ _swix(OS_Module, _IN(0) | _IN(2), 7, plugin_open_filename); plugin_open_reference = 0; plugin_open_tried_once = 0; plugin_open_filename = NULL; plugin_open_token = NULL; /* Remove the item from the queue, launching a new one */ /* if there is anything else there. */ RetError(plugin_remove_head_item()); } else { char combuf[16]; /* Size of '@PlugInType_xxx' plus terminator */ char sysvar[22]; /* As above, preceeded by 'Alias$' */ _kernel_swi_regs r; int required; BBox new; /* Try launching the Plug-In through Wimp_StartTask */ #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_plugin_open_bounced: Attempting Plug-In launch\n"); #endif plugin_open_tried_once = 1; if (open->file_type >= 0 && open->file_type <= 4095) sprintf(combuf, "@PlugInType_%03x", open->file_type); else sprintf(combuf, "@PlugInType_%03x", FileType_DATA); strcpy(sysvar, "Alias$"); strcat(sysvar, combuf); /* Does the system variable exist? */ r.r[0] = (int) sysvar; r.r[1] = (int) NULL; r.r[2] = -1; r.r[3] = 0; r.r[4] = 0; /* _swix will not work correctly for this particular SWI if */ /* requiring the returned R2 value. Something to do with */ /* the call relying on generating an error, but _swix spots */ /* it and pulls out earlier than the call expects. Or some */ /* such thing... */ _kernel_swi(OS_ReadVarVal, &r, &r); required = -r.r[2]; if (required) { show_error_ret(_swix(Wimp_StartTask, _IN(0), combuf)); } #ifdef TRACE else { if (tl & (1u<<30)) Printf("plugin_plugin_open_bounced: System variable '%s' is not set\n", sysvar); } #endif /* Now rebroadcast the message. Note we can't use the same position, */ /* as between the two redrawing may have occurred that has changed */ /* where the Object now sits. */ if ( !object_get_token_object_box((browser_data *) open->browser_instance_handle, plugin_open_token, &new) ) open->parent_area = new; #ifdef TRACE if (tl & (1u<<30)) { char debugbuf[1024]; sprintf(debugbuf,"plugin_plugin_open_bounced: New BBox %d, %d, %d, %d",new.xmin,new.ymin,new.xmax,new.ymax); Printf("%s\n",debugbuf); if (tl & (1u<<30)) Printf("plugin_plugin_open_bounced: Rebroadcasting Message_PlugIn_Open\n"); } #endif m->hdr.my_ref = m->hdr.your_ref = 0; e = wimp_send_message(Wimp_EUserMessageRecorded, m, 0, 0, NULL); /* Record my_ref in case it bounces for a second time */ if (!e) plugin_open_reference = m->hdr.my_ref; else return e; } } #ifdef TRACE else { if (tl & (1u<<30)) Printf("plugin_plugin_open_bounced: Message reference %x is not known\n", m->hdr.my_ref); erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "Unknown message reference %x in plugin_broadcast_plugin_open", m->hdr.my_ref); return &erb; } #endif #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_plugin_open_bounced: Successful\n"); #endif return NULL; } /*************************************************/ /* plugin_got_plugin_opening() */ /* */ /* Handle reception of a Message_PlugIn_Opening. */ /* */ /* Parameters: Pointer to a Wimp_Message struct */ /* relevant to the message. */ /*************************************************/ _kernel_oserror * plugin_got_plugin_opening(WimpMessage * m) { _kernel_oserror * e; MPlugIn_Opening * opening = (MPlugIn_Opening *) &m->data; #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_got_plugin_opening: Called\n"); #endif if (plugin_open_filename) { if (!(opening->flags & MPlugIn_Opening_WillDeleteParamsItself)) { #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_got_plugin_opening: Removing parameters file\n"); #endif remove(plugin_open_filename); } /* Need to free up the RMA space used for the filename */ _swix(OS_Module, _IN(0) | _IN(2), 7, plugin_open_filename); } /* Tell the Object the PlugIn details */ object_set_token_object_plugin(opening->browser_instance_handle, plugin_open_token, opening->plugin_instance_handle, m->hdr.sender); plugin_open_reference = 0; plugin_open_tried_once = 0; plugin_open_filename = NULL; plugin_open_token = NULL; /* Remove the item from the queue, launching a new one */ /* if there is anything else there. */ RetError(plugin_remove_head_item()); #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_got_plugin_opening: Successful\n"); #endif return NULL; } /*************************************************/ /* plugin_send_plugin_close() */ /* */ /* Tell a Plug-In to close down. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Plug-In (this is */ /* used for the browser instance */ /* handle in the Close message); */ /* */ /* Plug-In instance handle; */ /* */ /* Plug-In task handle. */ /*************************************************/ _kernel_oserror * plugin_send_plugin_close(browser_data * b, unsigned int instance, unsigned int task) { _kernel_oserror * e; WimpMessage m; MPlugIn_Close * close = (MPlugIn_Close *) &m.data; #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_send_plugin_close: Called\n"); #endif /* Fill in the header... */ m.hdr.size = sizeof(MPlugIn_Close) + sizeof(m.hdr); m.hdr.your_ref = 0; m.hdr.action_code = Message_PlugIn_Close; /* ...and the body... */ close->flags = 0; close->plugin_instance_handle = instance; close->browser_instance_handle = (int) b; /* ...then send it. */ e = wimp_send_message(Wimp_EUserMessageRecorded, &m, task, 0, NULL); /* Remember the reference for any replies */ if (!e) plugin_close_reference = m.hdr.my_ref; #ifdef TRACE if (tl & (1u<<30)) { if (e) Printf("plugin_send_plugin_close: Exitting with error\n"); else Printf("plugin_send_plugin_close: Successful\n"); } #endif return e; } /*************************************************/ /* plugin_send_original_plugin_reshape() */ /* */ /* Tell a Plug-In to reposition or resize itself */ /* - not as part of a Plug-In request to resize. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Plug-In (this is */ /* used for the browser instance */ /* handle in the Close message); */ /* */ /* Plug-In instance handle; */ /* */ /* Plug-In task handle; */ /* */ /* New bounding box for the Plug-In */ /* child window (in (parent) window */ /* coordinates). */ /*************************************************/ _kernel_oserror * plugin_send_original_plugin_reshape(browser_data * b, unsigned int instance, unsigned int task, BBox * position) { _kernel_oserror * e; WimpMessage m; MPlugIn_Reshape * reshape = (MPlugIn_Reshape *) &m.data; #ifdef TRACE if (1 || tl & (1u<<30)) { char debugbuf[1024]; sprintf(debugbuf,"plugin_send_original_reshape: Called for %p to move instance 0x%08x to %d, %d, %d, %d",b,instance,position->xmin,position->ymin,position->xmax,position->ymax); Printf("%s\n",debugbuf); } #endif /* Fill in the header... */ m.hdr.size = sizeof(MPlugIn_Reshape) + sizeof(m.hdr); m.hdr.your_ref = 0; m.hdr.action_code = Message_PlugIn_Reshape; /* ...and the body... */ reshape->flags = 0; reshape->plugin_instance_handle = instance; reshape->browser_instance_handle = (int) b; reshape->parent_window_handle = b->window_handle; reshape->parent_area = *position; /* ...then send it. */ e = wimp_send_message(Wimp_EUserMessage, &m, task, 0, NULL); #ifdef TRACE if (tl & (1u<<30)) { if (e) Printf("plugin_send_original_plugin_reshape: Exitting with error\n"); else Printf("plugin_send_original_plugin_reshape: Successful\n"); } #endif return e; } /*************************************************/ /* plugin_got_url_access() */ /* */ /* Handle reception of a */ /* Message_PlugIn_URLAccess */ /* */ /* Parameters: Pointer to a Wimp_Message struct */ /* relevant to the message. */ /*************************************************/ _kernel_oserror * plugin_got_url_access(WimpMessage * m) { _kernel_oserror * e; MPlugIn_URLAccess * access = (MPlugIn_URLAccess *) &m->data; const char * url; const char * target; browser_data * targetted; browser_data * b = (browser_data *) access->browser_instance_handle; browser_data * ancestor = utils_ancestor(b); #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_got_url_access: Called\n"); #endif url = plugin_return_string(m, &access->url); target = plugin_return_string(m, &access->target); #ifdef TRACE if (tl & (1u<<30)) { if (url) Printf("plugin_got_url_access: URL '%s'\n", url); else Printf("plugin_got_url_access: No URL\n"); if (target) Printf("plugin_got_url_access: Target '%s'\n", target); else Printf("plugin_got_url_access: No Target\n"); } #endif if (url) { if (target) targetted = frames_find_target(b, target); else targetted = NULL; /* Don't want to ever open a new window if configured */ /* to run full screen. */ if (targetted || choices.full_screen) { /* If a named target was found, open in that. Otherwise we must */ /* be running full screen, so can't open a new window; in this */ /* case, open in the ancestor. */ RetError(fetchpage_new(targetted ? targetted : ancestor, url, 1, 1)); } else { /* If we've reached here, a named target wasn't found but the */ /* browser isn't running full screen either, so open a new */ /* window with the name specified in the link. */ RetError(windows_create_browser((char *) url, NULL, NULL, (char *) target, 0)); } } return NULL; } /*************************************************/ /* plugin_add_queue_item() */ /* */ /* Add details of a new Plug-In to the queue of */ /* Plug-Ins. If there were none already in the */ /* queue, then start this new one immediately. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Object; */ /* */ /* Pointer to the HStream struct */ /* representing the OBJECT, APPLET */ /* or EMBED tag (Object) that the */ /* message is for; */ /* */ /* Pointer to a BBox describing the */ /* where the Plug-In should open, in */ /* parent window coordinates. */ /*************************************************/ _kernel_oserror * plugin_add_queue_item(browser_data * b, HStream * t, BBox * position) { plugin_queue * new; int start_now = 0; #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_add_queue_item: Called for %p, %p\n",b,t); #endif /* Allocate memory for the item */ new = malloc(sizeof(plugin_queue)); if (!new) return make_no_memory_error(21); if (plugin_queue_head) { /* Insert the new item in between the existing first and second items */ new->next = plugin_queue_head->next; plugin_queue_head->next = new; } else { new->next = NULL; plugin_queue_head = new; /* This is the only item in the queue, so try to start a Plug-In */ /* for it as soon as possible. */ start_now = 1; } /* Fill in the rest of the structure */ new->browser = b; new->token = t; new->position = *position; /* If required, try to start the Plug-In */ if (start_now) { #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_add_queue_item: Exitting through plugin_broadcast_plugin_open\n"); #endif return plugin_broadcast_plugin_open(); } #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_add_queue_item: Successful\n"); #endif return NULL; } /*************************************************/ /* plugin_remove_item() */ /* */ /* Remove an item from the Plug-In queue. */ /* */ /* Parameters: Pointer to the plugin_queue */ /* struct to remove. */ /*************************************************/ _kernel_oserror * plugin_remove_item(plugin_queue * remove) { plugin_queue * prev; #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_remove_item: Called for %p\n",remove); #endif /* Can't do anything if there are no items */ if (!plugin_queue_head || !remove) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "NULL queue head (0x%08x) or remove item (0x%08x)in plugin_remove_item", (int) plugin_queue_head, (int) remove); return &erb; #endif return NULL; } /* Find the previous item */ prev = plugin_queue_head; while (prev && prev->next != remove) prev = prev->next; /* If we've not found the item we were asked to remove, and */ /* the remove item isn't at the queue head, 'remove' must */ /* be invalid - so exit. */ if (!prev && remove != plugin_queue_head) { #ifdef TRACE erb.errnum = Utils_Error_Custom_Normal; sprintf(erb.errmess, "Can't find item that points to given structure %0x08x in plugin_remove_item", (int) remove); return &erb; #endif return NULL; } /* OK, unlink it */ if (prev) prev->next = remove->next; else plugin_queue_head = remove->next; /* Free the item - finished. */ free(remove); #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_remove_item: Successful\n"); #endif return NULL; } /*************************************************/ /* plugin_remove_head_item() */ /* */ /* Remove the head item from the Plug-In queue, */ /* launching the next item if there is one. */ /*************************************************/ static _kernel_oserror * plugin_remove_head_item(void) { _kernel_oserror * e; #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_remove_head_item: Called\n"); #endif RetError(plugin_remove_item(plugin_queue_head)); if (plugin_queue_head) { #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_remove_head_item: Exitting through plugin_broadcast_plugin_open\n"); #endif return plugin_broadcast_plugin_open(); } else { #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_remove_head_item: Successful\n"); #endif return NULL; } } /*************************************************/ /* plugin_flush_queue() */ /* */ /* Remove selected, or all Plug-Ins in the */ /* queue. */ /* */ /* Parameters: Pointer to a browser_data struct */ /* relevant to the Plug-Ins to */ /* remove, or NULL for all items; */ /* */ /* If one of the removed items was */ /* at the head of the queue, 1 to */ /* launch the new head item Plug-In, */ /* else 0. */ /*************************************************/ _kernel_oserror * plugin_flush_queue(browser_data * b, int start_now) { _kernel_oserror * e; plugin_queue * old_head = plugin_queue_head; plugin_queue * current; plugin_queue * next; #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_flush_queue: Called for %p\n",b); #endif current = plugin_queue_head; /* For each item, remove it only if it belongs to the given */ /* browser, or the given browser is NULL. */ while (current) { next = current->next; if (!b || (b && next->browser == b)) RetError(plugin_remove_item(current)); current = next; } /* If there are still queue items, the head item has changed and */ /* the start_now parameter passed in says to do so, launch the */ /* new head item Plug-In. */ if ( plugin_queue_head && plugin_queue_head != old_head && start_now ) { #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_flush_queue: Exitting through plugin_broadcast_plugin_open\n"); #endif return plugin_broadcast_plugin_open(); } else { #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_flush_queue: Successful\n"); #endif return NULL; } } /*************************************************/ /* plugin_shutdown() */ /* */ /* Closes down all activities, flushing the */ /* Plug-In queue and freeing any RMA associated */ /* with string_value fields for in-transit */ /* messages. */ /*************************************************/ void plugin_shutdown(void) { /* In transit Message_PlugIn_Open broadcasts */ #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_shutdown: Called\n"); #endif if (plugin_open_filename) { _swix(OS_Module, _IN(0) | _IN(2), 7, plugin_open_filename); } /* Clear the message fields */ plugin_open_reference = 0; plugin_open_tried_once = 0; plugin_open_filename = NULL; plugin_open_token = NULL; /* (For now that's all we have to do for messages). */ /* */ /* Flush the queue and exit. */ plugin_flush_queue(NULL, 0); #ifdef TRACE if (tl & (1u<<30)) Printf("plugin_shutdown: Successful\n"); #endif return; }