Cookie Delay

Made a cool mod to CEF that you'd like to share with others? Discuss CEF modifications here, and view modifications that others have made.

Cookie Delay

Postby SynapseJumps » Sun May 08, 2016 5:45 pm

Hey Everybody,

I've got a very simple cookie-based application that is showing unexpected behavior in my CEF browser versus a conventional Chrome or IE browser. The app, pictured in the attached, just keeps track of the times at which a flag is set in a cookie. The PHP code is straightforward:
Code: Select all
<?php

// Keep a list of each time we set the cookie
if (isset($_GET["set"]))
{
   // Keep the cookie around for 3 days for this entire domain
    setcookie("flag", (isset($_COOKIE["flag"]) ? $_COOKIE["flag"] : "") .
                   "time: ". time() . "<br>\r\n",
            time()+60*60*24*3, "/");
   
    $_COOKIE["flag"] = (isset($_COOKIE["flag"]) ? $_COOKIE["flag"] : "") .
                   "time: ". time() . "<br>\r\n";
    $_GET["show"] = 1;
}

// Pop the first flag timestamp off the list
else if (isset($_GET["unset"]))
{
   if (isset($_COOKIE["flag"]))
       setcookie("flag", strstr(strstr($_COOKIE["flag"], "<br>\r\n"), "time:") ,time()+60*60*24*3, "/");
   
   $_COOKIE["flag"] =
      strstr(strstr($_COOKIE["flag"], "<br>\r\n"), "time:");
   $_GET["show"] = 1;
}

if (isset($_GET["clear"]))
{
   setcookie("flag", "", time()+60*60*24*3, "/");
   
   $_COOKIE["flag"] = "";
   $_GET["show"] = 1;
}
echo "<center>";
echo "It's a cookie app!<br>\r\n";
echo "<a href=\"?show\">Show</a>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;";
echo "<a href=\"?set\">Set</a>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;";
echo "<a href=\"?show\">Show</a>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;";
echo "<a href=\"?unset\">Unset</a>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;";
echo "<a href=\"?show\">Show</a>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;";
echo "<a href=\"?clear\">Clear</a>&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp;";
echo "<a href=\"?show\">Show</a>";
echo "<br>\r\n<br>\r\n";
echo (isset($_COOKIE["flag"]) ? $_COOKIE["flag"] : "");
echo "</center>";

 ?>


So! That's the code I'm using to test out and profile this issue. The issue that I'm observing is a substantial delay in cookie write speeds. If I build up a few timestamps in the cookie, like in the attached image, and then I quickly clear them and close the browser, I would expect that when I navigate back to the cookie app in a new window my list would be empty. In Chrome and IE, this is definitely the case. In my CEF application, however, it is not. There seems to be a delay between when a cookie is written and accessible in program memory and when that value gets committed to the file system.

My CEF application's cookie management is relatively straight forward. I have based my implementation of Cookie Management off an old forum posting from back in 2014. I base my application off CEF Simple, so my cookie manager comes into play in OnContextInitialized:
Code: Select all
void MyApp::OnContextInitialized() {
  CEF_REQUIRE_UI_THREAD();

  // Information used when creating the native window.
  CefWindowInfo window_info;

   #if defined(OS_WIN)
     // Set Window Size... Boring stuff...
   #endif

  // SimpleHandler implements browser-level callbacks.
  CefRefPtr<MyApp_Handler> handler(new MyApp_Handler());

  // Specify CEF browser settings here.
  CefBrowserSettings browser_settings;

  // Here's where I implement the cookie manager!
  CefRefPtr<CefRequestContext> rc = CefRequestContext::CreateContext(new WXRequestContextHandler());

  // Create the first browser window.
  CefBrowserHost::CreateBrowser(window_info, handler.get(), "mycookieapp.com",
                                browser_settings, rc);
}


The code for the RequestContextHandler is also very straight-forward:
Code: Select all
class WXRequestContextHandler :public CefRequestContextHandler
{
public:
   CefRefPtr<CefCookieManager> ourMan;

   WXRequestContextHandler()
   {
      CHAR szPath[MAX_PATH];
                // Create our path... Boring stuff
      this->ourMan = CefCookieManager::CreateManager(szPath, TRUE);      
   }
   ~WXRequestContextHandler(){};
   CefRefPtr<CefCookieManager> GetCookieManager() OVERRIDE{

      return this->ourMan;
   }

private:
   // Include the default reference counting implementation.
   IMPLEMENT_REFCOUNTING(WXRequestContextHandler);
};


So... Is there a way that I can get my cookies to "take hold" on the file system more quickly in my CEF Application? I'm pretty sure it's not by web-app that's the limiting factor, here. Can I, for example, flush the contents of the cookie in memory to the file system more often?
SynapseJumps
Newbie
 
Posts: 9
Joined: Mon May 11, 2015 5:36 pm

Re: Cookie Delay

Postby magreenblatt » Mon May 09, 2016 9:37 am

What OS and CEF version? How are you running the CEF message loop? Are you calling CefShutdown? How does it behave if you use the global cookie manager instead of a custom cookie manager?
magreenblatt
Site Admin
 
Posts: 9988
Joined: Fri May 29, 2009 6:57 pm

Re: Cookie Delay

Postby SynapseJumps » Mon May 09, 2016 11:35 am

Hey magreenblatt,

Excellent questions! This application is running on Windows 7. The applicaion is based off cef_binary_3.2171.1979_windows32. I understand this is an old build, but I've not run into any insurmountable problems due to the age of the build, yet. Maybe this is the first?

It's been a while since I poured through my WinMain in the application, but it looks like:
Code: Select all
// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPTSTR    lpCmdLine,
                      int       nCmdShow) {

  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);

  void* sandbox_info = NULL;

#if defined(CEF_USE_SANDBOX)
  // Manage the life span of the sandbox information object. This is necessary
  // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
  CefScopedSandboxInfo scoped_sandbox;
  sandbox_info = scoped_sandbox.sandbox_info();
#endif

  // Provide CEF with command-line arguments.
  CefMainArgs main_args(hInstance);

  // SimpleApp implements application-level callbacks. It will create the first
  // browser instance in OnContextInitialized() after CEF has initialized.
  CefRefPtr<MyApp> app(new MyApp);

  // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
  // that share the same executable. This function checks the command-line and,
  // if this is a sub-process, executes the appropriate logic.
  int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);
  if (exit_code >= 0) {
    // The sub-process has completed so return here.
    return exit_code;
  }


#if !defined(CEF_USE_SANDBOX)
  settings.no_sandbox = true;
#endif

  // Specify CEF global settings here.
  CefSettings settings;
  CefString(&settings.cache_path) = szPath;

  // Initialize CEF.
  CefInitialize(main_args, settings, app.get(), sandbox_info);

  // Run the CEF message loop. This will block until CefQuitMessageLoop() is called
  CefRunMessageLoop();

  // Shut down CEF.
  CefShutdown();

  return 0;
}


So I'm using the standard CefRunMessageLoop. I'm not handling the messages myself. CefShutdown is being called in a fairly conventional fashion. When I close the application, I'm just Alt-F4'ing. Is it possible that this is somehow bypassing CefShutdown?

I made a special build to try working with the Global Cookie Manager, instead. I made a simple code change:
Code: Select all
class WXRequestContextHandler :public CefRequestContextHandler
{
public:
   CefRefPtr<CefCookieManager> ourMan;

   WXRequestContextHandler()
   {

      this->ourMan = CefCookieManager::GetGlobalManager();
      /*  NOT THIS TIME!
         this->ourMan = CefCookieManager::CreateManager(szPath, TRUE);
      */
      
   }

   ~WXRequestContextHandler(){};

   CefRefPtr<CefCookieManager> GetCookieManager() OVERRIDE{

      return this->ourMan;
   }

private:
   // Include the default reference counting implementation.
   IMPLEMENT_REFCOUNTING(WXRequestContextHandler);
};


I hope this is what you meant when you suggested trying the GlobalCookieManager. If not, please let me know and I'll try again. When I run with the Global Cookie Manager implemented as above, cookies seem to be completely disabled. When I dial up my lame cookie app (from the first post), it works during one browsing session, but doesn't seem to maintain any memory of cookie flags when restarting browsing sessions (that is -- after Alt-F4'ing out of my app and restarting it).

Thanks for all your help in this issue magreenblatt. I appreciate all your ideas and suggestions and, of course, your fantastic work on CEF. Any more ideas?
Last edited by SynapseJumps on Mon May 09, 2016 1:00 pm, edited 1 time in total.
SynapseJumps
Newbie
 
Posts: 9
Joined: Mon May 11, 2015 5:36 pm

Re: Cookie Delay

Postby magreenblatt » Mon May 09, 2016 11:49 am

You need to set CefSettings.cache_path to persist data across restarts.
magreenblatt
Site Admin
 
Posts: 9988
Joined: Fri May 29, 2009 6:57 pm

Re: Cookie Delay

Postby SynapseJumps » Mon May 09, 2016 1:01 pm

Whoops! Touche! My mistake...

I've implemented the cache_path (see my previous post in the WinMain section -- nothing you wouldn't expect) and see that cookies are now functioning. I'm seeing the same substantial delay, though, in writing the cookie to the file system.
SynapseJumps
Newbie
 
Posts: 9
Joined: Mon May 11, 2015 5:36 pm

Re: Cookie Delay

Postby magreenblatt » Mon May 09, 2016 1:25 pm

SynapseJumps wrote:Whoops! Touche! My mistake...

I've implemented the cache_path (see my previous post in the WinMain section -- nothing you wouldn't expect) and see that cookies are now functioning. I'm seeing the same substantial delay, though, in writing the cookie to the file system.

There should be a delay in writing cookies to the filesystem. However, all cookies should be written when you exit the application cleanly and CefShutdown is called.
magreenblatt
Site Admin
 
Posts: 9988
Joined: Fri May 29, 2009 6:57 pm

Re: Cookie Delay

Postby SynapseJumps » Mon May 09, 2016 3:43 pm

magreenblatt wrote:However, all cookies should be written when you exit the application cleanly and CefShutdown is called.


Hmm... I've gone ahead and changed my WinMain to ensure that CefShutdown is being called and we're not accidentally taking some stupid execution path through the program:
Code: Select all
// Entry point function for all processes.
int APIENTRY wWinMain(HINSTANCE hInstance,
                      HINSTANCE hPrevInstance,
                      LPTSTR    lpCmdLine,
                      int       nCmdShow) {

  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);

  void* sandbox_info = NULL;

#if defined(CEF_USE_SANDBOX)
  // Manage the life span of the sandbox information object. This is necessary
  // for sandbox support on Windows. See cef_sandbox_win.h for complete details.
  CefScopedSandboxInfo scoped_sandbox;
  sandbox_info = scoped_sandbox.sandbox_info();
#endif

  // Provide CEF with command-line arguments.
  CefMainArgs main_args(hInstance);

  // SimpleApp implements application-level callbacks. It will create the first
  // browser instance in OnContextInitialized() after CEF has initialized.
  CefRefPtr<MyApp> app(new MyApp);

  // CEF applications have multiple sub-processes (render, plugin, GPU, etc)
  // that share the same executable. This function checks the command-line and,
  // if this is a sub-process, executes the appropriate logic.
  int exit_code = CefExecuteProcess(main_args, app.get(), sandbox_info);
  if (exit_code >= 0) {
    // The sub-process has completed so return here.
    return exit_code;
  }

  // Specify CEF global settings here.
  CefSettings settings;

  CHAR szPath[MAX_PATH];
  if (SUCCEEDED(SHGetFolderPathA(NULL,
     CSIDL_LOCAL_APPDATA,
     NULL,
     0,
     szPath)))
  {
     PathAppendA(szPath, "MyApp");
     CefString(&settings.cache_path) = szPath;
  }

#if !defined(CEF_USE_SANDBOX)
  settings.no_sandbox = true;
#endif

  // Initialize CEF.
  CefInitialize(main_args, settings, app.get(), sandbox_info);

  // Run the CEF message loop. This will block until CefQuitMessageLoop() is called.
  CefRunMessageLoop();

  // Shut down CEF.
  CefShutdown();
  MessageBox(NULL, L"We exited normally!", L"Alert!", 0);

  return 0;
}


When experiencing this issue, I'm always getting the "We exited normally" message box, but my cookies aren't being written to the file system. Is it possible that CefShutdown is silently failing? Is there another way that I can flush the cookie to the file system manually? How can I probe this harder?
SynapseJumps
Newbie
 
Posts: 9
Joined: Mon May 11, 2015 5:36 pm

Re: Cookie Delay

Postby magreenblatt » Mon May 09, 2016 3:51 pm

Are the cookies never written? Or will they be written if you wait long enough?

2171 is quite an old branch. You should upgrade as the problem may already be fixed.
magreenblatt
Site Admin
 
Posts: 9988
Joined: Fri May 29, 2009 6:57 pm

Re: Cookie Delay

Postby SynapseJumps » Mon May 09, 2016 4:00 pm

magreenblatt wrote:Are the cookies never written? Or will they be written if you wait long enough?

The cookies will be written if I wait long enough.

magreenblatt wrote:2171 is quite an old branch. You should upgrade as the problem may already be fixed.

Very reasonable. I'll begin the process of upgrading to branch 2556 right now. I'll post back and let you know how it works.

EDIT: Wait... no. Instead, I'll be upgrading to branch 2623. Because it's more recent. I think all I need to do is replace libcef.dll, right? And maybe the library that my application links against?
SynapseJumps
Newbie
 
Posts: 9
Joined: Mon May 11, 2015 5:36 pm

Re: Cookie Delay

Postby magreenblatt » Mon May 09, 2016 4:12 pm

The header files will have changed, so you need to compile libcef_dll_wrapper and your application using the newest source code.
magreenblatt
Site Admin
 
Posts: 9988
Joined: Fri May 29, 2009 6:57 pm


Return to Modifications Forum

Who is online

Users browsing this forum: No registered users and 2 guests