[wam][cef] Make it possible to use cef as a backend
[AGL/meta-agl-demo.git] / recipes-wam / wam / files / 0001-agl-cef-Snapshot-with-all-patches-needed-to-enable-w.patch
1 From 54da26083a7a08b73fe617b683c3f3c8c895c4a2 Mon Sep 17 00:00:00 2001
2 From: Jose Dapena Paz <jdapena@igalia.com>
3 Date: Fri, 9 Jun 2023 14:08:08 +0200
4 Subject: [PATCH] [agl][cef] Snapshot with all patches needed to enable wam-cef
5
6 ---
7  CMakeLists.txt                                |  18 +-
8  src/CMakeLists.txt                            |  58 ++-
9  src/agl-cef/CMakeLists.txt                    |  54 +++
10  src/agl-cef/plugin/CMakeLists.txt             |  59 +++
11  src/agl-cef/plugin/agl_cef_context.cc         |   4 +
12  src/agl-cef/plugin/agl_cef_context.h          |  42 ++
13  src/agl-cef/plugin/background_cef_app.cc      |  33 ++
14  src/agl-cef/plugin/background_cef_app.h       |  20 +
15  src/agl-cef/plugin/homescreen_cef_app.cc      |  25 ++
16  src/agl-cef/plugin/homescreen_cef_app.h       |  15 +
17  src/agl-cef/plugin/regular_cef_app.cc         |  11 +
18  src/agl-cef/plugin/regular_cef_app.h          |  12 +
19  src/agl-cef/plugin/web_app_factory_agl_cef.cc |  49 +++
20  src/agl-cef/plugin/web_app_factory_agl_cef.h  |  23 ++
21  src/agl-cef/web_runtime_agl_cef.cc            |  63 +++
22  src/agl-cef/web_runtime_agl_cef.h             |  11 +
23  src/agl/web_runtime_agl.cc                    |  16 +-
24  src/agl/web_runtime_agl.h                     |  20 +-
25  src/cef/cli/CMakeLists.txt                    |  17 +
26  src/cef/cli/wam_cli.cc                        | 171 ++++++++
27  src/cef/device_info_cef.cc                    | 104 +++++
28  src/cef/device_info_cef.h                     |  38 ++
29  src/cef/handlers/wam_cef_browser_handler.cc   |  31 ++
30  src/cef/handlers/wam_cef_browser_handler.h    |  23 ++
31  src/cef/handlers/wam_cef_client.cc            |  39 ++
32  src/cef/handlers/wam_cef_client.h             |  31 ++
33  src/cef/handlers/wam_cef_render_handler.cc    | 135 +++++++
34  src/cef/handlers/wam_cef_render_handler.h     |  54 +++
35  src/cef/platform_module_factory_cef.cc        |  31 ++
36  src/cef/platform_module_factory_cef.h         |  27 ++
37  src/cef/plugin/web_app_cef.cc                 | 172 ++++++++
38  src/cef/plugin/web_app_cef.h                  |  95 +++++
39  src/cef/plugin/web_page_cef.cc                |  48 +++
40  src/cef/plugin/web_page_cef.h                 |  69 ++++
41  src/cef/service/CMakeLists.txt                |  64 +++
42  src/cef/service/applauncher.proto             |  50 +++
43  src/cef/service/applauncher_client_grpc.cc    |  58 +++
44  src/cef/service/applauncher_client_grpc.h     |  24 ++
45  src/cef/service/wam_ipc.proto                 |  22 +
46  .../service/web_app_manager_client_grpc.cc    |  42 ++
47  src/cef/service/web_app_manager_client_grpc.h |  23 ++
48  .../service/web_app_manager_service_grpc.cc   | 382 ++++++++++++++++++
49  .../service/web_app_manager_service_grpc.h    |  85 ++++
50  src/core/CMakeLists.txt                       |   4 +
51  src/core/application_description.cc           |  37 ++
52  src/core/application_installation_handler.h   |  12 +
53  .../application_installation_handler_stub.cc  |   4 +
54  src/core/memory_pressure_level.h              |   6 +
55  src/core/web_app_manager.cc                   |  29 +-
56  src/core/web_app_manager.h                    |   4 +-
57  src/core/web_app_manager_service.cc           |   4 +-
58  src/core/web_app_manager_service.h            |   3 +-
59  src/core/web_page_base.h                      |   6 +-
60  src/core/web_process_manager.h                |   1 +
61  src/core/web_runtime.h                        |   3 +-
62  src/desktop/CMakeLists.txt                    | 100 +++++
63  src/desktop/README.md                         | 102 +++++
64  src/desktop/web_runtime_desktop.cc            |  28 ++
65  src/desktop/web_runtime_desktop.h             |  11 +
66  src/platform/CMakeLists.txt                   |  23 +-
67  src/platform/web_app_window.h                 |   6 +-
68  src/util/log_msg_id.h                         |   2 +
69  src/util/timer.h                              |   4 +-
70  src/wam_main.cc                               |   4 +-
71  src/webos/web_app_manager_service_luna.cc     |   2 +
72  src/webos/web_runtime_webos.cc                |   2 +-
73  src/webos/web_runtime_webos.h                 |   2 +-
74  67 files changed, 2693 insertions(+), 74 deletions(-)
75  create mode 100644 src/agl-cef/CMakeLists.txt
76  create mode 100644 src/agl-cef/plugin/CMakeLists.txt
77  create mode 100644 src/agl-cef/plugin/agl_cef_context.cc
78  create mode 100644 src/agl-cef/plugin/agl_cef_context.h
79  create mode 100644 src/agl-cef/plugin/background_cef_app.cc
80  create mode 100644 src/agl-cef/plugin/background_cef_app.h
81  create mode 100644 src/agl-cef/plugin/homescreen_cef_app.cc
82  create mode 100644 src/agl-cef/plugin/homescreen_cef_app.h
83  create mode 100644 src/agl-cef/plugin/regular_cef_app.cc
84  create mode 100644 src/agl-cef/plugin/regular_cef_app.h
85  create mode 100644 src/agl-cef/plugin/web_app_factory_agl_cef.cc
86  create mode 100644 src/agl-cef/plugin/web_app_factory_agl_cef.h
87  create mode 100644 src/agl-cef/web_runtime_agl_cef.cc
88  create mode 100644 src/agl-cef/web_runtime_agl_cef.h
89  create mode 100644 src/cef/cli/CMakeLists.txt
90  create mode 100644 src/cef/cli/wam_cli.cc
91  create mode 100644 src/cef/device_info_cef.cc
92  create mode 100644 src/cef/device_info_cef.h
93  create mode 100644 src/cef/handlers/wam_cef_browser_handler.cc
94  create mode 100644 src/cef/handlers/wam_cef_browser_handler.h
95  create mode 100644 src/cef/handlers/wam_cef_client.cc
96  create mode 100644 src/cef/handlers/wam_cef_client.h
97  create mode 100644 src/cef/handlers/wam_cef_render_handler.cc
98  create mode 100644 src/cef/handlers/wam_cef_render_handler.h
99  create mode 100644 src/cef/platform_module_factory_cef.cc
100  create mode 100644 src/cef/platform_module_factory_cef.h
101  create mode 100644 src/cef/plugin/web_app_cef.cc
102  create mode 100644 src/cef/plugin/web_app_cef.h
103  create mode 100644 src/cef/plugin/web_page_cef.cc
104  create mode 100644 src/cef/plugin/web_page_cef.h
105  create mode 100644 src/cef/service/CMakeLists.txt
106  create mode 100644 src/cef/service/applauncher.proto
107  create mode 100644 src/cef/service/applauncher_client_grpc.cc
108  create mode 100644 src/cef/service/applauncher_client_grpc.h
109  create mode 100644 src/cef/service/wam_ipc.proto
110  create mode 100644 src/cef/service/web_app_manager_client_grpc.cc
111  create mode 100644 src/cef/service/web_app_manager_client_grpc.h
112  create mode 100644 src/cef/service/web_app_manager_service_grpc.cc
113  create mode 100644 src/cef/service/web_app_manager_service_grpc.h
114  create mode 100644 src/core/application_installation_handler.h
115  create mode 100644 src/core/application_installation_handler_stub.cc
116  create mode 100644 src/core/memory_pressure_level.h
117  create mode 100644 src/desktop/CMakeLists.txt
118  create mode 100644 src/desktop/README.md
119  create mode 100644 src/desktop/web_runtime_desktop.cc
120  create mode 100644 src/desktop/web_runtime_desktop.h
121
122 diff --git a/CMakeLists.txt b/CMakeLists.txt
123 index 1e9f94f..073e326 100644
124 --- a/CMakeLists.txt
125 +++ b/CMakeLists.txt
126 @@ -18,22 +18,24 @@ cmake_minimum_required(VERSION 3.13.0)
127  
128  project(WebAppMgr VERSION 1.0.0 LANGUAGES CXX)
129  
130 -set(CMAKE_CXX_STANDARD 14)
131 +set(CMAKE_CXX_STANDARD 20)
132  set(CMAKE_CXX_STANDARD_REQUIRED ON)
133 -set(CMAKE_BUILD_TYPE Release)
134  
135  include(FindPkgConfig)
136  
137  set(OS_WEBOS FALSE)
138  set(OS_AGL FALSE)
139 -set(PLATFORM_NAME "WebOS" CACHE STRING "Target platform name (WebOS, POKY_AGL)")
140 +set(OS_DESKTOP FALSE)
141 +set(WEBENGINE_CEF TRUE)
142 +set(WEBENGINE_CBE FALSE)
143 +set(PLATFORM_NAME "Desktop" CACHE STRING "Target platform name (WebOS, POKY_AGL, Desktop)")
144  string(TOLOWER ${PLATFORM_NAME} PLATFORM)
145  if(${PLATFORM} STREQUAL "webos")
146      set(OS_WEBOS TRUE)
147  elseif(${PLATFORM} MATCHES ".*agl")
148      set(OS_AGL TRUE)
149  else()
150 -    message(FATAL_ERROR "Unsupported platform: ${PLATFORM}")
151 +    set(OS_DESKTOP TRUE)
152  endif()
153  
154  if(OS_WEBOS)
155 @@ -45,4 +47,12 @@ if(OS_WEBOS)
156      webos_build_system_bus_files(${CMAKE_SOURCE_DIR}/files/sysbus)
157  endif()
158  
159 +message(STATUS "WAM Configuration:")
160 +message(STATUS "OS_WEBOS: ${OS_WEBOS}")
161 +message(STATUS "OS_AGL: ${OS_AGL}")
162 +message(STATUS "OS_DESKTOP: ${OS_DESKTOP}")
163 +message(STATUS "WEBENGINE_CEF: ${WEBENGINE_CEF}")
164 +message(STATUS "WEBENGINE_CBE: ${WEBENGINE_CBE}")
165 +message(STATUS "PLATFORM_NAME: ${PLATFORM_NAME}")
166 +
167  add_subdirectory(src)
168 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
169 index 3cca138..173dafc 100644
170 --- a/src/CMakeLists.txt
171 +++ b/src/CMakeLists.txt
172 @@ -18,10 +18,12 @@ project(WebAppMgrExec VERSION 1.0.0 DESCRIPTION "WAM")
173  
174  set(WAM_ROOT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
175  
176 -if(NOT DEFINED CHROMIUM_SRC_DIR)
177 -    message(FATAL_ERROR "CHROMIUM_SRC_DIR was not set")
178 +if (WEBVIEW_CBE)
179 +  if(NOT DEFINED CHROMIUM_SRC_DIR)
180 +      message(FATAL_ERROR "CHROMIUM_SRC_DIR was not set")
181 +  endif()
182 +  set(CHROMIUM_LDFLAGS -lcbe)
183  endif()
184 -set(CHROMIUM_LDFLAGS -lcbe)
185  
186  find_package(PkgConfig REQUIRED)
187  find_package(Boost COMPONENTS filesystem REQUIRED)
188 @@ -39,6 +41,8 @@ elseif(OS_AGL)
189      find_package(gRPC REQUIRED)
190      find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED)
191      find_package(Threads)
192 +elseif(OS_DESKTOP)
193 +    set(DISABLE_PMLOG(true))
194  endif()
195  
196  if(DISABLE_PMLOG)
197 @@ -58,7 +62,6 @@ set(WAM_COMPILER_FLAGS -fno-rtti
198                         -Wall
199                         -fpermissive
200                         -funwind-tables
201 -                       -std=c++14
202                         -Wno-psabi
203                         -Werror
204  )
205 @@ -70,29 +73,68 @@ endif()
206  add_link_options(-Wl,--no-as-needed -Wno-psabi -rdynamic)
207  
208  add_subdirectory(core)
209 -add_subdirectory(platform)
210  
211  set(WAM_INCLUDE_DIRS
212      ${GLIB_INCLUDE_DIRS}
213      ${CMAKE_CURRENT_SOURCE_DIR}/core
214      ${CMAKE_CURRENT_SOURCE_DIR}/util
215 -    ${CMAKE_CURRENT_SOURCE_DIR}/webos
216  )
217  
218  set(WAM_LIBS
219      ${CHROMIUM_LDFLAGS}
220      ${PMLOGLIB_LDFLAGS}
221 -    WebAppMgr
222      WebAppMgrCore
223  )
224  
225 +if(WEBENGINE_CBE)
226 +    add_subdirectory(platform)
227 +    LIST(APPEND WAM_INCLUDE_DIRS
228 +        ${CMAKE_CURRENT_SOURCE_DIR}/webos
229 +    )
230 +    LIST(APPEND WAM_LIBS
231 +        WebAppMgr
232 +    )
233 +endif()
234 +
235 +if(OS_DESKTOP OR WEBENGINE_CEF)
236 +    if(NOT DEFINED CEF_ROOT)
237 +        message(FATAL_ERROR "CEF_ROOT needs to point to the binary distribution directory")
238 +    endif()
239 +
240 +    set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CEF_ROOT}/cmake")
241 +    find_package(CEF REQUIRED)
242 +    message(STATUS "CEF lib location: ${CEF_LIB_RELEASE}")
243 +    print_cef_config()
244 +
245 +    add_subdirectory(${CEF_LIBCEF_DLL_WRAPPER_PATH} libcef_dll_wrapper)
246 +    add_library(libcef_lib SHARED IMPORTED)
247 +    set_target_properties(libcef_lib PROPERTIES IMPORTED_LOCATION ${CEF_LIB_RELEASE})
248 +    target_link_libraries(libcef_dll_wrapper libcef_lib)
249 +
250 +    LIST(APPEND WAM_LIBS libcef_lib libcef_dll_wrapper)
251 +endif()
252 +
253 +if(OS_DESKTOP)
254 +    add_subdirectory(desktop)
255 +    add_subdirectory(cef/service)
256 +    add_subdirectory(cef/cli)
257 +    LIST(APPEND WAM_LIBS WebAppMgrDesktop)
258 +endif()
259 +
260  if(OS_WEBOS)
261      add_subdirectory(plugin)
262      add_subdirectory(tests)
263      add_subdirectory(testplugin)
264          LIST(APPEND WAM_LIBS ${LIBLUNAPREFS_LDFLAGS})
265  elseif(OS_AGL)
266 -    add_subdirectory(agl/plugin)
267 +    if(WEBENGINE_CEF)
268 +        add_subdirectory(agl-cef)
269 +        add_subdirectory(cef/service)
270 +        add_subdirectory(cef/cli)
271 +        LIST(APPEND WAM_LIBS WebAppMgrAGLCEF)
272 +    else()
273 +        add_subdirectory(agl/plugin)
274 +    endif()
275      LIST(APPEND WAM_INCLUDE_DIRS
276          ${Protobuf_INCLUDE_DIRS}
277          ${gRPC_INCLUDE_DIRS}
278 diff --git a/src/agl-cef/CMakeLists.txt b/src/agl-cef/CMakeLists.txt
279 new file mode 100644
280 index 0000000..8d29004
281 --- /dev/null
282 +++ b/src/agl-cef/CMakeLists.txt
283 @@ -0,0 +1,54 @@
284 +project(WebAppMgrAGLCEF VERSION 1.0.0 DESCRIPTION "Web Application Manager library")
285 +
286 +set(WAM_LIB_LIBS
287 +    ${JSONCPP_LDFLAGS}
288 +    WebAppMgrCore
289 +    WebAppMgrService
290 +    libcef_lib
291 +    libcef_dll_wrapper
292 +)
293 +
294 +set(SOURCES
295 +    web_runtime_agl_cef.cc
296 +)
297 +
298 +set(HEADERS
299 +    web_runtime_agl_cef.h
300 +)
301 +
302 +set(WAM_LIB_CEF_DIR ${WAM_ROOT_SOURCE_DIR}/cef)
303 +
304 +set(WAM_LIB_INCLUDE_DIRS
305 +    ${JSONCPP_INCLUDE_DIRS}
306 +    ${CEF_INCLUDE_PATH}
307 +)
308 +
309 +LIST(APPEND SOURCES
310 +    ${WAM_LIB_CEF_DIR}/device_info_cef.cc
311 +    ${WAM_LIB_CEF_DIR}/platform_module_factory_cef.cc
312 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_browser_handler.cc
313 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_client.cc
314 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_render_handler.cc
315 +)
316 +LIST(APPEND HEADERS
317 +    ${WAM_LIB_CEF_DIR}/device_info_cef.h
318 +    ${WAM_LIB_CEF_DIR}/platform_module_factory_cef.h
319 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_browser_handler.h
320 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_client.h
321 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_render_handler.cc
322 +)
323 +LIST(APPEND WAM_LIB_INCLUDE_DIRS
324 +    ${WAM_LIB_CEF_DIR}
325 +    ${WAM_LIB_CEF_DIR}/handlers
326 +)
327 +
328 +add_library(${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES})
329 +target_include_directories(${PROJECT_NAME} PUBLIC ${WAM_LIB_INCLUDE_DIRS})
330 +set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 1.0.0 SOVERSION 1.0)
331 +
332 +install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/webappmanager)
333 +
334 +target_link_libraries(${PROJECT_NAME} PUBLIC ${WAM_LIB_LIBS})
335 +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
336 +
337 +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/plugin)
338 diff --git a/src/agl-cef/plugin/CMakeLists.txt b/src/agl-cef/plugin/CMakeLists.txt
339 new file mode 100644
340 index 0000000..052c94e
341 --- /dev/null
342 +++ b/src/agl-cef/plugin/CMakeLists.txt
343 @@ -0,0 +1,59 @@
344 +project(webappmgr-default-plugin VERSION 1.0.0 DESCRIPTION "Default WAM plugin")
345 +
346 +set(CEF_PLUGINS_DIR ${WAM_ROOT_SOURCE_DIR}/cef/plugin)
347 +set(CEF_HANDLERS_DIR ${WAM_ROOT_SOURCE_DIR}/cef/handlers)
348 +
349 +set (SOURCES
350 +    ${CEF_HANDLERS_DIR}/wam_cef_client.cc
351 +    ${CEF_PLUGINS_DIR}/web_app_cef.cc
352 +    ${CEF_PLUGINS_DIR}/web_page_cef.cc
353 +    agl_cef_context.cc
354 +    web_app_factory_agl_cef.cc
355 +    background_cef_app.cc
356 +    homescreen_cef_app.cc
357 +    regular_cef_app.cc
358 +)
359 +set (HEADERS
360 +    ${CEF_HANDLERS_DIR}/wam_cef_client.h
361 +    ${CEF_PLUGINS_DIR}/web_app_cef.h
362 +    ${CEF_PLUGINS_DIR}/web_page_cef.h
363 +    agl_cef_context.h
364 +    web_app_factory_agl_cef.h
365 +    background_cef_app.h
366 +    homescreen_cef_app.h
367 +    regular_cef_app.h
368 +)
369 +set (WAM_PLUGIN_INCLUDE_DIRS
370 +    ${CEF_HANDLERS_DIR}
371 +    ${CEF_PLUGINS_DIR}
372 +    ${WAM_ROOT_SOURCE_DIR}
373 +    ${WAM_ROOT_SOURCE_DIR}/core
374 +    ${WAM_ROOT_SOURCE_DIR}/platform
375 +    ${WAM_ROOT_SOURCE_DIR}/platform/webengine
376 +    ${WAM_ROOT_SOURCE_DIR}/util
377 +    ${CEF_INCLUDE_PATH}
378 +)
379 +set(WAM_PLUGIN_LIBS
380 +    WebAppMgrService
381 +    WebAppMgrService-grpc
382 +    libcef_lib
383 +    libcef_dll_wrapper
384 +)
385 +
386 +if (OS_DESKTOP)
387 +    LIST(APPEND WAM_PLUGIN_LIBS
388 +        WebAppMgrDesktop
389 +    )
390 +else()
391 +    LIST(APPEND WAM_PLUGIN_LIBS
392 +        WebAppMgrAGLCEF
393 +    )
394 +endif()
395 +
396 +add_library(${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES})
397 +add_dependencies(${PROJECT_NAME} libcef_lib libcef_dll_wrapper)
398 +
399 +target_include_directories(${PROJECT_NAME} PRIVATE ${WAM_PLUGIN_INCLUDE_DIRS})
400 +target_link_libraries(${PROJECT_NAME} PRIVATE ${WAM_PLUGIN_LIBS})
401 +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR}/webappmanager/plugins)
402 +install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/webappmanager)
403 diff --git a/src/agl-cef/plugin/agl_cef_context.cc b/src/agl-cef/plugin/agl_cef_context.cc
404 new file mode 100644
405 index 0000000..8c1a390
406 --- /dev/null
407 +++ b/src/agl-cef/plugin/agl_cef_context.cc
408 @@ -0,0 +1,4 @@
409 +#include "agl_cef_context.h"
410 +
411 +AglCefContext* AglCefContext::instance_ = nullptr;
412 +
413 diff --git a/src/agl-cef/plugin/agl_cef_context.h b/src/agl-cef/plugin/agl_cef_context.h
414 new file mode 100644
415 index 0000000..a1e698f
416 --- /dev/null
417 +++ b/src/agl-cef/plugin/agl_cef_context.h
418 @@ -0,0 +1,42 @@
419 +#ifndef AGL_CEF_PLUGIN_AGL_CEF_CONTEXT_H
420 +#define AGL_CEF_PLUGIN_AGL_CEF_CONTEXT_H
421 +
422 +#include <memory>
423 +
424 +class AglCefContext {
425 + public:
426 +  AglCefContext(const AglCefContext&) = delete;
427 +  AglCefContext& operator=(const AglCefContext&) = delete;
428 +
429 +  static AglCefContext* get() {
430 +      if (!instance_) {
431 +          instance_ = new AglCefContext();
432 +      }
433 +      return instance_;
434 +  }
435 +
436 +  uint32_t activation_area_width() const { return activation_area_width_; }
437 +  void set_activation_area_width(uint32_t activation_area_width) {
438 +      activation_area_width_ = activation_area_width;
439 +  }
440 +
441 +  uint32_t activation_area_height() const { return activation_area_height_; }
442 +  void set_activation_area_height(uint32_t activation_area_height) {
443 +      activation_area_height_ = activation_area_height;
444 +  }
445 +
446 +  uint32_t panel_offset() const { return panel_offset_; }
447 +  void set_panel_offset(uint32_t panel_offset) {
448 +      panel_offset_ = panel_offset;
449 +  }
450 +
451 + private:
452 +  AglCefContext() = default;
453 +
454 +  static AglCefContext* instance_;
455 +  uint32_t activation_area_width_ = 0;
456 +  uint32_t activation_area_height_ = 0;
457 +  uint32_t panel_offset_ = 0;
458 +};
459 +
460 +#endif // AGL_CEF_PLUGIN_AGL_CEF_CONTEXT_H
461 diff --git a/src/agl-cef/plugin/background_cef_app.cc b/src/agl-cef/plugin/background_cef_app.cc
462 new file mode 100644
463 index 0000000..c406641
464 --- /dev/null
465 +++ b/src/agl-cef/plugin/background_cef_app.cc
466 @@ -0,0 +1,33 @@
467 +#include "background_cef_app.h"
468 +
469 +BackgroundCefApp::BackgroundCefApp(std::shared_ptr<ApplicationDescription> app_desc)
470 +  : WebAppCEF(app_desc) {
471 +  CefRect display_bounds = GetDisplayBounds();
472 +  width_override_ = display_bounds.width;
473 +  height_override_ = display_bounds.height;
474 +}
475 +
476 +BackgroundCefApp::~BackgroundCefApp() {}
477 +
478 +void BackgroundCefApp::Init(int width,
479 +                            int height,
480 +                            AglShellSurfaceType surface_type,
481 +                            AglShellPanelEdge panel_type) {
482 +  if (!IsReady()) {
483 +    return;
484 +  }
485 +
486 +  /*
487 +  // TODO: change when in portrait mode
488 +  window_->SetupActivationArea(AglCefContext::get()->panel_offset(),
489 +                               0,
490 +                               AglCefContext::get()->activation_area_width(),
491 +                               AglCefContext::get()->activation_area_height());
492 +                               */
493 +
494 +  WebAppCEF::Init(width, height, surface_type, panel_type);
495 +}
496 +
497 +bool BackgroundCefApp::IsReady() const {
498 +  return window_ != nullptr;
499 +}
500 diff --git a/src/agl-cef/plugin/background_cef_app.h b/src/agl-cef/plugin/background_cef_app.h
501 new file mode 100644
502 index 0000000..6681b5d
503 --- /dev/null
504 +++ b/src/agl-cef/plugin/background_cef_app.h
505 @@ -0,0 +1,20 @@
506 +#ifndef AGL_CEF_PLUGIN_BACKGROUND_CEF_APP_H
507 +#define AGL_CEF_PLUGIN_BACKGROUND_CEF_APP_H
508 +
509 +#include "agl_cef_context.h"
510 +#include "web_app_cef.h"
511 +
512 +class BackgroundCefApp : public WebAppCEF {
513 + public:
514 +  BackgroundCefApp(std::shared_ptr<ApplicationDescription> app_desc);
515 +  ~BackgroundCefApp();
516 +
517 +  void Init(int width,
518 +            int height,
519 +            AglShellSurfaceType surface_type,
520 +            AglShellPanelEdge panel_type) override;
521 +
522 +  bool IsReady() const override;
523 +};
524 +
525 +#endif // AGL_CEF_PLUGIN_BACKGROUND_CEF_APP_H
526 diff --git a/src/agl-cef/plugin/homescreen_cef_app.cc b/src/agl-cef/plugin/homescreen_cef_app.cc
527 new file mode 100644
528 index 0000000..cc6af64
529 --- /dev/null
530 +++ b/src/agl-cef/plugin/homescreen_cef_app.cc
531 @@ -0,0 +1,25 @@
532 +#include "homescreen_cef_app.h"
533 +
534 +#include "agl_cef_context.h"
535 +
536 +HomescreenCefApp::HomescreenCefApp(std::shared_ptr<ApplicationDescription> app_desc)
537 +  : WebAppCEF(app_desc) {
538 +  CefRect display_bounds = GetDisplayBounds();
539 +  uint32_t panel_offset = app_desc->WidthOverride(); // TODO: height when in portrait mode
540 +  uint32_t activation_width = display_bounds.width - panel_offset - 1;
541 +  uint32_t activation_height = display_bounds.height;
542 +
543 +  // TODO: change when in portrait mode
544 +  width_override_ = panel_offset;
545 +  height_override_ = activation_height;
546 +
547 +  AglCefContext::get()->set_panel_offset(panel_offset);
548 +  AglCefContext::get()->set_activation_area_width(activation_width);
549 +  AglCefContext::get()->set_activation_area_height(activation_height);
550 +}
551 +
552 +HomescreenCefApp::~HomescreenCefApp() {}
553 +
554 +bool HomescreenCefApp::IsReady() const {
555 +  return window_ && window_->IsSurfaceConfigured();
556 +}
557 diff --git a/src/agl-cef/plugin/homescreen_cef_app.h b/src/agl-cef/plugin/homescreen_cef_app.h
558 new file mode 100644
559 index 0000000..c4f86ab
560 --- /dev/null
561 +++ b/src/agl-cef/plugin/homescreen_cef_app.h
562 @@ -0,0 +1,15 @@
563 +#ifndef AGL_CEF_PLUGIN_HOMESCREEN_CEF_APP_H
564 +#define AGL_CEF_PLUGIN_HOMESCREEN_CEF_APP_H
565 +
566 +#include "web_app_cef.h"
567 +
568 +class HomescreenCefApp : public WebAppCEF {
569 + public:
570 +  HomescreenCefApp(std::shared_ptr<ApplicationDescription> app_desc);
571 +  ~HomescreenCefApp();
572 +
573 + protected:
574 +  bool IsReady() const override;
575 +};
576 +
577 +#endif // AGL_CEF_PLUGIN_BACKGROUND_CEF_APP_H
578 diff --git a/src/agl-cef/plugin/regular_cef_app.cc b/src/agl-cef/plugin/regular_cef_app.cc
579 new file mode 100644
580 index 0000000..a882314
581 --- /dev/null
582 +++ b/src/agl-cef/plugin/regular_cef_app.cc
583 @@ -0,0 +1,11 @@
584 +#include "regular_cef_app.h"
585 +
586 +#include "agl_cef_context.h"
587 +
588 +RegularCefApp::RegularCefApp(std::shared_ptr<ApplicationDescription> app_desc)
589 +  : WebAppCEF(app_desc) {
590 +  width_override_ = AglCefContext::get()->activation_area_width();
591 +  height_override_ = AglCefContext::get()->activation_area_height();
592 +}
593 +
594 +RegularCefApp::~RegularCefApp() {}
595 diff --git a/src/agl-cef/plugin/regular_cef_app.h b/src/agl-cef/plugin/regular_cef_app.h
596 new file mode 100644
597 index 0000000..ed4b34d
598 --- /dev/null
599 +++ b/src/agl-cef/plugin/regular_cef_app.h
600 @@ -0,0 +1,12 @@
601 +#ifndef AGL_CEF_PLUGIN_REGULAR_CEF_APP_H
602 +#define AGL_CEF_PLUGIN_REGULAR_CEF_APP_H
603 +
604 +#include "web_app_cef.h"
605 +
606 +class RegularCefApp : public WebAppCEF {
607 + public:
608 +  RegularCefApp(std::shared_ptr<ApplicationDescription> app_desc);
609 +  ~RegularCefApp();
610 +};
611 +
612 +#endif // AGL_CEF_PLUGIN_REGULAR_CEF_APP_H
613 diff --git a/src/agl-cef/plugin/web_app_factory_agl_cef.cc b/src/agl-cef/plugin/web_app_factory_agl_cef.cc
614 new file mode 100644
615 index 0000000..8ca2ba8
616 --- /dev/null
617 +++ b/src/agl-cef/plugin/web_app_factory_agl_cef.cc
618 @@ -0,0 +1,49 @@
619 +#include "web_app_factory_agl_cef.h"
620 +
621 +#include "application_description.h"
622 +#include "plugin_interface.h"
623 +
624 +#include "background_cef_app.h"
625 +#include "homescreen_cef_app.h"
626 +#include "regular_cef_app.h"
627 +
628 +#include "web_page_cef.h"
629 +
630 +#include "wam_cef_client.h"
631 +
632 +const char* kPluginApplicationType = "default";
633 +
634 +WebAppFactoryInterface* CreateInstance() {
635 +  return new WebAppFactoryCEF();
636 +}
637 +
638 +void DeleteInstance(WebAppFactoryInterface* interface) {
639 +  delete interface;
640 +}
641 +
642 +WebAppBase* WebAppFactoryCEF::CreateWebApp(
643 +    const std::string&,
644 +    std::shared_ptr<ApplicationDescription> app_desc) {
645 +  std::string app_id = app_desc->Id();
646 +
647 +  if (app_id == "homescreen") {
648 +      return new HomescreenCefApp(app_desc);
649 +  } else if (app_id == "webapps-html5-background") {
650 +      return new BackgroundCefApp(app_desc);
651 +  }
652 +  return new RegularCefApp(app_desc);
653 +}
654 +
655 +WebAppBase* WebAppFactoryCEF::CreateWebApp(
656 +    const std::string& win_type,
657 +    WebPageBase*,
658 +    std::shared_ptr<ApplicationDescription> desc) {
659 +  return CreateWebApp(win_type, desc);
660 +}
661 +
662 +WebPageBase* WebAppFactoryCEF::CreateWebPage(
663 +    const wam::Url& url,
664 +    std::shared_ptr<ApplicationDescription> app_desc,
665 +    const std::string&) {
666 +  return new WebPageCEF(app_desc, url.ToString());
667 +}
668 diff --git a/src/agl-cef/plugin/web_app_factory_agl_cef.h b/src/agl-cef/plugin/web_app_factory_agl_cef.h
669 new file mode 100644
670 index 0000000..eb4b7ba
671 --- /dev/null
672 +++ b/src/agl-cef/plugin/web_app_factory_agl_cef.h
673 @@ -0,0 +1,23 @@
674 +#ifndef AGL_CEF_PLUGIN_WEB_APP_FACTORY_CEF_H
675 +#define AGL_CEF_PLUGIN_WEB_APP_FACTORY_CEF_H
676 +
677 +#include <memory>
678 +#include <string>
679 +
680 +#include "web_app_factory_interface.h"
681 +
682 +class WebAppFactoryCEF : public WebAppFactoryInterface {
683 + public:
684 +  WebAppBase* CreateWebApp(
685 +      const std::string& win_type,
686 +      std::shared_ptr<ApplicationDescription> desc = 0) override;
687 +  WebAppBase* CreateWebApp(
688 +      const std::string& win_type,
689 +      WebPageBase* page,
690 +      std::shared_ptr<ApplicationDescription> desc = 0) override;
691 +  WebPageBase* CreateWebPage(const wam::Url& url,
692 +                             std::shared_ptr<ApplicationDescription> desc,
693 +                             const std::string& launchParams = "") override;
694 +};
695 +
696 +#endif  // AGL_CEF_PLUGIN_WEB_APP_FACTORY_CEF_H
697 diff --git a/src/agl-cef/web_runtime_agl_cef.cc b/src/agl-cef/web_runtime_agl_cef.cc
698 new file mode 100644
699 index 0000000..9bc1bd6
700 --- /dev/null
701 +++ b/src/agl-cef/web_runtime_agl_cef.cc
702 @@ -0,0 +1,63 @@
703 +#include "web_runtime_agl_cef.h"
704 +
705 +#include "include/cef_base.h"
706 +#include "include/cef_origin_whitelist.h"
707 +
708 +#include "wam_cef_browser_handler.h"
709 +#include "wam_cef_render_handler.h"
710 +
711 +const char kProcessType[] = "type";
712 +const char kRendererProcess[] = "renderer";
713 +const char kZygoteProcess[] = "zygote";
714 +
715 +class WamCefUtilityHandler : public CefApp {
716 + public:
717 +  WamCefUtilityHandler () {}
718 +
719 + private:
720 +  IMPLEMENT_REFCOUNTING(WamCefUtilityHandler);
721 +  DISALLOW_COPY_AND_ASSIGN(WamCefUtilityHandler);
722 +};
723 +
724 +int WebRuntimeCEF::Run(int argc, char** argv) {
725 +  CefMainArgs main_args(argc, argv);
726 +
727 +  CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
728 +  command_line->InitFromArgv(main_args.argc, main_args.argv);
729 +
730 +  std::string app_id = command_line->GetSwitchValue("appid");
731 +  if (app_id.empty()) {
732 +    app_id = "WebAppMgr";
733 +  }
734 +
735 +  CefRefPtr<CefApp> app;
736 +  if (!command_line->HasSwitch(kProcessType)) {
737 +    app = new WamCefBrowserHandler();
738 +  } else {
739 +    const std::string& process_type = command_line->GetSwitchValue(kProcessType);
740 +    if (process_type == kRendererProcess || process_type == kZygoteProcess) {
741 +      app = new WamCefRenderHandler();
742 +    } else {
743 +      app = new WamCefUtilityHandler();
744 +    }
745 +  }
746 +
747 +  auto exit_code = CefExecuteProcess(main_args, app.get(), nullptr);
748 +  if (exit_code >= 0) {
749 +    return exit_code;
750 +  }
751 +
752 +  CefSettings settings;
753 +  settings.remote_debugging_port = 9998;
754 +  CefInitialize(main_args, settings, app.get(), nullptr);
755 +
756 +  CefRunMessageLoop();
757 +
758 +  CefShutdown();
759 +
760 +  return 0;
761 +}
762 +
763 +std::unique_ptr<WebRuntime> WebRuntime::Create() {
764 +  return std::make_unique<WebRuntimeCEF>();
765 +}
766 diff --git a/src/agl-cef/web_runtime_agl_cef.h b/src/agl-cef/web_runtime_agl_cef.h
767 new file mode 100644
768 index 0000000..049e554
769 --- /dev/null
770 +++ b/src/agl-cef/web_runtime_agl_cef.h
771 @@ -0,0 +1,11 @@
772 +#ifndef AGL_CEF_WEB_RUNTIME_AGL_CEF_H_
773 +#define AGL_CEF_WEB_RUNTIME_AGL_CEF_H_
774 +
775 +#include "web_runtime.h"
776 +
777 +class WebRuntimeCEF : public WebRuntime {
778 + public:
779 +  int Run(int argc, char** argv) override;
780 +};
781 +
782 +#endif  // AGL_CEF_WEB_RUNTIME_CEF_H_
783 diff --git a/src/agl/web_runtime_agl.cc b/src/agl/web_runtime_agl.cc
784 index ce8525b..c791c70 100644
785 --- a/src/agl/web_runtime_agl.cc
786 +++ b/src/agl/web_runtime_agl.cc
787 @@ -128,7 +128,7 @@ void SingleBrowserProcessWebAppLauncher::Launch(
788  }
789  
790  int SingleBrowserProcessWebAppLauncher::Loop(int argc,
791 -                                             const char** argv,
792 +                                             char** argv,
793                                               volatile sig_atomic_t& e_flag) {
794    AGLMainDelegateWAM delegate;
795    webos::WebOSMain webOSMain(&delegate);
796 @@ -154,7 +154,7 @@ void SharedBrowserProcessWebAppLauncher::Launch(
797  }
798  
799  int SharedBrowserProcessWebAppLauncher::Loop(int argc,
800 -                                             const char** argv,
801 +                                             char** argv,
802                                               volatile sig_atomic_t& e_flag) {
803    // TODO: wait for a pid
804    while (e_flag)
805 @@ -173,7 +173,7 @@ static void AglShellActivateApp(const std::string& app_id) {
806    WebAppManagerServiceAGL::Instance()->SendEvent(kActivateEvent, app_id);
807  }
808  
809 -int WebAppLauncherRuntime::Run(int argc, const char** argv) {
810 +int WebAppLauncherRuntime::Run(int argc, char** argv) {
811    bool is_wait_host_service = IsWaitForHostService();
812    std::string app_id = IsActivateApp(Args::Instance());
813  
814 @@ -334,7 +334,7 @@ bool WebAppLauncherRuntime::ParseJsonConfig(const char* path_to_config) {
815    return true;
816  }
817  
818 -int SharedBrowserProcessRuntime::Run(int argc, const char** argv) {
819 +int SharedBrowserProcessRuntime::Run(int argc, char** argv) {
820    if (WebAppManagerServiceAGL::Instance()->InitializeAsHostService()) {
821      AGLMainDelegateWAM delegate;
822      webos::WebOSMain webOSMain(&delegate);
823 @@ -347,7 +347,7 @@ int SharedBrowserProcessRuntime::Run(int argc, const char** argv) {
824    }
825  }
826  
827 -int RenderProcessRuntime::Run(int argc, const char** argv) {
828 +int RenderProcessRuntime::Run(int argc, char** argv) {
829    AGLMainDelegateWAM delegate;
830    webos::WebOSMain webOSMain(&delegate);
831    return webOSMain.Run(argc, argv);
832 @@ -372,7 +372,7 @@ static void print_help(void) {
833    exit(EXIT_FAILURE);
834  }
835  
836 -void Args::parse_args(int argc, const char** argv) {
837 +void Args::parse_args(int argc, char** argv) {
838    int c;
839    int option_index;
840    opterr = 0;
841 @@ -427,7 +427,7 @@ void Args::parse_args(int argc, const char** argv) {
842    }
843  }
844  
845 -void Args::copy_cmdline(int argc, const char** argv) {
846 +void Args::copy_cmdline(int argc, char** argv) {
847    new_argc = argc;
848    new_argv = static_cast<char**>(calloc(new_argc + 1, sizeof(*new_argv)));
849  
850 @@ -446,7 +446,7 @@ void Args::clear_cmdline(void) {
851    free(new_argv);
852  }
853  
854 -int WebRuntimeAGL::Run(int argc, const char** argv) {
855 +int WebRuntimeAGL::Run(int argc, char** argv) {
856    int ret;
857    Args::Instance()->parse_args(argc, argv);
858  
859 diff --git a/src/agl/web_runtime_agl.h b/src/agl/web_runtime_agl.h
860 index ad045c2..14bc0ed 100644
861 --- a/src/agl/web_runtime_agl.h
862 +++ b/src/agl/web_runtime_agl.h
863 @@ -39,7 +39,7 @@ class Args {
864      static Args* args = new Args();
865      return args;
866    }
867 -  void parse_args(int argc, const char** argv);
868 +  void parse_args(int argc, char** argv);
869  
870    inline void set_flag(unsigned int flag) { flags |= flag; }
871  
872 @@ -56,7 +56,7 @@ class Args {
873  
874   private:
875    uint32_t flags = FLAG_NONE;
876 -  void copy_cmdline(int argc, const char** argv);
877 +  void copy_cmdline(int argc, char** argv);
878    char** new_argv;
879    int new_argc;
880  };
881 @@ -69,9 +69,7 @@ class Launcher {
882                        AglShellPanelEdge panel_edge,
883                        int width,
884                        int height) = 0;
885 -  virtual int Loop(int argc,
886 -                   const char** argv,
887 -                   volatile sig_atomic_t& e_flag) = 0;
888 +  virtual int Loop(int argc, char** argv, volatile sig_atomic_t& e_flag) = 0;
889  };
890  
891  class SharedBrowserProcessWebAppLauncher : public Launcher {
892 @@ -82,7 +80,7 @@ class SharedBrowserProcessWebAppLauncher : public Launcher {
893                AglShellPanelEdge panel_edge,
894                int width,
895                int height) override;
896 -  int Loop(int argc, const char** argv, volatile sig_atomic_t& e_flag) override;
897 +  int Loop(int argc, char** argv, volatile sig_atomic_t& e_flag) override;
898  };
899  
900  class SingleBrowserProcessWebAppLauncher : public Launcher {
901 @@ -93,12 +91,12 @@ class SingleBrowserProcessWebAppLauncher : public Launcher {
902                AglShellPanelEdge panel_edge,
903                int width,
904                int height) override;
905 -  int Loop(int argc, const char** argv, volatile sig_atomic_t& e_flag) override;
906 +  int Loop(int argc, char** argv, volatile sig_atomic_t& e_flag) override;
907  };
908  
909  class WebAppLauncherRuntime : public WebRuntime {
910   public:
911 -  int Run(int argc, const char** argv) override;
912 +  int Run(int argc, char** argv) override;
913  
914   private:
915    bool Init(Args* args);
916 @@ -127,17 +125,17 @@ class WebAppLauncherRuntime : public WebRuntime {
917  
918  class SharedBrowserProcessRuntime : public WebRuntime {
919   public:
920 -  int Run(int argc, const char** argv) override;
921 +  int Run(int argc, char** argv) override;
922  };
923  
924  class RenderProcessRuntime : public WebRuntime {
925   public:
926 -  int Run(int argc, const char** argv) override;
927 +  int Run(int argc, char** argv) override;
928  };
929  
930  class WebRuntimeAGL : public WebRuntime {
931   public:
932 -  int Run(int argc, const char** argv) override;
933 +  int Run(int argc, char** argv) override;
934  
935   private:
936    WebRuntime* runtime_;
937 diff --git a/src/cef/cli/CMakeLists.txt b/src/cef/cli/CMakeLists.txt
938 new file mode 100644
939 index 0000000..1b5f04a
940 --- /dev/null
941 +++ b/src/cef/cli/CMakeLists.txt
942 @@ -0,0 +1,17 @@
943 +project(WebAppMgrCli VERSION 1.0.0 DESCRIPTION "Web Application Manager cli helper")
944 +
945 +set(CLI_EXE ${PROJECT_NAME})
946 +set(CLI_EXE_INCLUDE_DIRS
947 +    ${WAM_ROOT_SOURCE_DIR}/util
948 +)
949 +
950 +set(CLI_EXE_LIBS
951 +    WebAppMgrCore
952 +    WebAppMgrService
953 +    WebAppMgrService-grpc
954 +)
955 +
956 +add_executable(${CLI_EXE} wam_cli.cc)
957 +target_include_directories(${CLI_EXE} PUBLIC ${CLI_EXE_INCLUDE_DIRS})
958 +target_link_libraries(${CLI_EXE} PUBLIC ${CLI_EXE_LIBS})
959 +install(TARGETS ${CLI_EXE} DESTINATION ${CMAKE_INSTALL_BINDIR})
960 diff --git a/src/cef/cli/wam_cli.cc b/src/cef/cli/wam_cli.cc
961 new file mode 100644
962 index 0000000..4775ce4
963 --- /dev/null
964 +++ b/src/cef/cli/wam_cli.cc
965 @@ -0,0 +1,171 @@
966 +// Copyright (c) 2018-2022 LG Electronics, Inc.
967 +//
968 +// Licensed under the Apache License, Version 2.0 (the "License");
969 +// you may not use this file except in compliance with the License.
970 +// You may obtain a copy of the License at
971 +//
972 +// http://www.apache.org/licenses/LICENSE-2.0
973 +//
974 +// Unless required by applicable law or agreed to in writing, software
975 +// distributed under the License is distributed on an "AS IS" BASIS,
976 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
977 +// See the License for the specific language governing permissions and
978 +// limitations under the License.
979 +//
980 +// SPDX-License-Identifier: Apache-2.0
981 +
982 +#include <getopt.h>
983 +#include <optional>
984 +
985 +#include "web_app_manager_client_grpc.h"
986 +
987 +#include "log_manager.h"
988 +
989 +class Args {
990 + public:
991 +  enum flags {
992 +    FLAG_NONE = 0,
993 +    FLAG_APP_TYPE = 1 << 0,
994 +    FLAG_ACTIVATE_APP = 1 << 1,
995 +    FLAG_HTTP_LINK = 1 << 2,
996 +    FLAG_APP_ID = 1 << 3,
997 +    FLAG_APP_DIR = 1 << 4,
998 +  };
999 +
1000 +  static Args* Instance() {
1001 +    static Args* args = new Args();
1002 +    return args;
1003 +  }
1004 +  void PrintHelp(void) {
1005 +    fprintf(stderr, "WAM: Web Application Manager\n");
1006 +    fprintf(stderr,
1007 +            "\t[--activate_app=appid] -- activate application. Interrnal "
1008 +            "usage.\n\tNot needing for starting applications.\n");
1009 +    fprintf(stderr,
1010 +            "\t[--appid=appid] name of an application id.\n\tRequired if "
1011 +            "starting a "
1012 +            "web application.\n");
1013 +    fprintf(
1014 +        stderr,
1015 +        "\t[--app-install-dir=/path/to/root_index] installation path for web "
1016 +        "application.\n\tRequired if starting a web application.\n");
1017 +    fprintf(stderr, "\t-h -- this help message \n");
1018 +    exit(EXIT_FAILURE);
1019 +  }
1020 +
1021 +  void ParseArgs(int argc, char** argv) {
1022 +    int c;
1023 +    int option_index;
1024 +    opterr = 0;
1025 +
1026 +    CopyCmdLine(argc, argv);
1027 +
1028 +    struct option long_opts[] = {{"help", no_argument, 0, 'h'},
1029 +                                 {"activate-app", required_argument, 0, 'x'},
1030 +                                 {"appid", required_argument, 0, 'a'},
1031 +                                 {"app-install-dir", required_argument, 0, 'd'},
1032 +                                 {0, 0, 0, 0}};
1033 +
1034 +    while ((c = getopt_long(new_argc, new_argv, "ht:a:i:d:", long_opts,
1035 +                            &option_index)) != -1) {
1036 +      switch (c) {
1037 +        case 'h':
1038 +          PrintHelp();
1039 +          break;
1040 +        case 'x':
1041 +          activate_app_id_ = optarg;
1042 +          break;
1043 +        case 'a':
1044 +          app_id_ = optarg;
1045 +          break;
1046 +        case 'd':
1047 +          app_dir_ = optarg;
1048 +          break;
1049 +        default:
1050 +          break;
1051 +      }
1052 +    }
1053 +
1054 +    if (optind < new_argc) {
1055 +      // check for 'http://'
1056 +      int p = optind;
1057 +      while (p < new_argc) {
1058 +        if (!strcmp(new_argv[p], "http://")) {
1059 +          http_link_ = new_argv[p];
1060 +          break;
1061 +        }
1062 +        p++;
1063 +      }
1064 +    }
1065 +  }
1066 +
1067 +  void ClearCmdLine() {
1068 +    for (int i = 0; i < new_argc; i++)
1069 +      free(new_argv[i]);
1070 +    free(new_argv);
1071 +  }
1072 +
1073 +  std::string GetAppId() const {
1074 +    return app_id_.has_value() ? *app_id_ : std::string();
1075 +  }
1076 +
1077 +  std::string GetAppUri() const {
1078 +    if (http_link_.has_value())
1079 +      return *http_link_;
1080 +    else if (app_dir_.has_value())
1081 +      return *app_dir_;
1082 +    return std::string();
1083 +  }
1084 +
1085 +  bool HasActivateAppId() const { return activate_app_id_.has_value(); }
1086 +  std::string GetActivateAppId() const {
1087 +    return activate_app_id_.has_value() ? *activate_app_id_ : std::string();
1088 +  }
1089 +
1090 + private:
1091 +  void CopyCmdLine(int argc, char** argv) {
1092 +    new_argc = argc;
1093 +    new_argv = static_cast<char**>(calloc(new_argc + 1, sizeof(*new_argv)));
1094 +
1095 +    for (int i = 0; i < new_argc; i++) {
1096 +      size_t len = strlen(argv[i]) + 1;
1097 +      new_argv[i] = static_cast<char*>(calloc(len, sizeof(char)));
1098 +      memcpy(new_argv[i], argv[i], len);
1099 +    }
1100 +
1101 +    new_argv[argc] = nullptr;
1102 +  }
1103 +  char** new_argv;
1104 +  int new_argc;
1105 +
1106 +  std::optional<std::string> activate_app_id_;
1107 +  std::optional<std::string> http_link_;
1108 +  std::optional<std::string> app_id_;
1109 +  std::optional<std::string> app_dir_;
1110 +};
1111 +
1112 +WebAppManagerClientGRPC* GetGrpcClient() {
1113 +  static std::unique_ptr<WebAppManagerClientGRPC> grpc_client;
1114 +  if (!grpc_client) {
1115 +    grpc_client = std::make_unique<WebAppManagerClientGRPC>();
1116 +  }
1117 +  return grpc_client.get();
1118 +}
1119 +
1120 +int main(int argc, char** argv) {
1121 +  auto* args = Args::Instance();
1122 +  args->ParseArgs(argc, argv);
1123 +
1124 +  // TODO: handle completed grpc calls
1125 +  // and get the correct ok() result
1126 +  if (args->HasActivateAppId()) {
1127 +    GetGrpcClient()->Activate(args->GetActivateAppId());
1128 +  } else {
1129 +    WebAppManagerClientGRPC::LaunchParams params;
1130 +    params.app_id = args->GetAppId();
1131 +    params.uri = args->GetAppUri();
1132 +    GetGrpcClient()->Launch(params);
1133 +  }
1134 +
1135 +  return 0;
1136 +}
1137 diff --git a/src/cef/device_info_cef.cc b/src/cef/device_info_cef.cc
1138 new file mode 100644
1139 index 0000000..f5fd681
1140 --- /dev/null
1141 +++ b/src/cef/device_info_cef.cc
1142 @@ -0,0 +1,104 @@
1143 +#include "device_info_cef.h"
1144 +
1145 +#include <string>
1146 +
1147 +#include <glib.h>
1148 +#include <json/value.h>
1149 +
1150 +#include "log_manager.h"
1151 +#include "utils.h"
1152 +
1153 +DeviceInfoCEF::DeviceInfoCEF() = default;
1154 +
1155 +void DeviceInfoCEF::Initialize() {
1156 +  const std::string& json_string =
1157 +      util::ReadFile("/var/luna/preferences/localeInfo");
1158 +  if (json_string.empty()) {
1159 +    return;
1160 +  }
1161 +
1162 +  Json::Value locale_json = util::StringToJson(json_string);
1163 +  if (!locale_json.isObject() || locale_json.empty() ||
1164 +      !locale_json["localeInfo"].isObject() ||
1165 +      !locale_json["localeInfo"]["locales"].isObject() ||
1166 +      !locale_json["localeInfo"]["locales"]["UI"].isString() ||
1167 +      !locale_json["country"].isString() ||
1168 +      !locale_json["smartServiceCountryCode3"].isString()) {
1169 +    LOG_ERROR(MSGID_LOCALEINFO_READ_FAIL, 1,
1170 +              PMLOGKS("CONTENT", json_string.c_str()), "");
1171 +    return;
1172 +  }
1173 +
1174 +  Json::Value locale_info = locale_json["localeInfo"];
1175 +
1176 +  std::string language(locale_info["locales"]["UI"].asString());
1177 +  std::string localcountry(locale_json["country"].asString());
1178 +  std::string smartservicecountry(
1179 +      locale_json["smartServiceCountryCode3"].asString());
1180 +
1181 +  SetSystemLanguage(language.c_str());
1182 +  SetDeviceInfo("LocalCountry", localcountry.c_str());
1183 +  SetDeviceInfo("SmartServiceCountry", smartservicecountry.c_str());
1184 +}
1185 +
1186 +void DeviceInfoCEF::InitDisplayInfo() {
1187 +  // Display information
1188 +  // --------------------------------------------------------
1189 +  float screen_density_ = 1.0f;
1190 +  int hardware_screen_width = 0;
1191 +  int hardware_screen_height = 0;
1192 +
1193 +  std::string hardware_screen_width_str;
1194 +  std::string hardware_screen_height_str;
1195 +  if (GetDeviceInfo("HardwareScreenWidth", hardware_screen_width_str) &&
1196 +      GetDeviceInfo("HardwareScreenHeight", hardware_screen_height_str)) {
1197 +    hardware_screen_width =
1198 +        util::StrToIntWithDefault(hardware_screen_width_str, 0);
1199 +    hardware_screen_height =
1200 +        util::StrToIntWithDefault(hardware_screen_height_str, 0);
1201 +  } else {
1202 +    GetDisplayWidth(hardware_screen_width);
1203 +    GetDisplayHeight(hardware_screen_height);
1204 +  }
1205 +
1206 +  screen_width_ = static_cast<int>(hardware_screen_width / screen_density_);
1207 +  screen_height_ = static_cast<int>(hardware_screen_height / screen_density_);
1208 +}
1209 +
1210 +void DeviceInfoCEF::InitPlatformInfo() {
1211 +  // normally like this info
1212 +  /*
1213 +     "modelName": "WEBOS1",
1214 +     "platformVersion": "00.00.00",
1215 +     "platformVersionDot": 00,
1216 +     "platformVersionMajor_pos": 00,
1217 +     "platformVersionMinor": 00,
1218 +  */
1219 +
1220 +  std::string value;
1221 +  if (GetDeviceInfo("ModelName", value))
1222 +    model_name_ = value;
1223 +  if (GetDeviceInfo("FirmwareVersion", value))
1224 +    platform_version_ = value;
1225 +
1226 +  size_t major_pos = 0, minor_pos = 0;
1227 +  major_pos = platform_version_.find_first_of('.');
1228 +  if (major_pos != std::string::npos &&
1229 +      major_pos <= platform_version_.size() - 1)
1230 +    minor_pos = platform_version_.find_first_of('.', major_pos + 1);
1231 +  if (major_pos == std::string::npos || minor_pos == std::string::npos) {
1232 +    version_major_ = version_minor_ = version_dot_ = -1;
1233 +  } else {
1234 +    version_major_ =
1235 +        util::StrToIntWithDefault(platform_version_.substr(0, major_pos), 0);
1236 +    version_minor_ = util::StrToIntWithDefault(
1237 +        platform_version_.substr(major_pos + 1, minor_pos), 0);
1238 +    version_dot_ =
1239 +        util::StrToIntWithDefault(platform_version_.substr(minor_pos + 1), 0);
1240 +  }
1241 +}
1242 +
1243 +void DeviceInfoCEF::GatherInfo() {
1244 +  InitDisplayInfo();
1245 +  InitPlatformInfo();
1246 +}
1247 diff --git a/src/cef/device_info_cef.h b/src/cef/device_info_cef.h
1248 new file mode 100644
1249 index 0000000..e2b3712
1250 --- /dev/null
1251 +++ b/src/cef/device_info_cef.h
1252 @@ -0,0 +1,38 @@
1253 +#ifndef CEF_DEVICE_INFO_CEF_H_
1254 +#define CEF_DEVICE_INFO_CEF_H_
1255 +
1256 +#include <string>
1257 +
1258 +#include "device_info.h"
1259 +
1260 +class DeviceInfoCEF : public DeviceInfo {
1261 + public:
1262 +  DeviceInfoCEF();
1263 +
1264 +  void Initialize() override;
1265 +
1266 + private:
1267 +  int screen_width_ = 0;
1268 +  int screen_height_ = 0;
1269 +
1270 +  float screen_density_ = 1.0f;
1271 +
1272 +  std::string model_name_ = "webOS.Open.CEF";
1273 +  std::string platform_version_ = "00.00.00";
1274 +
1275 +  // platform versions are <major>.<minor>.<dot>
1276 +  int version_major_ = 0;
1277 +  int version_minor_ = 0;
1278 +  int version_dot_ = 0;
1279 +
1280 +  bool support_3d_ = false;
1281 +  std::string ota_id_;
1282 +  std::string hardware_version_ = "0x00000001";
1283 +  std::string firmware_version_ = "00.00.01";
1284 +
1285 +  void InitDisplayInfo();
1286 +  void InitPlatformInfo();
1287 +  void GatherInfo();
1288 +};
1289 +
1290 +#endif  // CEF_DEVICE_INFO_IMPL_H_
1291 diff --git a/src/cef/handlers/wam_cef_browser_handler.cc b/src/cef/handlers/wam_cef_browser_handler.cc
1292 new file mode 100644
1293 index 0000000..0708363
1294 --- /dev/null
1295 +++ b/src/cef/handlers/wam_cef_browser_handler.cc
1296 @@ -0,0 +1,31 @@
1297 +#include "wam_cef_browser_handler.h"
1298 +
1299 +#include "log_manager.h"
1300 +#include "log_msg_id.h"
1301 +#include "platform_module_factory_cef.h"
1302 +#include "wam_cef_client.h"
1303 +#include "web_app_manager_service_grpc.h"
1304 +
1305 +WamCefBrowserHandler::WamCefBrowserHandler() :
1306 +  client_(new WamCefClient()) {
1307 +  WebAppManager::Instance()->SetPlatformModules(
1308 +      std::make_unique<PlatformModuleFactoryCEF>());
1309 +}
1310 +
1311 +WamCefBrowserHandler::~WamCefBrowserHandler() {}
1312 +
1313 +CefRefPtr<CefBrowserProcessHandler> WamCefBrowserHandler::GetBrowserProcessHandler() {
1314 +  return this;
1315 +}
1316 +
1317 +CefRefPtr<CefClient> WamCefBrowserHandler::GetDefaultClient() {
1318 +  return client_;
1319 +}
1320 +
1321 +void WamCefBrowserHandler::OnContextInitialized() {
1322 +  if (!WebAppManagerServiceGRPC::Instance()->InitializeAsHostService()) {
1323 +    LOG_ERROR(MSGID_ERROR_CANNOT_LOCK_SERVICE, 0,
1324 +        "Cannot lock WAM GRPC service IPC");
1325 +  }
1326 +  WebAppManagerServiceGRPC::Instance()->StartService();
1327 +}
1328 diff --git a/src/cef/handlers/wam_cef_browser_handler.h b/src/cef/handlers/wam_cef_browser_handler.h
1329 new file mode 100644
1330 index 0000000..58c7f20
1331 --- /dev/null
1332 +++ b/src/cef/handlers/wam_cef_browser_handler.h
1333 @@ -0,0 +1,23 @@
1334 +#ifndef CEF_HANDLERS_WAM_CEF_BROWSER_HANDLER_H
1335 +#define CEF_HANDLERS_WAM_CEF_BROWSER_HANDLER_H
1336 +
1337 +#include "include/cef_app.h"
1338 +#include "include/cef_browser_process_handler.h"
1339 +
1340 +#include "wam_cef_client.h"
1341 +
1342 +class WamCefBrowserHandler : public CefApp, public CefBrowserProcessHandler {
1343 + public:
1344 +  WamCefBrowserHandler();
1345 +  virtual ~WamCefBrowserHandler();
1346 +
1347 +  CefRefPtr<CefBrowserProcessHandler> GetBrowserProcessHandler() override;
1348 +  CefRefPtr<CefClient> GetDefaultClient() override;
1349 +  void OnContextInitialized() override;
1350 +
1351 + private:
1352 +  IMPLEMENT_REFCOUNTING(WamCefBrowserHandler);
1353 +  CefRefPtr<WamCefClient> client_;
1354 +};
1355 +
1356 +#endif  // CEF_HANDLERS_WAM_CEF_BROWSER_HANDLER_H
1357 diff --git a/src/cef/handlers/wam_cef_client.cc b/src/cef/handlers/wam_cef_client.cc
1358 new file mode 100644
1359 index 0000000..5ba6201
1360 --- /dev/null
1361 +++ b/src/cef/handlers/wam_cef_client.cc
1362 @@ -0,0 +1,39 @@
1363 +#include "wam_cef_client.h"
1364 +
1365 +#include "include/wrapper/cef_helpers.h"
1366 +
1367 +WamCefClient* g_instance = nullptr;
1368 +
1369 +WamCefClient::WamCefClient() {
1370 +  DCHECK(!g_instance);
1371 +  g_instance = this;
1372 +}
1373 +
1374 +// static
1375 +WamCefClient* WamCefClient::GetInstance() {
1376 +  return g_instance;
1377 +}
1378 +
1379 +bool WamCefClient::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
1380 +                                            CefRefPtr<CefFrame> frame,
1381 +                                            CefProcessId source_process,
1382 +                                            CefRefPtr<CefProcessMessage> message) {
1383 +  std::string message_name = message->GetName();
1384 +  CefRefPtr<CefListValue> args = message->GetArgumentList();
1385 +  if (message_name == "start") {
1386 +    if (args->GetSize() != 1) {
1387 +      return false;
1388 +    }
1389 +    std::string app_id = args->GetString(0);
1390 +    applauncher_.Start(app_id);
1391 +    return true;
1392 +  } else if (message_name == "get_applications") {
1393 +    if (args->GetSize() != 1) {
1394 +      return false;
1395 +    }
1396 +    bool only_graphical = args->GetBool(0);
1397 +    applauncher_.GetApplications(browser, only_graphical);
1398 +    return true;
1399 +  }
1400 +  return false;
1401 +}
1402 diff --git a/src/cef/handlers/wam_cef_client.h b/src/cef/handlers/wam_cef_client.h
1403 new file mode 100644
1404 index 0000000..3189c42
1405 --- /dev/null
1406 +++ b/src/cef/handlers/wam_cef_client.h
1407 @@ -0,0 +1,31 @@
1408 +#ifndef CEF_HANDLERS_WAM_CEF_CLIENT_H
1409 +#define CEF_HANDLERS_WAM_CEF_CLIENT_H
1410 +
1411 +#include "include/cef_client.h"
1412 +
1413 +#include "applauncher_client_grpc.h"
1414 +
1415 +class WamCefClient : public CefClient,
1416 +                     public CefLifeSpanHandler {
1417 + public:
1418 +  WamCefClient();
1419 +
1420 +  static WamCefClient* GetInstance();
1421 +
1422 +  CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override {
1423 +    return this;
1424 +  }
1425 +
1426 +  bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
1427 +                                CefRefPtr<CefFrame> frame,
1428 +                                CefProcessId source_process,
1429 +                                CefRefPtr<CefProcessMessage> message) override;
1430 +
1431 + private:
1432 +  AppLauncherClientGRPC applauncher_;
1433 +
1434 +  IMPLEMENT_REFCOUNTING(WamCefClient);
1435 +  DISALLOW_COPY_AND_ASSIGN(WamCefClient);
1436 +};
1437 +
1438 +#endif  // CEF_HANDLERS_WAM_CEF_CLIENT_H
1439 diff --git a/src/cef/handlers/wam_cef_render_handler.cc b/src/cef/handlers/wam_cef_render_handler.cc
1440 new file mode 100644
1441 index 0000000..48c881a
1442 --- /dev/null
1443 +++ b/src/cef/handlers/wam_cef_render_handler.cc
1444 @@ -0,0 +1,135 @@
1445 +#include "wam_cef_render_handler.h"
1446 +
1447 +#include "include/cef_parser.h"
1448 +#include "include/cef_process_message.h"
1449 +
1450 +WamCefRenderHandler::WamCefRenderHandler() {}
1451 +
1452 +void WamCefRenderHandler::OnContextCreated(CefRefPtr<CefBrowser> browser,
1453 +                                           CefRefPtr<CefFrame> frame,
1454 +                                           CefRefPtr<CefV8Context> context) {
1455 +
1456 +  CefRefPtr<CefV8Value> app_service = CefV8Value::CreateObject(nullptr, nullptr);
1457 +
1458 +  CefRefPtr<CefV8Value> start = CefV8Value::CreateFunction("start", this);
1459 +  app_service->SetValue("start", start, V8_PROPERTY_ATTRIBUTE_NONE);
1460 +
1461 +  CefRefPtr<CefV8Value> get_applications = CefV8Value::CreateFunction("getApplications", this);
1462 +  app_service->SetValue("getApplications", get_applications, V8_PROPERTY_ATTRIBUTE_NONE);
1463 +
1464 +  CefRefPtr<CefV8Value> global = context->GetGlobal(); // window object
1465 +  CefRefPtr<CefV8Value> navigator = global->GetValue("navigator");
1466 +
1467 +  navigator->SetValue("appService", app_service, V8_PROPERTY_ATTRIBUTE_NONE);
1468 +}
1469 +
1470 +void WamCefRenderHandler::OnContextReleased(CefRefPtr<CefBrowser> browser,
1471 +                                            CefRefPtr<CefFrame> frame,
1472 +                                            CefRefPtr<CefV8Context> context) {
1473 +  if (callback_map_.empty()) {
1474 +    return;
1475 +  }
1476 +
1477 +  CallbackMap::iterator it = callback_map_.begin();
1478 +  for (; it != callback_map_.end();) {
1479 +    if (it->second.first->IsSame(context)) {
1480 +      callback_map_.erase(it++);
1481 +    } else {
1482 +      ++it;
1483 +    }
1484 +  }
1485 +}
1486 +
1487 +void WamCefRenderHandler::Start(const std::string &app_id) {
1488 +  CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("start");
1489 +  CefRefPtr<CefListValue> args = message->GetArgumentList();
1490 +  args->SetString(0, app_id);
1491 +  auto context = CefV8Context::GetCurrentContext();
1492 +  context->GetFrame()->SendProcessMessage(PID_BROWSER, message);
1493 +}
1494 +
1495 +void WamCefRenderHandler::GetApplications(bool only_graphical, CefRefPtr<CefV8Value> callback) {
1496 +  std::string message_name = "get_applications";
1497 +
1498 +  // store the callback until we receive the browser's response
1499 +  CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
1500 +  int browser_id = context->GetBrowser()->GetIdentifier();
1501 +  callback_map_.insert(
1502 +      std::make_pair(std::make_pair(message_name, browser_id),
1503 +                     std::make_pair(context, callback)));
1504 +
1505 +  CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create(message_name);
1506 +  CefRefPtr<CefListValue> args = message->GetArgumentList();
1507 +  args->SetBool(0, only_graphical);
1508 +  context->GetFrame()->SendProcessMessage(PID_BROWSER, message);
1509 +}
1510 +
1511 +bool WamCefRenderHandler::Execute(const CefString& name,
1512 +                                  CefRefPtr<CefV8Value> object,
1513 +                                  const CefV8ValueList& arguments,
1514 +                                  CefRefPtr<CefV8Value>& retval,
1515 +                                  CefString& exception) {
1516 +  if (name == "start") {
1517 +    if (arguments.size() != 1 || !arguments[0]->IsString()) {
1518 +      return false;
1519 +    }
1520 +    std::string app_id = arguments[0]->GetStringValue();
1521 +    Start(app_id);
1522 +    return true;
1523 +  } else if (name == "getApplications") {
1524 +    if (arguments.size() != 2 ||
1525 +        !arguments[0]->IsBool() ||
1526 +        !arguments[1]->IsFunction()) {
1527 +      return false;
1528 +    }
1529 +    GetApplications(arguments[0]->GetBoolValue(), arguments[1]);
1530 +    return true;
1531 +  }
1532 +
1533 +  return false;
1534 +}
1535 +
1536 +bool WamCefRenderHandler::OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
1537 +                                                   CefRefPtr<CefFrame> frame,
1538 +                                                   CefProcessId source_process,
1539 +                                                   CefRefPtr<CefProcessMessage> message) {
1540 +  std::string message_name = message->GetName();
1541 +  CefRefPtr<CefListValue> args = message->GetArgumentList();
1542 +  if (message_name == "get_applications") {
1543 +    CallbackMap::const_iterator it = callback_map_.find(
1544 +      std::make_pair(message_name,
1545 +                     browser->GetIdentifier()));
1546 +    if (it == callback_map_.end()) {
1547 +      return false;
1548 +    }
1549 +
1550 +    CefRefPtr<CefV8Context> context = it->second.first;
1551 +    CefRefPtr<CefV8Value> callback = it->second.second;
1552 +
1553 +    context->Enter();
1554 +
1555 +    CefRefPtr<CefValue> apps_list_value = CefParseJSON(args->GetString(0), JSON_PARSER_RFC);
1556 +
1557 +    CefRefPtr<CefListValue> list = apps_list_value->GetList();
1558 +    int size = list->GetSize();
1559 +    CefRefPtr<CefV8Value> apps_list = CefV8Value::CreateArray(size);
1560 +    for (int i = 0; i < size; i++) {
1561 +      CefRefPtr<CefDictionaryValue> app_info_dict = list->GetDictionary(i);
1562 +      CefRefPtr<CefV8Value> dict = CefV8Value::CreateObject(nullptr, nullptr);
1563 +      dict->SetValue("id", CefV8Value::CreateString(app_info_dict->GetString("id")), V8_PROPERTY_ATTRIBUTE_NONE);
1564 +      dict->SetValue("name", CefV8Value::CreateString(app_info_dict->GetString("name")), V8_PROPERTY_ATTRIBUTE_NONE);
1565 +      dict->SetValue("icon", CefV8Value::CreateString(app_info_dict->GetString("icon")), V8_PROPERTY_ATTRIBUTE_NONE);
1566 +      apps_list->SetValue(i, dict);
1567 +    }
1568 +
1569 +    CefV8ValueList arguments;
1570 +    arguments.push_back(apps_list);
1571 +    callback->ExecuteFunctionWithContext(context, nullptr, arguments);
1572 +
1573 +    context->Exit();
1574 +
1575 +    return true;
1576 +  }
1577 +
1578 +  return false;
1579 +}
1580 diff --git a/src/cef/handlers/wam_cef_render_handler.h b/src/cef/handlers/wam_cef_render_handler.h
1581 new file mode 100644
1582 index 0000000..4a05ed6
1583 --- /dev/null
1584 +++ b/src/cef/handlers/wam_cef_render_handler.h
1585 @@ -0,0 +1,54 @@
1586 +#ifndef CEF_HANDLERS_WAM_CEF_RENDER_HANDLER_H
1587 +#define CEF_HANDLERS_WAM_CEF_RENDER_HANDLER_H
1588 +
1589 +#include <map>
1590 +#include <string>
1591 +
1592 +#include "include/cef_app.h"
1593 +#include "include/cef_render_process_handler.h"
1594 +#include "include/cef_v8.h"
1595 +
1596 +class WamCefRenderHandler : public CefApp,
1597 +                            public CefRenderProcessHandler,
1598 +                            public CefV8Handler {
1599 + public:
1600 +  typedef std::map<std::pair<std::string, int>,
1601 +                  std::pair<CefRefPtr<CefV8Context>, CefRefPtr<CefV8Value>>> CallbackMap;
1602 +
1603 +  WamCefRenderHandler();
1604 +
1605 +  CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override {
1606 +    return this;
1607 +  }
1608 +
1609 +  void OnContextCreated(CefRefPtr<CefBrowser> browser,
1610 +                        CefRefPtr<CefFrame> frame,
1611 +                        CefRefPtr<CefV8Context> context) override;
1612 +
1613 +
1614 +  void OnContextReleased(CefRefPtr<CefBrowser> browser,
1615 +                         CefRefPtr<CefFrame> frame,
1616 +                         CefRefPtr<CefV8Context> context) override;
1617 +
1618 +  bool Execute(const CefString& name,
1619 +               CefRefPtr<CefV8Value> object,
1620 +               const CefV8ValueList& arguments,
1621 +               CefRefPtr<CefV8Value>& retval,
1622 +               CefString& exception) override;
1623 +
1624 +  bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
1625 +                                CefRefPtr<CefFrame> frame,
1626 +                                CefProcessId source_process,
1627 +                                CefRefPtr<CefProcessMessage> message) override;
1628 +
1629 +  void Start(const std::string &app_id);
1630 +  void GetApplications(bool only_graphical, CefRefPtr<CefV8Value> callback);
1631 +
1632 + private:
1633 +  IMPLEMENT_REFCOUNTING(WamCefRenderHandler);
1634 +  DISALLOW_COPY_AND_ASSIGN(WamCefRenderHandler);
1635 +
1636 +  CallbackMap callback_map_;
1637 +};
1638 +
1639 +#endif  // CEF_HANDLERS_WAM_CEF_RENDER_HANDLER_H
1640 diff --git a/src/cef/platform_module_factory_cef.cc b/src/cef/platform_module_factory_cef.cc
1641 new file mode 100644
1642 index 0000000..e225b9d
1643 --- /dev/null
1644 +++ b/src/cef/platform_module_factory_cef.cc
1645 @@ -0,0 +1,31 @@
1646 +#include "platform_module_factory_cef.h"
1647 +
1648 +#include "device_info_cef.h"
1649 +#include "service_sender.h"
1650 +#include "web_app_manager_config.h"
1651 +#include "web_process_manager.h"
1652 +
1653 +PlatformModuleFactoryCEF::PlatformModuleFactoryCEF() {
1654 +  PrepareRenderingContext();
1655 +}
1656 +
1657 +std::unique_ptr<ServiceSender>
1658 +PlatformModuleFactoryCEF::CreateServiceSender() {
1659 +  return nullptr;
1660 +}
1661 +
1662 +std::unique_ptr<WebProcessManager>
1663 +PlatformModuleFactoryCEF::CreateWebProcessManager() {
1664 +  return nullptr;
1665 +}
1666 +
1667 +std::unique_ptr<DeviceInfo> PlatformModuleFactoryCEF::CreateDeviceInfo() {
1668 +  return std::make_unique<DeviceInfoCEF>();
1669 +}
1670 +
1671 +std::unique_ptr<WebAppManagerConfig>
1672 +PlatformModuleFactoryCEF::CreateWebAppManagerConfig() {
1673 +  return std::unique_ptr<WebAppManagerConfig>(new WebAppManagerConfig());
1674 +}
1675 +
1676 +void PlatformModuleFactoryCEF::PrepareRenderingContext() {}
1677 diff --git a/src/cef/platform_module_factory_cef.h b/src/cef/platform_module_factory_cef.h
1678 new file mode 100644
1679 index 0000000..5015dda
1680 --- /dev/null
1681 +++ b/src/cef/platform_module_factory_cef.h
1682 @@ -0,0 +1,27 @@
1683 +#ifndef CEF_PLATFORM_MODULE_FACTORY_CEF_H_
1684 +#define CEF_PLATFORM_MODULE_FACTORY_CEF_H_
1685 +
1686 +#include <memory>
1687 +
1688 +#include "platform_module_factory.h"
1689 +
1690 +class ServiceSender;
1691 +class WebProcessManager;
1692 +class DeviceInfo;
1693 +class WebAppManagerConfig;
1694 +
1695 +class PlatformModuleFactoryCEF : public PlatformModuleFactory {
1696 + public:
1697 +  PlatformModuleFactoryCEF();
1698 +
1699 + protected:
1700 +  std::unique_ptr<ServiceSender> CreateServiceSender() override;
1701 +  std::unique_ptr<WebProcessManager> CreateWebProcessManager() override;
1702 +  std::unique_ptr<DeviceInfo> CreateDeviceInfo() override;
1703 +  std::unique_ptr<WebAppManagerConfig> CreateWebAppManagerConfig() override;
1704 +
1705 + private:
1706 +  void PrepareRenderingContext();
1707 +};
1708 +
1709 +#endif  // CEF_PLATFORM_MODULE_FACTORY_CEF_H_
1710 diff --git a/src/cef/plugin/web_app_cef.cc b/src/cef/plugin/web_app_cef.cc
1711 new file mode 100644
1712 index 0000000..f57212b
1713 --- /dev/null
1714 +++ b/src/cef/plugin/web_app_cef.cc
1715 @@ -0,0 +1,172 @@
1716 +#include "web_app_cef.h"
1717 +
1718 +#include "include/base/cef_callback.h"
1719 +#include "include/views/cef_display.h"
1720 +#include "include/wrapper/cef_closure_task.h"
1721 +
1722 +#include "web_page_cef.h"
1723 +
1724 +WebAppCEF::WebAppCEF(std::shared_ptr<ApplicationDescription> app_desc) {
1725 +  SetAppDescription(app_desc);
1726 +}
1727 +
1728 +WebAppCEF::~WebAppCEF() {}
1729 +
1730 +void WebAppCEF::Init(int width,
1731 +                     int height,
1732 +                     AglShellSurfaceType surface_type,
1733 +                     AglShellPanelEdge panel_type) {
1734 +  ApplicationDescription* app_desc = GetAppDescription();
1735 +  std::string app_id = app_desc->Id();
1736 +
1737 +  if (!IsReady()) {
1738 +    return;
1739 +  }
1740 +
1741 +  surface_type_ = surface_type;
1742 +  panel_type_ = panel_type;
1743 +
1744 +  switch (surface_type_) {
1745 +    case AglShellSurfaceType::kBackground:
1746 +      window_->AglSetBackGroundApp();
1747 +      window_->AglSetAppReady();
1748 +      break;
1749 +    case AglShellSurfaceType::kPanel:
1750 +      window_->AglSetPanelApp(static_cast<int>(panel_type_));
1751 +      break;
1752 +    case AglShellSurfaceType::kNone:
1753 +      surface_type_ = AglShellSurfaceType::kNone;
1754 +      CefPostDelayedTask(
1755 +          TID_UI,
1756 +          base::BindOnce(&WebAppCEF::DelayedActivate, this),
1757 +          500);
1758 +      break;
1759 +  }
1760 +}
1761 +
1762 +void WebAppCEF::TryInitialize() {
1763 +  ApplicationDescription* app_desc = GetAppDescription();
1764 +
1765 +  if (!IsReady()) {
1766 +    CefPostDelayedTask(
1767 +        TID_UI,
1768 +        base::BindOnce(&WebAppCEF::TryInitialize, this),
1769 +        500);
1770 +    return;
1771 +    // TODO: add a maximum number of retries
1772 +  }
1773 +
1774 +  Init(app_desc->WidthOverride(),
1775 +       app_desc->HeightOverride(),
1776 +       app_desc->SurfaceType(),
1777 +       app_desc->PanelType());
1778 +}
1779 +
1780 +void WebAppCEF::Attach(WebPageBase* web_page) {
1781 +  WebAppBase::Attach(web_page);
1782 +
1783 +  WebPageCEF* web_page_cef = static_cast<WebPageCEF*>(Page());
1784 +  if (!web_page_cef) {
1785 +    // TODO: handle error
1786 +    return;
1787 +  }
1788 +  web_page_cef->SetWebApp(this);
1789 +}
1790 +
1791 +void WebAppCEF::OnWindowCreated(CefRefPtr<CefWindow> window) {
1792 +  if (!browser_view_) {
1793 +    return;
1794 +  }
1795 +
1796 +  window_ = window;
1797 +  window_->AddChildView(browser_view_);
1798 +  window_->Show();
1799 +
1800 +  TryInitialize();
1801 +}
1802 +
1803 +CefRect WebAppCEF::GetDisplayBounds() const {
1804 +  CefRefPtr<CefDisplay> display = CefDisplay::GetPrimaryDisplay();
1805 +  CefRect display_bounds;
1806 +  if (display) {
1807 +    display_bounds = display->GetBounds();
1808 +  }
1809 +  return display_bounds;
1810 +}
1811 +
1812 +CefSize WebAppCEF::GetPreferredSize(CefRefPtr<CefView> view) {
1813 +  return CefSize(width_override_, height_override_);
1814 +}
1815 +
1816 +CefRect WebAppCEF::GetInitialBounds(CefRefPtr<CefWindow> window) {
1817 +  return CefRect(0, 0, width_override_, height_override_);
1818 +}
1819 +
1820 +void WebAppCEF::SendAglReady() {
1821 +  // Empty because it's called on Init()
1822 +}
1823 +
1824 +void WebAppCEF::SetAglAppId(const char* app_id) {
1825 +  if (!window_) {
1826 +    return;
1827 +  }
1828 +  window_->SetTitle(app_id);
1829 +  window_->AglSetAppId(app_id);
1830 +}
1831 +
1832 +void WebAppCEF::SendAglActivate(const char* app_id) {
1833 +  if (!window_) {
1834 +    return;
1835 +  }
1836 +  window_->AglActivateApp(app_id);
1837 +}
1838 +
1839 +void WebAppCEF::Resize(int width, int height) {
1840 +  if (!window_) {
1841 +    return;
1842 +  }
1843 +  window_->SetSize(CefSize(width, height));
1844 +}
1845 +
1846 +bool WebAppCEF::IsReady() const {
1847 +  return window_ != nullptr;
1848 +}
1849 +
1850 +void WebAppCEF::Hide(bool forced_hide) {
1851 +  if (!window_) {
1852 +    return;
1853 +  }
1854 +  window_->Hide();
1855 +}
1856 +
1857 +bool WebAppCEF::HideWindow() {
1858 +  if (!window_) {
1859 +    return false;
1860 +  }
1861 +  window_->Hide();
1862 +  return true;
1863 +}
1864 +
1865 +void WebAppCEF::Raise() {
1866 +  if (!window_) {
1867 +    return;
1868 +  }
1869 +  window_->BringToTop();
1870 +}
1871 +
1872 +void WebAppCEF::DelayedActivate() {
1873 +  ApplicationDescription* app_desc = GetAppDescription();
1874 +  SendAglActivate(app_desc->Id().c_str());
1875 +}
1876 +
1877 +void WebAppCEF::Relaunch(const std::string& args,
1878 +                         const std::string& launching_app_id) {
1879 +  if (!window_) {
1880 +    return;
1881 +  }
1882 +
1883 +  ApplicationDescription* app_desc = GetAppDescription();
1884 +  std::string app_id = app_desc->Id();
1885 +
1886 +  SendAglActivate(app_id.c_str());
1887 +}
1888 diff --git a/src/cef/plugin/web_app_cef.h b/src/cef/plugin/web_app_cef.h
1889 new file mode 100644
1890 index 0000000..57145cf
1891 --- /dev/null
1892 +++ b/src/cef/plugin/web_app_cef.h
1893 @@ -0,0 +1,95 @@
1894 +#ifndef CEF_PLUGIN_WEB_APP_CEF_H
1895 +#define CEF_PLUGIN_WEB_APP_CEF_H
1896 +
1897 +#include <cstdint>
1898 +#include <memory>
1899 +
1900 +#include "web_app_base.h"
1901 +
1902 +#include "include/views/cef_window.h"
1903 +#include "include/views/cef_browser_view.h"
1904 +#include "include/views/cef_window_delegate.h"
1905 +
1906 +#include "application_description.h"
1907 +
1908 +class WebAppCEF : public WebAppBase, public CefWindowDelegate {
1909 + public:
1910 +  WebAppCEF(std::shared_ptr<ApplicationDescription> app_desc);
1911 +
1912 +  ~WebAppCEF();
1913 +
1914 +  virtual void Init(int width,
1915 +                    int height,
1916 +                    AglShellSurfaceType surface_type,
1917 +                    AglShellPanelEdge panel_type) override;
1918 +
1919 +  void SuspendAppRendering() override {}
1920 +  void ResumeAppRendering() override {}
1921 +  bool IsFocused() const override { return false; }
1922 +  void Resize(int width, int height) override;
1923 +  bool IsActivated() const override { return false; }
1924 +  bool IsMinimized() override { return false; }
1925 +  bool IsNormal() override { return true; }
1926 +  void OnStageActivated() override {}
1927 +  void OnStageDeactivated() override {}
1928 +  void DoAttach() override {}
1929 +  void ConfigureWindow(const std::string& type) override {}
1930 +  void SetWindowProperty(const std::string& name,
1931 +                         const std::string& value) override {}
1932 +  void PlatformBack() override {}
1933 +  void SetCursor(const std::string& cursor_arg,
1934 +                       int hotspot_x,
1935 +                       int hotspot_y) override {}
1936 +  void SetInputRegion(const Json::Value& json_doc) override {}
1937 +  void SetKeyMask(const Json::Value& json_doc) override {}
1938 +  void Hide(bool forced_hide = false) override;
1939 +  void Focus() override {}
1940 +  void Unfocus() override {}
1941 +  void SetOpacity(float opacity) override {}
1942 +  void Raise() override;
1943 +  void GoBackground() override {}
1944 +  void DoPendingRelaunch() override {}
1945 +  void DeleteSurfaceGroup() override {}
1946 +  void DoClose() override {}
1947 +  void SetUseVirtualKeyboard(const bool enable) override {}
1948 +  bool HideWindow() override;
1949 +
1950 +  void SendAglReady() override;
1951 +  void SendAglActivate(const char* app_id) override;
1952 +  void SetAglAppId(const char* app_id) override;
1953 +
1954 +  void Attach(WebPageBase* web_page) override;
1955 +
1956 +  void Relaunch(const std::string& args,
1957 +                const std::string& launching_app_id) override;
1958 +
1959 +  void SetBrowserView(CefRefPtr<CefBrowserView> browser_view) {
1960 +    browser_view_ = browser_view;
1961 +  }
1962 +
1963 +  virtual bool IsReady() const;
1964 +
1965 +  // CEF overrides
1966 +  void OnWindowCreated(CefRefPtr<CefWindow> window) override;
1967 +  CefSize GetPreferredSize(CefRefPtr<CefView> view) override;
1968 +  CefRect GetInitialBounds(CefRefPtr<CefWindow> window) override;
1969 +  bool IsFrameless(CefRefPtr<CefWindow> window) override { return true; }
1970 +
1971 + protected:
1972 +  void TryInitialize();
1973 +  void DelayedActivate();
1974 +
1975 +  CefRect GetDisplayBounds() const;
1976 +
1977 +  CefRefPtr<CefBrowserView> browser_view_;
1978 +  CefRefPtr<CefWindow> window_;
1979 +  AglShellSurfaceType surface_type_;
1980 +  AglShellPanelEdge panel_type_;
1981 +  uint32_t width_override_ = 0;
1982 +  uint32_t height_override_ = 0;
1983 +
1984 + private:
1985 +  IMPLEMENT_REFCOUNTING(WebAppCEF);
1986 +};
1987 +
1988 +#endif  // CEF_PLUGIN_WEB_APP_CEF_H
1989 diff --git a/src/cef/plugin/web_page_cef.cc b/src/cef/plugin/web_page_cef.cc
1990 new file mode 100644
1991 index 0000000..32c6e89
1992 --- /dev/null
1993 +++ b/src/cef/plugin/web_page_cef.cc
1994 @@ -0,0 +1,48 @@
1995 +#include "web_page_cef.h"
1996 +#include "application_description.h"
1997 +
1998 +#include "include/views/cef_window.h"
1999 +
2000 +#include "wam_cef_client.h"
2001 +
2002 +WebPageCEF::WebPageCEF(std::shared_ptr<ApplicationDescription> app_desc, const std::string& url)
2003 +  : url_{url} {
2004 +  SetApplicationDescription(app_desc);
2005 +}
2006 +
2007 +WebPageCEF::~WebPageCEF() {}
2008 +
2009 +void WebPageCEF::LoadUrl(const std::string& url) {
2010 +  CefBrowserSettings browser_settings;
2011 +  browser_view_ = CefBrowserView::CreateBrowserView(
2012 +      WamCefClient::GetInstance(), url, browser_settings, nullptr, nullptr, this);
2013 +
2014 +  web_app_->SetBrowserView(browser_view_);
2015 +
2016 +  ApplicationDescription* app_desc = GetAppDescription();
2017 +  CefWindow::CreateTopLevelWindowWithId(web_app_, app_desc->Id());
2018 +}
2019 +
2020 +void WebPageCEF::LoadDefaultUrl() {
2021 +  LoadUrl(url_);
2022 +}
2023 +
2024 +bool WebPageCEF::HasBeenShown() const {
2025 +  if (!web_app_) {
2026 +    return false;
2027 +  }
2028 +
2029 +  return web_app_->IsReady();
2030 +}
2031 +
2032 +
2033 +void WebPageCEF::EvaluateJavaScript(const std::string& jsCode) {
2034 +  /*if (!browser_view_) {
2035 +    return;
2036 +  }
2037 +  CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
2038 +  if (!browser) {
2039 +    return;
2040 +  }
2041 +  browser->GetMainFrame()->ExecuteJavaScript(jsCode, url_, 0);*/
2042 +}
2043 diff --git a/src/cef/plugin/web_page_cef.h b/src/cef/plugin/web_page_cef.h
2044 new file mode 100644
2045 index 0000000..f62c223
2046 --- /dev/null
2047 +++ b/src/cef/plugin/web_page_cef.h
2048 @@ -0,0 +1,69 @@
2049 +#ifndef CEF_PLUGIN_WEB_PAGE_CEF_H
2050 +#define CEF_PLUGIN_WEB_PAGE_CEF_H
2051 +
2052 +#include <memory>
2053 +
2054 +#include "web_page_base.h"
2055 +#include "web_app_cef.h"
2056 +
2057 +#include "include/views/cef_browser_view_delegate.h"
2058 +
2059 +class WebPageCEF : public WebPageBase,
2060 +                   public CefBrowserViewDelegate {
2061 + public:
2062 +  WebPageCEF(std::shared_ptr<ApplicationDescription> app_desc, const std::string& url);
2063 +  ~WebPageCEF() override;
2064 +
2065 +  void Init() override {}
2066 +  void* GetWebContents() override { return nullptr; }
2067 +
2068 +  wam::Url Url() const override { return wam::Url(""); }
2069 +  std::string FailedUrl() const override { return ""; }
2070 +  void LoadUrl(const std::string& url) override;
2071 +  int Progress() const override { return 0; }
2072 +  bool HasBeenShown() const override;
2073 +  void SetPageProperties() override {}
2074 +  void SetPreferredLanguages(const std::string& language) override {}
2075 +  void SetDefaultFont(const std::string& font) override {}
2076 +  void ReloadDefaultPage() override {}
2077 +  void Reload() override {}
2078 +  void SetVisibilityState(WebPageVisibilityState visibility_state) override {}
2079 +  void SetFocus(bool focus) override {}
2080 +  std::string Title() override { return ""; }
2081 +  bool CanGoBack() override { return false; }
2082 +  void CloseVkb() override {}
2083 +  void HandleDeviceInfoChanged(const std::string& device_info) override {}
2084 +  void EvaluateJavaScript(const std::string& jsCode) override;
2085 +  void EvaluateJavaScriptInAllFrames(const std::string& js_code,
2086 +                                     const char* method = {}) override {}
2087 +  uint32_t GetWebProcessProxyID() override { return 0; }
2088 +  uint32_t GetWebProcessPID() const override { return 0; }
2089 +  void CreatePalmSystem(WebAppBase* app) override {}
2090 +
2091 +  void SuspendWebPageAll() override {}
2092 +  void ResumeWebPageAll() override {}
2093 +  void SuspendWebPageMedia() override {}
2094 +  void ResumeWebPageMedia() override {}
2095 +  void ResumeWebPagePaintingAndJSExecution() override {}
2096 +  void ForwardEvent(void* event) override {}
2097 +
2098 +  void SuspendWebPagePaintingAndJSExecution() override {}
2099 +
2100 +  void SetWebApp(CefRefPtr<WebAppCEF> web_app) { web_app_ = web_app; }
2101 +
2102 + protected:
2103 +  void LoadDefaultUrl() override;
2104 +  void AddUserScript(const std::string& script) override {}
2105 +  void AddUserScriptUrl(const wam::Url& url) override {}
2106 +  void LoadErrorPage(int error_code) override {}
2107 +  void RecreateWebView() override {}
2108 +
2109 + private:
2110 +  IMPLEMENT_REFCOUNTING(WebPageCEF);
2111 +
2112 +  CefRefPtr<CefBrowserView> browser_view_;
2113 +  CefRefPtr<WebAppCEF> web_app_;
2114 +  std::string url_;
2115 +};
2116 +
2117 +#endif  // CEF_PLUGIN_WEB_PAGE_CEF_H
2118 diff --git a/src/cef/service/CMakeLists.txt b/src/cef/service/CMakeLists.txt
2119 new file mode 100644
2120 index 0000000..763b527
2121 --- /dev/null
2122 +++ b/src/cef/service/CMakeLists.txt
2123 @@ -0,0 +1,64 @@
2124 +project(WebAppMgrService VERSION 1.0.0 DESCRIPTION "Web Application Manager cli helper")
2125 +
2126 +find_package(gRPC REQUIRED)
2127 +find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED)
2128 +find_package(Protobuf REQUIRED)
2129 +find_package(Threads)
2130 +
2131 +set(WAM_GRPC_LIB_NAME ${PROJECT_NAME}-grpc)
2132 +set(APPLAUNCHER_LIB_NAME WamAppLauncher-grpc)
2133 +
2134 +set(WAM_GRPC_LIBS
2135 +    protobuf::libprotobuf
2136 +    gRPC::grpc
2137 +    gRPC::grpc++
2138 +    gRPC::grpc++_reflection
2139 +)
2140 +set(WAM_SERVICE_LIBS
2141 +    ${WAM_GRPC_LIBS}
2142 +    ${WAM_GRPC_LIB_NAME}
2143 +    ${APPLAUNCHER_LIB_NAME}
2144 +    libcef_lib
2145 +    libcef_dll_wrapper
2146 +)
2147 +set(WAM_GRPC_INCLUDE_DIRS
2148 +    ${CMAKE_CURRENT_SOURCE_DIR}
2149 +    ${CMAKE_CURRENT_BINARY_DIR}
2150 +)
2151 +set(WAM_SERVICE_INCLUDE_DIRS
2152 +    ${CEF_INCLUDE_PATH}
2153 +    ${WAM_ROOT_SOURCE_DIR}/core
2154 +    ${WAM_ROOT_SOURCE_DIR}/util
2155 +)
2156 +set(SOURCES
2157 +    applauncher_client_grpc.cc
2158 +    web_app_manager_client_grpc.cc
2159 +    web_app_manager_service_grpc.cc
2160 +)
2161 +set(HEADERS
2162 +    applauncher_client_grpc.h
2163 +    web_app_manager_client_grpc.h
2164 +    web_app_manager_service_grpc.h
2165 +)
2166 +
2167 +
2168 +macro(add_wam_grpc_lib target proto)
2169 +    add_library(${target} SHARED ${proto})
2170 +    target_include_directories(${target} PUBLIC ${WAM_GRPC_INCLUDE_DIRS})
2171 +    target_link_libraries(${target} PUBLIC ${WAM_GRPC_LIBS})
2172 +    set_target_properties(${target} PROPERTIES VERSION 1.0.0 SOVERSION 1.0)
2173 +    protobuf_generate(TARGET ${target} LANGUAGE cpp APPEND_PATH)
2174 +    protobuf_generate(TARGET ${target} LANGUAGE grpc APPEND_PATH GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=${GRPC_CPP_PLUGIN_EXECUTABLE}")
2175 +    install(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR})
2176 +endmacro(add_wam_grpc_lib)
2177 +
2178 +add_wam_grpc_lib(${WAM_GRPC_LIB_NAME} wam_ipc.proto)
2179 +add_wam_grpc_lib(${APPLAUNCHER_LIB_NAME} applauncher.proto)
2180 +
2181 +add_library(${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES})
2182 +set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 1.0.0 SOVERSION 1.0)
2183 +add_dependencies(${PROJECT_NAME} ${WAM_GRPC_LIB_NAME})
2184 +target_include_directories(${PROJECT_NAME} PUBLIC ${WAM_SERVICE_INCLUDE_DIRS})
2185 +target_link_libraries(${PROJECT_NAME} PUBLIC ${WAM_SERVICE_LIBS})
2186 +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
2187 +install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
2188 diff --git a/src/cef/service/applauncher.proto b/src/cef/service/applauncher.proto
2189 new file mode 100644
2190 index 0000000..0b8e0fc
2191 --- /dev/null
2192 +++ b/src/cef/service/applauncher.proto
2193 @@ -0,0 +1,50 @@
2194 +syntax = "proto3";
2195 +
2196 +package automotivegradelinux;
2197 +
2198 +service AppLauncher {
2199 +  rpc StartApplication(StartRequest) returns (StartResponse) {}
2200 +  rpc ListApplications(ListRequest) returns (ListResponse) {}
2201 +  rpc GetStatusEvents(StatusRequest) returns (stream StatusResponse) {}
2202 +}
2203 +
2204 +message StartRequest {
2205 +  string id = 1;
2206 +}
2207 +
2208 +message StartResponse {
2209 +  bool status = 1;
2210 +  string message = 2;
2211 +}
2212 +
2213 +message ListRequest {
2214 +}
2215 +
2216 +message ListResponse {
2217 +  repeated AppInfo apps = 1;
2218 +}
2219 +
2220 +message AppInfo {
2221 +  string id = 1;
2222 +  string name = 2;
2223 +  string icon_path = 3;
2224 +}
2225 +
2226 +message StatusRequest {
2227 +}
2228 +
2229 +message AppStatus {
2230 +  string id = 1;
2231 +  string status = 2;
2232 +}
2233 +
2234 +// Future-proofing for e.g. potentially signaling a list refresh
2235 +message LauncherStatus {
2236 +}
2237 +
2238 +message StatusResponse {
2239 +  oneof status {
2240 +    AppStatus app = 1;
2241 +    LauncherStatus launcher = 2;
2242 +  }
2243 +}
2244 diff --git a/src/cef/service/applauncher_client_grpc.cc b/src/cef/service/applauncher_client_grpc.cc
2245 new file mode 100644
2246 index 0000000..f704742
2247 --- /dev/null
2248 +++ b/src/cef/service/applauncher_client_grpc.cc
2249 @@ -0,0 +1,58 @@
2250 +#include "applauncher_client_grpc.h"
2251 +
2252 +#include <grpcpp/ext/proto_server_reflection_plugin.h>
2253 +#include <grpcpp/grpcpp.h>
2254 +#include <grpcpp/health_check_service_interface.h>
2255 +
2256 +#include "include/cef_parser.h"
2257 +
2258 +AppLauncherClientGRPC::AppLauncherClientGRPC()
2259 +  : stub_{MakeStub()} {
2260 +}
2261 +
2262 +std::unique_ptr<automotivegradelinux::AppLauncher::Stub>AppLauncherClientGRPC::MakeStub() const {
2263 +  return automotivegradelinux::AppLauncher::NewStub(grpc::CreateChannel("localhost:50052",
2264 +                                                    grpc::InsecureChannelCredentials()));
2265 +}
2266 +
2267 +void AppLauncherClientGRPC::Start(const std::string& app_id) {
2268 +  automotivegradelinux::StartRequest request;
2269 +    request.set_id(app_id);
2270 +
2271 +    grpc::ClientContext context;
2272 +    automotivegradelinux::StartResponse response;
2273 +
2274 +    grpc::Status status = stub_->StartApplication(&context, request, &response);
2275 +}
2276 +
2277 +void AppLauncherClientGRPC::GetApplications(CefRefPtr<CefBrowser> browser, bool only_graphical) {
2278 +  automotivegradelinux::ListRequest request;
2279 +  automotivegradelinux::ListResponse response;
2280 +  grpc::ClientContext context;
2281 +
2282 +  grpc::Status status = stub_->ListApplications(&context, request, &response);
2283 +  if (!status.ok()) {
2284 +    return;
2285 +  }
2286 +
2287 +  CefRefPtr<CefListValue> apps_list = CefListValue::Create();
2288 +  for (int i = 0; i < response.apps_size(); i++) {
2289 +    automotivegradelinux::AppInfo app_info = response.apps(i);
2290 +    CefRefPtr<CefDictionaryValue> app_info_dict = CefDictionaryValue::Create();
2291 +    app_info_dict->SetString("id", app_info.id());
2292 +    app_info_dict->SetString("name", app_info.name());
2293 +    app_info_dict->SetString("icon", app_info.icon_path());
2294 +    apps_list->SetDictionary(i, app_info_dict);
2295 +  }
2296 +
2297 +  CefRefPtr<CefValue> apps_list_value = CefValue::Create();
2298 +  apps_list_value->SetList(apps_list);
2299 +  std::string response_string = CefWriteJSON(apps_list_value, JSON_WRITER_DEFAULT);
2300 +
2301 +  // send the response to renderer process
2302 +  CefRefPtr<CefProcessMessage> message = CefProcessMessage::Create("get_applications");
2303 +  CefRefPtr<CefListValue> args = message->GetArgumentList();
2304 +  args->SetString(0, response_string);
2305 +  browser->GetMainFrame()->SendProcessMessage(PID_RENDERER, message);
2306 +}
2307 +
2308 diff --git a/src/cef/service/applauncher_client_grpc.h b/src/cef/service/applauncher_client_grpc.h
2309 new file mode 100644
2310 index 0000000..4a3f289
2311 --- /dev/null
2312 +++ b/src/cef/service/applauncher_client_grpc.h
2313 @@ -0,0 +1,24 @@
2314 +#ifndef CEF_SERVICE_APPLAUNCHER_CLIENT_GRPC_H
2315 +#define CEF_SERVICE_APPLAUNCHER_CLIENT_GRPC_H
2316 +
2317 +#include <string>
2318 +
2319 +#include "applauncher.grpc.pb.h"
2320 +
2321 +#include "include/cef_browser.h"
2322 +
2323 +class AppLauncherClientGRPC {
2324 + public:
2325 +
2326 +  AppLauncherClientGRPC();
2327 +
2328 +  void Start(const std::string& app_id);
2329 +  void GetApplications(CefRefPtr<CefBrowser> browser, bool only_graphical);
2330 +
2331 + private:
2332 +  std::unique_ptr<automotivegradelinux::AppLauncher::Stub> MakeStub() const;
2333 +
2334 +  std::unique_ptr<automotivegradelinux::AppLauncher::Stub> stub_;
2335 +};
2336 +
2337 +#endif // CEF_SERVICE_APPLAUNCHER_CLIENT_GRPC_H
2338 diff --git a/src/cef/service/wam_ipc.proto b/src/cef/service/wam_ipc.proto
2339 new file mode 100644
2340 index 0000000..313de8f
2341 --- /dev/null
2342 +++ b/src/cef/service/wam_ipc.proto
2343 @@ -0,0 +1,22 @@
2344 +syntax = "proto3";
2345 +import "google/protobuf/empty.proto";
2346 +package wam_ipc;
2347 +
2348 +service WebAppManagerService {
2349 +  rpc Launch(LaunchRequest) returns (google.protobuf.Empty) {}
2350 +  rpc Activate(ActivateRequest) returns (google.protobuf.Empty) {}
2351 +  rpc Kill(KillRequest) returns (google.protobuf.Empty) {}
2352 +}
2353 +
2354 +message LaunchRequest {
2355 +  string app_id = 1;
2356 +  string uri = 2;
2357 +}
2358 +
2359 +message ActivateRequest {
2360 +  string app_id = 1;
2361 +}
2362 +
2363 +message KillRequest {
2364 +  string app_id = 1;
2365 +}
2366 diff --git a/src/cef/service/web_app_manager_client_grpc.cc b/src/cef/service/web_app_manager_client_grpc.cc
2367 new file mode 100644
2368 index 0000000..8529868
2369 --- /dev/null
2370 +++ b/src/cef/service/web_app_manager_client_grpc.cc
2371 @@ -0,0 +1,42 @@
2372 +#include "web_app_manager_client_grpc.h"
2373 +
2374 +#include <grpcpp/ext/proto_server_reflection_plugin.h>
2375 +#include <grpcpp/grpcpp.h>
2376 +#include <grpcpp/health_check_service_interface.h>
2377 +
2378 +const char kDefaultGrpcServiceAddress[] = "127.0.0.1:15000";
2379 +
2380 +WebAppManagerClientGRPC::WebAppManagerClientGRPC() {
2381 +  auto channel = grpc::CreateChannel(kDefaultGrpcServiceAddress,
2382 +                                     grpc::InsecureChannelCredentials());
2383 +  stub_ = wam_ipc::WebAppManagerService::NewStub(channel);
2384 +}
2385 +
2386 +bool WebAppManagerClientGRPC::Launch(const LaunchParams& params) {
2387 +  wam_ipc::LaunchRequest request;
2388 +  request.set_app_id(params.app_id);
2389 +  request.set_uri(params.uri);
2390 +
2391 +  grpc::ClientContext context;
2392 +  google::protobuf::Empty reply;
2393 +  grpc::Status status = stub_->Launch(&context, request, &reply);
2394 +  return status.ok();
2395 +}
2396 +
2397 +bool WebAppManagerClientGRPC::Activate(const std::string& app_id) {
2398 +  grpc::ClientContext context;
2399 +  google::protobuf::Empty reply;
2400 +  wam_ipc::ActivateRequest request;
2401 +  request.set_app_id(app_id);
2402 +  grpc::Status status = stub_->Activate(&context, request, &reply);
2403 +  return status.ok();
2404 +}
2405 +
2406 +bool WebAppManagerClientGRPC::Kill(const std::string& app_id) {
2407 +  grpc::ClientContext context;
2408 +  google::protobuf::Empty reply;
2409 +  wam_ipc::KillRequest request;
2410 +  request.set_app_id(app_id);
2411 +  grpc::Status status = stub_->Kill(&context, request, &reply);
2412 +  return status.ok();
2413 +}
2414 diff --git a/src/cef/service/web_app_manager_client_grpc.h b/src/cef/service/web_app_manager_client_grpc.h
2415 new file mode 100644
2416 index 0000000..9c4be70
2417 --- /dev/null
2418 +++ b/src/cef/service/web_app_manager_client_grpc.h
2419 @@ -0,0 +1,23 @@
2420 +#ifndef CEF_SERVICE_WEB_APP_MANAGER_CLIENT_GRPC_H
2421 +#define CEF_SERVICE_WEB_APP_MANAGER_CLIENT_GRPC_H
2422 +
2423 +#include "wam_ipc.grpc.pb.h"
2424 +
2425 +class WebAppManagerClientGRPC {
2426 + public:
2427 +  struct LaunchParams {
2428 +    std::string app_id;
2429 +    std::string uri;
2430 +  };
2431 +
2432 +  WebAppManagerClientGRPC();
2433 +  bool Launch(const LaunchParams& params);
2434 +  bool Activate(const std::string& app_id);
2435 +  bool Kill(const std::string& app_id);
2436 +
2437 + private:
2438 +  std::unique_ptr<wam_ipc::WebAppManagerService::Stub> stub_;
2439 +};
2440 +
2441 +#endif  // CEF_SERVICE_WEB_APP_MANAGER_CLIENT_GRPC_H
2442 +
2443 diff --git a/src/cef/service/web_app_manager_service_grpc.cc b/src/cef/service/web_app_manager_service_grpc.cc
2444 new file mode 100644
2445 index 0000000..52de924
2446 --- /dev/null
2447 +++ b/src/cef/service/web_app_manager_service_grpc.cc
2448 @@ -0,0 +1,382 @@
2449 +// Copyright (c) 2018-2022 LG Electronics, Inc.
2450 +//
2451 +// Licensed under the Apache License, Version 2.0 (the "License");
2452 +// you may not use this file except in compliance with the License.
2453 +// You may obtain a copy of the License at
2454 +//
2455 +// http://www.apache.org/licenses/LICENSE-2.0
2456 +//
2457 +// Unless required by applicable law or agreed to in writing, software
2458 +// distributed under the License is distributed on an "AS IS" BASIS,
2459 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2460 +// See the License for the specific language governing permissions and
2461 +// limitations under the License.
2462 +//
2463 +// SPDX-License-Identifier: Apache-2.0
2464 +
2465 +#include "web_app_manager_service_grpc.h"
2466 +
2467 +#include <grpcpp/ext/proto_server_reflection_plugin.h>
2468 +#include <grpcpp/grpcpp.h>
2469 +#include <grpcpp/health_check_service_interface.h>
2470 +#include <pthread.h>
2471 +#include <sys/file.h>
2472 +#include <sys/un.h>
2473 +#include <unistd.h>
2474 +#include <algorithm>
2475 +#include <cassert>
2476 +#include <climits>
2477 +#include <cstdlib>
2478 +#include <exception>
2479 +#include <fstream>
2480 +#include <iostream>
2481 +#include <set>
2482 +#include <sstream>
2483 +
2484 +#include <json/value.h>
2485 +
2486 +#include "log_manager.h"
2487 +#include "utils.h"
2488 +#include "wam_ipc.grpc.pb.h"
2489 +#include "web_app_base.h"
2490 +#include "web_app_manager.h"
2491 +
2492 +namespace {
2493 +const char kDefaultGrpcServiceAddress[] = "127.0.0.1:15000";
2494 +}  // namespace
2495 +
2496 +class WamIPCLockFile {
2497 + public:
2498 +  WamIPCLockFile() {
2499 +    const char* runtime_dir;
2500 +    if ((runtime_dir = getenv("XDG_RUNTIME_DIR")) == NULL) {
2501 +      LOG_DEBUG("Failed to retrieve XDG_RUNTIME_DIR, falling back to /tmp");
2502 +      runtime_dir = "/tmp";
2503 +    }
2504 +    lock_file_ = std::string(runtime_dir);
2505 +    lock_file_.append("/wamipc.lock");
2506 +  }
2507 +
2508 +  ~WamIPCLockFile() {
2509 +    if (lock_fd_ != -1)
2510 +      ReleaseLock(lock_fd_);
2511 +    if (lock_fd_ != -1)
2512 +      close(lock_fd_);
2513 +  }
2514 +
2515 +  bool CreateAndLock() {
2516 +    lock_fd_ = OpenLockFile();
2517 +    if (!AcquireLock(lock_fd_)) {
2518 +      LOG_DEBUG("Failed to lock file %d", lock_fd_);
2519 +      return false;
2520 +    }
2521 +    return true;
2522 +  }
2523 +
2524 +  bool OwnsLock() const { return lock_fd_ != -1; }
2525 +
2526 +  bool TryAcquireLock() {
2527 +    int fd = OpenLockFile();
2528 +    if (fd != -1) {
2529 +      if (AcquireLock(fd)) {
2530 +        ReleaseLock(fd);
2531 +        return true;
2532 +      }
2533 +    }
2534 +    return false;
2535 +  }
2536 +
2537 + private:
2538 +  int OpenLockFile() {
2539 +    int fd = open(lock_file_.c_str(), O_CREAT | O_TRUNC, S_IRWXU);
2540 +    if (fd == -1) {
2541 +      LOG_DEBUG("Failed to open lock file descriptor");
2542 +      return fd;
2543 +    }
2544 +
2545 +    int flags = fcntl(fd, F_GETFD);
2546 +    if (flags == -1)
2547 +      LOG_DEBUG("Could not get flags for lock file %d", fd);
2548 +
2549 +    flags |= FD_CLOEXEC;
2550 +
2551 +    if (fcntl(fd, F_SETFD, flags) == -1)
2552 +      LOG_DEBUG("Could not set flags for lock file %d", fd);
2553 +
2554 +    return fd;
2555 +  }
2556 +
2557 +  bool AcquireLock(int fd) {
2558 +    if (flock(fd, LOCK_EX | LOCK_NB) != 0)
2559 +      return false;
2560 +    return true;
2561 +  }
2562 +
2563 +  void ReleaseLock(int fd) { flock(fd, LOCK_UN); }
2564 +
2565 +  std::string lock_file_;
2566 +  int lock_fd_ = -1;
2567 +};
2568 +
2569 +class GrpcServiceImpl final
2570 +    : public wam_ipc::WebAppManagerService::CallbackService {
2571 +  grpc::ServerUnaryReactor* Launch(grpc::CallbackServerContext* context,
2572 +                                   const ::wam_ipc::LaunchRequest* request,
2573 +                                   google::protobuf::Empty* /*response*/) {
2574 +    WebAppManagerServiceGRPC::LaunchParams launch_params;
2575 +    launch_params.app_id = request->app_id();
2576 +    launch_params.uri = request->uri();
2577 +    launch_params.width = 0;
2578 +    launch_params.height = 0;
2579 +
2580 +    WebAppManagerServiceGRPC::Instance()->LaunchOnIdle(launch_params);
2581 +
2582 +    grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
2583 +    reactor->Finish(grpc::Status::OK);
2584 +    return reactor;
2585 +  }
2586 +  grpc::ServerUnaryReactor* Activate(grpc::CallbackServerContext* context,
2587 +                                     const ::wam_ipc::ActivateRequest* request,
2588 +                                     google::protobuf::Empty* /*response*/) {
2589 +    WebAppManagerServiceGRPC::Instance()->SendEventOnIdle(kActivateEvent,
2590 +                                                          request->app_id());
2591 +    grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
2592 +    reactor->Finish(grpc::Status::OK);
2593 +    return reactor;
2594 +  }
2595 +  grpc::ServerUnaryReactor* Kill(grpc::CallbackServerContext* context,
2596 +                                 const ::wam_ipc::KillRequest* request,
2597 +                                 google::protobuf::Empty* /*response*/) {
2598 +    WebAppManagerServiceGRPC::Instance()->SendEventOnIdle(kKilledApp,
2599 +                                                          request->app_id());
2600 +    grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
2601 +    reactor->Finish(grpc::Status::OK);
2602 +    return reactor;
2603 +  }
2604 +};
2605 +
2606 +WebAppManagerServiceGRPC::WebAppManagerServiceGRPC()
2607 +    : lock_file_(std::make_unique<WamIPCLockFile>()) {}
2608 +
2609 +WebAppManagerServiceGRPC* WebAppManagerServiceGRPC::Instance() {
2610 +  static WebAppManagerServiceGRPC* srv = new WebAppManagerServiceGRPC();
2611 +  return srv;
2612 +}
2613 +
2614 +bool WebAppManagerServiceGRPC::InitializeAsHostService() {
2615 +  return lock_file_->CreateAndLock();
2616 +}
2617 +
2618 +bool WebAppManagerServiceGRPC::IsHostServiceRunning() {
2619 +  return !lock_file_->TryAcquireLock();
2620 +}
2621 +
2622 +void* RunGrpcService(void*) {
2623 +  std::string server_address(kDefaultGrpcServiceAddress);
2624 +  GrpcServiceImpl service;
2625 +
2626 +  grpc::EnableDefaultHealthCheckService(true);
2627 +  grpc::reflection::InitProtoReflectionServerBuilderPlugin();
2628 +
2629 +  grpc::ServerBuilder builder;
2630 +  builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
2631 +  builder.RegisterService(&service);
2632 +
2633 +  std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
2634 +  std::cout << "Server listening on " << server_address << std::endl;
2635 +  server->Wait();
2636 +
2637 +  return nullptr;
2638 +}
2639 +
2640 +bool WebAppManagerServiceGRPC::StartService() {
2641 +  if (lock_file_->OwnsLock()) {
2642 +    pthread_t thread_id;
2643 +    if (pthread_create(&thread_id, nullptr, RunGrpcService, nullptr) < 0) {
2644 +      perror("Could not create thread");
2645 +      LOG_DEBUG("Could not create thread...");
2646 +      return false;
2647 +    }
2648 +  }
2649 +
2650 +  return true;
2651 +}
2652 +
2653 +void WebAppManagerServiceGRPC::LaunchOnIdle(const LaunchParams& params) {
2654 +  auto launch_params = std::make_unique<LaunchParams>(params);
2655 +
2656 +  auto* timer =
2657 +      new OneShotTimerWithData<WebAppManagerServiceGRPC, LaunchParams>();
2658 +  timer->Start(0, this, &WebAppManagerServiceGRPC::OnLaunchApp,
2659 +               std::move(launch_params));
2660 +}
2661 +
2662 +void WebAppManagerServiceGRPC::SendEventOnIdle(const std::string& event,
2663 +                                               const std::string& app_id) {
2664 +  auto event_data = std::make_unique<EventData>();
2665 +  event_data->app_id = app_id;
2666 +  auto* timer = new OneShotTimerWithData<WebAppManagerServiceGRPC, EventData>();
2667 +  if (event == kActivateEvent)
2668 +    timer->Start(0, this, &WebAppManagerServiceGRPC::OnActivateEvent,
2669 +                 std::move(event_data));
2670 +  else if (event == kDeactivateEvent)
2671 +    timer->Start(0, this, &WebAppManagerServiceGRPC::OnDeactivateEvent,
2672 +                 std::move(event_data));
2673 +  else if (event == kKilledApp)
2674 +    timer->Start(1000, this, &WebAppManagerServiceGRPC::OnKillEvent,
2675 +                 std::move(event_data));
2676 +}
2677 +
2678 +void WebAppManagerServiceGRPC::OnLaunchApp(LaunchParams* params) {
2679 +  LOG_DEBUG("Triggering app start: %s", params->uri.c_str());
2680 +  if (!params->uri.empty()) {
2681 +    if (params->uri.find("http://") == 0) {
2682 +      LaunchStartupAppFromURL(params);
2683 +    } else {
2684 +      LaunchStartupAppFromJsonConfig(params);
2685 +    }
2686 +  }
2687 +}
2688 +
2689 +void WebAppManagerServiceGRPC::LaunchStartupAppFromJsonConfig(
2690 +    LaunchParams* params) {
2691 +  std::string configfile;
2692 +  configfile.append(params->uri);
2693 +  configfile.append("/appinfo.json");
2694 +
2695 +  Json::Value root;
2696 +  Json::CharReaderBuilder builder;
2697 +  JSONCPP_STRING errs;
2698 +
2699 +  std::ifstream ifs;
2700 +  ifs.open(configfile.c_str());
2701 +
2702 +  if (!parseFromStream(builder, ifs, &root, &errs)) {
2703 +    LOG_DEBUG("Failed to parse %s configuration file", configfile.c_str());
2704 +  }
2705 +
2706 +  root["folderPath"] = params->uri.c_str();
2707 +
2708 +  auto surface_obj = root["surface"];
2709 +  auto surface_type = surface_obj["type"].asString();
2710 +  if (surface_type == "background") {
2711 +    root["surface_type"] = 1; // AglShellSurfaceType::kBackground;
2712 +  } else if (surface_type == "panel") {
2713 +    root["surface_type"] = 2; // AglShellSurfaceType::kPanel;
2714 +  } else {
2715 +    root["surface_type"] = 0; // AglShellSurfaceType::kNone;
2716 +  }
2717 +
2718 +  std::string app_desc = util::JsonToString(root);
2719 +  std::string empty_params = "{}";
2720 +  std::string app_id = root["id"].asString();
2721 +  int err_code = 0;
2722 +  std::string err_msg;
2723 +  WebAppManagerService::OnLaunch(app_desc, empty_params, app_id, err_code,
2724 +                                 err_msg);
2725 +}
2726 +
2727 +void WebAppManagerServiceGRPC::LaunchStartupAppFromURL(LaunchParams* params) {
2728 +  LOG_DEBUG("WebAppManagerServiceGRPC::LaunchStartupAppFromURL");
2729 +  LOG_DEBUG("    url: %s", params->uri.c_str());
2730 +  Json::Value obj(Json::objectValue);
2731 +  obj["id"] = params->app_id;
2732 +  obj["version"] = "1.0";
2733 +  obj["vendor"] = "some vendor";
2734 +  obj["type"] = "web";
2735 +  obj["main"] = params->uri;
2736 +  obj["title"] = "webapp";
2737 +  obj["uiRevision"] = "2";
2738 +
2739 +  obj["widthOverride"] = params->width;
2740 +  obj["heightOverride"] = params->height;
2741 +
2742 +  std::string app_desc = util::JsonToString(obj);
2743 +  std::string app_id = params->app_id;
2744 +  int err_code = 0;
2745 +  std::string empty_params = "{}";
2746 +  std::string err_msg;
2747 +
2748 +  LOG_DEBUG("Launching with appDesc=[%s]", app_desc.c_str());
2749 +
2750 +  WebAppManagerService::OnLaunch(app_desc, empty_params, app_id, err_code,
2751 +                                 err_msg);
2752 +  LOG_DEBUG("onLaunch: Done.");
2753 +}
2754 +
2755 +Json::Value WebAppManagerServiceGRPC::launchApp(const Json::Value& request) {
2756 +  return Json::Value(Json::objectValue);
2757 +}
2758 +
2759 +Json::Value WebAppManagerServiceGRPC::killApp(const Json::Value& request) {
2760 +  return Json::Value(Json::objectValue);
2761 +}
2762 +
2763 +Json::Value WebAppManagerServiceGRPC::pauseApp(const Json::Value& request) {
2764 +  return Json::Value(Json::objectValue);
2765 +}
2766 +
2767 +Json::Value WebAppManagerServiceGRPC::logControl(const Json::Value& request) {
2768 +  return Json::Value(Json::objectValue);
2769 +}
2770 +
2771 +Json::Value WebAppManagerServiceGRPC::setInspectorEnable(
2772 +    const Json::Value& request) {
2773 +  return Json::Value(Json::objectValue);
2774 +}
2775 +
2776 +Json::Value WebAppManagerServiceGRPC::closeAllApps(const Json::Value& request) {
2777 +  return Json::Value(Json::objectValue);
2778 +}
2779 +
2780 +Json::Value WebAppManagerServiceGRPC::discardCodeCache(
2781 +    const Json::Value& request) {
2782 +  return Json::Value(Json::objectValue);
2783 +}
2784 +
2785 +Json::Value WebAppManagerServiceGRPC::listRunningApps(
2786 +    const Json::Value& request,
2787 +    bool subscribed) {
2788 +  return Json::Value(Json::objectValue);
2789 +}
2790 +
2791 +Json::Value WebAppManagerServiceGRPC::getWebProcessSize(
2792 +    const Json::Value& request) {
2793 +  return Json::Value(Json::objectValue);
2794 +}
2795 +
2796 +Json::Value WebAppManagerServiceGRPC::clearBrowsingData(
2797 +    const Json::Value& request) {
2798 +  return Json::Value(Json::objectValue);
2799 +}
2800 +
2801 +Json::Value WebAppManagerServiceGRPC::webProcessCreated(
2802 +    const Json::Value& request,
2803 +    bool subscribed) {
2804 +  return Json::Value(Json::objectValue);
2805 +}
2806 +
2807 +void WebAppManagerServiceGRPC::OnActivateEvent(EventData* event_data) {
2808 +  LOG_DEBUG("Activate app=%s", event_data->app_id.c_str());
2809 +  WebAppBase* web_app =
2810 +      WebAppManager::Instance()->FindAppById(event_data->app_id);
2811 +  if (web_app) {
2812 +    web_app->OnStageActivated();
2813 +    web_app->SendAglActivate(event_data->app_id.c_str());
2814 +  } else {
2815 +    LOG_DEBUG("Not found app=%s running", event_data->app_id.c_str());
2816 +  }
2817 +}
2818 +
2819 +void WebAppManagerServiceGRPC::OnDeactivateEvent(EventData* event_data) {
2820 +  LOG_DEBUG("Dectivate app=%s", event_data->app_id.c_str());
2821 +  WebAppBase* web_app =
2822 +      WebAppManager::Instance()->FindAppById(event_data->app_id);
2823 +  if (web_app)
2824 +    web_app->OnStageDeactivated();
2825 +}
2826 +
2827 +void WebAppManagerServiceGRPC::OnKillEvent(EventData* event_data) {
2828 +  LOG_DEBUG("Kill app=%s", event_data->app_id.c_str());
2829 +  WebAppManager::Instance()->OnKillApp(event_data->app_id, event_data->app_id);
2830 +}
2831 diff --git a/src/cef/service/web_app_manager_service_grpc.h b/src/cef/service/web_app_manager_service_grpc.h
2832 new file mode 100644
2833 index 0000000..69ea0ed
2834 --- /dev/null
2835 +++ b/src/cef/service/web_app_manager_service_grpc.h
2836 @@ -0,0 +1,85 @@
2837 +// Copyright (c) 2018-2022 LG Electronics, Inc.
2838 +//
2839 +// Licensed under the Apache License, Version 2.0 (the "License");
2840 +// you may not use this file except in compliance with the License.
2841 +// You may obtain a copy of the License at
2842 +//
2843 +// http://www.apache.org/licenses/LICENSE-2.0
2844 +//
2845 +// Unless required by applicable law or agreed to in writing, software
2846 +// distributed under the License is distributed on an "AS IS" BASIS,
2847 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2848 +// See the License for the specific language governing permissions and
2849 +// limitations under the License.
2850 +//
2851 +// SPDX-License-Identifier: Apache-2.0
2852 +
2853 +#ifndef CEF_SERVICE_WEB_APP_MANAGER_SERVICE_GRPC_H
2854 +#define CEF_SERVICE_WEB_APP_MANAGER_SERVICE_GRPC_H
2855 +
2856 +#include <memory>
2857 +
2858 +#include "timer.h"
2859 +#include "web_app_manager_service.h"
2860 +
2861 +constexpr char kStartApp[] = "start-app";
2862 +constexpr char kKilledApp[] = "killed-app";
2863 +constexpr char kActivateEvent[] = "activate-event";
2864 +constexpr char kDeactivateEvent[] = "deactivate-event";
2865 +
2866 +class GrpcClient;
2867 +class WamIPCLockFile;
2868 +
2869 +class WebAppManagerServiceGRPC : public WebAppManagerService,
2870 +                                 public TimerReceiver {
2871 + public:
2872 +  struct LaunchParams {
2873 +    std::string app_id;
2874 +    std::string uri;
2875 +    int width = 0;
2876 +    int height = 0;
2877 +  };
2878 +
2879 +  static WebAppManagerServiceGRPC* Instance();
2880 +
2881 +  bool InitializeAsHostService();
2882 +  bool IsHostServiceRunning();
2883 +
2884 +  void LaunchOnIdle(const LaunchParams& params);
2885 +  void SendEventOnIdle(const std::string& event, const std::string& app_id);
2886 +
2887 +  // WebAppManagerService
2888 +  bool StartService() override;
2889 +  Json::Value launchApp(const Json::Value& request) override;
2890 +  Json::Value killApp(const Json::Value& request) override;
2891 +  Json::Value pauseApp(const Json::Value& request) override;
2892 +  Json::Value logControl(const Json::Value& request) override;
2893 +  Json::Value setInspectorEnable(const Json::Value& request) override;
2894 +  Json::Value closeAllApps(const Json::Value& request) override;
2895 +  Json::Value discardCodeCache(const Json::Value& request) override;
2896 +  Json::Value listRunningApps(const Json::Value& request,
2897 +                              bool subscribed) override;
2898 +  Json::Value getWebProcessSize(const Json::Value& request) override;
2899 +  Json::Value clearBrowsingData(const Json::Value& request) override;
2900 +  Json::Value webProcessCreated(const Json::Value& request,
2901 +                                bool subscribed) override;
2902 +
2903 +  void TriggerStartupApp();
2904 +
2905 + private:
2906 +  WebAppManagerServiceGRPC();
2907 +
2908 +  void OnLaunchApp(LaunchParams* launch_data);
2909 +  void LaunchStartupAppFromJsonConfig(LaunchParams*);
2910 +  void LaunchStartupAppFromURL(LaunchParams*);
2911 +  struct EventData {
2912 +    std::string app_id;
2913 +  };
2914 +  void OnActivateEvent(EventData* event_data);
2915 +  void OnDeactivateEvent(EventData* event_data);
2916 +  void OnKillEvent(EventData* event_data);
2917 +
2918 +  std::unique_ptr<WamIPCLockFile> lock_file_;
2919 +};
2920 +
2921 +#endif  // CEF_SERVICE_WEB_APP_MANAGER_SERVICE_GRPC_H
2922 diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
2923 index 182f96a..41871b9 100644
2924 --- a/src/core/CMakeLists.txt
2925 +++ b/src/core/CMakeLists.txt
2926 @@ -18,6 +18,7 @@ project(WebAppMgrCore VERSION 1.0.0 DESCRIPTION "Core of the Web Application Man
2927  
2928  set(SOURCES
2929      application_description.cc
2930 +    application_installation_handler_stub.cc
2931      device_info.cc
2932      palm_system_base.cc
2933      plugin_service.cc
2934 @@ -44,7 +45,9 @@ set(SOURCES
2935  set(HEADERS
2936      agl_shell_types.h
2937      application_description.h
2938 +    application_installation_handler.h
2939      device_info.h
2940 +    memory_pressure_level.h
2941      palm_system_base.h
2942      platform_module_factory.h
2943      plugin_service.h
2944 @@ -95,6 +98,7 @@ set(CORE_INCLUDE_DIRS
2945  set(CORE_LIBS
2946      ${CHROMIUM_LDFLAGS}
2947      ${GLIB_LDFLAGS}
2948 +    ${JSONCPP_LDFLAGS}
2949      ${PMLOGLIB_LDFLAGS}
2950      Boost::filesystem
2951      dl
2952 diff --git a/src/core/application_description.cc b/src/core/application_description.cc
2953 index 9b494fc..adbb7d8 100644
2954 --- a/src/core/application_description.cc
2955 +++ b/src/core/application_description.cc
2956 @@ -144,12 +144,49 @@ std::unique_ptr<ApplicationDescription> ApplicationDescription::FromJsonString(
2957    auto app_desc =
2958        std::unique_ptr<ApplicationDescription>(new ApplicationDescription());
2959  
2960 +
2961    app_desc->surface_type_ =
2962        static_cast<AglShellSurfaceType>(json_obj["surface_type"].asInt());
2963    app_desc->panel_type_ =
2964        static_cast<AglShellPanelEdge>(json_obj["panel_type"].asInt());
2965    app_desc->width_override_ = json_obj["widthOverride"].asInt();
2966    app_desc->height_override_ = json_obj["heightOverride"].asInt();
2967 +
2968 +  // override previous values if the json config file contains
2969 +  // a "surface" object with nested data
2970 +  auto surface_obj = json_obj["surface"];
2971 +  if (!surface_obj.empty()) {
2972 +    std::string surface_type = surface_obj["type"].asString();
2973 +    if (surface_type == "background") {
2974 +      app_desc->surface_type_ = AglShellSurfaceType::kBackground;
2975 +    } else if (surface_type == "panel") {
2976 +      app_desc->surface_type_ = AglShellSurfaceType::kPanel;
2977 +    } else {
2978 +      app_desc->surface_type_ = AglShellSurfaceType::kNone;
2979 +    }
2980 +
2981 +    std::string panel_edge = surface_obj["panel_edge"].asString();
2982 +    if (panel_edge == "left") {
2983 +      app_desc->panel_type_ = AglShellPanelEdge::kLeft;
2984 +    } else if (panel_edge == "right") {
2985 +      app_desc->panel_type_ = AglShellPanelEdge::kRight;
2986 +    } else if (panel_edge == "top") {
2987 +      app_desc->panel_type_ = AglShellPanelEdge::kTop;
2988 +    } else if (panel_edge == "bottom") {
2989 +      app_desc->panel_type_ = AglShellPanelEdge::kBottom;
2990 +    }
2991 +
2992 +    int width = 0;
2993 +    if (!surface_obj["width"].empty())
2994 +      util::StrToInt(surface_obj["width"].asString(), width);
2995 +    app_desc->width_override_ = width;
2996 +
2997 +    int height = 0;
2998 +    if (!surface_obj["height"].empty())
2999 +      util::StrToInt(surface_obj["height"].asString(), height);
3000 +    app_desc->height_override_ = height;
3001 +  }
3002 +
3003    app_desc->transparency_ = json_obj["transparent"].asBool();
3004    auto vendor_extension =
3005        json_obj.get("vendorExtension", Json::Value(Json::objectValue));
3006 diff --git a/src/core/application_installation_handler.h b/src/core/application_installation_handler.h
3007 new file mode 100644
3008 index 0000000..054bc9d
3009 --- /dev/null
3010 +++ b/src/core/application_installation_handler.h
3011 @@ -0,0 +1,12 @@
3012 +#ifndef CORE_APPLICATION_INSTALLATION_HANDLER_H_
3013 +#define CORE_APPLICATION_INSTALLATION_HANDLER_H_
3014 +
3015 +#include <string>
3016 +
3017 +class ApplicationInstallationHandler {
3018 + public:
3019 +  static void OnAppInstalled(const std::string& app_id);
3020 +  static void OnAppRemoved(const std::string& app_id);
3021 +};
3022 +
3023 +#endif  // CORE_APPLICATION_INSTALLATION_HANDLER_H_
3024 \ No newline at end of file
3025 diff --git a/src/core/application_installation_handler_stub.cc b/src/core/application_installation_handler_stub.cc
3026 new file mode 100644
3027 index 0000000..016c7d2
3028 --- /dev/null
3029 +++ b/src/core/application_installation_handler_stub.cc
3030 @@ -0,0 +1,4 @@
3031 +#include "application_installation_handler.h"
3032 +
3033 +void ApplicationInstallationHandler::OnAppInstalled(const std::string&) {}
3034 +void ApplicationInstallationHandler::OnAppRemoved(const std::string&) {}
3035 \ No newline at end of file
3036 diff --git a/src/core/memory_pressure_level.h b/src/core/memory_pressure_level.h
3037 new file mode 100644
3038 index 0000000..01c9316
3039 --- /dev/null
3040 +++ b/src/core/memory_pressure_level.h
3041 @@ -0,0 +1,6 @@
3042 +#ifndef CORE_MEMORY_PRESSURE_LEVEL_H_
3043 +#define CORE_MEMORY_PRESSURE_LEVEL_H_
3044 +
3045 +enum class MemoryPressureLevel { kNone, kLow, kCritical };
3046 +
3047 +#endif  // CORE_MEMORY_PRESSURE_LEVEL_H_
3048 \ No newline at end of file
3049 diff --git a/src/core/web_app_manager.cc b/src/core/web_app_manager.cc
3050 index ca64ef1..42e8be7 100644
3051 --- a/src/core/web_app_manager.cc
3052 +++ b/src/core/web_app_manager.cc
3053 @@ -22,10 +22,9 @@
3054  #include <string>
3055  
3056  #include <json/value.h>
3057 -#include "webos/application_installation_handler.h"
3058 -#include "webos/public/runtime.h"
3059  
3060  #include "application_description.h"
3061 +#include "application_installation_handler.h"
3062  #include "base_check.h"
3063  #include "device_info.h"
3064  #include "log_manager.h"
3065 @@ -63,8 +62,7 @@ WebAppManager::~WebAppManager() {
3066      device_info_->Terminate();
3067  }
3068  
3069 -void WebAppManager::NotifyMemoryPressure(
3070 -    webos::WebViewBase::MemoryPressureLevel level) {
3071 +void WebAppManager::NotifyMemoryPressure(MemoryPressureLevel level) {
3072    std::list<const WebAppBase*> app_list = RunningApps();
3073    for (auto it = app_list.begin(); it != app_list.end(); ++it) {
3074      const WebAppBase* app = *it;
3075 @@ -72,15 +70,14 @@ void WebAppManager::NotifyMemoryPressure(
3076      // critical (when system is on low or critical) because they will be killed
3077      // anyway
3078      if (app->IsActivated() &&
3079 -        (!app->Page()->IsPreload() ||
3080 -         level != webos::WebViewBase::MEMORY_PRESSURE_CRITICAL))
3081 +        (!app->Page()->IsPreload() || level != MemoryPressureLevel::kCritical))
3082        app->Page()->NotifyMemoryPressure(level);
3083      else {
3084        LOG_DEBUG(
3085            "Skipping memory pressure handler for"
3086            " instanceId(%s) appId(%s) isActivated(%d) isPreload(%d) Level(%d)",
3087            app->InstanceId().c_str(), app->AppId().c_str(), app->IsActivated(),
3088 -          app->Page()->IsPreload(), level);
3089 +          app->Page()->IsPreload(), static_cast<int>(level));
3090      }
3091    }
3092  }
3093 @@ -341,8 +338,10 @@ WebAppBase* WebAppManager::OnLaunchUrl(
3094    WebPageAdded(page);
3095  
3096    /* if the surface role is a background send ready to display them */
3097 -  if (app_desc->SurfaceType() == AglShellSurfaceType::kBackground)
3098 +  if (app_desc->SurfaceType() == AglShellSurfaceType::kBackground) {
3099 +    LOG_DEBUG("Sending agl_ready from app %s", app_desc->Id().c_str());
3100      app->SendAglReady();
3101 +  }
3102  
3103    app_list_.push_back(app);
3104  
3105 @@ -831,8 +830,10 @@ void WebAppManager::UpdateNetworkStatus(const Json::Value& object) {
3106    NetworkStatus status;
3107    status.FromJsonObject(object);
3108  
3109 +#if defined(OS_WEBOS)
3110    webos::Runtime::GetInstance()->SetNetworkConnected(
3111        status.IsInternetConnectionAvailable());
3112 +#endif
3113    network_status_manager_->UpdateNetworkStatus(status);
3114  
3115    if (status.IsInternetConnectionAvailable()) {
3116 @@ -867,16 +868,12 @@ int WebAppManager::MaskForBrowsingDataType(const char* type) {
3117  
3118  void WebAppManager::AppInstalled(const std::string& app_id) {
3119    LOG_INFO(MSGID_WAM_DEBUG, 0, "App installed; id=%s", app_id.c_str());
3120 -  auto p = webos::ApplicationInstallationHandler::GetInstance();
3121 -  if (p)
3122 -    p->OnAppInstalled(app_id);
3123 +  ApplicationInstallationHandler::OnAppInstalled(app_id);
3124  }
3125  
3126  void WebAppManager::AppRemoved(const std::string& app_id) {
3127    LOG_INFO(MSGID_WAM_DEBUG, 0, "App removed; id=%s", app_id.c_str());
3128 -  auto p = webos::ApplicationInstallationHandler::GetInstance();
3129 -  if (p)
3130 -    p->OnAppRemoved(app_id);
3131 +  ApplicationInstallationHandler::OnAppRemoved(app_id);
3132  }
3133  
3134  std::string WebAppManager::IdentifierForSecurityOrigin(
3135 @@ -889,5 +886,9 @@ std::string WebAppManager::IdentifierForSecurityOrigin(
3136      LOG_WARNING(MSGID_APPID_HAS_UPPERCASE, 0,
3137                  "Application id should not contain capital letters");
3138    }
3139 +#if defined(OS_WEBOS)
3140    return (lowcase_identifier + webos::WebViewBase::kSecurityOriginPostfix);
3141 +#else
3142 +  return lowcase_identifier;
3143 +#endif
3144  }
3145 diff --git a/src/core/web_app_manager.h b/src/core/web_app_manager.h
3146 index b10f53d..0f30a85 100644
3147 --- a/src/core/web_app_manager.h
3148 +++ b/src/core/web_app_manager.h
3149 @@ -24,7 +24,7 @@
3150  #include <unordered_map>
3151  #include <vector>
3152  
3153 -#include "webos/webview_base.h"
3154 +#include "memory_pressure_level.h"
3155  
3156  class ApplicationDescription;
3157  class DeviceInfo;
3158 @@ -150,7 +150,7 @@ class WebAppManager {
3159                     const std::string& payload,
3160                     const std::string& app_id);
3161    void UpdateNetworkStatus(const Json::Value& object);
3162 -  void NotifyMemoryPressure(webos::WebViewBase::MemoryPressureLevel level);
3163 +  void NotifyMemoryPressure(MemoryPressureLevel level);
3164  
3165    bool IsEnyoApp(const std::string& app_id);
3166  
3167 diff --git a/src/core/web_app_manager_service.cc b/src/core/web_app_manager_service.cc
3168 index 1770d02..90b880f 100644
3169 --- a/src/core/web_app_manager_service.cc
3170 +++ b/src/core/web_app_manager_service.cc
3171 @@ -19,6 +19,7 @@
3172  #include <json/value.h>
3173  
3174  #include "log_manager.h"
3175 +#include "memory_pressure_level.h"
3176  #include "web_app_base.h"
3177  #include "web_app_manager_tracer.h"
3178  
3179 @@ -158,8 +159,7 @@ void WebAppManagerService::UpdateNetworkStatus(const Json::Value& object) {
3180    WebAppManager::Instance()->UpdateNetworkStatus(object);
3181  }
3182  
3183 -void WebAppManagerService::NotifyMemoryPressure(
3184 -    webos::WebViewBase::MemoryPressureLevel level) {
3185 +void WebAppManagerService::NotifyMemoryPressure(MemoryPressureLevel level) {
3186    WebAppManager::Instance()->NotifyMemoryPressure(level);
3187  }
3188  
3189 diff --git a/src/core/web_app_manager_service.h b/src/core/web_app_manager_service.h
3190 index 7ead117..c294e50 100644
3191 --- a/src/core/web_app_manager_service.h
3192 +++ b/src/core/web_app_manager_service.h
3193 @@ -22,7 +22,6 @@
3194  #include <vector>
3195  
3196  #include "web_app_manager.h"
3197 -#include "webos/webview_base.h"
3198  
3199  namespace Json {
3200  class Value;
3201 @@ -114,7 +113,7 @@ class WebAppManagerService {
3202    void KillCustomPluginProcess(const std::string& app_base_path);
3203    void RequestKillWebProcess(uint32_t pid);
3204    void UpdateNetworkStatus(const Json::Value& object);
3205 -  void NotifyMemoryPressure(webos::WebViewBase::MemoryPressureLevel level);
3206 +  void NotifyMemoryPressure(MemoryPressureLevel level);
3207    void SetAccessibilityEnabled(bool enable);
3208    uint32_t GetWebProcessId(const std::string& app_id,
3209                             const std::string& instance_id);
3210 diff --git a/src/core/web_page_base.h b/src/core/web_page_base.h
3211 index 7bbca84..8a689a7 100644
3212 --- a/src/core/web_page_base.h
3213 +++ b/src/core/web_page_base.h
3214 @@ -20,8 +20,7 @@
3215  #include <memory>
3216  #include <string>
3217  
3218 -#include "webos/webview_base.h"
3219 -
3220 +#include "memory_pressure_level.h"
3221  #include "observer_list.h"
3222  #include "util/url.h"
3223  
3224 @@ -58,8 +57,7 @@ class WebPageBase {
3225    virtual void Init() = 0;
3226    virtual void* GetWebContents() = 0;
3227    virtual void SetLaunchParams(const std::string& params);
3228 -  virtual void NotifyMemoryPressure(
3229 -      webos::WebViewBase::MemoryPressureLevel level) {}
3230 +  virtual void NotifyMemoryPressure(MemoryPressureLevel level) {}
3231  
3232    virtual std::string GetIdentifier() const;
3233    virtual wam::Url Url() const = 0;
3234 diff --git a/src/core/web_process_manager.h b/src/core/web_process_manager.h
3235 index b63d270..c7ffde1 100644
3236 --- a/src/core/web_process_manager.h
3237 +++ b/src/core/web_process_manager.h
3238 @@ -17,6 +17,7 @@
3239  #ifndef CORE_WEB_PROCESS_MANAGER_H_
3240  #define CORE_WEB_PROCESS_MANAGER_H_
3241  
3242 +#include <cstdint>
3243  #include <list>
3244  #include <string>
3245  #include <unordered_map>
3246 diff --git a/src/core/web_runtime.h b/src/core/web_runtime.h
3247 index 69bc204..1ae6ca9 100644
3248 --- a/src/core/web_runtime.h
3249 +++ b/src/core/web_runtime.h
3250 @@ -21,8 +21,9 @@
3251  
3252  class WebRuntime {
3253   public:
3254 +  virtual ~WebRuntime() = default;
3255    static std::unique_ptr<WebRuntime> Create();
3256 -  virtual int Run(int argc, const char** argv) = 0;
3257 +  virtual int Run(int argc, char** argv) = 0;
3258  };
3259  
3260  #endif  // CORE_WEB_RUNTIME_H_
3261 diff --git a/src/desktop/CMakeLists.txt b/src/desktop/CMakeLists.txt
3262 new file mode 100644
3263 index 0000000..06078da
3264 --- /dev/null
3265 +++ b/src/desktop/CMakeLists.txt
3266 @@ -0,0 +1,100 @@
3267 +project(WebAppMgrDesktop VERSION 1.0.0 DESCRIPTION "Web Application Manager library")
3268 +
3269 +find_package(gRPC REQUIRED)
3270 +find_program(GRPC_CPP_PLUGIN_EXECUTABLE grpc_cpp_plugin REQUIRED)
3271 +find_package(Protobuf REQUIRED)
3272 +find_package(Threads)
3273 +
3274 +set(WAM_IPC_LIB_NAME ${PROJECT_NAME}IPC)
3275 +set(WAM_IPC_PROTO_FILES ${WAM_ROOT_SOURCE_DIR}/cef/ipc/wam_ipc.proto)
3276 +set(WAM_IPC_LIBS
3277 +    protobuf::libprotobuf
3278 +    gRPC::grpc
3279 +    gRPC::grpc++
3280 +    gRPC::grpc++_reflection
3281 +)
3282 +set(WAM_IPC_INCLUDE_DIRS
3283 +    ${CMAKE_CURRENT_BINARY_DIR}
3284 +)
3285 +
3286 +set(WAM_LIB_LIBS
3287 +    ${JSONCPP_LDFLAGS}
3288 +    WebAppMgrCore
3289 +    ${WAM_IPC_LIB_NAME}
3290 +    libcef_lib
3291 +    libcef_dll_wrapper
3292 +)
3293 +
3294 +set(SOURCES
3295 +    web_runtime_desktop.cc
3296 +)
3297 +
3298 +set(HEADERS
3299 +    web_runtime_desktop.h
3300 +)
3301 +
3302 +set(WAM_LIB_CEF_DIR ${WAM_ROOT_SOURCE_DIR}/cef)
3303 +
3304 +
3305 +set(WAM_LIB_INCLUDE_DIRS
3306 +    ${JSONCPP_INCLUDE_DIRS}
3307 +    ${CEF_INCLUDE_PATH}
3308 +)
3309 +
3310 +add_library(${WAM_IPC_LIB_NAME} SHARED ${WAM_IPC_PROTO_FILES})
3311 +target_include_directories(${WAM_IPC_LIB_NAME} PUBLIC ${WAM_IPC_INCLUDE_DIRS})
3312 +target_link_libraries(${WAM_IPC_LIB_NAME} PUBLIC ${WAM_IPC_LIBS})
3313 +set_target_properties(${WAM_IPC_LIB_NAME} PROPERTIES VERSION 1.0.0 SOVERSION 1.0)
3314 +protobuf_generate(TARGET ${WAM_IPC_LIB_NAME} LANGUAGE cpp APPEND_PATH)
3315 +protobuf_generate(TARGET ${WAM_IPC_LIB_NAME} LANGUAGE grpc APPEND_PATH GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc PLUGIN "protoc-gen-grpc=${GRPC_CPP_PLUGIN_EXECUTABLE}")
3316 +install(TARGETS ${WAM_IPC_LIB_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
3317 +
3318 +
3319 +LIST(APPEND SOURCES
3320 +    ${WAM_LIB_CEF_DIR}/device_info_cef.cc
3321 +    ${WAM_LIB_CEF_DIR}/platform_module_factory_cef.cc
3322 +    ${WAM_LIB_CEF_DIR}/ipc/web_app_manager_service_grpc.cc
3323 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_browser_handler.cc
3324 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_client.cc
3325 +)
3326 +LIST(APPEND HEADERS
3327 +    ${WAM_LIB_CEF_DIR}/device_info_cef.h
3328 +    ${WAM_LIB_CEF_DIR}/platform_module_factory_cef.h
3329 +    ${WAM_LIB_CEF_DIR}/ipc/web_app_manager_service_grpc.h
3330 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_browser_handler.h
3331 +    ${WAM_LIB_CEF_DIR}/handlers/wam_cef_client.h
3332 +)
3333 +LIST(APPEND WAM_LIB_INCLUDE_DIRS
3334 +    ${WAM_LIB_CEF_DIR}
3335 +    ${WAM_LIB_CEF_DIR}/ipc
3336 +    ${WAM_LIB_CEF_DIR}/webapp
3337 +)
3338 +
3339 +add_library(${PROJECT_NAME} SHARED ${HEADERS} ${SOURCES})
3340 +target_include_directories(${PROJECT_NAME} PUBLIC ${WAM_LIB_INCLUDE_DIRS})
3341 +set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 1.0.0 SOVERSION 1.0)
3342 +
3343 +install(FILES ${HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX}/include/webappmanager)
3344 +
3345 +macro(INSTALL_CEF_FILES file_list source_dir target_dir)
3346 +  foreach(FILENAME ${file_list})
3347 +    set(source_file ${source_dir}/${FILENAME})
3348 +
3349 +    # Remove the target file path component.
3350 +    get_filename_component(target_name ${FILENAME} NAME)
3351 +    set(target_file ${target_dir}/${target_name})
3352 +
3353 +    if (IS_DIRECTORY ${source_file})
3354 +        install(DIRECTORY ${source_file} DESTINATION ${target_dir})
3355 +    else()
3356 +        install(FILES ${source_file} DESTINATION ${target_dir})
3357 +    endif()
3358 +  endforeach()
3359 +endmacro()
3360 +
3361 +# Copy CEF dependencies
3362 +install_cef_files("${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CMAKE_INSTALL_PREFIX}")
3363 +install_cef_files("${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CMAKE_INSTALL_PREFIX}")
3364 +
3365 +target_link_libraries(${PROJECT_NAME} PUBLIC ${WAM_LIB_LIBS})
3366 +install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR})
3367 diff --git a/src/desktop/README.md b/src/desktop/README.md
3368 new file mode 100644
3369 index 0000000..2d32b39
3370 --- /dev/null
3371 +++ b/src/desktop/README.md
3372 @@ -0,0 +1,102 @@
3373 +# CEF backend
3374 +
3375 +This is an experimental CEF backend for WAM.
3376 +
3377 +## Compilation
3378 +
3379 +### Preparations
3380 +
3381 +First prepare a workspace:
3382 +```
3383 +mkdir wam-cef
3384 +cd wam-cef
3385 +```
3386 +
3387 +Now clone WAM repository:
3388 +```
3389 +git clone ssh://git@gitlab.igalia.com:4429/dape/wam.git
3390 +```
3391 +
3392 +Fetch latest stable CEF binary distribution (standard) for your system, from [CEF binary download](https://cef-builds.spotifycdn.com/index.html). Then uncompress the tarball:
3393 +```
3394 +tar xvf ...path...to...binary/cef_binary...tar.bz2
3395 +```
3396 +
3397 +### Compilation of CEF DLL wrapper
3398 +
3399 +Create a folder to compile the CEF DLL wrapper `.a` file:
3400 +```
3401 +mkdir build-cef-dll
3402 +cd build-cef-dll
3403 +```
3404 +
3405 +Prepare compilation scripts:
3406 +```
3407 +cmake ../cef_binary_...
3408 +```
3409 +
3410 +Then compile the DLL wrapper:
3411 +```
3412 +make libcef_dll_wrapper
3413 +```
3414 +
3415 +Finally go back to the top directory:
3416 +```
3417 +cd ..
3418 +```
3419 +
3420 +After this, you can see the wrapper at `build-cef-dll/libcef_dll_wrapper/libcef_dll_wrapper.a`.
3421 +
3422 +### Test applications
3423 +
3424 +You can just use webOS `test-apps` repository:
3425 +```
3426 +git clone https://github.com/webosose/test-apps.git
3427 +```
3428 +
3429 +### Compilation of WAM
3430 +
3431 +Prepare build folder:
3432 +
3433 +```
3434 +mkdir build-wam
3435 +cd build-wam
3436 +mkdir wam-install
3437 +```
3438 +
3439 +Then call *CMake* to generate the compilation scripts. You will need to pass several variables:
3440 +* `CEF_ROOT`: full path to the CEF dist directory.
3441 +* `CMAKE_INSTALL_PREFIX`: base install directory.
3442 +* `CMAKE_INSTALL_BINDIR`: where executables will go.
3443 +* `CMAKE_INSTALL_LIBDIR`: libraries.
3444 +* `CMAKE_INSTALL_INCLUDEDIR`: path for includes.
3445 +
3446 +You can also use `CMAKE_BUILD_TYPE` to set `Debug` or `Release` builds.
3447 +
3448 +An example of the *CMake* invokation:
3449 +```
3450 +cmake -DCMAKE_INSTALL_PREFIX=$PWD/wam-install -DCMAKE_INSTALL_BINDIR=$PWD/wam-install/bin -DCMAKE_INSTALL_LIBDIR=$PWD/wam-install/lib -DCMAKE_INSTALL_INCLUDEDIR=$PWD/wam-install/include -DCEF_ROOT=$WAM_BASE_PATH/cef_binary_114.2.10+g398e3c3+chromium-114.0.5735.110_linux64/Debug/ -DCMAKE_BUILD_TYPE=Debug
3451 +```
3452 +
3453 +And finally compilation of WAM:
3454 +```
3455 +make
3456 +```
3457 +
3458 +And installation:
3459 +```
3460 +make install
3461 +```
3462 +
3463 +## Running
3464 +
3465 +To run the daemon, you can do:
3466 +```
3467 +cd wam-install/bin
3468 +WEBAPPFACTORY_PLUGIN_PATH=../lib/webappmanager/plugins/ LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../lib:$WAM_BASE_PATH/cef_binary_114.2.10+g398e3c3+chromium-114.0.5735.110_linux64/Release/ ./WebAppMgr &
3469 +```
3470 +
3471 +Then, you can launch an application:
3472 +```
3473 +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../lib ../WebAppMgrDesktopCli --app-id=bareapp --app-install-dir=$WAM_BASE_PATH/test-apps/bareapp/
3474 +```
3475 diff --git a/src/desktop/web_runtime_desktop.cc b/src/desktop/web_runtime_desktop.cc
3476 new file mode 100644
3477 index 0000000..49d1914
3478 --- /dev/null
3479 +++ b/src/desktop/web_runtime_desktop.cc
3480 @@ -0,0 +1,28 @@
3481 +#include "web_runtime_desktop.h"
3482 +
3483 +#include "include/cef_base.h"
3484 +
3485 +#include "wam_cef_browser_handler.h"
3486 +
3487 +int WebRuntimeDesktop::Run(int argc, char** argv) {
3488 +  CefMainArgs main_args(argc, argv);
3489 +
3490 +  CefRefPtr<CefApp> app = new WamCefBrowserHandler;
3491 +  auto exit_code = CefExecuteProcess(main_args, app.get(), nullptr);
3492 +  if (exit_code >= 0) {
3493 +    return exit_code;
3494 +  }
3495 +
3496 +  CefSettings settings;
3497 +  CefInitialize(main_args, settings, app.get(), nullptr);
3498 +
3499 +  CefRunMessageLoop();
3500 +
3501 +  CefShutdown();
3502 +
3503 +  return 0;
3504 +}
3505 +
3506 +std::unique_ptr<WebRuntime> WebRuntime::Create() {
3507 +  return std::make_unique<WebRuntimeDesktop>();
3508 +}
3509 diff --git a/src/desktop/web_runtime_desktop.h b/src/desktop/web_runtime_desktop.h
3510 new file mode 100644
3511 index 0000000..e65f738
3512 --- /dev/null
3513 +++ b/src/desktop/web_runtime_desktop.h
3514 @@ -0,0 +1,11 @@
3515 +#ifndef DESKTOP_WEB_RUNTIME_CEF_H_
3516 +#define DESKTOP_WEB_RUNTIME_CEF_H_
3517 +
3518 +#include "web_runtime.h"
3519 +
3520 +class WebRuntimeDesktop : public WebRuntime {
3521 + public:
3522 +  int Run(int argc, char** argv) override;
3523 +};
3524 +
3525 +#endif  // DESKTOP_WEB_RUNTIME_CEF_H_
3526 diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt
3527 index 876921b..b401dca 100644
3528 --- a/src/platform/CMakeLists.txt
3529 +++ b/src/platform/CMakeLists.txt
3530 @@ -17,10 +17,6 @@
3531  project(WebAppMgr VERSION 1.0.0 DESCRIPTION "Web Application Manager library")
3532  
3533  set(SOURCES
3534 -    palm_system_webos.cc
3535 -    web_app_wayland.cc
3536 -    web_app_wayland_window.cc
3537 -    web_app_window_impl.cc
3538      webengine/blink_web_process_manager.cc
3539      webengine/blink_web_view.cc
3540      webengine/blink_web_view_profile_helper.cc
3541 @@ -32,12 +28,8 @@ set(SOURCES
3542  )
3543  
3544  set(HEADERS
3545 -    palm_system_webos.h
3546 -    web_app_wayland.h
3547 -    web_app_wayland_window.h
3548      web_app_window.h
3549      web_app_window_factory.h
3550 -    web_app_window_impl.h
3551      webengine/blink_web_process_manager.h
3552      webengine/blink_web_view.h
3553      webengine/blink_web_view_profile_helper.h
3554 @@ -67,6 +59,21 @@ set(WAM_LIB_LIBS
3555      WebAppMgrCore
3556  )
3557  
3558 +if (WEBENGINE_CBE)
3559 +    LIST(APPEND SOURCES
3560 +        web_app_window_impl.h
3561 +        web_app_wayland_window.cc
3562 +        palm_system_webos.cc
3563 +        web_app_wayland.cc
3564 +    )
3565 +    LIST(APPEND HEADERS
3566 +        palm_system_webos.h
3567 +        web_app_wayland.h
3568 +        web_app_wayland_window.h
3569 +        web_app_window_impl.h
3570 +    )
3571 +endif()
3572 +
3573  if (OS_WEBOS)
3574      LIST(APPEND SOURCES
3575          ${WAM_ROOT_SOURCE_DIR}/webos/palm_service_base.cc
3576 diff --git a/src/platform/web_app_window.h b/src/platform/web_app_window.h
3577 index 7381b0c..a90127f 100644
3578 --- a/src/platform/web_app_window.h
3579 +++ b/src/platform/web_app_window.h
3580 @@ -20,8 +20,6 @@
3581  #include <string>
3582  #include <vector>
3583  
3584 -#include "webos/webapp_window_base.h"
3585 -
3586  class WebAppWayland;
3587  
3588  class WebAppWindow {
3589 @@ -32,12 +30,14 @@ class WebAppWindow {
3590    virtual int DisplayWidth() = 0;
3591    virtual int DisplayHeight() = 0;
3592    virtual void InitWindow(int width, int height) = 0;
3593 -  virtual void SetLocationHint(webos::WebAppWindowBase::LocationHint value) = 0;
3594 +  virtual void SetLocationHint(const std::string& value) = 0;
3595    virtual webos::NativeWindowState GetWindowHostState() const = 0;
3596 +#if defined(OS_WEBOS)
3597    virtual void CreateWindowGroup(
3598        const webos::WindowGroupConfiguration& config) = 0;
3599    virtual void AttachToWindowGroup(const std::string& name,
3600                                     const std::string& layer) = 0;
3601 +#endif
3602    virtual bool IsKeyboardVisible() = 0;
3603    virtual void SetKeyMask(webos::WebOSKeyMask key_mask) = 0;
3604    virtual void SetKeyMask(webos::WebOSKeyMask key_mask, bool set) = 0;
3605 diff --git a/src/util/log_msg_id.h b/src/util/log_msg_id.h
3606 index 7d114cf..71d9621 100644
3607 --- a/src/util/log_msg_id.h
3608 +++ b/src/util/log_msg_id.h
3609 @@ -150,6 +150,8 @@
3610  
3611  #define MSGID_DL_ERROR                  "DL_ERROR" /** Dinamic load library error **/
3612  
3613 +#define MSGID_ERROR_CANNOT_LOCK_SERVICE      "MSGID_CANNOT_LOCK_SERVICE" /** Cannot lock the GRPC IPC lock **/
3614 +
3615  // clang-format on
3616  
3617  #endif  // LOGMSGID_H
3618 diff --git a/src/util/timer.h b/src/util/timer.h
3619 index 795a38c..6824fb8 100644
3620 --- a/src/util/timer.h
3621 +++ b/src/util/timer.h
3622 @@ -30,12 +30,12 @@ class Timer {
3623        : source_id_(0), is_running_(false), is_repeating_(is_repeating) {}
3624    virtual ~Timer() {}
3625  
3626 -  // Timer
3627    virtual void HandleCallback() = 0;
3628 -  virtual void Start(int delay_in_milli_seconds);
3629  
3630    bool IsRunning() { return is_running_; }
3631    bool IsRepeating() { return is_repeating_; }
3632 +
3633 +  void Start(int delay_in_milli_seconds);
3634    void Stop();
3635  
3636   protected:
3637 diff --git a/src/wam_main.cc b/src/wam_main.cc
3638 index 0c04a40..d559ee4 100644
3639 --- a/src/wam_main.cc
3640 +++ b/src/wam_main.cc
3641 @@ -14,11 +14,9 @@
3642  //
3643  // SPDX-License-Identifier: Apache-2.0
3644  
3645 -#include <webos/app/webos_main.h>
3646 -
3647  #include "web_runtime.h"
3648  
3649 -int main(int argc, const char** argv) {
3650 +int main(int argc, char** argv) {
3651    std::unique_ptr<WebRuntime> web_runtime(WebRuntime::Create());
3652    return web_runtime->Run(argc, argv);
3653  }
3654 diff --git a/src/webos/web_app_manager_service_luna.cc b/src/webos/web_app_manager_service_luna.cc
3655 index 627cf31..b69635f 100644
3656 --- a/src/webos/web_app_manager_service_luna.cc
3657 +++ b/src/webos/web_app_manager_service_luna.cc
3658 @@ -632,6 +632,7 @@ void WebAppManagerServiceLuna::GetForegroundAppInfoCallback(
3659    if (cleared_cache_)
3660      cleared_cache_ = false;
3661  
3662 +#if defined(OS_WEBOS)
3663    if (reply["returnValue"] == true) {
3664      if (reply.isMember("appId") && reply["appId"].isString()) {
3665        std::string appId = reply["appId"].asString();
3666 @@ -639,6 +640,7 @@ void WebAppManagerServiceLuna::GetForegroundAppInfoCallback(
3667            WebAppManagerService::IsEnyoApp(appId.c_str()));
3668      }
3669    }
3670 +#endif
3671  }
3672  
3673  void WebAppManagerServiceLuna::BootdConnectCallback(const Json::Value& reply) {
3674 diff --git a/src/webos/web_runtime_webos.cc b/src/webos/web_runtime_webos.cc
3675 index 9dd2f72..cab7e5a 100644
3676 --- a/src/webos/web_runtime_webos.cc
3677 +++ b/src/webos/web_runtime_webos.cc
3678 @@ -70,7 +70,7 @@ class WebOSMainDelegateWAM : public webos::WebOSMainDelegate {
3679    void AboutToCreateContentBrowserClient() override { StartWebAppManager(); }
3680  };
3681  
3682 -int WebRuntimeWebOS::Run(int argc, const char** argv) {
3683 +int WebRuntimeWebOS::Run(int argc, char** argv) {
3684    WebOSMainDelegateWAM delegate;
3685    webos::WebOSMain webos_main(&delegate);
3686    return webOSMain.Run(argc, argv);
3687 diff --git a/src/webos/web_runtime_webos.h b/src/webos/web_runtime_webos.h
3688 index eb52348..fa031a2 100644
3689 --- a/src/webos/web_runtime_webos.h
3690 +++ b/src/webos/web_runtime_webos.h
3691 @@ -21,7 +21,7 @@
3692  
3693  class WebRuntimeWebOS : public WebRuntime {
3694   public:
3695 -  int Run(int argc, const char** argv) override;
3696 +  int Run(int argc, char** argv) override;
3697  };
3698  
3699  #endif  // WEBOS_WEB_RUNTIME_WEBOS_H_
3700 -- 
3701 2.39.2
3702