"src/browser/wrt_web_contents_view_delegate.h",
"src/browser/wrt_window_tree_host.cc",
"src/browser/wrt_window_tree_host.h",
+ "src/browser/wrt_xwalk_extension_browser.cc",
+ "src/browser/wrt_xwalk_extension_browser.h",
"src/common/api/wrt_api_base_object.cc",
"src/common/api/wrt_api_base_object.h",
"src/common/api/wrt_api_web_runtime_common.cc",
"xwalk_extensions/browser/xwalk_extension.h",
"xwalk_extensions/browser/xwalk_extension_manager.cc",
"xwalk_extensions/browser/xwalk_extension_manager.h",
+ "xwalk_extensions/common/xwalk_extension_browser_delegate.h",
"xwalk_extensions/renderer/native_module/object_tools_module.cc",
"xwalk_extensions/renderer/native_module/object_tools_module.h",
"xwalk_extensions/renderer/native_module/v8_tools_module.cc",
"src/browser/tv/wrt_browser_client_tv.h",
"src/browser/tv/wrt_native_window_tv.cc",
"src/browser/tv/wrt_native_window_tv.h",
+ "src/browser/tv/wrt_xwalk_extension_browser_tv.cc",
+ "src/browser/tv/wrt_xwalk_extension_browser_tv.h",
"src/common/tv/application_data_tv.cc",
"src/common/tv/application_data_tv.h",
"src/renderer/tv/wrt_renderer_client_tv.cc",
"src/renderer/tv/wrt_renderer_client_tv.h",
- "xwalk_extensions/browser/tv/xwalk_extension_manager_tv.cc",
- "xwalk_extensions/browser/tv/xwalk_extension_manager_tv.h",
]
wrt_lib_sources_da = [
#include "wrt/src/browser/tv/native_web_runtime_delegate_tv.h"
#include "wrt/src/browser/tv/wrt_browser_client_tv.h"
#include "wrt/src/browser/tv/wrt_native_window_tv.h"
+#include "wrt/src/browser/tv/wrt_xwalk_extension_browser_tv.h"
#include "wrt/src/browser/wrt_native_window.h"
#include "wrt/src/common/constants.h"
#include "wrt/src/common/locale_manager.h"
return false;
auto* extension_manager = XWalkExtensionManager::GetInstance();
- extension_manager->LoadExtensions(ApplicationData::AppType::UI);
+ extension_manager->LoadUIAppExtensions();
+ extension_manager->SetDelegate(std::make_unique<WRTXWalkExtensionBrowserTV>());
auto bin_path = base::CommandLine::ForCurrentProcess()->GetProgram();
if (bin_path.value() != kLoaderPath) {
#include "wrt/src/base/platform_info.h"
#include "wrt/src/browser/native_web_runtime.h"
#include "wrt/src/browser/wrt_browser_client.h"
+#include "wrt/src/browser/wrt_xwalk_extension_browser.h"
#include "wrt/src/common/api/wrt_api_web_runtime_common.h"
#include "wrt/src/common/application_data.h"
#include "wrt/src/common/constants.h"
bool WRTMainDelegate::PreSetup() {
auto* extension_manager = XWalkExtensionManager::GetInstance();
- extension_manager->LoadExtensions(ApplicationData::AppType::UI);
+ extension_manager->LoadUIAppExtensions();
+ extension_manager->SetDelegate(std::make_unique<WRTXWalkExtensionBrowser>());
+
auto bin_path = base::CommandLine::ForCurrentProcess()->GetProgram();
if (bin_path.value() == kLoaderPath) {
extension_manager->PreloadExtensions();
// TODO(kenshin.choi): This extends ui app extensions with ui service
// extensions. Please consider providing separate extension list to them.
- auto* extension_manager = wrt::XWalkExtensionManager::GetInstance();
- extension_manager->LoadExtensions(wrt::ApplicationData::AppType::SERVICE);
+ auto* extension_manager = XWalkExtensionManager::GetInstance();
+ extension_manager->LoadServiceAppExtensions();
const auto& extensions_map = extension_manager->GetExtensions();
std::vector<XWalkExtension*> extensions;
for (const auto& iter : extensions_map) {
ApplicationData::GetInstance().Initialize();
app_id_ = ApplicationData::GetInstance().app_id();
auto extension_manager = XWalkExtensionManager::GetInstance();
- extension_manager->ParseUpgradableExtensions();
extension_manager->RegisterUpgradableExtensions();
initialized_ = true;
}
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
- base::BindOnce(&XWalkExtensionManager::SetCachedPrivileges,
- base::Unretained(XWalkExtensionManager::GetInstance())));
+ base::BindOnce([]() {
+ XWalkExtensionManager::GetInstance()->SetCachedPrivileges();
+ }));
}
std::set<std::string> NativeWebRuntimeDelegateTV::GetPrivilegeCache() {
-// Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+// Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "wrt/xwalk_extensions/browser/tv/xwalk_extension_manager_tv.h"
+#include "wrt/src/browser/tv/wrt_xwalk_extension_browser_tv.h"
#include <dlfcn.h>
#include <fstream>
#include "wrt/src/browser/tv/native_web_runtime_delegate_tv.h"
#include "wrt/src/browser/tv/tv_window_manager.h"
#include "wrt/src/browser/tv/wrt_native_window_tv.h"
+#include "wrt/src/common/application_data.h"
#include "wrt/src/common/constants.h"
+#include "wrt/xwalk_extensions/browser/xwalk_extension_manager.h"
#ifndef XWALK_EXTENSION_PATH
#error XWALK_EXTENSION_PATH is not set.
namespace wrt {
-XWalkExtensionManagerTV::XWalkExtensionManagerTV() {
+WRTXWalkExtensionBrowserTV::WRTXWalkExtensionBrowserTV() {
preload_extensions_["widget"] =
XWALK_EXTENSION_PATH + std::string("/libwidget_plugin.so");
EarlyInitialization();
}
-bool XWalkExtensionManagerTV::OpenTizenCommonExntension() {
+bool WRTXWalkExtensionBrowserTV::OpenTizenCommonExntension() {
if (tizen_common_dlhandle_)
return true;
return true;
}
-void XWalkExtensionManagerTV::EarlyInitialization() {
+void WRTXWalkExtensionBrowserTV::EarlyInitialization() {
if (!OpenTizenCommonExntension())
return;
create_task_queue();
}
-void XWalkExtensionManagerTV::SetCachedPrivileges() {
+void WRTXWalkExtensionBrowserTV::SetCachedPrivileges() {
if (!OpenTizenCommonExntension())
return;
set_privilege(privilege.c_str());
}
-void XWalkExtensionManagerTV::LoadExtensions(
- wrt::ApplicationData::AppType app_type) {
- XWalkExtensionManager::LoadExtensions(app_type);
-
- // now just for UI webapp, will consider other type app later
- if (app_type == wrt::ApplicationData::AppType::UI)
- ParseUpgradableExtensions();
+void WRTXWalkExtensionBrowserTV::LoadUIAppExtensions() {
+ is_ui_app_ = true;
+ ParseUpgradableExtensions();
}
-std::string XWalkExtensionManagerTV::HandleRuntimeMessageInternal(
+std::string WRTXWalkExtensionBrowserTV::HandleRuntimeMessageInternal(
const std::string& type, const std::string& value) {
if (electron::Browser::Get()->is_quitting()) {
LOG(ERROR) << "App is quitting, handle runtime message is skipped";
}
if (type == "tizen://tvwindow/show") {
bool supported = true;
- if (wrt::TvWindowManager::GetInstance()->Show(supported))
+ if (TvWindowManager::GetInstance()->Show(supported))
return "success";
else
return supported ? "UnknownError" : "NotSupportedError";
} else if (type == "tizen://tvwindow/hide") {
- if (wrt::TvWindowManager::GetInstance()->Hide())
+ if (TvWindowManager::GetInstance()->Hide())
return "success";
else
return "UnknownError";
} else if (type == "tizen://tvwindow/reposition") {
- if (wrt::TvWindowManager::GetInstance()->RepositionTvWindow(value))
+ if (TvWindowManager::GetInstance()->RepositionTvWindow(value))
return "success";
else
return "UnknownError";
} else if (type == "tizen://api/inputdevice/registerKey") {
- if (!wrt::InputDeviceManager::GetInstance()->RegisterKey(value))
+ if (!InputDeviceManager::GetInstance()->RegisterKey(value))
return "error";
else
return "success";
} else if (type == "tizen://api/inputdevice/unregisterKey") {
- if (!wrt::InputDeviceManager::GetInstance()->UnregisterKey(value))
+ if (!InputDeviceManager::GetInstance()->UnregisterKey(value))
return "error";
else
return "success";
auto vector = base::SplitString(value, ",", base::KEEP_WHITESPACE,
base::SPLIT_WANT_ALL);
std::list<std::string> keylist(vector.begin(), vector.end());
- if (!wrt::InputDeviceManager::GetInstance()->RegisterKey(keylist))
+ if (!InputDeviceManager::GetInstance()->RegisterKey(keylist))
return "error";
else
return "success";
auto vector = base::SplitString(value, ",", base::KEEP_WHITESPACE,
base::SPLIT_WANT_ALL);
std::list<std::string> keylist(vector.begin(), vector.end());
- if (!wrt::InputDeviceManager::GetInstance()->UnregisterKey(keylist))
+ if (!InputDeviceManager::GetInstance()->UnregisterKey(keylist))
return "error";
else
return "success";
} else if (type == "tizen://api/systeminfo/getDisplayResolution") {
Json::Value response(Json::objectValue);
- Evas_Object* root_window = wrt::WRTNativeWindow::GetTopWindow();
+ Evas_Object* root_window = WRTNativeWindow::GetTopWindow();
if (root_window) {
int width, height;
evas_object_geometry_get(
builder["indentation"] = "";
return Json::writeString(builder, response);
} else if (type == "tizen://tvwindow/showCaptions") {
- return wrt::TvWindowManager::GetInstance()->ShowTextOnScreen(
- wrt::TvWindowManager::HostUGTextType::CAPTIONS);
+ return TvWindowManager::GetInstance()->ShowTextOnScreen(
+ TvWindowManager::HostUGTextType::CAPTIONS);
} else if (type == "tizen://tvwindow/hideCaptions") {
- return wrt::TvWindowManager::GetInstance()->HideTextOnScreen(
- wrt::TvWindowManager::HostUGTextType::CAPTIONS);
+ return TvWindowManager::GetInstance()->HideTextOnScreen(
+ TvWindowManager::HostUGTextType::CAPTIONS);
} else if (type == "tizen://tvwindow/showSubtitles") {
- return wrt::TvWindowManager::GetInstance()->ShowTextOnScreen(
- wrt::TvWindowManager::HostUGTextType::SUBTITLES);
+ return TvWindowManager::GetInstance()->ShowTextOnScreen(
+ TvWindowManager::HostUGTextType::SUBTITLES);
} else if (type == "tizen://tvwindow/hideSubtitles") {
- return wrt::TvWindowManager::GetInstance()->HideTextOnScreen(
- wrt::TvWindowManager::HostUGTextType::SUBTITLES);
+ return TvWindowManager::GetInstance()->HideTextOnScreen(
+ TvWindowManager::HostUGTextType::SUBTITLES);
} else if (type == "tizen://widgetQuarterPosition") {
- auto native_window_tv = wrt::WRTNativeWindowTV::GetMainNativeWindow();
+ auto native_window_tv = WRTNativeWindowTV::GetMainNativeWindow();
return (native_window_tv && native_window_tv->SetQuarterPosition(value)) ?
"success" : "failed";
} else if (type == "tizen://widgetWindowMove") {
- auto native_window_tv = wrt::WRTNativeWindowTV::GetMainNativeWindow();
+ auto native_window_tv = WRTNativeWindowTV::GetMainNativeWindow();
return (native_window_tv && native_window_tv->MoveWindow(value)) ?
"success" : "failed";
} else if (type == "tizen://widgetWindowResize") {
- auto native_window_tv = wrt::WRTNativeWindowTV::GetMainNativeWindow();
+ auto native_window_tv = WRTNativeWindowTV::GetMainNativeWindow();
return (native_window_tv && native_window_tv->ResizeWindow(value)) ?
"success" : "failed";
} else if (type == "tizen://downloadedWebapis") {
- auto& runtime_tv = wrt::NativeWebRuntimeDelegateTV::GetInstance();
+ auto& runtime_tv = NativeWebRuntimeDelegateTV::GetInstance();
return runtime_tv.GetUpgradeWebapiJsonContent();
} else if (type == "tizen://setSuspendDelay") {
auto delay = strtoul(value.c_str(), nullptr, 10);
LOG(INFO) << "tizen://setSuspendDelay : " << delay;
for (const auto& it : electron::WindowList::GetWindows()) {
- auto native_window_tv = static_cast<wrt::WRTNativeWindowTV*>(it);
+ auto native_window_tv = static_cast<WRTNativeWindowTV*>(it);
native_window_tv->SetSuspendDelay(delay);
}
return "success";
} else if (type == "tizen://enableFocus") {
- if (auto native_window_tv = wrt::WRTNativeWindowTV::GetMainNativeWindow()) {
+ if (auto native_window_tv = WRTNativeWindowTV::GetMainNativeWindow()) {
native_window_tv->SetUseFocus(true);
return "success";
}
return "failed";
} else if (type == "tizen://setTransparent") {
- if (auto native_window_tv = wrt::WRTNativeWindowTV::GetMainNativeWindow()) {
+ if (auto native_window_tv = WRTNativeWindowTV::GetMainNativeWindow()) {
native_window_tv->SetWindowAlpha(value == "true");
return "success";
}
} else if (type == "tizen://getGlobalResourceId") {
return std::to_string(WRTNativeWindowTV::GetGlobalResourceId());
} else {
- return XWalkExtensionManager::HandleRuntimeMessageInternal(type, value);
+ return WRTXWalkExtensionBrowser::HandleRuntimeMessageInternal(type, value);
}
}
-bool XWalkExtensionManagerTV::IsPreloadedExtension(std::string extension_name) {
+bool WRTXWalkExtensionBrowserTV::IsPreloadedExtension(std::string extension_name) {
return preload_extensions_.find(extension_name) != preload_extensions_.end();
}
-bool XWalkExtensionManagerTV::NeedHandleUpgradeWebapiJson() {
+bool WRTXWalkExtensionBrowserTV::NeedHandleUpgradeWebapiJson() {
auto upgrade_webapis_json_path =
- wrt::NativeWebRuntimeDelegateTV::GetInstance().GetUpgradeWebapiJsonPath();
+ NativeWebRuntimeDelegateTV::GetInstance().GetUpgradeWebapiJsonPath();
base::stat_wrapper_t file_stat;
if (base::File::Stat(upgrade_webapis_json_path.c_str(), &file_stat) == -1)
return true;
}
-void XWalkExtensionManagerTV::RegisterUpgradableExtensions() {
+void WRTXWalkExtensionBrowserTV::RegisterUpgradableExtensions() {
+ ParseUpgradableExtensions();
+
+ auto* extension_manager = XWalkExtensionManager::GetInstance();
+ const auto& extension_map = extension_manager->GetExtensions();
for (const auto& it : force_update_extensions_) {
auto name = it.first;
auto path = it.second;
auto entries = upgradable_extensions_entries_[name];
- if (!extensions_[name])
- RegisterExtension(new XWalkExtension(path, name, entries));
+ if (extension_map.find(name) == extension_map.end()) {
+ extension_manager->RegisterExtension(
+ new XWalkExtension(path, name, entries));
+ }
}
for (const auto& it : system_default_extensions_) {
auto name = it.first;
auto path = it.second;
auto entries = upgradable_extensions_entries_[name];
- if (!extensions_[name])
- RegisterExtension(new XWalkExtension(path, name, entries));
+ if (extension_map.find(name) == extension_map.end()) {
+ extension_manager->RegisterExtension(
+ new XWalkExtension(path, name, entries));
+ }
}
- auto pkg_id = wrt::ApplicationData::GetInstance().GetPackageID();
+ auto pkg_id = ApplicationData::GetInstance().GetPackageID();
for (const auto& it : upgradable_extensions_[pkg_id]) {
auto name = it.first;
auto path = it.second;
auto entries = upgradable_extensions_entries_[name];
- if (!extensions_[name])
- RegisterExtension(new XWalkExtension(path, name, entries));
+ if (extension_map.find(name) == extension_map.end()) {
+ extension_manager->RegisterExtension(
+ new XWalkExtension(path, name, entries));
+ }
}
}
-void XWalkExtensionManagerTV::ParseUpgradableExtensions() {
+void WRTXWalkExtensionBrowserTV::ParseUpgradableExtensions() {
if (!NeedHandleUpgradeWebapiJson())
return;
auto upgrade_webapis_json_path =
- wrt::NativeWebRuntimeDelegateTV::GetInstance().GetUpgradeWebapiJsonPath();
+ NativeWebRuntimeDelegateTV::GetInstance().GetUpgradeWebapiJsonPath();
std::ifstream upgrade_webapi_file(upgrade_webapis_json_path);
if (!upgrade_webapi_file.is_open()) {
}
upgradable_extensions_entries_[name] = std::move(entries);
- bool force_update = (item["forceupdate"].asString() == "true");
- if (force_update)
+ if (item["forceupdate"].asString() == "true")
force_update_extensions_[name] = item["path"].asString();
bool system = (item["system"].asString() == "true");
}
}
-std::string XWalkExtensionManagerTV::GetUpgradableLibPath(
+std::string WRTXWalkExtensionBrowserTV::GetUpgradableLibPath(
const std::string& name) {
- auto binpath = base::CommandLine::ForCurrentProcess()->GetProgram();
- if (wrt::ApplicationData::IsServiceApp() ||
- (kLoaderPath == binpath.value()))
+ if (!is_ui_app_)
return std::string();
if (!force_update_extensions_[name].empty())
return force_update_extensions_[name];
- auto pkg_id = wrt::ApplicationData::GetInstance().GetPackageID();
+ auto pkg_id = ApplicationData::GetInstance().GetPackageID();
if (!upgradable_extensions_[pkg_id].empty() &&
!upgradable_extensions_[pkg_id][name].empty())
return upgradable_extensions_[pkg_id][name];
return std::string();
}
-void XWalkExtensionManagerTV::PreloadExtensions() {
- XWalkExtensionManager::PreloadExtensions();
+void WRTXWalkExtensionBrowserTV::PreloadExtensions() {
+ WRTXWalkExtensionBrowser::PreloadExtensions();
for (auto& extension : lazyload_extensions_) {
LOG(INFO) << "preload name: " << extension.first
<< ",lib:" << extension.second;
void* dlhandle = dlopen(extension.second.c_str(), RTLD_LAZY);
- if (!dlhandle)
+ if (!dlhandle) {
LOG(WARNING) << "Fail to load libs : " << dlerror();
- else
- preload_handle_[extension.second] = dlhandle;
+ continue;
+ }
+ XWalkExtensionManager::GetInstance()->SetPreloadHandle(
+ extension.second, dlhandle);
}
}
-// Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+// Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef XWALK_EXTENSIONS_XWALK_EXTENSION_MANAGER_TV_H_
-#define XWALK_EXTENSIONS_XWALK_EXTENSION_MANAGER_TV_H_
+#ifndef BROWSER_TV_WRT_XWALK_EXTENSION_BROWSER_TV_H_
+#define BROWSER_TV_WRT_XWALK_EXTENSION_BROWSER_TV_H_
-#include "wrt/xwalk_extensions/browser/xwalk_extension_manager.h"
+#include <map>
+#include <vector>
+
+#include "base/time/time.h"
+#include "wrt/src/browser/wrt_xwalk_extension_browser.h"
namespace wrt {
-class XWalkExtensionManagerTV : public XWalkExtensionManager {
+class WRTXWalkExtensionBrowserTV : public WRTXWalkExtensionBrowser {
public:
- XWalkExtensionManagerTV();
- ~XWalkExtensionManagerTV() {}
+ WRTXWalkExtensionBrowserTV();
+ ~WRTXWalkExtensionBrowserTV() {}
private:
- // XWalkExtensionManager:
- void LoadExtensions(wrt::ApplicationData::AppType app_type) override;
+ // XWalkExtensionBrowserDelegate
+ void LoadUIAppExtensions() override;
void PreloadExtensions() override;
- void ParseUpgradableExtensions() override;
void RegisterUpgradableExtensions() override;
void SetCachedPrivileges() override;
std::string GetUpgradableLibPath(const std::string& name) override;
bool IsPreloadedExtension(std::string extension_name);
bool NeedHandleUpgradeWebapiJson();
bool OpenTizenCommonExntension();
+ void ParseUpgradableExtensions();
using ExtensionInfo = std::map<std::string, std::string>;
ExtensionInfo force_update_extensions_;
upgradable_extensions_entries_; // "name" : enties[]
base::Time upgrade_webapi_modified_time_;
void* tizen_common_dlhandle_ = nullptr;
+ bool is_ui_app_ = false;
std::map<std::string, std::string> lazyload_extensions_;
};
} // namespace wrt
-#endif // XWALK_EXTENSIONS_XWALK_EXTENSION_MANAGER_TV_H_
+#endif // BROWSER_TV_WRT_XWALK_EXTENSION_BROWSER_TV_H_
\ No newline at end of file
--- /dev/null
+// Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "wrt/src/browser/wrt_xwalk_extension_browser.h"
+
+#include <dlfcn.h>
+
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/navigation_entry.h"
+#include "electron/shell/browser/browser.h"
+#include "wrt/src/base/file_utils.h"
+#include "wrt/src/base/string_utils.h"
+#include "wrt/src/browser/native_web_runtime.h"
+#include "wrt/src/browser/splash_screen.h"
+#include "wrt/src/browser/wrt_browser_context.h"
+#include "wrt/src/browser/wrt_native_window.h"
+#include "wrt/src/browser/wrt_web_contents.h"
+#include "wrt/src/service/wrt_service_manager.h"
+#include "wrt/xwalk_extensions/browser/xwalk_extension_manager.h"
+
+#ifndef XWALK_EXTENSION_PATH
+ #error XWALK_EXTENSION_PATH is not set.
+#endif
+
+namespace wrt {
+
+WRTXWalkExtensionBrowser::WRTXWalkExtensionBrowser() {
+ preload_extensions_["tizen"] =
+ XWALK_EXTENSION_PATH + std::string("/libtizen.so");
+ preload_extensions_["common"] =
+ XWALK_EXTENSION_PATH + std::string("/libtizen_common.so");
+ preload_extensions_["tizen.application"] =
+ XWALK_EXTENSION_PATH + std::string("/libtizen_application.so");
+ preload_extensions_["xwalk"] =
+ XWALK_EXTENSION_PATH + std::string("/libtizen_utils.so");
+}
+
+void WRTXWalkExtensionBrowser::PreloadExtensions() {
+ for (auto& extension : preload_extensions_) {
+ LOG(INFO) << "preload name: " << extension.first
+ << ",lib:" << extension.second;
+ void* dlhandle = dlopen(extension.second.c_str(), RTLD_NOW | RTLD_GLOBAL);
+ if (!dlhandle) {
+ LOG(WARNING) << "Fail to load libs : " << dlerror();
+ continue;
+ }
+ XWalkExtensionManager::GetInstance()->SetPreloadHandle(
+ extension.second, dlhandle);
+ }
+}
+
+std::string WRTXWalkExtensionBrowser::HandleRuntimeMessageInternal(
+ const std::string& type, const std::string& value) {
+ if (electron::Browser::Get()->is_quitting()) {
+ LOG(ERROR) << "App is quitting, handle runtime message is skipped";
+ return std::string();
+ }
+ if (type == "tizen://hide") {
+ LOG(ERROR) << "tizen://hide";
+ auto native_window = WRTNativeWindow::GetMainNativeWindow();
+ if (native_window)
+ native_window->LowerWindow();
+ } else if (type == "tizen://exit") {
+ LOG(ERROR) << "tizen://exit";
+ NativeWebRuntime::GetInstance().RequestQuit();
+ } else if (type == "tizen://changeUA") {
+ for (auto* web_contents : content::WebContentsImpl::GetAllWebContents()) {
+ auto& controller = web_contents->GetController();
+ bool override = !value.empty();
+ for (int i = 0; i < controller.GetEntryCount(); ++i)
+ controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(override);
+#if BUILDFLAG(IS_TIZEN_TV)
+ web_contents->SetReloadByUserAgentChange(false);
+#endif
+ web_contents->SetUserAgentOverride(
+ blink::UserAgentOverride::UserAgentOnly(value), false);
+ }
+ return "lazy_success";
+ } else if (type == "tizen://deleteAllCookies") {
+ LOG(INFO) << "tizen://deleteAllCookies";
+ WRTBrowserContext::GetInstance()->DeleteCookies();
+ return "success";
+ } else if (type == "tizen://hide_splash_screen") {
+ LOG(INFO) << "tizen://hide_splash_screen";
+ std::vector<std::string> params = {"custom"};
+ NativeWebRuntime::GetInstance().NotifyMessage("hideSplashScreen", params);
+#if !defined(WRT_JS_BRINGUP)
+ } else if (type == "tizen://setAudioLatencyMode") {
+ LOG(INFO) << "tizen://setAudioLatencyMode - " << value;
+ int mode = content::BrowserContext::AudioLatencyMode::ERROR;
+ base::StringToInt(value, &mode);
+ WRTBrowserContext::GetInstance()->SetAudioLatencyMode(
+ static_cast<content::BrowserContext::AudioLatencyMode>(mode));
+ return "success";
+ } else if (type == "tizen://getAudioLatencyMode") {
+ auto mode = WRTBrowserContext::GetInstance()->GetAudioLatencyMode();
+ LOG(INFO) << "tizen://getAudioLatencyMode - " << mode;
+ return std::to_string(mode);
+#endif
+ } else {
+ LOG(ERROR) << "Unknown message type : " << type;
+ }
+ return std::string();
+}
+
+void WRTXWalkExtensionBrowser::GetRuntimeVariable(
+ const char* key, char* value, size_t value_len) {
+ if (!key || !value)
+ return;
+
+ std::string runtime_variable;
+ if (ApplicationData::IsServiceApp()) {
+ auto service_manager = WRTServiceManager::Get();
+ runtime_variable = service_manager->GetRuntimeVariable(key);
+ } else {
+ auto& runtime = NativeWebRuntime::GetInstance();
+ runtime_variable = runtime.GetRuntimeVariable(key);
+ }
+ if (!runtime_variable.empty())
+ strncpy(value, runtime_variable.c_str(), value_len);
+}
+
+} // namespace wrt
--- /dev/null
+// Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BROWSER_WRT_XWALK_EXTENSION_BROWSER_H_
+#define BROWSER_WRT_XWALK_EXTENSION_BROWSER_H_
+
+#include <map>
+
+#include "wrt/xwalk_extensions/common/xwalk_extension_browser_delegate.h"
+
+namespace wrt {
+
+class WRTXWalkExtensionBrowser : public XWalkExtensionBrowserDelegate {
+ public:
+ WRTXWalkExtensionBrowser();
+ ~WRTXWalkExtensionBrowser() {}
+
+ protected:
+ // XWalkExtensionBrowserDelegate
+ void GetRuntimeVariable(
+ const char* key, char* value, size_t value_len) override;
+ void PreloadExtensions() override;
+ std::string HandleRuntimeMessageInternal(
+ const std::string& type, const std::string& value) override;
+
+ std::map<std::string, std::string> preload_extensions_;
+};
+
+} // namespace wrt
+
+#endif // BROWSER_WRT_XWALK_EXTENSION_BROWSER_H_
\ No newline at end of file
#include "wrt/src/browser/tv/wrt_native_window_tv.h"
#include "wrt/src/browser/tv/widget_state.h"
#include "wrt/src/common/constants.h"
+#include "wrt/src/common/privilege.h"
+#include "wrt/xwalk_extensions/renderer/xwalk_extension_renderer_controller.h"
#if defined(TIZEN_PEPPER_EXTENSIONS)
#include "tizen_src/ewk/efl_integration/common/trusted_pepper_plugin_util.h"
void WRTRendererClientTV::RenderThreadStarted() {
WRTRendererClient::RenderThreadStarted();
+ XWalkExtensionRendererController::GetInstance().SetPrivilegeChecker(
+ base::BindRepeating(&privilege::CheckHostedAppPrivilege));
+
auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kApplicationType)) {
std::string type =
render_thread_observer_.reset(new RenderThreadObserverEfl(nullptr));
auto* thread = content::RenderThread::Get();
thread->AddObserver(render_thread_observer_.get());
+
+ if (ApplicationData::GetInstance().OffloadEnabled())
+ XWalkExtensionRendererController::GetInstance().SetOffloadEnable();
}
void WRTRendererClient::RenderFrameCreated(
return true;
LOG(INFO) << "XWalkExtension:Initialize";
+ auto* extension_manager = XWalkExtensionManager::GetInstance();
std::string library_path = library_path_;
-#if BUILDFLAG(IS_TIZEN_TV)
- auto upgradable_lib_path =
- XWalkExtensionManager::GetInstance()->GetUpgradableLibPath(name_);
+ auto upgradable_lib_path = extension_manager->GetUpgradableLibPath(name_);
if (!upgradable_lib_path.empty())
library_path = upgradable_lib_path;
-#endif
- handle_ = XWalkExtensionManager::GetInstance()->GetPreloadHandle(library_path);
+ handle_ = extension_manager->GetPreloadHandle(library_path);
if (!handle_) {
LOG(INFO) << "start dlopen path: " << library_path;
handle_ = dlopen(library_path.c_str(), RTLD_LAZY);
#include <glob.h>
#include <json/json.h>
#include <sys/utsname.h>
-#include <tzplatform_config.h>
#include <fstream>
#include "base/logging.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/navigation_entry.h"
-#include "electron/shell/browser/browser.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "wrt/src/base/file_utils.h"
-#include "wrt/src/base/string_utils.h"
-#include "wrt/src/browser/native_web_runtime.h"
-#include "wrt/src/browser/splash_screen.h"
-#include "wrt/src/browser/wrt_browser_context.h"
-#include "wrt/src/browser/wrt_native_window.h"
-#include "wrt/src/browser/wrt_web_contents.h"
-#include "wrt/src/service/wrt_service_manager.h"
#include "wrt/xwalk_extensions/browser/xwalk_extension.h"
-#if BUILDFLAG(IS_TIZEN_TV)
-#include "wrt/xwalk_extensions/browser/tv/xwalk_extension_manager_tv.h"
-#endif
-
#ifndef XWALK_EXTENSION_PATH
#error XWALK_EXTENSION_PATH is not set.
#endif
// static
XWalkExtensionManager* XWalkExtensionManager::GetInstance() {
-#if BUILDFLAG(IS_TIZEN_TV)
- static XWalkExtensionManagerTV self;
-#else
static XWalkExtensionManager self;
-#endif
return &self;
}
manager->receivers_.Add(manager, std::move(receiver));
}
-XWalkExtensionManager::XWalkExtensionManager() {
- preload_extensions_["tizen"] =
- XWALK_EXTENSION_PATH + std::string("/libtizen.so");
- preload_extensions_["common"] =
- XWALK_EXTENSION_PATH + std::string("/libtizen_common.so");
- preload_extensions_["tizen.application"] =
- XWALK_EXTENSION_PATH + std::string("/libtizen_application.so");
- preload_extensions_["xwalk"] =
- XWALK_EXTENSION_PATH + std::string("/libtizen_utils.so");
-}
-
-XWalkExtensionManager::~XWalkExtensionManager() {}
-
XWalkExtension::Instance* XWalkExtensionManager::GetExtensionInstance(
XW_Instance xw_instance) {
base::AutoLock lock(xmanager_instance_lock);
}
void XWalkExtensionManager::PreloadExtensions() {
- for (auto& extension : preload_extensions_) {
- LOG(INFO) << "preload name: " << extension.first
- << ",lib:" << extension.second;
- void* dlhandle = dlopen(extension.second.c_str(), RTLD_NOW | RTLD_GLOBAL);
- if (!dlhandle)
- LOG(WARNING) << "Fail to load libs : " << dlerror();
- else
- preload_handle_[extension.second] = dlhandle;
- }
+ if (delegate_)
+ delegate_->PreloadExtensions();
}
void XWalkExtensionManager::ClearPreloadHandle(const std::string& lib_path) {
return nullptr;
}
-void XWalkExtensionManager::LoadExtensions(
- wrt::ApplicationData::AppType app_type) {
- if (app_type != wrt::ApplicationData::AppType::SERVICE &&
- !is_loaded_for_web_app_)
- is_loaded_for_web_app_ = true;
- else if (!is_loaded_for_service_app_)
- is_loaded_for_service_app_ = true;
- else
+void XWalkExtensionManager::SetPreloadHandle(
+ const std::string& lib_path, void* handle) {
+ preload_handle_[lib_path] = handle;
+}
+
+void XWalkExtensionManager::LoadUIAppExtensions() {
+ if (is_loaded_for_web_app_)
return;
- std::string extension_path;
- if (app_type == wrt::ApplicationData::AppType::SERVICE)
- extension_path = XWALK_EXTENSION_SERVICE_PATH;
- else
- extension_path = XWALK_EXTENSION_PATH;
+ std::ignore = LoadExtensions(XWALK_EXTENSION_PATH);
+ if (delegate_)
+ delegate_->LoadUIAppExtensions();
+
+ is_loaded_for_web_app_ = true;
+}
+
+void XWalkExtensionManager::LoadServiceAppExtensions() {
+ if (is_loaded_for_service_app_)
+ return;
+
+ auto files = LoadExtensions(XWALK_EXTENSION_SERVICE_PATH);
+ for (auto it = files.begin(); it != files.end(); ++it) {
+ LOG(INFO) << "*it : " << *it;
+ RegisterExtension(new XWalkExtension(*it));
+ }
+
+ is_loaded_for_service_app_ = true;
+}
+
+std::set<std::string> XWalkExtensionManager::LoadExtensions(
+ const std::string& extension_path) {
LOG(INFO) << "extension_path : " << extension_path;
// Gets all extension files in the XWALK_EXTENSION_PATH
for (unsigned int i = 0; i < glob_result.gl_pathc; ++i)
ParseMetadata(glob_result.gl_pathv[i], &files, extension_path);
}
-
- // Load extensions in the remained files of the set 'files'
- if (app_type == wrt::ApplicationData::AppType::SERVICE) {
- for (auto it = files.begin(); it != files.end(); ++it)
- RegisterExtension(new XWalkExtension(*it));
- }
+ return files;
}
-void XWalkExtensionManager::LoadUserExtensions(const std::string app_path) {
+void XWalkExtensionManager::LoadUserExtensions(const std::string& app_path) {
if (app_path.empty()) {
LOG(ERROR) << "Failed to get package root path";
return;
std::string name = item["name"].asString();
std::string lib = item["lib"].asString();
- if (!wrt::utils::StartsWith(lib, "/"))
+ if (lib.substr(0, 1) != "/")
lib = extension_path + "/" + lib;
std::vector<std::string> entries;
HandleRuntimeAsyncMessageCallback callback) {
auto result = HandleRuntimeMessageInternal(type, value);
if (result == "lazy_success") {
- // FIXME(dh81.song): for the userAgent setting, this 'callback' has a timing
- // issue with renderer's perference actual update.
- // this 50ms delay is not a correct solution, this has to be solved with
- // more proper way.
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(
std::string XWalkExtensionManager::HandleRuntimeMessageInternal(
const std::string& type, const std::string& value) {
- if (electron::Browser::Get()->is_quitting()) {
- LOG(ERROR) << "App is quitting, handle runtime message is skipped";
- return std::string();
- }
- if (type == "tizen://hide") {
- LOG(ERROR) << "tizen://hide";
- auto native_window = wrt::WRTNativeWindow::GetMainNativeWindow();
- if (native_window)
- native_window->LowerWindow();
- } else if (type == "tizen://exit") {
- LOG(ERROR) << "tizen://exit";
- wrt::NativeWebRuntime::GetInstance().RequestQuit();
- } else if (type == "tizen://changeUA") {
- for (auto* web_contents : content::WebContentsImpl::GetAllWebContents()) {
- auto& controller = web_contents->GetController();
- bool override = !value.empty();
- for (int i = 0; i < controller.GetEntryCount(); ++i)
- controller.GetEntryAtIndex(i)->SetIsOverridingUserAgent(override);
-#if BUILDFLAG(IS_TIZEN_TV)
- web_contents->SetReloadByUserAgentChange(false);
-#endif
- web_contents->SetUserAgentOverride(
- blink::UserAgentOverride::UserAgentOnly(value), false);
- }
- return "lazy_success";
- } else if (type == "tizen://deleteAllCookies") {
- LOG(INFO) << "tizen://deleteAllCookies";
- wrt::WRTBrowserContext::GetInstance()->DeleteCookies();
- return "success";
- } else if (type == "tizen://hide_splash_screen") {
- LOG(INFO) << "tizen://hide_splash_screen";
- std::vector<std::string> params = {"custom"};
- wrt::NativeWebRuntime::GetInstance().NotifyMessage("hideSplashScreen", params);
-#if !defined(WRT_JS_BRINGUP)
- } else if (type == "tizen://setAudioLatencyMode") {
- LOG(INFO) << "tizen://setAudioLatencyMode - " << value;
- int mode = content::BrowserContext::AudioLatencyMode::ERROR;
- base::StringToInt(value, &mode);
- wrt::WRTBrowserContext::GetInstance()->SetAudioLatencyMode(
- static_cast<content::BrowserContext::AudioLatencyMode>(mode));
- return "success";
- } else if (type == "tizen://getAudioLatencyMode") {
- auto mode = wrt::WRTBrowserContext::GetInstance()->GetAudioLatencyMode();
- LOG(INFO) << "tizen://getAudioLatencyMode - " << mode;
- return std::to_string(mode);
-#endif
- } else {
- LOG(ERROR) << "Unknown message type : " << type;
- }
+ if (delegate_)
+ return delegate_->HandleRuntimeMessageInternal(type, value);
+
return std::string();
}
if (!key || !value)
return;
- std::string runtime_variable;
- if (wrt::ApplicationData::IsServiceApp()) {
- auto service_manager = wrt::WRTServiceManager::Get();
- runtime_variable = service_manager->GetRuntimeVariable(key);
- } else {
- auto& runtime = wrt::NativeWebRuntime::GetInstance();
- runtime_variable = runtime.GetRuntimeVariable(key);
- }
- if (!runtime_variable.empty())
- strncpy(value, runtime_variable.c_str(), value_len);
+ if (delegate_)
+ delegate_->GetRuntimeVariable(key, value, value_len);
+}
+
+std::string XWalkExtensionManager::GetUpgradableLibPath(
+ const std::string& name) {
+ return delegate_ ? delegate_->GetUpgradableLibPath(name) : std::string();
+}
+
+void XWalkExtensionManager::SetCachedPrivileges() {
+ if (delegate_)
+ delegate_->SetCachedPrivileges();
+}
+
+void XWalkExtensionManager::RegisterUpgradableExtensions() {
+ if (delegate_)
+ delegate_->RegisterUpgradableExtensions();
}
} // namespace wrt
#include <set>
#include <string>
-#include "base/synchronization/lock.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "wrt/src/common/application_data.h"
#include "wrt/xwalk_extensions/browser/xwalk_extension.h"
+#include "wrt/xwalk_extensions/common/xwalk_extension_browser_delegate.h"
#include "wrt/xwalk_extensions/common/xwalk_extension.mojom.h"
namespace content {
const ExtensionMap& GetExtensions() const { return extensions_; }
XWalkExtension::Instance* GetExtensionInstance(XW_Instance xw_instance);
-
- void GetRuntimeVariable(const char* key, char* value, size_t value_len);
- void LoadUserExtensions(const std::string app_path);
- void RegisterInstance(XWalkExtension::Instance* instance);
- void UnregisterInstance(XWalkExtension::Instance* instance);
-
- void PrepareShutdown();
- bool Shutdown();
-
- void ClearPreloadHandle(const std::string& lib_path);
void* GetPreloadHandle(const std::string& lib_path);
int32_t GetNextInstanceID();
+ bool Shutdown();
- virtual void PreloadExtensions();
- virtual void LoadExtensions(wrt::ApplicationData::AppType app_type);
- virtual void UnloadExtensions();
-
- // product specific functions
- virtual void ParseUpgradableExtensions() {}
- virtual void RegisterUpgradableExtensions() {}
- virtual void SetCachedPrivileges() {}
- virtual std::string GetUpgradableLibPath(const std::string& name) {
- return std::string();
+ void ClearPreloadHandle(const std::string& lib_path);
+ void GetRuntimeVariable(const char* key, char* value, size_t value_len);
+ void LoadUIAppExtensions();
+ void LoadServiceAppExtensions();
+ void LoadUserExtensions(const std::string& app_path);
+ void PreloadExtensions();
+ void PrepareShutdown();
+ void RegisterExtension(XWalkExtension* extension);
+ void RegisterInstance(XWalkExtension::Instance* instance);
+ void SetDelegate(std::unique_ptr<XWalkExtensionBrowserDelegate> delegate) {
+ delegate_ = std::move(delegate);
}
+ void SetPreloadHandle(const std::string& lib_path, void* handle);
+ void UnloadExtensions();
+ void UnregisterInstance(XWalkExtension::Instance* instance);
+
+ // product specific features
+ void RegisterUpgradableExtensions();
+ void SetCachedPrivileges();
+ std::string GetUpgradableLibPath(const std::string& name);
protected:
- XWalkExtensionManager();
- virtual ~XWalkExtensionManager();
+ XWalkExtensionManager() {}
+ virtual ~XWalkExtensionManager() {}
- bool ValidateSymbols(XWalkExtension* extension);
- void RegisterExtension(XWalkExtension* extension);
+ std::set<std::string> LoadExtensions(const std::string& extension_path);
void ParseMetadata(const std::string& meta_path,
std::set<std::string>* files,
std::string extension_path);
+ bool ValidateSymbols(XWalkExtension* extension);
// mojom::XWalkExtensionBrowser
void AddRenderer(mojo::PendingRemote<mojom::XWalkExtensionRenderer> remote,
bool is_loaded_for_web_app_ = false;
std::map<int32_t, std::unique_ptr<XWalkExtension::Instance>> instances_;
-
std::set<std::string> extension_symbols_;
ExtensionMap extensions_;
std::map<std::string, void*> preload_handle_;
std::map<mojo::ReceiverId, mojo::Remote<mojom::XWalkExtensionRenderer>>
renderers_;
- std::map<std::string, std::string> preload_extensions_;
+ std::unique_ptr<XWalkExtensionBrowserDelegate> delegate_;
};
} // namespace wrt
--- /dev/null
+// Copyright (c) 2023 Samsung Electronics Co., Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_EXTENSION_BROWSER_DELEGATE_H_
+#define XWALK_EXTENSION_BROWSER_DELEGATE_H_
+
+#include <string>
+
+namespace wrt {
+
+class XWalkExtensionBrowserDelegate {
+ public:
+ XWalkExtensionBrowserDelegate() {}
+ virtual ~XWalkExtensionBrowserDelegate() {}
+
+ virtual void GetRuntimeVariable(
+ const char* key, char* value, size_t value_len) {}
+ virtual void LoadUIAppExtensions() {}
+ virtual void PreloadExtensions() {}
+ virtual std::string HandleRuntimeMessageInternal(
+ const std::string& type, const std::string& value) {
+ return {};
+ }
+
+ // product specific functions
+ virtual void RegisterUpgradableExtensions() {}
+ virtual void SetCachedPrivileges() {}
+ virtual std::string GetUpgradableLibPath(const std::string& name) {
+ return std::string();
+ }
+};
+
+} // namespace wrt
+
+#endif // XWALK_EXTENSION_BROWSER_DELEGATE_H_
#include "wrt/xwalk_extensions/renderer/xwalk_extension_renderer_controller.h"
#include "base/logging.h"
+#include "base/no_destructor.h"
#include "base/strings/string_util.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_thread.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
-#include "wrt/src/base/profiler.h"
-#include "wrt/src/common/application_data.h"
-#include "wrt/src/renderer/wrt_render_frame_observer.h"
#include "wrt/xwalk_extensions/renderer/native_module/object_tools_module.h"
#include "wrt/xwalk_extensions/renderer/native_module/v8_tools_module.h"
#include "wrt/xwalk_extensions/renderer/native_module/widget_module.h"
#include "wrt/xwalk_extensions/renderer/xwalk_extension_context_data.h"
#include "wrt/xwalk_extensions/renderer/xwalk_extension_module.h"
-#if BUILDFLAG(IS_TIZEN_TV)
-#include "wrt/src/common/privilege.h"
-#endif
-
namespace wrt {
// static
return *static_cast<XWalkExtensionRendererController*>(instance->Get());
}
-XWalkExtensionRendererController::XWalkExtensionRendererController() = default;
-
XWalkExtensionRendererController::~XWalkExtensionRendererController() {
if (!instance_map_.empty())
LOG(ERROR) << "Instances are remained : " << instance_map_.size();
void XWalkExtensionRendererController::Initialize(
blink::ExecutionContext* execution_context) {
- SCOPE_PROFILE();
if (!description_map_.empty())
return;
{
auto it = description_map_.find("offload");
if (it != description_map_.end()) {
- if (wrt::ApplicationData::GetInstance().OffloadEnabled()) {
+ if (offload_enabled_) {
it->second.use_trampoline_ = false;
offload_desc_ = std::unique_ptr<XWalkExtensionDescription>(
new XWalkExtensionDescription(it->second));
// static
void XWalkExtensionRendererController::DidCreateScriptContext(
v8::Local<v8::Context> context) {
- SCOPE_PROFILE();
-
// Initialize context's aligned pointer in embedder data with nullptr
// This should be handled even if 'is_shutdown_' = true, otherise,
// GetAlignedPointerFromEmbedderData can give invalid uninitialized memory.
return;
auto* execution_context = blink::ExecutionContext::From(context);
- if (execution_context->Url().ProtocolIsInHTTPFamily()
-#if BUILDFLAG(IS_TIZEN_TV)
- && !wrt::privilege::CheckHostedAppPrivilege()
-#endif
- ) {
- LOG(ERROR) << "External url not allowed plugin loading.";
- return;
+ if (execution_context->Url().ProtocolIsInHTTPFamily()) {
+ auto privilege_checker = GetInstance().privilege_checker_;
+ if (privilege_checker.is_null() || !privilege_checker.Run()) {
+ LOG(ERROR) << "External url not allowed plugin loading.";
+ return;
+ }
}
if (execution_context->IsServiceWorkerGlobalScope()) {
void PostMessage(int32_t id, const std::string& message);
void PostBinaryMessage(
int32_t id, const std::vector<uint8_t>& message);
+ void SetOffloadEnable() { offload_enabled_ = true; }
+ void SetPrivilegeChecker(
+ const base::RepeatingCallback<bool()>& checker) {
+ privilege_checker_ = checker;
+ }
std::string SendSyncMessageWithStringReply(
int32_t id, const std::string& message);
ReplyCallback callback);
private:
- XWalkExtensionRendererController();
+ XWalkExtensionRendererController() {}
virtual ~XWalkExtensionRendererController();
void Initialize(blink::ExecutionContext* execution_context);
mojo::Receiver<mojom::XWalkExtensionRenderer> receiver_{this};
absl::optional<uint64_t> receiver_id_;
mojo::Remote<mojom::XWalkExtensionBrowser> browser_;
+ bool offload_enabled_ = false;
+ base::RepeatingCallback<bool()> privilege_checker_;
};
} // namespace wrt