📜 ⬆️ ⬇️

Awesomium for C ++

Awesomium is a library for integrating a Chromium-based browser into your application. The beauty of Awesomium is that it can be integrated into almost any type of application (there are examples of integration into 3D games based on Unity3D), it has a wide range of features for the developer and, frankly, it's just a pleasure to work with it.

But, unfortunately, the library has rather modest documentation, there are practically no examples and communities (this applies to C ++ development, and more to the dotnetchikam). I had to collect some moments bit by bit from various sources, while others came to understanding after a series of trial and error.

And having accumulated some knowledge, I decided to share them. I am sure that I am not the first and not the last who will pass this way.
')
I just want to warn you: maybe in some places I misunderstood or misunderstood, you should not judge strictly, just point the correct way, I will be very grateful.

Window and windowless awesomium



First of all, it should be said that applications using Awesomium can be of 2 types:



The first is interesting because it allows you to work with a browser without a window. You can even work with a console application, for example, to create screenshots of pages. We will not dwell on this type, because there are good examples on it and I actually did not work with it. I was interested in the second mode - Windowed.

Windowed Awesomium is used when you need a full browser in a windowed application. In this case, the library will take care of the main thing - user interaction. But do not think that adding a couple of lines in the program you get a full browser, it is not. The lion's part of the work lies on the programmers' shoulders, for example: file upload / upload dialogs (yes, all dialogs in principle), pop-up menus, drop-down lists, the creation of new tabs, etc.

Library structure



The structure of the library is very simple (although at first it was not at all obvious):

The core of the browser is the core ( WebCore ). Each application can have only one core and this in turn imposes some restrictions. For example, if you want a tab to be canceled by other User Agents, then you will not succeed, because the User Agent value is stored in the kernel settings.

Next in the hierarchy is WebView - this is a browser window. When creating each WebView, a separate Chromium process is launched. When you no longer need WebView - do not forget to clean it up, otherwise the process will hang until we destroy WebCore.

Each WebView can use a session ( WebSession ). Session is user data (cookies, caches, certificates, local databases, etc.). One WebSession can be connected to different WebView. Also in the WebSession are stored important settings for browsers (those that use this session), such as a proxy.

Well, the last thing (from what I had to work with) is Listeners - interfaces for interacting with the browser. Listeners are several and each of them solves certain problems. For example, WebViewListener :: Dialog contains implementation of methods for working with dialog boxes, and WebViewListener :: Download contains methods for informing about the progress of file downloads.

Birth



With the theory of done, go to the practice. First of all, let's consider the process of creating and initializing the kernel and browser tabs in Windowed mode.

First you need to initialize the kernel:
WebCore* core = 0; WebConfig config; core = WebCore::Initialize(config); 


Next, create a session (and for the example, in the session settings, write the proxy used)
 WebPreferences prefs; prefs.proxy_config = WSLit("198.1.99.26:3128"); WebSession * session = core->CreateWebSession(WSLit(""), prefs); 


And of course, create a WebView object.
 WebView* view = core->CreateWebView(WIN_WIDTH, WIN_HEIGHT, session, kWebViewType_Window); view->set_parent_window(hwnd); 


At the last step we will dwell in more detail:



A life



Depending on the purpose for which Awesomium is used - its “life” may differ significantly. I will only focus on the main points when working with the Windowed tabs.

First, despite the fact that Windowed Awesomium partially lives its life, it is still necessary to periodically push it to work. The kernel Update method is pushing . It is recommended to call it in a timer, like this:

 // Create our WebCore Update timer, renders at a max of 66 FPS UINT myTimer = SetTimer ( hwnd, 0, 15, NULL ); ... case WM_TIMER: { if (core) { core->Update(); } } ... 


It is also recommended to do kernel updates after destroying WebView.

Secondly, if you want the browser window to change its size along with the parent window, you must process the WM_SIZE message of the parent window and report the new sizes to the browser. This is done quite simply:

 case WM_SIZE: { if (view) { int nWidth = LOWORD(lParam); //    int nHeight = HIWORD(lParam); //    view->Resize(nWidth, nHeight); } } 


And thirdly, for the full operation of the browser, you need to implement the Listeners interfaces and connect them to each of the WebView. There should be no problems with the implementation of interfaces, they are well documented. All necessary hints can be found in the WebViewListener.h file. Well, it's not difficult to connect them:

 DialogListener * dialog_lis = new DialogListener(); view->set_dialog_listener(dialog_lis); 


As I said before, when working in Windowed mode, the library will worry about a lot of things: drawing the loaded page on the parent window, handling keyboard and mouse keystrokes, changing mouse cursors, etc.

Well, at the end of this chapter is a small example of opening the page and waiting for it to load:

 //   view->LoadURL(WebURL(WSLit("http://google.com/"))); //    while(view->IsLoading()) { Sleep(50); core->Update(); } //   (     ) view->Focus(); 


Death



With the cleaning after work, the greatest problems arose. Information about this in the official documentation and on Google for work in Windowed mode is slightly more than zero. Through trial and error, I came to the following:

1. Before destroying WebView, you first need to destroy the parent window (the reverse order will cause the application to crash).

2. If you want the session data to be saved (if it is not an in-memmory session), you need to call the Release method for the session instance.

3. WebView is destroyed by calling the Destroy method (and nothing else)

4. The kernel is destroyed by calling the Shutdown method, which by the way is able to clean up and behind the incorrectly destroyed WebView (but it’s better still to control the process itself)

Approximately, it looks like this:

 // -     ... //    (     ,      ,    ) view->Stop(); //      view->session()->Release(); //  WebView (    Chromium       ) view->Destroy(); //   (      ,      ) core->Update(); //   core->Shutdown(); 


It is necessary to destroy the kernel only before shutting down the program. If you just need to close one browser tab, then you only need to delete it and WebView, which was located on this tab.

useful links



When studying Awesomium, the comments in the header files in the \ Awesomium SDK \ 1.7.1.0 \ include \ Awesomium \ and the following Internet pages helped me a lot.

- wiki.awesomium.com/general-use - modest examples of use from the creators of Awesomium. There is also a description of how to create a project using this library and which files are necessary for the application to work.

- awesomium.com/docs/1_7_0/cpp_api/index.html#intro_sec - official documentation (essentially duplicates the comments in the connected header files)

- gist.github.com/khrona - the work of the user khrona on github. He helped me a lot to create the first test application, in particular this example of Example of using Awesomium r148 API with GDI / WinForms / WinAPI . True, he is trying to do in Offscreen mode a similarity to the Windowed mode, because of which he has scanty functionality (for example, the scrolling does not work and the mouse cursor does not change when hovering over the link), as well as a lot of excess when.

- answers.awesomium.com/index.html - answers to users' questions. Unfortunately, not all questions get answers, so there is not very much useful information, but it is

Source: https://habr.com/ru/post/183826/


All Articles