How to implement a NavigationDelagate in webview_cef

I started to implementing NavigationDelegate feature in webview_cef packagehave write some code and it’s blocking all URLs so I need help to do this and manage code properly.

Here’s the package code I did

https://drive.google.com/file/d/1pFwxTEO0-Lw-Hf9IW22dCdms_zGNobfZ/view?usp=sharing

I try to implementing callback NavigationDelegate class and method channel to communicate with native but not have deep knowledge about it.

In my code when I use this code it blocks all the URLs that user can click and redirect but I want to implement it like a callback when dart decision for specific URL is prevent the URL should be prevent and also if decision is navigate the URL should be navigated.

But using this code whatever decision I give it blocks al the URLs in short I have to manage this code so it works as expected. I did changes like given and there nothing loaded everything will be intercepted.

Here’s what I did for this:

webview_handler.cc:

bool WebviewHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                                    CefRefPtr<CefFrame> frame,
                                    CefRefPtr<CefRequest> request,
                                    bool user_gesture,
                                    bool is_redirect) {
    CEF_REQUIRE_UI_THREAD();
    std::string url = request->GetURL();
    // bool shouldAllowNavigation = true;
    if (onNavigationRequestEvent) {
        std::cout << "URL =======> " << url << std::endl;
        bool shouldAllowNavigation = onNavigationRequestEvent(browser->GetIdentifier(), url);

        std::cout << "shouldAllowNavigation ===================> " << shouldAllowNavigation << std::endl;
        // If the callback explicitly returns false, block the navigation.
        if (!shouldAllowNavigation) {
            std::cout << "Blocking navigation to: " << url << std::endl;
            return true; // Returning true here blocks the navigation.
        }
    }
    // Otherwise, allow navigation by default.
    return false;
}

webview_handler.h:

class WebviewHandler : public CefClient,
                       public CefDisplayHandler,
                       public CefLifeSpanHandler,
                       public CefFocusHandler,
                       public CefLoadHandler,
                       public CefRequestHandler,
                       public CefRenderHandler{
public:
    //Paint callback
    std::function<void(int browserId, const void* buffer, int32_t width, int32_t height)> onPaintCallback;
    //cef message event
    std::function<bool(int, std::string)> onNavigationRequestEvent;
    std::function<void(int browserId, std::string url)> onUrlChangedEvent;
    std::function<void(int browserId, std::string title)> onTitleChangedEvent;
    std::function<void(int browserId, int type)>onCursorChangedEvent;
    std::function<void(int browserId, std::string text)> onTooltipEvent;
    std::function<void(int browserId, int level, std::string message, std::string source, int line)>onConsoleMessageEvent;
    std::function<void(int browserId, bool editable)> onFocusedNodeChangeMessage;
    std::function<void(int browserId, int32_t x, int32_t y)> onImeCompositionRangeChangedMessage;
    //webpage message
    std::function<void(std::string, std::string, std::string, int browserId, std::string)> onJavaScriptChannelMessage;

    explicit WebviewHandler();
    ~WebviewHandler();

    // CefClient methods:
    virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() override {
        return this;
    }
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override {
        return this;
    }
    virtual CefRefPtr<CefFocusHandler> GetFocusHandler() override {
        return this;
    }
    virtual CefRefPtr<CefRequestHandler> GetRequestHandler() override {
        return this;
    }
    virtual CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
    virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; }

    virtual bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                                CefRefPtr<CefFrame> frame,
                                CefRefPtr<CefRequest> request,
                                bool user_gesture,
                                bool is_redirect) override;

webview_plugin.cc:

namespace webview_cef {
    CefMainArgs mainArgs;
    CefRefPtr<WebviewApp> app;
    CefString userAgent;
    bool isCefInitialized = false;

    WebviewPlugin::WebviewPlugin() {
       m_handler = new WebviewHandler();
    }

    WebviewPlugin::~WebviewPlugin() {
       uninitCallback();
       m_handler->CloseAllBrowsers(true);
       m_handler = nullptr;
       if(!m_renderers.empty()){
          m_renderers.clear();
       }
    }

    void WebviewPlugin::initCallback() {
       if (!m_init)
       {
m_handler->onNavigationRequestEvent = [=](int browserId, std::string url) {
                if (m_invokeFuncWithReturn) {
                    std::cout << "C++ Received URL: " << url << std::endl;
                    WValue* bId = webview_value_new_int(browserId);
                    WValue* wUrl = webview_value_new_string(const_cast<char*>(url.c_str()));
                    WValue* retMap = webview_value_new_map();
                    webview_value_set_string(retMap, "browserId", bId);
                    webview_value_set_string(retMap, "url", wUrl);
                    WValue* result = m_invokeFuncWithReturn("onNavigationRequest", retMap);  // Send request to Dart
                    bool shouldAllow = webview_value_get_bool(result);
                    webview_value_unref(bId);
                    webview_value_unref(wUrl);
                    webview_value_unref(retMap);
                    return shouldAllow;  // Allow by default if no decision from Dart
                }
                return false;  // Block navigation if no Dart callback
            };
m_init = true;
        }
    }

    void WebviewPlugin::uninitCallback(){
        m_handler->onPaintCallback = nullptr;
        m_handler->onTooltipEvent = nullptr;
        m_handler->onCursorChangedEvent = nullptr;
        m_handler->onConsoleMessageEvent = nullptr;
        m_handler->onUrlChangedEvent = nullptr;
        m_handler->onNavigationRequestEvent = nullptr;
        m_handler->onTitleChangedEvent = nullptr;
        m_handler->onJavaScriptChannelMessage = nullptr;
        m_handler->onFocusedNodeChangeMessage = nullptr;
        m_handler->onImeCompositionRangeChangedMessage = nullptr;
        m_init = false;
    }
 void WebviewPlugin::HandleMethodCall(std::string name, WValue* values, std::function<void(int ,WValue*)> result) {
        if (name.compare("setNavigationDelegate") == 0) {
            int browserId = int(webview_value_get_int(webview_value_get_list_value(values, 0)));
            const auto url = webview_value_get_string(webview_value_get_list_value(values, 1));
              m_handler->onNavigationRequestEvent(browserId,url);
//            setNavigationRequestCallback();
            result(1, nullptr);  // Respond to Dart
        }
//        else if (name.compare("setNavigationDelegate") == 0) {
//            // Set up navigation delegate
//            m_handler->onNavigationRequestEvent = [=](int browserId, std::string url) {
//                std::cout << "C++ Received URL: " << url << std::endl;
//
//                // Call Dart side via the channel
//                if (m_invokeFunc) {
//                    WValue* bId = webview_value_new_int(browserId);
//                    WValue* wUrl = webview_value_new_string(const_cast<char*>(url.c_str()));
//                    WValue* retMap = webview_value_new_map();
//                    webview_value_set_string(retMap, "browserId", bId);
//                    webview_value_set_string(retMap, "url", wUrl);
//
//                    // Send navigation request event to Dart
//                    m_invokeFunc("onNavigationRequest", retMap);
//
//                    webview_value_unref(bId);
//                    webview_value_unref(wUrl);
//                    webview_value_unref(retMap);
//
//                    // For now, allow navigation by default until Dart responds
//                    return true;  // Allow navigation by default
//                }
//                return false;  // Block navigation if Dart doesn't respond
//            };
//            result(1, nullptr);  // Respond to Dart that setup is complete
//        }
        else {
            result = 0;
        }
        }

    void WebviewPlugin::setInvokeMethodFunc(std::function<void(std::string, WValue*)> func){
        m_invokeFunc = func;
    }
    void WebviewPlugin::setInvokeMethodFuncWithReturn(std::function<WValue * (std::string, WValue *)> func) {
        m_invokeFuncWithReturn = func;
    }

    void WebviewPlugin::setNavigationRequestCallback(std::function<bool(int, std::string)> callback) {
        m_navigationRequestCallback = [callback](int browserId, std::string url) -> bool {
            if (callback) {
                return callback(browserId, url);
            }
            return true; // Allow navigation by default
        };
    }

webview_plugin.h:

#ifndef WEBVIEW_PLUGIN_H
#define WEBVIEW_PLUGIN_H

#include "webview_value.h"
#include "webview_app.h"
#include <include/cef_base.h>

#include <functional>
namespace webview_cef {
    class WebviewTexture{
    public:
        virtual ~WebviewTexture(){}
        virtual void onFrame(const void* buffer, int width, int height){}
        int64_t textureId = 0;
        bool isFocused = false;
    };
    class WebviewPlugin {
    public:
        WebviewPlugin();
        ~WebviewPlugin();
        void initCallback();
        void uninitCallback();
        void HandleMethodCall(std::string name, WValue* values, std::function<void(int ,WValue*)> result);
        void sendKeyEvent(CefKeyEvent& ev);
        void setInvokeMethodFunc(std::function<void(std::string, WValue*)> func);
        void setInvokeMethodFuncWithReturn(std::function<WValue*(std::string, WValue*)> func); // New function
        void setNavigationRequestCallback(std::function<bool(int, std::string)> callback);

        void setCreateTextureFunc(std::function<std::shared_ptr<WebviewTexture>()> func);
        bool getAnyBrowserFocused();

    private :
        int cursorAction(WValue *args, std::string name);
        std::function<void(std::string, WValue*)> m_invokeFunc;
        std::function<WValue*(std::string, WValue*)> m_invokeFuncWithReturn; // New member
        std::function<std::shared_ptr<WebviewTexture>()> m_createTextureFunc;
        std::function<bool(int, std::string)> m_navigationRequestCallback;

        CefRefPtr<WebviewHandler> m_handler;
        CefRefPtr<WebviewApp> m_app;
        std::unordered_map<int, std::shared_ptr<WebviewTexture>> m_renderers;
        bool m_init = false;
    };

    void initCEFProcesses(CefMainArgs args);
    void initCEFProcesses();
    void startCEF();
    void doMessageLoopWork();
    void SwapBufferFromBgraToRgba(void* _dest, const void* _src, int width, int height);
    void stopCEF();
}

#endif //WEBVIEW_PLUGIN_H

navigation_delegate.dart:

typedef OnNavigationDecisionCb = NavigationDecision Function(String url);

class NavigationDelegate {
  final OnNavigationDecisionCb? onNavigationRequest;

  NavigationDelegate({this.onNavigationRequest});
}

enum NavigationDecision {
  prevent,
  navigate,
}

webview_manager.dart:

Future<bool> navigationCallHandle(MethodCall call) async{
  switch (call.method){
    case "onNavigationRequest":
      int browserId = call.arguments["browserId"] as int;
      final String url = call.arguments['url'];
      print("Dart side URL: $url");
      final decision = _webViews[browserId]?.delegate?.onNavigationRequest!(url);

      // if (decision != null) {
        print("Navigation decision for $url: $decision");
        final shouldBlock = (decision == NavigationDecision.navigate);
        return shouldBlock;
      // }
  }
  return true;

}

webview.dart:

setNavigationDelegate(NavigationDelegate delegate){
  _delegate = delegate;
}

New contributor

JEET NADIYADARA is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật