Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
41b22f5
initial
NickSpag Aug 27, 2020
e915cd3
assets fix
NickSpag Aug 27, 2020
c830c53
adjust key
NickSpag Aug 27, 2020
80cb52e
hashset backed
NickSpag Aug 27, 2020
6b1d984
add the adguard blocklist file for now
NickSpag Aug 28, 2020
9e433fb
change blocker to static class
NickSpag Aug 28, 2020
f85b625
background the blocker load in app delegate
NickSpag Aug 28, 2020
211f7f8
Merge remote-tracking branch 'origin/master' into feature/ad-blocking
NickSpag Sep 30, 2020
56120d2
content rules in filesystem helper
NickSpag Oct 1, 2020
517e979
mv filestructure method to filesystem helper
NickSpag Oct 1, 2020
3d5cad4
impl contentblocker compilation
NickSpag Oct 1, 2020
3690f09
change to safariTest.json
NickSpag Oct 1, 2020
f767107
use new content compil method name
NickSpag Oct 1, 2020
4809280
Merge branch 'master' into feature/ad-blocking
NickSpag Oct 1, 2020
c415f07
rm filter list
NickSpag Oct 2, 2020
aa3e3d5
add safari rules
NickSpag Oct 2, 2020
148ef00
refactor contentblocker to a rulelist provider
NickSpag Oct 2, 2020
f266149
general logger improvements
NickSpag Oct 2, 2020
af48f94
refactor event registering
NickSpag Oct 2, 2020
4bc5b9f
initialization refactoring
NickSpag Oct 2, 2020
e431bdd
expose off thread content rule initialization
NickSpag Oct 2, 2020
aeebc92
consume contentrule when creating WKWebKit
NickSpag Oct 2, 2020
13dc590
rm old content list
NickSpag Oct 3, 2020
3cca301
refactor back to checking if list is available
NickSpag Oct 4, 2020
498b736
bump realm to 5.1
NickSpag Oct 4, 2020
6fe18d7
switch to exception catch vs id lookup
NickSpag Oct 4, 2020
7eab0fc
rm unnecessary portion of url history query
NickSpag Oct 4, 2020
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
86 changes: 60 additions & 26 deletions source/Roam.macOS/AppDelegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Microsoft.AppCenter;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;
using WebKit;

namespace Roam.macOS
{
Expand All @@ -15,32 +16,85 @@ public partial class AppDelegate : NSApplicationDelegate, INSWindowRestoration
const string AppCenterKey = "36109d82-252b-4bd5-b3c7-3fa12c15457e";

private static WindowRestorer windowRestorer;
private Task<WKContentRuleList> contentBlockerLoading;

private bool firstContentRuleAccess = true;
private WKContentRuleList _contentRuleList;
public WKContentRuleList ContentRuleList
{
get
{
if(_contentRuleList is null)
{
if (contentBlockerLoading.IsCompleted)
{
_contentRuleList = contentBlockerLoading.Result;
}
else if(firstContentRuleAccess)
{
firstContentRuleAccess = false;

Help.Logger.WriteWarning("ContentRuleList was not compiled by the time of first access");
}
}

return _contentRuleList;
}
}

//TODO: Make this a download manager, implement the cookie thing?, and add it to appdelegate
public Downloader downloader;

public AppDelegate()
{
AppCenter.Start($"macos={AppCenterKey};", typeof(Analytics), typeof(Crashes));

RegisterForAppEvents();

contentBlockerLoading = ContentBlocking.PrepareRuleList();
}

public override void DidFinishLaunching(NSNotification notification)
{
AppCenter.Start($"macos={AppCenterKey};", typeof(Analytics), typeof(Crashes));
try
{

#if !DEBUG
Help.Logger.RedirectConsoleLogging();
Help.Logger.RedirectConsoleLogging();
#endif

Help.StartUp.Run();

NSUserDefaults.StandardUserDefaults.SetBool(true, "NSQuitAlwaysKeepsWindows");

CompleteWindowLaunchProcess();
}
catch (Exception ex)
{
Crashes.TrackError(ex);
}
}

#region General App Events
private void RegisterForAppEvents()
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
}

Help.StartUp.Run();
private void DeregisterForAppEvents()
{
AppDomain.CurrentDomain.UnhandledException -= CurrentDomain_UnhandledException;
TaskScheduler.UnobservedTaskException -= TaskScheduler_UnobservedTaskException;
}

NSUserDefaults.StandardUserDefaults.SetBool(true, "NSQuitAlwaysKeepsWindows");
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) =>
Help.Logger.WriteUnhandledException(sender, e);

CompleteWindowLaunchProcess();
}
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) =>
Help.Logger.WriteUnobservedTaskException(sender, e);

#endregion

#region UI Menu Actions
partial void OpenSpacesMenuClicked(NSObject sender)
Expand Down Expand Up @@ -102,26 +156,6 @@ private void CompleteWindowLaunchProcess()
}
}

private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
System.Console.WriteLine($"**{(e.IsTerminating ? "CRASHING:" : "")} UNHANDLED EXCEPTION");

if(e.ExceptionObject is Exception exception)
{
System.Console.WriteLine($" {exception.Message}");
}
else
{
System.Console.WriteLine($" non-exception object of type {e.ExceptionObject.GetType()}: {e.ExceptionObject}");
}
}

private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
System.Console.WriteLine("**UNOBSERVED TASK EXCEPTION: In an async Task");
System.Console.WriteLine(" " + e.Exception.Message);
}

/// <summary>
/// Restores a window that AppKit saved. This is called for each restorable window detected. On it's first run,
/// it instantiates the WindowRestorer that this AppDelegate will hold, statically (by requirement),
Expand Down
67 changes: 67 additions & 0 deletions source/Roam.macOS/Common/ContentBlocker.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using Foundation;
using WebKit;

namespace Roam.macOS
{
public static class ContentBlocking
{
private const string DefaultListIdentifier = "RoamContentBlockingList";

public static async Task<WKContentRuleList> PrepareRuleList()
{
var ruleStore = WKContentRuleListStore.FromUrl(Help.FileSystem.ContentStoreDirectory);

// LookUpContentRule throws an exception if unavailable, so we wrap it in try catch and use
// it as a signal to know the rulelist hasnt been compiled yet (first run of the app, probably)
//
// We could check what rules are available but that is another async call that, in testing,
// typically means the first WKWebView is created prior to rulelist being retreived
try
{
return await ruleStore.LookUpContentRuleListAsync(DefaultListIdentifier);
}
catch (Exception ex)
{
return await CompileBlockingList(ruleStore);
}
}

private static async Task<WKContentRuleList> CompileBlockingList(WKContentRuleListStore ruleStore)
{
string resourceName = "safariTestBase";

try
{
if (NSBundle.MainBundle.PathForResource(resourceName, "json") is string blockListPath)
{
if (await File.ReadAllTextAsync(blockListPath) is string rulesJson)
{
if (await ruleStore.CompileContentRuleListAsync(DefaultListIdentifier, rulesJson)
is WKContentRuleList compiledRuleList)
{
return compiledRuleList;
}
else LogError("Unable to compile the rule list.");
}
else LogError("Unable to find block list in bundled resource");
}
else LogError("Unable to read the block list from resource bundle.");
}
catch (Exception ex)
{
Help.Logger.WriteException(ex, "EXCEPTION while compile the rule list.");
}

return null;

void LogError(string message)
{
Help.Logger.WriteError(message);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using WebKit;
using AppKit;
using WebKit;

namespace Roam.macOS
{
Expand All @@ -16,6 +17,10 @@ public override WKWebView CreateWebView(WKWebView webView,
WKNavigationAction navigationAction,
WKWindowFeatures windowFeatures)
{
if(((AppDelegate)NSApplication.SharedApplication.Delegate).ContentRuleList is WKContentRuleList ruleList)
{
configuration.UserContentController.AddContentRuleList(ruleList);
}

switch (navigationAction.NavigationType)
{
Expand Down
13 changes: 13 additions & 0 deletions source/Roam.macOS/Helpers/FileSystem.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using Foundation;

namespace Roam.macOS
{
Expand All @@ -9,6 +10,9 @@ public static class FileSystem
{
private const string devAppName = "Roam-Dev";
private const string appName = "Roam";
private const string contentRuleStoreName = "content-blocking";

private static string contentStoreFolder => Path.Combine(CurrentRoamAppSupportFolder, contentRuleStoreName);

public static string DevRoamAppSupportFolder => Path.Combine(AppSupportFolder, devAppName);
public static string ReleaseRoamAppSupportFolder => Path.Combine(AppSupportFolder, appName);
Expand All @@ -20,6 +24,9 @@ public static class FileSystem
ReleaseRoamAppSupportFolder;
#endif

public static NSUrl ContentStoreDirectory =>
new NSUrl(Path.Combine(CurrentRoamAppSupportFolder, contentRuleStoreName), isDir: true);

private static string AppSupportFolder
{
get
Expand All @@ -29,6 +36,12 @@ private static string AppSupportFolder
return Path.Combine(libraryFolder, "Application Support");
}
}

public static void EnsureAppsFileStructureExists()
{
Directory.CreateDirectory(CurrentRoamAppSupportFolder);
Directory.CreateDirectory(contentStoreFolder);
}
}
}
}
66 changes: 65 additions & 1 deletion source/Roam.macOS/Helpers/Logger.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,31 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Microsoft.AppCenter.Analytics;
using Microsoft.AppCenter.Crashes;

namespace Roam.macOS
{
public static partial class Help
{
internal class UnknownUnhandledException : Exception
{
public UnknownUnhandledException()
{

}
}

public static class Logger
{
private const string GeneralErrorEvent = nameof(GeneralErrorEvent);
private const string GeneralWarningEvent = nameof(GeneralWarningEvent);

public static string LogFile => Path.Combine(Help.FileSystem.CurrentRoamAppSupportFolder, "log.txt");


public static void RedirectConsoleLogging()
{
var fileStream = new FileStream(Help.Logger.LogFile, FileMode.Append);
Expand All @@ -33,6 +49,12 @@ public static void WriteInvalidStateError(string infoMessage, [CallerMemberName]
//This represents an error that should never happen, so a breakpoint should be kept here to flag us in debug, no matter what we're doing.
System.Console.WriteLine($" INVALID-STATE found within {callerMember}");
System.Console.WriteLine($" -info: {infoMessage}");

Crashes.TrackError(new IllegalAppStateRepresented(), new Dictionary<string, string>
{
{ "caller", callerMember },
{ "message", infoMessage },
});
}

/// <summary>
Expand All @@ -42,7 +64,24 @@ public static void WriteInvalidStateError(string infoMessage, [CallerMemberName]
/// <param name="callerMember"></param>
public static void WriteWarning(string warningMessage, [CallerMemberName] string callerMember = "")
{
System.Console.WriteLine($" Warning from {callerMember}: {warningMessage}");
Analytics.TrackEvent(GeneralWarningEvent, new Dictionary<string, string>
{
{ "caller", callerMember },
{ "message", warningMessage },
});

System.Diagnostics.Debug.WriteLine($" Warning from {callerMember}: {warningMessage}");
}

public static void WriteError(string errorMessage, [CallerMemberName] string callerMember = "")
{
Analytics.TrackEvent(GeneralErrorEvent, new Dictionary<string, string>
{
{ "caller", callerMember },
{ "message", errorMessage },
});

System.Diagnostics.Debug.WriteLine($" Error from {callerMember}: {errorMessage}");
}

/// <summary>
Expand All @@ -56,6 +95,31 @@ public static void WriteException(Exception ex, string infoMessage, [CallerMembe
System.Console.WriteLine($" Exception occurred and caught within {callerMember}");
System.Console.WriteLine($" -info: {infoMessage}");
System.Console.WriteLine($" -ex: {ex.Message}");

Crashes.TrackError(ex, new Dictionary<string, string>() { { "message", infoMessage } });
}

public static void WriteUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
System.Console.WriteLine($"**{(e.IsTerminating ? "CRASHING:" : "")} UNHANDLED EXCEPTION");

if (e.ExceptionObject is Exception exception)
{
Crashes.TrackError(exception, new Dictionary<string, string>() { { "isTerminating", e.IsTerminating.ToString() } });

System.Console.WriteLine($" {exception.Message}");
}
else
{
Crashes.TrackError(new UnknownUnhandledException(), new Dictionary<string, string>() { { "isTerminating", e.IsTerminating.ToString() } });

System.Console.WriteLine($" non-exception object of type {e.ExceptionObject.GetType()}: {e.ExceptionObject}");
}
}

public static void WriteUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
WriteException(e.Exception, $"Unobserved task exception in async task, {e.Exception.Message}");
}

private static void WriteBeginSessionMessage()
Expand Down
6 changes: 2 additions & 4 deletions source/Roam.macOS/Helpers/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,11 @@ public static class StartUp

public static void Run()
{
EnsureFileStructureExists();
Help.FileSystem.EnsureAppsFileStructureExists();

VerifyRealmFiles();
}

private static void EnsureFileStructureExists() =>
Directory.CreateDirectory(Help.FileSystem.CurrentRoamAppSupportFolder);

private static void VerifyRealmFiles()
{
bool databaseNeedsCreated = !File.Exists(Help.RealmDB.RealmPath);
Expand Down
Loading