Browse Source

First version of the ActiveX browser plugin wrapper

tags/2021-05-28
jules 16 years ago
parent
commit
c0ddf1406c
12 changed files with 970 additions and 249 deletions
  1. +14
    -0
      extras/browser plugins/How to build a browser plugin.txt
  2. +0
    -0
      extras/browser plugins/demo/build/mac/English.lproj/InfoPlist.strings
  3. +0
    -0
      extras/browser plugins/demo/build/mac/Info.plist
  4. +0
    -0
      extras/browser plugins/demo/build/mac/JuceBrowserPluginDemo.xcodeproj/TemplateIcon.tiff
  5. +0
    -0
      extras/browser plugins/demo/build/mac/JuceBrowserPluginDemo.xcodeproj/project.pbxproj
  6. +0
    -20
      extras/browser plugins/demo/build/npapi_win/JuceBrowserPluginDemo.sln
  7. +0
    -216
      extras/browser plugins/demo/build/npapi_win/JuceBrowserPluginDemo.vcproj
  8. +5
    -0
      extras/browser plugins/demo/src/BrowserPluginCharacteristics.h
  9. +1
    -1
      extras/browser plugins/demo/src/JuceBrowserPluginDemo.cpp
  10. +10
    -2
      extras/browser plugins/demo/test.html
  11. +926
    -0
      extras/browser plugins/wrapper/juce_ActiveX_GlueCode.cpp
  12. +14
    -10
      extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp

+ 14
- 0
extras/browser plugins/How to build a browser plugin.txt View File

@@ -53,3 +53,17 @@ Building a Windows NPAPI plugin in Visual Studio
- Note that the "browser plugins/wrapper/npapi" folder contains a copy of some NPAPI header files. If you're
building a closed-source project, please check the licensing details in these files to make sure
you're not breaking any Mozilla licensing restictions.
Building a Windows ActiveX control for Internet Explorer
--------------------------------------------------------
- This is actually quite easy, because the same DLL that functions as an NPAPI plugin can
also be used as an ActiveX control.
- Just create a windows NPAPI plugin as described above, but add the juce_ActiveX_GlueCode.cpp
file to the project.
- In your BrowserPluginCharacteristics.h file, the JuceBrowserPlugin_ActiveXCLSID setting needs
to be given a unique GUID for your plugin.
- Because the plugin is a COM object, it doesn't matter where the DLL lives, but it needs to
be registered in the normal COM way, with regsvr32.exe. Note that on Vista, this command
needs to be run with administrator permissions for it to be able to write to the registry.

extras/browser plugins/demo/build/npapi_mac/English.lproj/InfoPlist.strings → extras/browser plugins/demo/build/mac/English.lproj/InfoPlist.strings View File


extras/browser plugins/demo/build/npapi_mac/Info.plist → extras/browser plugins/demo/build/mac/Info.plist View File


extras/browser plugins/demo/build/npapi_mac/JuceBrowserPluginDemo.xcodeproj/TemplateIcon.tiff → extras/browser plugins/demo/build/mac/JuceBrowserPluginDemo.xcodeproj/TemplateIcon.tiff View File


extras/browser plugins/demo/build/npapi_mac/JuceBrowserPluginDemo.xcodeproj/project.pbxproj → extras/browser plugins/demo/build/mac/JuceBrowserPluginDemo.xcodeproj/project.pbxproj View File


+ 0
- 20
extras/browser plugins/demo/build/npapi_win/JuceBrowserPluginDemo.sln View File

@@ -1,20 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JuceBrowserPluginDemo", "JuceBrowserPluginDemo.vcproj", "{865C6463-5BC7-4F36-8667-FF9221C32797}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{865C6463-5BC7-4F36-8667-FF9221C32797}.Debug|Win32.ActiveCfg = Debug|Win32
{865C6463-5BC7-4F36-8667-FF9221C32797}.Debug|Win32.Build.0 = Debug|Win32
{865C6463-5BC7-4F36-8667-FF9221C32797}.Release|Win32.ActiveCfg = Release|Win32
{865C6463-5BC7-4F36-8667-FF9221C32797}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

+ 0
- 216
extras/browser plugins/demo/build/npapi_win/JuceBrowserPluginDemo.vcproj View File

@@ -1,216 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="JuceBrowserPluginDemo"
ProjectGUID="{865C6463-5BC7-4F36-8667-FF9221C32797}"
RootNamespace="JuceBrowserPluginDemo"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../src"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;JUCEBROWSERPLUGINDEMO_EXPORTS"
MinimalRebuild="false"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories="../../src"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\np$(ProjectName).dll"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
CommandLine="copy /Y &quot;$(TargetPath)&quot; &quot;C:\Program Files\Mozilla Firefox\plugins&quot;"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="../../src"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;JUCEBROWSERPLUGINDEMO_EXPORTS"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
AdditionalIncludeDirectories="../../src"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)\np$(ProjectName).dll"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\BrowserPluginCharacteristics.h"
>
</File>
<File
RelativePath="..\..\src\juce_LibrarySource.cpp"
>
</File>
<File
RelativePath="..\..\src\JuceBrowserPluginDemo.cpp"
>
</File>
<Filter
Name="wrapper"
>
<File
RelativePath="..\..\..\wrapper\juce_BrowserPluginComponent.h"
>
</File>
<File
RelativePath="..\..\..\wrapper\juce_IncludeBrowserPluginInfo.h"
>
</File>
<File
RelativePath="..\..\..\wrapper\juce_NPAPI_GlueCode.cpp"
>
</File>
<File
RelativePath="..\..\..\wrapper\juce_NPAPI_WinResource.rc"
>
</File>
</Filter>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

+ 5
- 0
extras/browser plugins/demo/src/BrowserPluginCharacteristics.h View File

@@ -35,3 +35,8 @@
can open. If you don't need to use it, just use a made-up name here.
*/
#define JuceBrowserPlugin_FileSuffix ".jucedemo"
/** If you're building an activeX version, you'll need to create a unique GUID for
your plugin. Use a tool like uuidgen.exe to create this.
*/
#define JuceBrowserPlugin_ActiveXCLSID "F683B990-3ADF-11DE-BDFE-F9CB55D89593"

+ 1
- 1
extras/browser plugins/demo/src/JuceBrowserPluginDemo.cpp View File

@@ -120,7 +120,7 @@ public:
if (numParams > 0)
owner->textBox->setText (owner->textBox->getText() + "\n" + params[0].toString());

return var();
return "text was printed ok!";
}

const var popUpMessageBox (const var* params, int numParams)


+ 10
- 2
extras/browser plugins/demo/test.html View File

@@ -15,7 +15,8 @@ function getPlugin()

function showAMessage()
{
getPlugin().printText ("This is a message sent from the website's javascript...");
var response = getPlugin().printText ("This is a message sent from the website's javascript...");
printmessage (response);
}

function popUpMessageBox()
@@ -40,7 +41,14 @@ function sendCallbackObjectToPlugin()

</script>

<embed id="plugin" type="application/npjucedemo-plugin" width=80% height=400>
<!-- This tag works in IE - for Netscape plugins, remove or rename the classid tag
and it should use the npapi plugin instead -->
<object id="plugin"
type="application/npjucedemo-plugin"
classid="CLSID:F683B990-3ADF-11DE-BDFE-F9CB55D89593"
width="80%" height="400">
</object>


<br>
<form name="formname">


+ 926
- 0
extras/browser plugins/wrapper/juce_ActiveX_GlueCode.cpp View File

@@ -0,0 +1,926 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
//==============================================================================
/*
This file contains all the gubbins to create an ActiveX browser plugin that
wraps your BrowserPluginComponent object.
*/
//==============================================================================
#if _MSC_VER
//==============================================================================
#include <windows.h>
#include <windowsx.h>
#include <olectl.h>
#include <objsafe.h>
#pragma warning (disable:4584)
#include "../../../juce_amalgamated.h"
#include "juce_BrowserPluginComponent.h"
#include "juce_IncludeBrowserPluginInfo.h"
#ifndef JuceBrowserPlugin_ActiveXCLSID
#error "For an activeX plugin, you need to define JuceBrowserPlugin_ActiveXCLSID in your BrowserPluginCharacteristics.h file!"
#endif
//==============================================================================
#if JUCE_MAC && JUCE_DEBUG && 0
static void log (const String& s)
{
FILE* f = fopen ("/Users/jules/Desktop/log.txt", "a+");
fprintf (f, (const char*) s);
fprintf (f, "\n");
fflush (f);
fclose (f);
}
#else
#define log(a) DBG(a)
#endif
// Cunning trick used to add functions to export list without messing about with .def files.
#define EXPORTED_FUNCTION comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
//==============================================================================
static void juceVarToVariant (const var& v, VARIANT& dest);
static const var variantTojuceVar (const VARIANT& v);
#if JUCE_DEBUG
static int numDOWID = 0, numJuceSO = 0;
#endif
//==============================================================================
// Takes care of the logic in invoking var methods from IDispatch callbacks.
class IDispatchHelper
{
public:
IDispatchHelper() {}
~IDispatchHelper() {}
var::identifier getId (int hash) const
{
for (int i = knownIdentifiers.size(); --i >= 0;)
if (knownIdentifiers.getUnchecked(i)->hashCode == hash)
return *knownIdentifiers.getUnchecked(i);
return var::identifier (String::empty);
}
var::identifier getId (const String& name)
{
for (int i = knownIdentifiers.size(); --i >= 0;)
if (knownIdentifiers.getUnchecked(i)->name == name)
return *knownIdentifiers.getUnchecked(i);
const var::identifier v (name);
knownIdentifiers.add (new var::identifier (v));
return v;
}
HRESULT doGetIDsOfNames (LPOLESTR* rgszNames, UINT cNames, DISPID* rgDispId)
{
for (unsigned int i = 0; i < cNames; ++i)
{
var::identifier id (getId (rgszNames[i]));
rgDispId[i] = (DISPID) id.hashCode;
}
return S_OK;
}
HRESULT doInvoke (const var& v,
DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
const var::identifier memberId (getId ((int) dispIdMember));
if (memberId.name.isEmpty() || v.getObject() == 0)
return DISP_E_MEMBERNOTFOUND;
if ((wFlags & DISPATCH_METHOD) != 0)
{
if (! v.getObject()->hasMethod (memberId))
return DISP_E_MEMBERNOTFOUND;
const int numArgs = pDispParams == 0 ? 0 : pDispParams->cArgs;
var result;
if (numArgs == 0)
{
result = v.call (memberId);
}
else
{
var* args = (var*) juce_calloc (sizeof (var) * numArgs);
for (int j = 0; j < numArgs; ++j)
args[j] = variantTojuceVar (pDispParams->rgvarg[j]);
result = v.invoke (memberId, args, numArgs);
for (int j = 0; j < numArgs; ++j)
args[j] = var();
juce_free (args);
}
if (pVarResult != 0)
juceVarToVariant (result, *pVarResult);
return S_OK;
}
else if ((wFlags & DISPATCH_PROPERTYGET) != 0)
{
if (! v.getObject()->hasProperty (memberId))
return DISP_E_MEMBERNOTFOUND;
if (pVarResult != 0)
{
juceVarToVariant (v.getObject()->getProperty (memberId), *pVarResult);
return S_OK;
}
}
else if ((wFlags & DISPATCH_PROPERTYPUT) != 0)
{
if (pDispParams != 0 && pDispParams->cArgs > 0)
{
v.getObject()->setProperty (memberId, variantTojuceVar (pDispParams->rgvarg[0]));
return S_OK;
}
}
return DISP_E_MEMBERNOTFOUND;
}
private:
OwnedArray <var::identifier> knownIdentifiers;
IDispatchHelper (const IDispatchHelper&);
const IDispatchHelper& operator= (const IDispatchHelper&);
};
//==============================================================================
// Makes a var look like an IDispatch
class IDispatchWrappingDynamicObject : public IDispatch
{
public:
IDispatchWrappingDynamicObject (const var& object_)
: object (object_),
refCount (0)
{
DBG ("num Juce wrapper objs: " + String (++numJuceSO));
}
virtual ~IDispatchWrappingDynamicObject()
{
DBG ("num Juce wrapper objs: " + String (--numJuceSO));
}
HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
{
if (id == IID_IUnknown) { AddRef(); *result = (IUnknown*) this; return S_OK; }
else if (id == IID_IDispatch) { AddRef(); *result = (IDispatch*) this; return S_OK; }
*result = 0;
return E_NOINTERFACE;
}
ULONG __stdcall AddRef() { return ++refCount; }
ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
HRESULT __stdcall GetTypeInfoCount (UINT*) { return E_NOTIMPL; }
HRESULT __stdcall GetTypeInfo (UINT, LCID, ITypeInfo**) { return E_NOTIMPL; }
HRESULT __stdcall GetIDsOfNames (REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId)
{
return iDispatchHelper.doGetIDsOfNames (rgszNames, cNames, rgDispId);
}
HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
return iDispatchHelper.doInvoke (object, dispIdMember, riid, lcid, wFlags, pDispParams,
pVarResult, pExcepInfo, puArgErr);
}
private:
//==============================================================================
var object;
int refCount;
IDispatchHelper iDispatchHelper;
};
//==============================================================================
// Makes an IDispatch look like a var
class DynamicObjectWrappingIDispatch : public DynamicObject
{
IDispatch* const source;
public:
DynamicObjectWrappingIDispatch (IDispatch* const source_)
: source (source_)
{
source->AddRef();
DBG ("num IDispatch wrapper objs: " + String (++numDOWID));
}
~DynamicObjectWrappingIDispatch()
{
source->Release();
DBG ("num IDispatch wrapper objs: " + String (--numDOWID));
}
const var getProperty (const var::identifier& propertyName) const
{
LPCOLESTR name = (LPCOLESTR) propertyName.name;
DISPID id = 0;
if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*)&name, 1, 0, &id) == S_OK)
{
EXCEPINFO excepInfo;
DISPPARAMS params;
zerostruct (params);
UINT argError;
VARIANT result;
zerostruct (result);
if (source->Invoke (id, IID_NULL, 0, DISPATCH_PROPERTYGET,
&params, &result, &excepInfo, &argError) == S_OK)
{
var v (variantTojuceVar (result));
VariantClear (&result);
return v;
}
}
return var();
}
bool hasProperty (const var::identifier& propertyName) const
{
LPCOLESTR name = (LPCOLESTR) propertyName.name;
DISPID id = 0;
return source->GetIDsOfNames (IID_NULL, (LPOLESTR*)&name, 1, 0, &id) == S_OK;
}
void setProperty (const var::identifier& propertyName, const var& newValue)
{
LPCOLESTR name = (LPCOLESTR) propertyName.name;
DISPID id = 0;
if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*)&name, 1, 0, &id) == S_OK)
{
VARIANT param;
zerostruct (param);
juceVarToVariant (newValue, param);
DISPPARAMS dispParams;
zerostruct (dispParams);
dispParams.cArgs = 1;
dispParams.rgvarg = &param;
EXCEPINFO excepInfo;
zerostruct (excepInfo);
VARIANT result;
zerostruct (result);
UINT argError = 0;
if (source->Invoke (id, IID_NULL, 0, DISPATCH_PROPERTYPUT,
&dispParams, &result, &excepInfo, &argError) == S_OK)
{
VariantClear (&result);
}
VariantClear (&param);
}
}
void removeProperty (const var::identifier& propertyName)
{
setProperty (propertyName, var());
}
bool hasMethod (const var::identifier& methodName) const
{
LPCOLESTR name = (LPCOLESTR) methodName.name;
DISPID id = 0;
return source->GetIDsOfNames (IID_NULL, (LPOLESTR*)&name, 1, 0, &id) == S_OK;
}
const var invokeMethod (const var::identifier& methodName,
const var* parameters,
int numParameters)
{
var returnValue;
LPCOLESTR name = (LPCOLESTR) methodName.name;
DISPID id = 0;
if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*)&name, 1, 0, &id) == S_OK)
{
VARIANT* params = (VARIANT*) juce_calloc (sizeof (VARIANT) * (numParameters + 1));
for (int i = 0; i < numParameters; ++i)
juceVarToVariant (parameters[i], params[i]);
DISPPARAMS dispParams;
zerostruct (dispParams);
dispParams.cArgs = numParameters;
dispParams.rgvarg = params;
EXCEPINFO excepInfo;
zerostruct (excepInfo);
VARIANT result;
zerostruct (result);
UINT argError = 0;
if (source->Invoke (id, IID_NULL, 0, DISPATCH_METHOD,
&dispParams, &result, &excepInfo, &argError) == S_OK)
{
returnValue = variantTojuceVar (result);
VariantClear (&result);
}
juce_free (params);
}
return returnValue;
}
};
//==============================================================================
void juceVarToVariant (const var& v, VARIANT& dest)
{
if (v.isVoid())
{
dest.vt = VT_EMPTY;
}
else if (v.isInt())
{
dest.vt = VT_INT;
dest.intVal = (int) v;
}
else if (v.isBool())
{
dest.vt = VT_BOOL;
dest.boolVal = (int) v;
}
else if (v.isDouble())
{
dest.vt = VT_R8;
dest.dblVal = (double) v;
}
else if (v.isString())
{
dest.vt = VT_BSTR;
dest.bstrVal = SysAllocString (v.toString());
}
else if (v.isObject())
{
dest.vt = VT_DISPATCH;
dest.pdispVal = new IDispatchWrappingDynamicObject (v);
}
else if (v.isMethod())
{
dest.vt = VT_EMPTY;
}
}
const var variantTojuceVar (const VARIANT& v)
{
if ((v.vt & VT_ARRAY) != 0)
{
//xxx
}
else
{
switch (v.vt & ~VT_BYREF)
{
case VT_VOID:
case VT_EMPTY: return var();
case VT_I1: return var ((int) v.cVal);
case VT_I2: return var ((int) v.iVal);
case VT_I4: return var ((int) v.lVal);
case VT_I8: return var (String (v.llVal));
case VT_UI1: return var ((int) v.bVal);
case VT_UI2: return var ((int) v.uiVal);
case VT_UI4: return var ((int) v.ulVal);
case VT_UI8: return var (String (v.ullVal));
case VT_INT: return var ((int) v.intVal);
case VT_UINT: return var ((int) v.uintVal);
case VT_R4: return var ((double) v.fltVal);
case VT_R8: return var ((double) v.dblVal);
case VT_BSTR: return var (v.bstrVal);
case VT_BOOL: return var (v.boolVal ? true : false);
case VT_DISPATCH: return var (new DynamicObjectWrappingIDispatch (v.pdispVal));
default:
break;
}
}
return var();
}
//==============================================================================
// This acts as the embedded HWND
class AXBrowserPluginHolderComponent : public Component
{
public:
//==============================================================================
AXBrowserPluginHolderComponent()
: child (0),
parentHWND (0)
{
setOpaque (true);
setWantsKeyboardFocus (false);
addAndMakeVisible (child = createBrowserPlugin());
jassert (child != 0); // You have to create one of these!
}
~AXBrowserPluginHolderComponent()
{
setWindow (0);
deleteAndZero (child);
}
//==============================================================================
void paint (Graphics& g)
{
if (child == 0 || ! child->isOpaque())
g.fillAll (Colours::white);
}
void resized()
{
if (child != 0)
child->setBounds (0, 0, getWidth(), getHeight());
}
const var getObject() { return child->getJavascriptObject(); }
void setWindow (IOleInPlaceSite* site)
{
HWND newHWND = 0;
if (site != 0)
site->GetWindow (&newHWND);
//log ("setWindow: " + String ((int) newHWND));
if (parentHWND != newHWND)
{
removeFromDesktop();
setVisible (false);
parentHWND = newHWND;
if (parentHWND != 0)
{
addToDesktop (0);
HWND ourHWND = (HWND) getWindowHandle();
SetParent (ourHWND, parentHWND);
DWORD val = GetWindowLong (ourHWND, GWL_STYLE);
val = (val & ~WS_POPUP) | WS_CHILD;
SetWindowLong (ourHWND, GWL_STYLE, val);
setVisible (true);
}
}
if (site != 0)
site->OnInPlaceActivate();
}
private:
//==============================================================================
BrowserPluginComponent* child;
HWND parentHWND;
};
//==============================================================================
class JuceActiveXObject : public IUnknown,
public IDispatch,
public IObjectWithSite,
public IObjectSafety,
public IOleInPlaceObject
{
public:
JuceActiveXObject()
: refCount (0)
{
log ("JuceActiveXObject");
site = 0;
holderComp = 0;
}
~JuceActiveXObject()
{
deleteAndZero (holderComp);
log ("~JuceActiveXObject");
}
HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
{
if (id == IID_IUnknown) { AddRef(); *result = (IUnknown*) this; return S_OK; }
else if (id == IID_IDispatch) { AddRef(); *result = (IDispatch*) this; return S_OK; }
else if (id == IID_IObjectWithSite) { AddRef(); *result = (IObjectWithSite*) this; return S_OK; }
else if (id == IID_IObjectSafety) { AddRef(); *result = (IObjectSafety*) this; return S_OK; }
else if (id == IID_IOleInPlaceObject) { AddRef(); *result = (IOleInPlaceObject*) this; return S_OK; }
else if (id == IID_IOleWindow) { AddRef(); *result = (IOleWindow*) (IOleInPlaceObject*) this; return S_OK; }
*result = 0;
return E_NOINTERFACE;
}
ULONG __stdcall AddRef() { return ++refCount; }
ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
HRESULT __stdcall GetTypeInfoCount (UINT* pctinfo) { return E_NOTIMPL; }
HRESULT __stdcall GetTypeInfo (UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { return E_NOTIMPL; }
HRESULT __stdcall GetIDsOfNames (REFIID riid, LPOLESTR* rgszNames, UINT cNames,
LCID lcid, DISPID* rgDispId)
{
return iDispatchHelper.doGetIDsOfNames (rgszNames, cNames, rgDispId);
}
HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pVarResult,
EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
if (holderComp == 0)
return DISP_E_MEMBERNOTFOUND;
return iDispatchHelper.doInvoke (holderComp->getObject(),
dispIdMember, riid, lcid, wFlags, pDispParams,
pVarResult, pExcepInfo, puArgErr);
}
HRESULT __stdcall SetSite (IUnknown* newSite)
{
if (newSite != site)
{
if (site != 0)
site->Release();
site = newSite;
if (site != 0)
{
site->AddRef();
IOleInPlaceSite* inPlaceSite = 0;
site->QueryInterface (IID_IOleInPlaceSite, (void**) &inPlaceSite);
if (inPlaceSite != 0)
{
if (holderComp == 0)
holderComp = new AXBrowserPluginHolderComponent();
holderComp->setWindow (inPlaceSite);
inPlaceSite->Release();
}
else
{
deleteAndZero (holderComp);
}
}
else
{
deleteAndZero (holderComp);
}
}
return S_OK;
}
HRESULT __stdcall GetSite (REFIID riid, void **ppvSite)
{
*ppvSite = site;
return S_OK;
}
//==============================================================================
HRESULT __stdcall SetObjectRects (LPCRECT r, LPCRECT c)
{
if (holderComp != 0)
holderComp->setBounds (r->left, r->top, r->right - r->left, r->bottom - r->top);
return S_OK;
}
HRESULT __stdcall GetWindow (__RPC__deref_out_opt HWND* phwnd)
{
if (holderComp == 0)
return E_NOTIMPL;
*phwnd = (HWND) holderComp->getWindowHandle();
return S_OK;
}
//==============================================================================
HRESULT __stdcall ContextSensitiveHelp (BOOL fEnterMode) { return E_NOTIMPL; }
HRESULT __stdcall InPlaceDeactivate() { return E_NOTIMPL; }
HRESULT __stdcall UIDeactivate() { return E_NOTIMPL; }
HRESULT __stdcall ReactivateAndUndo() { return E_NOTIMPL; }
//==============================================================================
HRESULT __stdcall GetInterfaceSafetyOptions (REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
{
*pdwSupportedOptions = *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA;
return S_OK;
}
HRESULT __stdcall SetInterfaceSafetyOptions (REFIID, DWORD, DWORD) { return S_OK; }
private:
IUnknown* site;
int refCount;
AXBrowserPluginHolderComponent* holderComp;
IDispatchHelper iDispatchHelper;
JuceActiveXObject (const JuceActiveXObject&);
const JuceActiveXObject& operator= (const JuceActiveXObject&);
};
//==============================================================================
class JuceActiveXObjectFactory : public IUnknown,
public IClassFactory
{
public:
JuceActiveXObjectFactory() : refCount (0) {}
~JuceActiveXObjectFactory() {}
HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
{
if (id == IID_IUnknown) { AddRef(); *result = (IUnknown*) this; return S_OK; }
else if (id == IID_IClassFactory) { AddRef(); *result = (IClassFactory*) this; return S_OK; }
*result = 0;
return E_NOINTERFACE;
}
ULONG __stdcall AddRef() { return ++refCount; }
ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
HRESULT __stdcall CreateInstance (IUnknown* pUnkOuter, REFIID riid, void** ppvObject)
{
*ppvObject = 0;
if (pUnkOuter != 0 && riid != IID_IUnknown)
return CLASS_E_NOAGGREGATION;
JuceActiveXObject* ax = new JuceActiveXObject();
return ax->QueryInterface (riid, ppvObject);
}
HRESULT __stdcall LockServer (BOOL /*fLock*/) { return S_OK; }
private:
int refCount;
JuceActiveXObjectFactory (const JuceActiveXObjectFactory&);
const JuceActiveXObjectFactory& operator= (const JuceActiveXObjectFactory&);
};
//==============================================================================
extern String browserVersionDesc;
static const String getExePath()
{
TCHAR moduleFile [2048];
moduleFile[0] = 0;
GetModuleFileName (0, moduleFile, 2048);
return moduleFile;
}
static const String getExeVersion (const String& exeFileName, const String& fieldName)
{
String resultString;
DWORD pointlessWin32Variable;
DWORD size = GetFileVersionInfoSize (exeFileName, &pointlessWin32Variable);
if (size > 0)
{
void* const exeInfo = juce_calloc (size);
if (GetFileVersionInfo (exeFileName, 0, size, exeInfo))
{
TCHAR* result = 0;
unsigned int resultLen = 0;
// try the 1200 codepage (Unicode)
String queryStr ("\\StringFileInfo\\040904B0\\" + fieldName);
if (! VerQueryValue (exeInfo, queryStr, (void**) &result, &resultLen))
{
// try the 1252 codepage (Windows Multilingual)
queryStr = "\\StringFileInfo\\040904E4\\" + fieldName;
VerQueryValue (exeInfo, queryStr, (void**) &result, &resultLen);
}
resultString = String (result, resultLen);
}
juce_free (exeInfo);
}
return resultString;
}
//==============================================================================
extern "C" BOOL WINAPI DllMain (HANDLE instance, DWORD reason, LPVOID)
{
#pragma EXPORTED_FUNCTION
static int numPluginInstances = 0;
switch (reason)
{
case DLL_PROCESS_ATTACH:
log ("DLL_PROCESS_ATTACH");
if (numPluginInstances++ == 0)
{
log ("initialiseJuce_GUI()");
initialiseJuce_GUI();
browserVersionDesc = "Internet Explorer " + getExeVersion (getExePath(), "FileVersion");
}
PlatformUtilities::setCurrentModuleInstanceHandle (instance);
break;
case DLL_PROCESS_DETACH:
log ("DLL_PROCESS_DETACH");
if (--numPluginInstances == 0)
{
log ("shutdownJuce_GUI()");
browserVersionDesc = String::empty;
shutdownJuce_GUI();
}
break;
default:
break;
}
return TRUE;
}
static const String CLSIDToJuceString (REFCLSID clsid)
{
LPWSTR s = 0;
StringFromIID (clsid, &s);
if (s == 0)
return String::empty;
const String result (s);
LPMALLOC malloc;
CoGetMalloc (1, &malloc);
if (malloc != 0)
{
malloc->Free (s);
malloc->Release();
}
return result.removeCharacters (T("{}")).trim();
}
STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
#pragma EXPORTED_FUNCTION
*ppv = 0;
if (CLSIDToJuceString (rclsid) == String (JuceBrowserPlugin_ActiveXCLSID))
{
JuceActiveXObjectFactory* afx = new JuceActiveXObjectFactory();
if (afx->QueryInterface (riid, ppv) == S_OK)
return S_OK;
delete afx;
}
return CLASS_E_CLASSNOTAVAILABLE;
}
STDAPI DllCanUnloadNow()
{
#pragma EXPORTED_FUNCTION
return S_OK;
}
//==============================================================================
static const String makeLegalRegistryName (const String& s)
{
return s.retainCharacters (T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_."));
}
static HRESULT doRegistration (const bool unregister)
{
const String company (makeLegalRegistryName (JuceBrowserPlugin_Company));
const String plugin (makeLegalRegistryName (JuceBrowserPlugin_Name));
const String clsID ("{" + String (JuceBrowserPlugin_ActiveXCLSID) + "}");
const String root ("HKEY_CLASSES_ROOT\\");
const String companyDotPlugin (company + "." + plugin);
const String companyDotPluginCur (companyDotPlugin + ".1");
const String clsIDRoot (root + "CLSID\\" + clsID + "\\");
const String dllPath (File::getSpecialLocation (File::currentApplicationFile).getFullPathName());
StringPairArray settings;
settings.set (root + companyDotPluginCur + "\\", JuceBrowserPlugin_Name);
settings.set (root + companyDotPluginCur + "\\CLSID\\", clsID);
settings.set (root + companyDotPlugin + "\\", JuceBrowserPlugin_Name);
settings.set (root + companyDotPlugin + "\\CLSID\\", clsID);
settings.set (root + companyDotPlugin + "\\CurVer\\", companyDotPluginCur);
settings.set (clsIDRoot, JuceBrowserPlugin_Name);
settings.set (clsIDRoot + "Implemented Categories\\{7DD95801-9882-11CF-9FA9-00AA006C42C4}\\", String::empty);
settings.set (clsIDRoot + "Implemented Categories\\{7DD95802-9882-11CF-9FA9-00AA006C42C4}\\", String::empty);
settings.set (clsIDRoot + "ProgID\\", companyDotPluginCur);
settings.set (clsIDRoot + "VersionIndependentProgID\\", companyDotPlugin);
settings.set (clsIDRoot + "Programmable\\", String::empty);
settings.set (clsIDRoot + "InProcServer32\\", dllPath);
settings.set (clsIDRoot + "InProcServer32\\ThreadingModel", "Apartment");
settings.set (clsIDRoot + "Control\\", String::empty);
settings.set (clsIDRoot + "Insertable\\", String::empty);
settings.set (clsIDRoot + "ToolboxBitmap32\\", dllPath + ", 101");
settings.set (clsIDRoot + "TypeLib\\", "");
settings.set (clsIDRoot + "Version\\", JuceBrowserPlugin_Version);
if (unregister)
{
for (int i = 0; i < settings.getAllKeys().size(); ++i)
PlatformUtilities::deleteRegistryValue (settings.getAllKeys()[i]);
PlatformUtilities::deleteRegistryKey (root + companyDotPluginCur);
PlatformUtilities::deleteRegistryKey (root + companyDotPlugin);
PlatformUtilities::deleteRegistryKey (clsIDRoot);
if (PlatformUtilities::registryValueExists (clsIDRoot + "InProcServer32"))
return SELFREG_E_CLASS;
}
else
{
PlatformUtilities::deleteRegistryKey (clsIDRoot);
for (int i = 0; i < settings.getAllKeys().size(); ++i)
PlatformUtilities::setRegistryValue (settings.getAllKeys()[i],
settings [settings.getAllKeys()[i]]);
// check whether the registration actually worked - if not, we probably don't have
// enough privileges to write to the registry..
if (PlatformUtilities::getRegistryValue (clsIDRoot + "InProcServer32\\") != dllPath)
return SELFREG_E_CLASS;
}
return S_OK;
}
STDAPI DllRegisterServer()
{
#pragma EXPORTED_FUNCTION
return doRegistration (false);
}
STDAPI DllUnregisterServer()
{
#pragma EXPORTED_FUNCTION
return doRegistration (true);
}
#endif

+ 14
- 10
extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp View File

@@ -106,6 +106,7 @@ extern "C"
//==============================================================================
static NPNetscapeFuncs browser;
String browserVersionDesc;
//==============================================================================
NPError NP_GetValue (void* future, NPPVariable variable, void* value)
@@ -924,8 +925,8 @@ NPError NPP_New (NPMIMEType pluginType, NPP npp, ::uint16 mode, ::int16 argc, ch
if (numPluginInstances++ == 0)
{
initialiseJuce_GUI();
log ("initialiseJuce_GUI()");
initialiseJuce_GUI();
}
currentlyInitialisingNPP = npp;
@@ -950,8 +951,9 @@ NPError NPP_Destroy (NPP npp, NPSavedData** save)
if (--numPluginInstances == 0)
{
shutdownJuce_GUI();
log ("shutdownJuce_GUI()");
shutdownJuce_GUI();
browserVersionDesc = String::empty;
}
}
@@ -1100,15 +1102,17 @@ BrowserPluginComponent::BrowserPluginComponent()
BrowserPluginComponent::~BrowserPluginComponent()
{
}
const String BrowserPluginComponent::getBrowserVersion() const
{
String s;
if (getInstance (this) != 0)
s << browser.uagent (getInstance (this));
else
s << "Netscape Plugin V" << (int) ((browser.version >> 8) & 0xff)
<< "." << (int) (browser.version & 0xff);
if (browserVersionDesc.isEmpty())
{
if (getInstance (this) != 0)
browserVersionDesc << browser.uagent (getInstance (this));
else
browserVersionDesc << "Netscape Plugin V" << (int) ((browser.version >> 8) & 0xff)
<< "." << (int) (browser.version & 0xff);
}
return s;
return browserVersionDesc;
}

Loading…
Cancel
Save