# Create a Chromium Embedded Framework Project

## In this learning path

- [Introduction](https://learn.arm.com/learning-paths/laptops-and-desktops/win_cef/)
- [Create a Chromium Embedded Framework Project](https://learn.arm.com/learning-paths/laptops-and-desktops/win_cef/how-to-1/)
- [Next Steps](https://learn.arm.com/learning-paths/laptops-and-desktops/win_cef/_next-steps/)

## Introduction
The Chromium Embedded Framework (CEF) is a robust and versatile open-source framework that simplifies the embedding of Chromium-based web browsers into other applications. Primarily written in C++, CEF enables developers to seamlessly integrate web functionalities into desktop programs. It leverages modern web technologies, enriching user interfaces with dynamic web content and utilizing a familiar web development stack in desktop application development. CEF’s widespread adoption is attributed to its high performance, extensive features, and ability to deliver consistent, cross-platform web experiences in native applications.

In this learning path, you will learn how to create a desktop application for Windows on Arm64. This application will fetch and display data from `JSONPlaceholder`, a mock REST API for demonstration purposes. Fetching and displaying data from an API is a standard functionality in web applications, and through this process, you will learn how to effectively utilize web technologies in a desktop app.

## Before you begin
Before you begin, install the following:
1. CMake for Arm64 [link](https://github.com/Kitware/CMake/releases/download/v3.28.1/cmake-3.28.1-windows-arm64.msi). During an installation check **Add CMake to the system PATH for the current user** as shown below
2. Visual Studio 2022 with Desktop development with C++ workload

## Prepare the project
Start by downloading the Standard Distribution of the CEF binary for [Windows on Arm64](https://cef-builds.spotifycdn.com/index.html#windowsarm64). In this learning path, you will use the following CEF version: 120.1.10+g3ce3184+chromium-120.0.6099.129 / Chromium 120.0.6099.129.

Extract the downloaded file to a folder. Right-click the downloaded file, select ‘Extract all…’, and name the folder ‘cef-binary’. Once the extraction process completes, you will find a folder named ‘cef_binary_120.1.10+g3ce3184+chromium-120.0.6099.129_windowsarm64’ within ‘cef-binary’. Note that the exact name might differ if you have downloaded a different CEF version.

Next, rename the folder `cef_binary_120.1.10+g3ce3184+chromium-120.0.6099.129_windowsarm64` to `windowsarm64` for simplicity.

Now, use CMake to prepare the build files for Visual Studio 2022 and the Arm64 architecture. Open the Command Prompt or a Terminal, and proceed with the following steps:
```bash
cd <PATH_TO_CEF_BINARY>
cd windowsarm64

cmake -G "Visual Studio 17" -A arm64 -B build
```
Replace `<PATH_TO_CEF_BINARY>` in the command above to the directory path on your machine where you downloaded the CEF binary.

The output of this command will look like:
```
__output__
C:\cef_binary\windowsarm64>cmake -G "Visual Studio 17" -A arm64 -B build
__output__ -- Selecting Windows SDK version 10.0.22621.0 to target Windows 10.0.22631.
__output__ -- The C compiler identification is MSVC 19.38.33133.0
__output__ -- The CXX compiler identification is MSVC 19.38.33133.0
...
-- Build files have been written to: C:/cef_binary/windowsarm64/build
```

## Build the project
The previous command has generated the build files in the ‘build’ subfolder within ‘cef_binary/windowsarm64’. To build the project, use the following CMake command in the console:
```bash
cmake --build build
```
This command compiles the project, including sample applications such as `cefsimple`. This particular application creates a browser window and renders an HTML website. It is composed of several components, including the `SimpleApp` class, which is crucial for managing process-level callbacks in a CEF-based application. `SimpleApp` offers a variety of interfaces and methods crucial for multiple processes, along with some that are specific to certain process types. For example, the `CefBrowserProcessHandler interface` is unique to the browser process. The `GetBrowserProcessHandler()` method in `SimpleApp` must return a reference to `SimpleApp` itself since it implements both `CefApp` and `CefBrowserProcessHandler`. This ensures that appropriate handlers are accessible in the correct process context. For more detailed information about this application, visit the CEF project’s [website](https://bitbucket.org/chromiumembedded/cef/wiki/GeneralUsage.md#markdown-header-sample-application).

## Launching the application
Let’s run the `cefsimple` application. The binaries can be found under the `build\tests\cefsimple\Debug` folder. For example, the path might be something like `C:\cef_binary\windowsarm64\build\tests\cefsimple\Debug` but this could vary based on your specific setup.

By default, the application renders the Google homepage:

![Image Alt Text: fig2](https://learn.arm.com/learning-paths/laptops-and-desktops/win_cef/figures/02.webp)

## Modify the application
You will now modify the `cefsimple` application to render a custom page. This page will fetch data from `JSONPlaceholder` and display it in a table.

First, close the `cefsimple` application if it’s running. Then, locate and open the `simple_app.cc` file, under the `cef_binary\windowsarm64\tests\cefsimple` folder. Scroll down to the definition of the `SimpleApp` class, and modify the `OnContextInitialized` method. Change the URL from [https://www.google.com](https://www.google.com) to `file://c:\web\index.html`. (**note**: replace this path with the actual location of your custom HTML file.):
```cpp
void SimpleApp::OnContextInitialized() {
  CEF_REQUIRE_UI_THREAD();

  CefRefPtr<CefCommandLine> command_line = CefCommandLine::GetGlobalCommandLine();

  // Create the browser using the Views framework if "--use-views" is specified
  // via the command-line. Otherwise, create the browser using the native
  // platform framework.
  const bool use_views = command_line->HasSwitch("use-views");

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

  // 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.
  url = command_line->GetSwitchValue("url");
  if (url.empty()) {
    //url = "http://www.google.com";
    url = "file://c:\\web\\index.html";
  }

  if (use_views) {
    // Create the BrowserView.
    CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
        handler, url, browser_settings, nullptr, nullptr,
        new SimpleBrowserViewDelegate());

    // Create the Window. It will show itself after creation.
    CefWindow::CreateTopLevelWindow(new SimpleWindowDelegate(browser_view));
  } else {
    // 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(nullptr, "cefsimple");
#endif

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

CefRefPtr<CefClient> SimpleApp::GetDefaultClient() {
  // Called when a new browser window is created via the Chrome runtime UI.
  return SimpleHandler::GetInstance();
}
```
Make sure to save the `simple_app.cc` file after making your changes. Then, to rebuild the project, open your Command Prompt or Terminal, navigate to your build directory, and type the following command:
```bash
cmake --build build
```
This command will compile the updated code and rebuild the `cefsimple` application with your modifications. Remember, it’s important to be in the directory where your CMake build files are located when executing this command.

### Custom webpage
You will now create a custom index.html file to fetch the data from the JSONPlaceholder:
1. Create the new folder `C:\web`.
2. Under `C:\web` create a new file `index.html` and modify it as follows:
```html
<!DOCTYPE html>
<html>
<head>
    <title>CEF JSONPlaceholder Viewer</title>
    <script>
        function fetchPosts() {
            fetch('https://jsonplaceholder.typicode.com/posts')
                .then(response => response.json())
                .then(posts => {
                    let tableContent = posts.map(post => {
                        return `<tr><td>${post.id}</td><td>${post.title}</td><td>${post.body}</td></tr>`;
                    }).join('');
                    document.getElementById('postsTable').innerHTML = tableContent;
                })
                .catch(error => console.error('Error:', error));
        }
    </script>
</head>
<body>
    <h1>Posts from JSONPlaceholder</h1>
    <button onclick="fetchPosts()">Fetch Posts</button>
    <table>
        <thead>
            <tr>
                <th>ID</th>
                <th>Title</th>
                <th>Body</th>
            </tr>
        </thead>
        <tbody id="postsTable">
            <!-- Posts will be loaded here -->
        </tbody>
    </table>
</body>
</html>
```
Re-run the application and you will see the following:

![Image Alt Text: fig3](https://learn.arm.com/learning-paths/laptops-and-desktops/win_cef/figures/03.webp)

This example demonstrates the versatility and power of CEF applications. One of their key strengths is the ability to modify the rendered content dynamically. This means you can change what’s displayed in the application, like updating the HTML or CSS, without having to rebuild the entire application each time. This feature significantly streamlines the development process, making it quicker and more efficient.

Let’s leverage this capability to enhance our application. You will focus on styling the application by updating the HTML and CSS, providing a more engaging and visually appealing user interface. This step will show how easily you can improve the look and feel of your CEF application with a few modifications to the web content.

### Style the application
Add `styles.css` file to modify the appearance of the application:
1. In the `C:\web\` folder create a new file `styles.css` with the content below:
```css
body {
    font-family: Arial, sans-serif;
    margin: 20px;
    background-color: #f4f4f4;
    color: #333;
}

h1 {
    color: #007bff;
}

table {
    width: 100%;
    border-collapse: collapse;
}

table, th, td {
    border: 1px solid #ddd;
}

th, td {
    padding: 10px;
    text-align: left;
}

th {
    background-color: #007bff;
    color: white;
}

tr:nth-child(even) {
    background-color: #f2f2f2;
}

button {
    background-color: #007bff;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 16px;
    margin: 10px 0;
}

button:hover {
    background-color: #0056b3;
}
```
2. Modify `index.html` to reference `styles.css` as shown below:
```html
<!DOCTYPE html>
<html>
<head>
    <title>CEF JSONPlaceholder Viewer</title>
    <link rel="stylesheet" type="text/css" href="styles.css">
    <!--Other contents of the index.html file-->
</head>
```
After re-running the application you will see the following:

![Image Alt Text: fig4](https://learn.arm.com/learning-paths/laptops-and-desktops/win_cef/figures/04.webp)

## Summary
CEF is a powerful tool for integrating web browser functionalities into desktop applications, utilizing modern web technologies. You have learned how to setup a project, create a basic application, and use CMake for CEF projects. Additionally, you have explored more advanced features like fetching and displaying data from JSONPlaceholder, adding and styling HTML elements like tables and buttons through separate CSS files all on your Windows on Arm machine.
