private void AddCustomScheme(string scheme, ResolveWebResourceDelegate requestHandler) { // Because of WKWebView limitations, this can only be called during the constructor // before the first call to Show. To enforce this, it's private and is only called // in response to the constructor options. WebResourceRequestedCallback callback = (string url, out int numBytes, out string contentType) => { var responseStream = requestHandler(url, out contentType, out Encoding encoding); if (responseStream == null) { // Webview should pass through request to normal handlers (e.g., network) // or handle as 404 otherwise numBytes = 0; return(default);
/// <summary> /// Resolves an Uri to a stream. /// </summary> /// <param name="uri">The uri to resolve.</param> /// <param name="resolveWebResourceDelegate">The delegate to call.</param> /// <returns>A Stream.</returns> private Stream Resolve(string uri, ResolveWebResourceDelegate resolveWebResourceDelegate) { var result = resolveWebResourceDelegate(uri, out string contentType, out Encoding encoding); if (result == null) { throw new ArgumentOutOfRangeException(uri.ToString()); } if (contentType == "text/html") { var finalStream = new MemoryStream((int)result.Length + 100); using (var tempStream = new MemoryStream((int)result.Length + 100)) using (var reader = new StreamReader(result, encoding)) using (var writer = new StreamWriter(tempStream, encoding)) { var defaultHandler = this.schemeHandlers["http"]; var content = reader.ReadToEnd(); foreach (var handler in this.schemeHandlers.Where(s => s.Value != defaultHandler)) { var hash = GetHashString(handler.Key); content = content.Replace($"{handler.Key}://", $"{hash}/"); } writer.Write(content); writer.Flush(); tempStream.Position = 0; tempStream.CopyTo(finalStream); finalStream.Position = 0; } result.Dispose(); result = finalStream; } return(result); }
/// <summary> /// Add a custom scheme with a handler to the webiew. /// </summary> /// <param name="schemeName">The scheme name to handle.</param> /// <param name="handler">The handler for the scheme.</param> internal void AddCustomScheme(string schemeName, ResolveWebResourceDelegate handler) { this.schemeHandlers.Add(schemeName, handler); }
public SchemeHandler(ResolveWebResourceDelegate handler) { this.handler = handler; }
/// <summary> /// Initializes a new instance of the <see cref="UrlSchemeHandler"/> class. /// </summary> /// <param name="requestHandler">A reference to the requesthandler delegate.</param> public UrlSchemeHandler(ResolveWebResourceDelegate requestHandler) { this.requestHandler = requestHandler; }
/// <summary> /// Runs Blazor using the specified <see cref="IBlazorWebView"/> implementation, /// using the path to the index.html host file and optionally a delegate to /// resolve the normal (non framework) resources. /// </summary> /// <typeparam name="TStartup">A startup class.</typeparam> /// <param name="blazorWebView">An <see cref="IBlazorWebView"/> implementation.</param> /// <param name="hostHtmlPath">The specified oath to the index.html file.</param> /// <param name="defaultResolveDelegate">An optional delegate to resolve non framework resources.</param> /// <returns>An <see cref="IDisposable "/> instance that can be used to cleanup Blazor.</returns> public static IDisposable Run <TStartup>(IBlazorWebView blazorWebView, string hostHtmlPath, ResolveWebResourceDelegate defaultResolveDelegate = null) { if (defaultResolveDelegate == null) { var contentRootAbsolute = Path.GetDirectoryName(Path.GetFullPath(hostHtmlPath)); defaultResolveDelegate = (string url, out string contentType, out Encoding encoding) => { // TODO: Only intercept for the hostname 'app' and passthrough for others // TODO: Prevent directory traversal? var appFile = Path.Combine(contentRootAbsolute, new Uri(url).AbsolutePath.Substring(1)); if (appFile == contentRootAbsolute) { appFile = hostHtmlPath; } contentType = GetContentType(appFile); if (!File.Exists(appFile)) { encoding = Encoding.Default; return(null); } return(GetEncodingAndOpen(appFile, out encoding)); }; } BlazorWebView = blazorWebView; BlazorWebView.Initialize(options => { options.SchemeHandlers.Add(BlazorAppScheme, defaultResolveDelegate); // framework:// is resolved as embedded resources options.SchemeHandlers.Add("framework", (string url, out string contentType, out Encoding encoding) => { contentType = GetContentType(url); encoding = Encoding.UTF8; return(SupplyFrameworkFile(url)); }); }); CancellationTokenSource appLifetimeCts = new CancellationTokenSource(); Task.Factory.StartNew(async() => { try { var ipc = new IPC(BlazorWebView); await RunAsync <TStartup>(ipc, appLifetimeCts.Token); } catch (Exception ex) { UnhandledException(ex); throw; } }); try { BlazorWebView.NavigateToUrl(BlazorAppScheme + "://app/"); } catch { appLifetimeCts.Cancel(); throw; } return(new DelegateDisposable(() => appLifetimeCts.Cancel())); }
/// <summary> /// Adds a custom scheme handler to the collection of schemes to handle. /// </summary> /// <param name="webConfig">The webiew configuration.</param> /// <param name="scheme">The scheme to use.</param> /// <param name="requestHandler">The handler for the scheme.</param> private void AddCustomScheme(WKWebViewConfiguration webConfig, string scheme, ResolveWebResourceDelegate requestHandler) { var urlSchemeHandler = new UrlSchemeHandler(requestHandler); webConfig.SetUrlSchemeHandler(urlSchemeHandler, scheme); }
/// <summary> /// Adds a scheme handler to the EdgeResolver. /// </summary> /// <param name="schemeName">The name of the scheme.</param> /// <param name="handler">The handler.</param> public void AddSchemeHandler(string schemeName, ResolveWebResourceDelegate handler) { this.schemeHandlers.Add(schemeName, handler); }