summaryrefslogtreecommitdiff
path: root/extensions/source/plugin/aqua
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/source/plugin/aqua')
-rw-r--r--extensions/source/plugin/aqua/macmgr.cxx646
-rw-r--r--extensions/source/plugin/aqua/makefile.mk75
-rw-r--r--extensions/source/plugin/aqua/sysplug.cxx808
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 );
+}
+