Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 72 additions & 44 deletions src/SyncTrayzor/Pages/ViewerViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@
using CefSharp;
using CefSharp.Wpf;
using SyncTrayzor.Services.Config;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using SyncTrayzor.Services;
using SyncTrayzor.Properties;
using Microsoft.WindowsAPICodePack.Dialogs;
using CefSharp.Handler;
using PropertyChanged;
using SyncTrayzor.Localization;

namespace SyncTrayzor.Pages
{
public class ViewerViewModel : Screen, IResourceRequestHandlerFactory, ILifeSpanHandler, IContextMenuHandler,
IDisposable
{
private const int ErrorSharingViolation = unchecked((int)0x80070020);

private readonly IWindowManager windowManager;
private readonly ISyncthingManager syncthingManager;
private readonly IProcessStartProvider processStartProvider;
Expand All @@ -30,6 +32,7 @@ public class ViewerViewModel : Screen, IResourceRequestHandlerFactory, ILifeSpan
private readonly CustomResourceRequestHandler customResourceRequestHandler;

private readonly object cultureLock = new(); // This can be read from many threads
private readonly Lock _initLock = new();
private CultureInfo? culture;
private double zoomLevel;

Expand Down Expand Up @@ -109,58 +112,83 @@ protected override void OnInitialActivate()
language = culture!.Name;
}

var cefLogFile = pathsProvider.LogFilePath + @"\cef.log";
var settings = new CefSettings()
lock (_initLock)
{
RemoteDebuggingPort = AppSettings.Instance.CefRemoteDebuggingPort,
// We really only want to set the LocalStorage path, but we don't have that level of control....
CachePath = pathsProvider.CefCachePath,
LogFile = cefLogFile,
IgnoreCertificateErrors = true,
LogSeverity = LogSeverity.Warning,
AcceptLanguageList = language,
Locale = language
};

// CEF will attempt de-elevating the process when launched as admin. This is done by relaunching
// the current process in unprivileged mode. However, we're not equipped to handle such a
// process restart cleanly, so ask CEF to not relaunch. Running as admin is not ideal for security,
// but the user wants it...
settings.CefCommandLineArgs.Add("do-not-de-elevate");

// System proxy settings (which also specify a proxy for localhost) shouldn't affect us
settings.CefCommandLineArgs.Add("no-proxy-server", "1");
settings.CefCommandLineArgs.Add("disable-cache", "1");
settings.CefCommandLineArgs.Add("disable-extensions", "1");

if (configuration.DisableHardwareRendering)
{
settings.CefCommandLineArgs.Add("disable-gpu");
settings.CefCommandLineArgs.Add("disable-gpu-vsync");
// It may happen that we have another SyncTrazyor instance using the same CEF cache path
// This will cause a generic CEF initialization failure. Try to catch this early
// by acquiring the log file.
var cefCachePath = pathsProvider.CefCachePath;
var cefLock = cefCachePath + @"\lockfile";
try
{
settings.CefCommandLineArgs.Add("disable-gpu-compositing");
using var lockFile = new FileStream(cefLock, FileMode.OpenOrCreate, FileAccess.ReadWrite,
FileShare.None);
}
catch (IOException e) when (e.HResult == ErrorSharingViolation)
{
var msg = Localizer.Translate("ViewerView_CefCacheLocked", cefCachePath);
var title = Localizer.Translate("ViewerView_CefCacheLocked_Title");
windowManager.ShowMessageBox(msg, title, MessageBoxButton.OK, MessageBoxImage.Error);
Environment.Exit(1);
}
catch (ArgumentException)
catch (Exception)
{
// CefSharp 139+ may set this by default, ignore if unable to set the flag.
// Ignore potentially unrelated errors
}

settings.CefCommandLineArgs.Add("disable-application-cache");
}
var cefLogFile = pathsProvider.LogFilePath + @"\cef.log";
var settings = new CefSettings()
{
RemoteDebuggingPort = AppSettings.Instance.CefRemoteDebuggingPort,
// We really only want to set the LocalStorage path, but we don't have that level of control....
CachePath = cefCachePath,
LogFile = cefLogFile,
IgnoreCertificateErrors = true,
LogSeverity = LogSeverity.Warning,
AcceptLanguageList = language,
Locale = language
};

// CEF will attempt de-elevating the process when launched as admin. This is done by relaunching
// the current process in unprivileged mode. However, we're not equipped to handle such a
// process restart cleanly, so ask CEF to not relaunch. Running as admin is not ideal for security,
// but the user wants it...
settings.CefCommandLineArgs.Add("do-not-de-elevate");

// System proxy settings (which also specify a proxy for localhost) shouldn't affect us
settings.CefCommandLineArgs.Add("no-proxy-server", "1");
settings.CefCommandLineArgs.Add("disable-cache", "1");
settings.CefCommandLineArgs.Add("disable-extensions", "1");

if (configuration.DisableHardwareRendering)
{
settings.CefCommandLineArgs.Add("disable-gpu");
settings.CefCommandLineArgs.Add("disable-gpu-vsync");
try
{
settings.CefCommandLineArgs.Add("disable-gpu-compositing");
}
catch (ArgumentException)
{
// CefSharp 139+ may set this by default, ignore if unable to set the flag.
}

settings.CefCommandLineArgs.Add("disable-application-cache");
}

try
{
if (!Cef.Initialize(settings))
try
{
throw new InvalidOperationException("Unable to initialize CEF.");
if (!Cef.Initialize(settings))
{
throw new InvalidOperationException("Unable to initialize CEF.");
}
}
catch (InvalidOperationException e)
{
throw new AggregateException(
$"SyncTrayzor was unable to initialize its embedded browser.\nWhen reporting this issue, please attach the CEF logfile @ \n{cefLogFile}\n in addition to this message and the normal SyncTrayzor logfile.",
e);
}
}
catch (InvalidOperationException e)
{
throw new AggregateException(
$"SyncTrayzor was unable to initialize its embedded browser.\nWhen reporting this issue, please attach the CEF logfile @ \n{cefLogFile}\n in addition to this message and the normal SyncTrayzor logfile.",
e);
}
}

Expand Down
8 changes: 8 additions & 0 deletions src/SyncTrayzor/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1014,4 +1014,12 @@ Please donate to the syncthing project.</value>
<value>[File Deleted]</value>
<comment>When the base file for a conflict is not found, this placeholder is shown instead of the actual file name</comment>
</data>
<data name="ViewerView_CefCacheLocked" xml:space="preserve">
<value>SyncTrayzor detected that another instance is currently running using the same configuration. Please stop any other SyncTrayzor instances, or restart your system to close them.</value>
<comment>Shown when the embedded browser cannot acquire exclusive access to its cache folder, because another SyncTrayzor instance is running in a different location.</comment>
</data>
<data name="ViewerView_CefCacheLocked_Title" xml:space="preserve">
<value>Conflicting SyncTrayzor processes detected</value>
<comment>Title of the window when the ViewerView_CefCacheLocked message is displayed</comment>
</data>
</root>