prepare / kneadium

CEF3 bridge for C#
http://prepare.github.io/kneadium/
Other
8 stars 4 forks source link

Wiki: Intro #19

Closed prepare closed 7 years ago

prepare commented 7 years ago

from https://bitbucket.org/chromiumembedded/cef

Introduction

This tutorial explains how to create a simple application using CEF3. It references the cefsimple example project which is included with trunk revision 1535 (on Google Code) and newer. For complete CEF3 usage information visit the GeneralUsage Wiki page.

Getting Started

Begin by downloading a binary distribution for your platform from http://cefbuilds.com. For the purposes of this tutorial download the 2171 branch or newer. Currently supported platforms include Windows, Linux and Mac OS X. Each binary distribution contains all files necessary to build a particular version of CEF3 on a particular platform. See the included README.txt file or the "Getting Started" section of the GeneralUsage Wiki page for a detailed description of binary distribution contents.

Building the Included Project

Applications based on CEF binary distributions can be built using standard platform build tools. This includes Visual Studio on Windows, Xcode on Mac OS X and gcc/make on Linux. Each platform has a slightly different build process and requirements.

Using CMake

Starting with 2171 branch the CEF3 sample applications can be built using CMake, a cross-platform open-source build system that can generate project files in many different formats. See the comments at the top of the CMakeLists.txt file included with the binary distribution for platform-specific CMake usage instructions.

DEPRECATED Using Pre-Built Project Files

Pre-built project files are provided with 2171 branch and older versions of CEF3.

Windows

Follow these steps to build the cefsimple application on Windows:

  1. Open the solution file appropriate to your version of Visual Studio. For example, when using Visual Studio 2010 open the cefclient2010.sln solution file.
  2. If you downloaded a 64-bit build make sure to select the 64-bit platform in Configuration Manager.
  3. Build the “cefsimple” target.
  4. If the build is successful an “out/Debug” directory (or “Release” if you selected the release configuration) will be created.
  5. Run “out/Debug/cefsimple.exe” to verify that it works.

Linux

Follow these steps to build the cefsimple application on Linux:

  1. Make sure you’re using one of the supported Linux distributions. This currently includes Debian Wheezy, Ubuntu Precise, and related Linux distributions. Newer versions will likely also work but may not have been tested.
  2. Install the required dependencies. This includes the build-essential, libgtk2.0-dev and libgtkglext1-dev packages (note that the GTK packages are only required for the cefclient example).
  3. Build the “cefsimple” target by running “./build.sh Debug”.
  4. If the build is successful an “out/Debug” directory (or “Release” if you selected the release configuration) will be created.
  5. Run “./out/Debug/cefsimple” to verify that it works.

Mac OS X

Follow these steps to build the cefsimple application on OS X:

  1. Open cefclient.xcodeproj using Xcode 4.x (Xcode 5.x is not yet tested or supported).
  2. Build the “cefsimple” target.
  3. If the build is successful an “xcodebuild/Debug” directory (or “Release” if you selected the release configuration) will be created.
  4. Run “open out/Debug/cefsimple.app” to verify that it works.

Loading a Custom URL

The cefsimple application loads google.com by default but you can change it to load a custom URL instead. The easiest way to load a different URL is via the command-line.

# Load the local file “c:\example\example.html”
cefsimple.exe --url=file://c:/example/example.html

You can also edit the source code in cefsimple/simple_app.cpp and recompile the application to load your custom URL by default.

// Load the local file “c:\example\example.html”
…
if (url.empty())
  url = "file://c:/example/example.html";
…

Application Components

All CEF applications have the following primary components:

  1. The CEF dynamic library (libcef.dll on Windows, libcef.so on Linux, “Chromium Embedded Framework.framework” on OS X).
  2. Support libraries (ICU for unicode, ffmpeg for media playback, etc).
  3. Resources (html/js/css for built-in features, strings, etc).
  4. Client executable (cefsimple in this example).

The CEF dynamic library, support libraries and resources will be the same for every CEF-based application. They are included in the Debug/Release or Resources directory of the binary distribution. See the README.txt file included in the binary distribution for details on which of these files are required and which can be safely left out. See below for a detailed description of the required application layout on each platform.

Architecture in 60 Seconds

The below list summarizes the items of primary importance for this tutorial:

Read the GeneralUsage Wiki page for complete discussion of the above points.

Source Code

The cefsimple application initializes CEF and creates a single popup browser window. The application terminates when all browser windows have been closed. Program flow is as follows:

  1. The OS executes the browser process entry point function (main or wWinMain).
  2. The entry point function:
    1. Creates an instance of SimpleApp which handles process-level callbacks.
    2. Initializes CEF and runs the CEF message loop.
  3. After initialization CEF calls SimpleApp::OnContextInitialized(). This method:
    1. Creates the singleton instance of SimpleHandler.
    2. Creates a browser window using CefBrowserHost::CreateBrowserSync().
  4. All browsers share the SimpleHandler instance which is responsible for customizing browser behavior and handling browser-related callbacks (life span, loading state, title display, etc).
  5. When a browser window is closed SimpleHandler::OnBeforeClose() is called. When all browser windows have closed the OnBeforeClose implementation quits the CEF message loop to exit the application.

Your binary distribution may include newer versions of the below files. However, the general concepts remain unchanged.

Entry Point Function

Execution begins in the browser process entry point function. This function is responsible for initializing CEF and any OS-related objects. For example, it installs X11 error handlers on Linux and allocates the necessary Cocoa objects on OS X. OS X has a separate entry point function for helper processes (see the OS X section below).

Windows Entry Point

// cefsimple_win.cpp
#include <windows.h>

#include "cefsimple/simple_app.h"
#include "include/cef_sandbox_win.h"

// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
// automatically if using the required compiler version. Pass -DUSE_SANDBOX=OFF
// to the CMake command-line to disable use of the sandbox.
// Uncomment this line to manually enable sandbox support.
// #define CEF_USE_SANDBOX 1

#if defined(CEF_USE_SANDBOX)
// The cef_sandbox.lib static library is currently built with VS2013. It may not
// link successfully with other VS versions.
#pragma comment(lib, "cef_sandbox.lib")
#endif

// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPTSTR    lpCmdLine,
                      int       nCmdShow) {
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);

  void* sandbox_info = NULL;

#if defined(CEF_USE_SANDBOX)
  // Manage the life span of the sandbox information object. This is necessary
  // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
  CefScopedSandboxInfo scoped_sandbox;
  sandbox_info = scoped_sandbox.sandbox_info();
#endif

  // Provide CEF with command-line arguments.
  CefMainArgs main_args(hInstance);

  // SimpleApp implements application-level callbacks. It will create the first
  // browser instance in OnContextInitialized() after CEF has initialized.
  CefRefPtr<SimpleApp> app(new SimpleApp);

  // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
  // that share the same executable. This function checks the command-line and,
  // if this is a sub-process, executes the appropriate logic.
  int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);
  if (exit_code >= 0) {
    // The sub-process has completed so return here.
    return exit_code;
  }

  // Specify CEF global settings here.
  CefSettings settings;

#if !defined(CEF_USE_SANDBOX)
  settings.no_sandbox = true;
#endif

  // Initialize CEF.
  CefInitialize(main_args, settings, app.get(), sandbox_info);

  // Run the CEF message loop. This will block until CefQuitMessageLoop() is
  // called.
  CefRunMessageLoop();

  // Shut down CEF.
  CefShutdown();

  return 0;
}

Linux Entry Point

// cefsimple_linux.cpp
#include "cefsimple/simple_app.h"

#include <X11/Xlib.h>

#include "include/base/cef_logging.h"

namespace {

int XErrorHandlerImpl(Display *display, XErrorEvent *event) {
  LOG(WARNING)
        << "X error received: "
        << "type " << event->type << ", "
        << "serial " << event->serial << ", "
        << "error_code " << static_cast<int>(event->error_code) << ", "
        << "request_code " << static_cast<int>(event->request_code) << ", "
        << "minor_code " << static_cast<int>(event->minor_code);
  return 0;
}

int XIOErrorHandlerImpl(Display *display) {
  return 0;
}

}  // namespace

// Entry point function for all processes.
int main(int argc, char* argv[]) {
  // Provide CEF with command-line arguments.
  CefMainArgs main_args(argc, argv);

  // SimpleApp implements application-level callbacks. It will create the first
  // browser instance in OnContextInitialized() after CEF has initialized.
  CefRefPtr<SimpleApp> app(new SimpleApp);

  // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
  // that share the same executable. This function checks the command-line and,
  // if this is a sub-process, executes the appropriate logic.
  int exit_code = CefExecuteProcess(main_args, app.get(), NULL);
  if (exit_code >= 0) {
    // The sub-process has completed so return here.
    return exit_code;
  }

  // Specify CEF global settings here.
  CefSettings settings;

  // Install xlib error handlers so that the application won't be terminated
  // on non-fatal errors.
  XSetErrorHandler(XErrorHandlerImpl);
  XSetIOErrorHandler(XIOErrorHandlerImpl);

  // Initialize CEF for the browser process.
  CefInitialize(main_args, settings, app.get(), NULL);

  // Run the CEF message loop. This will block until CefQuitMessageLoop() is
  // called.
  CefRunMessageLoop();

  // Shut down CEF.
  CefShutdown();

  return 0;
}

Mac OS X Entry Point

Browser process entry point:

// cefsimple_mac.mm
#import <Cocoa/Cocoa.h>

#include "cefsimple/simple_app.h"
#include "cefsimple/simple_handler.h"
#include "include/cef_application_mac.h"
#include "include/wrapper/cef_helpers.h"

// Receives notifications from the application.
@interface SimpleAppDelegate : NSObject
- (void)createApplication:(id)object;
- (void)tryToTerminateApplication:(NSApplication*)app;
@end

// Provide the CefAppProtocol implementation required by CEF.
@interface SimpleApplication : NSApplication<CefAppProtocol> {
@private
  BOOL handlingSendEvent_;
}
@end

@implementation SimpleApplication
- (BOOL)isHandlingSendEvent {
  return handlingSendEvent_;
}

- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
  handlingSendEvent_ = handlingSendEvent;
}

- (void)sendEvent:(NSEvent*)event {
  CefScopedSendingEvent sendingEventScoper;
  [super sendEvent:event];
}

// |-terminate:| is the entry point for orderly "quit" operations in Cocoa. This
// includes the application menu's quit menu item and keyboard equivalent, the
// application's dock icon menu's quit menu item, "quit" (not "force quit") in
// the Activity Monitor, and quits triggered by user logout and system restart
// and shutdown.
//
// The default |-terminate:| implementation ends the process by calling exit(),
// and thus never leaves the main run loop. This is unsuitable for Chromium
// since Chromium depends on leaving the main run loop to perform an orderly
// shutdown. We support the normal |-terminate:| interface by overriding the
// default implementation. Our implementation, which is very specific to the
// needs of Chromium, works by asking the application delegate to terminate
// using its |-tryToTerminateApplication:| method.
//
// |-tryToTerminateApplication:| differs from the standard
// |-applicationShouldTerminate:| in that no special event loop is run in the
// case that immediate termination is not possible (e.g., if dialog boxes
// allowing the user to cancel have to be shown). Instead, this method tries to
// close all browsers by calling CloseBrowser(false) via
// ClientHandler::CloseAllBrowsers. Calling CloseBrowser will result in a call
// to ClientHandler::DoClose and execution of |-performClose:| on the NSWindow.
// DoClose sets a flag that is used to differentiate between new close events
// (e.g., user clicked the window close button) and in-progress close events
// (e.g., user approved the close window dialog). The NSWindowDelegate
// |-windowShouldClose:| method checks this flag and either calls
// CloseBrowser(false) in the case of a new close event or destructs the
// NSWindow in the case of an in-progress close event.
// ClientHandler::OnBeforeClose will be called after the CEF NSView hosted in
// the NSWindow is dealloc'ed.
//
// After the final browser window has closed ClientHandler::OnBeforeClose will
// begin actual tear-down of the application by calling CefQuitMessageLoop.
// This ends the NSApplication event loop and execution then returns to the
// main() function for cleanup before application termination.
//
// The standard |-applicationShouldTerminate:| is not supported, and code paths
// leading to it must be redirected.
- (void)terminate:(id)sender {
  SimpleAppDelegate* delegate =
      static_cast<SimpleAppDelegate*>([NSApp delegate]);
  [delegate tryToTerminateApplication:self];
  // Return, don't exit. The application is responsible for exiting on its own.
}
@end

@implementation SimpleAppDelegate

// Create the application on the UI thread.
- (void)createApplication:(id)object {
  [NSApplication sharedApplication];
  [NSBundle loadNibNamed:@"MainMenu" owner:NSApp];

  // Set the delegate for application events.
  [NSApp setDelegate:self];
}

- (void)tryToTerminateApplication:(NSApplication*)app {
  SimpleHandler* handler = SimpleHandler::GetInstance();
  if (handler && !handler->IsClosing())
    handler->CloseAllBrowsers(false);
}

- (NSApplicationTerminateReply)applicationShouldTerminate:
      (NSApplication *)sender {
  return NSTerminateNow;
}
@end

// Entry point function for the browser process.
int main(int argc, char* argv[]) {
  // Provide CEF with command-line arguments.
  CefMainArgs main_args(argc, argv);

  // SimpleApp implements application-level callbacks. It will create the first
  // browser instance in OnContextInitialized() after CEF has initialized.
  CefRefPtr<SimpleApp> app(new SimpleApp);

  // Initialize the AutoRelease pool.
  NSAutoreleasePool* autopool = [[NSAutoreleasePool alloc] init];

  // Initialize the SimpleApplication instance.
  [SimpleApplication sharedApplication];

  // Specify CEF global settings here.
  CefSettings settings;

  // Initialize CEF for the browser process.
  CefInitialize(main_args, settings, app.get(), NULL);

  // Create the application delegate.
  NSObject* delegate = [[SimpleAppDelegate alloc] init];
  [delegate performSelectorOnMainThread:@selector(createApplication:)
                             withObject:nil
                          waitUntilDone:NO];

  // Run the CEF message loop. This will block until CefQuitMessageLoop() is
  // called.
  CefRunMessageLoop();

  // Shut down CEF.
  CefShutdown();

  // Release the delegate.
  [delegate release];

  // Release the AutoRelease pool.
  [autopool release];

  return 0;
}

Sub-process entry point:

// process_helper_mac.cpp
#include "include/cef_app.h"

// Entry point function for sub-processes.
int main(int argc, char* argv[]) {
  // Provide CEF with command-line arguments.
  CefMainArgs main_args(argc, argv);

  // Execute the sub-process.
  return CefExecuteProcess(main_args, NULL, NULL);
}

SimpleApp

SimpleApp is responsible for handling process-level callbacks. It exposes some interfaces/methods that are shared by multiple processes and some that are only called in a particular process. The CefBrowserProcessHandler interface, for example, is only called in the browser process. There’s a separate CefRenderProcessHandler interface (not shown in this example) that is only called in the render process. Note that GetBrowserProcessHandler() must return |this| because SimpleApp implements both CefApp and CefBrowserProcessHandler. See the GeneralUsage Wiki page or API header files for additional information on CefApp and related interfaces.

// simple_app.h
#include "include/cef_app.h"

class SimpleApp : public CefApp,
                  public CefBrowserProcessHandler {
 public:
  SimpleApp();

  // CefApp methods:
  virtual CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler()
      OVERRIDE { return this; }

  // CefBrowserProcessHandler methods:
  virtual void OnContextInitialized() OVERRIDE;

 private:
  // Include the default reference counting implementation.
  IMPLEMENT_REFCOUNTING(SimpleApp);
};

// simple_app.cpp
#include "cefsimple/simple_app.h"

#include <string>

#include "cefsimple/simple_handler.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/wrapper/cef_helpers.h"

SimpleApp::SimpleApp() {
}

void SimpleApp::OnContextInitialized() {
  CEF_REQUIRE_UI_THREAD();

  // Information used when creating the native window.
  CefWindowInfo window_info;

#if defined(OS_WIN)
  // On Windows we need to specify certain flags that will be passed to
  // CreateWindowEx().
  window_info.SetAsPopup(NULL, "cefsimple");
#endif

  // SimpleHandler implements browser-level callbacks.
  CefRefPtr<SimpleHandler> handler(new SimpleHandler());

  // Specify CEF browser settings here.
  CefBrowserSettings browser_settings;

  std::string url;

  // Check if a "--url=" value was provided via the command-line. If so, use
  // that instead of the default URL.
  CefRefPtr<CefCommandLine> command_line =
      CefCommandLine::GetGlobalCommandLine();
  url = command_line->GetSwitchValue("url");
  if (url.empty())
    url = "http://www.google.com";

  // Create the first browser window.
  CefBrowserHost::CreateBrowser(window_info, handler.get(), url,
                                browser_settings, NULL);
}

SimpleHandler

SimpleHandler is responsible for handling browser-level callbacks. These callbacks are executed in the browser process. In this example we use the same CefClient instance for all browsers, but your application can use different CefClient instances as appropriate. See the GeneralUsage Wiki page or API header files for additional information on CefClient and related interfaces.

// simple_handler.h
#include "include/cef_client.h"

#include <list>

class SimpleHandler : public CefClient,
                      public CefDisplayHandler,
                      public CefLifeSpanHandler,
                      public CefLoadHandler {
 public:
  SimpleHandler();
  ~SimpleHandler();

  // Provide access to the single global instance of this object.
  static SimpleHandler* GetInstance();

  // CefClient methods:
  virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
    return this;
  }
  virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
    return this;
  }
  virtual CefRefPtr<CefLoadHandler> GetLoadHandler() OVERRIDE {
    return this;
  }

  // CefDisplayHandler methods:
  virtual void OnTitleChange(CefRefPtr<CefBrowser> browser,
                             const CefString& title) OVERRIDE;

  // CefLifeSpanHandler methods:
  virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
  virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;

  // CefLoadHandler methods:
  virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
                           CefRefPtr<CefFrame> frame,
                           ErrorCode errorCode,
                           const CefString& errorText,
                           const CefString& failedUrl) OVERRIDE;

  // Request that all existing browser windows close.
  void CloseAllBrowsers(bool force_close);

 private:
  // List of existing browser windows. Only accessed on the CEF UI thread.
  typedef std::list<CefRefPtr<CefBrowser> > BrowserList;
  BrowserList browser_list_;

  // Include the default reference counting implementation.
  IMPLEMENT_REFCOUNTING(SimpleHandler);
};

// simple_handler.cpp
#include "cefsimple/simple_handler.h"

#include <sstream>
#include <string>

#include "cefsimple/util.h"
#include "include/cef_app.h"
#include "include/cef_runnable.h"

namespace {

SimpleHandler* g_instance = NULL;

}  // namespace

SimpleHandler::SimpleHandler() {
  ASSERT(!g_instance);
  g_instance = this;
}

SimpleHandler::~SimpleHandler() {
  g_instance = NULL;
}

// static
SimpleHandler* SimpleHandler::GetInstance() {
  return g_instance;
}

void SimpleHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
  REQUIRE_UI_THREAD();

  // Add to the list of existing browsers.
  browser_list_.push_back(browser);
}

void SimpleHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
  REQUIRE_UI_THREAD();

  // Remove from the list of existing browsers.
  BrowserList::iterator bit = browser_list_.begin();
  for (; bit != browser_list_.end(); ++bit) {
    if ((*bit)->IsSame(browser)) {
      browser_list_.erase(bit);
      break;
    }
  }

  if (browser_list_.empty()) {
    // All browser windows have closed. Quit the application message loop.
    CefQuitMessageLoop();
  }
}

void SimpleHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
                                CefRefPtr<CefFrame> frame,
                                ErrorCode errorCode,
                                const CefString& errorText,
                                const CefString& failedUrl) {
  REQUIRE_UI_THREAD();

  // Don't display an error for downloaded files.
  if (errorCode == ERR_ABORTED)
    return;

  // Display a load error message.
  std::stringstream ss;
  ss << "<html><body bgcolor=\"white\">"
        "<h2>Failed to load URL " << std::string(failedUrl) <<
        " with error " << std::string(errorText) << " (" << errorCode <<
        ").</h2></body></html>";
  frame->LoadString(ss.str(), failedUrl);
}

void SimpleHandler::CloseAllBrowsers(bool force_close) {
  if (!CefCurrentlyOn(TID_UI)) {
    // Execute on the UI thread.
    CefPostTask(TID_UI,
        NewCefRunnableMethod(this, &SimpleHandler::CloseAllBrowsers,
                             force_close));
    return;
  }

  if (browser_list_.empty())
    return;

  BrowserList::const_iterator it = browser_list_.begin();
  for (; it != browser_list_.end(); ++it)
    (*it)->GetHost()->CloseBrowser(force_close);
}

// simple_handler_win.cpp -- Windows-specific code.
#include "cefsimple/simple_handler.h"

#include <string>
#include <windows.h>

#include "cefsimple/util.h"
#include "include/cef_browser.h"

void SimpleHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
                                  const CefString& title) {
  REQUIRE_UI_THREAD();

  CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle();
  SetWindowText(hwnd, std::wstring(title).c_str());
}

// simple_handler_linux.cc  -- Linux-specific code.
#include "cefsimple/simple_handler.h"

#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <string>

#include "include/cef_browser.h"
#include "include/wrapper/cef_helpers.h"

void SimpleHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
                                  const CefString& title) {
  CEF_REQUIRE_UI_THREAD();
  std::string titleStr(title);

  // Retrieve the X11 display shared with Chromium.
  ::Display* display = cef_get_xdisplay();
  DCHECK(display);

  // Retrieve the X11 window handle for the browser.
  ::Window window = browser->GetHost()->GetWindowHandle();
  DCHECK(window != kNullWindowHandle);

  // Retrieve the atoms required by the below XChangeProperty call.
  const char* kAtoms[] = {
    "_NET_WM_NAME",
    "UTF8_STRING"
  };
  Atom atoms[2];
  int result = XInternAtoms(display, const_cast<char**>(kAtoms), 2, false,
                            atoms);
  if (!result)
    NOTREACHED();

  // Set the window title.
  XChangeProperty(display,
                  window,
                  atoms[0],
                  atoms[1],
                  8,
                  PropModeReplace,
                  reinterpret_cast<const unsigned char*>(titleStr.c_str()),
                  titleStr.size());

  // TODO(erg): This is technically wrong. So XStoreName and friends expect
  // this in Host Portable Character Encoding instead of UTF-8, which I believe
  // is Compound Text. This shouldn't matter 90% of the time since this is the
  // fallback to the UTF8 property above.
  XStoreName(display, browser->GetHost()->GetWindowHandle(), titleStr.c_str());
}

// simple_handler_mac.mm -- OS X-specific code.
#include "cefsimple/simple_handler.h"

#import <Cocoa/Cocoa.h>

#include "cefsimple/util.h"
#include "include/cef_browser.h"

void SimpleHandler::OnTitleChange(CefRefPtr<CefBrowser> browser,
                                  const CefString& title) {
  REQUIRE_UI_THREAD();

  NSView* view = (NSView*)browser->GetHost()->GetWindowHandle();
  NSWindow* window = [view window];
  std::string titleStr(title);
  NSString* str = [NSString stringWithUTF8String:titleStr.c_str()];
  [window setTitle:str];
}

Build Steps

Build steps vary depending on the platform. Explore the CMake files included with the binary distribution for a complete understanding of all required steps. The build steps common to all platforms can generally be summarized as follows:

  1. Compile the libcef_dll_wrapper static library.
  2. Compile the application source code files. Link against the libcef dynamic library and the libcef_dll_wrapper static library.
  3. Copy libraries and resources to the output directory.

Windows Build Steps

  1. Compile the libcef_dll_wrapper static library.
  2. Compile/link cefsimple.exe.
    • Required source code files include: cefsimple_win.cpp, simple_app.cpp, simple_handler.cpp, simple_handler_win.cpp.
    • Required link libraries include: comctl32.lib, shlwapi.lib, rcprt4.lib, libcef_dll_wrapper.lib, libcef.lib, cef_sandbox.lib. Note that cef_sandbox.lib (required for sandbox support) is a static library currently built with Visual Studio 2013 and it may not compile with other Visual Studio versions. See comments in cefsimple_win.cpp for how to disable sandbox support.
    • Resource file is cefsimple.rc.
    • Manifest files are cefsimple.exe.manifest and compatibility.manifest.
  3. Copy all files from the Resources directory to the output directory.
  4. Copy all files from the Debug/Release directory to the output directory.

The resulting directory structure looks like this:

Application/
  cefsimple.exe  <= cefsimple application executable
  libcef.dll <= main CEF library
  icudt.dll <= ICU unicode support library
  ffmpegsumo.dll <= HTML5 audio/video support library
  libEGL.dll, libGLESv2.dll, … <= accelerated compositing support libraries
  cef.pak, devtools_resources.pak <= non-localized resources and strings
  locales/
    en-US.pak, … <= locale-specific resources and strings

Linux Build Steps

  1. Compile the libcef_dll_wrapper static library.
  2. Compile/link cefsimple.
    • Required source code files include: cefsimple_linux.cpp, simple_app.cpp, simple_handler.cpp, simple_handler_linux.cpp.
    • Required link libraries include: libcef_dll_wrapper.so, libcef.so and dependencies (identified at build time using the “pkg-config” tool).
    • Configure the rpath to find libcef.so in the current directory (“-Wl,-rpath,.”) or use the LD_LIBRARY_PATH environment variable.
  3. Copy all files from the Resources directory to the output directory.
  4. Copy all files from the Debug/Release directory to the output directory.
  5. Set SUID permissions on the chrome-sandbox executable to support the sandbox. This is done as the last step in the provided build.sh script.

The resulting directory structure looks like this:

Application/
  cefsimple  <= cefsimple application executable
  chrome-sandbox <= sandbox support binary
  libcef.so <= main CEF library
  ffmpegsumo.so <-- HTML5 audio/video support library
  cef.pak, devtools_resources.pak <= non-localized resources and strings
  locales/
    en-US.pak, … <= locale-specific resources and strings

Mac OS X Build Steps

  1. Compile the libcef_dll_wrapper static library.
  2. Compile/link/package the “cefsimple Helper” app.
    • Required source code files include: process_helper_mac.cpp.
    • Required link frameworks include: AppKit.framework, Chromium Embedded Framework.framework (unversioned, included in the binary distribution).
    • App bundle configuration is provided via “cefsimple/mac/helper-Info.plist”.
    • Use “install_name_tool -change” to rewrite the framework link so that it points to the “Chromium Embedded Framework.framework/Chromium Embedded Framework” library in the correct location.
  3. Compile/link/package the “cefsimple” app.
    • Required source code files include: cefsimple_mac.mm, simple_app.cpp, simple_handler.cpp, simple_handler_mac.mm.
    • Required link frameworks include: AppKit.framework, Chromium Embedded Framework.framework (unversioned, included in the binary distribution).
    • App bundle configuration is provided via “cefsimple/mac/Info.plist”.
    • Use “install_name_tool -change” to rewrite the framework link so that it points to the “Chromium Embedded Framework.framework/Chromium Embedded Framework” library in the correct location.
  4. Create a Contents/Frameworks directory in the cefsimple.app bundle. Copy the following files to that directory: libplugin_carbon_interpose.dylib, “cefsimple Helper.app”, “Chromium Embedded Framework.framework”.
  5. Run the “tools/make_more_helpers.sh” script to copy/configure the sub-process helper app bundles based on “cefsimple Helper.app”.

The resulting directory structure looks like this:

cefsimple.app/
  Contents/
    Frameworks/
      Chromium Embedded Framework.framework/
        Chromium Embedded Framework <= main application library
        Libraries/
          ffmpegsumo.so <= HTML5 audio/video support library
        Resources/
          cef.pak, devtools_resources.pak <= non-localized resources and strings
          crash_inspector, crash_report_sender <= breakpad support
          en.lproj/, ... <= locale-specific resources and strings
          Info.plist
      libplugin_carbon_interpose.dylib <= plugin support library
      cefsimple Helper.app/
        Contents/
          Info.plist
          MacOS/
            cefsimple Helper <= helper executable
          Pkginfo
      cefsimple Helper EH.app/
        Contents/
          Info.plist
          MacOS/
            cefsimple Helper EH <= helper executable
          Pkginfo
      cefsimple Helper NP.app/
        Contents/
          Info.plist
          MacOS/
            cefsimple Helper NP <= helper executable
          Pkginfo
      Info.plist
    MacOS/
      cefsimple <= cefsimple application executable
    Pkginfo
    Resources/
      cefsimple.icns, ... <= cefsimple application resources