Awesomium 1.6 RC1 Updates

Sep 20, 2010 at 8:57 PM
Edited Sep 20, 2010 at 8:58 PM

Awesomium 1.6 RC1 came out the other day - a couple of changes are required to the wrapper to get it working under 1.6 RC1, but so far it works great with the following modifications. (My M/C++ is tarnished and rusty, so call out any baddities ;)

Cjc.AwesomiumWrapper.h

1) Remove the methods for zoomIn and zoomOut and replace with setZoom:

 

void SetZoom(int zoomPercent) { webView->setZoom(zoomPercent); }

 

2) Modify the constructor with the following:

 

Awesomium::WebCoreConfig& webCoreOptions = *new Awesomium::WebCoreConfig();
//TODO: Create a full wrapper object around WebCoreConfig
webCoreOptions.setEnablePlugins(enablePlugins);
webCoreOptions.setUserDataPath(marshal_as<std::wstring>( userDataPath ));
webCoreOptions.setPluginPath(marshal_as<std::wstring>( pluginPath ));
webCoreOptions.setLogPath(marshal_as<std::wstring>( logPath ));
webCoreOptions.setLogLevel(level);
webCoreOptions.setUserAgentOverride(marshal_as<std::string>( userAgentOverride ));

webCore = new Awesomium::WebCore(webCoreOptions);

 

I took the lazy way out - if someone creates a full wrapper for WebCoreConfig, post below!

New Features:

Awesomium 1.6 RC1 also introduces a few new features too - I implemented a few of them in the wrapper as follows:

1) Ability to pause/resume rendering (Add to WebView class):

 

            void PauseRendering() { webView->pauseRendering(); }

            void ResumeRendering() { webView->resumeRendering(); }

 

2) Ability to intercept additional requests:

(Add the following somewhere within Cjc.Awesomiumwrapper.h

	public ref class ResourceResponse
	{
		public:
		
			property bool IsHandled;

			property array<unsigned char>^ Buffer;

			property String^ MimeType;

		internal:

			operator Awesomium::ResourceResponse*()
			{ 
				if (this->IsHandled == false)
					return nullptr;

				if (this->Buffer == nullptr || this->Buffer->Length == 0)
				{
					unsigned char result = { 0 };
					return Awesomium::ResourceResponse::Create( 1, &result, marshal_as<std::string>(this->MimeType));
				}

				pin_ptr<unsigned char> pinned = &this->Buffer[ 0 ];
				return Awesomium::ResourceResponse::Create(this->Buffer->Length, pinned, marshal_as<std::string>(this->MimeType));
			}

	};

	typedef void (*RequestHandler)( const std::string& url, const std::string& referrer );
	typedef void (*ResponseHandler)( const std::string& url, int statusCode, const Awesomium::ResourceResponseMetrics& metrics);

	class DelegatingResourceInterceptor : public Awesomium::ResourceInterceptor
	{
		public:
			virtual ~DelegatingResourceInterceptor() {}

			Awesomium::ResourceResponse* onRequest(Awesomium::WebView* caller, const std::string& url, const std::string& referrer)
			{
				if ( Request ) (*Request)( url, referrer );
				
				return response;
			}

			RequestHandler Request;
		
			void onResponse(Awesomium::WebView* caller, const std::string& url, int statusCode, const Awesomium::ResourceResponseMetrics& metrics)
			{
				if ( Response ) (*Response)( url, statusCode, metrics );
			}

			ResponseHandler Response;

			void SetResponse(Awesomium::ResourceResponse* response)
			{
				this->response = response;
			}
		private:

			Awesomium::ResourceResponse* response;
	};

	public ref class ResourceResponseMetrics
	{
		private:
			
			Awesomium::ResourceResponseMetrics* value;

		public:

			ResourceResponseMetrics() { this->value = new Awesomium::ResourceResponseMetrics(); }
			ResourceResponseMetrics( Awesomium::ResourceResponseMetrics* value ) { this->value = value; }

			virtual ~ResourceResponseMetrics() { delete value; }

			bool WasCached() { return value->wasCached; }
			int64 RequestTimeMs() { return value->requestTimeMs; }
			int64 ResponseTimeMs() { return value->responseTimeMs; }
			String^ MimeType() { return marshal_as<String^>( value->mimeType ); }

		internal:

			operator Awesomium::ResourceResponseMetrics() { return *value; }
	};

	public ref class ResourceInterceptor
	{
		public:

		private:
			DelegatingResourceInterceptor* resourceInterceptor;

			void OnRequest(const std::string& url, const std::string& referrer )
			{
				ResourceResponse^ result = gcnew ResourceResponse();
				Request(marshal_as<String^>( url ), marshal_as<String^>( referrer ), result );

				resourceInterceptor->SetResponse( (Awesomium::ResourceResponse*)result );
			}

			void OnResponse(const std::string& url, int statusCode, const Awesomium::ResourceResponseMetrics& metrics)
			{
				ResourceResponseMetrics^ gcMetrics = gcnew ResourceResponseMetrics( (Awesomium::ResourceResponseMetrics*)&metrics );
				Response(marshal_as<String^>( url ), statusCode, gcMetrics );
			}

			delegate void RequestInternal( const std::string& url, const std::string& referrer );
			delegate void ResponseInternal( const std::string& url, int statusCode, const Awesomium::ResourceResponseMetrics& metrics);

			RequestInternal^ requestInternal;
			ResponseInternal^ responseInternal;
		public:
			
			ResourceInterceptor()
			{
				this->resourceInterceptor = new DelegatingResourceInterceptor();

				this->resourceInterceptor->Request = (RequestHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
					requestInternal = gcnew RequestInternal(this, &ResourceInterceptor::OnRequest) ).ToPointer();

				this->resourceInterceptor->Response = (ResponseHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
					responseInternal = gcnew ResponseInternal(this, &ResourceInterceptor::OnResponse) ).ToPointer();
			}

			virtual ~ResourceInterceptor() { delete resourceInterceptor; resourceInterceptor = NULL; }

			delegate void RequestDelegate( String^ url, String^ referrer, ResourceResponse^ response );
			event RequestDelegate^ Request;

			delegate void ResponseDelegate( String^ url, int statusCode, ResourceResponseMetrics^ metrics );
			event ResponseDelegate^ Response;

		internal:

			operator DelegatingResourceInterceptor*() { return resourceInterceptor; }
	};

Add the following to WebView
            property ResourceInterceptor^ Interceptor
            {
                ResourceInterceptor^ get()
                {
                    return interceptor;
                }

                void set(ResourceInterceptor^ value)
                {
                    interceptor = value;
                    webView->setResourceInterceptor( value != nullptr ? value : (Awesomium::ResourceInterceptor*)NULL );
                }

            }

 

Coordinator
Sep 20, 2010 at 9:04 PM
Edited Sep 20, 2010 at 9:05 PM

Here's a WebCoreConfig wrapper.  Will get the rest on Codeplex asap.  FYI have reverted back to my original JSValue wrapper (instead of borrowing the one from Awesomium.net); needs some additions, but it'll be more robust overall.

	public ref class WebCoreConfig
	{
		private:

			Awesomium::WebCoreConfig* webCoreConfig;

		public:

			WebCoreConfig()
			{
				this->webCoreConfig = new Awesomium::WebCoreConfig();
			}

			WebCoreConfig( Awesomium::WebCoreConfig* webCoreConfig )
			{
				this->webCoreConfig = webCoreConfig;
			}

			virtual ~WebCoreConfig() { delete webCoreConfig; webCoreConfig = NULL; }

			void SetEnablePlugins( bool enablePlugins )
			{
				webCoreConfig->setEnablePlugins( enablePlugins );
			}

			void SetUserDataPath( String^ userDataPath )
			{
				webCoreConfig->setUserDataPath( marshal_as<std::wstring>( userDataPath ) );
			}

			void SetPluginPath( String^ pluginPath )
			{
				webCoreConfig->setPluginPath( marshal_as<std::wstring>( pluginPath ) );
			}

			void SetLogPath( String^ logPath )
			{
				webCoreConfig->setLogPath( marshal_as<std::wstring>( logPath ) );
			}

			void SetLogLevel( Awesomium::LogLevel logLevel )
			{
				webCoreConfig->setLogLevel( logLevel );
			}

			void SetUserAgentOverride( String^ userAgentOverride )
			{
				webCoreConfig->setUserAgentOverride( marshal_as<std::string>( userAgentOverride ) );
			}

			void SetProxyServer( String^ proxyServer )
			{
				webCoreConfig->setProxyServer( marshal_as<std::string>( proxyServer ) );
			}

			void SetProxyConfigScript( String^ proxyConfigScript )
			{
				webCoreConfig->setProxyConfigScript( marshal_as<std::string>( proxyConfigScript ) );
			}

			void SetSaveCacheAndCookies( bool saveCacheAndCookies )
			{
				webCoreConfig->setSaveCacheAndCookies( saveCacheAndCookies );
			}

			void SetMaxCacheSize( int maxCacheSize )
			{
				webCoreConfig->setMaxCacheSize( maxCacheSize );
			}

			void SetDisableSameOriginPolicy( bool disableSameOriginPolicy )
			{
				webCoreConfig->setDisableSameOriginPolicy( disableSameOriginPolicy );
			}

			void SetCustomCSS( String^ customCSS )
			{
				webCoreConfig->setCustomCSS( marshal_as<std::string>( customCSS ) );
			}

			void SetCustomCSSFromFile( String^ customCSSFilePath )
			{
				webCoreConfig->setCustomCSSFromFile( marshal_as<std::string>( customCSSFilePath ) );
			}

		internal:

			operator Awesomium::WebCoreConfig*() { return webCoreConfig; }
	};

 

 

Nov 19, 2010 at 8:42 PM

After all the hassle and tweaking to get it to build I can't get it to run properly.

WebSnapshot exits at line:

if ( RenderSnapshot( url, buffer, width, height, transparent ) == null )

with error:

The program '[1420] WebSnapshot.vshost.exe: Managed (v4.0.30319)' has exited with code -1073740777 (0xc0000417).

if I step through the program last line I get to before app exist is in Cjc.AwesomiumWrapper.h                

webCoreOptions.setUserAgentOverride(marshal_as<std::string>( userAgentOverride ));

if I comment out that line app exits on the line before that.

I'm building on Windows 7 machine in VS2010 Cjc.WPFChromium.4.0. using Awesomium v1.6 RC2 sdk for msvc9. I had to change one more thing not mentioned here:

Add

void onRequestDownload(Awesomium::WebView* caller,
const std::string& url)
{
	// Empty implementation to make project build
}

to Cjc.AwesomiumWrapper.h
Any help would be appreciated.

Jun 9, 2011 at 3:13 PM

Many people have had problems compiling Cjc.AwesomiumWrapper.h in version 1.6. So I leave the whole class to only copy and paste.

// Cjc.AwesomiumWrapper.h

#pragma once
#include <stdlib.h>
#include <string.h>
#include <msclr\marshal.h>
//#include <msclr\marshal_atl.h>
#include <msclr\marshal_cppstd.h>
#include <msclr\marshal_windows.h>
#include <cliext/adapter>
#include <cliext/map>
#include "WebCore.h"

using namespace System;
using namespace msclr::interop;

public enum CursorType
{
    CursorPointer,
    CursorCross,
    CursorHand,
    CursorIBeam,
    CursorWait,
    CursorHelp,
    CursorEastResize,
    CursorNorthResize,
    CursorNorthEastResize,
    CursorNorthWestResize,
    CursorSouthResize,
    CursorSouthEastResize,
    CursorSouthWestResize,
    CursorWestResize,
    CursorNorthSouthResize,
    CursorEastWestResize,
    CursorNorthEastSouthWestResize,
    CursorNorthWestSouthEastResize,
    CursorColumnResize,
    CursorRowResize,
    CursorMiddlePanning,
    CursorEastPanning,
    CursorNorthPanning,
    CursorNorthEastPanning,
    CursorNorthWestPanning,
    CursorSouthPanning,
    CursorSouthEastPanning,
    CursorSouthWestPanning,
    CursorWestPanning,
    CursorMove,
    CursorVerticalText,
    CursorCell,
    CursorContextMenu,
    CursorAlias,
    CursorProgress,
    CursorNoDrop,
    CursorCopy,
    CursorNone,
    CursorNotAllowed,
    CursorZoomIn,
    CursorZoomOut,
    CursorCustom
};

typedef void (*BeginNavigationHandler)( const std::string& url, const std::wstring& frameName );
typedef void (*BeginLoadingHandler)( const std::string& url, const std::wstring& frameName, int statusCode, const std::wstring& mimeType );
typedef void (*FinishLoadingHandler)();
typedef void (*CallbackHandler)( const std::wstring& objectName, const std::wstring& callbackName, const Awesomium::JSArguments& args );
typedef void (*ReceiveTitleHandler)( const std::wstring& title, const std::wstring& frameName );
typedef void (*ChangeTooltipHandler)( const std::wstring& tooltip );
typedef void (*ChangeCursorHandler)( Awesomium::CursorType cursor );
typedef void (*ChangeKeyboardFocusHandler)( bool isFocused );
typedef void (*ChangeTargetURLHandler)( const std::string& url );
typedef void (*OpenExternalLinkHandler)( const std::string& url, const std::wstring& source );
typedef void (*RequestDownloadHandler)( const std::string& url );
typedef void (*WebViewCrashedHandler)();
typedef void (*PluginCrashedHandler)( const std::wstring& pluginName );
typedef void (*RequestMoveHandler)( int x, int y );
typedef void (*GetPageContentsHandler)( const std::string& url, const std::wstring& contents );
typedef void (*DOMReadyHandler)();
typedef void (*RequestFileChooserHandler)( bool selectMultipleFiles, const std::wstring& title, const std::wstring& defaultPath);
typedef void (*GetScrollDataHandler)( int contentWidth, int contentHeight, int preferredWidth, int scrollX, int scrollY);
typedef void (*JavascriptConsoleMessageHandler)( const std::wstring& message, int lineNumber, const std::wstring& source );

namespace CjcAwesomiumWrapper
{
 typedef void (*BeginNavigation)();

 ref class WebViewListener;

 class DelegatingWebViewListener : public Awesomium::WebViewListener
 {
  public:

   DelegatingWebViewListener()
   {
    BeginLoading = 0;
    BeginNavigation = 0;
    FinishLoading = 0;
    Callback = 0;
    ReceiveTitle = 0;
    ChangeTooltip = 0;
    ChangeCursor = 0;
    ChangeKeyboardFocus = 0;
    ChangeTargetURL = 0;
    OpenExternalLink = 0;
    //Agregados Roberto
    RequestDownload = 0;
    //WebViewCrashed = 0;
    //PluginCrashed = 0;
    //RequestMove = 0;
    //GetPageContents = 0;
    //DOMReady = 0;
    RequestFileChooser = 0;
    GetScrollData = 0;
    JavascriptConsoleMessage = 0;
   }

   virtual ~DelegatingWebViewListener() {}

   void onBeginNavigation( Awesomium::WebView* caller,
         const std::string& url,
         const std::wstring& frameName )
   {
    if ( BeginNavigation ) (*BeginNavigation)( url, frameName );
   }

   BeginNavigationHandler BeginNavigation;

   void onBeginLoading( Awesomium::WebView* caller,
         const std::string& url,
         const std::wstring& frameName,
         int statusCode,
         const std::wstring& mimeType )
   {
    if ( BeginLoading ) (*BeginLoading)( url, frameName, statusCode, mimeType );
   }

   BeginLoadingHandler BeginLoading;

   void onFinishLoading( Awesomium::WebView* caller )
   {
    if ( FinishLoading ) (*FinishLoading)();
   }

   FinishLoadingHandler FinishLoading;

   void onCallback( Awesomium::WebView* caller,
        const std::wstring& objectName,
        const std::wstring& callbackName,
        const Awesomium::JSArguments& args )
   {
    if ( Callback ) (*Callback)( objectName, callbackName, args );
   }

   CallbackHandler Callback;

   void onReceiveTitle( Awesomium::WebView* caller,
         const std::wstring& title,
         const std::wstring& frameName )
   {
    if ( ReceiveTitle ) (*ReceiveTitle)( title, frameName );
   }

   ReceiveTitleHandler ReceiveTitle;

   void onChangeTooltip( Awesomium::WebView* caller,
          const std::wstring& tooltip )
   {
    if ( ChangeTooltip ) (*ChangeTooltip)( tooltip );
   }

   ChangeTooltipHandler ChangeTooltip;

#if defined(_WIN32)

   void onChangeCursor( Awesomium::WebView* caller,
         Awesomium::CursorType cursor )
   {
    if ( ChangeCursor ) (*ChangeCursor)( cursor );
   }

   ChangeCursorHandler ChangeCursor;

#endif

   void onChangeKeyboardFocus( Awesomium::WebView* caller,
          bool isFocused )
   {
    if ( ChangeKeyboardFocus ) (*ChangeKeyboardFocus)( isFocused );
   }

   ChangeKeyboardFocusHandler ChangeKeyboardFocus;

   void onChangeTargetURL( Awesomium::WebView* caller,
         const std::string& url )
   {
    if ( ChangeTargetURL ) (*ChangeTargetURL)( url );
   }

   ChangeTargetURLHandler ChangeTargetURL;

   void onOpenExternalLink( Awesomium::WebView* caller,
          const std::string& url,
          const std::wstring& source )
   {
    if ( OpenExternalLink ) (*OpenExternalLink)( url, source );
   }

   OpenExternalLinkHandler OpenExternalLink;

   void onRequestDownload( Awesomium::WebView* caller,
            const std::string& url )
   {
    if ( RequestDownload ) (*RequestDownload)( url );
   }

   RequestDownloadHandler RequestDownload;

   void onWebViewCrashed( Awesomium::WebView* caller )
   {
    if ( WebViewCrashed ) (*WebViewCrashed)();
   }

   WebViewCrashedHandler WebViewCrashed;

   void onPluginCrashed( Awesomium::WebView* caller,
          const std::wstring& pluginName )
   {
    if ( PluginCrashed ) (*PluginCrashed)( pluginName );
   }

   PluginCrashedHandler PluginCrashed;

   void onRequestMove( Awesomium::WebView* caller,
        int x, int y )
   {
    if ( RequestMove ) (*RequestMove)( x, y );
   }

   RequestMoveHandler RequestMove;

   void onGetPageContents( Awesomium::WebView* caller,
         const std::string& url,
         const std::wstring& contents )
   {
    if ( GetPageContents ) (*GetPageContents)( url, contents );
   }

   GetPageContentsHandler GetPageContents;

   void onDOMReady( Awesomium::WebView* caller )
   {
    if ( DOMReady ) (*DOMReady)();
   }

   DOMReadyHandler DOMReady;
   
   void onRequestFileChooser( Awesomium::WebView* caller,
            bool selectMultipleFiles,
            const std::wstring& title,
            const std::wstring& defaultPath )
   {
    if ( RequestFileChooser ) (*RequestFileChooser)( selectMultipleFiles, title, defaultPath );
   }
   
   RequestFileChooserHandler RequestFileChooser;

   void onGetScrollData( Awesomium::WebView* caller,
          int contentWidth,
          int contentHeight,
          int preferredWidth,
          int scrollX,
          int scrollY )
   {
    if ( GetScrollData ) (*GetScrollData)( contentWidth, contentHeight, preferredWidth, scrollX, scrollY );
   }

   GetScrollDataHandler GetScrollData;

   void onJavascriptConsoleMessage( Awesomium::WebView* caller,
            const std::wstring& message,
            int lineNumber,
            const std::wstring& source )
   {
    if ( JavascriptConsoleMessage ) (*JavascriptConsoleMessage)( message, lineNumber, source );
   }

   JavascriptConsoleMessageHandler JavascriptConsoleMessage;
 };

 public ref class JSValue
 {
  private:

   Awesomium::JSValue* value;

  public:

   JSValue() { this->value = new Awesomium::JSValue(); }
   JSValue( Awesomium::JSValue* value ) { this->value = value; }
   JSValue( bool value ) { this->value = new Awesomium::JSValue( value ); }
   JSValue( int value ) { this->value = new Awesomium::JSValue( value ); }
   JSValue( double value ) { this->value = new Awesomium::JSValue( value ); }
   JSValue( String^ value ) { this->value = new Awesomium::JSValue( marshal_as<std::wstring>( value ) ); }

   virtual ~JSValue() { delete value; }

   bool IsBoolean() { return value->isBoolean(); }
   bool IsInteger() { return value->isInteger(); }
   bool IsDouble() { return value->isDouble(); }
   bool IsNumber() { return value->isNumber(); }
   bool IsString() { return value->isString(); }
   bool IsNull() { return value->isNull(); }

   operator Object^() { return Value(); }
   operator String^() { return marshal_as<String^>( value->toString() ); }
   int ToInteger() { return value->toInteger(); }
   double ToDouble() { return value->toDouble(); }
   bool ToBoolean() { return value->toBoolean(); }
   virtual String^ ToString() override { return (String^)this; }

   System::Object^ Value()
   {
    if ( IsBoolean() ) return value->toBoolean();
    if ( IsInteger() ) return value->toInteger();
    if ( IsDouble() || IsNumber() ) return value->toDouble();
    if ( IsString() ) return (String^)this;
    return nullptr;
   }

  internal:

   operator Awesomium::JSValue() { return *value; }
 };
/*
 public ref class FutureJSValue
 {
  private:

   Awesomium::FutureJSValue* value;

  public:

   FutureJSValue( Awesomium::FutureJSValue& value ) { this->value = &value; }
   virtual ~FutureJSValue() { delete value; }

   JSValue^ Get() { return gcnew JSValue( (Awesomium::JSValue*)&value->get() ); }

  internal:

   operator Awesomium::FutureJSValue() { return *value; }
 };
*/

 public enum class CursorType
 {
  CursorPointer,
  CursorCross,
  CursorHand,
  CursorIBeam,
  CursorWait,
  CursorHelp,
  CursorEastResize,
  CursorNorthResize,
  CursorNorthEastResize,
  CursorNorthWestResize,
  CursorSouthResize,
  CursorSouthEastResize,
  CursorSouthWestResize,
  CursorWestResize,
  CursorNorthSouthResize,
  CursorEastWestResize,
  CursorNorthEastSouthWestResize,
  CursorNorthWestSouthEastResize,
  CursorColumnResize,
  CursorRowResize,
  CursorMiddlePanning,
  CursorEastPanning,
  CursorNorthPanning,
  CursorNorthEastPanning,
  CursorNorthWestPanning,
  CursorSouthPanning,
  CursorSouthEastPanning,
  CursorSouthWestPanning,
  CursorWestPanning,
  CursorMove,
  CursorVerticalText,
  CursorCell,
  CursorContextMenu,
  CursorAlias,
  CursorProgress,
  CursorNoDrop,
  CursorCopy,
  CursorNone,
  CursorNotAllowed,
  CursorZoomIn,
  CursorZoomOut,
  CursorCustom
 };

 public ref class WebViewListener
 {
  public:

  private:

   DelegatingWebViewListener* webViewListener;

   void OnBeginNavigation( const std::string& url, const std::wstring& frameName )
   {
    BeginNavigation( marshal_as<String^>( url ), marshal_as<String^>( frameName ) );
   };

   void OnBeginLoading( const std::string& url, const std::wstring& frameName, int statusCode, const std::wstring& mimeType )
   {
    BeginLoading( marshal_as<String^>( url ), marshal_as<String^>( frameName ), statusCode, marshal_as<String^>( mimeType ) );
   };

   void OnFinishLoading()
   {
    FinishLoading();
   };

   void OnCallback( const std::wstring& objectName, const std::wstring& callbackName, const Awesomium::JSArguments& args )
   {
    array<JSValue^>^ argArray = gcnew array<JSValue^>( args.size() );

    for ( UINT i = 0; i < args.size(); ++ i ) argArray[ i ] = gcnew JSValue( (Awesomium::JSValue*)&args[ i ] );

    Callback( marshal_as<String^>( objectName ), marshal_as<String^>( callbackName ), argArray );
   };

   void OnReceiveTitle( const std::wstring& title, const std::wstring& frameName )
   {
    ReceiveTitle( marshal_as<String^>( title ), marshal_as<String^>( frameName ) );
   };

   void OnChangeTooltip( const std::wstring& tooltip )
   {
    ChangeTooltip( marshal_as<String^>( tooltip ) );
   };

   void OnChangeCursor( Awesomium::CursorType cursor )
   {
    ChangeCursor( (CursorType)cursor );
   };

   void OnChangeKeyboardFocus( bool isFocused )
   {
    ChangeKeyboardFocus( isFocused );
   };

   void OnChangeTargetURL( const std::string& url )
   {
    ChangeTargetURL( marshal_as<String^>( url ) );
   };

   void OnOpenExternalLink( const std::string& url, const std::wstring& source )
   {
    OpenExternalLink( marshal_as<String^>( url ), marshal_as<String^>( source ) );
   };

   void onRequestDownload( const std::string& url )
   {
    RequestDownload( marshal_as<String^>( url ) );
   };

   void OnWebViewCrashed()
   {
    WebViewCrashed();
   };

   void OnPluginCrashed( const std::wstring& pluginName )
   {
    PluginCrashed( marshal_as<String^>( pluginName ) );
   };

   void OnRequestMove( int x, int y )
   {
    RequestMove( x, y );
   };

   void OnGetPageContents( const std::string& url, const std::wstring& contents )
   {
    GetPageContents( marshal_as<String^>( url ), marshal_as<String^>( contents ) );
   };

   void OnDOMReady()
   {
    DOMReady();
   };

   void onRequestFileChooser( bool selectMultipleFiles, const std::wstring& title, const std::wstring& defaultPath )
   {
    RequestFileChooser( selectMultipleFiles, marshal_as<String^>( title ), marshal_as<String^>( defaultPath ) );
   };

   void onGetScrollData( int contentWidth, int contentHeight, int preferredWidth, int scrollX, int scrollY )
   {
    GetScrollData( contentWidth, contentHeight, preferredWidth, scrollX, scrollY );
   };

   void onJavascriptConsoleMessage( const std::wstring& message, int lineNumber, const std::wstring& source )
   {
    JavascriptConsoleMessage( marshal_as<String^>( message ), lineNumber, marshal_as<String^>( source ) );
   };

   delegate void BeginNavigationInternal( const std::string& url, const std::wstring& frameName );
   delegate void BeginLoadingInternal( const std::string& url, const std::wstring& frameName, int statusCode, const std::wstring& mimeType );
   delegate void FinishLoadingInternal();
   delegate void CallbackInternal( const std::wstring& objectName, const std::wstring& callbackName, const Awesomium::JSArguments& args );
   delegate void ReceiveTitleInternal( const std::wstring& title, const std::wstring& frameName );
   delegate void ChangeTooltipInternal( const std::wstring& tooltip );
   delegate void ChangeCursorInternal( Awesomium::CursorType cursor );
   delegate void ChangeKeyboardFocusInternal( bool isFocused );
   delegate void ChangeTargetURLInternal( const std::string& url );
   delegate void OpenExternalLinkInternal( const std::string& url, const std::wstring& source );
   delegate void RequestDownloadInternal( const std::string& url );
   delegate void WebViewCrashedInternal();
   delegate void PluginCrashedInternal( const std::wstring& pluginName );
   delegate void RequestMoveInternal( int x, int y );
   delegate void GetPageContentsInternal( const std::string& url, const std::wstring& contents );
   delegate void DOMReadyInternal();
   delegate void RequestFileChooserInternal( bool selectMultipleFiles, const std::wstring& title, const std::wstring& defaultPath );
   delegate void GetScrollDataInternal( int contentWidth, int contentHeight, int preferredWidth, int scrollX, int scrollY );
   delegate void JavascriptConsoleMessageInternal( const std::wstring& message, int lineNumber, const std::wstring& source );

   // Keep delegates alive
   BeginNavigationInternal^ beginNavigationInternal;
   BeginLoadingInternal^ beginLoadingInternal;
   FinishLoadingInternal^ finishLoadingInternal;
   CallbackInternal^ callbackInternal;
   ReceiveTitleInternal^ receiveTitleInternal;
   ChangeTooltipInternal^ changeTooltipInternal;
   ChangeCursorInternal^ changeCursorInternal;
   ChangeKeyboardFocusInternal^ changeKeyboardFocusInternal;
   ChangeTargetURLInternal^ changeTargetURLInternal;
   OpenExternalLinkInternal^ openExternalLinkInternal;
   RequestDownloadInternal^ requestDownloadInternal;
   WebViewCrashedInternal^ webViewCrashedInternal;
   PluginCrashedInternal^ pluginCrashedInternal;
   RequestMoveInternal^ requestMoveInternal;
   GetPageContentsInternal^ getPageContentsInternal;
   DOMReadyInternal^ domReadyInternal;
   RequestFileChooserInternal^ requestFileChooserInternal;
   GetScrollDataInternal^ getScrollDataInternal;
   JavascriptConsoleMessageInternal^ javascriptConsoleMessageInternal;

  public:

   WebViewListener()
   {
    this->webViewListener = new DelegatingWebViewListener();

    this->webViewListener->BeginNavigation = (BeginNavigationHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     beginNavigationInternal = gcnew BeginNavigationInternal( this, &WebViewListener::OnBeginNavigation ) ).ToPointer();

    this->webViewListener->BeginLoading = (BeginLoadingHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     beginLoadingInternal = gcnew BeginLoadingInternal( this, &WebViewListener::OnBeginLoading ) ).ToPointer();

    this->webViewListener->FinishLoading = (FinishLoadingHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     finishLoadingInternal = gcnew FinishLoadingInternal( this, &WebViewListener::OnFinishLoading ) ).ToPointer();

    this->webViewListener->Callback = (CallbackHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     callbackInternal = gcnew CallbackInternal( this, &WebViewListener::OnCallback ) ).ToPointer();

    this->webViewListener->ReceiveTitle = (ReceiveTitleHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     receiveTitleInternal = gcnew ReceiveTitleInternal( this, &WebViewListener::OnReceiveTitle ) ).ToPointer();

    this->webViewListener->ChangeTooltip = (ChangeTooltipHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     changeTooltipInternal = gcnew ChangeTooltipInternal( this, &WebViewListener::OnChangeTooltip ) ).ToPointer();

    this->webViewListener->ChangeCursor = (ChangeCursorHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     changeCursorInternal = gcnew ChangeCursorInternal( this, &WebViewListener::OnChangeCursor ) ).ToPointer();

    this->webViewListener->ChangeKeyboardFocus = (ChangeKeyboardFocusHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     changeKeyboardFocusInternal = gcnew ChangeKeyboardFocusInternal( this, &WebViewListener::OnChangeKeyboardFocus ) ).ToPointer();

    this->webViewListener->ChangeTargetURL = (ChangeTargetURLHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     changeTargetURLInternal = gcnew ChangeTargetURLInternal( this, &WebViewListener::OnChangeTargetURL ) ).ToPointer();

    this->webViewListener->OpenExternalLink = (OpenExternalLinkHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     openExternalLinkInternal = gcnew OpenExternalLinkInternal( this, &WebViewListener::OnOpenExternalLink ) ).ToPointer();

    this->webViewListener->RequestDownload = (RequestDownloadHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     requestDownloadInternal = gcnew RequestDownloadInternal( this, &WebViewListener::onRequestDownload ) ).ToPointer();

    this->webViewListener->WebViewCrashed = (WebViewCrashedHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     webViewCrashedInternal = gcnew WebViewCrashedInternal( this, &WebViewListener::OnWebViewCrashed ) ).ToPointer();

    this->webViewListener->PluginCrashed = (PluginCrashedHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     pluginCrashedInternal = gcnew PluginCrashedInternal( this, &WebViewListener::OnPluginCrashed ) ).ToPointer();

    this->webViewListener->RequestMove = (RequestMoveHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     requestMoveInternal = gcnew RequestMoveInternal( this, &WebViewListener::OnRequestMove ) ).ToPointer();

    this->webViewListener->GetPageContents = (GetPageContentsHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     getPageContentsInternal = gcnew GetPageContentsInternal( this, &WebViewListener::OnGetPageContents ) ).ToPointer();

    this->webViewListener->DOMReady = (DOMReadyHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     domReadyInternal = gcnew DOMReadyInternal( this, &WebViewListener::OnDOMReady ) ).ToPointer();

    this->webViewListener->RequestFileChooser = (RequestFileChooserHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     requestFileChooserInternal = gcnew RequestFileChooserInternal( this, &WebViewListener::onRequestFileChooser ) ).ToPointer();

    this->webViewListener->GetScrollData = (GetScrollDataHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     getScrollDataInternal = gcnew GetScrollDataInternal( this, &WebViewListener::onGetScrollData ) ).ToPointer();

    this->webViewListener->JavascriptConsoleMessage = (JavascriptConsoleMessageHandler)System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(
     javascriptConsoleMessageInternal = gcnew JavascriptConsoleMessageInternal( this, &WebViewListener::onJavascriptConsoleMessage ) ).ToPointer();
   }

   virtual ~WebViewListener() { delete webViewListener; webViewListener = NULL; }

   delegate void BeginNavigationDelegate( String^ url, String^ frameName );
   event BeginNavigationDelegate^ BeginNavigation;

   delegate void BeginLoadingDelegate( String^ url, String^ frameName, int statusCode, String^ mimeType );
   event BeginLoadingDelegate^ BeginLoading;

   delegate void FinishLoadingDelegate();
   event FinishLoadingDelegate^ FinishLoading;

   delegate void CallbackDelegate( String^ objectName, String^ callbackName, array<JSValue^>^ args );
   event CallbackDelegate^ Callback;

   delegate void ReceiveTitleDelegate( String^ title, String^ frameName );
   event ReceiveTitleDelegate^ ReceiveTitle;

   delegate void ChangeTooltipDelegate( String^ tooltip );
   event ChangeTooltipDelegate^ ChangeTooltip;

   delegate void ChangeCursorDelegate( CursorType cursor );
   event ChangeCursorDelegate^ ChangeCursor;

   delegate void ChangeKeyboardFocusDelegate( bool isFocused );
   event ChangeKeyboardFocusDelegate^ ChangeKeyboardFocus;

   delegate void ChangeTargetURLDelegate( String^ url );
   event ChangeTargetURLDelegate^ ChangeTargetURL;

   delegate void OpenExternalLinkDelegate( String^ url, String^ source );
   event OpenExternalLinkDelegate^ OpenExternalLink;
   
   delegate void RequestDownloadDelegate( String^ url );
   event RequestDownloadDelegate^ RequestDownload;
   
   delegate void WebViewCrashedDelegate();
   event WebViewCrashedDelegate^ WebViewCrashed;

   delegate void PluginCrashedDelegate( String^ pluginName );
   event PluginCrashedDelegate^ PluginCrashed;

   delegate void RequestMoveDelegate( int x, int y );
   event RequestMoveDelegate^ RequestMove;

   delegate void GetPageContentsDelegate( String^ url, String^ contents );
   event GetPageContentsDelegate^ GetPageContents;

   delegate void DOMReadyDelegate();
   event DOMReadyDelegate^ DOMReady;

   delegate void RequestFileChooserDelegate( bool selectMultipleFiles, String^ title, String^ defaultPath );
   event RequestFileChooserDelegate^ RequestFileChooser;

   delegate void GetScrollDataDelegate( int contentWidth, int contentHeight, int preferredWidth, int scrollX, int scrollY );
   event GetScrollDataDelegate^ GetScrollData;

   delegate void JavascriptConsoleMessageDelegate( String^ message, int lineNumber, String^ source );
   event JavascriptConsoleMessageDelegate^ JavascriptConsoleMessage;

  internal:

   operator DelegatingWebViewListener*() { return webViewListener; }
 };

 public ref struct Rect
 {
  public:
   int X;
   int Y;
   int Width;
   int Height;
 };

 public enum class MouseButton { Left, Middle, Right };

 struct _KeyLParam
 {
  short RepeatCount : 16;
  unsigned char ScanCode : 8;
  bool IsExtended : 1;
  bool ContextCode : 1;
  bool PreviousState : 1;
  bool TransitionState : 1;
 };

 public ref struct KeyLParam
 {
  private:

   _KeyLParam* keyLParam;

  public:

   KeyLParam( short repeatCount, unsigned char scanCode, bool isExtended, bool contextCode, bool previousState, bool transitionState )
   {
    keyLParam = new _KeyLParam();
    keyLParam->RepeatCount = repeatCount;
    keyLParam->ScanCode = scanCode;
    keyLParam->IsExtended = isExtended;
    keyLParam->ContextCode = contextCode;
    keyLParam->PreviousState = previousState;
    keyLParam->TransitionState = transitionState;
   }

   virtual ~KeyLParam() { delete keyLParam; }

  internal:

   operator LPARAM() { return (LPARAM)*(unsigned int *)keyLParam; }
 };

 public ref class RenderBuffer
 {
  private:

   const Awesomium::RenderBuffer* renderBuffer;

  public:

   RenderBuffer( const Awesomium::RenderBuffer* renderBuffer ) { this->renderBuffer = renderBuffer; }

   void CopyArea( array<unsigned char>^ destBuffer, int rowSpan, Rect^ rect )
   {
    pin_ptr<unsigned char> pinned = &destBuffer[ 0 ];

    return CopyArea( pinned, rowSpan, rect );
   }

   void CopyArea( IntPtr^ destBuffer, int rowSpan, Rect^ rect )
   {
    pin_ptr<unsigned char> pinned = (unsigned char *)destBuffer->ToPointer();

    return CopyArea( pinned, rowSpan, rect );
   }

   void CopyArea( unsigned char* pinned, int rowSpan, Rect^ rect )
   {
/*
    Awesomium::RenderBuffer destRenderBuffer(
     pinned, renderBuffer->width, renderBuffer->height, renderBuffer->rowSpan );

    Awesomium::Rect renderRect( rect->X, rect->Y, rect->Width, rect->Height );

    destRenderBuffer.copyArea( *renderBuffer, renderRect, renderRect );
*/
    int bpp = renderBuffer->rowSpan / renderBuffer->width;
    long offset = ( rect->Y * renderBuffer->rowSpan ) + ( rect->X * bpp );

    unsigned char* src = renderBuffer->buffer + offset;
    unsigned char* dest = pinned + offset;

    int rows = Math::Min( rect->Height, renderBuffer->height - rect->Y );
    int byteWidth = Math::Min( rect->Width, renderBuffer->width - rect->X ) * bpp;

    if ( byteWidth == rowSpan )
    {
     memcpy( dest, src, byteWidth * rows );
    }
    else
    {
     while ( rows-- > 0 )
     {
      memcpy( dest, src, byteWidth );
      src += rowSpan;
      dest += rowSpan;
     }
    }
   }

   int Width() { return renderBuffer->width; }
   int Height() { return renderBuffer->height; }
   int RowSpan() { return renderBuffer->rowSpan; }
 };

 public enum URLFilteringMode { UFM_BLACKLIST, UFM_WHITELIST, UFM_NONE };

 public ref class WebView
 {
  private:

   Awesomium::WebView* webView;
   WebViewListener^ listener;

  public:

   WebView( Awesomium::WebView* webView )
   {
    this->webView = webView;

   }

   virtual ~WebView()
   {
    listener = nullptr;

    if ( webView != NULL )
    {
     webView->setListener( NULL );
     webView->destroy();
     webView = NULL;
    }
   }

   void LoadURL( String^ url )
   {
    webView->loadURL( marshal_as<std::string>( url ) );
   }

   void LoadHTML( String^ html )
   {
    webView->loadHTML( marshal_as<std::string>( html ) );
   }

   void LoadFile( String^ file )
   {
    webView->loadFile( marshal_as<std::string>( file ) );
   }

   void SetListener( WebViewListener^ webViewListener )
   {
    this->listener = webViewListener;

    webView->setListener( webViewListener != nullptr ? webViewListener : (Awesomium::WebViewListener*)NULL );
   }

   void GotoHistoryOffset( int offset ) { webView->goToHistoryOffset( offset ); }

   void ExecuteJavascript( String^ javascript, String^ frameName )
   {
    webView->executeJavascript(
     marshal_as<std::string>( javascript ),
     marshal_as<std::wstring>( frameName ) );
   }

   JSValue^ ExecuteJavascriptWithResult( String^ javascript, String^ frameName )
   {
    Awesomium::JSValue* value = new Awesomium::JSValue();
    *value = webView->executeJavascriptWithResult(
     marshal_as<std::string>( javascript ),
     marshal_as<std::wstring>( frameName ) ).get();

    return gcnew JSValue( value );
   }

   void CreateObject( String^ objectName )
   {
    webView->createObject( marshal_as<std::wstring>( objectName ) );
   }

   void DestroyObject( String^ objectName )
   {
    webView->destroyObject( marshal_as<std::wstring>( objectName ) );
   }

   void SetObjectProperty( String^ objectName, String^ propertyName, JSValue^ value )
   {
    webView->setObjectProperty( marshal_as<std::wstring>( objectName ), marshal_as<std::wstring>( propertyName ), value );
   }

   void SetObjectCallback( String^ objectName, String^ callbackName )
   {
    webView->setObjectCallback( marshal_as<std::wstring>( objectName ), marshal_as<std::wstring>( callbackName ) );
   }

   bool IsDirty() { return webView->isDirty(); }

   Rect^ GetDirtyBounds()
   {
    Awesomium::Rect dirtyBounds = webView->getDirtyBounds();
    Rect^ dirty = gcnew Rect();

    dirty->X = dirtyBounds.x;
    dirty->Y = dirtyBounds.y;
    dirty->Width = dirtyBounds.width;
    dirty->Height = dirtyBounds.height;

    return dirty;
   }

   RenderBuffer^ Render()
   {
    return gcnew RenderBuffer( webView->render() );
   }

   void InjectMouseMove( int x, int y ) { webView->injectMouseMove( x, y ); }

   void InjectMouseDown( MouseButton button ) { webView->injectMouseDown( (Awesomium::MouseButton)(int)button ); }

   void InjectMouseUp( MouseButton button ) { webView->injectMouseUp( (Awesomium::MouseButton)(int)button ); }

   void InjectMouseWheel( int scrollAmount ) { webView->injectMouseWheel( scrollAmount ); }

   void InjectKeyboardEvent( IntPtr^ hWnd, int message, IntPtr^ wParam, IntPtr^ lParam )
   {
    LPARAM test = reinterpret_cast<LPARAM>( lParam->ToPointer() );

    Awesomium::WebKeyboardEvent& keyEvent = *new Awesomium::WebKeyboardEvent(
     message,
     reinterpret_cast<WPARAM>( wParam->ToPointer() ),
     reinterpret_cast<LPARAM>( lParam->ToPointer() ) );

    webView->injectKeyboardEvent( keyEvent );
   }

   void InjectKeyboardEvent( IntPtr^ hWnd, int message, int wParam, KeyLParam^ lParam )
   {
    Awesomium::WebKeyboardEvent& keyEvent = *new Awesomium::WebKeyboardEvent(
     message,
     wParam,
     lParam );

    webView->injectKeyboardEvent( keyEvent );
   }

   void Cut() { webView->cut(); }

   void Copy() { webView->copy(); }

   void Paste() { webView->paste(); }

   void SelectAll() { webView->selectAll(); }

   void DeselectAll() { /*webView->deselectAll();*/ }

   String^ GetContentAsText( int maxChars )
   {
    return nullptr;
/*    std::wstring result;
    webView->getContentAsText( result, maxChars );
    return marshal_as<std::wstring>( result );*/
   }

   /*void ZoomIn() { webView->zoomIn(); }*/

   //void ZoomOut() { webView->zoomOut(); }
   
   void SetZoom(int zoomPercent) { webView->setZoom(zoomPercent); }

   void ResetZoom() { webView->resetZoom(); }

   void Resize( int width, int height ) { webView->resize( width, height ); }

   void Unfocus() { webView->unfocus(); }

   void Focus() { webView->focus(); }

   void SetTransparent( bool transparent ) { webView->setTransparent( transparent ); }

   void SetURLFilteringMode( URLFilteringMode mode ) { webView->setURLFilteringMode( (Awesomium::URLFilteringMode)mode ); }

   void AddURLFilter( String^ filter ) { webView->addURLFilter( marshal_as<std::wstring>( filter ) ); }

   void ClearAllURLFilters() { webView->clearAllURLFilters(); }
   
   void SetHeaderDefinition( String^ name, System::Collections::Generic::IDictionary<String^, String^>^ definition )
   {
       cliext::collection_adapter<System::Collections::Generic::IDictionary<String^, String^>> dictAdapter( definition );
    Awesomium::HeaderDefinition& def = *new Awesomium::HeaderDefinition();

    for each ( System::Collections::Generic::KeyValuePair<String^, String^>^ kvp in dictAdapter )
    {
     std::pair<std::string, std::string> aPair( marshal_as<std::string>( kvp->Key ), marshal_as<std::string>( kvp->Value ) );
     def.insert( aPair );
    }

    webView->setHeaderDefinition( marshal_as<std::string>( name ), def );
   }

   void AddHeaderRewriteRule( String^ rule, String^ name) { webView->addHeaderRewriteRule( marshal_as<std::wstring>( rule ), marshal_as<std::string>( name ) ); }

   void RemoveHeaderRewriteRule( String^ rule ) { webView->removeHeaderRewriteRule( marshal_as<std::wstring>( rule ) ); }

   void RemoveHeaderRewriteRulesByDefinitionName( String^ name ) { webView->removeHeaderRewriteRulesByDefinitionName( marshal_as<std::string>( name ) ); }

   void SetOpensExternalLinksInCallingFrame( bool isEnabled ) {/* webView->setOpensExternalLinksInCallingFrame( isEnabled );*/ }

  internal:

   operator Awesomium::WebView*() { return webView; }
 };

 public ref class WebCore
 {
  private:

   Awesomium::WebCore* webCore;

   void Initialize( String^ userDataPath, String^ pluginPath, String^ logPath,
    Awesomium::LogLevel level, bool enablePlugins, String^ userAgentOverride )
   {
    /*webCore = new Awesomium::WebCore(
     marshal_as<std::wstring>( userDataPath ),
     marshal_as<std::wstring>( pluginPath ),
     marshal_as<std::wstring>( logPath ),
     level,
     enablePlugins,
     marshal_as<std::string>( userAgentOverride ) );*/
    
    Awesomium::WebCoreConfig& webCoreOptions = *new Awesomium::WebCoreConfig();
    //TODO: Create a full wrapper object around WebCoreConfig
    webCoreOptions.setEnablePlugins(enablePlugins);
    webCoreOptions.setUserDataPath(marshal_as<std::wstring>( userDataPath ));
    webCoreOptions.setPluginPath(marshal_as<std::wstring>( pluginPath ));
    webCoreOptions.setLogPath(marshal_as<std::wstring>( logPath ));
    webCoreOptions.setLogLevel(level);
    webCoreOptions.setUserAgentOverride(marshal_as<std::string>( userAgentOverride ));

    webCore = new Awesomium::WebCore(webCoreOptions);
   }

  public:

   WebCore()
   {
    Initialize( "", "", "", Awesomium::LOG_NONE, true, "" );
   }

   WebCore( String^ userDataPath )
   {
    Initialize( userDataPath, "", "", Awesomium::LOG_NONE, true, "" );
   }

   WebCore( String^ userDataPath, String^ userAgentOverride )
   {
    Initialize( userDataPath, "", "", Awesomium::LOG_NONE, true, userAgentOverride );
   }

   WebCore( String^ userDataPath, String^ pluginPath, String^ logPath, String^ userAgentOverride )
   {
    Initialize( userDataPath, pluginPath, logPath, Awesomium::LOG_NONE, true, userAgentOverride );
   }

   WebCore( String^ userDataPath, String^ pluginPath, String^ logPath,
    Awesomium::LogLevel level, bool enablePlugins, String^ userAgentOverride )
   {
    Initialize( userDataPath, pluginPath, logPath, level, enablePlugins, userAgentOverride );
   }

   virtual ~WebCore() { delete webCore; webCore = NULL; }

   WebView^ CreateWebView( int width, int height )
   {
    return gcnew WebView( webCore->createWebView( width, height ) );
   }

   void Update()
   {
    webCore->update();
   }
 };
}