Back to index

lightning-sunbird  0.9+nobinonly
NullPlugin.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 
00039 #include "npapi.h"
00040 
00041 #include <Carbon/Carbon.h>
00042 #include <CoreFoundation/CoreFoundation.h>
00043 
00044 #include <string.h>
00045 #include <ctype.h>
00046 #include <stdio.h>
00047 
00048 #define PLUGINFINDER_COMMAND_BEGINNING "javascript:window.open(\""
00049 #define PLUGINFINDER_COMMAND_END "\",\"plugin\",\"toolbar=no,status=no,resizable=no,scrollbars=no,height=252,width=626\");"
00050 #define PLUGINFINDER_COMMAND_END2 "\",\"plugin\",\"toolbar=no,status=no,resizable=yes,scrollbars=yes,height=252,width=626\");"
00051 
00052 
00053 //
00054 // Instance state information about the plugin.
00055 //
00056 class CPlugin
00057 {
00058 public:
00059        enum HiliteState { kUnhilited = 0, kHilited = 1 };      
00060 
00061        static NPError              Initialize();
00062        static void                 Shutdown();
00063        
00064        // no ctor because CPlugin is allocated and constructed by hand.
00065        // ideally, this should use placement |new|.
00066        
00067                      void          Constructor(NPP instance, NPMIMEType type, uint16 mode, int16 argc, char* argn[], char* argv[]);
00068                      void          Destructor();
00069                                           
00070                      void          SetWindow(NPWindow* window);
00071                      void          Print(NPPrint* printInfo);
00072                      Boolean              HandleEvent(EventRecord*);
00073 
00074 protected:
00075                      void          Draw(HiliteState hilite);
00076                      void          DrawString(const unsigned char* text, short width, short height, short centerX, Rect drawRect);
00077                      void          MouseDown();
00078                      
00079                      Boolean              FocusDraw();
00080                      void          RestoreDraw();
00081                      
00082                      void          DetermineURL(int16 argc, char* argn[], char* argv[]);
00083                      char *        MakeDefaultURL(void);
00084                      void          AddMimeTypeToList(StringPtr cTypeString);
00085                      Boolean              CheckMimeTypes();
00086                      void          AskAndLoadURL();
00087                      void          RefreshPluginPage();
00088                      
00089                      Ptr                  New(UInt32 size);
00090                      void          Delete(Ptr ptr);
00091                      
00092                      Boolean              IsPluginHidden(int16 argc, char* argn[], char* argv[]);
00093                      
00094 private:
00095        static        CIconHandle   sIconHandle;
00096        static CursHandle    sHandCursor;
00097        static char*         sAltText;
00098        static char*         sInstallCommand;
00099        static char*         sDefaultPage;
00100        static  char*        sRefreshText;
00101        static char*         sJavaScriptPage;
00102        static FSSpec        sDataFileSpec;      // only used for Mac OS 9
00103        static Boolean              sRunningOnOSX;
00104 
00105                      NPP                  fInstance;
00106                      NPWindow*     fWindow;
00107                      uint16        fMode;
00108                      NPMIMEType    fType;
00109                      char*         fPageURL;
00110                      char*         fFileURL;
00111                      NPBool        m_bOffline;
00112                      NPBool        m_bJavaScript;
00113                      
00114                      GrafPtr              fSavePort;
00115                      RgnHandle     fSaveClip;
00116                      Rect          fRevealedRect;
00117                      short         fSavePortTop;
00118                      short         fSavePortLeft;
00119                      Boolean              fUserInstalledPlugin;
00120                      Boolean              fHiddenPlugin;
00121                      Boolean              fAskedLoadURL;
00122 };
00123 
00124 
00125 CIconHandle CPlugin::sIconHandle          = NULL;
00126 CursHandle    CPlugin::sHandCursor               = NULL;
00127 char*         CPlugin::sAltText                  = NULL;
00128 char*         CPlugin::sInstallCommand    = NULL; 
00129 char*         CPlugin::sDefaultPage              = NULL;
00130 char*         CPlugin::sRefreshText              = NULL;
00131 char*         CPlugin::sJavaScriptPage    = NULL;
00132 FSSpec        CPlugin::sDataFileSpec;
00133 Boolean              CPlugin::sRunningOnOSX             = false;
00134 
00135 extern short         gResFile;
00136 
00137 // 'cicn'
00138 const short rBrokenPluginIcon = 326;
00139 
00140 // 'CURS'
00141 const short rHandCursor = 128;
00142 
00143 // 'STR '
00144 const short rDefaultPluginURL = 128;
00145 const short rAltTextString = 129;
00146 const short rJavaScriptInstallCommand = 130;
00147 const short rRefreshTextString = 131;
00148 const short rJavaScriptPageURL = 132;
00149 
00150 // 'STR#'
00151 const short rTypeListStrings = 129;
00152 
00153 static const char szPluginFinderCommandBeginning[] = PLUGINFINDER_COMMAND_BEGINNING;
00154 static const char szPluginFinderCommandEnd[] = PLUGINFINDER_COMMAND_END;
00155 
00156 
00157 //------------------------------------------------------------------------------------
00158 // NPP_Initialize:
00159 //------------------------------------------------------------------------------------
00160 NPError NPP_Initialize(void)
00161 {
00162        return CPlugin::Initialize();
00163 }
00164 
00165 
00166 //------------------------------------------------------------------------------------
00167 // NPP_Shutdown:
00168 //------------------------------------------------------------------------------------
00169 void NPP_Shutdown(void)
00170 {
00171        CPlugin::Shutdown();
00172 }
00173 
00174 
00175 //------------------------------------------------------------------------------------
00176 // NPP_New:
00177 //------------------------------------------------------------------------------------
00178 NPError NPP_New(NPMIMEType type, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData*)
00179 {
00180        if (instance == NULL)
00181               return NPERR_INVALID_INSTANCE_ERROR;
00182               
00183        CPlugin* This = (CPlugin*) (char*)NPN_MemAlloc(sizeof(CPlugin));
00184        instance->pdata = This;
00185        if (This != NULL)
00186        {
00187               This->Constructor(instance, type, mode, argc, argn, argv);
00188               return NPERR_NO_ERROR;
00189        }
00190        else
00191               return NPERR_OUT_OF_MEMORY_ERROR;
00192 }
00193 
00194 
00195 
00196 
00197 //------------------------------------------------------------------------------------
00198 // NPP_Destroy:
00199 //------------------------------------------------------------------------------------
00200 NPError NP_LOADDS
00201 NPP_Destroy(NPP instance, NPSavedData** /*save*/)
00202 {
00203        if (instance == NULL)
00204               return NPERR_INVALID_INSTANCE_ERROR;
00205 
00206        CPlugin* This = (CPlugin*) instance->pdata;
00207        
00208        if (This != NULL)
00209        {      
00210               This->Destructor();
00211               NPN_MemFree(This);
00212               instance->pdata = NULL;
00213        }
00214 
00215        return NPERR_NO_ERROR;
00216 }
00217 
00218 
00219 
00220 
00221 //------------------------------------------------------------------------------------
00222 // NPP_SetWindow:
00223 //------------------------------------------------------------------------------------
00224 NPError NPP_SetWindow(NPP instance, NPWindow* window)
00225 {
00226        if (instance == NULL)
00227               return NPERR_INVALID_INSTANCE_ERROR;
00228 
00229        CPlugin* This = (CPlugin*) instance->pdata;
00230        if (This != NULL)
00231               This->SetWindow(window);
00232        
00233        return NPERR_NO_ERROR;
00234 }
00235 
00236 
00237 
00238 //------------------------------------------------------------------------------------
00239 // NPP_NewStream:
00240 //------------------------------------------------------------------------------------
00241 NPError NP_LOADDS
00242 NPP_NewStream(NPP instance,
00243                                                  NPMIMEType /*type*/,
00244                                                  NPStream* /*stream*/, 
00245                                                  NPBool /*seekable*/,
00246                                                  uint16* /*stype*/)
00247 {
00248        if (instance == NULL)
00249               return NPERR_INVALID_INSTANCE_ERROR;
00250 
00251        return NPERR_NO_ERROR;
00252 }
00253 
00254 
00255 
00256 int32 STREAMBUFSIZE = 0X0FFFFFFF;   // If we are reading from a file in NPAsFile
00257                                     // mode so we can take any size stream in our
00258                                     // write call (since we ignore it)
00259 
00260 //------------------------------------------------------------------------------------
00261 // NPP_WriteReady:
00262 //------------------------------------------------------------------------------------
00263 int32 NP_LOADDS
00264 NPP_WriteReady(NPP /*instance*/, NPStream* /*stream*/)
00265 {
00266        return STREAMBUFSIZE;   // Number of bytes ready to accept in NPP_Write()
00267 }
00268 
00269 
00270 
00271 //------------------------------------------------------------------------------------
00272 // NPP_Write:
00273 //------------------------------------------------------------------------------------
00274 int32 NP_LOADDS
00275 NPP_Write(NPP /*instance*/, NPStream* /*stream*/, int32 /*offset*/, int32 len, void* /*buffer*/)
00276 {
00277        return len;                 // The number of bytes accepted
00278 }
00279 
00280 
00281 
00282 //------------------------------------------------------------------------------------
00283 // NPP_DestroyStream:
00284 //------------------------------------------------------------------------------------
00285 NPError NP_LOADDS
00286 NPP_DestroyStream(NPP instance, NPStream* /*stream*/, NPError /*reason*/)
00287 {
00288        if (instance == NULL)
00289               return NPERR_INVALID_INSTANCE_ERROR;
00290 
00291        return NPERR_NO_ERROR;
00292 }
00293 
00294 
00295 //------------------------------------------------------------------------------------
00296 // NPP_StreamAsFile:
00297 //------------------------------------------------------------------------------------
00298 void NP_LOADDS
00299 NPP_StreamAsFile(NPP /*instance*/, NPStream */*stream*/, const char* /*fname*/)
00300 {
00301 }
00302 
00303 
00304 
00305 //------------------------------------------------------------------------------------
00306 // NPP_Print:
00307 //------------------------------------------------------------------------------------
00308 void NP_LOADDS
00309 NPP_Print(NPP instance, NPPrint* printInfo)
00310 {
00311        if (printInfo == NULL)
00312               return;
00313 
00314        if (instance != NULL)
00315        {
00316               if (printInfo->mode == NP_FULL)
00317                      printInfo->print.fullPrint.pluginPrinted = FALSE; // Do the default
00318               else   // If not fullscreen, we must be embedded
00319               {
00320                      CPlugin* This = (CPlugin*) instance->pdata;
00321                      if (This != NULL)
00322                             This->Print(printInfo);
00323               }
00324        }
00325 
00326 }
00327 
00328 
00329 //------------------------------------------------------------------------------------
00330 // NPP_HandleEvent:
00331 // Mac-only.
00332 //------------------------------------------------------------------------------------
00333 int16 NPP_HandleEvent(NPP instance, void* event)
00334 {
00335        if (instance != NULL)
00336        {      
00337               CPlugin* This = (CPlugin*) instance->pdata;
00338               if (This != NULL && event != NULL)
00339                      return This->HandleEvent((EventRecord*) event);
00340        }
00341        
00342        return FALSE;
00343 }
00344 
00345 
00346 //------------------------------------------------------------------------------------
00347 // NPP_URLNotify:
00348 //------------------------------------------------------------------------------------
00349 void NPP_URLNotify(NPP /*instance*/, const char* /*url*/, NPReason /*reason*/, void* /*notifyData*/)
00350 {
00351 }
00352 
00353 #ifdef OJI
00354 //------------------------------------------------------------------------------------
00355 // NPP_GetJavaClass:
00356 //------------------------------------------------------------------------------------
00357 jref NPP_GetJavaClass(void)
00358 {
00359        return NULL;
00360 }
00361 #endif /* OJI */
00362 
00363 #pragma mark -
00364 
00365 //------------------------------------------------------------------------------------
00366 // CPlugin::Initialize:
00367 //------------------------------------------------------------------------------------
00368 NPError CPlugin::Initialize()
00369 {
00370        Handle string;
00371        short  saveResFile = CurResFile();
00372 
00373        UseResFile(gResFile);
00374 
00375        long   systemVersion;
00376        OSErr  err = ::Gestalt(gestaltSystemVersion, &systemVersion);
00377        sRunningOnOSX = (err == noErr) && (systemVersion >= 0x00001000);
00378 
00379        // Get Resources
00380        CPlugin::sIconHandle = GetCIcon(rBrokenPluginIcon);
00381        CPlugin::sHandCursor = GetCursor(rHandCursor);
00382 
00383        // Get "alt text" string
00384        string = Get1Resource('STR ', rAltTextString);
00385        if (string && *string)
00386        {
00387               short stringLen = (*string)[0];
00388               CPlugin::sAltText = (char*)NPN_MemAlloc(stringLen +1);
00389               if (CPlugin::sAltText != NULL)
00390               {
00391                      short src = 1;
00392                      short dest = 0;
00393                      while (src <= stringLen)
00394                             CPlugin::sAltText[dest++] = (*string)[src++];
00395                      CPlugin::sAltText[dest++] = 0;
00396               }
00397        }
00398        ReleaseResource(string);
00399        
00400        // Get "refresh text" string
00401        string = Get1Resource('STR ', rRefreshTextString);
00402        if (string && *string)
00403        {
00404               short stringLen = (*string)[0];
00405               CPlugin::sRefreshText = (char*)NPN_MemAlloc(stringLen + 1);
00406               if (CPlugin::sRefreshText != NULL)
00407               {
00408                      short src = 1;
00409                      short dest = 0;
00410                      while (src <= stringLen)
00411                             CPlugin::sRefreshText[dest++] = (*string)[src++];
00412                      CPlugin::sRefreshText[dest++] = 0;
00413               }
00414        }
00415        ReleaseResource(string);
00416        
00417        // Get JavaScript install command string
00418        string = Get1Resource('STR ', rJavaScriptInstallCommand);
00419        if (string && *string)
00420        {
00421               short stringLen = (*string)[0];
00422               CPlugin::sInstallCommand = (char*)NPN_MemAlloc(stringLen + 1);
00423               if (CPlugin::sInstallCommand != NULL)
00424               {
00425                      short src = 1;
00426                      short dest = 0;
00427                      while (src <= stringLen)
00428                             CPlugin::sInstallCommand[dest++] = (*string)[src++];
00429                      CPlugin::sInstallCommand[dest++] = 0;
00430               }
00431        }
00432        ReleaseResource(string);
00433 
00434        // Get default plug-in page URL
00435        string = Get1Resource('STR ', rDefaultPluginURL);
00436        if (string && *string)
00437        {
00438               short stringLen = (*string)[0];
00439               CPlugin::sDefaultPage = (char*)NPN_MemAlloc(stringLen + 1);
00440               if (CPlugin::sDefaultPage != NULL)
00441               {
00442                      short src = 1;
00443                      short dest = 0;
00444                      while (src <= stringLen)
00445                             CPlugin::sDefaultPage[dest++] = (*string)[src++];
00446                      CPlugin::sDefaultPage[dest++] = 0;
00447               }
00448        }
00449        ReleaseResource(string);
00450 
00451        // Get javascript plug-in page URL
00452        string = Get1Resource('STR ', rJavaScriptPageURL);
00453        if (string && *string)
00454        {
00455               short stringLen = (*string)[0];
00456               CPlugin::sJavaScriptPage = (char*)NPN_MemAlloc(stringLen + 1);
00457               if (CPlugin::sJavaScriptPage != NULL)
00458               {
00459                      short src = 1;
00460                      short dest = 0;
00461                      while (src <= stringLen)
00462                             CPlugin::sJavaScriptPage[dest++] = (*string)[src++];
00463                      CPlugin::sJavaScriptPage[dest++] = 0;
00464               }
00465        }
00466        ReleaseResource(string);
00467 
00468        UseResFile(saveResFile);
00469 
00470        if (!sRunningOnOSX) // We'll make some CFPreferences the first time we have to on OS X
00471        {
00472               ProcessSerialNumber psn;
00473               ProcessInfoRec       info;
00474               FSSpec fsTheApp;
00475               SInt16 wResFile;
00476               OSErr  wErr;
00477               
00478               psn.highLongOfPSN = 0;
00479               psn.lowLongOfPSN  = kCurrentProcess;
00480 
00481               info.processInfoLength = sizeof(ProcessInfoRec);
00482               info.processName = nil;
00483               info.processAppSpec = &fsTheApp;
00484               wErr = ::GetProcessInformation(&psn, &info);
00485               if (wErr == noErr) {
00486                      wErr = FSMakeFSSpec(fsTheApp.vRefNum, fsTheApp.parID, "\p:Plug-ins:Default Plug-in Data", &sDataFileSpec);
00487                      if (wErr == fnfErr) {
00488                             FSpCreateResFile(&sDataFileSpec, 'MOSS', 'BINA', smSystemScript);
00489                             wResFile = FSpOpenResFile(&CPlugin::sDataFileSpec, fsRdWrPerm);
00490                             if (wResFile != -1) {
00491                                    // create a STR# with 0 entires (i.e. only a count)
00492                                    string = NewHandleClear(sizeof(SInt16));
00493                                    AddResource(string, 'STR#', rTypeListStrings, "\p");
00494                                    UpdateResFile(wResFile);
00495                                    ReleaseResource(string);
00496                             }
00497                             FSClose(wResFile);
00498                      }
00499               }
00500        }
00501 
00502        return NPERR_NO_ERROR;
00503 }
00504 
00505 
00506 //------------------------------------------------------------------------------------
00507 // CPlugin::Shutdown:
00508 //------------------------------------------------------------------------------------
00509 void CPlugin::Shutdown()
00510 {
00511        if (CPlugin::sIconHandle != NULL)
00512               ::ReleaseResource((Handle) CPlugin::sIconHandle);
00513        if (CPlugin::sHandCursor != NULL)
00514               ::ReleaseResource((Handle) CPlugin::sHandCursor);
00515        
00516        if (CPlugin::sAltText != NULL)
00517               NPN_MemFree(CPlugin::sAltText);
00518        if (CPlugin::sInstallCommand != NULL)
00519               NPN_MemFree(CPlugin::sInstallCommand);
00520        if (CPlugin::sDefaultPage != NULL)
00521               NPN_MemFree(CPlugin::sDefaultPage);
00522        if(CPlugin::sRefreshText != NULL)
00523               NPN_MemFree(CPlugin::sRefreshText);
00524 }
00525 
00526 
00527 //------------------------------------------------------------------------------------
00528 // CPlugin::Constructor:
00529 //------------------------------------------------------------------------------------
00530 void CPlugin::Constructor(NPP instance, NPMIMEType type, uint16 mode, int16 argc, char* argn[], char* argv[])
00531 {
00532        fWindow = NULL;
00533        fPageURL = NULL;
00534        fFileURL = NULL;
00535        fInstance = instance;
00536        fMode = mode;    // Mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
00537        fAskedLoadURL = false;
00538        fUserInstalledPlugin = false;
00539        
00540        // Save a copy of our mime type string
00541        short typeLength = strlen(type);
00542        fType = (char*)NPN_MemAlloc(typeLength+1);
00543        if (fType != NULL)
00544               strcpy(fType, type);
00545        
00546        // Make a handy region for use in FocusDraw
00547        fSaveClip = NewRgn();
00548 
00549        // determine if the plugin is specified as HIDDEN
00550        if(IsPluginHidden(argc, argn, argv))
00551               fHiddenPlugin = true;
00552        else
00553               fHiddenPlugin = false;
00554 
00555        // Get some information about our environment
00556        NPN_GetValue(fInstance, NPNVisOfflineBool, (void *)&m_bOffline);
00557        NPN_GetValue(fInstance, NPNVjavascriptEnabledBool, (void *)&m_bJavaScript);
00558 
00559        // Figure out what URL we will go to
00560        DetermineURL(argc, argn, argv);
00561 }
00562 
00563 
00564 //------------------------------------------------------------------------------------
00565 // CPlugin::Destructor:
00566 //------------------------------------------------------------------------------------
00567 void CPlugin::Destructor()
00568 {
00569        if (fSaveClip != NULL)
00570               DisposeRgn(fSaveClip);
00571        
00572        if (fType != NULL)
00573               NPN_MemFree(fType);
00574        if (fFileURL != NULL)
00575               NPN_MemFree(fFileURL);
00576        if (fPageURL != NULL)
00577               NPN_MemFree(fPageURL);
00578 }             
00579 
00580 
00581 
00582 //------------------------------------------------------------------------------------
00583 // CPlugin::SetWindow:
00584 //------------------------------------------------------------------------------------
00585 void CPlugin::SetWindow(NPWindow* window)
00586 {
00587        fWindow = window;
00588 }
00589 
00590 
00591 //------------------------------------------------------------------------------------
00592 // CPlugin::Print:
00593 // 
00594 // To print, we need to retrieve the printing window from the printInfo,
00595 // temporarily make it our window, draw into it, and restore the window.
00596 //
00597 //------------------------------------------------------------------------------------
00598 void CPlugin::Print(NPPrint* printInfo)
00599 {
00600        NPWindow* printWindow = &(printInfo->print.embedPrint.window);
00601        
00602        NPWindow* oldWindow = fWindow;
00603        fWindow = printWindow;
00604 
00605        if (FocusDraw())
00606        {
00607               Draw(kUnhilited);
00608               RestoreDraw();
00609        }
00610        
00611        fWindow = oldWindow;
00612 }
00613 
00614 
00615 //------------------------------------------------------------------------------------
00616 // CPlugin::HandleEvent:
00617 //------------------------------------------------------------------------------------
00618 Boolean CPlugin::HandleEvent(EventRecord* ev)
00619 {
00620        Boolean eventHandled = false;
00621        
00622        switch (ev->what)
00623        {
00624               case mouseDown:
00625                      MouseDown();
00626                      eventHandled = true;
00627                      break;
00628                      
00629               case updateEvt:
00630                      if (FocusDraw()) {
00631                             Draw(kUnhilited);
00632                             RestoreDraw();
00633                      }
00634                      eventHandled = true;
00635                      break;
00636                      
00637               case NPEventType_AdjustCursorEvent:
00638                      if (CPlugin::sHandCursor != NULL)
00639                             SetCursor(*CPlugin::sHandCursor);
00640                      if (fUserInstalledPlugin) {
00641                             if (CPlugin::sRefreshText != NULL)
00642                                    NPN_Status(fInstance, CPlugin::sRefreshText);                         
00643                      } else {
00644                             if (CPlugin::sAltText != NULL)
00645                                    NPN_Status(fInstance, CPlugin::sAltText);
00646                      }
00647                      eventHandled = true;
00648                      break;
00649                      
00650               case nullEvent:
00651                      //
00652                      // NOTE: We have to wait until idle time
00653                      // to ask the user if they want to visit
00654                      // the URL to avoid reentering XP code.
00655                      //
00656                      if (!fAskedLoadURL) {
00657                             if (CheckMimeTypes())
00658                                    AskAndLoadURL();
00659                             fAskedLoadURL = true;
00660                      }
00661                      break;
00662               default:
00663                      break;
00664        }
00665               
00666        return eventHandled;
00667 }
00668 
00669 
00670 
00671 //------------------------------------------------------------------------------------
00672 // CPlugin::Draw:
00673 //------------------------------------------------------------------------------------
00674 void CPlugin::Draw(HiliteState hilite)
00675 {
00676        UInt8         *pTheText;
00677        SInt32        height = fWindow->height;
00678        SInt32        width = fWindow->width;
00679        SInt32        centerX = (width) >> 1;
00680        SInt32        centerY = (height) >> 1;
00681        Rect          drawRect;
00682        RGBColor      black = { 0x0000, 0x0000, 0x0000 };
00683        RGBColor      white = { 0xFFFF, 0xFFFF, 0xFFFF };
00684        RGBColor      hiliteColor = { 0x0000, 0x0000, 0x0000 };
00685        short         transform;
00686 
00687        drawRect.top = 0;
00688        drawRect.left = 0;
00689        drawRect.bottom = height;
00690        drawRect.right = width;
00691 
00692        if (height < 4 && width < 4)
00693               return;
00694               
00695        PenNormal();
00696        RGBForeColor(&black);
00697        RGBBackColor(&white);
00698 
00699        Pattern qdWhite;
00700        FillRect(&drawRect, GetQDGlobalsWhite(&qdWhite));
00701 
00702        if (hilite == kHilited) {
00703               hiliteColor.red = 0xFFFF;
00704               transform = ttSelected;
00705        } else {
00706               hiliteColor.blue = 0xFFFF;
00707               transform = ttNone;
00708        }
00709 
00710        RGBForeColor(&hiliteColor);
00711        FrameRect(&drawRect);
00712        
00713        if (height > 32 && width > 32 && CPlugin::sIconHandle != NULL)
00714        {
00715               drawRect.top = centerY - 16;
00716               drawRect.bottom = centerY + 16;
00717               drawRect.left = centerX - 16;
00718               drawRect.right = centerX + 16;
00719               PlotCIconHandle(&drawRect, atAbsoluteCenter, transform, CPlugin::sIconHandle);
00720        }
00721 
00722        if (fUserInstalledPlugin) {
00723               pTheText = (unsigned char*)CPlugin::sRefreshText;
00724        } else {
00725               pTheText = (unsigned char*)CPlugin::sAltText;
00726        }
00727               DrawString(pTheText, width, height, centerX, drawRect);
00728 }
00729 
00730 
00731 
00732 //------------------------------------------------------------------------------------
00733 // CPlugin::MouseDown:
00734 //
00735 // Track the click in our plugin by drawing the icon enabled or disabled
00736 // as the user moves the mouse in and out with the button held down.  If
00737 // they let up the mouse while still inside, get the URL.
00738 //
00739 //------------------------------------------------------------------------------------
00740 void  CPlugin::MouseDown()
00741 {
00742        if (FocusDraw())     
00743        {
00744               Draw(kHilited);
00745               Boolean inside = true;
00746   
00747               // evil CPU-hogging loop on Mac OS X!
00748               while (StillDown())
00749               {
00750                      Point localMouse;
00751                      GetMouse(&localMouse);
00752                      Boolean insideNow = ::PtInRect(localMouse, &fRevealedRect);
00753 
00754                      if (insideNow != inside)
00755                      {
00756                             Draw(insideNow ? kHilited : kUnhilited);
00757                             inside = insideNow;
00758                      }
00759               }
00760               
00761               if (inside) {
00762                      Draw(kUnhilited);
00763                      if (!fUserInstalledPlugin)
00764                             AskAndLoadURL();
00765                      else
00766                             RefreshPluginPage();
00767               }
00768 
00769               RestoreDraw();
00770        }
00771 }
00772 
00773 
00774 //------------------------------------------------------------------------------------
00775 // CPlugin::FocusDraw:
00776 //------------------------------------------------------------------------------------
00777 Boolean CPlugin::FocusDraw()
00778 {
00779        if (fWindow == NULL)
00780               return false;
00781               
00782        NP_Port* npport = (NP_Port*) fWindow->window;
00783        CGrafPtr ourPort = npport->port;
00784        
00785        if (fWindow->clipRect.left < fWindow->clipRect.right)
00786        {
00787               GetPort(&fSavePort);
00788               SetPort((GrafPtr) ourPort);
00789               Rect portRect;
00790               GetPortBounds(ourPort, &portRect);
00791               fSavePortTop = portRect.top;
00792               fSavePortLeft = portRect.left;
00793               GetClip(fSaveClip);
00794               
00795               fRevealedRect.top = fWindow->clipRect.top + npport->porty;
00796               fRevealedRect.left = fWindow->clipRect.left + npport->portx;
00797               fRevealedRect.bottom = fWindow->clipRect.bottom + npport->porty;
00798               fRevealedRect.right = fWindow->clipRect.right + npport->portx;
00799               SetOrigin(npport->portx, npport->porty);
00800               ClipRect(&fRevealedRect);
00801 
00802               return true;
00803        }
00804        else
00805               return false;
00806 }
00807 
00808 
00809 //------------------------------------------------------------------------------------
00810 // CPlugin::RestoreDraw:
00811 //------------------------------------------------------------------------------------
00812 void CPlugin::RestoreDraw()
00813 {
00814        SetOrigin(fSavePortLeft, fSavePortTop);
00815        SetClip(fSaveClip);
00816        SetPort(fSavePort);
00817 }
00818 
00819 
00820 
00821 //------------------------------------------------------------------------------------
00822 // CPlugin::DetermineURL:
00823 //
00824 // Get a URL from either the parameters passed from the EMBED.
00825 // Append "?" and our mime type and save for later use.
00826 //
00827 //------------------------------------------------------------------------------------
00828 void CPlugin::DetermineURL(int16 argc, char* argn[], char* argv[])
00829 {
00830        char*  url;
00831        SInt32 additionalLength = 0;
00832        SInt32 i;
00833 
00834        // Appended to the URL will be a "?" and the mime type of this instance.  This lets the server
00835        // do something intelligent with a CGI script.
00836 
00837        if (fType != NULL)
00838               additionalLength += (strlen(fType) + 1);         // Add 1 for '?'
00839 
00840        // The page designer can specify a URL where the plugin for this type can be downloaded.  Here
00841        // we scan the arguments for this attribute and save it away if we
00842        // find it for later use by LoadPluginURL().
00843        //
00844        for (i = 0; i < argc; i++) {
00845               if ((strcasecmp(argn[i], "PLUGINSPAGE") == 0) || (strcasecmp(argn[i], "CODEBASE") == 0)) {
00846                      url = argv[i];
00847                      fPageURL = (char*)NPN_MemAlloc(strlen(url) + 1 + additionalLength);   // Add 1 for '\0'
00848                      if (fPageURL != NULL) {
00849                             if (additionalLength > 0) {
00850                                    sprintf(fPageURL, "%s?%s", url, fType);
00851                             } else {
00852                                    strcpy(fPageURL, url);      
00853                             }
00854                      }
00855                      break;
00856               } else if ((strcasecmp(argn[i], "PLUGINURL") == 0) || (strcasecmp(argn[i], "CLASSID") == 0)) {
00857                      url = argv[i];
00858                      if (CPlugin::sInstallCommand != NULL) {
00859                             // Allocate a new string
00860                             fFileURL = (char*)NPN_MemAlloc(strlen(CPlugin::sInstallCommand) + 1 + strlen(url)); 
00861                             if (fFileURL != NULL)
00862                                    sprintf(fFileURL, CPlugin::sInstallCommand, url);
00863                      }
00864                      break;
00865               }
00866        }
00867 }
00868 
00869 
00870 
00871 //------------------------------------------------------------------------------------
00872 // CPlugin::MakeDefaultURL:
00873 //
00874 // Get a URL from our resources.  Append "?" and our mime type and save for later use.
00875 //
00876 //------------------------------------------------------------------------------------
00877 char *CPlugin::MakeDefaultURL(void)
00878 {
00879        char   *pDefURL = NULL;
00880        SInt32 additionalLength = 0;
00881 
00882        // Appended to the URL will be a "?" and the mime type of this instance.  This lets the server
00883        // do something intelligent with a CGI script.
00884 
00885        if (fType != NULL)
00886               additionalLength += (strlen(fType) + 1);         // Add 1 for '?'
00887 
00888        if (!m_bJavaScript) {
00889               if (CPlugin::sDefaultPage != NULL) {
00890                      pDefURL = (char*)NPN_MemAlloc(strlen(CPlugin::sDefaultPage) + 1 + additionalLength);
00891                      if (pDefURL != NULL) {
00892                             if (additionalLength > 0) {
00893                                    sprintf(pDefURL, "%s?%s", CPlugin::sDefaultPage, fType);
00894                             } else {
00895                                    strcpy(pDefURL, CPlugin::sDefaultPage);   
00896                             }
00897                      }
00898               }
00899        } else {
00900               if (CPlugin::sJavaScriptPage != NULL) {
00901                      pDefURL = (char*)NPN_MemAlloc(strlen(szPluginFinderCommandBeginning) +
00902                                           strlen(CPlugin::sJavaScriptPage) +
00903                                           additionalLength + strlen(szPluginFinderCommandEnd) + 1);
00904                      if (pDefURL != NULL) {
00905                             sprintf(pDefURL, "%s%s%s%s", szPluginFinderCommandBeginning,
00906                                           CPlugin::sJavaScriptPage, fType, szPluginFinderCommandEnd);
00907                      }
00908               }
00909        }
00910        return(pDefURL);
00911 }
00912 
00913 
00914 
00915 //------------------------------------------------------------------------------------
00916 // CPlugin::AddMimeTypeToList:
00917 //
00918 // Check the mime type of this instance against our list
00919 // of types weÕve seen before.  If we find our type in the
00920 // list, return false; otherwise, return true.
00921 //
00922 // type 'STR#' {
00923 //      integer = $$Countof(StringArray);
00924 //      array StringArray {
00925 //              pstring;
00926 //      };
00927 //
00928 //------------------------------------------------------------------------------------
00929 void CPlugin::AddMimeTypeToList(StringPtr cTypeString)
00930 {
00931        if (sRunningOnOSX)
00932        {
00933               CFStringRef          pluginKey     = CFSTR("DefaultPluginSeenTypes"); // don't release this
00934               CFStringRef          mimeType      = ::CFStringCreateWithPascalString(kCFAllocatorDefault, cTypeString, kCFStringEncodingASCII);
00935               CFArrayRef           prefsList     = (CFArrayRef)::CFPreferencesCopyAppValue(pluginKey, kCFPreferencesCurrentApplication);
00936               Boolean                     foundType     = false;
00937 
00938               if (prefsList == NULL)
00939               {
00940                      CFStringRef stringArray[1];
00941                      stringArray[0] = mimeType;
00942                      
00943                      prefsList = ::CFArrayCreate(kCFAllocatorDefault, (const void **)stringArray, 1, &kCFTypeArrayCallBacks);
00944                      if (prefsList)
00945                      {
00946                             ::CFPreferencesSetAppValue(pluginKey, prefsList, kCFPreferencesCurrentApplication);
00947                             ::CFRelease(prefsList);
00948                      }
00949               }
00950               else
00951               {
00952                      if (::CFGetTypeID(prefsList) == ::CFArrayGetTypeID())
00953                      {
00954                             // first make sure it's not in the list
00955                             CFIndex count = ::CFArrayGetCount(prefsList);
00956                             for (CFIndex i = 0; i < count; i ++)
00957                             {
00958                                    CFStringRef item = (CFStringRef)::CFArrayGetValueAtIndex(prefsList, i); // does not retain
00959                                    if (item &&
00960                                           (::CFGetTypeID(item) == ::CFStringGetTypeID()) &&
00961                                           (::CFStringCompareWithOptions(item, mimeType,
00962                                                         CFRangeMake(0, ::CFStringGetLength(item)), kCFCompareCaseInsensitive) == kCFCompareEqualTo))
00963                                    {
00964                                           foundType = true;
00965                                           break;
00966                                    }
00967                             }
00968                             
00969                             if (!foundType && !fHiddenPlugin)
00970                             {
00971                                    CFMutableArrayRef typesArray = ::CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, (CFArrayRef)prefsList);
00972                                    if (typesArray)
00973                                    {
00974                                           ::CFArrayAppendValue(typesArray, mimeType);
00975                                           ::CFPreferencesSetAppValue(pluginKey, typesArray, kCFPreferencesCurrentApplication);
00976                                    }
00977                             }
00978                      }
00979                      ::CFRelease(prefsList);
00980               }
00981               ::CFRelease(mimeType);
00982        }
00983        else
00984        {
00985               Handle hTypeList;
00986               SInt32 dwCount;
00987               SInt32 index;
00988               Str255 oldType;
00989               SInt16 wResFile;
00990               Boolean failedToFind = true;
00991 
00992               wResFile = FSpOpenResFile(&CPlugin::sDataFileSpec, fsRdWrPerm);
00993               if (wResFile != -1) {
00994                      hTypeList = Get1Resource('STR#', rTypeListStrings);
00995                      if (hTypeList != NULL) {
00996                             dwCount = **((short **)hTypeList);
00997                             
00998                             // First make sure it's not already in the list.
00999                             for (index = 1; index <= dwCount; index++) {
01000                                    GetIndString(oldType, rTypeListStrings, index);
01001 
01002                                    // if the mimetype already exists in our list, or the plugin is NOT hidden,
01003                                    // don't bring up the dialog box
01004                                    if (EqualString(cTypeString, oldType, true, true) && !fHiddenPlugin) {
01005                                           failedToFind = false;
01006                                           break;                                           // Found a match, so bail out!
01007                                    }
01008                             }
01009                             if (failedToFind) {
01010                                    // Grow the string list handle
01011                                    Size itsSize = GetHandleSize(hTypeList);
01012                                    Size typeSize = cTypeString[0] + 1;
01013                                    SetHandleSize(hTypeList, itsSize + typeSize);
01014                             
01015                                    // Increment the count of strings in the list
01016                                    (**((short**)hTypeList)) = (short)(++dwCount);   
01017 
01018                                    // Copy the data from our string into the handle
01019                                    long dwCount = Munger(hTypeList, itsSize, NULL, typeSize, cTypeString, typeSize);
01020 
01021                                    // Mark the resource as changed so it will be written out
01022                                    if (dwCount > 0) {
01023                                           ChangedResource(hTypeList);
01024                                           UpdateResFile(wResFile);
01025                                    }
01026                             }
01027                             ReleaseResource(hTypeList);
01028                      }
01029                      FSClose(wResFile);
01030               }
01031        }
01032 }
01033 
01034 
01035 
01036 //------------------------------------------------------------------------------------
01037 // CPlugin::CheckMimeTypes:
01038 //
01039 // Check the mime type of this instance against our list
01040 // of types weÕve seen before.  If we find our type in the
01041 // list, return false; otherwise, return true.
01042 //
01043 // type 'STR#' {
01044 //      integer = $$Countof(StringArray);
01045 //      array StringArray {
01046 //              pstring;
01047 //      };
01048 //
01049 //------------------------------------------------------------------------------------
01050 Boolean CPlugin::CheckMimeTypes()
01051 {
01052        Boolean failedToFind = true;
01053 
01054        if (sRunningOnOSX)
01055        {
01056               CFStringRef          pluginKey = CFSTR("DefaultPluginSeenTypes"); // don't release this
01057               CFStringRef          mimeType  = ::CFStringCreateWithCString(kCFAllocatorDefault, fType, kCFStringEncodingASCII);
01058               CFArrayRef           prefsList = (CFArrayRef)::CFPreferencesCopyAppValue(pluginKey, kCFPreferencesCurrentApplication);
01059               if (prefsList)
01060               {
01061                      if (::CFGetTypeID(prefsList) == ::CFArrayGetTypeID())
01062                      {
01063                             CFIndex count = ::CFArrayGetCount(prefsList);
01064                             for (CFIndex i = 0; i < count; i ++)
01065                             {
01066                                    CFStringRef item = (CFStringRef)::CFArrayGetValueAtIndex(prefsList, i); // does not retain
01067                                    if (item &&
01068                                           (::CFGetTypeID(item) == ::CFStringGetTypeID()) &&
01069                                           (::CFStringCompareWithOptions(item, mimeType,
01070                                                         CFRangeMake(0, ::CFStringGetLength(item)), kCFCompareCaseInsensitive) == kCFCompareEqualTo))
01071                                    {
01072                                           failedToFind = false;
01073                                           break;
01074                                    }
01075                             }
01076                      }
01077                      ::CFRelease(prefsList);
01078               }
01079               ::CFRelease(mimeType);
01080        }
01081        else
01082        {
01083               Handle hTypeList;
01084               SInt32 index;
01085               Str255 oldType;
01086               Str255 ourType;
01087               SInt16 wResFile;
01088 
01089               wResFile = FSpOpenResFile(&CPlugin::sDataFileSpec, fsRdPerm);
01090               if (wResFile != -1) {
01091                      hTypeList = Get1Resource('STR#', rTypeListStrings);
01092                      if (hTypeList != NULL) {
01093                             // Convert the mime-type C string to a Pascal string.
01094                             index = strlen(fType);
01095                             if (index > 255) {          // don't blow out the Str255
01096                                    index = 255;
01097                             }
01098                             BlockMoveData(fType, &ourType[1], index);
01099                             ourType[0] = index;
01100 
01101                             short count = **((short **)hTypeList);
01102                             
01103                             // Iterate through all the strings in the list.
01104                             for (index = 1; index <= count; index++) {
01105                                    GetIndString(oldType, rTypeListStrings, index);
01106 
01107                                    // if the mimetype already exists in our list, or the plugin is NOT hidden,
01108                                    // don't bring up the dialog box
01109                                    if (EqualString(ourType, oldType, true, true) && !fHiddenPlugin) {
01110                                           failedToFind = false;
01111                                           break;                                           // Found a match, so bail out!
01112                                    }
01113                             }
01114                             ReleaseResource(hTypeList);
01115                      }
01116                      FSClose(wResFile);
01117               }
01118        }
01119        return(failedToFind);
01120 }
01121 
01122 
01123 
01124 //------------------------------------------------------------------------------------
01125 // CPlugin::AskAndLoadURL:
01126 //------------------------------------------------------------------------------------
01127 void CPlugin::AskAndLoadURL()
01128 {
01129        char   *pTheURL;
01130        SInt32 dwLen;
01131        Str255 ourType;
01132 
01133        if (!m_bOffline) {
01134               // Convert the mime-type C string to a Pascal string.
01135               dwLen = strlen(fType);
01136               if (dwLen > 255) {          // don't blow out the Str255
01137                      dwLen = 255;
01138               }
01139               BlockMoveData(fType, &ourType[1], dwLen);
01140               ourType[0] = dwLen;
01141 
01142               // NOTE: We need to set the cursor because almost always we will have set it to the
01143               // hand cursor before we get here.
01144               Cursor qdArrow;
01145               SetCursor(GetQDGlobalsArrow(&qdArrow));
01146 
01147               // Now that weÕve queried the user about this mime type,
01148               // add it to our list so we wonÕt bug them again.
01149               AddMimeTypeToList(ourType);
01150               
01151               //
01152               // If the user clicked "Get the Plug-in", either execute the
01153               // JavaScript file-installation URL, or ask Netscape to open
01154               // a new window with the page URL.  The title of the window
01155               // is arbitrary since it has nothing to do with the actual
01156               // window title shown to the user (itÕs only used internally).
01157               //
01158               NPN_PushPopupsEnabledState(fInstance, true);
01159 
01160               if (fFileURL != NULL) {
01161                      (void) NPN_GetURL(fInstance, fFileURL, "_current");
01162               } else if (fPageURL != NULL) {
01163                      NPN_GetURL(fInstance, fPageURL, "_blank");
01164               } else {
01165                      pTheURL = MakeDefaultURL();
01166                      if (!m_bJavaScript) {
01167                             NPN_GetURL(fInstance, pTheURL, "_blank");
01168                      } else {
01169                             NPN_GetURL(fInstance, pTheURL, NULL);
01170                      }
01171                      NPN_MemFree(pTheURL);
01172               }
01173 
01174               NPN_PopPopupsEnabledState(fInstance);
01175 
01176               fUserInstalledPlugin = true;
01177               if (FocusDraw()) {
01178                      Draw(kUnhilited);
01179                      RestoreDraw();
01180               }
01181        }
01182 }
01183 
01184 void CPlugin::RefreshPluginPage()
01185 {
01186        (void) NPN_GetURL(fInstance, "javascript:navigator.plugins.refresh(true);", "_self");
01187 }
01188 
01189 void CPlugin::DrawString(const unsigned char* text, short width, short height, short centerX, Rect drawRect)
01190 {
01191        short length, textHeight, textWidth;
01192  
01193        if(text == NULL)
01194               return;
01195        
01196        length = strlen((char*)text);
01197        TextFont(20);
01198        TextFace(underline);
01199        TextMode(srcCopy);
01200        TextSize(10);
01201        
01202        FontInfo fontInfo;
01203        GetFontInfo(&fontInfo);
01204 
01205        textHeight = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
01206        textWidth = TextWidth(text, 0, length);
01207               
01208        if (width > textWidth && height > textHeight + 32)
01209        {
01210               MoveTo(centerX - (textWidth >> 1), drawRect.bottom + textHeight);
01211               DrawText(text, 0, length);
01212        }             
01213 }
01214 
01215 Boolean CPlugin::IsPluginHidden(int16 argc, char* argn[], char* argv[])
01216 {
01217        int i;
01218        for(i=0; i<argc; i++)
01219        {
01220               if(!strcasecmp(argn[i], "HIDDEN"))
01221                      if(!strcasecmp(argv[i], "TRUE"))
01222                             return true;
01223        }
01224        return false;
01225 }