Welcome to MSDN Blogs Sign in | Join | Help

Bringing more HTML to Silverlight [HtmlTextBlock improvements]

I blogged about my HtmlTextBlock implementation for Silverlight a few days ago. In that post I described HtmlTextBlock as a "plug-compatible" replacement for TextBlock that knows how to take simple HTML (technically XHTML) and display it in a manner that fairly closely approximates how a web browser does. The responses I've gotten suggest HtmlTextBlock is somewhat popular, so I've spent a bit of time improving upon the original implementation. The HtmlTextBlock demonstration and source code linked to by my earlier post have been updated, so feel free to play along as you read the notes:

HtmlTextBlock Demonstration Page

Notes:

  • I loved the simplicity of using an XmlReader to parse the input to HtmlTextBlock, but I worried that the prevalence of non-XHTML would limit the usefulness of HtmlTextBlock. For example, the following invalid XHTML would fail to parse correctly: foo<b>bar</i>baz. During an informal discussion, Ted Glaza suggested using the browser's Document Object Model to do the parsing of invalid XHTML - great idea! :)
    • So now when its Text property is set, HtmlTextBlock first treats the input as valid XHTML and tries to parse it with XmlReader. This is the most efficient code path and should be successful for any valid XHTML input.
    • However, if the input can't be parsed in that manner, HtmlTextBlock uses the objects in Silverlight's System.Windows.Browser namespace to dynamically insert the provided text into the host browser's DOM, run some JavaScript code to transform the input into valid XHTML, then extract and parse the transformed text with XmlReader as before.
    • Two techniques are tried:
      • The first method works in browsers that return XHTML for an element's innerHTML property even if the contents of the element are not valid XHTML (ex: Firefox) and simply inserts and retrieves XHTML from the innerHTML property.
      • The second method works in browsers that return the contents of an element as-is (ex: Internet Explorer (though it works fine in Firefox, too)) by walking the node's .firstChild/.nextSibling/.nodeName tree and manually building up the corresponding XHTML as the nodes of the tree are visited. The results of this method appear ideal in most scenarios, though it's possible to come up with edge cases where its output is slightly different from that of the browser itself (Internet Explorer): foo<b><i>bar</b>baz.
    • Strangely, BOTH browsers prefer <br> to <br/>, going as far as transforming the latter into the former despite the fact that doing so creates invalid XHTML!
    • If all parsing attempts fail, the supplied text is used as-is with no formatting applied.
    Unfortunately, there's a catch... Depending on the content of the text, adding it to the DOM could insert untrusted HTML into the host browser's page. A malicious user with control of the text could use the following approach to run their own JavaScript code in the context of the user's browser (Firefox only): </div><script>alert('Script code running!');</script>. As such, the new DOM parsing behavior is disabled by default and can be enabled by setting the UseDomAsParser property of HtmlTextBlock for scenarios when the input text is known to be safe.
  • A kind reader informed me that an HtmlTextBlock created in code (vs. in XAML as my sample demonstrated) did not seem to do text wrapping properly. The problem was caused by the difference in when the Control.Loaded event fires in the two scenarios. The fix is a simple change to HandleLoaded that skips sizing the contained TextBlock if the HtmlTextBlock hasn't been sized itself. Additionally, the sample code now demonstrates how to create a HtmlTextBlock in code - just #define CREATE_IN_CODE to see how.
  • Because HtmlTextBlock used bool variables to track the bold/italic/underline states, nesting a style caused that style to be prematurely removed. Specifically, the following scenario would not display properly: normal <b>bold <b>also bold</b> still bold</b> normal. HtmlTextBlock now handles nesting properly by using int variables.
  • I mentioned last time that making HtmlTextBlock adhere to all the individual browser quirks would be a daunting task. For fun, here's a simple input to demonstrate the point: <p>hello world</p>. Firefox (and HtmlTextBlock) leaves some space above the text because of the <p> element; Internet Explorer does not. :)

In its introductory post, I said that HtmlTextBlock is obviously nothing like a complete HTML rendering engine - and that statement remains true today. However, by taking advantage of the host browser's DOM to transform invalid XHTML input, HtmlTextBlock is much more flexible than it used to be. That - and a few fixes - makes it an even more compelling option for rich text display in Silverlight!

Published Monday, September 24, 2007 11:15 AM by Delay
Filed under:

Comments

# Techy News Blog &raquo; Bringing more HTML to Silverlight [HtmlTextBlock improvements]

# re: Bringing more HTML to Silverlight [HtmlTextBlock improvements]

Tuesday, September 25, 2007 2:30 AM by rbirkby

Inject the HTML into an IFrame in a different security context. This will give you the security you need.

# re: Bringing more HTML to Silverlight [HtmlTextBlock improvements]

Tuesday, September 25, 2007 11:19 AM by Delay

rbirkby,

Thanks very much for the suggestion! If you have a pointer to more information about this approach, I'd love to understand the implications a little better. According to my current understanding, moving to an IFRAME might let me use a different security context, but if I can't also turn off JavaScript entirely then I'm concerned the basic vulnerability still exists - even if it's limited to annoying alert dialogs.

On a related note, my concern about searching for "<script>...</script>" and ignoring it is that clever folks might be able to sneak the tags through anyway (ex: "<script >", etc.). I know I could use a Regex to do a pretty good job, but the underlying issue still concerns me. And even if I believed I'd addressed the <script> concern, I'd be worried about something like <img ... onload="..." /> where script runs for an event handler instead.

So if you've got a suggestion that lets me disable script entirely, then I'm definitely interested! :)

# Silverlight Cream for September 25, 2007

Tuesday, September 25, 2007 2:30 PM by WynApse

Silverlight Cream for September 25, 2007

# re: Bringing more HTML to Silverlight [HtmlTextBlock improvements]

Tuesday, October 09, 2007 9:03 AM by michael.tucker@getronics.com

Thanks a bunch for this great control!  It beings much needed HTML functionality back into Silverlight.  Any way to get the links to actually fire?  Maybe via a HtmlPage.Navigate() call or something?

# re: Bringing more HTML to Silverlight [HtmlTextBlock improvements]

Tuesday, October 09, 2007 1:40 PM by Delay

Michael,

I explain why links don't navigate in the third "note" of the initial post. Per your suggestion, .Navigate would be a good way to do the navigation - but the difficulty is in detecting the click of the link instead! :) Basically, there doesn't seem to be a good way to detect a click *on the link itself* at the moment. While it would be possible to detect a click on the HtmlTextBlock, that would only seem to make sense if there were exactly one link present. So for lack of a good way to support this, I chose not to for now. However, if you have a scenario where it makes sense to behave differently, by all means do so! :)

# Hello Silverlight - Start Your Silverlight Journey Today!

Wednesday, October 17, 2007 3:19 AM by BradVin's .Net Blog

I think today is the start for great things to come. And why? Because I had my first article published

# Continuing support for simple HTML display in Silverlight [HtmlTextBlock sample updated for Silverlight 2 Beta 1!]

Monday, March 17, 2008 3:48 PM by Delay's Blog

A few months ago when Silverlight 1.1 Alpha was all the rage, I wrote a sample control that made a best-effort

# Again with the support for simple HTML display in Silverlight [HtmlTextBlock sample updated for Silverlight 2 Beta 2!]

Wednesday, June 11, 2008 1:15 PM by Delay's Blog

A customer recently asked about an update to my HtmlTextBlock sample for the newly released Silverlight

Anonymous comments are disabled
 
Page view tracker