/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #define INCL_GPI #define INCL_WIN #include #include #include "npnulos2.h" #include "plugin.h" #include "utils.h" #include "dialogs.h" #include "dbg.h" #include "nsIServiceManager.h" #include "nsIPref.h" nsIServiceManager * gServiceManager = NULL; static char szNullPluginWindowClassName[] = CLASS_NULL_PLUGIN; MRESULT EXPENTRY PluginWndProc(HWND, ULONG, MPARAM, MPARAM); static char szDefaultPluginFinderURL[] = DEFAULT_PLUGINFINDER_URL; static char szPageUrlForJavaScript[] = PAGE_URL_FOR_JAVASCRIPT; static char szPageUrlForJVM[] = JVM_SMARTUPDATE_URL; //static char szPluginFinderCommandFormatString[] = PLUGINFINDER_COMMAND; static char szPluginFinderCommandBeginning[] = PLUGINFINDER_COMMAND_BEGINNING; static char szPluginFinderCommandEnd[] = PLUGINFINDER_COMMAND_END; BOOL RegisterNullPluginWindowClass() { return WinRegisterClass( (HAB)0, szNullPluginWindowClassName, (PFNWP)PluginWndProc, 0, sizeof(ULONG)); } void UnregisterNullPluginWindowClass() { } /*********************************************/ /* */ /* CPlugin class implementation */ /* */ /*********************************************/ CPlugin::CPlugin(HMODULE hInst, NPP pNPInstance, SHORT wMode, NPMIMEType pluginType, PSZ szPageURL, PSZ szFileURL, PSZ szFileExtension, BOOL bHidden) : m_hInst(hInst), m_pNPInstance(pNPInstance), m_wMode(wMode), m_hWnd(NULL), m_hWndParent(NULL), m_hIcon(NULL), m_szURLString(NULL), m_szCommandMessage(NULL), m_bWaitingStreamFromPFS(FALSE), m_PFSStream(NULL), m_bHidden(bHidden), m_pNPMIMEType(NULL), m_szPageURL(NULL), m_szFileURL(NULL), m_szFileExtension(NULL), m_hWndDialog(NULL), m_bOnline(TRUE), m_bJava(TRUE), m_bJavaScript(TRUE), m_bSmartUpdate(TRUE) { dbgOut1("CPlugin::CPlugin()"); assert(m_hInst != NULL); assert(m_pNPInstance != NULL); if(pluginType && *pluginType) { m_pNPMIMEType = (NPMIMEType)new char[strlen((PSZ)pluginType) + 1]; if(m_pNPMIMEType != NULL) strcpy((PSZ)m_pNPMIMEType, pluginType); } if(szPageURL && *szPageURL) { m_szPageURL = new char[strlen(szPageURL) + 1]; if(m_szPageURL != NULL) strcpy(m_szPageURL, szPageURL); } if(szFileURL && *szFileURL) { m_szFileURL = new char[strlen(szFileURL) + 1]; if(m_szFileURL != NULL) strcpy(m_szFileURL, szFileURL); } if(szFileExtension && *szFileExtension) { m_szFileExtension = new char[strlen(szFileExtension) + 1]; if(m_szFileExtension != NULL) strcpy(m_szFileExtension, szFileExtension); } m_hIcon = WinLoadPointer(HWND_DESKTOP, m_hInst, IDI_PLUGICON); char szString[1024] = {'\0'}; WinLoadString((HAB)0, m_hInst, IDS_CLICK_TO_GET, sizeof(szString), szString); if(*szString) { m_szCommandMessage = new char[strlen(szString) + 1]; if(m_szCommandMessage != NULL) strcpy(m_szCommandMessage, szString); } } CPlugin::~CPlugin() { dbgOut1("CPlugin::~CPlugin()"); if(m_pNPMIMEType != NULL) { delete [] m_pNPMIMEType; m_pNPMIMEType = NULL; } if(m_szPageURL != NULL) { delete [] m_szPageURL; m_szPageURL = NULL; } if(m_szFileURL != NULL) { delete [] m_szFileURL; m_szFileURL = NULL; } if(m_szFileExtension != NULL) { delete [] m_szFileExtension; m_szFileExtension = NULL; } if(m_szURLString != NULL) { delete [] m_szURLString; m_szURLString = NULL; } if(m_hIcon != NULL) { WinDestroyPointer(m_hIcon); m_hIcon = NULL; } if(m_szCommandMessage != NULL) { delete [] m_szCommandMessage; m_szCommandMessage = NULL; } } BOOL CPlugin::init(HWND hWndParent) { dbgOut1("CPlugin::init()"); nsISupports * sm = NULL; nsIPref * nsPrefService = NULL; PRBool bSendUrls = PR_FALSE; // default to false if problem getting pref // note that Mozilla will add reference, so do not forget to release NPN_GetValue(NULL, NPNVserviceManager, &sm); // do a QI on the service manager we get back to ensure it's the one we are expecting if(sm) { sm->QueryInterface(NS_GET_IID(nsIServiceManager), (void**)&gServiceManager); NS_RELEASE(sm); } if (gServiceManager) { // get service using its contract id and use it to allocate the memory gServiceManager->GetServiceByContractID(NS_PREF_CONTRACTID, NS_GET_IID(nsIPref), (void **)&nsPrefService); if(nsPrefService) { nsPrefService->GetBoolPref("application.use_ns_plugin_finder", &bSendUrls); NS_RELEASE(nsPrefService); } } m_bSmartUpdate = bSendUrls; if(!m_bHidden) { assert(WinIsWindow((HAB)0, hWndParent)); if(WinIsWindow((HAB)0, hWndParent)) m_hWndParent = hWndParent; RECTL rcParent; WinQueryWindowRect(m_hWndParent, &rcParent); m_hWnd = WinCreateWindow(m_hWndParent, szNullPluginWindowClassName, "NULL Plugin", 0, 0,0, rcParent.xRight, rcParent.yTop, m_hWndParent, HWND_TOP, 255, (PVOID)this, 0); WinSetPresParam(m_hWnd, PP_FONTNAMESIZE, 10, (PVOID)"9.WarpSans"); assert(m_hWnd != NULL); if((m_hWnd == NULL) || (!WinIsWindow((HAB)0, m_hWnd))) return FALSE; // UpdateWindow(m_hWnd); WinShowWindow(m_hWnd, TRUE); } if(IsNewMimeType((PSZ)m_pNPMIMEType) || m_bHidden) showGetPluginDialog(); return TRUE; } void CPlugin::shut() { dbgOut1("CPlugin::shut()"); if(m_hWndDialog != NULL) { WinDismissDlg(m_hWndDialog, DID_CANCEL); m_hWndDialog = NULL; } if(m_hWnd != NULL) { WinDestroyWindow(m_hWnd); m_hWnd = NULL; } // we should release the service manager NS_IF_RELEASE(gServiceManager); gServiceManager = NULL; } HWND CPlugin::getWindow() { return m_hWnd; } BOOL CPlugin::useDefaultURL_P() { if((m_szPageURL == NULL) && (m_szFileURL == NULL)) return TRUE; else return FALSE; } BOOL CPlugin::doSmartUpdate_P() { // due to current JavaScript problems never do it smart for now 5.1.98 return FALSE; if(m_bOnline && m_bJava && m_bJavaScript && m_bSmartUpdate && useDefaultURL_P()) return TRUE; else return FALSE; } PSZ CPlugin::createURLString() { if(m_szURLString != NULL) { delete [] m_szURLString; m_szURLString = NULL; } // check if there is file URL first if(!m_bSmartUpdate && m_szFileURL != NULL) { m_szURLString = new char[strlen(m_szFileURL) + 1]; if(m_szURLString == NULL) return NULL; strcpy(m_szURLString, m_szFileURL); return m_szURLString; } // if not get the page URL char * szAddress = NULL; char *urlToOpen = NULL; char contentTypeIsJava = 0; if (NULL != m_pNPMIMEType) { contentTypeIsJava = (0 == strcmp("application/x-java-vm", m_pNPMIMEType)) ? 1 : 0; } if(!m_bSmartUpdate && m_szPageURL != NULL && !contentTypeIsJava) { szAddress = new char[strlen(m_szPageURL) + 1]; if(szAddress == NULL) return NULL; strcpy(szAddress, m_szPageURL); m_szURLString = new char[strlen(szAddress) + 1 + strlen((PSZ)m_pNPMIMEType) + 1]; if(m_szURLString == NULL) return NULL; // Append the MIME type to the URL sprintf(m_szURLString, "%s?%s", szAddress, (PSZ)m_pNPMIMEType); } else // default { if(!m_bSmartUpdate) { urlToOpen = szDefaultPluginFinderURL; if (contentTypeIsJava) { urlToOpen = szPageUrlForJVM; } szAddress = new char[strlen(urlToOpen) + 1]; if(szAddress == NULL) return NULL; strcpy(szAddress, urlToOpen); m_szURLString = new char[strlen(szAddress) + 10 + strlen((PSZ)m_pNPMIMEType) + 1]; if(m_szURLString == NULL) return NULL; // Append the MIME type to the URL sprintf(m_szURLString, "%s?mimetype=%s", szAddress, (PSZ)m_pNPMIMEType); } else { urlToOpen = szPageUrlForJavaScript; if (contentTypeIsJava) { urlToOpen = szPageUrlForJVM; } // wsprintf doesn't like null pointers on NT or 98, so // change any null string pointers to null strings if (!m_szPageURL) { m_szPageURL = new char[1]; m_szPageURL[0] = '\0'; } if (!m_szFileURL) { m_szFileURL = new char[1]; m_szFileURL[0] = '\0'; } m_szURLString = new char[strlen(szPluginFinderCommandBeginning) + strlen(urlToOpen) + 10 + strlen((PSZ)m_pNPMIMEType) + 13 + strlen((PSZ)m_szPageURL) + 11 + strlen((PSZ)m_szFileURL) + strlen(szPluginFinderCommandEnd) + 1]; sprintf(m_szURLString, "%s%s?mimetype=%s&pluginspage=%s&pluginurl=%s%s", szPluginFinderCommandBeginning, urlToOpen, (PSZ)m_pNPMIMEType, m_szPageURL, m_szFileURL, szPluginFinderCommandEnd); } } if(szAddress != NULL) delete [] szAddress; return m_szURLString; } void CPlugin::getPluginRegular() { assert(m_bOnline); char * szURL = createURLString(); assert(szURL != NULL); if(szURL == NULL) return; dbgOut3("CPlugin::getPluginRegular(), %#08x '%s'", m_pNPInstance, szURL); NPN_GetURL(m_pNPInstance, szURL, NULL); m_bWaitingStreamFromPFS = TRUE; } void CPlugin::getPluginSmart() { /* static char szJSString[2048]; sprintf(szJSString, szPluginFinderCommandFormatString, szDefaultPluginFinderURL, m_pNPMIMEType, (m_szFileExtension != NULL) ? m_szFileExtension : szDefaultFileExt); dbgOut3("%#08x '%s'", m_pNPInstance, szJSString); assert(*szJSString); NPN_GetURL(m_pNPInstance, szJSString, "smartupdate_plugin_finder"); */ } void CPlugin::showGetPluginDialog() { assert(m_pNPMIMEType != NULL); if(m_pNPMIMEType == NULL) return; // Get environment BOOL bOffline = FALSE; NPN_GetValue(m_pNPInstance, NPNVisOfflineBool, (void *)&bOffline); NPN_GetValue(m_pNPInstance, NPNVjavascriptEnabledBool, (void *)&m_bJavaScript); //NPN_GetValue(m_pNPInstance, NPNVasdEnabledBool, (void *)&m_bSmartUpdate); m_bOnline = !bOffline; #ifdef OJI if(m_bOnline && m_bJavaScript && m_bSmartUpdate && useDefaultURL_P()) { JRIEnv *penv = NPN_GetJavaEnv(); m_bJava = (penv != NULL); } #else m_bJava = FALSE; #endif dbgOut1("Environment:"); dbgOut2("%s", m_bOnline ? "On-line" : "Off-line"); dbgOut2("Java %s", m_bJava ? "Enabled" : "Disabled"); dbgOut2("JavaScript %s", m_bJavaScript ? "Enabled" : "Disabled"); dbgOut2("SmartUpdate %s", m_bSmartUpdate ? "Enabled" : "Disabled"); if((!m_bSmartUpdate && (m_szPageURL != NULL) || (m_szFileURL != NULL)) || !m_bJavaScript) { int iRet = WinDlgBox(HWND_DESKTOP, m_hWnd, (PFNWP)GetPluginDialogProc, m_hInst, IDD_PLUGIN_DOWNLOAD, (PVOID)this); if(iRet != IDC_GET_PLUGIN) return; } else getPlugin(); } void CPlugin::getPlugin() { if(m_szCommandMessage != NULL) { delete [] m_szCommandMessage; m_szCommandMessage = NULL; } char szString[1024] = {'\0'}; WinLoadString((HAB)0, m_hInst, IDS_CLICK_WHEN_DONE, sizeof(szString), szString); if(*szString) { m_szCommandMessage = new char[strlen(szString) + 1]; if(m_szCommandMessage != NULL) strcpy(m_szCommandMessage, szString); } WinInvalidateRect(m_hWnd, NULL, TRUE); // UpdateWindow(m_hWnd); getPluginRegular(); } //******************* // NP API handles //******************* void CPlugin::resize() { dbgOut1("CPlugin::resize()"); } void CPlugin::print(NPPrint * pNPPrint) { dbgOut1("CPlugin::print()"); if(pNPPrint == NULL) return; } void CPlugin::URLNotify(const char * szURL) { dbgOut2("CPlugin::URLNotify(), URL '%s'", szURL); NPStream * pStream = NULL; char buf[256]; assert(m_hInst != NULL); assert(m_pNPInstance != NULL); int iSize = WinLoadString((HAB)0, m_hInst, IDS_GOING2HTML, sizeof(buf), buf); NPError rc = NPN_NewStream(m_pNPInstance, "text/html", "asd_plugin_finder", &pStream); if (rc != NPERR_NO_ERROR) return; //char buf[] = "\n\n\n

NPN_NewStream / NPN_Write - This seems to work.

\n\n\n"; NPN_Write(m_pNPInstance, pStream, iSize, buf); NPN_DestroyStream(m_pNPInstance, pStream, NPRES_DONE); } NPError CPlugin::newStream(NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype) { if (!m_bWaitingStreamFromPFS) return NPERR_NO_ERROR; m_bWaitingStreamFromPFS = FALSE; m_PFSStream = stream; if (stream) { if (type && !strcmp(type, "application/x-xpinstall")) NPN_GetURL(m_pNPInstance, stream->url, "_self"); else NPN_GetURL(m_pNPInstance, stream->url, "_blank"); } return NPERR_NO_ERROR; } NPError CPlugin::destroyStream(NPStream *stream, NPError reason) { if (stream == m_PFSStream) m_PFSStream = NULL; return NPERR_NO_ERROR; } BOOL CPlugin::readyToRefresh() { char szString[1024] = {'\0'}; WinLoadString((HAB)0, m_hInst, IDS_CLICK_WHEN_DONE, sizeof(szString), szString); if(m_szCommandMessage == NULL) return FALSE; return (strcmp(m_szCommandMessage, szString) == 0); } //*************************** // Windows message handlers //*************************** void CPlugin::onCreate(HWND hWnd) { m_hWnd = hWnd; } void CPlugin::onLButtonUp(HWND hWnd, int x, int y, UINT keyFlags) { if(!readyToRefresh()) showGetPluginDialog(); else NPN_GetURL(m_pNPInstance, "javascript:navigator.plugins.refresh(true)", "_self"); } void CPlugin::onRButtonUp(HWND hWnd, int x, int y, UINT keyFlags) { if(!readyToRefresh()) showGetPluginDialog(); else NPN_GetURL(m_pNPInstance, "javascript:navigator.plugins.refresh(true)", "_self"); } static void DrawCommandMessage(HPS hPS, PSZ szString, PRECTL lprc) { if(szString == NULL) return; POINTL ptls[5]; GpiQueryTextBox(hPS, strlen(szString), szString, 5, ptls); /* If the text won't fit, don't draw anything */ if (ptls[TXTBOX_CONCAT].x > lprc->xRight) return; RECTL rcText = rcText = *lprc; /* Reduce top of rectangle by twice the icon size so the */ /* text draws below the icon */ rcText.yTop -= 80; WinDrawText(hPS, strlen(szString), szString, &rcText, 0, 0, DT_TEXTATTRS | DT_CENTER | DT_VCENTER); } #define INSET 1 void CPlugin::onPaint(HWND hWnd) { RECTL rc; HDC hPS; int x, y; hPS = WinBeginPaint(hWnd, NULLHANDLE, NULL); GpiErase(hPS); WinQueryWindowRect(hWnd, &rc); x = (rc.xRight / 2) - (40 / 2); y = (rc.yTop / 2) - ((40) / 2); /* Only draw the icon if it fits */ if(rc.xRight > (40 + 6 + INSET) && rc.yTop > (40 + 6 + INSET) ) { if(m_hIcon != NULL) WinDrawPointer(hPS, x, y, m_hIcon, DP_NORMAL); } POINTL pt[5]; // white piece GpiSetColor(hPS, CLR_WHITE); pt[0].x = 1 + INSET; pt[0].y = 1 + INSET; GpiMove(hPS, &pt[0]); pt[0].x = rc.xRight - 2 - INSET; pt[0].y = 1 + INSET; pt[1].x = rc.xRight - 2 - INSET; pt[1].y = rc.yTop -1 - INSET; GpiPolyLine(hPS, 2, pt); pt[0].x = 2 + INSET; pt[0].y = 3 + INSET; GpiMove(hPS, &pt[0]); pt[0].x = 2 + INSET; pt[0].y = rc.yTop - 3 - INSET; pt[1].x = rc.xRight - 4 - INSET; pt[1].y = rc.yTop - 3 - INSET; GpiPolyLine(hPS, 2, pt); // pale gray pieces GpiSetColor(hPS, CLR_PALEGRAY); pt[0].x = INSET; pt[0].y = 1 + INSET; GpiMove(hPS, &pt[0]); pt[0].x = INSET; pt[0].y = rc.yTop - 1 - INSET; pt[1].x = rc.xRight - 2 - INSET; pt[1].y = rc.yTop - 1 - INSET; GpiPolyLine(hPS, 2, pt); pt[0].x = rc.xRight - 3 - INSET; pt[0].y = rc.yTop - 2 - INSET; GpiMove(hPS, &pt[0]); pt[0].x = rc.xRight - 3 - INSET; pt[0].y = 2 + INSET; pt[1].x = 2 + INSET; pt[1].y = 2 + INSET; GpiPolyLine(hPS, 2, pt); // dark gray piece GpiSetColor(hPS, CLR_DARKGRAY); pt[0].x = 1 + INSET; pt[0].y = 2 + INSET; GpiMove(hPS, &pt[0]); pt[0].x = 1 + INSET; pt[0].y = rc.yTop - 2 - INSET; pt[1].x = rc.xRight - 4 - INSET; pt[1].y = rc.yTop - 2 - INSET; GpiPolyLine(hPS, 2, pt); // black piece GpiSetColor(hPS, CLR_BLACK); pt[0].x = rc.xRight - 1 - INSET; pt[0].y = rc.yTop - 1 - INSET; GpiMove(hPS, &pt[0]); pt[0].x = rc.xRight - 1 - INSET; pt[0].y = 0 + INSET; pt[1].x = 0 + INSET; pt[1].y = 0 + INSET; GpiPolyLine(hPS, 2, pt); /* Offset rectangle by size of highlight(3) + 1 as well as inset */ /* so that text is not drawn over the border */ rc.xLeft += 4+INSET; rc.xRight -= 4+INSET; rc.yTop -= 4+INSET; rc.yBottom += 4+INSET; DrawCommandMessage(hPS, m_szCommandMessage, &rc); WinEndPaint (hPS); } //************************** // Plugin window procedure //************************** MRESULT EXPENTRY NP_LOADDS PluginWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2) { CPlugin *pPlugin = (CPlugin *)WinQueryWindowULong(hWnd, QWL_USER); switch(message) { case WM_CREATE: pPlugin = (CPlugin *)(((PCREATESTRUCT)mp2)->pCtlData); assert(pPlugin != NULL); WinSetWindowULong(hWnd, QWL_USER, (ULONG)pPlugin); pPlugin->onCreate(hWnd); return 0L; case WM_BUTTON1UP: pPlugin->onLButtonUp(hWnd,0,0,0); return 0L; case WM_BUTTON2UP: pPlugin->onRButtonUp(hWnd,0,0,0); return 0L; case WM_PAINT: pPlugin->onPaint(hWnd); return 0L; case WM_MOUSEMOVE: dbgOut1("MouseMove"); break; default: break; } return(WinDefWindowProc(hWnd, message, mp1, mp2)); }