summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorE.Z. Hart <hartez@users.noreply.github.com>2016-08-03 15:22:14 -0600
committerJason Smith <jason.smith@xamarin.com>2016-08-03 14:22:14 -0700
commitb186254d1f4a0547c67f4fd30669df9d4cf36b65 (patch)
tree6278a0f3217c726aed4e29c2027b10eb61522aeb
parentb60fa6acf84d897d6283310e58b1c6c6365c391c (diff)
downloadxamarin-forms-b186254d1f4a0547c67f4fd30669df9d4cf36b65.tar.gz
xamarin-forms-b186254d1f4a0547c67f4fd30669df9d4cf36b65.tar.bz2
xamarin-forms-b186254d1f4a0547c67f4fd30669df9d4cf36b65.zip
Enable WebView to render local HTML files on WinRT platforms (#277)
* Enable WebView to render local HTML files on WinRT platforms * Add test to demonstrate that the solution works even if <head> isn't in the HTML string
-rw-r--r--Xamarin.Forms.ControlGallery.WP8/local.html2
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/WebImages/XamarinLogo.pngbin0 -> 6990 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj3
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/default.css2
-rw-r--r--Xamarin.Forms.ControlGallery.Windows/local.html10
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/WebImages/XamarinLogo.pngbin0 -> 6990 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj3
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/default.css2
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsPhone/local.html10
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/WebImages/XamarinLogo.pngbin0 -> 6990 bytes
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj3
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/default.css2
-rw-r--r--Xamarin.Forms.ControlGallery.WindowsUniversal/local.html10
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32033.cs141
-rw-r--r--Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems1
-rw-r--r--Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs59
16 files changed, 240 insertions, 8 deletions
diff --git a/Xamarin.Forms.ControlGallery.WP8/local.html b/Xamarin.Forms.ControlGallery.WP8/local.html
index b1998a12..6ef9746b 100644
--- a/Xamarin.Forms.ControlGallery.WP8/local.html
+++ b/Xamarin.Forms.ControlGallery.WP8/local.html
@@ -4,7 +4,7 @@
</head>
<body>
<h1>Xamarin.Forms</h1>
-<p>This is a local iOS Html page</p>
+<p>This is a local HTML page</p>
</body>
</html> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Windows/WebImages/XamarinLogo.png b/Xamarin.Forms.ControlGallery.Windows/WebImages/XamarinLogo.png
new file mode 100644
index 00000000..361e2782
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/WebImages/XamarinLogo.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj b/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj
index c93c45b9..aa8f862f 100644
--- a/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj
+++ b/Xamarin.Forms.ControlGallery.Windows/Xamarin.Forms.ControlGallery.Windows.csproj
@@ -189,7 +189,10 @@
<Content Include="Assets\SplashScreen.scale-100.png" />
<Content Include="Assets\StoreLogo.scale-100.png" />
<Content Include="coffee.png" />
+ <Content Include="default.css" />
+ <Content Include="local.html" />
<Content Include="toolbar_close.png" />
+ <Content Include="WebImages\XamarinLogo.png" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
diff --git a/Xamarin.Forms.ControlGallery.Windows/default.css b/Xamarin.Forms.ControlGallery.Windows/default.css
new file mode 100644
index 00000000..9e32b419
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/default.css
@@ -0,0 +1,2 @@
+html,body{margin:0;padding:10}
+body,p,h1{font-family:Chalkduster;font-style: italic;} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.Windows/local.html b/Xamarin.Forms.ControlGallery.Windows/local.html
new file mode 100644
index 00000000..6ef9746b
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.Windows/local.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<link rel="stylesheet" href="default.css">
+</head>
+<body>
+<h1>Xamarin.Forms</h1>
+<p>This is a local HTML page</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/WebImages/XamarinLogo.png b/Xamarin.Forms.ControlGallery.WindowsPhone/WebImages/XamarinLogo.png
new file mode 100644
index 00000000..361e2782
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/WebImages/XamarinLogo.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj b/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj
index 16a042b0..a8565433 100644
--- a/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/Xamarin.Forms.ControlGallery.WindowsPhone.csproj
@@ -166,7 +166,10 @@
<Content Include="Assets\StoreLogo.scale-240.png" />
<Content Include="Assets\WideLogo.scale-240.png" />
<Content Include="coffee.png" />
+ <Content Include="default.css" />
+ <Content Include="local.html" />
<Content Include="toolbar_close.png" />
+ <Content Include="WebImages\XamarinLogo.png" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/default.css b/Xamarin.Forms.ControlGallery.WindowsPhone/default.css
new file mode 100644
index 00000000..9e32b419
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/default.css
@@ -0,0 +1,2 @@
+html,body{margin:0;padding:10}
+body,p,h1{font-family:Chalkduster;font-style: italic;} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsPhone/local.html b/Xamarin.Forms.ControlGallery.WindowsPhone/local.html
new file mode 100644
index 00000000..6ef9746b
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsPhone/local.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<link rel="stylesheet" href="default.css">
+</head>
+<body>
+<h1>Xamarin.Forms</h1>
+<p>This is a local HTML page</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/WebImages/XamarinLogo.png b/Xamarin.Forms.ControlGallery.WindowsUniversal/WebImages/XamarinLogo.png
new file mode 100644
index 00000000..361e2782
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/WebImages/XamarinLogo.png
Binary files differ
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj
index d5339b71..a4952000 100644
--- a/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/Xamarin.Forms.ControlGallery.WindowsUniversal.csproj
@@ -117,8 +117,11 @@
</ItemGroup>
<ItemGroup>
<Content Include="coffee.png" />
+ <Content Include="default.css" />
<Content Include="invalidimage.jpg" />
+ <Content Include="local.html" />
<Content Include="toolbar_close.png" />
+ <Content Include="WebImages\XamarinLogo.png" />
<None Include="project.json" />
<Content Include="..\Xamarin.Forms.ControlGallery.WP8\bank.png">
<Link>bank.png</Link>
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/default.css b/Xamarin.Forms.ControlGallery.WindowsUniversal/default.css
new file mode 100644
index 00000000..9e32b419
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/default.css
@@ -0,0 +1,2 @@
+html,body{margin:0;padding:10}
+body,p,h1{font-family:Chalkduster;font-style: italic;} \ No newline at end of file
diff --git a/Xamarin.Forms.ControlGallery.WindowsUniversal/local.html b/Xamarin.Forms.ControlGallery.WindowsUniversal/local.html
new file mode 100644
index 00000000..6ef9746b
--- /dev/null
+++ b/Xamarin.Forms.ControlGallery.WindowsUniversal/local.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<link rel="stylesheet" href="default.css">
+</head>
+<body>
+<h1>Xamarin.Forms</h1>
+<p>This is a local HTML page</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32033.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32033.cs
new file mode 100644
index 00000000..2576525a
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Bugzilla32033.cs
@@ -0,0 +1,141 @@
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+
+namespace Xamarin.Forms.Controls
+{
+ [Preserve (AllMembers = true)]
+ [Issue (IssueTracker.Bugzilla, 32033, "WebView on Windows does not display local HTML files", PlatformAffected.WinRT)]
+ public class Bugzilla32033 : TestNavigationPage
+ {
+ protected override void Init ()
+ {
+ PushAsync(Menu());
+ }
+
+ ContentPage Menu()
+ {
+ var page = new ContentPage();
+
+ var layout = new StackLayout();
+
+ var buttonLocal = new Button() {Text = "Local HTML file"};
+ buttonLocal.Clicked += (sender, args) => Navigation.PushAsync(LocalUrl());
+
+ var buttonHtmlString = new Button() {Text = "HTML string with links/refs to local files"};
+ buttonHtmlString.Clicked += (sender, args) => Navigation.PushAsync(HtmlString());
+
+ var buttonHtmlStringNoHead = new Button() {Text = "HTML string with links/refs to local files (no <head>)"};
+ buttonHtmlStringNoHead.Clicked += (sender, args) => Navigation.PushAsync(HtmlStringNoHead());
+
+ layout.Children.Add(buttonLocal);
+ layout.Children.Add(buttonHtmlString);
+ layout.Children.Add(buttonHtmlStringNoHead);
+
+ page.Content = layout;
+
+ return page;
+ }
+
+ static ContentPage LocalUrl()
+ {
+ var page = new ContentPage();
+
+ var instructions = new Label
+ {
+ Text = @"The WebView below should contain the heading 'Xamarin Forms' and text reading 'This is a local HTML page'. All text should be italicized."
+ };
+
+ var webView = new WebView
+ {
+ WidthRequest = 300,
+ HeightRequest = 500,
+ HorizontalOptions = LayoutOptions.Fill,
+ VerticalOptions = LayoutOptions.Fill,
+ Source = new UrlWebViewSource() { Url = "local.html" }
+ };
+
+ var layout = new StackLayout { Children = { instructions, webView } };
+ page.Content = layout;
+
+ return page;
+ }
+
+ static ContentPage HtmlString()
+ {
+ var page = new ContentPage();
+
+ var instructions = new Label
+ {
+ Text =
+@"The WebView below should contain the heading 'Xamarin Forms', display the Xamarin logo, and have a link labeled 'next page'.
+Clicking that link should navigate to a page with the heading 'Xamarin Forms' and text reading 'This is a local HTML page'. All text on both pages should be italicized."
+ };
+
+ var webView = new WebView
+ {
+ WidthRequest = 300,
+ HeightRequest = 500,
+ HorizontalOptions = LayoutOptions.Fill,
+ VerticalOptions = LayoutOptions.Fill,
+ Source = new HtmlWebViewSource
+ {
+ Html = @"<html>
+<head>
+<link rel=""stylesheet"" href=""default.css"">
+</head>
+<body>
+<h1>Xamarin.Forms</h1>
+<p>The CSS and image are loaded from local files!</p>
+<img src='WebImages/XamarinLogo.png'/>
+<p><a href=""local.html"">next page</a></p>
+</body>
+</html>"
+ }
+ };
+
+
+ var layout = new StackLayout {HorizontalOptions = LayoutOptions.Fill, VerticalOptions = LayoutOptions.Fill, Children = { instructions, webView } };
+ page.Content = layout;
+
+ return page;
+ }
+
+ // This test verifies that the <base> injection solution works even if the HTML string doesn't explicitly include a <head> section
+ static ContentPage HtmlStringNoHead()
+ {
+ var page = new ContentPage();
+
+ var instructions = new Label
+ {
+ Text =
+@"The WebView below should contain the heading 'Xamarin Forms', display the Xamarin logo, and have a link labeled 'next page'.
+Clicking that link should navigate to a page with the heading 'Xamarin Forms' and text reading 'This is a local HTML page'. "
+ };
+
+ var webView = new WebView
+ {
+ WidthRequest = 300,
+ HeightRequest = 500,
+ HorizontalOptions = LayoutOptions.Fill,
+ VerticalOptions = LayoutOptions.Fill,
+ Source = new HtmlWebViewSource
+ {
+ Html = @"<html>
+<body>
+<h1>Xamarin.Forms</h1>
+<p>The CSS and image are loaded from local files!</p>
+<img src='WebImages/XamarinLogo.png'/>
+<p><a href=""local.html"">next page</a></p>
+</body>
+</html>"
+ }
+ };
+
+
+ var layout = new StackLayout {HorizontalOptions = LayoutOptions.Fill, VerticalOptions = LayoutOptions.Fill, Children = { instructions, webView } };
+ page.Content = layout;
+
+ return page;
+ }
+ }
+} \ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
index 4fdb18fd..8d1e0b40 100644
--- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
@@ -46,6 +46,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla31333.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla31366.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla31964.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Bugzilla32033.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla32034.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla32776.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Bugzilla32842.xaml.cs">
diff --git a/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs
index 78d69abd..e3fcb898 100644
--- a/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs
+++ b/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs
@@ -1,8 +1,14 @@
using System;
+using System.Collections.Generic;
using System.ComponentModel;
+using System.Diagnostics;
+using System.Threading.Tasks;
using Windows.UI.Core;
+using Windows.UI.WebUI;
using Windows.UI.Xaml.Controls;
+using Windows.Web.Http;
using Xamarin.Forms.Internals;
+using static System.String;
#if WINDOWS_UWP
@@ -16,19 +22,59 @@ namespace Xamarin.Forms.Platform.WinRT
{
WebNavigationEvent _eventState;
bool _updating;
+ const string LocalScheme = "ms-appx-web:///";
+
+ // Script to insert a <base> tag into an HTML document
+ const string BaseInsertionScript = @"
+var head = document.getElementsByTagName('head')[0];
+var bases = head.getElementsByTagName('base');
+if(bases.length == 0){
+ head.innerHTML = 'baseTag' + head.innerHTML;
+}";
public void LoadHtml(string html, string baseUrl)
{
- /*
- * FIXME: If baseUrl is a file URL, set the Base property to its path.
- * Otherwise, it doesn't seem as if WebBrowser can handle it.
- */
- Control.NavigateToString(html);
+ if (IsNullOrEmpty(baseUrl))
+ {
+ baseUrl = LocalScheme;
+ }
+
+ // Generate a base tag for the document
+ var baseTag = $"<base href=\"{baseUrl}\"></base>";
+
+ string htmlWithBaseTag;
+
+ // Set up an internal WebView we can use to load and parse the original HTML string
+ var internalWebView = new Windows.UI.Xaml.Controls.WebView();
+
+ // When the 'navigation' to the original HTML string is done, we can modify it to include our <base> tag
+ internalWebView.NavigationCompleted += async (sender, args) =>
+ {
+ // Generate a version of the <base> script with the correct <base> tag
+ var script = BaseInsertionScript.Replace("baseTag", baseTag);
+
+ // Run it and retrieve the updated HTML from our WebView
+ await sender.InvokeScriptAsync("eval", new[] { script });
+ htmlWithBaseTag = await sender.InvokeScriptAsync("eval", new[] { "document.documentElement.outerHTML;" });
+
+ // Set the HTML for the 'real' WebView to the updated HTML
+ Control.NavigateToString(!IsNullOrEmpty(htmlWithBaseTag) ? htmlWithBaseTag : html);
+ };
+
+ // Kick off the initial navigation
+ internalWebView.NavigateToString(html);
}
public void LoadUrl(string url)
{
- Control.Source = new Uri(url);
+ Uri uri = new Uri(url, UriKind.RelativeOrAbsolute);
+
+ if (!uri.IsAbsoluteUri)
+ {
+ uri = new Uri(LocalScheme + url, UriKind.RelativeOrAbsolute);
+ }
+
+ Control.Source = uri;
}
protected override void Dispose(bool disposing)
@@ -165,7 +211,6 @@ namespace Xamarin.Forms.Platform.WinRT
_eventState = WebNavigationEvent.NewPage;
}
- // Nasty hack because we cant bind this because OneWayToSource isn't a thing in WP8, yay
void UpdateCanGoBackForward()
{
Element.CanGoBack = Control.CanGoBack;