diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md index fb9a35d18..2343ecba1 100644 --- a/packages/webview_flutter/CHANGELOG.md +++ b/packages/webview_flutter/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Code refactoring. + ## 0.4.4 * Update LWE binary (645719ed084d899ec7d53de1758db71a8974e446). diff --git a/packages/webview_flutter/tizen/src/buffer_pool.cc b/packages/webview_flutter/tizen/src/buffer_pool.cc index 4ff76f981..e69e20ba9 100644 --- a/packages/webview_flutter/tizen/src/buffer_pool.cc +++ b/packages/webview_flutter/tizen/src/buffer_pool.cc @@ -6,15 +6,7 @@ #include "log.h" -BufferUnit::BufferUnit(int index, int width, int height) - : isUsed_(false), - index_(index), - width_(0), - height_(0), - tbm_surface_(nullptr), - gpu_buffer_(nullptr) { - Reset(width, height); -} +BufferUnit::BufferUnit(int32_t width, int32_t height) { Reset(width, height); } BufferUnit::~BufferUnit() { if (tbm_surface_) { @@ -28,18 +20,14 @@ BufferUnit::~BufferUnit() { } bool BufferUnit::MarkInUse() { - if (!isUsed_) { - isUsed_ = true; + if (!is_used_) { + is_used_ = true; return true; } return false; } -FlutterDesktopGpuBuffer* BufferUnit::GpuBuffer() { return gpu_buffer_; } - -int BufferUnit::Index() { return index_; } - -bool BufferUnit::IsUsed() { return isUsed_ && tbm_surface_; } +void BufferUnit::UnmarkInUse() { is_used_ = false; } tbm_surface_h BufferUnit::Surface() { if (IsUsed()) { @@ -48,14 +36,13 @@ tbm_surface_h BufferUnit::Surface() { return nullptr; } -void BufferUnit::UnmarkInUse() { isUsed_ = false; } - -void BufferUnit::Reset(int width, int height) { +void BufferUnit::Reset(int32_t width, int32_t height) { if (width_ == width && height_ == height) { return; } width_ = width; height_ = height; + if (tbm_surface_) { tbm_surface_destroy(tbm_surface_); tbm_surface_ = nullptr; @@ -64,21 +51,22 @@ void BufferUnit::Reset(int width, int height) { delete gpu_buffer_; gpu_buffer_ = nullptr; } + tbm_surface_ = tbm_surface_create(width_, height_, TBM_FORMAT_ARGB8888); gpu_buffer_ = new FlutterDesktopGpuBuffer(); gpu_buffer_->width = width_; gpu_buffer_->height = height_; gpu_buffer_->buffer = tbm_surface_; gpu_buffer_->release_callback = [](void* release_context) { - BufferUnit* bu = (BufferUnit*)release_context; - bu->UnmarkInUse(); + BufferUnit* buffer = reinterpret_cast(release_context); + buffer->UnmarkInUse(); }; gpu_buffer_->release_context = this; } -BufferPool::BufferPool(int width, int height, int pool_size) : last_index_(0) { - for (int idx = 0; idx < pool_size; idx++) { - pool_.emplace_back(new BufferUnit(idx, width, height)); +BufferPool::BufferPool(int32_t width, int32_t height, size_t pool_size) { + for (size_t index = 0; index < pool_size; index++) { + pool_.emplace_back(std::make_unique(width, height)); } Prepare(width, height); } @@ -87,8 +75,8 @@ BufferPool::~BufferPool() {} BufferUnit* BufferPool::GetAvailableBuffer() { std::lock_guard lock(mutex_); - for (int idx = 0; idx < pool_.size(); idx++) { - int current = (idx + last_index_) % pool_.size(); + for (size_t index = 0; index < pool_.size(); index++) { + size_t current = (index + last_index_) % pool_.size(); BufferUnit* buffer = pool_[current].get(); if (buffer->MarkInUse()) { last_index_ = current; @@ -98,46 +86,47 @@ BufferUnit* BufferPool::GetAvailableBuffer() { return nullptr; } -void BufferPool::Release(BufferUnit* unit) { +void BufferPool::Release(BufferUnit* buffer) { std::lock_guard lock(mutex_); - unit->UnmarkInUse(); + buffer->UnmarkInUse(); } -void BufferPool::Prepare(int width, int height) { +void BufferPool::Prepare(int32_t width, int32_t height) { std::lock_guard lock(mutex_); - for (int idx = 0; idx < pool_.size(); idx++) { - BufferUnit* buffer = pool_[idx].get(); + for (size_t index = 0; index < pool_.size(); index++) { + BufferUnit* buffer = pool_[index].get(); buffer->Reset(width, height); } } -SingleBufferPool::SingleBufferPool(int width, int height) +SingleBufferPool::SingleBufferPool(int32_t width, int32_t height) : BufferPool(width, height, 1) {} SingleBufferPool::~SingleBufferPool() {} BufferUnit* SingleBufferPool::GetAvailableBuffer() { - pool_[0].get()->MarkInUse(); - return pool_[0].get(); + BufferUnit* buffer = pool_[0].get(); + buffer->MarkInUse(); + return buffer; } -void SingleBufferPool::Release(BufferUnit* unit) {} +void SingleBufferPool::Release(BufferUnit* buffer) {} #ifndef NDEBUG #include void BufferUnit::DumpToPng(int file_name) { - char filePath[256]; - sprintf(filePath, "/tmp/dump%d.png", file_name); - tbm_surface_info_s surfaceInfo; - tbm_surface_map(tbm_surface_, TBM_SURF_OPTION_WRITE, &surfaceInfo); - void* buffer = surfaceInfo.planes[0].ptr; - - cairo_surface_t* png_buffer; - png_buffer = cairo_image_surface_create_for_data( - (unsigned char*)buffer, CAIRO_FORMAT_ARGB32, width_, height_, - surfaceInfo.planes[0].stride); - - cairo_surface_write_to_png(png_buffer, filePath); + char file_path[256]; + sprintf(file_path, "/tmp/dump%d.png", file_name); + + tbm_surface_info_s surface_info; + tbm_surface_map(tbm_surface_, TBM_SURF_OPTION_WRITE, &surface_info); + + unsigned char* buffer = surface_info.planes[0].ptr; + cairo_surface_t* png_buffer = cairo_image_surface_create_for_data( + buffer, CAIRO_FORMAT_ARGB32, width_, height_, + surface_info.planes[0].stride); + + cairo_surface_write_to_png(png_buffer, file_path); tbm_surface_unmap(tbm_surface_); cairo_surface_destroy(png_buffer); diff --git a/packages/webview_flutter/tizen/src/buffer_pool.h b/packages/webview_flutter/tizen/src/buffer_pool.h index 549510ba1..66d4fefc3 100644 --- a/packages/webview_flutter/tizen/src/buffer_pool.h +++ b/packages/webview_flutter/tizen/src/buffer_pool.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEBVIEW_BUFFER_POOL_H_ -#define FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEBVIEW_BUFFER_POOL_H_ +#ifndef FLUTTER_PLUGIN_BUFFER_POOL_H_ +#define FLUTTER_PLUGIN_BUFFER_POOL_H_ #include #include @@ -14,52 +14,58 @@ class BufferUnit { public: - explicit BufferUnit(int index, int width, int height); + explicit BufferUnit(int32_t width, int32_t height); ~BufferUnit(); - void Reset(int width, int height); + + void Reset(int32_t width, int32_t height); + bool MarkInUse(); void UnmarkInUse(); - int Index(); - bool IsUsed(); + + bool IsUsed() { return is_used_ && tbm_surface_; } + tbm_surface_h Surface(); - FlutterDesktopGpuBuffer* GpuBuffer(); + + FlutterDesktopGpuBuffer* GpuBuffer() { return gpu_buffer_; } + #ifndef NDEBUG + // TODO: Unused code. void DumpToPng(int file_name); #endif private: - bool isUsed_; - int index_; - int width_; - int height_; - tbm_surface_h tbm_surface_; - FlutterDesktopGpuBuffer* gpu_buffer_; + bool is_used_ = false; + int32_t width_ = 0; + int32_t height_ = 0; + tbm_surface_h tbm_surface_ = nullptr; + FlutterDesktopGpuBuffer* gpu_buffer_ = nullptr; }; class BufferPool { public: - explicit BufferPool(int width, int height, int pool_size); + explicit BufferPool(int32_t width, int32_t height, size_t pool_size); virtual ~BufferPool(); virtual BufferUnit* GetAvailableBuffer(); - virtual void Release(BufferUnit* unit); - void Prepare(int with, int height); + virtual void Release(BufferUnit* buffer); + + void Prepare(int32_t with, int32_t height); protected: std::vector> pool_; private: - int last_index_; + size_t last_index_ = 0; std::mutex mutex_; }; class SingleBufferPool : public BufferPool { public: - explicit SingleBufferPool(int width, int height); + explicit SingleBufferPool(int32_t width, int32_t height); ~SingleBufferPool(); - virtual BufferUnit* GetAvailableBuffer(); - virtual void Release(BufferUnit* unit); + virtual BufferUnit* GetAvailableBuffer() override; + virtual void Release(BufferUnit* buffer) override; }; -#endif +#endif // FLUTTER_PLUGIN_BUFFER_POOL_H_ diff --git a/packages/webview_flutter/tizen/src/webview.cc b/packages/webview_flutter/tizen/src/webview.cc index df91cab80..94683cbee 100644 --- a/packages/webview_flutter/tizen/src/webview.cc +++ b/packages/webview_flutter/tizen/src/webview.cc @@ -19,7 +19,7 @@ #include "lwe/PlatformIntegrationData.h" #include "webview_factory.h" -#define BUFFER_POOL_SIZE 5 +static constexpr size_t kBufferPoolSize = 5; extern "C" size_t LWE_EXPORT createWebViewInstance( unsigned x, unsigned y, unsigned width, unsigned height, @@ -30,13 +30,13 @@ extern "C" size_t LWE_EXPORT createWebViewInstance( const std::function& flushCb, bool useSWBackend); -template -class NavigationRequestResult : public flutter::MethodResult { +class NavigationRequestResult + : public flutter::MethodResult { public: NavigationRequestResult(std::string url, WebView* webview) : url_(url), webview_(webview) {} - void SuccessInternal(const T* should_load) override { + void SuccessInternal(const flutter::EncodableValue* should_load) override { if (std::holds_alternative(*should_load)) { if (std::get(*should_load)) { LoadUrl(); @@ -46,14 +46,12 @@ class NavigationRequestResult : public flutter::MethodResult { void ErrorInternal(const std::string& error_code, const std::string& error_message, - const T* error_details) override { - throw std::invalid_argument("navigationRequest calls must succeed [code:" + - error_code + "][msg:" + error_message + "]"); + const flutter::EncodableValue* error_details) override { + LOG_ERROR("The request unexpectedly completed with an error."); } void NotImplementedInternal() override { - throw std::invalid_argument( - "navigationRequest must be implemented by the webview method channel"); + LOG_ERROR("The target method was unexpectedly unimplemented."); } private: @@ -67,7 +65,7 @@ class NavigationRequestResult : public flutter::MethodResult { WebView* webview_; }; -enum RequestErrorType { +enum class ResourceErrorType { NoError, UnknownError, HostLookupError, @@ -87,52 +85,51 @@ enum RequestErrorType { }; static std::string ErrorCodeToString(int error_code) { - switch (error_code) { - case RequestErrorType::AuthenticationError: + switch (ResourceErrorType(error_code)) { + case ResourceErrorType::AuthenticationError: return "authentication"; - case RequestErrorType::BadURLError: + case ResourceErrorType::BadURLError: return "badUrl"; - case RequestErrorType::ConnectError: + case ResourceErrorType::ConnectError: return "connect"; - case RequestErrorType::FailedSSLHandshakeError: + case ResourceErrorType::FailedSSLHandshakeError: return "failedSslHandshake"; - case RequestErrorType::FileError: + case ResourceErrorType::FileError: return "file"; - case RequestErrorType::FileNotFoundError: + case ResourceErrorType::FileNotFoundError: return "fileNotFound"; - case RequestErrorType::HostLookupError: + case ResourceErrorType::HostLookupError: return "hostLookup"; - case RequestErrorType::IOError: + case ResourceErrorType::IOError: return "io"; - case RequestErrorType::ProxyAuthenticationError: + case ResourceErrorType::ProxyAuthenticationError: return "proxyAuthentication"; - case RequestErrorType::RedirectLoopError: + case ResourceErrorType::RedirectLoopError: return "redirectLoop"; - case RequestErrorType::TimeoutError: + case ResourceErrorType::TimeoutError: return "timeout"; - case RequestErrorType::TooManyRequestError: + case ResourceErrorType::TooManyRequestError: return "tooManyRequests"; - case RequestErrorType::UnknownError: + case ResourceErrorType::UnknownError: return "unknown"; - case RequestErrorType::UnsupportedAuthSchemeError: + case ResourceErrorType::UnsupportedAuthSchemeError: return "unsupportedAuthScheme"; - case RequestErrorType::UnsupportedSchemeError: + case ResourceErrorType::UnsupportedSchemeError: return "unsupportedScheme"; + default: + LOG_ERROR("Unknown error type: %d", error_code); + return std::to_string(error_code); } - - std::string message = - "Could not find a string for errorCode: " + std::to_string(error_code); - throw std::invalid_argument(message); } template -bool GetValueFromEncodableMap(const flutter::EncodableValue& arguments, - std::string key, T* out) { - if (auto pmap = std::get_if(&arguments)) { - auto iter = pmap->find(flutter::EncodableValue(key)); - if (iter != pmap->end() && !iter->second.IsNull()) { - if (auto pval = std::get_if(&iter->second)) { - *out = *pval; +static bool GetValueFromEncodableMap(const flutter::EncodableValue* arguments, + std::string key, T* out) { + if (auto* map = std::get_if(arguments)) { + auto iter = map->find(flutter::EncodableValue(key)); + if (iter != map->end() && !iter->second.IsNull()) { + if (auto* value = std::get_if(&iter->second)) { + *out = *value; return true; } } @@ -140,12 +137,12 @@ bool GetValueFromEncodableMap(const flutter::EncodableValue& arguments, return false; } -bool NeedsSwBackend(void) { +static bool IsRunningOnEmulator() { bool result = false; char* value = nullptr; int ret = system_info_get_platform_string( "http://tizen.org/system/model_name", &value); - if ((SYSTEM_INFO_ERROR_NONE == ret) && (0 == strcmp(value, "Emulator"))) { + if (ret == SYSTEM_INFO_ERROR_NONE && strcmp(value, "Emulator") == 0) { result = true; } if (value) { @@ -154,34 +151,28 @@ bool NeedsSwBackend(void) { return result; } -WebView::WebView(flutter::PluginRegistrar* registrar, int viewId, +WebView::WebView(flutter::PluginRegistrar* registrar, int view_id, flutter::TextureRegistrar* texture_registrar, double width, - double height, flutter::EncodableMap& params) - : PlatformView(registrar, viewId, nullptr), + double height, const flutter::EncodableValue& params) + : PlatformView(registrar, view_id, nullptr), texture_registrar_(texture_registrar), - webview_instance_(nullptr), width_(width), - height_(height), - working_surface_(nullptr), - candidate_surface_(nullptr), - rendered_surface_(nullptr), - is_mouse_lbutton_down_(false), - has_navigation_delegate_(false), - has_progress_tracking_(false), - context_(nullptr), - texture_variant_(nullptr) { - use_sw_backend_ = NeedsSwBackend(); + height_(height) { + use_sw_backend_ = IsRunningOnEmulator(); if (use_sw_backend_) { tbm_pool_ = std::make_unique(width, height); } else { - tbm_pool_ = std::make_unique(width, height, BUFFER_POOL_SIZE); + tbm_pool_ = std::make_unique(width, height, kBufferPoolSize); } - texture_variant_ = new flutter::TextureVariant(flutter::GpuBufferTexture( - [this](size_t width, size_t height) -> const FlutterDesktopGpuBuffer* { - return this->ObtainGpuBuffer(width, height); - })); - SetTextureId(texture_registrar_->RegisterTexture(texture_variant_)); + texture_variant_ = + std::make_unique(flutter::GpuBufferTexture( + [this](size_t width, + size_t height) -> const FlutterDesktopGpuBuffer* { + return ObtainGpuBuffer(width, height); + })); + SetTextureId(texture_registrar_->RegisterTexture(texture_variant_.get())); + InitWebView(); channel_ = std::make_unique>( @@ -203,164 +194,130 @@ WebView::WebView(flutter::PluginRegistrar* registrar, int viewId, }); std::string url; - auto initial_url = params[flutter::EncodableValue("initialUrl")]; - if (std::holds_alternative(initial_url)) { - url = std::get(initial_url); - } else { + if (!GetValueFromEncodableMap(¶ms, "initialUrl", &url)) { url = "about:blank"; } - auto backgroundColor = params[flutter::EncodableValue("backgroundColor")]; - if (std::holds_alternative(backgroundColor)) { - auto color = std::get(backgroundColor); - auto settings = webview_instance_->GetSettings(); + int color; + if (GetValueFromEncodableMap(¶ms, "backgroundColor", &color)) { + LWE::Settings settings = webview_instance_->GetSettings(); settings.SetBaseBackgroundColor(color >> 16 & 0xff, color >> 8 & 0xff, color & 0xff, color >> 24 & 0xff); webview_instance_->SetSettings(settings); } - auto settings = params[flutter::EncodableValue("settings")]; - if (std::holds_alternative(settings)) { - auto settingList = std::get(settings); - if (settingList.size() > 0) { - ApplySettings(settingList); - } + flutter::EncodableMap settings; + if (GetValueFromEncodableMap(¶ms, "settings", &settings)) { + ApplySettings(settings); } - auto names = params[flutter::EncodableValue("javascriptChannelNames")]; - if (std::holds_alternative(names)) { - auto name_list = std::get(names); - for (size_t i = 0; i < name_list.size(); i++) { - if (std::holds_alternative(name_list[i])) { - RegisterJavaScriptChannelName(std::get(name_list[i])); + flutter::EncodableList names; + if (GetValueFromEncodableMap(¶ms, "javascriptChannelNames", &names)) { + for (flutter::EncodableValue name : names) { + if (std::holds_alternative(name)) { + RegisterJavaScriptChannelName(std::get(name)); } } } - // TODO: Not implemented - // auto media = params[flutter::EncodableValue("autoMediaPlaybackPolicy")]; + // TODO: Implement autoMediaPlaybackPolicy. - auto user_agent = params[flutter::EncodableValue("userAgent")]; - if (std::holds_alternative(user_agent)) { - auto settings = webview_instance_->GetSettings(); - settings.SetUserAgentString(std::get(user_agent)); + std::string user_agent; + if (GetValueFromEncodableMap(¶ms, "userAgent", &user_agent)) { + LWE::Settings settings = webview_instance_->GetSettings(); + settings.SetUserAgentString(user_agent); webview_instance_->SetSettings(settings); } webview_instance_->RegisterOnPageStartedHandler( [this](LWE::WebContainer* container, const std::string& url) { - LOG_DEBUG("RegisterOnPageStartedHandler(url: %s)\n", url.c_str()); - flutter::EncodableMap map; - map.insert( - std::make_pair( - flutter::EncodableValue("url"), flutter::EncodableValue(url))); - auto args = std::make_unique(map); - channel_->InvokeMethod("onPageStarted", std::move(args)); + flutter::EncodableMap args = { + {flutter::EncodableValue("url"), flutter::EncodableValue(url)}}; + channel_->InvokeMethod("onPageStarted", + std::make_unique(args)); }); webview_instance_->RegisterOnPageLoadedHandler( [this](LWE::WebContainer* container, const std::string& url) { - LOG_DEBUG("RegisterOnPageLoadedHandler(url: %s)(title:%s)\n", - url.c_str(), container->GetTitle().c_str()); - flutter::EncodableMap map; - map.insert( - std::make_pair( - flutter::EncodableValue("url"), flutter::EncodableValue(url))); - auto args = std::make_unique(map); - channel_->InvokeMethod("onPageFinished", std::move(args)); + flutter::EncodableMap args = { + {flutter::EncodableValue("url"), flutter::EncodableValue(url)}}; + channel_->InvokeMethod("onPageFinished", + std::make_unique(args)); }); webview_instance_->RegisterOnProgressChangedHandler( [this](LWE::WebContainer* container, int progress) { - LOG_DEBUG("RegisterOnProgressChangedHandler(progress:%d)\n", progress); if (!has_progress_tracking_) { return; } - flutter::EncodableMap map; - map.insert( - std::make_pair( - flutter::EncodableValue("progress"), - flutter::EncodableValue(progress))); - auto args = std::make_unique(map); - channel_->InvokeMethod("onProgress", std::move(args)); + flutter::EncodableMap args = {{flutter::EncodableValue("progress"), + flutter::EncodableValue(progress)}}; + channel_->InvokeMethod("onProgress", + std::make_unique(args)); }); webview_instance_->RegisterOnReceivedErrorHandler( - [this](LWE::WebContainer* container, LWE::ResourceError e) { - flutter::EncodableMap map; - map.insert( - std::make_pair( - flutter::EncodableValue("errorCode"), - flutter::EncodableValue(e.GetErrorCode()))); - map.insert( - std::make_pair( - flutter::EncodableValue("description"), - flutter::EncodableValue(e.GetDescription()))); - map.insert( - std::make_pair( - flutter::EncodableValue("errorType"), - flutter::EncodableValue(ErrorCodeToString(e.GetErrorCode())))); - map.insert( - std::make_pair( - flutter::EncodableValue("failingUrl"), - flutter::EncodableValue(e.GetUrl()))); - auto args = std::make_unique(map); - channel_->InvokeMethod("onWebResourceError", std::move(args)); + [this](LWE::WebContainer* container, LWE::ResourceError error) { + flutter::EncodableMap args = { + {flutter::EncodableValue("errorCode"), + flutter::EncodableValue(error.GetErrorCode())}, + {flutter::EncodableValue("description"), + flutter::EncodableValue(error.GetDescription())}, + {flutter::EncodableValue("errorType"), + flutter::EncodableValue(ErrorCodeToString(error.GetErrorCode()))}, + {flutter::EncodableValue("failingUrl"), + flutter::EncodableValue(error.GetUrl())}, + }; + channel_->InvokeMethod("onWebResourceError", + std::make_unique(args)); }); - webview_instance_->RegisterShouldOverrideUrlLoadingHandler( [this](LWE::WebContainer* view, const std::string& url) -> bool { if (!has_navigation_delegate_) { return false; } - flutter::EncodableMap map; - map.insert( - std::make_pair( - flutter::EncodableValue("url"), flutter::EncodableValue(url))); - map.insert( - std::make_pair( - flutter::EncodableValue("isForMainFrame"), - flutter::EncodableValue(true))); - auto args = std::make_unique(map); - auto on_result = - std::make_unique>( - url, this); - channel_->InvokeMethod("navigationRequest", std::move(args), - std::move(on_result)); - + flutter::EncodableMap args = { + {flutter::EncodableValue("url"), flutter::EncodableValue(url)}, + {flutter::EncodableValue("isForMainFrame"), + flutter::EncodableValue(true)}, + }; + auto result = std::make_unique(url, this); + channel_->InvokeMethod("navigationRequest", + std::make_unique(args), + std::move(result)); return true; }); webview_instance_->LoadURL(url); } -void WebView::ApplySettings(flutter::EncodableMap settings) { - for (auto const& [key, val] : settings) { +void WebView::ApplySettings(const flutter::EncodableMap& settings) { + for (const auto& [key, value] : settings) { if (std::holds_alternative(key)) { - std::string k = std::get(key); - if ("jsMode" == k) { - // NOTE: Not supported by Lightweight Web Engine (LWE) on Tizen. - } else if ("hasNavigationDelegate" == k) { - if (std::holds_alternative(val)) { - has_navigation_delegate_ = std::get(val); + std::string string_key = std::get(key); + if (string_key == "jsMode") { + // NOTE: Not supported by LWE on Tizen. + } else if (string_key == "hasNavigationDelegate") { + if (std::holds_alternative(value)) { + has_navigation_delegate_ = std::get(value); } - } else if ("hasProgressTracking" == k) { - if (std::holds_alternative(val)) { - has_progress_tracking_ = std::get(val); + } else if (string_key == "hasProgressTracking") { + if (std::holds_alternative(value)) { + has_progress_tracking_ = std::get(value); } - } else if ("debuggingEnabled" == k) { + } else if (string_key == "debuggingEnabled") { // NOTE: Not supported by LWE on Tizen. - } else if ("gestureNavigationEnabled" == k) { + } else if (string_key == "gestureNavigationEnabled") { // NOTE: Not supported by LWE on Tizen. - } else if ("allowsInlineMediaPlayback" == k) { + } else if (string_key == "allowsInlineMediaPlayback") { // no-op inline media playback is always allowed on Tizen. - } else if ("userAgent" == k) { - if (std::holds_alternative(val)) { - auto settings = webview_instance_->GetSettings(); - settings.SetUserAgentString(std::get(val)); + } else if (string_key == "userAgent") { + if (std::holds_alternative(value)) { + LWE::Settings settings = webview_instance_->GetSettings(); + settings.SetUserAgentString(std::get(value)); webview_instance_->SetSettings(settings); } - } else if ("zoomEnabled" == k) { + } else if (string_key == "zoomEnabled") { // NOTE: Not supported by LWE on Tizen. } else { - throw std::invalid_argument("Unknown WebView setting: " + k); + LOG_WARN("Unknown settings key: %s", string_key.c_str()); } } } @@ -374,24 +331,19 @@ void WebView::ApplySettings(flutter::EncodableMap settings) { * message over a method channel to the Dart code. */ void WebView::RegisterJavaScriptChannelName(const std::string& name) { - LOG_DEBUG("RegisterJavaScriptChannelName(channelName: %s)\n", name.c_str()); - - std::function cb = - [this, name](const std::string& message) -> std::string { - LOG_DEBUG("Invoke JavaScriptChannel(message: %s)\n", message.c_str()); - flutter::EncodableMap map; - map.insert(std::make_pair( - flutter::EncodableValue("channel"), flutter::EncodableValue(name))); - map.insert(std::make_pair( - flutter::EncodableValue("message"), flutter::EncodableValue(message))); - - std::unique_ptr args = - std::make_unique(map); - channel_->InvokeMethod("javascriptChannelMessage", std::move(args)); + LOG_DEBUG("Register a JavaScript channel: %s", name.c_str()); + + auto on_message = [this, name](const std::string& message) -> std::string { + LOG_DEBUG("JavaScript channel message: %s", message.c_str()); + flutter::EncodableMap args = { + {flutter::EncodableValue("channel"), flutter::EncodableValue(name)}, + {flutter::EncodableValue("message"), flutter::EncodableValue(message)}, + }; + channel_->InvokeMethod("javascriptChannelMessage", + std::make_unique(args)); return "success"; }; - - webview_instance_->AddJavaScriptInterface(name, "postMessage", cb); + webview_instance_->AddJavaScriptInterface(name, "postMessage", on_message); } WebView::~WebView() { Dispose(); } @@ -407,21 +359,16 @@ void WebView::Dispose() { webview_instance_->Destroy(); webview_instance_ = nullptr; } - - if (texture_variant_) { - delete texture_variant_; - texture_variant_ = nullptr; - } } void WebView::Resize(double width, double height) { - LOG_DEBUG("WebView::Resize width: %f height: %f \n", width, height); width_ = width; height_ = height; if (candidate_surface_) { candidate_surface_ = nullptr; } + tbm_pool_->Prepare(width_, height_); webview_instance_->ResizeTo(width_, height_); } @@ -446,90 +393,92 @@ void WebView::Touch(int type, int button, double x, double y, double dx, x, y); is_mouse_lbutton_down_ = false; } else { - // TODO: Not implemented + LOG_WARN("Unknown touch event type: %d", type); } } -static LWE::KeyValue EcoreEventKeyToKeyValue(const char* ecore_key_string, - bool is_shift_pressed) { - if (strcmp("Left", ecore_key_string) == 0) { +static LWE::KeyValue KeyNameToKeyValue(const std::string& ecore_key, + bool is_shift_pressed) { + if (ecore_key == "Left") { return LWE::KeyValue::ArrowLeftKey; - } else if (strcmp("Right", ecore_key_string) == 0) { + } else if (ecore_key == "Right") { return LWE::KeyValue::ArrowRightKey; - } else if (strcmp("Up", ecore_key_string) == 0) { + } else if (ecore_key == "Up") { return LWE::KeyValue::ArrowUpKey; - } else if (strcmp("Down", ecore_key_string) == 0) { + } else if (ecore_key == "Down") { return LWE::KeyValue::ArrowDownKey; - } else if (strcmp("space", ecore_key_string) == 0) { + } else if (ecore_key == "space") { return LWE::KeyValue::SpaceKey; - } else if (strcmp("Return", ecore_key_string) == 0) { + } else if (ecore_key == "Select") { return LWE::KeyValue::EnterKey; - } else if (strcmp("Tab", ecore_key_string) == 0) { + } else if (ecore_key == "Return") { + return LWE::KeyValue::EnterKey; + } else if (ecore_key == "Tab") { return LWE::KeyValue::TabKey; - } else if (strcmp("BackSpace", ecore_key_string) == 0) { + } else if (ecore_key == "BackSpace") { return LWE::KeyValue::BackspaceKey; - } else if (strcmp("Escape", ecore_key_string) == 0) { + } else if (ecore_key == "Escape") { return LWE::KeyValue::EscapeKey; - } else if (strcmp("Delete", ecore_key_string) == 0) { + } else if (ecore_key == "Delete") { return LWE::KeyValue::DeleteKey; - } else if (strcmp("at", ecore_key_string) == 0) { + } else if (ecore_key == "at") { return LWE::KeyValue::AtMarkKey; - } else if (strcmp("minus", ecore_key_string) == 0) { + } else if (ecore_key == "minus") { if (is_shift_pressed) { return LWE::KeyValue::UnderScoreMarkKey; } else { return LWE::KeyValue::MinusMarkKey; } - } else if (strcmp("equal", ecore_key_string) == 0) { + } else if (ecore_key == "equal") { if (is_shift_pressed) { return LWE::KeyValue::PlusMarkKey; } else { return LWE::KeyValue::EqualitySignKey; } - } else if (strcmp("bracketleft", ecore_key_string) == 0) { + } else if (ecore_key == "bracketleft") { if (is_shift_pressed) { return LWE::KeyValue::LeftCurlyBracketMarkKey; } else { return LWE::KeyValue::LeftSquareBracketKey; } - } else if (strcmp("bracketright", ecore_key_string) == 0) { + } else if (ecore_key == "bracketright") { if (is_shift_pressed) { return LWE::KeyValue::RightCurlyBracketMarkKey; } else { return LWE::KeyValue::RightSquareBracketKey; } - } else if (strcmp("semicolon", ecore_key_string) == 0) { + } else if (ecore_key == "semicolon") { if (is_shift_pressed) { return LWE::KeyValue::ColonMarkKey; } else { return LWE::KeyValue::SemiColonMarkKey; } - } else if (strcmp("apostrophe", ecore_key_string) == 0) { + } else if (ecore_key == "apostrophe") { if (is_shift_pressed) { return LWE::KeyValue::DoubleQuoteMarkKey; } else { return LWE::KeyValue::SingleQuoteMarkKey; } - } else if (strcmp("comma", ecore_key_string) == 0) { + } else if (ecore_key == "comma") { if (is_shift_pressed) { return LWE::KeyValue::LessThanMarkKey; } else { return LWE::KeyValue::CommaMarkKey; } - } else if (strcmp("period", ecore_key_string) == 0) { + } else if (ecore_key == "period") { if (is_shift_pressed) { return LWE::KeyValue::GreaterThanSignKey; } else { return LWE::KeyValue::PeriodKey; } - } else if (strcmp("slash", ecore_key_string) == 0) { + } else if (ecore_key == "slash") { if (is_shift_pressed) { return LWE::KeyValue::QuestionMarkKey; } else { return LWE::KeyValue::SlashKey; } - } else if (strlen(ecore_key_string) == 1) { - char ch = ecore_key_string[0]; + } else if (ecore_key.length() == 1) { + const char ch = ecore_key.at(0); if (ch >= '0' && ch <= '9') { if (is_shift_pressed) { switch (ch) { @@ -555,271 +504,189 @@ static LWE::KeyValue EcoreEventKeyToKeyValue(const char* ecore_key_string, return LWE::KeyValue::RightParenthesisMarkKey; } } - return (LWE::KeyValue)(LWE::KeyValue::Digit0Key + ch - '0'); + return LWE::KeyValue(LWE::KeyValue::Digit0Key + ch - '0'); } else if (ch >= 'a' && ch <= 'z') { if (is_shift_pressed) { - return (LWE::KeyValue)(LWE::KeyValue::LowerAKey + ch - 'a' - 32); + return LWE::KeyValue(LWE::KeyValue::LowerAKey + ch - 'a' - 32); } else { - return (LWE::KeyValue)(LWE::KeyValue::LowerAKey + ch - 'a'); + return LWE::KeyValue(LWE::KeyValue::LowerAKey + ch - 'a'); } } else if (ch >= 'A' && ch <= 'Z') { if (is_shift_pressed) { - return (LWE::KeyValue)(LWE::KeyValue::AKey + ch - 'A' + 32); + return LWE::KeyValue(LWE::KeyValue::AKey + ch - 'A' + 32); } else { - return (LWE::KeyValue)(LWE::KeyValue::AKey + ch - 'A'); + return LWE::KeyValue(LWE::KeyValue::AKey + ch - 'A'); } } - } else if (strcmp("XF86AudioRaiseVolume", ecore_key_string) == 0) { + } else if (ecore_key == "XF86AudioRaiseVolume") { return LWE::KeyValue::TVVolumeUpKey; - } else if (strcmp("XF86AudioLowerVolume", ecore_key_string) == 0) { + } else if (ecore_key == "XF86AudioLowerVolume") { return LWE::KeyValue::TVVolumeDownKey; - } else if (strcmp("XF86AudioMute", ecore_key_string) == 0) { + } else if (ecore_key == "XF86AudioMute") { return LWE::KeyValue::TVMuteKey; - } else if (strcmp("XF86RaiseChannel", ecore_key_string) == 0) { + } else if (ecore_key == "XF86RaiseChannel") { return LWE::KeyValue::TVChannelUpKey; - } else if (strcmp("XF86LowerChannel", ecore_key_string) == 0) { + } else if (ecore_key == "XF86LowerChannel") { return LWE::KeyValue::TVChannelDownKey; - } else if (strcmp("XF86AudioRewind", ecore_key_string) == 0) { + } else if (ecore_key == "XF86AudioRewind") { return LWE::KeyValue::MediaTrackPreviousKey; - } else if (strcmp("XF86AudioNext", ecore_key_string) == 0) { + } else if (ecore_key == "XF86AudioNext") { return LWE::KeyValue::MediaTrackNextKey; - } else if (strcmp("XF86AudioPause", ecore_key_string) == 0) { + } else if (ecore_key == "XF86AudioPause") { return LWE::KeyValue::MediaPauseKey; - } else if (strcmp("XF86AudioRecord", ecore_key_string) == 0) { + } else if (ecore_key == "XF86AudioRecord") { return LWE::KeyValue::MediaRecordKey; - } else if (strcmp("XF86AudioPlay", ecore_key_string) == 0) { + } else if (ecore_key == "XF86AudioPlay") { return LWE::KeyValue::MediaPlayKey; - } else if (strcmp("XF86AudioStop", ecore_key_string) == 0) { + } else if (ecore_key == "XF86AudioStop") { return LWE::KeyValue::MediaStopKey; - } else if (strcmp("XF86Info", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Info") { return LWE::KeyValue::TVInfoKey; - } else if (strcmp("XF86Back", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Back") { return LWE::KeyValue::TVReturnKey; - } else if (strcmp("XF86Red", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Red") { return LWE::KeyValue::TVRedKey; - } else if (strcmp("XF86Green", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Green") { return LWE::KeyValue::TVGreenKey; - } else if (strcmp("XF86Yellow", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Yellow") { return LWE::KeyValue::TVYellowKey; - } else if (strcmp("XF86Blue", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Blue") { return LWE::KeyValue::TVBlueKey; - } else if (strcmp("XF86SysMenu", ecore_key_string) == 0) { + } else if (ecore_key == "XF86SysMenu") { return LWE::KeyValue::TVMenuKey; - } else if (strcmp("XF86Home", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Home") { return LWE::KeyValue::TVHomeKey; - } else if (strcmp("XF86Exit", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Exit") { return LWE::KeyValue::TVExitKey; - } else if (strcmp("XF86PreviousChannel", ecore_key_string) == 0) { + } else if (ecore_key == "XF86PreviousChannel") { return LWE::KeyValue::TVPreviousChannel; - } else if (strcmp("XF86ChannelList", ecore_key_string) == 0) { + } else if (ecore_key == "XF86ChannelList") { return LWE::KeyValue::TVChannelList; - } else if (strcmp("XF86ChannelGuide", ecore_key_string) == 0) { + } else if (ecore_key == "XF86ChannelGuide") { return LWE::KeyValue::TVChannelGuide; - } else if (strcmp("XF86SimpleMenu", ecore_key_string) == 0) { + } else if (ecore_key == "XF86SimpleMenu") { return LWE::KeyValue::TVSimpleMenu; - } else if (strcmp("XF86EManual", ecore_key_string) == 0) { + } else if (ecore_key == "XF86EManual") { return LWE::KeyValue::TVEManual; - } else if (strcmp("XF86ExtraApp", ecore_key_string) == 0) { + } else if (ecore_key == "XF86ExtraApp") { return LWE::KeyValue::TVExtraApp; - } else if (strcmp("XF86Search", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Search") { return LWE::KeyValue::TVSearch; - } else if (strcmp("XF86PictureSize", ecore_key_string) == 0) { + } else if (ecore_key == "XF86PictureSize") { return LWE::KeyValue::TVPictureSize; - } else if (strcmp("XF86Sleep", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Sleep") { return LWE::KeyValue::TVSleep; - } else if (strcmp("XF86Caption", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Caption") { return LWE::KeyValue::TVCaption; - } else if (strcmp("XF86More", ecore_key_string) == 0) { + } else if (ecore_key == "XF86More") { return LWE::KeyValue::TVMore; - } else if (strcmp("XF86BTVoice", ecore_key_string) == 0) { + } else if (ecore_key == "XF86BTVoice") { return LWE::KeyValue::TVBTVoice; - } else if (strcmp("XF86Color", ecore_key_string) == 0) { + } else if (ecore_key == "XF86Color") { return LWE::KeyValue::TVColor; - } else if (strcmp("XF86PlayBack", ecore_key_string) == 0) { + } else if (ecore_key == "XF86PlayBack") { return LWE::KeyValue::TVPlayBack; } - - LOG_DEBUG("WebViewEFL - unimplemented key %s\n", ecore_key_string); + LOG_WARN("Unknown key name: %s", ecore_key.c_str()); return LWE::KeyValue::UnidentifiedKey; } void WebView::DispatchKeyDownEvent(Ecore_Event_Key* key_event) { - std::string key_name = key_event->keyname; - LOG_DEBUG("ECORE_EVENT_KEY_DOWN [%s, %d]\n", key_name.c_str(), - (key_event->modifiers & 1) || (key_event->modifiers & 2)); - if (!IsFocused()) { - LOG_DEBUG("ignore keydown because we dont have focus"); return; } - if ((strcmp(key_name.c_str(), "XF86Exit") == 0) || - (strcmp(key_name.c_str(), "Select") == 0) || - (strcmp(key_name.c_str(), "Cancel") == 0)) { - if (strcmp(key_name.c_str(), "Select") == 0) { - webview_instance_->AddIdleCallback( - [](void* data) { - WebView* view = (WebView*)data; - LWE::WebContainer* self = view->GetWebViewInstance(); - LWE::KeyValue kv = LWE::KeyValue::EnterKey; - self->DispatchKeyDownEvent(kv); - self->DispatchKeyPressEvent(kv); - self->DispatchKeyUpEvent(kv); - view->HidePanel(); - }, - this); - } else { - webview_instance_->AddIdleCallback( - [](void* data) { - WebView* view = (WebView*)data; - view->HidePanel(); - }, - this); - } - } + std::string key_name = key_event->keyname; + bool is_shift_pressed = key_event->modifiers & 1; struct Param { LWE::WebContainer* webview_instance; LWE::KeyValue key_value; }; - Param* p = new Param(); - p->webview_instance = webview_instance_; - p->key_value = - EcoreEventKeyToKeyValue(key_name.c_str(), (key_event->modifiers & 1)); + Param* param = new Param(); + param->webview_instance = webview_instance_; + param->key_value = KeyNameToKeyValue(key_name, is_shift_pressed); webview_instance_->AddIdleCallback( [](void* data) { - Param* p = (Param*)data; - p->webview_instance->DispatchKeyDownEvent(p->key_value); - p->webview_instance->DispatchKeyPressEvent(p->key_value); - delete p; + Param* param = reinterpret_cast(data); + param->webview_instance->DispatchKeyDownEvent(param->key_value); + param->webview_instance->DispatchKeyPressEvent(param->key_value); + delete param; }, - p); + param); } void WebView::DispatchKeyUpEvent(Ecore_Event_Key* key_event) { - std::string key_name = key_event->keyname; - LOG_DEBUG("ECORE_EVENT_KEY_UP [%s, %d]\n", key_name.c_str(), - (key_event->modifiers & 1) || (key_event->modifiers & 2)); - if (!IsFocused()) { - LOG_DEBUG("ignore keyup because we dont have focus"); return; } + std::string key_name = key_event->keyname; + bool is_shift_pressed = key_event->modifiers & 1; + struct Param { LWE::WebContainer* webview_instance; LWE::KeyValue key_value; }; - Param* p = new Param(); - p->webview_instance = webview_instance_; - p->key_value = - EcoreEventKeyToKeyValue(key_name.c_str(), (key_event->modifiers & 1)); + Param* param = new Param(); + param->webview_instance = webview_instance_; + param->key_value = KeyNameToKeyValue(key_name, is_shift_pressed); webview_instance_->AddIdleCallback( [](void* data) { - Param* p = (Param*)data; - p->webview_instance->DispatchKeyUpEvent(p->key_value); - delete p; + Param* param = reinterpret_cast(data); + param->webview_instance->DispatchKeyUpEvent(param->key_value); + delete param; }, - p); -} - -void WebView::DispatchCompositionUpdateEvent(const char* str, int size) { - if (str) { - LOG_DEBUG("WebView::DispatchCompositionUpdateEvent [%s]", str); - webview_instance_->DispatchCompositionUpdateEvent(std::string(str, size)); - } -} - -void WebView::DispatchCompositionEndEvent(const char* str, int size) { - if (str) { - LOG_DEBUG("WebView::DispatchCompositionEndEvent [%s]", str); - webview_instance_->DispatchCompositionEndEvent(std::string(str, size)); - } -} - -void WebView::ShowPanel() { - LOG_DEBUG("WebView::ShowPanel()"); - if (!context_) { - LOG_ERROR("Ecore_IMF_Context nullptr"); - return; - } - ecore_imf_context_input_panel_show(context_); - ecore_imf_context_focus_in(context_); -} - -void WebView::HidePanel() { - LOG_DEBUG("WebView::HidePanel()"); - if (!context_) { - LOG_ERROR("Ecore_IMF_Context nullptr"); - return; - } - ecore_imf_context_reset(context_); - ecore_imf_context_focus_out(context_); - ecore_imf_context_input_panel_hide(context_); -} - -void WebView::SetSoftwareKeyboardContext(Ecore_IMF_Context* context) { - context_ = context; - - webview_instance_->RegisterOnShowSoftwareKeyboardIfPossibleHandler( - [this](LWE::WebContainer* v) { ShowPanel(); }); - - webview_instance_->RegisterOnHideSoftwareKeyboardIfPossibleHandler( - [this](LWE::WebContainer*) { HidePanel(); }); -} - -void WebView::ClearFocus() { - LOG_DEBUG("WebView::ClearFocus()"); - HidePanel(); + param); } void WebView::SetDirection(int direction) { - LOG_DEBUG("WebView::SetDirection direction: %d\n", direction); - // TODO: implement this if necessary + // TODO: Implement if necessary. } void WebView::InitWebView() { - if (webview_instance_ != nullptr) { + if (webview_instance_) { webview_instance_->Destroy(); webview_instance_ = nullptr; } - float scale_factor = 1; + float pixel_ratio = 1.0; - webview_instance_ = (LWE::WebContainer*)createWebViewInstance( - 0, 0, width_, height_, scale_factor, "SamsungOneUI", "ko-KR", - "Asia/Seoul", - [this]() -> LWE::WebContainer::ExternalImageInfo { - std::lock_guard lock(mutex_); - LWE::WebContainer::ExternalImageInfo result; - if (!working_surface_) { - working_surface_ = tbm_pool_->GetAvailableBuffer(); - } - if (working_surface_) { - result.imageAddress = static_cast(working_surface_->Surface()); - } else { - result.imageAddress = nullptr; - } - return result; - }, - [this](LWE::WebContainer* c, bool isRendered) { - if (isRendered) { - std::lock_guard lock(mutex_); - if (candidate_surface_) { - tbm_pool_->Release(candidate_surface_); - candidate_surface_ = nullptr; - } - candidate_surface_ = working_surface_; - working_surface_ = nullptr; - texture_registrar_->MarkTextureFrameAvailable(GetTextureId()); - } - }, - use_sw_backend_); + auto on_prepare_image = [this]() -> LWE::WebContainer::ExternalImageInfo { + std::lock_guard lock(mutex_); + LWE::WebContainer::ExternalImageInfo result; + if (!working_surface_) { + working_surface_ = tbm_pool_->GetAvailableBuffer(); + } + if (working_surface_) { + result.imageAddress = working_surface_->Surface(); + } else { + result.imageAddress = nullptr; + } + return result; + }; + auto on_flush = [this](LWE::WebContainer* container, bool is_rendered) { + if (is_rendered) { + std::lock_guard lock(mutex_); + if (candidate_surface_) { + tbm_pool_->Release(candidate_surface_); + candidate_surface_ = nullptr; + } + candidate_surface_ = working_surface_; + working_surface_ = nullptr; + texture_registrar_->MarkTextureFrameAvailable(GetTextureId()); + } + }; + + webview_instance_ = + reinterpret_cast(createWebViewInstance( + 0, 0, width_, height_, pixel_ratio, "SamsungOneUI", "ko-KR", + "Asia/Seoul", on_prepare_image, on_flush, use_sw_backend_)); #ifndef TV_PROFILE - auto settings = webview_instance_->GetSettings(); + LWE::Settings settings = webview_instance_->GetSettings(); settings.SetUserAgentString( "Mozilla/5.0 (like Gecko/54.0 Firefox/54.0) Mobile"); webview_instance_->SetSettings(settings); @@ -829,162 +696,156 @@ void WebView::InitWebView() { void WebView::HandleMethodCall( const flutter::MethodCall& method_call, std::unique_ptr> result) { - if (!webview_instance_ || !method_call.arguments()) { + if (!webview_instance_) { + result->Error("Invalid operation", + "The webview instance has not been initialized."); return; } - const auto method_name = method_call.method_name(); - const auto& arguments = *method_call.arguments(); - LOG_DEBUG("WebView::HandleMethodCall : %s \n ", method_name.c_str()); + const std::string& method_name = method_call.method_name(); + const flutter::EncodableValue* arguments = method_call.arguments(); + + LOG_DEBUG("Handle a method call: %s", method_name.c_str()); - if (method_name.compare("loadUrl") == 0) { + if (method_name == "loadUrl") { std::string url; if (GetValueFromEncodableMap(arguments, "url", &url)) { webview_instance_->LoadURL(url); result->Success(); - return; + } else { + result->Error("Invalid argument", "No url provided."); } - result->Error("InvalidArguments", "Please set 'url' properly"); - } else if (method_name.compare("updateSettings") == 0) { - if (std::holds_alternative(arguments)) { - auto settings = std::get(arguments); - if (settings.size() > 0) { - try { - ApplySettings(settings); - } catch (const std::invalid_argument& ex) { - LOG_ERROR("[Exception] %s\n", ex.what()); - result->Error(ex.what()); - return; - } - } + } else if (method_name == "updateSettings") { + const auto* settings = std::get_if(arguments); + if (settings) { + ApplySettings(*settings); } result->Success(); - } else if (method_name.compare("canGoBack") == 0) { + } else if (method_name == "canGoBack") { result->Success(flutter::EncodableValue(webview_instance_->CanGoBack())); - } else if (method_name.compare("canGoForward") == 0) { + } else if (method_name == "canGoForward") { result->Success(flutter::EncodableValue(webview_instance_->CanGoForward())); - } else if (method_name.compare("goBack") == 0) { + } else if (method_name == "goBack") { webview_instance_->GoBack(); result->Success(); - } else if (method_name.compare("goForward") == 0) { + } else if (method_name == "goForward") { webview_instance_->GoForward(); result->Success(); - } else if (method_name.compare("reload") == 0) { + } else if (method_name == "reload") { webview_instance_->Reload(); result->Success(); - } else if (method_name.compare("currentUrl") == 0) { + } else if (method_name == "currentUrl") { result->Success(flutter::EncodableValue(webview_instance_->GetURL())); - } else if (method_name.compare("evaluateJavascript") == 0 || - method_name.compare("runJavascriptReturningResult") == 0 || - method_name.compare("runJavascript") == 0) { - if (std::holds_alternative(arguments)) { - std::string js_string = std::get(arguments); - bool returns_value = - method_name.compare("runJavascript") == 0 ? false : true; - webview_instance_->EvaluateJavaScript( - js_string, - [res = result.release(), returns_value](std::string value) { - LOG_DEBUG("value: %s\n", value.c_str()); - if (res) { - if (returns_value) { - res->Success(flutter::EncodableValue(value)); - } else { - res->Success(); - } - delete res; - } - }); + } else if (method_name == "evaluateJavascript" || + method_name == "runJavascriptReturningResult" || + method_name == "runJavascript") { + const auto* javascript = std::get_if(arguments); + if (javascript) { + bool should_return = method_name != "runJavascript"; + auto on_result = [result = result.release(), + should_return](std::string value) { + LOG_DEBUG("JavaScript evaluation result: %s", value.c_str()); + if (result) { + if (should_return) { + result->Success(flutter::EncodableValue(value)); + } else { + result->Success(); + } + delete result; + } + }; + webview_instance_->EvaluateJavaScript(*javascript, on_result); } else { - result->Error("InvalidArguments", "Please set javascript string"); + result->Error("Invalid argument", "The argument must be a string."); } - } else if (method_name.compare("addJavascriptChannels") == 0) { - if (std::holds_alternative(arguments)) { - auto name_list = std::get(arguments); - for (size_t i = 0; i < name_list.size(); i++) { - if (std::holds_alternative(name_list[i])) { - RegisterJavaScriptChannelName(std::get(name_list[i])); + } else if (method_name == "addJavascriptChannels") { + const auto* channels = std::get_if(arguments); + if (channels) { + for (flutter::EncodableValue channel : *channels) { + if (std::holds_alternative(channel)) { + RegisterJavaScriptChannelName(std::get(channel)); } } } result->Success(); - } else if (method_name.compare("removeJavascriptChannels") == 0) { - if (std::holds_alternative(arguments)) { - auto name_list = std::get(arguments); - for (size_t i = 0; i < name_list.size(); i++) { - if (std::holds_alternative(name_list[i])) { + } else if (method_name == "removeJavascriptChannels") { + const auto* channels = std::get_if(arguments); + if (channels) { + for (flutter::EncodableValue channel : *channels) { + if (std::holds_alternative(channel)) { webview_instance_->RemoveJavascriptInterface( - std::get(name_list[i]), "postMessage"); + std::get(channel), "postMessage"); } } } result->Success(); - } else if (method_name.compare("clearCache") == 0) { + } else if (method_name == "clearCache") { webview_instance_->ClearCache(); result->Success(); - } else if (method_name.compare("getTitle") == 0) { + } else if (method_name == "getTitle") { result->Success(flutter::EncodableValue(webview_instance_->GetTitle())); - } else if (method_name.compare("scrollTo") == 0) { + } else if (method_name == "scrollTo") { int x = 0, y = 0; if (GetValueFromEncodableMap(arguments, "x", &x) && GetValueFromEncodableMap(arguments, "y", &y)) { webview_instance_->ScrollTo(x, y); result->Success(); - return; + } else { + result->Error("Invalid argument", "No x or y provided."); } - result->Error("InvalidArguments", "Please set 'x' or 'y' properly"); - } else if (method_name.compare("scrollBy") == 0) { + } else if (method_name == "scrollBy") { int x = 0, y = 0; if (GetValueFromEncodableMap(arguments, "x", &x) && GetValueFromEncodableMap(arguments, "y", &y)) { webview_instance_->ScrollBy(x, y); result->Success(); - return; + } else { + result->Error("Invalid argument", "No x or y provided."); } - result->Error("InvalidArguments", "Please set 'x' or 'y' properly"); - } else if (method_name.compare("getScrollX") == 0) { + } else if (method_name == "getScrollX") { result->Success(flutter::EncodableValue(webview_instance_->GetScrollX())); - } else if (method_name.compare("getScrollY") == 0) { + } else if (method_name == "getScrollY") { result->Success(flutter::EncodableValue(webview_instance_->GetScrollY())); - } else if (method_name.compare("loadFlutterAsset") == 0) { - if (std::holds_alternative(arguments)) { - std::string key = std::get(arguments); - std::string path; - char* resPath = app_get_resource_path(); - if (resPath) { - path = std::string("file://") + resPath + "flutter_assets/" + key; - free(resPath); - webview_instance_->LoadURL(path); + } else if (method_name == "loadFlutterAsset") { + const auto* key = std::get_if(arguments); + if (key) { + char* res_path = app_get_resource_path(); + if (res_path) { + std::string url = + std::string("file://") + res_path + "flutter_assets/" + *key; + free(res_path); + webview_instance_->LoadURL(url); result->Success(); - return; + } else { + result->Error("Operation failed", + "Could not get the flutter_assets path."); } + } else { + result->Error("Invalid argument", "The argument must be a string."); } - result->Error("InvalidArguments", "Please set 'key' properly"); - } else if (method_name.compare("loadHtmlString") == 0) { - std::string html; - std::string baseUrl; + } else if (method_name == "loadHtmlString") { + std::string html, base_url; if (!GetValueFromEncodableMap(arguments, "html", &html)) { - result->Error("InvalidArguments", "Please set 'html' properly"); + result->Error("Invalid argument", "No html provided."); return; } - if (GetValueFromEncodableMap(arguments, "baseUrl", &baseUrl)) { - LOG_DEBUG( - "loadHtmlString : baseUrl is not yet supported. It will be " - "ignored.\n "); + if (GetValueFromEncodableMap(arguments, "baseUrl", &base_url)) { + LOG_WARN("loadHtmlString: baseUrl is not supported and will be ignored."); } webview_instance_->LoadData(html); result->Success(); - } else if (method_name.compare("loadFile") == 0) { - if (std::holds_alternative(arguments)) { - std::string absoluteFilePath = - std::string("file://") + std::get(arguments); - webview_instance_->LoadURL(absoluteFilePath); + } else if (method_name == "loadFile") { + const auto* file_path = std::get_if(arguments); + if (file_path) { + std::string url = std::string("file://") + *file_path; + webview_instance_->LoadURL(url); result->Success(); - return; + } else { + result->Error("Invalid argument", "The argument must be a string."); } - result->Error("InvalidArguments", "Please set 'absoluteFilePath' properly"); - } else if (method_name.compare("loadRequest") == 0) { + } else if (method_name == "loadRequest") { result->NotImplemented(); - } else if (method_name.compare("setCookie") == 0) { + } else if (method_name == "setCookie") { result->NotImplemented(); } else { result->NotImplemented(); @@ -994,16 +855,15 @@ void WebView::HandleMethodCall( void WebView::HandleCookieMethodCall( const flutter::MethodCall& method_call, std::unique_ptr> result) { - if (webview_instance_ == nullptr) { - result->Error("Not Webview created"); + if (!webview_instance_) { + result->Error("Invalid operation", + "The webview instance has not been initialized."); return; } - const auto method_name = method_call.method_name(); - - LOG_DEBUG("WebView::HandleMethodCall : %s \n ", method_name.c_str()); + const std::string& method_name = method_call.method_name(); - if (method_name.compare("clearCookies") == 0) { + if (method_name == "clearCookies") { LWE::CookieManager* cookie = LWE::CookieManager::GetInstance(); cookie->ClearCookies(); result->Success(flutter::EncodableValue(true)); diff --git a/packages/webview_flutter/tizen/src/webview.h b/packages/webview_flutter/tizen/src/webview.h index ffbb371f6..d3545e25b 100644 --- a/packages/webview_flutter/tizen/src/webview.h +++ b/packages/webview_flutter/tizen/src/webview.h @@ -2,10 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEVIEW_H_ -#define FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEVIEW_H_ +#ifndef FLUTTER_PLUGIN_WEVIEW_H_ +#define FLUTTER_PLUGIN_WEVIEW_H_ -#include #include #include #include @@ -22,37 +21,30 @@ namespace LWE { class WebContainer; } -class TextInputChannel; class BufferPool; -class SingleBufferPool; class BufferUnit; class WebView : public PlatformView { public: - WebView(flutter::PluginRegistrar* registrar, int viewId, - flutter::TextureRegistrar* textureRegistrar, double width, - double height, flutter::EncodableMap& params); + WebView(flutter::PluginRegistrar* registrar, int view_id, + flutter::TextureRegistrar* texture_registrar, double width, + double height, const flutter::EncodableValue& params); ~WebView(); + virtual void Dispose() override; + virtual void Resize(double width, double height) override; virtual void Touch(int type, int button, double x, double y, double dx, double dy) override; virtual void SetDirection(int direction) override; - virtual void ClearFocus() override; - // Key input event + virtual void ClearFocus() override {} + virtual void DispatchKeyDownEvent(Ecore_Event_Key* key) override; virtual void DispatchKeyUpEvent(Ecore_Event_Key* key) override; - void DispatchCompositionUpdateEvent(const char* str, int size); - void DispatchCompositionEndEvent(const char* str, int size); - void SetSoftwareKeyboardContext(Ecore_IMF_Context* context); - LWE::WebContainer* GetWebViewInstance() { return webview_instance_; } - void HidePanel(); - void ShowPanel(); - FlutterDesktopGpuBuffer* ObtainGpuBuffer(size_t width, size_t height); private: @@ -62,28 +54,28 @@ class WebView : public PlatformView { void HandleCookieMethodCall( const flutter::MethodCall& method_call, std::unique_ptr> result); - std::string GetChannelName(); - void InitWebView(); + void ApplySettings(const flutter::EncodableMap& settings); void RegisterJavaScriptChannelName(const std::string& name); - void ApplySettings(flutter::EncodableMap); + std::string GetChannelName(); + + void InitWebView(); + LWE::WebContainer* webview_instance_ = nullptr; flutter::TextureRegistrar* texture_registrar_; - LWE::WebContainer* webview_instance_; double width_; double height_; - BufferUnit* working_surface_; - BufferUnit* candidate_surface_; - BufferUnit* rendered_surface_; - bool is_mouse_lbutton_down_; - bool has_navigation_delegate_; - bool has_progress_tracking_; + BufferUnit* working_surface_ = nullptr; + BufferUnit* candidate_surface_ = nullptr; + BufferUnit* rendered_surface_ = nullptr; + bool is_mouse_lbutton_down_ = false; + bool has_navigation_delegate_ = false; + bool has_progress_tracking_ = false; std::unique_ptr> channel_; - Ecore_IMF_Context* context_; - flutter::TextureVariant* texture_variant_; + std::unique_ptr texture_variant_; std::mutex mutex_; std::unique_ptr tbm_pool_; bool use_sw_backend_; }; -#endif // FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEVIEW_H_ +#endif // FLUTTER_PLUGIN_WEVIEW_H_ diff --git a/packages/webview_flutter/tizen/src/webview_factory.cc b/packages/webview_flutter/tizen/src/webview_factory.cc index 158fc9021..a7344d9aa 100644 --- a/packages/webview_flutter/tizen/src/webview_factory.cc +++ b/packages/webview_flutter/tizen/src/webview_factory.cc @@ -6,51 +6,42 @@ #include #include +#include #include #include #include "log.h" #include "lwe/LWEWebView.h" +#include "webview.h" -WebViewFactory::WebViewFactory(flutter::PluginRegistrar* registrar, - flutter::TextureRegistrar* texture_registrar) - : PlatformViewFactory(registrar), texture_registrar_(texture_registrar) { +static std::string GetAppDataPath() { char* path = app_get_data_path(); - std::string path_string; - if (!path || strlen(path) == 0) { - path_string = "/tmp/"; - } else { - path_string = path; - free(path); - path = nullptr; + if (!path) { + return "/tmp/"; } - LOG_DEBUG("application data path : %s\n", path_string.c_str()); - std::string local_storage_path = - path_string + std::string("StarFish_localStorage.db"); - std::string cookie_path = path_string + std::string("StarFish_cookies.db"); - std::string cache_path = path_string + std::string("Starfish_cache.db"); + std::string result = std::string(path); + free(path); + return result; +} + +WebViewFactory::WebViewFactory(flutter::PluginRegistrar* registrar) + : PlatformViewFactory(registrar) { + texture_registrar_ = registrar->texture_registrar(); + + std::string data_path = GetAppDataPath(); + std::string local_storage_path = data_path + "StarFish_localStorage.db"; + std::string cookie_path = data_path + "StarFish_cookies.db"; + std::string cache_path = data_path + "Starfish_cache.db"; LWE::LWE::Initialize(local_storage_path.c_str(), cookie_path.c_str(), cache_path.c_str()); } -PlatformView* WebViewFactory::Create( - int view_id, double width, double height, - const std::vector& create_params) { - flutter::EncodableMap params; - auto decoded_value = *GetCodec().DecodeMessage(create_params); - if (std::holds_alternative(decoded_value)) { - params = std::get(decoded_value); - } - - try { - return new WebView(GetPluginRegistrar(), view_id, texture_registrar_, width, - height, params); - } catch (const std::invalid_argument& ex) { - LOG_ERROR("[Exception] %s\n", ex.what()); - return nullptr; - } +PlatformView* WebViewFactory::Create(int view_id, double width, double height, + const ByteMessage& params) { + return new WebView(GetPluginRegistrar(), view_id, texture_registrar_, width, + height, *GetCodec().DecodeMessage(params)); } void WebViewFactory::Dispose() { LWE::LWE::Finalize(); } diff --git a/packages/webview_flutter/tizen/src/webview_factory.h b/packages/webview_flutter/tizen/src/webview_factory.h index 9f0da78e5..fae47915f 100644 --- a/packages/webview_flutter/tizen/src/webview_factory.h +++ b/packages/webview_flutter/tizen/src/webview_factory.h @@ -2,30 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEVIEW_FACTORY_H_ -#define FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEVIEW_FACTORY_H_ +#ifndef FLUTTER_PLUGIN_WEVIEW_FACTORY_H_ +#define FLUTTER_PLUGIN_WEVIEW_FACTORY_H_ #include -#include #include #include -#include #include -#include "webview.h" - class WebViewFactory : public PlatformViewFactory { public: - WebViewFactory(flutter::PluginRegistrar* registrar, - flutter::TextureRegistrar* textureRegistrar); + WebViewFactory(flutter::PluginRegistrar* registrar); + + virtual PlatformView* Create(int view_id, double width, double height, + const ByteMessage& params) override; + virtual void Dispose() override; - virtual PlatformView* Create( - int viewId, double width, double height, - const std::vector& createParams) override; private: flutter::TextureRegistrar* texture_registrar_; }; -#endif // FLUTTER_PLUGIN_WEBVIEW_FLUTTER_TIZEN_WEVIEW_FACTORY_H_ +#endif // FLUTTER_PLUGIN_WEVIEW_FACTORY_H_ diff --git a/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc b/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc index 79f0d234c..66b6fd6e3 100644 --- a/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc +++ b/packages/webview_flutter/tizen/src/webview_flutter_tizen_plugin.cc @@ -11,7 +11,9 @@ #include "webview_factory.h" -static constexpr char kViewType[] = "plugins.flutter.io/webview"; +namespace { + +constexpr char kViewType[] = "plugins.flutter.io/webview"; class WebviewFlutterTizenPlugin : public flutter::Plugin { public: @@ -19,17 +21,20 @@ class WebviewFlutterTizenPlugin : public flutter::Plugin { auto plugin = std::make_unique(); registrar->AddPlugin(std::move(plugin)); } + WebviewFlutterTizenPlugin() {} + virtual ~WebviewFlutterTizenPlugin() {} }; +} // namespace + void WebviewFlutterTizenPluginRegisterWithRegistrar( - FlutterDesktopPluginRegistrarRef registrar) { - flutter::PluginRegistrar* core_registrar = + FlutterDesktopPluginRegistrarRef core_registrar) { + flutter::PluginRegistrar* registrar = flutter::PluginRegistrarManager::GetInstance() - ->GetRegistrar(registrar); - auto factory = std::make_unique( - core_registrar, core_registrar->texture_registrar()); - FlutterDesktopRegisterViewFactory(registrar, kViewType, std::move(factory)); - WebviewFlutterTizenPlugin::RegisterWithRegistrar(core_registrar); + ->GetRegistrar(core_registrar); + FlutterDesktopRegisterViewFactory( + core_registrar, kViewType, std::make_unique(registrar)); + WebviewFlutterTizenPlugin::RegisterWithRegistrar(registrar); }