Skip to content

Commit

Permalink
Mac: Fix issue with WebView on Mojave.
Browse files Browse the repository at this point in the history
Switch to a custom implementation of the delegates instead of events as using events causes all delegate methods to be "implemented" (by obj-c standards).
  • Loading branch information
cwensley committed Sep 28, 2018
1 parent 6b3a15e commit 1bcd8ea
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 60 deletions.
124 changes: 66 additions & 58 deletions src/Eto.Mac/Forms/Controls/WebViewHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,74 @@ protected override wk.WebView CreateControl()
return new EtoWebView(this);
}

public class EtoWebPolicyDelegate : wk.WebPolicyDelegate
{
WeakReference handler;
public WebViewHandler Handler { get => handler?.Target as WebViewHandler; set => handler = new WeakReference(value); }

public override void DecidePolicyForNavigation(wk.WebView webView, NSDictionary actionInformation, NSUrlRequest request, wk.WebFrame frame, NSObject decisionToken)
{
var h = Handler;
if (h != null)
{
var args = new WebViewLoadingEventArgs(new Uri(request.Url.AbsoluteString), frame == h.Control.MainFrame);
h.Callback.OnDocumentLoading(h.Widget, args);
if (args.Cancel)
decisionToken.PerformSelector(selIgnore, null, 0);
else
decisionToken.PerformSelector(selUse, null, 0);
}
}

public override void DecidePolicyForNewWindow(wk.WebView webView, NSDictionary actionInformation, NSUrlRequest request, string newFrameName, NSObject decisionToken)
{
var h = Handler;
if (h != null)
{
var args = new WebViewNewWindowEventArgs(new Uri(request.Url.AbsoluteString), newFrameName);
h.Callback.OnOpenNewWindow(h.Widget, args);
if (!args.Cancel)
NSWorkspace.SharedWorkspace.OpenUrl(request.Url);
decisionToken.PerformSelector(selIgnore, null, 0);
}
}

}

public class EtoWebFrameLoadDelegate : wk.WebFrameLoadDelegate
{
WeakReference handler;
public WebViewHandler Handler { get => handler?.Target as WebViewHandler; set => handler = new WeakReference(value); }

public override void FinishedLoad(wk.WebView sender, wk.WebFrame forFrame)
{
var h = Handler;
if (h != null)
{
var args = new WebViewLoadedEventArgs(h.Url);
if (forFrame == h.Control.MainFrame)
h.Callback.OnNavigated(h.Widget, args);
h.Callback.OnDocumentLoaded(h.Widget, args);
}
}

public override void ReceivedTitle(wk.WebView sender, string title, wk.WebFrame forFrame)
{
var h = Handler;
if (h != null)
{
h.Callback.OnDocumentTitleChanged(h.Widget, new WebViewTitleEventArgs(title));
}
}
}

protected override void Initialize()
{
Enabled = true;
base.Initialize();
HandleEvent(WebView.OpenNewWindowEvent); // needed to provide default implementation
HandleEvent(WebView.DocumentLoadingEvent);

Control.FrameLoadDelegate = new EtoWebFrameLoadDelegate { Handler = this };
Control.PolicyDelegate = new EtoWebPolicyDelegate { Handler = this };
}

public class EtoWebView : wk.WebView, IMacControl
Expand Down Expand Up @@ -219,71 +281,17 @@ public override void AttachEvent(string id)
HandleEvent(WebView.DocumentLoadedEvent);
break;
case WebView.DocumentLoadedEvent:
Control.FinishedLoad += HandleFinishedLoad;
break;
case WebView.DocumentLoadingEvent:
Control.DecidePolicyForNavigation += HandleDecidePolicyForNavigation;
break;
case WebView.OpenNewWindowEvent:
Control.DecidePolicyForNewWindow += HandleDecidePolicyForNewWindow;
break;
case WebView.DocumentLoadingEvent:
case WebView.DocumentTitleChangedEvent:
Control.ReceivedTitle += HandleReceivedTitle;
// handled by delegates
break;
default:
base.AttachEvent(id);
break;
}
}

static void HandleReceivedTitle(object sender, wk.WebFrameTitleEventArgs e)
{
var handler = GetHandler(e.ForFrame.WebView) as WebViewHandler;
if (handler != null)
{
handler.Callback.OnDocumentTitleChanged(handler.Widget, new WebViewTitleEventArgs(e.Title));
}
}

static void HandleDecidePolicyForNewWindow(object sender, wk.WebNewWindowPolicyEventArgs e)
{
var handler = GetHandler(sender) as WebViewHandler;
if (handler != null)
{
var args = new WebViewNewWindowEventArgs(new Uri(e.Request.Url.AbsoluteString), e.NewFrameName);
handler.Callback.OnOpenNewWindow(handler.Widget, args);
if (!args.Cancel)
NSWorkspace.SharedWorkspace.OpenUrl(e.Request.Url);
e.DecisionToken.PerformSelector(selIgnore, null, 0);
}
}

static void HandleDecidePolicyForNavigation(object sender, wk.WebNavigationPolicyEventArgs e)
{
var handler = GetHandler(e.Frame.WebView) as WebViewHandler;
if (handler != null)
{
var args = new WebViewLoadingEventArgs(new Uri(e.Request.Url.AbsoluteString), e.Frame == handler.Control.MainFrame);
handler.Callback.OnDocumentLoading(handler.Widget, args);
if (args.Cancel)
e.DecisionToken.PerformSelector(selIgnore, null, 0);
else
e.DecisionToken.PerformSelector(selUse, null, 0);
}
}

static void HandleFinishedLoad(object sender, wk.WebFrameEventArgs e)
{
var handler = GetHandler(e.ForFrame.WebView) as WebViewHandler;
if (handler != null)
{
var args = new WebViewLoadedEventArgs(handler.Url);
if (e.ForFrame == handler.Control.MainFrame)
handler.Callback.OnNavigated(handler.Widget, args);
handler.Callback.OnDocumentLoaded(handler.Widget, args);
}
}

public Uri Url
{
get { return new Uri(Control.MainFrameUrl); }
Expand Down
9 changes: 9 additions & 0 deletions test/Eto.Test.Mac/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,14 @@
<string>10.7</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
<key>NSAllowsLocalNetworking</key>
<true/>
</dict>
</dict>
</plist>
4 changes: 2 additions & 2 deletions test/Eto.Test/Sections/Controls/WebViewSection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ Control LoadUrl()
dialog.MinimumSize = new Size(300, 0);

var layout = new DynamicLayout();
var textBox = new TextBox { Text = "http://google.com" };
var textBox = new TextBox { Text = "https://google.com" };
var goButton = new Button { Text = "Go" };
dialog.DefaultButton = goButton;
goButton.Click += (sender, e) => dialog.Close(true);
Expand All @@ -405,7 +405,7 @@ Control LoadUrl()
}
}
else
webView.Url = new Uri("http://google.com");
webView.Url = new Uri("https://google.com");
};
return control;
}
Expand Down

0 comments on commit 1bcd8ea

Please sign in to comment.