Skip to content

Commit

Permalink
More heavily-WIP-style work towards #159. I wonder if we'll ever gonn…
Browse files Browse the repository at this point in the history
…a get that one solved actually... Well, of course we are, but how well with it work? Anyway, time to go to bed now and so forth.
  • Loading branch information
perlun committed Oct 30, 2013
1 parent 161a449 commit 2e0a73e
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 7 deletions.
3 changes: 3 additions & 0 deletions CefSharp.BrowserSubprocess/CefSharp.BrowserSubprocess.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.ServiceModel" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
Expand All @@ -78,6 +79,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="JavascriptProxy.cs" />
<Compile Include="JavascriptServiceHost.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SubprocessCefApp.cs" />
Expand Down
18 changes: 18 additions & 0 deletions CefSharp.BrowserSubprocess/JavascriptProxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using CefSharp.Internals.JavascriptBinding;
using System;

namespace CefSharp.BrowserSubprocess
{
internal class JavascriptProxy : IJavascriptProxy
{
public const String BaseAddress = "net.pipe://localhost";
public const String ServiceName = "JavaScriptProxy";
public const String Address = BaseAddress + "/" + ServiceName;

public object EvaluateScript(int frameId, string script, double timeout)
{
var cefFrame = SubprocessCefApp.Instance.CefBrowserWrapper.GetFrame(frameId);
return null;
}
}
}
51 changes: 51 additions & 0 deletions CefSharp.BrowserSubprocess/JavascriptServiceHost.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using CefSharp.Internals.JavascriptBinding;
using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace CefSharp.BrowserSubprocess
{
internal class JavascriptServiceHost
{
public static void Create(int browserId)
{
var uris = new[]
{
new Uri(JavascriptProxy.BaseAddress)
};

var host = new ServiceHost(typeof(JavascriptProxy), uris);
AddDebugBehavior(host);

// TODO: Include the name of the "parent process" here also, so you can run more than one CefSharp-based application
// TODO: simultaneously. :)
var serviceName = JavascriptProxy.ServiceName + "_" + browserId;

host.AddServiceEndpoint(
typeof(IJavascriptProxy),
new NetNamedPipeBinding(),
serviceName
);

host.Open();
}

private static void AddDebugBehavior(ServiceHostBase host)
{
var serviceDebugBehavior = host.Description.Behaviors.Find<ServiceDebugBehavior>();

if (serviceDebugBehavior == null)
{
serviceDebugBehavior = new ServiceDebugBehavior
{
IncludeExceptionDetailInFaults = true
};
host.Description.Behaviors.Add(serviceDebugBehavior);
}
else
{
serviceDebugBehavior.IncludeExceptionDetailInFaults = true;
}
}
}
}
4 changes: 2 additions & 2 deletions CefSharp.BrowserSubprocess/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ static int Main(string[] args)
{
var hInstance = Process.GetCurrentProcess().Handle;
LogCommandLine(args);
//MessageBox.Show("Please attach debugger now");
MessageBox.Show("Please attach debugger now", null, MessageBoxButtons.OK, MessageBoxIcon.Information);

return ExecuteCefRenderProcess(hInstance);
}
Expand All @@ -27,7 +27,7 @@ private static void LogCommandLine(string[] args)

private static int ExecuteCefRenderProcess(IntPtr hInstance)
{
var subprocessCefApp = new SubprocessCefApp();
var subprocessCefApp = SubprocessCefApp.Instance;
return GlobalMethods.CefExecuteProcess(hInstance, subprocessCefApp);
}
}
Expand Down
14 changes: 14 additions & 0 deletions CefSharp.BrowserSubprocess/SubprocessCefApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,19 @@ namespace CefSharp.BrowserSubprocess
{
internal class SubprocessCefApp : CefAppWrapper
{
private static SubprocessCefApp instance;

public static SubprocessCefApp Instance
{
get { return instance ?? (instance = new SubprocessCefApp()); }
}

public CefBrowserWrapper CefBrowserWrapper { get; private set; }

public override void OnBrowserCreated(CefBrowserWrapper cefBrowserWrapper)
{
CefBrowserWrapper = cefBrowserWrapper;
JavascriptServiceHost.Create(cefBrowserWrapper.BrowserId);
}
}
}
1 change: 1 addition & 0 deletions CefSharp/CefSharp.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@
<ClInclude Include="Internals\StreamAdapter.h" />
<ClInclude Include="TypeUtils.h" />
<ClInclude Include="vcclr_local.h" />
<ClInclude Include="Wrappers\CefBrowserWrapper.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
3 changes: 3 additions & 0 deletions CefSharp/CefSharp.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -208,5 +208,8 @@
<ClInclude Include="ManagedCefBrowserAdapter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Wrappers\CefBrowserWrapper.h">
<Filter>Source Files\Wrappers</Filter>
</ClInclude>
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion CefSharp/Wrappers/CefAppWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace CefSharp
{
CefAppWrapper::CefAppWrapper()
{
cefApp = new CefRefPtr<CefAppUnmanagedWrapper>(new CefAppUnmanagedWrapper());
cefApp = new CefRefPtr<CefAppUnmanagedWrapper>(new CefAppUnmanagedWrapper(this));
}

CefAppWrapper::~CefAppWrapper()
Expand Down
33 changes: 29 additions & 4 deletions CefSharp/Wrappers/CefAppWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,14 @@
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "Stdafx.h"
#include "CefBrowserWrapper.h"
#include "include/cef_app.h"

namespace CefSharp
{
namespace Wrappers
{
private class CefAppUnmanagedWrapper : CefApp
{
IMPLEMENT_REFCOUNTING(CefAppUnmanagedWrapper);
};
class CefAppUnmanagedWrapper;

// TODO: Support the stuff that CefApp has. One important question is whether we go with the C++ API or make the (seemingly a bit
// strange) move to start using the C API instead. It may actually make it possible to write our code in a cleaner fashion. Worth
Expand All @@ -27,9 +25,36 @@ namespace CefSharp
CefAppWrapper();
~CefAppWrapper();
void* GetUnmanaged();
virtual void OnBrowserCreated(CefBrowserWrapper^ cefBrowserWrapper) {};

private:
!CefAppWrapper();
};

private class CefAppUnmanagedWrapper : CefApp, CefRenderProcessHandler
{
private:
gcroot<CefAppWrapper^> _cefAppWrapper;
CefRefPtr<CefBrowser> _browser;

public:
CefAppUnmanagedWrapper(CefAppWrapper^ cefAppWrapper)
{
_cefAppWrapper = cefAppWrapper;
}

virtual DECL CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() OVERRIDE
{
return this;
}

virtual DECL void CefAppUnmanagedWrapper::OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE
{
// TODO: Could destroy this CefBrowserWrapper in OnBrowserDestroyed(), but it doesn't seem to be reliably called...
_cefAppWrapper->OnBrowserCreated(gcnew CefBrowserWrapper(browser));
}

IMPLEMENT_REFCOUNTING(CefAppUnmanagedWrapper);
};
}
}
75 changes: 75 additions & 0 deletions CefSharp/Wrappers/CefBrowserWrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright © 2010-2013 The CefSharp Project. All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "include/cef_browser.h"
#include "include/cef_runnable.h"

using namespace System::Threading;

namespace CefSharp
{
namespace Wrappers
{
private class CefBrowserUnmanagedWrapper
{
CefRefPtr<CefBrowser> _cefBrowser;

public:
CefRefPtr<CefFrame> Frame;
gcroot<AutoResetEvent^> WaitHandle;

CefBrowserUnmanagedWrapper(CefRefPtr<CefBrowser> cefBrowser)
{
_cefBrowser = cefBrowser;
WaitHandle = gcnew AutoResetEvent(false);
}

void GetFrameCallback(int64 frameId)
{
Frame = _cefBrowser->GetFrame(frameId);
WaitHandle->Set();
}

IMPLEMENT_REFCOUNTING(CefBrowserUnmanagedWrapper);
};

public ref class CefBrowserWrapper
{
CefRefPtr<CefBrowser>* _cefBrowser;
int _browserId;
CefRefPtr<CefBrowserUnmanagedWrapper>* _unmanagedWrapper;

public:
property int BrowserId
{
int get() { return _browserId; }
private: void set(int value) { _browserId = value; }
}

CefBrowserWrapper(CefRefPtr<CefBrowser> cefBrowser)
{
_cefBrowser = &cefBrowser;
_browserId = cefBrowser->GetIdentifier();

// TODO: Should be deallocated at some point to avoid leaking memory.
_unmanagedWrapper = new CefRefPtr<CefBrowserUnmanagedWrapper>(new CefBrowserUnmanagedWrapper(cefBrowser));
}

System::IntPtr GetFrame(long frameId)
{
// TODO: Could we do something genericly useful here using C++ lambdas? To avoid having to make a lot of of these...
// TODO: DON'T USE AUTORESETEVENT STUPIDITY! Even though the code below compiles & runs correctly, it deadlocks the
// thread from which the request came, which is very, very stupid, especially since V8 and Chromium are built
// with asynchrony in mind. Instead, we should re-think this API to utilize WCF callbacks instead:
// http://idunno.org/archive/2008/05/29/wcf-callbacks-a-beginners-guide.aspx
// That feels much more like 2013, and not 1994... :)
CefPostTask(CefThreadId::TID_RENDERER, NewCefRunnableMethod(_unmanagedWrapper->get(), &CefBrowserUnmanagedWrapper::GetFrameCallback, frameId));
_unmanagedWrapper->get()->WaitHandle->WaitOne();

// TODO: Wrap in a CefFrameWrapper, obviously...
return (System::IntPtr)&_unmanagedWrapper->get()->Frame;
}
};
}
}

0 comments on commit 2e0a73e

Please sign in to comment.