CEF Persist cookie in database(sqlLight)

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

CEF Persist cookie in database(sqlLight)

Postby ramjana » Tue Aug 18, 2020 2:43 am

Hi Experts,

I need a suggestion related to persisting cookie into custom database and using the same.

I have a win application where I am creating a browser instance. Once I close the browser, I want to store the cookies into a custom table created in the db(sql light)
table schema attached.

Below is the code to create RequestContext object,
Code: Select all
............
// Browser settings
        CefBrowserSettings browserSettings;
        browserSettings.plugins = background ? STATE_DISABLED : STATE_ENABLED;

        const auto resourceLoader = background ? nullptr : mResourceLoader;
        const auto clientHandler = CefRefPtr<ClientHandler>(new ClientHandler(mBrowserName, weak_from_this(), resourceLoader, mCookieStore, mCoreFramework->getNetworkManager(), mCertificateValidationHandler, useScfNetworkStack(), mRequestManager, mFeatureSettingsManager));

        CefRefPtr<CefRequestContext> requestContext = nullptr;
        if (!background)
        {
            mClientHandler = CefRefPtrContainer<ClientHandler>(clientHandler);
            RegisterQrcSchemeHandlerFactory(mResourceLoader);
        }
        requestContext = CefRequestContext::CreateContext(CefRequestContext::GetGlobalContext(), CefRefPtr<RequestContextHandler>(new RequestContextHandler(mCookieStore)));
       
        // Create the main browser window.
        if (!CefBrowserHost::CreateBrowser(
                window_info,     // window info
                clientHandler,   // handler
                url,             // url
                browserSettings, // settings
                nullptr,         // extra info
                requestContext)) // request context
        {
            .............
        }
....................


When I close the browser, it should store the cookie into local db,
Code: Select all
void CookieStore::saveCookies()
    {
        auto completionFunction = [browserName = mBrowserName, coreFramework = mCoreFramework](const Cookies& cookies) {
            RETURN_FROM_LAMBDA_IF_DEAD(coreFramework);

            const auto filteredCookies = spark::filter(cookies, [](auto& cookie) {
                return cookie->hasExpires;
            });

            coreFramework->getCookieManager()->setCookies(browserName, filteredCookies); [color=#FF0000]//>>>>> This calls the logic to store the cookie into my local table[/color]
        };
        const auto cookieVisitor = CefWrapper::CefCookieVisitor::build(completionFunction);
        mCefCookieManager->VisitAllCookies(cookieVisitor);
    }


Close application >> and open the application again >> it should fetch cookie from the local table and create cookieManager instance,
Code: Select all
void CookieManager::onDatabaseInitializationStateChanged(DatabaseInitializationState state)
{
    if (state == DatabaseInitializationState::InitialInitComplete)
    {
        loadCookiesFromPersistency();[color=#FF0000] // fetch cookie from table and parse cookieManager Object[/color]
    }
}


and then use the cookie Manager instance to create CEF request context.

Is is possible to set the cookie manager on request context??
I am using
cef_binary_84.3.10+ga46056b+chromium-84.0.4147.105_windows32_minimal
version

Thank you in advance
Attachments
CookieTableSchema.JPG
Cookie table schema
CookieTableSchema.JPG (116.54 KiB) Viewed 5762 times
ramjana
Techie
 
Posts: 15
Joined: Fri Aug 14, 2020 4:08 am

Re: CEF Persist cookie in database(sqlLight)

Postby magreenblatt » Tue Aug 18, 2020 10:48 am

You can get the cookie manager for the request context, and use the available methods to get/set cookies.
magreenblatt
Site Admin
 
Posts: 12402
Joined: Fri May 29, 2009 6:57 pm

Re: CEF Persist cookie in database(sqlLight)

Postby ramjana » Tue Aug 18, 2020 10:09 pm

Thank you Michael! Let me try that.
ramjana
Techie
 
Posts: 15
Joined: Fri Aug 14, 2020 4:08 am

Re: CEF Persist cookie in database(sqlLight)

Postby ramjana » Tue Aug 18, 2020 10:33 pm

Hi magreenblatt,

Does it make sense to override OnRequestContextInitialized to set the cookie manager?

Code: Select all
  ///
  // Called on the browser process UI thread immediately after the request
  // context has been initialized.
  ///
  /*--cef()--*/
  virtual void OnRequestContextInitialized(
      CefRefPtr<CefRequestContext> request_context) {}
ramjana
Techie
 
Posts: 15
Joined: Fri Aug 14, 2020 4:08 am

Re: CEF Persist cookie in database(sqlLight)

Postby ramjana » Thu Aug 20, 2020 7:55 am

I tried get cookie manager from request context and setting cookie before creating browser instance, But doesn't seem to work. I am missing something?

Code: Select all
...........
        requestContext = CefRequestContext::CreateContext(CefRequestContext::GetGlobalContext(), CefRefPtr<RequestContextHandler>(new
                      RequestContextHandler(mCookieStore)));
       
        auto cookieManager = requestContext->GetCookieManager(nullptr);
        cookieManager->FlushStore(nullptr);
        auto cookies = mCoreFramework->getCookieManager()->getCookies(mBrowserName);
        for (const auto& cookie : cookies)
        {
            CefCookie cefCookie;

            CefString(&cefCookie.domain) = cookie->hostKey;
            CefString(&cefCookie.name) = cookie->name;
            CefString(&cefCookie.value) = cookie->value;
            CefString(&cefCookie.path) = cookie->path;

            cef_time_from_timet(cookie->creationUTC, &cefCookie.creation);
            cef_time_from_timet(cookie->expiresUTC, &cefCookie.expires);
            cef_time_from_timet(cookie->lastAccessUTC, &cefCookie.last_access);

            cefCookie.has_expires = cookie->hasExpires;

            cookieManager->SetCookie(buildCookieUrl(cookie), cefCookie, nullptr);
        }
       
        // Create the main browser window.
        if (!CefBrowserHost::CreateBrowser(
                window_info,     // window info
                clientHandler,   // handler
                url,             // url
                browserSettings, // settings
                nullptr,         // extra info
                requestContext)) // request context
        {
            .....................
        }
................
ramjana
Techie
 
Posts: 15
Joined: Fri Aug 14, 2020 4:08 am

Re: CEF Persist cookie in database(sqlLight)

Postby magreenblatt » Thu Aug 20, 2020 10:41 am

Use the async callbacks on GetCookieManager and SetCookie to make sure the manager is initialized, and to check if the cookie was set successfully. After all that is done then create the browser.
magreenblatt
Site Admin
 
Posts: 12402
Joined: Fri May 29, 2009 6:57 pm

Re: CEF Persist cookie in database(sqlLight)

Postby ramjana » Fri Aug 21, 2020 9:09 am

Thanks a lot magreenblatt !!
I tried using async callback and found, mCefCookieManager->SetCookie(...) returns false.
Is there a way to find out what went wrong while setting the cookies? The call back only return success status.
ramjana
Techie
 
Posts: 15
Joined: Fri Aug 14, 2020 4:08 am

Re: CEF Persist cookie in database(sqlLight)

Postby magreenblatt » Fri Aug 21, 2020 10:27 am

Are you calling SetCookie from the GetCookieManager async callback (e.g. after the CookieManager is initialized)? Also check the log for any errors when setting the cookie.
magreenblatt
Site Admin
 
Posts: 12402
Joined: Fri May 29, 2009 6:57 pm

Re: CEF Persist cookie in database(sqlLight)

Postby ramjana » Fri Aug 21, 2020 11:55 am

Thanks for the reply magreenblatt!

Yes, I am calling SetCookie from the GetCookieManager async callback. Below sample,

Code: Select all
class CefCompletionCallback : public ::CefCompletionCallback
    {
    public:
        using CompletionFunc = std::function<void()>;

        CefCompletionCallback(CompletionFunc completionFunc)
            : mCompletionFunc(completionFunc)
        {
        }

        void OnComplete() override
        {
            mCompletionFunc();   
        }

    private:
        CompletionFunc mCompletionFunc;
        IMPLEMENT_REFCOUNTING(CefCompletionCallback);
    };

    class CefSetCookieCallback : public ::CefSetCookieCallback
    {
    public:
        using SetCookieFunc = std::function<void()>;

        CefSetCookieCallback(int count, int total, SetCookieFunc setCookieFunc)
            : mCount(count)
            , mTotal(total)
            , mSetCookieFunc(setCookieFunc)
        {
        }

        void OnComplete(bool success) override
        {
            if (mCount == mTotal)
            {
                mSetCookieFunc();
            }
        }

    private:
        SetCookieFunc mSetCookieFunc;
        int mCount;
        int mTotal;
        IMPLEMENT_REFCOUNTING(CefSetCookieCallback);
    };

.......................

void Browser::createCefRequestContext(const std::string& url, const WindowPtr& window, const IBrowserCallbackPtr& callback, bool background)
    {
        mRequestContext = CefRequestContext::CreateContext(CefRequestContext::GetGlobalContext(), CefRefPtr<RequestContextHandler>(new RequestContextHandler(mCookieStore)));

        auto completionFunction = [this, url, window, callback, background]() {
            RETURN_FROM_LAMBDA_IF_DEAD(mCoreFramework);

            auto cookies = mCoreFramework->getCookieManager()->getCookies(mBrowserName);
            int cookieSetCount = 0;

            if (cookies.size() > 0)
            {
                for (const auto& cookie : cookies)
                {
                    CefCookie cefCookie;

                    CefString(&cefCookie.domain) = cookie->hostKey;
                    CefString(&cefCookie.name) = cookie->name;
                    CefString(&cefCookie.value) = cookie->value;
                    CefString(&cefCookie.path) = cookie->path;

                    cef_time_from_timet(cookie->creationUTC, &cefCookie.creation);
                    cef_time_from_timet(cookie->expiresUTC, &cefCookie.expires);
                    cef_time_from_timet(cookie->lastAccessUTC, &cefCookie.last_access);

                    cefCookie.has_expires = cookie->hasExpires;

                    auto cookieSetFunction = [this, url, window, callback, background, cookieSetCount]() {
                        RETURN_FROM_LAMBDA_IF_DEAD(mCoreFramework);

                        initializeBrowser(url, window, callback, background);
                    };

                    cookieSetCount++;
                    mCefCookieManager->SetCookie(buildCookieUrl(cookie), cefCookie, CefRefPtr<CefSetCookieCallback>(new CefSetCookieCallback(cookieSetCount, cookies.size(), cookieSetFunction)));
                }
            }
            else
            {
                initializeBrowser(url, window, callback, background);
            }
        };

        mCefCookieManager = mRequestContext->GetCookieManager(CefRefPtr<CefCompletionCallback>(new CefCompletionCallback(completionFunction)));
    }
ramjana
Techie
 
Posts: 15
Joined: Fri Aug 14, 2020 4:08 am

Re: CEF Persist cookie in database(sqlLight)

Postby magreenblatt » Fri Aug 21, 2020 12:11 pm

You're not checking the |success| value in CefSetCookieCallback::OnComplete. Also check the log file for any related errors.
magreenblatt
Site Admin
 
Posts: 12402
Joined: Fri May 29, 2009 6:57 pm

Next

Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 43 guests