-2

We had CefSharp calling a project deployed on IIS. That worked. And a cookie I need for the third party library is loaded successfully.

Now we want CefSharp to load the same html and third party library through disk, bypassing IIS. Files are loading and running complete with functioning javascript, however the third party library requires a "domain name" to match the one associated with the license.

I need my domain name to match the one on my license which was generated with domain=localhost. But once I specify a domain name, the page, including the license checker, doesn't load.

This is a related problem. A cookie I need to load loads succesfully when I use csharp to call the IIS project, but fails when I open up the html project from disk. For reference, static void FrameLoaded is the same cookie loading procedure used in both versions of my project.

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MinRepExample2
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;



namespace MinRepExample2
{
    public partial class Form1 : Form
    {

        private ChromiumWebBrowser browser;
        public Form1()
        {
            InitializeComponent();

            try
            {
                string siteURL = "";
                string FileBase = @"c:\users\romero.ryan\documents\visual studio 2015\Projects\MinRepExample2";
                string CacheDir = FileBase+@"\Cef2";



                // CefSettings to temporarily reduce security
                CefSettings MySettings = new CefSettings();

                MySettings.CachePath = CacheDir;


                MySettings.CefCommandLineArgs.Add("enable-media-stream", "enable-media-stream");
                MySettings.CefCommandLineArgs.Add("allow-file-access-from-files", "allow-file-access-from-files");
                MySettings.CefCommandLineArgs.Add("disable-web-security", "disable-web-security");



                MySettings.JavascriptFlags = "--expose-wasm";



                // Browser Settings

                BrowserSettings browserSettings = new BrowserSettings();
                browserSettings.FileAccessFromFileUrls = CefState.Enabled;
                browserSettings.LocalStorage = CefState.Enabled;
                browserSettings.UniversalAccessFromFileUrls = CefState.Enabled;
                browserSettings.WebSecurity = CefState.Disabled;


                // Custom Scheme Registration
                MySettings.RegisterScheme(new CefCustomScheme
                {
                    SchemeName = MySchemeHandlerFactory.SchemeName,
                    SchemeHandlerFactory = new MySchemeHandlerFactory(),
                    IsFetchEnabled = true,
                    IsLocal = false,
                    IsCorsEnabled = true,
                    IsSecure = true,


                    //DomainName= @"\Users\romero.ryan"
                      DomainName = "localhost"


                });




                CefSharpSettings.LegacyJavascriptBindingEnabled = true;

                if (!Cef.IsInitialized)
                {
                    Cef.Initialize(MySettings);
                }


                //string fName = @"C:\Users\romero.ryan\Documents\Visual Studio 2015\Projects\WinHostScandit1\WebHostOnDisk\CefPrimeFiles";

                //c:\users\romero.ryan\documents\visual studio 2015\Projects\MinRepExample2\TestSite.html



                browser = new ChromiumWebBrowser(@"fileProtocol:\\" + FileBase + "\\TestSite.html");

                browser.BrowserSettings = browserSettings;
                browser.Dock = DockStyle.Fill;

                browser.Name = "browser";

                browser.LoadingStateChanged += FrameLoaded;

                this.Controls.Add(browser);

            }
            catch (Exception ex)
            {

                throw ex;
            }

        }


        public  void FrameLoaded(object sender, LoadingStateChangedEventArgs e)
        {

            //ChromiumWebBrowser ans = (ChromiumWebBrowser)Controls.Find("browser", false).First();



            if (!e.IsLoading)
            {
                // CefSharp specific Cookie manipulation to register app as single device used with Scandit Library. 

                // ADD Cookie in C# code. Also adding in javascript code

                var cookman = browser.GetCookieManager();
                string[] schemes = { "fileProtocol", "fileprotocol", "fileprotocol:", "fileProtocol:" };

                cookman.SetSupportedSchemes(schemes, true);

                CefSharp.Cookie cook1 = new CefSharp.Cookie();
                cook1.Domain = "localhost";
                cook1.Name = "scandit-device-id";
                cook1.Value = "ffaf4f340998d137fc260d563004eabcd388e90f";
                cook1.Path = "/scanditpage";
                cook1.Expires = new DateTime(2029, 6, 17);
                // cookman.SetCookieAsync(ConfigurationManager.AppSettings["ScanditURL"], cook1);

                var respcook = cookman.SetCookieAsync("http://localhost/scanditpage/ScanditTest.html", cook1);
                bool cookieSet = cookman.SetCookie("http://localhost/scanditpage/ScanditTest.html", cook1);
                CefSharpSettings.LegacyJavascriptBindingEnabled = true;
                //cookman.SetCookie

                // Adding Test cookie
                browser.ExecuteScriptAsync("TestAddCookie()");

                // Launches Dev tools for Debugging Purposes. 
                browser.ShowDevTools();
            }


        }
    }
}

MySchemeHandler.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp;
using System.IO;

namespace MinRepExample2
{
    public class MySchemeHandler : ResourceHandler
    {
        public const string SchemeName = "fileProtocol";
        private string folderPath;

        public MySchemeHandler()
        {
            folderPath = "";

        }


        public override CefSharp.CefReturnValue ProcessRequestAsync(IRequest request, ICallback callback)
        {
            var uri = new Uri(request.Url);
            string fileName = uri.LocalPath;


            var requestedFilePath = "C:/" + fileName;

            string bFileName = "";

            bFileName = requestedFilePath;

            if (File.Exists(bFileName))
            {
                byte[] bytes = File.ReadAllBytes(bFileName);
                Stream = new MemoryStream(bytes);


                var fileExtension = Path.GetExtension(bFileName);
                MimeType = GetMimeType(fileExtension);

                return CefReturnValue.Continue;

                //return true;
            }
            else
            {

                throw new FileNotFoundException();
            }



            callback.Dispose();

            return CefReturnValue.Continue;


        }
    }
}

MySchemeHandlerFactory:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CefSharp;
namespace MinRepExample2
{
    public class MySchemeHandlerFactory: ISchemeHandlerFactory
    {

        public const string SchemeName = "fileProtocol";


        public IResourceHandler Create(IBrowser browser, IFrame frame, string schemeName, IRequest request)
        {
            return new MySchemeHandler();
        }
    }
}

Testing HTML:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Test Site for CefSharp Cookies</title>

    <script type="text/javascript">


        function AddCookie(name, value) {
            // Add cookie as name value pair.
            var newcookie = name + "=" + value + ";";
            document.cookie=newcookie
        }

        function TestAddCookie() {
            // Add specific cookie. Called from executescript in FrameLoaded method
            AddCookie("name", "everlast");

        }

        function ButtonCookie() {
            //Adds cookie by button click, then displays all available cookies. 
            AddCookie("button", "clicked");
            var decodedCookie = decodeURIComponent(document.cookie);
            alert(decodedCookie);
        }

    </script>


</head>
<body>
    <div>Hello, World!</div>
    <button onclick="ButtonCookie();">Add Cookie</button>

</body>
</html>
R. Romero
  • 117
  • 1
  • 8
  • You are incorrectly setting IsLocal = true – amaitland Sep 04 '19 at 21:22
  • problem persists if IsLocal left blank or set to false. – R. Romero Sep 04 '19 at 21:39
  • Your example is incomplete so I cannot say. Please read https://stackoverflow.com/help/minimal-reproducible-example – amaitland Sep 04 '19 at 23:56
  • @amaitland, I've included the entirety of my static class responsible for loading the page. When I comment out the DomainName line in Scheme Registration, the page works, but the domain name mismatch causes a third party library to fail. – R. Romero Sep 05 '19 at 14:29
  • I might close this question. The library won't work without successful loading of cookies. That might be the only way it tests domain compatibility. Once I fix that, this still might be a problem. – R. Romero Sep 05 '19 at 18:55
  • @amaitland, I've added a minimum example. Everything works complete with cookies until I set the domain name in Form.cs for the scheme handler. Afterwards what appears to be a default mostly empty page comes up. document.domain returns empty string. Left blink,document.domain outputs 'c'. I think what I want to to do is load html from disk, but associate with it a different url. – R. Romero Sep 10 '19 at 14:15
  • I think the issue is I need to use a cookie from domain=localhost path=/x, but when loading files from disk, bypassing webserver, the associated domain and path are derived from the disk path. The mismatch causes the cookie to be ignored. The scheme handler also needs to match the domain, causing nothing to be loaded. Is there a way to load files from "C:\blah" but associate with the site "domainX/PathY"? – R. Romero Sep 10 '19 at 16:48
  • Yes, there is a default implementation for this purpose see http://cefsharp.github.io/api/75.1.x/html/T_CefSharp_SchemeHandler_FolderSchemeHandlerFactory.htm – amaitland Sep 10 '19 at 20:28
  • Also read https://github.com/cefsharp/CefSharp/wiki/General-Usage#scheme-handler – amaitland Sep 10 '19 at 20:28

1 Answers1

0

I figured it out from advice from amaitland and this answer: Simple Custom Scheme.

CefSettings allows you to set permissions like allowing CORS and Fetch for loading WASM files. CefSettings is also used for registering custom scheme handlers. Some schemes might need special permissions to load dependent javascript libraries. Permissions associated with this variable must be set before calling Cef.Initialize. Cef.Initialize should not be called after new ChromiumWebBrowser();

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp;
using CefSharp.WinForms;
using CefSharp.SchemeHandler;


namespace EpmsMobileWF.ScanditWebForm
{
    public partial class ScanditPopupForm : Form
    {

        public static ScanditPopupConfig scanditConfigs;
        public static JSObj1 mess;
        public ChromiumWebBrowser browser;


        public ScanditPopupForm(TextBox inForm)
        {
            InitializeComponent();
            InitScanner();
            mess = new JSObj1(inForm, this);

        }

        public void  InitScanner()
        {
            scanditConfigs = new ScanditPopupConfig();
            var settings = new CefSettings();
            FolderSchemeHandlerFactory newFac = new FolderSchemeHandlerFactory(scanditConfigs.HTMLRootFolder,null, scanditConfigs.DomainName, "ScanditTest.html");

            CefCustomScheme ScanditScheme = new CefCustomScheme
            {
                SchemeName = "http",
                DomainName = scanditConfigs.DomainName,
                SchemeHandlerFactory = newFac,
            };

            ScanditScheme.IsCorsEnabled = true;
            ScanditScheme.IsFetchEnabled = true;
            ScanditScheme.IsLocal = true;
            ScanditScheme.IsStandard = true;


            settings.CachePath = scanditConfigs.ScanditCacheDirectory;

            settings.CefCommandLineArgs.Add("enable-media-stream", "enable-media-stream");
            settings.CefCommandLineArgs.Add("allow-file-access-from-files", "allow-file-access-from-files");

            settings.PersistSessionCookies = true;
            settings.JavascriptFlags = "--expose-wasm";



            settings.RegisterScheme(ScanditScheme);

            Cef.Initialize(settings);

            browser = new ChromiumWebBrowser(scanditConfigs.ScanditURL);

            this.Controls.Add(browser);
            browser.Dock = DockStyle.Fill;

        }


    }
}
R. Romero
  • 117
  • 1
  • 8