Structure of the Silverlight Object Tag

The Silverlight 2 installation/instantiation model promotes the use of the Silverlight <object> tag template. In my post Instantiating Silverlight: HTML vs. Script I mentioned that this template was designed to meet five criteria:

  1. be backwards-compatible with Silverilght 1.0
  2. rely on static HTML only
  3. offer the right installer for the right client (Mac vs. Windows vs. other)
  4. provide actionable feedback to users who will not be able to use Silverlight
  5. provide an easily-customizable installation/upgrade experience

This post will provide detail around how each of these criteria is met by the template.

 <object data="data:application/x-silverlight," type="application/x-silverlight-2-b2" width="500" height="500">
    <param name="source" value="MyApplication.xap"/>
    <param name="onerror" value="myOnError" />
    <param name="background" value="black" />
    
    <a href="https://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">
         <img src="https://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" 
              style="border-style: none"/>
    </a>
</object>
<iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>

Example 1: Silverlight 2 Beta 2 <object> template (partial)

Compatible with Silverlight 1.0

The Silverlight 1.0 installation and instantiation model was built around a javascript helper file called Silverlight.js. This file takes a set of parameters via a function and uses the parameters to inject a Silverlight control into a <DIV> on the web page. The Silverlight control is injected into the <DIV> by means of an <object> tag on IE and an <embed> tag on Firefox and Safari.

By using just the MIME type in the <object> tag and not the classid, a web page is able to correctly instantiate the Silverlight control across all browsers that are supported by Silverlight. The type attribute which specifies the MIME type is interpreted in the same fashion by these browsers while the classid attribute has differing, and often mutually exclusive, definitions. Therefore, using the type attribute in an <object> tag is sufficient for instantiating Silverlight 1.0 and Silverlight 2 controls through the use of a single HTML tag.

<object ... type="application/x-silverlight-2-b2" ...>

Rely on Static HTML Only

Removing the js dependency present in the Silverlight.js model was important in a number of hosting scenarios:

  1. Some web hosts do not allow users to add javascript to their web pages
  2. Linking an application in a web page requires the author to link both the application and the Silverlight.js file
  3. Browsers with javascript disabled are not able to view Silverlight content

Once we settled on using a single <object> tag, the static HTML instantiation model was readily available. However, 1.0 also relied on Silverlight.js to inject the Silverlight installation prompt when the right version of the control was not already installed on the user's computer. Providing this same experience in an <object> tag is done by using the browser's fallback mechanism for object tags. Specifically, if a web browser encounters an <object> tag with a MIME type that it does not recognize then the browser will ignore the <object> tag and any associated<param> tags. Instead, it will render the inner HTML of the <object> tag. Therefore, given the following block of HTML:

 <object type="fake/mimetype" width="500" height="500">
    <param name="foo" value="bar"/>
    
    <table>
        <tr>
            <td>
                You need the control to view this content!
            </td>
            <td>
                <a href="https://www.tempuri.org/install/control.exe">
                    <img src="https://www.tempuri.org/install/installControl.png" alt="Install Control"/>
                </a>
            </td>
        </tr>
    </table>
</object>

If the browser has a control mapped to the "fake/mimetype" MIME type then it will treat this block as:

 <object type="fake/mimetype" width="500" height="500">
    <param name="foo" value="bar"/>
</object>

Otherwise, it will ignore the <object> and <param> tags and treat the block as:

 <table>
    <tr>
        <td>
            You need the control to view this content!
        </td>
        <td>
            <a href="https://www.tempuri.org/install/control.exe">
                <img src="https://www.tempuri.org/install/installControl.png" alt="Install Control"/>
            </a>
        </td>
    </tr>
</table>

The Silverlight <object> template uses this fallback mechanism to display installation content when Silverlight is not available. If the user visits a Silverlight-enabled web page and has Silverlight installed then the Silverlight application is shown. If the user does not have Silverlight installed then the browser will ignore the Silverlight <object> tag and display the inner HTML. By default, the following HTML is used for Silverlight 2 Beta 2:

 <a href="https://go.microsoft.com/fwlink/?LinkID=115261" style="text-decoration: none;">
     <img src="https://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" 
          style="border-style: none"/>
</a>

And, when rendered, generates this UI element:

Get Microsoft Silverlight

Offer the right installer for the right client

If you inspect the default installation HTML for the Silverlight <object> template you will notice that it uses a single <a> tag to refer to the Silverlight installer: https://go.microsoft.com/fwlink/?LinkID=115261 for Silverlight 2 Beta 2. In the Silverlight.js file, however, there was a unique URL for each OS version of the installer: .exe for Windows, .dmg for Mac, and a separate URL for unsupported platforms. In Silverlight 2 Microsoft moved this detection logic to the server side. When a user follows the aforementioned installer URL a server process determines if an applicable installer exists for that user. If so, they are given that installer without ever leaving the page they were trying to view. If the browser is not supported by Silverlight, like 64-bit IE, then they are redirected to a Microsoft Web page which tells them about the platform requirements of the Silverlight control.

This server-side tool is useful for a number of reasons. First, a web site only needs to offer a single download URL for the control. Second, web authors don't have to worry about communicating problematic conditions, like unsupported platforms, to the end-user. Third, if a platform moves from the unsupported list to the supported list then Web sites using this single URL will usually get support for that platform automatically.

Provide actionable feedback to users

This was covered a bit in the previous section. There is a set of users for whom we can detect that Silverlight will not work well under their current system configuration. The three big groups in this set are:

  • Unsupported OS
  • Unsupported Browser
  • Unsupported Browser Flavor (64-bit IE)

The system which decides which installer to offer for a particular client also checks for these conditions. If any of them are met then the user is sent to a Microsoft Web page which tells them about the detected problem. In some cases, the system tells users that their OS is unsupported. In other cases, the user is warned that they should switch to a supported browser. In the 64-bit browser case, the user is asked to use a 32-bit browser instead.

This system will be updated with new error conditions as they become problematic. The goal of this system is to, as much as possible, prevent users from getting into infinite installation loops. We chose this particular implementation because it moves the responsibility of detecting problematic conditions to Microsoft and away from Web site owners.

Provide an easily-customizable installation/upgrade experience

While the default installation medallion for Silverlight is very clear and actionable, it does not provide insight into the cool features of the Silverlight-powered application that is asking for the install. The Silverlight <object> tag template is easily customizable so that this insight can be provided at a very low cost. Instead of writing Javascript, a developer can simply take ordinary HTML code from a designer and add it to their Silverlight <object> tag template. As long as this HTML contains a link to the Silverlight installer and is wholly contained by the associated Silverlight <object> tag, it will provide a customized installation experience. You can see an example of this in the "Rely on static HTML only" section above.

Other template elements

data="data:...,"

There are two elements of the <object> tag template whose purpose is not immediately clear. The data attribute of the <object> tag and the trailing <iframe> tag.

The data attribute was added to the Silverlight <object> tag shortly before Silverlight 1.0 shipped. The attribute was added to augment a behavior we were seeing in some Silverlight-supported browsers. If we added an <object> tag to a web page and did not include a data attribute on that <object> tag then the browser would pass the html file which contained the <object> tag to the object through the data field. I'll clarify with an example:

test1.html
---------------------------------------------------
<html>
   <body>
       <object type="fake/MIMEtype">
       </object>
   </body>
</html>
---------------------------------------------------

When read by particular browsers, this web page would be treated like this:

test1.html (example of strange behavior)
---------------------------------------------------
<html>
   <body>
       <object type="fake/MIMEtype" data='<html><body><object type="fake/MIMEtype"></object></body></html>' >
       </object>
   </body>
</html>
---------------------------------------------------

This behavior obviously increases the memory footprint of the affected control, especially for complicated web pages. What is worse, the HTML for the web page was not retrieved from memory. Instead, the browser would make additional requests back to the Web server to get updated copies of the page. This added latency to page load times and increased the server load for these web pages.

To mitigate the problem, we needed a cross-browser method for populating the <object>'s data attribute without adding cost for the web developer. After some research we found that the object tag specification allows for data to be specified externally (from a file) or inlined (from HTML). With this in mind, we created the data attribute to be an inlined empty data stream which would not be associated with any other control. The result is what you have seen:

data="data:application/x-silverlight,"

The Silverlight MIME type prevents other controls from interpreting this data incorrectly. The empty string after the comma minimizes the size of the stream. Adding this attribute to <object> tags prevents extra memory usage and server hits.

<iframe>

The trailing <iframe> is included to provide a consistent caching experience across browsers. According to the Safari Developer FAQ, "Safari achieves much of its performance through efficient use of content caching." This caching can provide inconsistent behavior for Silverlight controls that are rendered in Safari and the same controls rendered by other browsers. For example, the behavior of onLoad events may become different from what is expected. To ensure that Silverlight content behaves in a predictable fashion, we included the <iframe> tag as suggested by the Safari Developer FAQ. That same FAQ, however, offers a number of alternatives to the <iframe> which a developer may choose to implement instead.