diff options
Diffstat (limited to 'extensions/source/plugin/aqua')
-rw-r--r-- | extensions/source/plugin/aqua/macmgr.cxx | 646 | ||||
-rw-r--r-- | extensions/source/plugin/aqua/makefile.mk | 75 | ||||
-rw-r--r-- | extensions/source/plugin/aqua/sysplug.cxx | 808 |
3 files changed, 1529 insertions, 0 deletions
diff --git a/extensions/source/plugin/aqua/macmgr.cxx b/extensions/source/plugin/aqua/macmgr.cxx new file mode 100644 index 000000000000..e0bfe3ad5c01 --- /dev/null +++ b/extensions/source/plugin/aqua/macmgr.cxx @@ -0,0 +1,646 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "rtl/ustrbuf.hxx" +#include "rtl/strbuf.hxx" + +#include "plugin/impl.hxx" +#include "osl/file.h" +#include "osl/module.hxx" + +using namespace rtl; +using namespace std; +using namespace com::sun::star::uno; +using namespace com::sun::star::plugin; + +namespace plugstringhelper +{ + +rtl::OUString getString( CFStringRef i_xString ) +{ + rtl::OUStringBuffer aBuf; + if( i_xString ) + { + CFIndex nChars = CFStringGetLength( i_xString ); + CFRange aRange = { 0, nChars }; + aBuf.setLength( nChars ); + CFStringGetCharacters( i_xString, aRange, static_cast< UniChar* >(const_cast<sal_Unicode*>(aBuf.getStr())) ); + } + return aBuf.makeStringAndClear(); +} + +rtl::OUString getString( CFURLRef i_xURL ) +{ + CFStringRef xString = CFURLGetString( i_xURL ); + return getString( xString ); +} + +CFMutableStringRef createString( const rtl::OUString& i_rString ) +{ + CFMutableStringRef xString = CFStringCreateMutable( NULL, 0 ); + if( xString ) + CFStringAppendCharacters( xString, i_rString.getStr(), i_rString.getLength() ); + return xString; +} + +CFURLRef createURL( const rtl::OUString& i_rString ) +{ + + CFMutableStringRef xMutableString = createString( i_rString ); + CFURLRef xURL = CFURLCreateWithString( NULL, xMutableString, NULL ); + CFRelease( xMutableString ); + return xURL; +} + +rtl::OUString getURLFromPath( const rtl::OUString& i_rPath ) +{ + CFMutableStringRef xMutableString = createString( i_rPath ); + CFURLRef xURL = CFURLCreateWithFileSystemPath( NULL, xMutableString, kCFURLPOSIXPathStyle, true ); + CFRelease( xMutableString ); + CFStringRef xString = CFURLGetString( xURL ); + rtl::OUString aRet = getString( xString ); + CFRelease( xURL ); + return aRet; +} + +CFURLRef createURLFromPath( const rtl::OUString& i_rPath ) +{ + CFMutableStringRef xMutableString = createString( i_rPath ); + CFURLRef xURL = CFURLCreateWithFileSystemPath( NULL, xMutableString, kCFURLPOSIXPathStyle, true ); + return xURL; +} + +rtl::OUString CFURLtoOSLURL( CFURLRef i_xURL ) +{ + // make URL absolute + CFURLRef xAbsURL = CFURLCopyAbsoluteURL( i_xURL ); + // copy system path + CFStringRef xSysPath = CFURLCopyFileSystemPath( xAbsURL ? xAbsURL : i_xURL, kCFURLPOSIXPathStyle ); + if( xAbsURL ) + CFRelease( xAbsURL ); + rtl::OUString aSysPath( getString( xSysPath ) ); + CFRelease( xSysPath ); + rtl::OUString aFileURL; + osl_getFileURLFromSystemPath( aSysPath.pData, &aFileURL.pData ); + return aFileURL; +} + +} + +using namespace plugstringhelper; + +static int parsePlist( CFBundleRef i_xBundle, const rtl::OUString& i_rBundleURL , list< PluginDescription* >& io_rDescriptions ) +{ + CFTypeRef xMimeDict = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("WebPluginMIMETypes")); + int nMimetypes = 0; + if( xMimeDict == 0 || + CFGetTypeID(xMimeDict) != CFDictionaryGetTypeID() || + (nMimetypes = CFDictionaryGetCount( static_cast<CFDictionaryRef>(xMimeDict))) <= 0 ) + { + return 0; + } + + // prepare an array of key and value refs + std::vector< CFTypeRef > aKeys( nMimetypes, CFTypeRef(NULL) ); + std::vector< CFTypeRef > aValues( nMimetypes, CFTypeRef(NULL) ); + CFDictionaryGetKeysAndValues(static_cast<CFDictionaryRef>(xMimeDict), &aKeys[0], &aValues[0] ); + + int nAdded = 0; + for( int i = 0; i < nMimetypes; i++ ) + { + // get the mimetype + CFTypeRef xKey = aKeys[i]; + if( ! xKey || CFGetTypeID(xKey) != CFStringGetTypeID() ) + continue; + rtl::OUString aMimetype = getString( (CFStringRef)xKey ); + + // the correspoding value should be a dictionary + CFTypeRef xDict = aValues[i]; + if( ! xDict || CFGetTypeID( xDict ) != CFDictionaryGetTypeID() ) + continue; + + // get the extension list + CFTypeRef xExtArray = CFDictionaryGetValue( (CFDictionaryRef)xDict, CFSTR("WebPluginExtensions" ) ); + if( !xExtArray || CFGetTypeID( xExtArray ) != CFArrayGetTypeID() ) + continue; + + OUStringBuffer aExtBuf; + int nExtensions = CFArrayGetCount( (CFArrayRef)xExtArray ); + for( int n = 0; n < nExtensions; n++ ) + { + CFTypeRef xExt = CFArrayGetValueAtIndex( (CFArrayRef)xExtArray, n ); + if( xExt && CFGetTypeID( xExt ) == CFStringGetTypeID() ) + { + if( aExtBuf.getLength() > 0 ) + aExtBuf.append( sal_Unicode(';') ); + OUString aExt( getString( (CFStringRef)xExt ) ); + if( aExt.indexOfAsciiL( "*.", 2 ) != 0 ) + aExtBuf.appendAscii( "*." ); + aExtBuf.append( aExt ); + } + } + + // get the description string + CFTypeRef xDescString = CFDictionaryGetValue( (CFDictionaryRef)xDict, CFSTR("WebPluginTypeDescription" ) ); + if( !xDescString || CFGetTypeID( xDescString ) != CFStringGetTypeID() ) + continue; + rtl::OUString aDescription = getString( (CFStringRef)xDescString ); + + PluginDescription* pNew = new PluginDescription; + // set plugin name (path to library) + pNew->PluginName = i_rBundleURL; + // set mimetype + pNew->Mimetype = aMimetype; + // set extension line + pNew->Extension = aExtBuf.makeStringAndClear(); + // set description + pNew->Description= aDescription; + + io_rDescriptions.push_back( pNew ); + nAdded++; + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "Inserting from PList:\n" + " Mimetype: %s\n" + " Extension: %s\n" + " Description: %s\n", + OUStringToOString( pNew->Mimetype, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( pNew->Extension, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( pNew->Description, RTL_TEXTENCODING_UTF8 ).getStr() + ); +#endif + + } + + return nAdded; +} + +static int parseMimeString( const rtl::OUString& i_rBundleURL , list< PluginDescription* >& io_rDescriptions, const char* i_pMime ) +{ + if( ! i_pMime ) + return 0; + + rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); + + OStringBuffer aMIME; + aMIME.append( i_pMime ); + + if( aMIME.getLength() < 1 ) + return 0; + + OString aLine = aMIME.makeStringAndClear(); + + int nAdded = 0; + sal_Int32 nIndex = 0; + while( nIndex != -1 ) + { + OString aType = aLine.getToken( 0, ';', nIndex ); + + sal_Int32 nTypeIndex = 0; + OString aMimetype = aType.getToken( 0, ':', nTypeIndex ); + OString aExtLine = aType.getToken( 0, ':', nTypeIndex ); + if( nTypeIndex < 0 ) // ensure at least three tokens + continue; + OString aDesc = aType.getToken( 0, ':', nTypeIndex ); + + // create extension list string + sal_Int32 nExtIndex = 0; + OStringBuffer aExtension; + while( nExtIndex != -1 ) + { + OString aExt = aExtLine.getToken( 0, ',', nExtIndex); + if( aExt.indexOf( "*." ) != 0 ) + aExtension.append( "*." ); + aExtension.append( aExt ); + if( nExtIndex != -1 ) + aExtension.append( ';' ); + } + + PluginDescription* pNew = new PluginDescription; + // set plugin name (path to library) + pNew->PluginName = i_rBundleURL; + // set mimetype + pNew->Mimetype = OStringToOUString( aMimetype, aEncoding ); + // set extension line + pNew->Extension = OStringToOUString( aExtension.makeStringAndClear(), aEncoding ); + // set description + pNew->Description= OStringToOUString( aDesc, aEncoding ); + io_rDescriptions.push_back( pNew ); + nAdded++; + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "Inserting from mime string:\n" + " Mimetype: %s\n" + " Extension: %s\n" + " Description: %s\n", + OUStringToOString( pNew->Mimetype, aEncoding ).getStr(), + OUStringToOString( pNew->Extension, aEncoding ).getStr(), + OUStringToOString( pNew->Description, aEncoding ).getStr() + ); +#endif + } + return nAdded; +} + +// this is so ugly it you want to tear your eyes out +static rtl::OUString GetNextPluginStringFromHandle(Handle h, short *index) +{ + char* pPascalBytes = (*h + *index); + sal_uInt32 nLen = (unsigned char)pPascalBytes[0]; + rtl::OStringBuffer aBuf( nLen ); + aBuf.append( pPascalBytes+1, nLen ); + *index += nLen + 1; + return rtl::OStringToOUString( aBuf.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ); +} + +static int parseMimeResource( CFBundleRef i_xBundle, + oslModule& i_rMod, + const rtl::OUString& i_rBundleURL, + list< PluginDescription* >& io_rDescriptions ) +{ + int nAdded = 0; + // just to hurt our eyes more there is an alternative mimetype function plus the possibility + // of a resource fork. Must be a case of think different. + #if __LP64__ + int + #else + SInt16 + #endif + xRes = 0; + BPSupportedMIMETypes aMIMETypesStrangeStruct = {kBPSupportedMIMETypesStructVers_1, NULL, NULL}; + + BP_GetSupportedMIMETypesUPP pBPGetSupp = (BP_GetSupportedMIMETypesUPP)osl_getAsciiFunctionSymbol( i_rMod, "BP_GetSupportedMIMETypes" ); + if( pBPGetSupp && + noErr == pBPGetSupp( &aMIMETypesStrangeStruct, 0 ) && + aMIMETypesStrangeStruct.typeStrings ) + { + HLock( aMIMETypesStrangeStruct.typeStrings ); + if( aMIMETypesStrangeStruct.infoStrings ) // it's possible some plugins have infoStrings missing + HLock( aMIMETypesStrangeStruct.infoStrings ); + } + else // Try to get data from the resource fork + { + xRes = CFBundleOpenBundleResourceMap( i_xBundle ); + if( xRes > 0 ) + { + aMIMETypesStrangeStruct.typeStrings = Get1Resource('STR#', 128); + if( aMIMETypesStrangeStruct.typeStrings ) + { + DetachResource( aMIMETypesStrangeStruct.typeStrings ); + HLock( aMIMETypesStrangeStruct.typeStrings ); + aMIMETypesStrangeStruct.infoStrings = Get1Resource('STR#', 127); + if( aMIMETypesStrangeStruct.infoStrings ) + { + DetachResource( aMIMETypesStrangeStruct.infoStrings ); + HLock( aMIMETypesStrangeStruct.infoStrings ); + } + } + } + } + + if( aMIMETypesStrangeStruct.typeStrings && aMIMETypesStrangeStruct.infoStrings ) + { + short nVariantCount = (**(short**)aMIMETypesStrangeStruct.typeStrings) / 2; + // Fill in the info struct based on the data in the BPSupportedMIMETypes struct + // this is an array of pascal string of unknown (!) encoding + // whoever thought of this deserves a fair beating + short mimeIndex = 2; + short descriptionIndex = 2; + for( int i = 0; i < nVariantCount; i++ ) + { + rtl::OUString aMimetype = GetNextPluginStringFromHandle( aMIMETypesStrangeStruct.typeStrings, &mimeIndex ); + rtl::OUString aExtLine = GetNextPluginStringFromHandle( aMIMETypesStrangeStruct.typeStrings, &mimeIndex ); + rtl::OUString aDescription; + if( aMIMETypesStrangeStruct.infoStrings ) + aDescription = GetNextPluginStringFromHandle( aMIMETypesStrangeStruct.infoStrings, &descriptionIndex ); + + // create extension list string + sal_Int32 nExtIndex = 0; + OUStringBuffer aExtension; + while( nExtIndex != -1 ) + { + OUString aExt = aExtLine.getToken( 0, ',', nExtIndex); + if( aExt.indexOfAsciiL( "*.", 2 ) != 0 ) + aExtension.appendAscii( "*." ); + aExtension.append( aExt ); + if( nExtIndex != -1 ) + aExtension.append( sal_Unicode(';') ); + } + + PluginDescription* pNew = new PluginDescription; + // set plugin name (path to library) + pNew->PluginName = i_rBundleURL; + // set mimetype + pNew->Mimetype = aMimetype; + // set extension line + pNew->Extension = aExtension.makeStringAndClear(); + // set description + pNew->Description= aDescription; + io_rDescriptions.push_back( pNew ); + nAdded++; + + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, + "Inserting from resource:\n" + " Mimetype: %s\n" + " Extension: %s\n" + " Description: %s\n", + OUStringToOString( pNew->Mimetype, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( pNew->Extension, RTL_TEXTENCODING_UTF8 ).getStr(), + OUStringToOString( pNew->Description, RTL_TEXTENCODING_UTF8 ).getStr() + ); + #endif + } + } + + + // clean up + if( aMIMETypesStrangeStruct.typeStrings ) + { + HUnlock( aMIMETypesStrangeStruct.typeStrings ); + DisposeHandle( aMIMETypesStrangeStruct.typeStrings ); + } + if( aMIMETypesStrangeStruct.infoStrings ) + { + HUnlock( aMIMETypesStrangeStruct.infoStrings ); + DisposeHandle( aMIMETypesStrangeStruct.infoStrings ); + } + if( xRes ) + CFBundleCloseBundleResourceMap( i_xBundle, xRes ); + + return nAdded; +} + +// check some known bad plugins to avoid crashes +static bool checkBlackList( CFBundleRef i_xBundle ) +{ + rtl::OUString aBundleName; + CFTypeRef bundlename = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("CFBundleName")); + if( bundlename && CFGetTypeID(bundlename) == CFStringGetTypeID() ) + aBundleName = getString( static_cast<CFStringRef>(bundlename) ); + + rtl::OUString aBundleVersion; + CFTypeRef bundleversion = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("CFBundleVersion")); + if( bundleversion && CFGetTypeID(bundleversion) == CFStringGetTypeID() ) + aBundleVersion = getString( static_cast<CFStringRef>(bundleversion) ); + + bool bReject = false; + // #i102735# VLC plugin prior to 1.0 tends to crash + if( aBundleName.equalsAscii( "VLC Plug-in" ) ) + { + sal_Int32 nIndex = 0; + rtl::OUString aMajor( aBundleVersion.getToken( 0, '.', nIndex ) ); + if( aMajor.toInt32() < 1 ) + { + bReject = true; + } + } + // #i103674# Garmin Communicator Plugin crashes + else if( aBundleName.equalsAscii( "Garmin Communicator Plugin" ) ) + { + bReject = true; + } + + #if OSL_DEBUG_LEVEL > 1 + if( bReject ) + fprintf( stderr, "rejecting plugin \"%s\" version %s\n", + rtl::OUStringToOString( aBundleName, RTL_TEXTENCODING_UTF8 ).getStr(), + rtl::OUStringToOString( aBundleVersion, RTL_TEXTENCODING_UTF8 ).getStr() + ); + #endif + + return bReject; +} + +static int getPluginDescriptions( CFBundleRef i_xBundle , list< PluginDescription* >& io_rDescriptions ) +{ + int nDescriptions = 0; + if( ! i_xBundle ) + return nDescriptions; + + if( checkBlackList( i_xBundle ) ) + return 0; + + rtl::OUString aPlugURL; + CFURLRef xURL = CFBundleCopyBundleURL( i_xBundle ); + aPlugURL = getString( xURL ); + CFRelease( xURL ); + + #if OSL_DEBUG_LEVEL > 1 + rtl::OUString aPlugName, aPlugDescription; + CFTypeRef name = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("WebPluginName")); + if( name && CFGetTypeID(name) == CFStringGetTypeID() ) + aPlugName = getString( static_cast<CFStringRef>(name) ); + + CFTypeRef description = CFBundleGetValueForInfoDictionaryKey( i_xBundle, CFSTR("WebPluginDescription")); + if( description && CFGetTypeID(description) == CFStringGetTypeID() ) + aPlugDescription = getString( static_cast<CFStringRef>(description) ); + + fprintf( stderr, "URL: %s\nname: %s\ndescription: %s\n", + rtl::OUStringToOString( aPlugURL, RTL_TEXTENCODING_UTF8 ).getStr(), + rtl::OUStringToOString( aPlugName, RTL_TEXTENCODING_UTF8 ).getStr(), + rtl::OUStringToOString( aPlugDescription, RTL_TEXTENCODING_UTF8 ).getStr() + ); + #endif + + + // get location of plugin library + CFURLRef xLibURL = CFBundleCopyExecutableURL( i_xBundle ); + if( ! xLibURL ) + return 0; + // get the file system path + rtl::OUString aModuleURL( CFURLtoOSLURL( xLibURL ) ); + CFRelease( xLibURL ); + + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "exec URL = %s\n", rtl::OUStringToOString( aModuleURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + #endif + + /* TODO: originally the C++ wrapper for oslModule was used here, but that led to + mysterious crashes in the event loop (pointing to heap corruption). Why using + the C style oslModule should fix this is completely unknown. It may be that + we have just hidden the heap corruption a little more. + */ + oslModule aMod = osl_loadModule( aModuleURL.pData, SAL_LOADMODULE_DEFAULT ); + if( ! aMod ) + return 0; + + // check for at least the init function of a plugin + if( ! osl_getAsciiFunctionSymbol( aMod, "NP_Initialize") && + ! osl_getAsciiFunctionSymbol( aMod, "NP_GetEntryPoints" ) ) + { + return 0; + } + + // ask the plist of the bundle for mimetypes + nDescriptions = parsePlist( i_xBundle, aPlugURL, io_rDescriptions ); + if( nDescriptions ) + { + osl_unloadModule( aMod ); + return nDescriptions; + } + + // resolve the symbol that might get us the mimetypes + const char* (*pGetMimeDescription)() = (const char*(*)())osl_getAsciiFunctionSymbol( aMod, "_NP_GetMIMEDescription" ); + if( pGetMimeDescription ) + { + const char* pMime = pGetMimeDescription(); + if( pMime ) + { + nDescriptions = parseMimeString( aPlugURL, io_rDescriptions, pMime ); + if( nDescriptions ) + { + osl_unloadModule( aMod ); + return nDescriptions; + } + } + } + + // and as last resort check the resource of the bundle + nDescriptions = parseMimeResource( i_xBundle, aMod, aPlugURL, io_rDescriptions ); + osl_unloadModule( aMod ); + + return nDescriptions; +} + +// Unix specific implementation +static bool CheckPlugin( const rtl::OUString& rPath, list< PluginDescription* >& rDescriptions ) +{ +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "Trying path %s ... ", rtl::OUStringToOString( rPath, RTL_TEXTENCODING_UTF8 ).getStr() ); +#endif + CFURLRef xURL = createURL( rPath ); + + CFArrayRef xBundles = CFBundleCreateBundlesFromDirectory( NULL, xURL, CFSTR("plugin") ); + if( ! xBundles ) + return false; + + CFIndex nBundles = CFArrayGetCount( xBundles ); + +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "got %d bundles\n", (int)nBundles ); +#endif + + int nDescriptions = 0; + for( CFIndex i = 0; i < nBundles; i++ ) + { + CFBundleRef xBundle = (CFBundleRef)CFArrayGetValueAtIndex( xBundles, i ); + nDescriptions += getPluginDescriptions( xBundle, rDescriptions ); + + CFRelease( xBundle ); + } + CFRelease( xBundles ); + + + return nDescriptions > 0; +} + +static rtl::OUString FindFolderURL( FSVolumeRefNum vRefNum, OSType folderType ) +{ + rtl::OUString aRet; + + FSRef aFSRef; + OSErr err = FSFindFolder( vRefNum, folderType, kDontCreateFolder, &aFSRef ); + if( err == noErr ) + { + CFURLRef xURL = CFURLCreateFromFSRef( NULL, &aFSRef ); + aRet = getString( xURL ); + CFRelease( xURL ); + } + + return aRet; +} + +Sequence<PluginDescription> XPluginManager_Impl::impl_getPluginDescriptions() throw() +{ + static Sequence<PluginDescription> aDescriptions; + static sal_Bool bHavePlugins = sal_False; + if( ! bHavePlugins ) + { + std::list<PluginDescription*> aPlugins; + + static const char* pNPXPluginPath = getenv( "MOZ_PLUGIN_PATH" ); + + // get directories + std::list< rtl::OUString > aPaths; + if( pNPXPluginPath ) + { + CFMutableStringRef xMutableString = CFStringCreateMutable( NULL, 0 ); + CFStringAppendCString( xMutableString, pNPXPluginPath, kCFStringEncodingUTF8 ); + CFURLRef xURL = CFURLCreateWithFileSystemPath( NULL, xMutableString, kCFURLPOSIXPathStyle, true ); + CFRelease( xMutableString ); + aPaths.push_back( getString( xURL ) ); + CFRelease( xURL ); + } + + rtl::OUString aPath = FindFolderURL( kUserDomain, kInternetPlugInFolderType ); + if( aPath.getLength() ) + aPaths.push_back( aPath ); + aPath = FindFolderURL( kLocalDomain, kInternetPlugInFolderType ); + if( aPath.getLength() ) + aPaths.push_back( aPath ); + aPath = FindFolderURL( kOnAppropriateDisk, kInternetPlugInFolderType ); + if( aPath.getLength() ) + aPaths.push_back( aPath ); + + + const Sequence< ::rtl::OUString >& rPaths( PluginManager::getAdditionalSearchPaths() ); + for( sal_Int32 i = 0; i < rPaths.getLength(); i++ ) + { + aPaths.push_back( getURLFromPath( rPaths.getConstArray()[i] ) ); + } + + for( std::list< rtl::OUString >::const_iterator it = aPaths.begin(); it != aPaths.end(); ++it ) + { + rtl::OUString aPath( *it ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "check path %s\n", rtl::OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr() ); +#endif + CheckPlugin( aPath, aPlugins ); + } + + + // create return value + aDescriptions = Sequence<PluginDescription>( aPlugins.size() ); +#if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "found %d plugins\n", (int)aPlugins.size() ); +#endif + list<PluginDescription*>::iterator iter; + sal_Int32 nPlug = 0; + for( iter = aPlugins.begin(); iter != aPlugins.end(); ++iter ) + { + aDescriptions.getArray()[ nPlug++ ] = **iter; + delete *iter; + } + aPlugins.clear(); + bHavePlugins = sal_True; + } + return aDescriptions; +} + diff --git a/extensions/source/plugin/aqua/makefile.mk b/extensions/source/plugin/aqua/makefile.mk new file mode 100644 index 000000000000..e29418a526f2 --- /dev/null +++ b/extensions/source/plugin/aqua/makefile.mk @@ -0,0 +1,75 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* +PRJ=..$/..$/.. + +PRJNAME=extensions +TARGET=plaqua +#ENABLE_EXCEPTIONS=TRUE +#TARGETTYPE=CUI + +.INCLUDE : ..$/util$/makefile.pmk + +.IF "$(GUIBASE)"!="aqua" || "$(WITH_MOZILLA)"=="NO" + +dummy: + @echo "Nothing to build for GUIBASE $(GUIBASE)." + +.ELSE + +# --- Files -------------------------------------------------------- + +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/plugin +.IF "$(SOLAR_JAVA)" != "" +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/java +INCPRE+=-I$(SOLARINCDIR)$/mozilla$/nspr +INCPRE+=-I$(SOLARINCDIR)$/npsdk +CDEFS+=-DOJI +.ENDIF + +.IF "$(GUIBASE)"=="aqua" +CFLAGSCXX+=$(OBJCXXFLAGS) +.ENDIF # "$(GUIBASE)"=="aqua" + +SLOFILES=\ + $(SLO)$/macmgr.obj \ + $(SLO)$/sysplug.obj + +#APP1TARGET=pluginapp.bin +#APP1OBJS=$(OBJFILES) +#APP1STDLIBS=\ +# $(TOOLSLIB) \ +# $(VOSLIB) \ +# $(SALLIB) + +#APP1DEF= $(MISC)$/$(TARGET).def + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + +.ENDIF # $(GUIBASE)==aqua diff --git a/extensions/source/plugin/aqua/sysplug.cxx b/extensions/source/plugin/aqua/sysplug.cxx new file mode 100644 index 000000000000..206204fa10a7 --- /dev/null +++ b/extensions/source/plugin/aqua/sysplug.cxx @@ -0,0 +1,808 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <cstdarg> + +#include <sys/types.h> +#include <signal.h> +#include <sys/wait.h> +#include <osl/thread.h> + +#include <plugin/impl.hxx> + +extern NPNetscapeFuncs aNPNFuncs; + +#include <tools/debug.hxx> + +using namespace rtl; +using namespace plugstringhelper; + +#if OSL_DEBUG_LEVEL > 1 +void TRACE( char const * s ); +void TRACEN( char const * s, long n ); +#else +#define TRACE(x) +#define TRACEN(x,n) +#endif + +struct FakeEventRecord : public EventRecord +{ + FakeEventRecord() + { + memset( this, 0, sizeof(EventRecord) ); + ::GetGlobalMouse( &where ); + when = ::TickCount(); + modifiers = ::GetCurrentEventKeyModifiers(); + } +}; + + +@interface OOoPluginView : NSView +{ + XPlugin_Impl* m_pImpl; + MacPluginComm* m_pCom; +} +-(id)initWithInstance: (XPlugin_Impl*)i_pImpl pluginComm: (MacPluginComm*)i_pCom frame: (NSRect)i_aRect; +-(void)drawRect: (NSRect)i_aRect; +-(BOOL)isOpaque; +-(BOOL)isFlipped; + +// NSResponder +-(void)mouseMoved: (NSEvent*)i_pEvent; +-(void)mouseDown: (NSEvent*)i_pEvent; +-(void)mouseDragged: (NSEvent*)i_pEvent; +-(void)mouseUp: (NSEvent*)i_pEvent; +-(void)rightMouseDown: (NSEvent*)i_pEvent; +-(void)rightMouseDragged: (NSEvent*)i_pEvent; +-(void)rightMouseUp: (NSEvent*)i_pEvent; +-(void)otherMouseDown: (NSEvent*)i_pEvent; +-(void)otherMouseDragged: (NSEvent*)i_pEvent; +-(void)otherMouseUp: (NSEvent*)i_pEvent; +-(void)mouseEntered: (NSEvent*)i_pEvent; +-(void)mouseExited: (NSEvent*)i_pEvent; +@end + +@implementation OOoPluginView +-(id)initWithInstance: (XPlugin_Impl*)i_pImpl pluginComm: (MacPluginComm*)i_pCom frame: (NSRect) i_aRect +{ + if( (self = [super initWithFrame: i_aRect]) ) + { + m_pImpl = i_pImpl; + m_pCom = i_pCom; + } + return self; +} + +-(void)drawRect: (NSRect) i_aRect +{ + m_pCom->drawView( m_pImpl ); +} + +-(BOOL)isOpaque +{ + return NO; +} + +-(BOOL)isFlipped +{ + return YES; +} + +// NSResponder +-(void)mouseMoved: (NSEvent*)i_pEvent +{ + FakeEventRecord aRec; + aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseDown: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseDown; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseDragged: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseUp: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseUp; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)rightMouseDown: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseDown; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)rightMouseDragged: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)rightMouseUp: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseUp; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)otherMouseDown: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseDown; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)otherMouseDragged: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)otherMouseUp: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = mouseUp; + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseEntered: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +-(void)mouseExited: (NSEvent*)i_pEvent; +{ + FakeEventRecord aRec; + aRec.what = aRec.what = osEvt + 18; // NPEventType_AdjustCursorEvent + m_pCom->NPP_HandleEvent( m_pImpl->getNPPInstance(), &aRec ); +} + +@end + +//-------------------------------------------------------------------------------------------------- +MacPluginComm::MacPluginComm( const rtl::OUString& i_rMimetype, const rtl::OUString& i_rBundle, NSView* i_pParent ) + : PluginComm( OUStringToOString( i_rBundle, RTL_TEXTENCODING_UTF8 ) ), + m_xBundle( NULL ), + m_hPlugLib( NULL ), + m_pNullTimer( NULL ) +{ + // initialize plugin function table + memset( &m_aNPPfuncs, 0, sizeof( m_aNPPfuncs ) ); + + // load the bundle + CFURLRef xURL = createURL( i_rBundle ); + m_xBundle = CFBundleCreate( NULL, xURL ); + CFRelease( xURL ); + if( m_xBundle ) + { + // ask the plugin library + // first get its location + CFURLRef xLibURL = CFBundleCopyExecutableURL( m_xBundle ); + if( xLibURL ) + { + // get the file system path + rtl::OUString aModuleURL( CFURLtoOSLURL( xLibURL ) ); + CFRelease( xLibURL ); + m_hPlugLib = osl_loadModule( aModuleURL.pData, SAL_LOADMODULE_DEFAULT ); + #if OSL_DEBUG_LEVEL > 1 + if( ! m_hPlugLib ) + fprintf( stderr, "module %s could not be loaded\n", OUStringToOString( aModuleURL, RTL_TEXTENCODING_UTF8 ).getStr() ); + #endif + } + #if OSL_DEBUG_LEVEL > 1 + else + fprintf( stderr, "bundle %s has no exectutable URL\n", OUStringToOString( i_rBundle, RTL_TEXTENCODING_UTF8 ).getStr() ); + #endif + } + else + { + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "bundle %s could not be loaded\n", OUStringToOString( i_rBundle, RTL_TEXTENCODING_UTF8 ).getStr() ); + #endif + } + + DBG_ASSERT( m_xBundle && m_hPlugLib, "loading plugin bundle failed!" ); + + + m_aNPPfuncs.size = sizeof( m_aNPPfuncs ); + m_aNPPfuncs.version = 0; + + + m_eCall = eNP_Initialize; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +MacPluginComm::~MacPluginComm() +{ + if( m_hPlugLib ) + { + // NPP_Shutdown(); + NPError (*pShutdown)(); + if( retrieveFunction( "NP_Shutdown", (void**)&pShutdown ) ) + { + NPError nErr = (*pShutdown)(); (void)nErr; + DBG_ASSERT( nErr == NPERR_NO_ERROR, "NP_Shutdown() failed!" ); + } + osl_unloadModule( m_hPlugLib ); + } + if( m_xBundle ) + CFRelease( m_xBundle ); +} + +//-------------------------------------------------------------------------------------------------- +sal_Bool MacPluginComm::retrieveFunction( const char* i_pName, void** o_ppFunc ) const +{ + if( ! m_hPlugLib || ! o_ppFunc ) + return sal_False; + + *o_ppFunc = (void*)osl_getAsciiFunctionSymbol( m_hPlugLib, i_pName ); + + if( ! *o_ppFunc && m_xBundle ) + { + rtl::OUString aName( OUString::createFromAscii( *i_pName == '_' ? i_pName+1 : i_pName ) ); + CFStringRef xName = createString( aName ); + if( xName ) + { + *o_ppFunc = CFBundleGetFunctionPointerForName( m_xBundle, xName ); + CFRelease( xName ); + } + } + + return (*o_ppFunc != NULL); +} + +IMPL_LINK( MacPluginComm, NullTimerHdl, void*, EMPTYARG ) +{ + // note: this is a Timer handler, we are already protected by the SolarMutex + + FakeEventRecord aRec; + aRec.what = nullEvent; + aRec.where.h = aRec.where.v = 20000; + + for( std::list< XPlugin_Impl* >::iterator it = m_aNullEventClients.begin(); + it != m_aNullEventClients.end(); ++it ) + { + SysPlugData& rPlugData( (*it)->getSysPlugData() ); + if( rPlugData.m_pPlugView ) // for safety do not dispatch null events before first NPP_SetWindow + (*m_aNPPfuncs.event)( (*it)->getNPPInstance(), &aRec ); + } + + return 0; +} + +//-------------------------------------------------------------------------------------------------- + +long MacPluginComm::doIt() +{ + long nRet = 0; + switch( m_eCall ) + { + case eNP_Initialize: + { + TRACE( "eNP_Initialize" ); + NPError (*pInit)( NPNetscapeFuncs* ); + if( retrieveFunction( "NP_Initialize", (void**)&pInit ) ) + { + nRet = (*pInit)( &aNPNFuncs ); + + NPError nErr = NPERR_NO_ERROR; + NPError (*pEntry)( NPPluginFuncs* ); + retrieveFunction( "NP_GetEntryPoints", (void**)&pEntry ); + nErr = (*pEntry)( &m_aNPPfuncs ); + + DBG_ASSERT( nErr == NPERR_NO_ERROR, "NP_GetEntryPoints() failed!" ); + } + else + { + nRet = NPERR_GENERIC_ERROR; + } + DBG_ASSERT( nRet == NPERR_NO_ERROR, "### NP_Initialize() failed!" ); + } + break; + case eNPP_Destroy: + if( m_aNullEventClients.empty() ) + delete m_pNullTimer, m_pNullTimer = NULL; + + TRACE( "eNPP_Destroy" ); + nRet = (m_aNPPfuncs.destroy + ? (*m_aNPPfuncs.destroy)( + (NPP)m_aArgs[0], + (NPSavedData**)m_aArgs[1] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_DestroyStream: + TRACE( "eNPP_DestroyStream" ); + nRet = (m_aNPPfuncs.destroystream + ? (*m_aNPPfuncs.destroystream)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1], + (NPError)(sal_IntPtr)m_aArgs[2] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_New: + TRACE( "eNPP_New" ); + nRet = (m_aNPPfuncs.newp + ? (*m_aNPPfuncs.newp)( + (NPMIMEType)m_aArgs[0], + (NPP)m_aArgs[1], + (uint16)(sal_IntPtr)m_aArgs[2], + (int16)(sal_IntPtr)m_aArgs[3], + (char**)m_aArgs[4], + (char**)m_aArgs[5], + (NPSavedData*)m_aArgs[6] ) + : NPERR_GENERIC_ERROR); + + if( ! m_pNullTimer && m_aNPPfuncs.event ) + { + m_pNullTimer = new AutoTimer(); + m_pNullTimer->SetTimeout( 50 ); + m_pNullTimer->SetTimeoutHdl( LINK( this, MacPluginComm, NullTimerHdl ) ); + m_pNullTimer->Start(); + } + + break; + case eNPP_NewStream: + TRACE( "eNPP_NewStream" ); + nRet = (m_aNPPfuncs.newstream + ? (*m_aNPPfuncs.newstream)( + (NPP)m_aArgs[0], + (NPMIMEType)m_aArgs[1], + (NPStream*)m_aArgs[2], + (NPBool)(sal_IntPtr)m_aArgs[3], + (uint16*)m_aArgs[4] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_Print: + TRACE( "eNPP_Print" ); + if (m_aNPPfuncs.print) + (*m_aNPPfuncs.print)( + (NPP)m_aArgs[0], + (NPPrint*)m_aArgs[1] ); + break; + case eNPP_SetWindow: + { + TRACE( "eNPP_SetWindow" ); + nRet = (m_aNPPfuncs.setwindow + ? (*m_aNPPfuncs.setwindow)( + (NPP)m_aArgs[0], + (NPWindow*)m_aArgs[1] ) + : NPERR_GENERIC_ERROR); + + break; + } + case eNPP_HandleEvent: + { + TRACE( "eNPP_HandleEvent" ); + nRet = (m_aNPPfuncs.event + ? (*m_aNPPfuncs.event)( + (NPP)m_aArgs[0], + m_aArgs[1] ) + : NPERR_GENERIC_ERROR); + + break; + } + case eNPP_StreamAsFile: + TRACE( "eNPP_StreamAsFile" ); + if (m_aNPPfuncs.asfile) + (*m_aNPPfuncs.asfile)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1], + (char*)m_aArgs[2] ); + break; + case eNPP_URLNotify: + TRACE( "eNPP_URLNotify" ); + if (m_aNPPfuncs.urlnotify) + (*m_aNPPfuncs.urlnotify)( + (NPP)m_aArgs[0], + (char*)m_aArgs[1], + (NPReason)(sal_IntPtr)m_aArgs[2], + m_aArgs[3] ); + break; + case eNPP_Write: + TRACEN( "eNPP_Write n=", (int32)m_aArgs[3] ); + nRet = (m_aNPPfuncs.write + ? (*m_aNPPfuncs.write)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1], + (int32)m_aArgs[2], + (int32)m_aArgs[3], + m_aArgs[4] ) + : 0); + break; + case eNPP_WriteReady: + TRACE( "eNPP_WriteReady" ); + nRet = (m_aNPPfuncs.writeready + ? (*m_aNPPfuncs.writeready)( + (NPP)m_aArgs[0], + (NPStream*)m_aArgs[1] ) + : 0); + break; + case eNPP_GetValue: + TRACE( "eNPP_GetValue" ); + nRet = (m_aNPPfuncs.getvalue + ? (*m_aNPPfuncs.getvalue)( + (NPP)m_aArgs[0], + (NPPVariable)(int)m_aArgs[1], + m_aArgs[2] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_SetValue: + TRACE( "eNPP_SetValue" ); + nRet = (m_aNPPfuncs.setvalue + ? (*m_aNPPfuncs.setvalue)( + (NPP)m_aArgs[0], + (NPNVariable)(int)m_aArgs[1], + m_aArgs[2] ) + : NPERR_GENERIC_ERROR); + break; + case eNPP_Shutdown: + { + TRACE( "eNPP_Shutdown" ); + NPP_ShutdownUPP pFunc; + if (retrieveFunction( "NPP_Shutdown", (void**)&pFunc )) + (*pFunc)(); + } + break; + case eNPP_Initialize: + TRACE( "eNPP_Initialize" ); + OSL_ENSURE( false, "NPP_Initialize: not implemented!" ); + break; + case eNPP_GetJavaClass: + TRACE( "eNPP_GetJavaClass" ); + OSL_ENSURE( false, "NPP_GetJavaClass: not implemented!" ); + break; + } + return nRet; +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_Destroy( XPlugin_Impl* i_pImpl, NPSavedData** save ) +{ + // remove from NullEvent timer + m_aNullEventClients.remove( i_pImpl ); + + NPError nErr = NPP_Destroy( i_pImpl->getNPPInstance(), save ); + + // release plugin view + SysPlugData& rPlugData( i_pImpl->getSysPlugData() ); + if( rPlugData.m_pPlugView ) + { + [rPlugData.m_pPlugView removeFromSuperview]; + [rPlugData.m_pPlugView release]; + rPlugData.m_pPlugView = nil; + } + + return nErr; +} + + +NPError MacPluginComm::NPP_Destroy( NPP instance, NPSavedData** save ) +{ + DBG_ASSERT( m_aNPPfuncs.destroy, "### NPP_Destroy(): null pointer in NPP functions table!" ); + m_eCall = eNPP_Destroy; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)save; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_DestroyStream( NPP instance, NPStream* stream, NPError reason ) +{ + DBG_ASSERT( m_aNPPfuncs.destroystream, "### NPP_DestroyStream(): null pointer in NPP functions table!" ); + m_eCall = eNPP_DestroyStream; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + m_aArgs[2] = (void*)reason; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, + char* argn[], char* argv[], NPSavedData *saved ) +{ + XPlugin_Impl* pImpl = XPluginManager_Impl::getXPluginFromNPP( instance ); + DBG_ASSERT( pImpl, "no instance found" ); + + if( pImpl ) // sanity check + m_aNullEventClients.push_back( pImpl ); + + DBG_ASSERT( m_aNPPfuncs.newp, "### NPP_New(): null pointer in NPP functions table!" ); + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "NPP_New( %s. %p, %d, %d", + pluginType, instance, (int)mode, (int)argc ); + for( int16 i = 0; i < argc; i++ ) + fprintf( stderr, "\n%s = %s", argn[i], argv[i] ); + fprintf( stderr, ", %p )\n", saved ); + #endif + m_eCall = eNPP_New; + m_aArgs[0] = (void*)pluginType; + m_aArgs[1] = (void*)instance; + m_aArgs[2] = (void*)mode; + m_aArgs[3] = (void*)argc; + m_aArgs[4] = (void*)argn; + m_aArgs[5] = (void*)argv; + m_aArgs[6] = (void*)saved; + + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_NewStream( NPP instance, NPMIMEType type, NPStream* stream, + NPBool seekable, uint16* stype ) +{ + DBG_ASSERT( m_aNPPfuncs.newstream, "### NPP_NewStream(): null pointer in NPP functions table!" ); + m_eCall = eNPP_NewStream; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)type; + m_aArgs[2] = (void*)stream; + m_aArgs[3] = (void*)seekable; + m_aArgs[4] = (void*)stype; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +void MacPluginComm::NPP_Print( NPP instance, NPPrint* platformPrint ) +{ + DBG_ASSERT( m_aNPPfuncs.print, "### NPP_Print(): null pointer in NPP functions table!" ); + m_eCall = eNPP_Print; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)platformPrint; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_SetWindow( NPP instance, NPWindow* window ) +{ + DBG_ASSERT( m_aNPPfuncs.setwindow, "### NPP_SetWindow(): null pointer in NPP functions table!" ); + m_eCall = eNPP_SetWindow; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)window; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_HandleEvent( NPP instance, void* event ) +{ + DBG_ASSERT( m_aNPPfuncs.event, "### NPP_HandleEvent(): null pointer in NPP functions table!" ); + m_eCall = eNPP_HandleEvent; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = event; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +void MacPluginComm::NPP_StreamAsFile( NPP instance, NPStream* stream, const char* fname ) +{ + DBG_ASSERT( m_aNPPfuncs.asfile, "### NPP_StreamAsFile(): null pointer in NPP functions table!" ); + m_eCall = eNPP_StreamAsFile; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + m_aArgs[2] = (void*)fname; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +void MacPluginComm::NPP_URLNotify( NPP instance, const char* url, NPReason reason, void* notifyData ) +{ + DBG_ASSERT( m_aNPPfuncs.urlnotify, "### NPP_URLNotify(): null pointer in NPP functions table!" ); + m_eCall = eNPP_URLNotify; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)url; + m_aArgs[2] = (void*)reason; + m_aArgs[3] = notifyData; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +int32 MacPluginComm::NPP_Write( NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer ) +{ + DBG_ASSERT( m_aNPPfuncs.write, "### NPP_Write(): null pointer in NPP functions table!" ); + m_eCall = eNPP_Write; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + m_aArgs[2] = (void*)offset; + m_aArgs[3] = (void*)len; + m_aArgs[4] = buffer; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +int32 MacPluginComm::NPP_WriteReady( NPP instance, NPStream* stream ) +{ + DBG_ASSERT( m_aNPPfuncs.writeready, "### NPP_WriteReady(): null pointer in NPP functions table!" ); + m_eCall = eNPP_WriteReady; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)stream; + return execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_GetValue( NPP instance, NPPVariable variable, void *ret_value ) +{ + DBG_ASSERT( m_aNPPfuncs.getvalue, "### NPP_GetValue(): null pointer in NPP functions table!" ); + m_eCall = eNPP_GetValue; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)variable; + m_aArgs[2] = ret_value; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_SetValue( NPP instance, NPNVariable variable, void *set_value ) +{ + DBG_ASSERT( m_aNPPfuncs.setvalue, "### NPP_SetValue(): null pointer in NPP functions table!" ); + m_eCall = eNPP_SetValue; + m_aArgs[0] = (void*)instance; + m_aArgs[1] = (void*)variable; + m_aArgs[2] = set_value; + return (NPError)execute(); +} + +//-------------------------------------------------------------------------------------------------- +void * MacPluginComm::NPP_GetJavaClass() +{ + DBG_ERROR( "no java class available!" ); + return 0; +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_Initialize() +{ + return NPERR_NO_ERROR; +} + +//-------------------------------------------------------------------------------------------------- +void MacPluginComm::NPP_Shutdown() +{ + m_eCall = eNPP_Shutdown; + execute(); +} + +//-------------------------------------------------------------------------------------------------- +NPError MacPluginComm::NPP_SetWindow( XPlugin_Impl* i_pImpl ) +{ + // update window NPWindow from view + SysPlugData& rPlugData( i_pImpl->getSysPlugData() ); + + // update plug view + NSRect aPlugRect = [rPlugData.m_pParentView frame]; + aPlugRect.origin.x = aPlugRect.origin.y = 0; + if( ! rPlugData.m_pPlugView ) + { + rPlugData.m_pPlugView = [[OOoPluginView alloc] initWithInstance: i_pImpl pluginComm: this frame: aPlugRect]; + [rPlugData.m_pParentView addSubview: rPlugData.m_pPlugView]; + } + else + [rPlugData.m_pPlugView setFrame: aPlugRect]; + + NPWindow* pNPWin = i_pImpl->getNPWindow(); + NSWindow* pWin = [rPlugData.m_pPlugView window]; + NSRect aWinRect = [pWin frame]; + NSRect aBounds = [rPlugData.m_pPlugView frame]; + NSRect aVisibleBounds = [rPlugData.m_pPlugView visibleRect]; + + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "visible bounds = %d+%d+%dx%d\n", + (int)aVisibleBounds.origin.x, (int)aVisibleBounds.origin.y, + (int)aVisibleBounds.size.width, (int)aVisibleBounds.size.height ); + #endif + + NSPoint aViewOrigin = [rPlugData.m_pPlugView convertPoint: NSZeroPoint toView: nil]; + // save view origin so we can notice movement of the view in drawView + // in case of a moved view we need to reset the port/context + rPlugData.m_aLastPlugViewOrigin = aViewOrigin; + + // convert view origin to topdown coordinates + aViewOrigin.y = aWinRect.size.height - aViewOrigin.y; + + // same for clipping + NSPoint aClipOrigin = [rPlugData.m_pPlugView convertPoint: aVisibleBounds.origin toView: nil]; + aClipOrigin.y = aWinRect.size.height - aClipOrigin.y; + + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "view origin: %d+%d, clip origin = %d+%d\n", + (int)aViewOrigin.x, (int)aViewOrigin.y, + (int)aClipOrigin.x, (int)aClipOrigin.y ); + #endif + + pNPWin->x = aViewOrigin.x; + pNPWin->y = aViewOrigin.y; + pNPWin->width = aBounds.size.width; + pNPWin->height = aBounds.size.height; + pNPWin->clipRect.left = aClipOrigin.x; + pNPWin->clipRect.top = aClipOrigin.y; + pNPWin->clipRect.right = aClipOrigin.x + aVisibleBounds.size.width; + pNPWin->clipRect.bottom = aClipOrigin.y + aVisibleBounds.size.height; + + if( rPlugData.m_nDrawingModel == 1 ) + { + rPlugData.m_aCGContext.window = reinterpret_cast<WindowRef>([pWin windowRef]); + pNPWin->window = &rPlugData.m_aCGContext; + rPlugData.m_aCGContext.context = reinterpret_cast<CGContextRef>([[pWin graphicsContext] graphicsPort]); + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "window is %p, context is %p\n", + rPlugData.m_aCGContext.window, rPlugData.m_aCGContext.context ); + #endif + } + else + { + rPlugData.m_aNPPort.port = GetWindowPort( reinterpret_cast<WindowRef>([pWin windowRef]) ); + rPlugData.m_aNPPort.portx = aClipOrigin.x; + rPlugData.m_aNPPort.porty = aClipOrigin.y; + pNPWin->window = &rPlugData.m_aNPPort; + #if OSL_DEBUG_LEVEL > 1 + fprintf( stderr, "port is %p at (%d,%d)\n", + rPlugData.m_aNPPort.port, (int)rPlugData.m_aNPPort.portx, (int)rPlugData.m_aNPPort.porty ); + #endif + } + + if( pNPWin->width == 0 || pNPWin->height == 0 || [rPlugData.m_pPlugView isHiddenOrHasHiddenAncestor] ) + rPlugData.m_bSetWindowOnDraw = true; + + NPError nErr = NPP_SetWindow( i_pImpl->getNPPInstance(), i_pImpl->getNPWindow() ); + + return nErr; +} + +void MacPluginComm::drawView( XPlugin_Impl* i_pImpl ) +{ + SysPlugData& rPlugData( i_pImpl->getSysPlugData() ); + + // check if the view was moved since the last SetWindow + NSPoint aViewOrigin = [rPlugData.m_pPlugView convertPoint: NSZeroPoint toView: nil]; + if( rPlugData.m_bSetWindowOnDraw || + aViewOrigin.x != rPlugData.m_aLastPlugViewOrigin.x || + aViewOrigin.y != rPlugData.m_aLastPlugViewOrigin.y ) + { + NPP_SetWindow( i_pImpl ); + rPlugData.m_bSetWindowOnDraw = false; + } + + // send a paint event + NSWindow* pWin = [rPlugData.m_pPlugView window]; + FakeEventRecord aRec; + aRec.what = updateEvt; + aRec.message = (UInt32)[pWin windowRef]; + this->NPP_HandleEvent( i_pImpl->getNPPInstance(), &aRec ); +} + |