Skip to content

[flutter_inappwebview] Introduce flutter_inappwebview_tizen#1015

Open
JSUYA wants to merge 3 commits intoflutter-tizen:masterfrom
JSUYA:flutter_inappwebview_tizen
Open

[flutter_inappwebview] Introduce flutter_inappwebview_tizen#1015
JSUYA wants to merge 3 commits intoflutter-tizen:masterfrom
JSUYA:flutter_inappwebview_tizen

Conversation

@JSUYA
Copy link
Copy Markdown
Member

@JSUYA JSUYA commented Apr 30, 2026

Introduce flutter_inappwebview_tizen, the Tizen implementation of flutter_inappwebview.

Like webview_flutter_tizen, it is built on top of EWK (chromium-efl) and
renders offscreen via a TBM surface buffer pool. Only the surface that maps
cleanly onto the Tizen WebView is implemented; APIs that have no EWK
counterpart raise UnsupportedError / UnimplementedError.

Screenshot from 2026-04-30 15-35-21

+#1008

@JSUYA JSUYA marked this pull request as draft April 30, 2026 03:48
@JSUYA JSUYA self-assigned this Apr 30, 2026
@JSUYA JSUYA added the enhancement New feature or request label Apr 30, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the flutter_inappwebview_tizen package, providing a Tizen implementation for the flutter_inappwebview plugin using the EWK API. The implementation supports core features such as URL loading, JavaScript evaluation, and offscreen rendering via a TBM surface buffer pool. Feedback on the native C++ implementation identifies a potential memory leak regarding the management of string allocations for HTTP headers.

Comment thread packages/flutter_inappwebview/tizen/src/webview.cc
@JSUYA JSUYA force-pushed the flutter_inappwebview_tizen branch 3 times, most recently from 9214876 to 29d9cee Compare April 30, 2026 06:44
@JSUYA JSUYA force-pushed the flutter_inappwebview_tizen branch from 29d9cee to 79c335c Compare April 30, 2026 08:02
@JSUYA JSUYA marked this pull request as ready for review April 30, 2026 09:08
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces the flutter_inappwebview_tizen plugin, providing a Tizen implementation for the flutter_inappwebview package. The changes include the necessary plugin infrastructure, Tizen-specific platform implementation using the EWK API, and an example application. Review feedback identified a memory leak in the touch event handling logic, a potential issue with automatic JSON decoding of JavaScript evaluation results, and a suggestion to use specific error codes in error reporting.

Comment thread packages/flutter_inappwebview/tizen/src/webview.cc
Comment thread packages/flutter_inappwebview/tizen/src/webview.cc
@JSUYA
Copy link
Copy Markdown
Member Author

JSUYA commented Apr 30, 2026

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds the Tizen implementation for the flutter_inappwebview plugin, featuring offscreen rendering using the EWK API. The native C++ implementation manages WebView instances and buffer pools for texture integration. Review feedback highlights stability concerns, including race conditions in the resizing and buffer management methods, potential crashes, and resource leaks of Ecore_Evas objects. Suggestions also include ensuring one-time initialization of EWK arguments and transitioning to a multi-buffer pool to improve rendering performance.

Comment on lines +334 to +344
void WebView::Resize(double width, double height) {
width_ = width;
height_ = height;

if (candidate_surface_) {
candidate_surface_ = nullptr;
}

tbm_pool_->Prepare(width_, height_);
evas_object_resize(webview_instance_, width_, height_);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The Resize method has several issues:

  1. It accesses and modifies candidate_surface_ without holding mutex_, which is a race condition with ObtainGpuSurface and OnFrameRendered.
  2. If candidate_surface_ is not null, it should be released back to the pool before being cleared, otherwise that buffer unit will be leaked (marked as in-use indefinitely).
  3. tbm_pool_->Prepare destroys existing surfaces. If rendered_surface_ is currently being accessed by the Flutter GPU thread, this will result in a Use-After-Free (UAF) crash.
void WebView::Resize(double width, double height) {
  std::lock_guard<std::mutex> lock(mutex_);
  width_ = width;
  height_ = height;

  if (candidate_surface_) {
    tbm_pool_->Release(candidate_surface_);
    candidate_surface_ = nullptr;
  }

  tbm_pool_->Prepare(width_, height_);
  evas_object_resize(webview_instance_, width_, height_);
}

// temporarily comment out ewk_init() and ewk_shutdown(). It can be reverted
// depending on updates to chromium-efl.
// ewk_init();
Ecore_Evas* evas = ecore_evas_new("wayland_egl", 0, 0, 1, 1, 0);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The Ecore_Evas object created here is never freed, leading to a resource leak every time a WebView is created and destroyed. It should be stored as a member variable and freed in Dispose using ecore_evas_free.

Comment on lines +900 to +902
if (rendered_surface_ && rendered_surface_->IsUsed()) {
tbm_pool_->Release(rendered_surface_);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This logic is incorrect. rendered_surface_ is the buffer currently held by Flutter. If IsUsed() is true, it means Flutter is still reading from it. Calling Release here marks the buffer as available in the pool, allowing OnFrameRendered to acquire and overwrite it while Flutter is still using it. These lines should be removed; the buffer is automatically returned to the pool when Flutter is done via the release_callback.

Comment on lines +914 to +915
webview->working_surface_ = webview->tbm_pool_->GetAvailableBuffer();
webview->working_surface_->UseExternalBuffer();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

GetAvailableBuffer() can return nullptr if all buffers in the pool are currently in use. Dereferencing it without a null check will cause a crash.

Suggested change
webview->working_surface_ = webview->tbm_pool_->GetAvailableBuffer();
webview->working_surface_->UseExternalBuffer();
if (!webview->working_surface_) {
webview->working_surface_ = webview->tbm_pool_->GetAvailableBuffer();
if (!webview->working_surface_) {
return;
}
webview->working_surface_->UseExternalBuffer();
}

Comment on lines +125 to +130
BufferUnit* SingleBufferPool::GetAvailableBuffer() {
std::lock_guard<std::mutex> lock(mutex_);
BufferUnit* buffer = pool_[0].get();
buffer->MarkInUse();
return buffer;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

SingleBufferPool::GetAvailableBuffer ignores the return value of MarkInUse(). If the buffer is already in use (e.g., held by Flutter), MarkInUse() returns false, but the function still returns the buffer. This allows the same buffer to be acquired multiple times simultaneously, leading to race conditions. It should return nullptr if the buffer is in use.

Suggested change
BufferUnit* SingleBufferPool::GetAvailableBuffer() {
std::lock_guard<std::mutex> lock(mutex_);
BufferUnit* buffer = pool_[0].get();
buffer->MarkInUse();
return buffer;
}
BufferUnit* SingleBufferPool::GetAvailableBuffer() {
std::lock_guard<std::mutex> lock(mutex_);
BufferUnit* buffer = pool_[0].get();
if (buffer->MarkInUse()) {
return buffer;
}
return nullptr;
}

Comment thread packages/flutter_inappwebview/tizen/src/webview.cc
Comment thread packages/flutter_inappwebview/tizen/src/webview.cc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant