Skip to content

Commit

Permalink
Lots of work towards #159.
Browse files Browse the repository at this point in the history
  • Loading branch information
perlun committed Nov 6, 2013
1 parent d6284f4 commit 07c3c0c
Show file tree
Hide file tree
Showing 12 changed files with 222 additions and 144 deletions.
8 changes: 2 additions & 6 deletions CefSharp.BrowserSubprocess/JavascriptProxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@ 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;
var result = SubprocessCefApp.Instance.CefSubprocessWrapper.EvaluateScript(frameId, script, timeout);
return result;
}
}
}
10 changes: 4 additions & 6 deletions CefSharp.BrowserSubprocess/JavascriptServiceHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,18 @@ namespace CefSharp.BrowserSubprocess
{
internal class JavascriptServiceHost
{
public static void Create(int browserId)
public static void Create(int parentProcessId, int browserId)
{
var uris = new[]
{
new Uri(JavascriptProxy.BaseAddress)
new Uri(JavascriptProxySupport.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;

var serviceName = JavascriptProxySupport.GetServiceName(parentProcessId, browserId);
Kernel32.OutputDebugString("Setting up IJavascriptProxy using service name: " + serviceName);
host.AddServiceEndpoint(
typeof(IJavascriptProxy),
new NetNamedPipeBinding(),
Expand Down
39 changes: 30 additions & 9 deletions CefSharp.BrowserSubprocess/Program.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,50 @@
using System;
using CefSharp.Wrappers;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using CefSharp.Wrappers;
using System.Linq;

namespace CefSharp.BrowserSubprocess
{
public class Program
{
static int Main(string[] args)
{
var hInstance = Process.GetCurrentProcess().Handle;
LogCommandLine(args);
MessageBox.Show("Please attach debugger now", null, MessageBoxButtons.OK, MessageBoxIcon.Information);

return ExecuteCefRenderProcess(hInstance);
var subprocessCefApp = SubprocessCefApp.Instance;
subprocessCefApp.ParentProcessId = FindParentProcessId(args);

//MessageBox.Show("Please attach debugger now", null, MessageBoxButtons.OK, MessageBoxIcon.Information);
var result = ExecuteCefRenderProcess();
Kernel32.OutputDebugString("BrowserSubprocess shutting down.");
return result;
}

private static void LogCommandLine(string[] args)
{
Kernel32.OutputDebugString("BrowserSubprocess starting up with command line: " + String.Join("\n", args));
Kernel32.OutputDebugString("BrowserSubprocess starting up with command line: " + String.Join("\n", args));
}

private static int? FindParentProcessId(IEnumerable<string> args)
{
// Format being parsed:
// --channel=3828.2.1260352072\1102986608
// We only really care about the PID (3828) part.
var channelPrefix = "--channel=";
var channelArgument = args.SingleOrDefault(arg => arg.StartsWith(channelPrefix));
if (channelArgument == null) return null;

var parentProcessId = channelArgument
.Substring(channelPrefix.Length)
.Split('.')
.First();
return int.Parse(parentProcessId);
}

private static int ExecuteCefRenderProcess(IntPtr hInstance)
private static int ExecuteCefRenderProcess()
{
var hInstance = Process.GetCurrentProcess().Handle;
var subprocessCefApp = SubprocessCefApp.Instance;
return GlobalMethods.CefExecuteProcess(hInstance, subprocessCefApp);
}
Expand Down
13 changes: 9 additions & 4 deletions CefSharp.BrowserSubprocess/SubprocessCefApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@ public static SubprocessCefApp Instance
get { return instance ?? (instance = new SubprocessCefApp()); }
}

public CefBrowserWrapper CefBrowserWrapper { get; private set; }
public CefSubprocessWrapper CefSubprocessWrapper { get; private set; }
public int? ParentProcessId { get; set; }

public override void OnBrowserCreated(CefBrowserWrapper cefBrowserWrapper)
public override void OnBrowserCreated(CefSubprocessWrapper cefBrowserWrapper)
{
CefBrowserWrapper = cefBrowserWrapper;
JavascriptServiceHost.Create(cefBrowserWrapper.BrowserId);
CefSubprocessWrapper = cefBrowserWrapper;

if (ParentProcessId != null)
{
JavascriptServiceHost.Create(ParentProcessId.Value, CefSubprocessWrapper.BrowserId);
}
}
}
}
3 changes: 2 additions & 1 deletion CefSharp/CefSharp.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@
<ClInclude Include="BrowserSettings.h" />
<ClInclude Include="Cef.h" />
<ClInclude Include="CefCustomScheme.h" />
<ClInclude Include="Internals\JavascriptBinding\JavascriptProxySupport.h" />
<ClInclude Include="Wrappers\CefAppWrapper.h" />
<ClInclude Include="ConsoleMessageEventArgs.h" />
<ClInclude Include="IDownloadHandler.h" />
Expand Down Expand Up @@ -279,7 +280,7 @@
<ClInclude Include="Internals\StreamAdapter.h" />
<ClInclude Include="TypeUtils.h" />
<ClInclude Include="vcclr_local.h" />
<ClInclude Include="Wrappers\CefBrowserWrapper.h" />
<ClInclude Include="Wrappers\CefSubprocessWrapper.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
22 changes: 14 additions & 8 deletions CefSharp/CefSharp.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
<Filter Include="Source Files\Wrappers">
<UniqueIdentifier>{b5511138-8f2e-4ace-9e68-76929de8c004}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Wrappers">
<UniqueIdentifier>{598626f0-6a78-477c-955b-8cdf26d2cb64}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="AssemblyInfo.cpp">
Expand Down Expand Up @@ -184,9 +187,6 @@
<ClInclude Include="ScriptException.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Internals\JavascriptBinding\IJavascriptProxy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ISchemeHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
Expand All @@ -202,14 +202,20 @@
<ClInclude Include="CefCustomScheme.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Wrappers\CefAppWrapper.h">
<Filter>Source Files\Wrappers</Filter>
</ClInclude>
<ClInclude Include="ManagedCefBrowserAdapter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Wrappers\CefBrowserWrapper.h">
<Filter>Source Files\Wrappers</Filter>
<ClInclude Include="Wrappers\CefAppWrapper.h">
<Filter>Header Files\Wrappers</Filter>
</ClInclude>
<ClInclude Include="Wrappers\CefSubprocessWrapper.h">
<Filter>Header Files\Wrappers</Filter>
</ClInclude>
<ClInclude Include="Internals\JavascriptBinding\IJavascriptProxy.h">
<Filter>Header Files\Internals\JavascriptBinding</Filter>
</ClInclude>
<ClInclude Include="Internals\JavascriptBinding\JavascriptProxySupport.h">
<Filter>Header Files\Internals\JavascriptBinding</Filter>
</ClInclude>
</ItemGroup>
</Project>
30 changes: 30 additions & 0 deletions CefSharp/Internals/JavascriptBinding/JavascriptProxySupport.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright © 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.

using namespace System;

namespace CefSharp
{
namespace Internals
{
namespace JavascriptBinding
{
public ref class JavascriptProxySupport
{
public:
literal String^ BaseAddress = "net.pipe://localhost";

static String^ GetServiceName(int parentProcessId, int browserId)
{
auto elements = gcnew array<String^>(3);
elements[0] = "JavaScriptProxy";
elements[1] = parentProcessId.ToString();
elements[2] = browserId.ToString();

return String::Join("_", elements);
}
};
}
}
}
6 changes: 4 additions & 2 deletions CefSharp/ManagedCefBrowserAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
#include "MouseButtonType.h"
#include "ScriptCore.h"
#include "Internals/JavascriptBinding/IJavascriptProxy.h"
#include "Internals/JavascriptBinding/JavascriptProxySupport.h"
#include "Internals/IRenderWebBrowser.h"
#include "Internals/RenderClientAdapter.h"

using namespace CefSharp::Internals;
using namespace CefSharp::Internals::JavascriptBinding;
using namespace System::Diagnostics;
using namespace System::ServiceModel;

namespace CefSharp
Expand Down Expand Up @@ -260,11 +262,11 @@ namespace CefSharp
if (browser != nullptr &&
frame != nullptr)
{
// TODO: Make the address be shared between the Subprocess and the CefSharp projects.
// TODO: Don't instantiate this on every request. The problem is that the CefBrowser is not set in our constructor.
auto serviceName = JavascriptProxySupport::GetServiceName(Process::GetCurrentProcess()->Id, _renderClientAdapter->GetCefBrowser()->GetIdentifier());
auto channelFactory = gcnew ChannelFactory<IJavascriptProxy^>(
gcnew NetNamedPipeBinding(),
gcnew EndpointAddress("net.pipe://localhost/JavaScriptProxy_" + _renderClientAdapter->GetCefBrowser()->GetIdentifier())
gcnew EndpointAddress(JavascriptProxySupport::BaseAddress + "/" + serviceName)
);

_javaScriptProxy = channelFactory->CreateChannel();
Expand Down
30 changes: 0 additions & 30 deletions CefSharp/ScriptCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,36 +37,6 @@ namespace CefSharp
if (TryGetMainFrame(browser, mainFrame))
{
// TODO: fails, most likely because we are not in the render process.
CefRefPtr<CefV8Context> context = mainFrame->GetV8Context();

if (context.get() && context->Enter())
{
CefRefPtr<CefV8Value> result;
CefRefPtr<CefV8Exception> exception;

bool success = context->Eval(script, result, exception);
if (success)
{
try
{
_result = TypeUtils::ConvertFromCef(result);
}
catch (Exception^ ex)
{
_exceptionMessage = ex->Message;
}
}
else if (exception.get())
{
_exceptionMessage = StringUtils::ToClr(exception->GetMessage());
}
else
{
_exceptionMessage = "Failed to evaluate script";
}

context->Exit();
}
}
else
{
Expand Down
6 changes: 3 additions & 3 deletions CefSharp/Wrappers/CefAppWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// 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 "CefSubprocessWrapper.h"
#include "include/cef_app.h"

namespace CefSharp
Expand All @@ -25,7 +25,7 @@ namespace CefSharp
CefAppWrapper();
~CefAppWrapper();
void* GetUnmanaged();
virtual void OnBrowserCreated(CefBrowserWrapper^ cefBrowserWrapper) {};
virtual void OnBrowserCreated(CefSubprocessWrapper^ cefBrowserWrapper) {};

private:
!CefAppWrapper();
Expand All @@ -51,7 +51,7 @@ namespace CefSharp
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));
_cefAppWrapper->OnBrowserCreated(gcnew CefSubprocessWrapper(browser));
}

IMPLEMENT_REFCOUNTING(CefAppUnmanagedWrapper);
Expand Down
75 changes: 0 additions & 75 deletions CefSharp/Wrappers/CefBrowserWrapper.h

This file was deleted.

Loading

0 comments on commit 07c3c0c

Please sign in to comment.