<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Windows Live Quantum Mechanics : cross domain</title><link>http://blogs.msdn.com/dthorpe/archive/tags/cross+domain/default.aspx</link><description>Tags: cross domain</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Cross-Domain Communication Using Domain Lowering</title><link>http://blogs.msdn.com/dthorpe/archive/2007/09/27/cross-domain-communication-using-domain-lowering.aspx</link><pubDate>Fri, 28 Sep 2007 08:52:28 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5180444</guid><dc:creator>dthorpe</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/dthorpe/comments/5180444.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dthorpe/commentrss.aspx?PostID=5180444</wfw:commentRss><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/dthorpe/archive/2007/06/18/secure-cross-domain-communication-the-architecture-journal.aspx"&gt;More than a few blog posts ago&lt;/a&gt;&amp;nbsp;I stated my intent to publish a series of articles on cross-domain communication techniques.&amp;nbsp; More time has passed than I had intended, but at last here is the start of that series of articles.&amp;nbsp; The series will explore progressively more advanced cross-domain techniques as well as their strengths and weaknesses, culminating in&amp;nbsp;an announcement about stuff we've been working on that I think you'll find interesting.&lt;/p&gt; &lt;p&gt;Cross-domain communication is usually discussed in the context of a browser client communicating to a web server that is different than the domain of the web page currently shown in the browser.&amp;nbsp; The browser client displays a page from server foo.com, and that page tries to access data on server bar.com.&amp;nbsp; This is forbidden by the same-origin browser security policy because bar.com isn't foo.com.&lt;/p&gt; &lt;h4&gt;Server Side Proxy&lt;/h4&gt; &lt;p&gt;One relatively simple way to resolve this is to have the browser page request data from the page's web server, and have the web server relay that request to the actual third party server.&amp;nbsp; The browser displays a page from foo.com, and that page makes a data request to foo.com which foo.com relays to bar.com.&amp;nbsp; Bar.com replies to foo.com, and foo.com forwards that response on to the browser client page to complete the circuit.&lt;/p&gt; &lt;p&gt;While this solution is simple and quite widespread today, it has some significant problems:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;&lt;strong&gt;Scalability and Network costs&lt;/strong&gt;:&amp;nbsp; The request and response travel across your server's network twice.&amp;nbsp; Request in, request out, response in, response out.&amp;nbsp; Traffic on your server network grows four times faster than growth of your application use.&amp;nbsp;&amp;nbsp;That means you'll&amp;nbsp;reach network saturation four times sooner than&amp;nbsp;with other techniques, and you'll pay four times more (in server network traffic costs) for the privilege.&amp;nbsp; &lt;/li&gt; &lt;li&gt;&amp;nbsp;&lt;strong&gt;Impersonating the user&lt;/strong&gt;:&amp;nbsp; When your foo.com server makes a request to bar.com seeking data for the user, you're essentially impersonating the end user.&amp;nbsp; If the data on bar.com requires any sort of user identification or authorization, your server side proxy suddenly jumps from super simple to super difficult.&amp;nbsp; It's easy enough to ask the user to log in to bar.com, but your foo.com can't see anything that goes on in bar.com.&amp;nbsp; In particular, foo.com cannot see whatever browser cookies that bar.com sets to indicate logged in state.&amp;nbsp; Thus, it will be next to impossible for foo.com to present the appropriate cookies or credentials in its http request to bar.com to make bar.com believe that the request is coming from the legitimate user.&amp;nbsp; And this should be difficult - this is nothing short of a man-in-the-middle attack on bar.com's security!&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;So, server side proxies are a quick and dirty way to toss anonymous data around, but they don't scale well and they hit a wall when the data requires authentication.&lt;/p&gt; &lt;h4&gt;Web Sites With Subdomains&lt;/h4&gt; &lt;p&gt;Web sites and web applications generally start out as simple beasts running on a single web domain (www.foo.com).&amp;nbsp; As the site grows in functionality and complexity, the incentives to break that site up into subdomains (downloads.foo.com, feedback.food.com, images.foo.com) grows as well.&amp;nbsp; Perhaps your web site has a download area that needs to be optimized for large file transfers.&amp;nbsp; That would probably be easier to fine tune as a server or cluster dedicated to that function than to try to tune the entire web site for large file downloads.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Subdomains often sprout as a byproduct of a company's internal structure.&amp;nbsp; It takes a lot more effort to coordinate updates to one central server shared by multiple departments on different schedules than for a department to own their own subdomain, nicely isolated from the rest of the company's constant revisions.&lt;/p&gt; &lt;h4&gt;Double Edged Sword&lt;/h4&gt; &lt;p&gt;Domain isolation is convenient to let you get your work done independently of the noise going on in the rest of the company's web presence, but also presents a new problem:&amp;nbsp; web pages served from your subdomain cannot share information with web pages served from other subdomains of your company.&amp;nbsp; If the user logs in to your company's main page, the browser cookies representing that login state are not accessible to your subdomain.&amp;nbsp; &lt;/p&gt; &lt;h4&gt;Lowering the Domain Barrier&lt;/h4&gt; &lt;p&gt;The major browsers support a technique around this quandary, to allow subdomains to operate as equals within a common shared context.&amp;nbsp; The HTML document object has a domain property which normally reflects the complete domain name of the server from which the HTML document was loaded.&amp;nbsp;The browser will allow you to&amp;nbsp;assign a subset of the current&amp;nbsp;domain name to the document.domain property to&amp;nbsp;indicate that you wish for the HTML document to be treated as though it were loaded from the parent domain.&lt;/p&gt; &lt;p&gt;So, an HTML&amp;nbsp;page served from downloads.foo.com can assign document.domain = "foo.com" in a JavaScript code block.&amp;nbsp; From that point forward, browser domain security checks will treat that page as a peer of any page in the foo.com domain.&amp;nbsp; &lt;/p&gt; &lt;p&gt;The browser will (should) only allow you to change the document.domain to a less specific version of your current domain.&amp;nbsp; one.two.three.foo.com could be lowered to foo.com, or could be lowered to three.foo.com.&amp;nbsp; &lt;/p&gt; &lt;p&gt;The browser should not allow assignment of a top-level domain (domain suffix) to document.domain.&amp;nbsp; You should not be able to change a document domain from "one.foo.com" to "com".&amp;nbsp; There have been browser bugs in this area in the past where a browser implementer mistakenly interpreted "top level domain" to mean "the bit of the domain after the last dot".&amp;nbsp; ".com", ".edu", and ".org" are top level domains, but ".co.uk" and ".co.jp" are TLDs also.&lt;/p&gt; &lt;p&gt;The browsers will not allow you to raise the domain of an HTML document to something more specific than its domain of origin, nor allow lateral domain shuttling.&amp;nbsp; Changing document.domain from "two.foo.com" to one.two.foo.com" is forbidden.&amp;nbsp; Changing a document.domain from&amp;nbsp;"one.foo.com" to "two.foo.com" is forbidden.&lt;/p&gt; &lt;h4&gt;Irreversible (Mostly)&lt;/h4&gt; &lt;p&gt;Firefox 1.5 and 2.0 will not allow you to assign a domain name that is more specific than the document's current domain name under any circumstances.&amp;nbsp; Once you lower one.foo.com to foo.com, it's stuck at foo.com forever.&amp;nbsp; The only way to clear that state is to reload the page.&lt;/p&gt; &lt;p&gt;IE6 and IE7 will allow you to raise a document's domain back to it's actual domain of origin.&amp;nbsp; If a page was served from one.foo.com, and you lower it to foo.com, IE will let you raise it back to one.foo.com.&amp;nbsp; However, I've seen some instabilities and inconsistencies in the aftermath of "raising shields", so I don't recommend relying on this behavior.&amp;nbsp; Since Firefox doesn't allow restoring domains to their original values, you should ignore the fact that IE sort of does allow it.&lt;/p&gt; &lt;h4&gt;Bridging Silos Via Least Common Denominators&lt;/h4&gt; &lt;p&gt;When an HTML document's domain is lowered to a parent domain, the security context and JavaScript symbol&amp;nbsp;space of that document joins the security context and JavaScript symbol space of any and all pages that are also in the parent domain.&amp;nbsp;&amp;nbsp;JavaScript in your page served from one.foo.com and lowered to foo.com can access JavaScript functions and variables defined in other pages whose domain is foo.com, and visa-versa.&lt;/p&gt; &lt;p&gt;So, if you have pages on one.foo.com that would like to interoperate with pages on two.foo.com, you can use domain lowering to pull down the domain barriers just enough to allow them to talk to each other, but still provide domain protections against third parties trying to steal or corrupt the internal state of your web app.&amp;nbsp; Place a JavaScript block at the top of each page in the "one" and "two" subdomains which assigns document.domain = "foo.com" and you're good to go.&amp;nbsp; All the pages will operate as though they were served from the same domain, and can access anything in each other's DOMs and JavaScript symbol space.&lt;/p&gt; &lt;h4&gt;One or the Other, Not Both&lt;/h4&gt; &lt;p&gt;Note that once your one.foo.com page has been lowered into the parent domain, your HTML and JavaScript code loses all access to DOMs and JavaScript data in any other pages that are still in the original one.foo.com subdomain.&amp;nbsp; A web page can only be in one domain context&amp;nbsp;or the other, not both.&lt;/p&gt; &lt;h4&gt;Interesting Inconsistencies&lt;/h4&gt; &lt;p&gt;Domain lowering applies only to the DOM and JavaScript sandboxes.&amp;nbsp; Parts (actually, nearly all) of the browser execute in native machine code outside the browser security sandbox. Native objects exposed to JavaScript in the sandbox are largely on their own to implement appropriate security checks on operations initiated by JavaScript.&amp;nbsp; JavaScript can't access the local file system, for example, but if the user installs an ActiveX control for IE or a browser plugin for Firefox that allows local file access, and that extension declares itself safe for scripting, then JavaScript could use that control to access files on the local file system.&lt;/p&gt; &lt;p&gt;In both IE and Firefox, XMLHttpRequest (XHR) is a native object exposed to JavaScript.&amp;nbsp; This is pretty obvious in IE6 since you have to construct the object using ActiveXObject; in Firefox you can deduce that the XHR is a native object&amp;nbsp;from the phrasing of some error messages and error behaviors while the browser goes down in flames.&lt;/p&gt; &lt;p&gt;XHR is restricted to connecting only to the current HTML page's domain of origin.&amp;nbsp; Domain lowering applies only to the browser sandbox.&amp;nbsp; XHR operates outside the browser sandbox, enforcing same-origin domain policy on its own. This leads to an interesting - and valuable - inconsistency:&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;strong&gt;XMLHttpRequest is not affected by domain lowering&lt;/strong&gt;.&amp;nbsp; &lt;/p&gt; &lt;p&gt;This means you can actually have one foot in each domain:&amp;nbsp; Your JavaScript executes in the context of the lowered subdomain (foo.com), but XHR requests made by your JavaScript are held to the domain restriction of the page's original subdomain (one.foo.com). XHR doesn't know anything about document.domain.&lt;/p&gt; &lt;p&gt;If you're trying to get your JavaScript to open an XHR to a resource on foo.com, this can be infuriating because XHR won't do it.&amp;nbsp; You have to refer to an HTML page served from foo.com in order to get XHR to open a connection to foo.com.&lt;/p&gt; &lt;h4&gt;The Money Shot&lt;/h4&gt; &lt;p&gt;This inconsistency in the handling of document.domain enforcement/awareness makes the following scenario possible:&amp;nbsp; The logic of your web app runs in the context of a page loaded from one.foo.com, and you want to XHR load data from two.foo.com.&lt;/p&gt; &lt;p&gt;Here's how you do that:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Make your&amp;nbsp;html page A served from one.foo.com lower&amp;nbsp;its document.domain to foo.com&lt;/li&gt; &lt;li&gt;Place an html page&amp;nbsp;B&amp;nbsp;on two.foo.com, and have it lower its document.domain to foo.com early in its load cycle.&amp;nbsp; (A JavaScript statement in&amp;nbsp;global scope&amp;nbsp;in the &amp;lt;head&amp;gt; section is fine).&amp;nbsp; &lt;/li&gt; &lt;li&gt;Implement a function GetData(callback) on this page that constructs an XHR request to load the desired data from two.foo.com.&amp;nbsp; Wire up the XHR onReadyStateChanged to process the data completion using a function implemented in B.html, and in that function pass the received data to the callback function passed into GetData().&lt;/li&gt; &lt;li&gt;Insert an invisible (1x1 pixel) iframe on page A and set its src to http://two.foo.com/B.html&lt;/li&gt; &lt;li&gt;After page A has fully loaded, and page B in the iframe has loaded, JavaScript code in page A can call the GetData() function in page B through the iframe element:&amp;nbsp; bframe.window.GetData(mycallback)&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Believe it or not, this works.&amp;nbsp;Domain lowering allows JavaScript to call between A and B, and the fact that B is served from two.foo.com allows the XHR request implemented in B to access two.foo.com.&lt;/p&gt; &lt;h4&gt;Here Be Pixies.&amp;nbsp; (Try Not To Piss Them Off)&lt;/h4&gt; &lt;p&gt;The path through this&amp;nbsp;murky&amp;nbsp;realm&amp;nbsp;is neither straight nor wide.&amp;nbsp; If you take liberties or shortcuts with this recipe, be careful to test your code thoroughly on multiple browsers.&amp;nbsp; Chances are high that any deviation will&amp;nbsp;lead to failure on one of the browsers.&amp;nbsp; &lt;/p&gt; &lt;p&gt;IE is fairly flexible in this area.&amp;nbsp; You don't actually have to implement the GetData function in the B page.&amp;nbsp; You can just construct in the&amp;nbsp;A context&amp;nbsp;an XHR object type&amp;nbsp;from the B context and use it directly in the A context.&amp;nbsp; ( var xhr = new bframe.window.XMLHttpRequest() )&amp;nbsp; For IE, the B page need only lower the domain to foo.com.&amp;nbsp; After that, all the driving can be done from A.&lt;/p&gt; &lt;p&gt;Firefox is more particular about this technique.&amp;nbsp; Firefox will allow you to construct an instance of the B XHR in the context of A, but you'll get access denied or weirder errors when you try to call the methods of the B XHR from the context of A.&amp;nbsp; Firefox gets confused when you&amp;nbsp;call native object methods across these convoluted domain bridges, but calling JavaScript functions and methods works fine on either side of the context boundary.&amp;nbsp; Once the JavaScript call context gets from A to B, then the native object method calls will work.&amp;nbsp;&lt;/p&gt; &lt;p&gt;This is also why step 3 above&amp;nbsp;mandates that the XHR onReadyStateChange event handler should be wired to a function implemented in the B page - the native XHR object operating in the B context&amp;nbsp;may have difficulty firing an event wired to a function in the A page context.&lt;/p&gt; &lt;h4&gt;The Downside to Homogeneity&lt;/h4&gt; &lt;p&gt;For domain lowering to work between two subdomains, both sides have to "lower their shields" to a common middle ground.&amp;nbsp;As this technique catches on across departments and their corresponding subdomains, you can quickly reach a point where just about all the subdomains on the corporate web have provisions to lower their domain to the common corporate parent domain.&lt;/p&gt; &lt;p&gt;This is convenient and quite powerful&amp;nbsp;for building web apps that can access data bits from all across the company.&amp;nbsp; The problem is that it weakens your corporate defenses across the board.&amp;nbsp; If just one of the subdomain silos&amp;nbsp;were compromised and an attacker were able to inject malicious JavaScript to execute in the browser context of that compromised subdomain, that malicious code would have easy access to every subdomain across the company that lowers its domain to foo.com.&lt;/p&gt; &lt;p&gt;This risk grows with scale.&amp;nbsp; The more subdomains you have that routinely lower their domains to the common ground, the greater the risk that one of them may be compromisable and serve as a&amp;nbsp;beachhead to your entire network.&lt;/p&gt; &lt;h4&gt;Tune In Next Time&lt;/h4&gt; &lt;p&gt;There is a way to mitigate this weakest link risk such that an attacker compromising a weak subdomain does not get access to everything.&amp;nbsp; This requires inverting some of the relationships presented in this article&amp;nbsp;and making the silos deeper rather than shallower.&amp;nbsp; I'll cover&amp;nbsp;"Siloed Domain Lowering"&amp;nbsp;in my next&amp;nbsp;cross-domain&amp;nbsp;article.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5180444" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dthorpe/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/web/default.aspx">web</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/cross+domain/default.aspx">cross domain</category></item><item><title>Secure Cross-Domain Communication:  The Architecture Journal</title><link>http://blogs.msdn.com/dthorpe/archive/2007/06/18/secure-cross-domain-communication-the-architecture-journal.aspx</link><pubDate>Tue, 19 Jun 2007 01:53:50 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3392059</guid><dc:creator>dthorpe</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/dthorpe/comments/3392059.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dthorpe/commentrss.aspx?PostID=3392059</wfw:commentRss><description>&lt;p&gt;The June issue (Journal 12) of &lt;a href="http://msdn2.microsoft.com/en-us/arcjournal/default.aspx"&gt;The Architecture Journal&lt;/a&gt;&amp;nbsp;focuses on web architecture.&amp;nbsp; I was delighted to be invited to contribute, and wrote "Secure Cross-Domain Communication in the Browser" for this issue.&amp;nbsp;&amp;nbsp;In the article I&amp;nbsp;describe&amp;nbsp;a&amp;nbsp;somewhat bizarre technique we use in the&amp;nbsp;&lt;a href="http://dev.live.com/contactscontrol/"&gt;Windows Live Contacts web control&lt;/a&gt; and &lt;a href="http://dev.live.com/spacescontrol"&gt;Windows Live Spaces web control&lt;/a&gt; to move data from HTML pages running on&amp;nbsp;*.live.com to and from third party web sites.&amp;nbsp; This is how the contacts control returns&amp;nbsp;user-selected contact data to the page hosting the control, a web site that is not a Microsoft site.&amp;nbsp;&amp;nbsp;&lt;/p&gt; &lt;p&gt;The print edition of &lt;a href="http://download.microsoft.com/download/f/5/2/f520c83a-d2ed-4be8-9bc6-b39a1f9a4562/AJ12_EN.zip"&gt;Journal 12&lt;/a&gt; is out already and was handed out at TechEd in Orlando&amp;nbsp;earlier this month.&amp;nbsp; You can request&amp;nbsp;a print copy by registering on the Journal's web site, or you can just &lt;a href="http://download.microsoft.com/download/f/5/2/f520c83a-d2ed-4be8-9bc6-b39a1f9a4562/AJ12_EN.zip"&gt;grab the PDF&lt;/a&gt; and read it on-screen.&amp;nbsp;&amp;nbsp;Journal 12&amp;nbsp;will&amp;nbsp;rotate into the headlines on the Journal's homepage soon.&lt;/p&gt; &lt;p&gt;&lt;a href="http://blogs.msdn.com/dthorpe/archive/2007/05/31/quot-undisclosed-browser-technology-quot.aspx"&gt;A few posts ago&lt;/a&gt; I mentioned I could finally reveal &lt;a href="http://blogs.msdn.com/dthorpe/archive/2007/05/31/quot-undisclosed-browser-technology-quot.aspx"&gt;what I had been working on at Google&lt;/a&gt;.&amp;nbsp; Now I can also tell you in exquisite detail what I've been working on here at Microsoft for the past year and foreseeable future:&amp;nbsp; cross-domain browser communication techniques.&amp;nbsp; Coaxing stubborn little bits to migrate through impenetrable browser&amp;nbsp;barriers.&amp;nbsp; &lt;/p&gt; &lt;p&gt;"Secure Cross-Domain Communication in the Browser"&amp;nbsp;is a high-level walk-through of the iframe URL technique of passing information between domain contexts in the browser, it's limitations and weaknesses, and the approach we've taken to build a channel communications library to fortify against those weaknesses and limitations.&lt;/p&gt; &lt;p&gt;Over the next few weeks I will be posting here on&amp;nbsp;&lt;a href="http://blogs.msdn.com/dthorpe/"&gt;Windows Live Quantum Mechanics&lt;/a&gt;&amp;nbsp;a series of articles&amp;nbsp;digging into the nitty gritty of cross-domain communication, why it has been&amp;nbsp;taboo&amp;nbsp;in the browser, why it's time to change that perception, and techniques and code you can use today to achieve it - without compromising security or server scalability.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Cross domain communication would be much easier with the browser's help and shepherding, but with a little bit of effort we can actually do quite a bit today - safely -&amp;nbsp;in spite of the browser's objections.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3392059" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dthorpe/archive/tags/Windows+Live/default.aspx">Windows Live</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/Blogging/default.aspx">Blogging</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/cross+domain/default.aspx">cross domain</category></item><item><title>A Cross-Domain Silverlight Channel 9 VideoRSS Player</title><link>http://blogs.msdn.com/dthorpe/archive/2007/05/30/a-cross-domain-silverlight-channel-9-videorss-player.aspx</link><pubDate>Wed, 30 May 2007 11:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2984147</guid><dc:creator>dthorpe</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/dthorpe/comments/2984147.aspx</comments><wfw:commentRss>http://blogs.msdn.com/dthorpe/commentrss.aspx?PostID=2984147</wfw:commentRss><description>&lt;P&gt;Last week Kevin Ledley, keeper of the dev.live.com content, asked me for a bit of help to get a &lt;a href="http://www.microsoft.com/silverlight/"&gt;Silverlight&lt;/a&gt; video player working.&amp;nbsp; He wanted to "borrow" the cool scrolling video list and video player from our sister site, &lt;A href="http://msdn2.microsoft.com/" mce_href="http://msdn2.microsoft.com/"&gt;msdn2.microsoft.com&lt;/A&gt; and set it up on our &lt;A href="http://dev.live.com/" mce_href="http://dev.live.com"&gt;dev.live.com&lt;/A&gt; homepage to show Windows Live related videos from &lt;A href="http://channel9.msdn.com/" mce_href="http://channel9.msdn.com"&gt;Channel 9&lt;/A&gt;.&amp;nbsp; Copying the necessary JavaScript and XAML files for the Silverlight video player was easy enough, but even after fixing all the URL references, it still wasn't working.&amp;nbsp; So, I took a look.&lt;/P&gt;
&lt;H3&gt;Get the files&lt;/H3&gt;
&lt;P&gt;First, I needed to grab the files and set them up on my localhost IIS server.&amp;nbsp; The msdn2.microsoft.com page referenced the following JS files:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Silverlight.js - we know what that is 
&lt;LI&gt;main.js 
&lt;LI&gt;button.js 
&lt;LI&gt;helpermethods.js 
&lt;LI&gt;listbox.js 
&lt;LI&gt;listboxitem.js 
&lt;LI&gt;scrollbar.js 
&lt;LI&gt;transportButtons.js 
&lt;LI&gt;videoEntry.js 
&lt;LI&gt;videoPlayer.js 
&lt;LI&gt;videoService.js&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;main.js is what makes the call to create the Silverlight control, same as our CreateSilverlight.js file in helloworld earlier.&amp;nbsp; main.js has a lot of other code in it as well.&amp;nbsp; Scanning for ".xaml", we find there are actually three&amp;nbsp;different xaml files used&amp;nbsp;by main.js:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;videoListHor.xaml 
&lt;LI&gt;itemTemplate.xaml 
&lt;LI&gt;videoPlayer.xaml&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;After copying these files locally, I scanned each for hard coded URL references and stripped them down to relative paths for easier tinkering on localhost.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;I made a small test page to host the video player, using the same variable and element names as the original msdn page:&lt;/P&gt;
&lt;H4&gt;vidtest.html&lt;/H4&gt;&lt;PRE style="BACKGROUND-COLOR: #e0e0e0"&gt;&lt;SPAN style="COLOR: black"&gt;&amp;lt;!DOCTYPE&lt;/SPAN&gt; html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;
&lt;SPAN style="COLOR: black"&gt;&amp;lt;html&lt;/SPAN&gt; xmlns=&lt;SPAN style="COLOR: black"&gt;"http://www.w3.org/1999/xhtml"&lt;/SPAN&gt; xml:lang=&lt;SPAN style="COLOR: black"&gt;"en"&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;head&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;title&amp;gt;&lt;/SPAN&gt;Channel 9 Video on Silverlight&lt;SPAN style="COLOR: black"&gt;&amp;lt;/title&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"SilverLight.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"main.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"transportButtons.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"listbox.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"listboxitem.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"button.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"scrollbar.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"helperMethods.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"videoPlayer.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"videoEntry.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"videoService.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/head&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;body&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;div&lt;/SPAN&gt; style=&lt;SPAN style="COLOR: black"&gt;"position: relative;text-align:center;width:475px; z-index:10;"&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;div&lt;/SPAN&gt; id=&lt;SPAN style="COLOR: black"&gt;"videoListHost"&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;        &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;script type="text/javascript"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;        &amp;nbsp;&amp;nbsp;&amp;nbsp; var videoScrollerFeedUrl = &lt;BR&gt;"http://www.mscommunities.com/MixItUp/Search/default.aspx?q=msdn";&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;         startVideoScroller();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;          &amp;lt;/script&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/div&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;div&lt;/SPAN&gt; id=&lt;SPAN style="COLOR: black"&gt;"videoPlayerHost"&lt;/SPAN&gt; &amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/div&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/div&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/body&amp;gt;&lt;/SPAN&gt;
&lt;SPAN style="COLOR: black"&gt;&amp;lt;/html&amp;gt;&lt;/SPAN&gt;        &lt;/PRE&gt;
&lt;P&gt;With this in place,&amp;nbsp;I had all the bits in place on the localhost server to run the app.&amp;nbsp; Would it work?&amp;nbsp; Probably not, but no harm in trying!&lt;/P&gt;
&lt;H3&gt;Eliminate Framework Dependencies&lt;/H3&gt;
&lt;P&gt;Sure enough, vidtest.html threw a JavaScript exception on load.&amp;nbsp; The culprit:&amp;nbsp; Some of the code in the js files refers to a $get() function which appear to be a shortcut for document.getElementById.&amp;nbsp; A little bit of spelunking around in the msdn code with&amp;nbsp;a JavaScript debugger confirmed this hypothesis. $get() is a helper function implemented in the JavaScript libraries that run the msdn web site.&amp;nbsp; I definitely did not want to start pulling on that thread.&amp;nbsp; $get() is innocuous enough, so we can placate the borrowed JS files on our localhost system by implementing a $get() function in vidtest.html&lt;/P&gt;&lt;PRE style="BACKGROUND-COLOR: #e0e0e0"&gt;&lt;SPAN style="COLOR: black"&gt;function&lt;/SPAN&gt; $get(id) {&lt;BR&gt;&lt;SPAN style="COLOR: black"&gt;    return&lt;/SPAN&gt; document.getElementById(id);&lt;BR&gt;}&lt;BR&gt;&lt;/PRE&gt;
&lt;P&gt;Easy enough.&amp;nbsp; Will it work now?&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Bzzzt!&amp;nbsp;The browser next complains about "Object required" or somesuch on the expression Sys.Application.notifyScriptLoaded() at the bottom of one of the .JS files.&amp;nbsp; This, too, is a bit of goo defined by the msdn web site infrastructure.&amp;nbsp; It notifies the application when the .JS file has finished loading, so that it's ok to construct the Silverlight control.&lt;/P&gt;
&lt;P&gt;For vidtest.html, I have an equivalent, simpler approach:&amp;nbsp; construct the Silverlight control in the onLoad event of the body element.&amp;nbsp; The page's onLoad event won't fire until after all the JavaScript references in the head of the document have been loaded.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Ok.&amp;nbsp; Will it work now?&lt;/P&gt;
&lt;P&gt;Yes!&amp;nbsp; The Silverlight video scroller draws itself on the page!&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;A href="http://blogs.msdn.com/blogfiles/dthorpe/WindowsLiveWriter/ASilverlightVideoRSSPlayer_13B48/image%7B0%7D%5B3%5D.png" mce_href="http://blogs.msdn.com/blogfiles/dthorpe/WindowsLiveWriter/ASilverlightVideoRSSPlayer_13B48/image%7B0%7D%5B3%5D.png" atomicselection="true"&gt;&lt;IMG style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px" height=107 alt="This is a screenshot of a Silverlight app.  Had this been an actual Silverlight app, it would look much cooler." src="http://blogs.msdn.com/blogfiles/dthorpe/WindowsLiveWriter/ASilverlightVideoRSSPlayer_13B48/image%7B0%7D_thumb%5B1%5D.png" width=360 border=0 mce_src="http://blogs.msdn.com/blogfiles/dthorpe/WindowsLiveWriter/ASilverlightVideoRSSPlayer_13B48/image%7B0%7D_thumb%5B1%5D.png"&gt;&lt;/A&gt; &lt;/P&gt;
&lt;P&gt;But it's empty.&amp;nbsp; Why is it empty?&amp;nbsp; Let's go look at that videoScrollerFeedURL&amp;nbsp;variable and where it's used in the code.&lt;/P&gt;
&lt;P&gt;A quick grep&amp;nbsp;of the&amp;nbsp;JS files brings us to videoService.js, in a function called getVideoEntryList:&lt;/P&gt;&lt;PRE style="BACKGROUND-COLOR: #e0e0e0"&gt;&lt;SPAN style="COLOR: black"&gt;function&lt;/SPAN&gt; getVideoEntryList() {&lt;BR&gt;&lt;SPAN style="COLOR: black"&gt;&lt;P&gt;    Microsoft.Mtps.Rendering.Behaviors.VideoService.GetVideoEntryList(&lt;BR&gt;        videoScrollerFeedUrl, loadVideos);&lt;/P&gt;&lt;/SPAN&gt;}&lt;BR&gt;&lt;/PRE&gt;
&lt;P&gt;What's all that about?&lt;/P&gt;
&lt;H3&gt;Bubble Burster&lt;/H3&gt;
&lt;P&gt;videoScrollerFeedUrl is a string with a value of &lt;A href="http://www.mscommunities.com/MixItUp/Search/default.aspx?q=msdn" mce_href="http://www.mscommunities.com/MixItUp/Search/default.aspx?q=msdn"&gt;http://www.mscommunities.com/MixItUp/Search/default.aspx?q=msdn&lt;/A&gt;.&amp;nbsp; If you follow that link, you'll see that it's an RSS feed.&amp;nbsp; But you should also notice that the URL is in a domain that is not msdn.&amp;nbsp; How is the msdn web code able to use the RSS data from mscommunities.com?&lt;/P&gt;
&lt;P&gt;Microsoft.Mtps.Rendering.Behaviors.VideoService.GetVideoEntryList must be a cross-domain proxy of some kind responsible for fetching RSS entries from mscommunities.com and returning them to the JavaScript running on msdn.microsoft.com.&amp;nbsp; A little friendly debugger inspecting confirms that this&amp;nbsp;function call&amp;nbsp;receives back an array of JavaScript objects - a &lt;A href="http://en.wikipedia.org/wiki/Json" mce_href="http://en.wikipedia.org/wiki/Json"&gt;JSON&lt;/A&gt; result - describing the video description, a thumbnail image URL and a video&amp;nbsp;stream URL.&lt;/P&gt;
&lt;P&gt;This presents a not so small problem for our objective.&amp;nbsp; dev.live.com is not msdn.microsoft.com.&amp;nbsp; We can't call that GetVideoEntryList function or use the web service behind it to find out what videos are available on Channel 9.&amp;nbsp; Full stop.&lt;/P&gt;
&lt;H3&gt;The Options: Few and Ugly&lt;/H3&gt;
&lt;P&gt;I called Kevin up with the bad news.&amp;nbsp; Our options were few and ugly:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Get the server proxy code from msdn and install it on dev.live.com.&amp;nbsp; Great plan, but even if we could get our hands on the code, chances are high that some sort of server configuration difference (installed version of ASP.NET, installed version of .NET framework, etc) between how msdn is set up from how dev.live.com is set up could still make this a no-go.&amp;nbsp; 
&lt;LI&gt;Write our own server side proxy to perform the same relay of RSS content.&amp;nbsp; Trivially simple, perhaps, but the depth of security and code reviews and testing that would be required to roll out live code on a production server would turn our cute little video thingie into a&amp;nbsp;weeks-long fire-breathing hydra from hell.&amp;nbsp; No thanks.&amp;nbsp; I already do that for my day job - why take on all that for a side project? 
&lt;LI&gt;Hardcode the URLs of the videos we want shown in this video scroller into the JS code.&amp;nbsp; Kevin: "We don't have that many videos."&amp;nbsp; Danny:&amp;nbsp; "Yet."&amp;nbsp; Doesn't scale, labor intensive. 
&lt;LI&gt;Construct an RSS feed on the dev.live.com domain to feed video URLs into the video scroller.&amp;nbsp; Much more maintainable over time than #3, but still requires constant maintenance to update the local feed when something relevant shows up on Channel 9.&amp;nbsp; The whole reason for RSS is to have the machine take care of discovery and updating.&lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;Kevin said he'd work on #1 and #4.&amp;nbsp; I opted for #5: Stew on it some more.&amp;nbsp; Take the dog on a long walk. Check the mailbox.&amp;nbsp; Return.&lt;/P&gt;
&lt;H3&gt;Strange Bedfellows&lt;/H3&gt;
&lt;P&gt;A funny thing happened on the way back from the mailbox -&amp;nbsp;it dawned on me that I was trying to solve the wrong problem, or at least,&amp;nbsp;more problem than we needed to solve.&amp;nbsp; We needed a way to read the video RSS feed in the browser across domain boundaries, but we didn't need an all-purpose cross domain data conduit (like we use in the &lt;a href="http://dev.live.com/contactscontrol/"&gt;Windows Live Contacts web control&lt;/a&gt;).&amp;nbsp;A conduit that could move just RSS data and only RSS data would suffice for this project.&lt;/P&gt;
&lt;P&gt;That's when I recalled hearing about Google's recent launch of&amp;nbsp;an RSS Feed&amp;nbsp;API.&amp;nbsp; Mark Lucovsky, who I had a chance to meet (and almost work for) in my Google days now&amp;nbsp;400 days ago, &lt;A href="http://googleajaxsearchapi.blogspot.com/2007/04/announcing-google-ajax-feed-api.html" mce_href="http://googleajaxsearchapi.blogspot.com/2007/04/announcing-google-ajax-feed-api.html"&gt;announced&lt;/A&gt; about a month and a half ago a new API built from a subset of the Google Search API that returns only RSS data.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;In concept, the &lt;A href="http://code.google.com/apis/ajaxfeeds/" mce_href="http://code.google.com/apis/ajaxfeeds/"&gt;Google Feed API&lt;/A&gt; acts as a cross-domain proxy service between your web app and the RSS content you want to use.&amp;nbsp; In reality, it's far simpler:&amp;nbsp; it returns the RSS data cached in Google's search index.&amp;nbsp; This approach creates a multitude of curious&amp;nbsp;artifacts with positive and negative spin:&amp;nbsp; &lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Response latency to your RSS requests is&amp;nbsp;determined solely&amp;nbsp;by Google's network infrastructure, not the server originating the RSS data.&amp;nbsp; The server of origin might not even be up but you can still get the RSS data from the Feed API. 
&lt;LI&gt;This use of RSS data is entirely in the spirit of syndication.&amp;nbsp;It's a bummer that the server of origin can't find out how many secondary and tertiary consumers of their data are out there, but hey, that's the nature of syndication.&amp;nbsp; 
&lt;LI&gt;The RSS data you&amp;nbsp;get from the Feed API could be stale or out of sync with the server of origin by several hours or more depending on how quickly Google's web crawlers return to the server of origin to index new content.&amp;nbsp; That's not a major concern for our video viewer, but could be a show stopper for, say, live broadcasting. 
&lt;LI&gt;It's possible the RSS feed you want is not indexed by Google.&amp;nbsp; Hey, it does happen - the RSS feed could be too new to be in the index, or too isolated (no inbound links) to be considered indexible, or the server of origin could have&amp;nbsp;a robots.txt file that tells search engine spiders to piss off. It seems a bit contradictory to have an RSS feed that does not want to be found, but stranger things have happened.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;EM&gt;&lt;STRONG&gt;Wait a second.&amp;nbsp; Use a Google API in a Microsoft app?&amp;nbsp; What blasphemy is this?!&lt;/STRONG&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Oh, grow up.&amp;nbsp; Use what works.&amp;nbsp; Windows Live Search has a perfectly good Search API, but it doesn't provide anything to bring RSS content from a specific RSS URL into our web app.&lt;/P&gt;
&lt;P&gt;And why shouldn't a Microsoft app use a Google service when appropriate?&amp;nbsp; Google certainly uses plenty of Microsoft browsers and operating systems to&amp;nbsp;reach end users!&lt;/P&gt;
&lt;H3&gt;API Keys&lt;/H3&gt;
&lt;P&gt;To use the Google Feed API (I don't know why they had to put "AJAX" in the middle of it), you have to agree to the&amp;nbsp;usual mile long list of terms of use plus generate an API key&amp;nbsp;associated your web site URL.&amp;nbsp; You use the API key when initializing the Google API subsystem.&amp;nbsp; Presumably, this is&amp;nbsp;so they can get an idea of how much traffic your app is generating and be able to block your app's access if you're found to be abusing the system or violating the ToU.&lt;/P&gt;
&lt;P&gt;As far as I can tell by experimentation, the API key only gives Google some idea of who is using their service; the key does not appear to automatically disable API access if the key is used from a domain different from the URL you&amp;nbsp;specified when you generated the key.&amp;nbsp; I generated a key for use&amp;nbsp;on localhost, but found that it works just as well when I run my app from 127.0.0.1.&amp;nbsp; (It doesn't matter that one resolves into the other - a DNS name and an IP address are considered distinct domain names by the browser.&amp;nbsp; Domain name matching in the browser is by string matching, not by what the strings mean)&amp;nbsp; Perhaps lockouts only occur after a significant volume of suspicious traffic goes by.&amp;nbsp; I dunno.&lt;/P&gt;
&lt;H3&gt;The Brass Tacks&lt;/H3&gt;
&lt;P&gt;Here's the vidtest main page again, with the Google Feed API spliced in and bootstrapped:&lt;/P&gt;
&lt;H4&gt;vidtest.html&lt;/H4&gt;&lt;PRE style="BACKGROUND-COLOR: #e0e0e0"&gt;&lt;SPAN style="COLOR: black"&gt;&amp;lt;!DOCTYPE&lt;/SPAN&gt; html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;
&lt;SPAN style="COLOR: black"&gt;&amp;lt;html&lt;/SPAN&gt; xmlns=&lt;SPAN style="COLOR: black"&gt;"http://www.w3.org/1999/xhtml"&lt;/SPAN&gt; xml:lang=&lt;SPAN style="COLOR: black"&gt;"en"&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;head&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;title&amp;gt;&lt;/SPAN&gt;Channel 9 Video on Silverlight&lt;SPAN style="COLOR: black"&gt;&amp;lt;/title&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"SilverLight.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"main.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"transportButtons.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"listbox.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"listboxitem.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"button.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"scrollbar.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"helperMethods.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"videoPlayer.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"videoEntry.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;script&lt;/SPAN&gt; src=&lt;SPAN style="COLOR: black"&gt;"videoService.js"&lt;/SPAN&gt; type=&lt;SPAN style="COLOR: black"&gt;"text/javascript"&amp;gt;&lt;/SPAN&gt;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/script&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;script src=http://www.google.com/jsapi?key=xxxGetYerOwnAPIKeyxxx"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;script type="text/javascript"&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;       google.load("feeds", "1");&lt;BR&gt; &lt;BR&gt;&lt;BR&gt;            var videoScrollerFeedUrl = &lt;BR&gt;"http://www.mscommunities.com/MixItUp/Search/default.aspx?q=msdn";&lt;BR&gt;&amp;nbsp;&lt;BR&gt;     &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function initialize() { &lt;BR&gt;      &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; startVideoScroller();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     } &lt;BR&gt;&lt;BR&gt; &lt;BR&gt;          google.setOnLoadCallback(initialize);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt; &lt;BR&gt;          function $get(id) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;       return document.getElementById(id);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;/script&amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/head&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;SPAN style="COLOR: black"&gt;  &amp;lt;body&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;    &lt;SPAN style="COLOR: black"&gt;&amp;lt;div&lt;/SPAN&gt; style=&lt;SPAN style="COLOR: black"&gt;"position: relative;text-align:center;width:475px; z-index:10;"&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;      &lt;SPAN style="COLOR: black"&gt;&amp;lt;div&lt;/SPAN&gt; id=&lt;SPAN style="COLOR: black"&gt;"videoListHost"&amp;gt;&lt;BR&gt;&lt;/SPAN&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    &lt;SPAN style="COLOR: black"&gt;&amp;lt;/div&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    &lt;SPAN style="COLOR: black"&gt;&amp;lt;div&lt;/SPAN&gt; id=&lt;SPAN style="COLOR: black"&gt;"videoPlayerHost"&lt;/SPAN&gt; &amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;    &lt;SPAN style="COLOR: black"&gt;&amp;lt;/div&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  &lt;SPAN style="COLOR: black"&gt;&amp;lt;/div&amp;gt;&lt;/SPAN&gt;
&amp;nbsp;&amp;nbsp;&lt;SPAN style="COLOR: black"&gt;&amp;lt;/body&amp;gt;&lt;/SPAN&gt;
&lt;SPAN style="COLOR: black"&gt;&amp;lt;/html&amp;gt;&lt;/SPAN&gt;        &lt;/PRE&gt;
&lt;P&gt;We've added a new script reference that pulls in jsapi from www.google.com, and includes our API key.&amp;nbsp; I replaced my API key with a dummy value.&amp;nbsp; You'll need to go generate your own key if you want to run this code yourself.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;google.load("feeds", "1")&lt;/STRONG&gt; tells Google that we want to use the Feeds API.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;google.setOnLoadCallback(initialize)&lt;/STRONG&gt; tells Google to call our initialize() function when the requested API has been loaded. Dynamic loading of JavaScript might not be finished before the body onLoad event fires, so we have to take this route to wait for the Feed API to load.&amp;nbsp; Body onLoad event deleted.&lt;/P&gt;
&lt;P&gt;Now, let's go load that RSS content and build our video list, in videoService.js:&lt;/P&gt;
&lt;H4&gt;videoService.js&lt;/H4&gt;&lt;PRE style="BACKGROUND-COLOR: #e0e0e0"&gt;function getVideoEntryList() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var feed = new google.feeds.Feed(videoScrollerFeedUrl); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; feed.setNumEntries(100);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; feed.setResultFormat(google.feeds.Feed.MIXED_FORMAT);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; feed.load(function(result) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!result.error) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var videoEntries = [];&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (var i = 0; i &amp;lt; result.feed.entries.length; i++) {&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var entry = result.feed.entries[i];&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var vidEntry = new Object;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vidEntry.VideoTitle = entry.title;&lt;BR&gt; &lt;BR&gt;                var test = google.feeds.getElementsByTagNameNS(&lt;BR&gt;                        entry.xmlNode, &lt;BR&gt;                        "http://search.yahoo.com/mrss", &lt;BR&gt;                        "content");&lt;BR&gt;                if (!test || !test.length) continue;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vidEntry.VideoUrl = test[0].getAttribute("url");&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt; &lt;BR&gt;                test = google.feeds.getElementsByTagNameNS(&lt;BR&gt;                        entry.xmlNode, &lt;BR&gt;                        "http://search.yahoo.com/mrss", &lt;BR&gt;                        "thumbnail");&lt;BR&gt;                if (!test || !test.length) continue;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vidEntry.VideoThumbnailUrl = test[0].getAttribute("url");&lt;BR&gt; &lt;BR&gt;                test = google.feeds.getElementsByTagNameNS(&lt;BR&gt;                        entry.xmlNode, &lt;BR&gt;                        "http://purl.org/dc/elements/1.1/", &lt;BR&gt;                        "creator")&lt;BR&gt;                if (test &amp;amp;&amp;amp; test.length) {&lt;BR&gt;    &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; vidEntry.Author = test[0].text;&lt;BR&gt;                }&lt;BR&gt; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; videoEntries.push(vidEntry);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; loadVideos(videoEntries);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;}&lt;BR&gt;&lt;/PRE&gt;
&lt;P&gt;The msdn2.microsoft.com video scroller expects an array of vidEntry objects as input to build its playlist.&amp;nbsp; The msdn server side proxy takes care of digesting the RSS XML content down to a simple list of vidEntry objects.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;For our dev.live.com version of the video scroller, we need to build the vidEntry objects ourselves.&amp;nbsp;The Google Feed API can return JSON, XML, or both.&amp;nbsp; The title of the RSS entry is standard fare, so that's easy to grab from the JSON field entry.title.&amp;nbsp;The other fields we need - thumbnail URL, video URL, and author - are not normal RSS fields.&amp;nbsp; These fields are defined&amp;nbsp;in the &lt;A href="http://en.wikipedia.org/wiki/Media_RSS" mce_href="http://en.wikipedia.org/wiki/Media_RSS"&gt;Media RSS&lt;/A&gt; (MRSS) RSS extension module and are&amp;nbsp;generated by the Channel 9 video RSS feed as such.&lt;/P&gt;
&lt;P&gt;We make short work of finding the exact XML elements we're looking for by using a utility function provided by the google.feeds library: a cross-browser implementation of getElementsByTagNameNS().&amp;nbsp; &lt;/P&gt;
&lt;P&gt;We push each vidEntry object into the array and loop until we run out of RSS items.&lt;/P&gt;
&lt;P&gt;Finally, we hand off the array of objects to loadVideos and return to the original code path of the video scroller implementation.&lt;/P&gt;
&lt;P&gt;The result looks something like this:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;IMG title="Screenshot of Silverlight video player in action" style="WIDTH: 600px; HEIGHT: 353px" height=353 alt="Screenshot of Silverlight video player in action" src="http://storage.msn.com/y1pzRzjtWRm1XdRRsx8xkn8abFGABJ2qFich9CPbh33-j6lHwlqKaeQokFLRgDnCT98" width=600 mce_src=" http://storage.msn.com/y1pzRzjtWRm1XdRRsx8xkn8abFGABJ2qFich9CPbh33-j6lHwlqKaeQokFLRgDnCT98"&gt;&lt;/P&gt;
&lt;H3&gt;Why stop there?&lt;/H3&gt;
&lt;P&gt;So now we have what we set out to build:&amp;nbsp; a Silverlight video player that can show videos from the Channel 9 libraries, using the video RSS feeds returned by the mscommunities.com query service.&amp;nbsp;Note that this is built on the &lt;a href="http://www.microsoft.com/silverlight/"&gt;Silverlight&lt;/a&gt; 1.0 beta control using browser JavaScript, not the Silverlight 1.1 Alpha.&lt;/P&gt;
&lt;P&gt;The fact that we ended up using a generic RSS provider to get the specific RSS feed we needed opens some interesting possibilities:&amp;nbsp; Aren't we just a hair's breadth from showing any video from any video RSS feed on the Internet?&amp;nbsp; All we'd need to change is the videoScrollerFeedURL to point to a different RSS feed, right?&amp;nbsp; Perhaps this could be wired directly into Yahoo's Video Search service, which returns MRSS results for keyword searches of videos across the web?&lt;/P&gt;
&lt;P&gt;The answer is: yes and no.&amp;nbsp; Yes, the app actually is just a small step away from using any video RSS feed, or even a video search service that returns MRSS results.&amp;nbsp; The catch is: there are a bezillion different video formats and codecs out there in the wild.&amp;nbsp; It would be unreasonable to expect Silverlight 1.0 beta to be able to play all of them.&amp;nbsp; Silverlight's media player&amp;nbsp;isn't designed to play all video formats - it's designed to play media content encoded for Silverlight playback, using tools such as Expression Media.&amp;nbsp; Apparently, the Channel 9 video library is already encoded in a format that Silverlight can use.&amp;nbsp; Most video in the wild is not.&lt;/P&gt;
&lt;P&gt;That's no ding against Silverlight - all video sharing sites with built-in players play only one video format - their own.&amp;nbsp; When you upload a video to the sharing site, it&amp;nbsp;is almost always&amp;nbsp;converted (transcoded) into the site's native encoding format so that the site's player can play it.&amp;nbsp; You can build that kind of video sharing site with Silverlight.&lt;/P&gt;
&lt;P&gt;With a few tricks from this article, you can show Channel 9 videos on your web site or blog pages with Silverlight!&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&lt;/EM&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2984147" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/dthorpe/archive/tags/Windows+Live/default.aspx">Windows Live</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/Programming/default.aspx">Programming</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/cross+domain/default.aspx">cross domain</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/Google/default.aspx">Google</category><category domain="http://blogs.msdn.com/dthorpe/archive/tags/Feed+API/default.aspx">Feed API</category></item></channel></rss>