Skip to content

Commit 3d37d03

Browse files
committed
CEF tutorial
1 parent 32fca47 commit 3d37d03

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import AutoStarlightPage from '@src/components/AutoStarlightPage.astro';
2+
import { getSeeAlsoLinksFromList } from '@src/utils/general';
3+
import SeeAlsoSection from '@src/components/SeeAlsoSection.astro';
4+
import VersionBox from '@src/components/VersionBox.astro';
5+
import { Code } from '@astrojs/starlight/components';
6+
import NoteBox from '@src/components/NoteBox.astro';
7+
8+
<AutoStarlightPage frontmatter={{
9+
template: 'doc',
10+
title: 'CEF Tutorial',
11+
tableOfContents: true
12+
}}>
13+
14+
## What is CEF?
15+
CEF stands for **C**hromium **E**mbedded **F**ramework and is a framework for embedding Chromium-based browsers in other applications - in our case MTA.
16+
CEF is based on Google's Chromium project so it is also a fast, secure and stable web engine.
17+
You can find more information about CEF on CEF's GoogleCode project page: https://bitbucket.org/chromiumembedded/cef
18+
19+
## The basics
20+
Creating a new browser is really simple. Let's open YouTube for example:
21+
22+
```lua
23+
-- Create a new remote browser (size is 800*600px) with transparency enabled
24+
local browser = createBrowser(800, 600, true, true)
25+
26+
-- "Wait" for the browser (this is necessary because CEF runs in a secondary thread and hence requires the 'asynchronous' event mechanism)
27+
addEventHandler("onClientBrowserCreated", browser, function()
28+
-- We're ready to load the URL now (the source of this event is the browser that has been created)
29+
loadBrowserURL(source, "https://youtube.com/")
30+
end)
31+
```
32+
33+
This example does not require any domain requests as YouTube is whitelisted by default. More about domain requests below.
34+
35+
## Domain request system
36+
In order to prevent people from abusing the possibilities CEF offers, we decided to introduce a request system.
37+
This means the domain you want to load has to meet at least one of the following requirements:
38+
- It isn't blacklisted globally by the MTA team. A domain might be blacklisted due to malicious content. Such domains cannot be requested.
39+
- The domain was requested via [requestBrowserDomains](/reference/requestBrowserDomains) and accepted by the player before.
40+
- The domain is on the user's whitelist `(MTA settings => Tab: Browser => Whitelist)`.
41+
42+
## Local vs remote mode
43+
There are two modes CEF can run in:
44+
45+
Characteristics of **local** mode:
46+
- You **can** execute Javascript code without any restriction (See: [executeBrowserJavascript](/reference/executeBrowserJavascript)).
47+
- You **can** only load websites stored in the resource folder (See [local scheme](/reference/Local_Scheme_Handler)).
48+
- You **cannot** load remote content.
49+
50+
Characteristics of **remote** mode:
51+
- You **cannot** execute Javascript code.
52+
- You **can** only load remote content.
53+
- Keep in mind that either loading remote websites or Javascript on remote websites can be disabled in the MTA settings.
54+
55+
Changing the mode after the browser was created is not possible due to technical reasons.
56+
57+
## Resource management
58+
### How to load local HTML files
59+
Loading local HTML files works similar to loading images.
60+
61+
Add your HTML files to your [meta.xml](/reference/Meta.xml) through the file tag:
62+
```xml
63+
<file src="html/myAwesomeUI.html"/>
64+
```
65+
66+
### How to load local resources in local HTML files
67+
Imagine you want to load an image or play a video from your MTA resource. This is possible via a custom URI scheme named `http://mta/`.
68+
Check out the [local scheme handler](/reference/Local_Scheme_Handler) page for more information.
69+
70+
#### Example
71+
This examples shows how to play a video.
72+
**Lua**
73+
```lua
74+
-- Create a browser (local mode is also required to access local data)
75+
local webView = createBrowser(640, 480, true, true)
76+
77+
addEventHandler("onClientBrowserCreated", webView, function()
78+
-- Load HTML UI
79+
loadBrowserURL(webView, "http://mta/local/html/myVideo.html")
80+
end)
81+
```
82+
83+
**meta.xml**
84+
```xml
85+
<file src="html/myVideo.html"/>
86+
<file src="media/myVideo.webm"/>
87+
```
88+
89+
**html**
90+
```html
91+
<html>
92+
<head></head>
93+
<body>
94+
<video width="640" height="480" controls>
95+
<source src="http://mta/local/myVideo.webm" type="video/webm"/>
96+
</video>
97+
</body>
98+
</html>
99+
```
100+
101+
## Lua \<==\> Javascript communication
102+
First of all, communication between Lua and Javascript is only available in local mode due to security reasons.
103+
104+
### Lua to Javascript
105+
Lua to javascript is pretty easy as you can execute Javascript code from Lua using [executeBrowserJavascript](/reference/executeBrowserJavascript).
106+
107+
### Javascript to Lua
108+
You are able to trigger a client event via the Javascript method `triggerEvent` which is part of the static class/namespace `mta`. The syntax is as follows:
109+
```javascript
110+
mta.triggerEvent(string event, var parameter1, var parameter2, var parameter3, ...)
111+
```
112+
The source of this event is always the [browser element](/reference/browser) that triggered the event.
113+
114+
### Debugging
115+
The web development mode can be enabled as follows (type it in the client's F8 console):
116+
117+
```lua
118+
crun setDevelopmentMode(true, true)
119+
```
120+
Now, you should be able to see web errors and blocked domains/URLs in the debug window at the bottom (debugscript).
121+
122+
## Things you should keep in mind while working with CEF
123+
You should always keep in mind that some modern browser features are not available on some computers.
124+
This is for example true for WebGL.
125+
126+
Another problematic feature is Adobe Flash. Adobe Flash is enabled by default, but you should avoid using it due to the fact that plugins can be disabled in the settings on the one hand (Java is disabled completely by the way) and Flash is very restrictive on the other hand.
127+
Restrictive means it runs in a separate process uses a very old interface and offers therefore just a few ways to control it.
128+
As a consequence, you cannot control the volume of flash objects. Fortunately, HTML5 is an even better replacement and provides very good audio and video interface (http://www.w3schools.com/tags/ref_av_dom.asp) which even supports 3D sound.
129+
130+
## Advanced usage
131+
Since our CEF implementation does not do z-ordering by default, you have to provide your own z-ordering mechanism.
132+
You can find a basic implementation of such a mechanism here: https://github.com/Jusonex/mtasa_cef_tools
133+
There are also a few utility functions that allow you to integrate these classes easily into your own object-oriented UI system.
134+
135+
## Performance
136+
Creating lots of browsers does not influence MTA directly (except the fact MTA has to copy the texture data in the main/GTA thread due to technical restrictions), because one part of CEF runs in another process and the other part in a secondary thread.
137+
So if you do not want to show the browser, it is definitely the best to destroy the browser.
138+
If you cannot destroy the browser (imagine you have to save the website's state for some reason), you can save a lot of resources by disabling rendering via [setBrowserRenderingPaused](/reference/setBrowserRenderingPaused).
139+
This will stop CEF from rendering new frames/processing input and MTA from copying the texture data.
140+
141+
## Troubleshooting
142+
**google.com doesn't work (even though I requested google.com)**
143+
144+
Google redirects to a country-specific website by default. If you want to prevent Google from doing this, load the following URL: https://www.google.com/ncr
145+
146+
## 3-rd party
147+
### Typescript
148+
Typescript declaration for mta functions:
149+
150+
```typescript
151+
declare var mta: {
152+
triggerEvent(event: string): void;
153+
triggerEvent(event: string, ...any): void;
154+
};
155+
```
156+
157+
### React
158+
Example how to call react function from mta
159+
160+
1. Create a hook
161+
```typescript
162+
const useMta = () => {
163+
const dispatch = yourDispatcherHere();
164+
const w = window as any;
165+
w.MtaPrefixSomeName = () => dispatch(dispatchFunction());
166+
}
167+
export default useMta;
168+
```
169+
170+
2. Add this hook to main App component.
171+
172+
3. Call from lua
173+
```lua
174+
function callReactFunction(name, arg)
175+
local name = string.format(name, "[^a-zA-Z0-9]", "");
176+
local code;
177+
if(arg~= nil)then
178+
code = string.format("MtaPrefix%s(%q)",name, arg)
179+
else
180+
code = string.format("MtaPrefix%s()",name)
181+
end
182+
return executeBrowserJavascript(theBrowser, code)
183+
end
184+
```
185+
186+
Use of prefix let you call only mta specific functions with bare minimum of validation required.
187+
Option `%q` puts quotes around a string argument's value. Read more at https://www.gammon.com.au/scripts/doc.php?lua=string.format
188+
189+
<SeeAlsoSection seeAlsoLinks={getSeeAlsoLinksFromList([
190+
'reference:Scripting_Functions.html#Browser',
191+
'reference:Resource_Web_Access',
192+
])} currentId='' />
193+
194+
</AutoStarlightPage>

0 commit comments

Comments
 (0)