Given some of the feedback I've received during the first couple of weeks after releasing DOM Snitch, I'd like to shed more light into some of the inner workings of DOM Snitch and the rationales behind some of the decisions that were made while building the tool.
Topic 1: Why is DOM Snitch not catching security issues executing at load time through inline JavaScript?
In its current implementation, DOM Snitch is set to start running on a page as soon as the DOMWindow object is created, but before the DOM tree is built. This allows the extension to act either as soon as it's instantiated or when any of the DOM modification events get dispatched. Relying on the events, however, comes with a cost and that is the inability to know what caused the event to be dispatched in the first place; therefore resulting in the tool's inability to gather proper debug information. (I should add the disclaimer that currently DOM Snitch does not use any of the V8 debugging functionality.)
Topic 2: Is DOM Snitch using any of the experimental APIs in Chrome?
The short answer is "no". One of the early goals I set while building the tool was to stay away from experimental APIs or touching the Chromium code base as doing either one of the two will get in the way of deploying easily without changing the security posture of the user. Additionally, using unsupported functionality might result in some maintenance issues further down the line. That being said, I'm quite keen on using the chrome.experimental.debugger API should it become supported by the Chromium team.
Topic 3: On innerHTML, outerHTML, and stale pointers inside JavaScript
Stale JavaScript pointers is one side effects that really worries me when intercepting innerHTML. Although, the tool has gone through lots of iterations to getting this right, I must admit that people still find creative ways to introduce a stale pointer somewhere in their code. By giving a bit more detail on how innerHTML is intercepted, I hope that developers will pay some attention as to what may go wrong in their code from a testability perspective.
In its current version, WebKit does not reveal the internal innerHTML pointers through the getter and setter methods. As a result, by overwriting the innerHTML setter, DOM Snitch loses the value of the original pointer. To counter this, DOM Snitch re-creates the action of setting an element's innerHTML by appending a new child element and setting the child's outerHTML to the intended innerHTML value ( and as it turns out, this will force WebKit to throw away the newly created child element and replace it with whatever children that get introduced through the HTML content). You can see this implementation here.
Showing posts with label web. Show all posts
Showing posts with label web. Show all posts
Jul 23, 2011
Jun 4, 2011
Creating spreadsheets in Google Docs... mission possible?
Exporting data as spreadsheets into Google Docs sounds easy and quite feasible. However, it also has a few gotcha's. After struggling for a day, I've decided to share my notes on approaching this problem.
Creating the spreadsheet
My initial requirement for my application is to export my data into a brand new spreadsheet where the user will have ownership of it. A quick stroll through the Spreadsheet API led me to a section describing the need to upload a spreadsheet beforehand or create one manually. This was definitely against my requirements.
However, buried inside the Google Documents List Data API is a mechanism for creating empty documents or from a template (I'll come to this in a minute). Voila!
Changing the term attribute to http://schemas.google.com/docs/2007#spreadsheet surely does the trick if I want a completely blank spreadsheet.
Feeding data into the spreadsheet
This is where it becomes more tricky -- as it turns out, there isn't any convenient way to use the list approach (something I preferred using as opposed to the cell approach) to populate an empty spreadsheet without first telling Google Docs the schema that your list would use. One bit of observation to make is that the list schema is derived from the header row in your spreadsheet, therefore if the A1 cell stores "sample text" as its value, every subsequent row will have the "A" column described as <gsx:sampletext>. In my case, I opted to use a pre-built template from which to create my spreadsheet (see above about copying documents); however, there might be also a workaround involving batch cell update.
Some random tips
Here are some random bits that I found useful during this exercise:
- Always pay attention to the response object when posting new items (be it documents, worksheets, list entries, etc.) to Google Docs. The response object will provide you with some very useful information (stored inside the link element of the feed/entry) about what are the next logical APIs to call.
- The _worksheetId_ for the default worksheet in a newly created spreadsheet is... yes, "default". Should you need to add a row to it, you can simply call POST https://spreadsheets.google.com/feeds/list/[spreadsheet key]/default/private/full.
Edit: I went back to experiment with alternative ways of setting the header row of the default worksheet. As expected, one can set the header row by fetching the cells there and updating them with whatever contents they need to have.
Creating the spreadsheet
My initial requirement for my application is to export my data into a brand new spreadsheet where the user will have ownership of it. A quick stroll through the Spreadsheet API led me to a section describing the need to upload a spreadsheet beforehand or create one manually. This was definitely against my requirements.
However, buried inside the Google Documents List Data API is a mechanism for creating empty documents or from a template (I'll come to this in a minute). Voila!
Changing the term attribute to http://schemas.google.com/docs/2007#spreadsheet surely does the trick if I want a completely blank spreadsheet.
Feeding data into the spreadsheet
This is where it becomes more tricky -- as it turns out, there isn't any convenient way to use the list approach (something I preferred using as opposed to the cell approach) to populate an empty spreadsheet without first telling Google Docs the schema that your list would use. One bit of observation to make is that the list schema is derived from the header row in your spreadsheet, therefore if the A1 cell stores "sample text" as its value, every subsequent row will have the "A" column described as <gsx:sampletext>. In my case, I opted to use a pre-built template from which to create my spreadsheet (see above about copying documents); however, there might be also a workaround involving batch cell update.
Some random tips
Here are some random bits that I found useful during this exercise:
- Always pay attention to the response object when posting new items (be it documents, worksheets, list entries, etc.) to Google Docs. The response object will provide you with some very useful information (stored inside the link element of the feed/entry) about what are the next logical APIs to call.
- The _worksheetId_ for the default worksheet in a newly created spreadsheet is... yes, "default". Should you need to add a row to it, you can simply call POST https://spreadsheets.google.com/feeds/list/[spreadsheet key]/default/private/full.
Edit: I went back to experiment with alternative ways of setting the header row of the default worksheet. As expected, one can set the header row by fetching the cells there and updating them with whatever contents they need to have.
May 16, 2010
Domain names in Cyrilic
Veni Markovski wrote:
Well done, ICANN! We now have domain names in Cyrilic!
I suspect this will have a lot of security implications, but from an internationalization perspective, it's awesome! :)
http://президент.рф is up and running! congratulations, Russia!!!
Well done, ICANN! We now have domain names in Cyrilic!
I suspect this will have a lot of security implications, but from an internationalization perspective, it's awesome! :)
Feb 13, 2010
Plastic problems
...or Cambridge 2 PCI 0
This past week I landed on two very interesting papers that came out of Cambridge. The papers basically discuss the weaknesses of Chip & PIN and the 3-D Secure protocol for online transactions. Highly recommended read.
This past week I landed on two very interesting papers that came out of Cambridge. The papers basically discuss the weaknesses of Chip & PIN and the 3-D Secure protocol for online transactions. Highly recommended read.
Aug 3, 2009
Recycling security test cases
Test cases are precious. In my day to day work, a lot of what we do is built around the notion that a test case either passes or fails. Think about the time when you withdraw money out of your favorite ATM or when your favorite application may have compromised your privacy... it's always the case of a passed or failed test case. Is there a flaw in the system? Can the system under test be put to its knees because of it?
A while ago James Whittaker talked about building repositories with reusable test cases. The whole discussion is available at the MSDN blogs. I definitely recommend reading it. As applications often have common flaws, it is beneficial to have such a repository. Tweaking the test cases to the application under test is definitely a "must-do". However, once those tweaks are done for the particular software under test, the job gets much easier.
Reflecting at the security industry, it's hard to not notice the need for James's idea to be adopted. In fact, a typical problem report from a security vendor will include the following bits:
A while ago James Whittaker talked about building repositories with reusable test cases. The whole discussion is available at the MSDN blogs. I definitely recommend reading it. As applications often have common flaws, it is beneficial to have such a repository. Tweaking the test cases to the application under test is definitely a "must-do". However, once those tweaks are done for the particular software under test, the job gets much easier.
Reflecting at the security industry, it's hard to not notice the need for James's idea to be adopted. In fact, a typical problem report from a security vendor will include the following bits:
- What is the problem?
- How can the problem be reproduced?
- How can the problem be fixed?
Labels:
productivity,
security,
testing,
web
Jul 22, 2009
Phish me a Safari
Recently I decided to install Safari 4. The experience is quite nice, except I'm paranoid about phishing. Yes, I check the certificates of sites where I'm about to provide my user credentials. I check the validity of links before I click on them. I even use different browsers when browsing trusted and not so trusted sites (some might point me to this surf jacking article, but oh well).
In general, phishing is a concept that's been around for a while. It revolves around the idea to trick a user into performing an action while thinking he/she was performing another action. One of the mechanisms to do so is through obfuscating links inside a Web page. More on this can be found here.
Typically, Windows based browsers have been pretty good about revealing the URL of a link before clicking on it as this was a valid concern a few years ago (circa 2004/5). However, after switching to Mac I could say that I'm quite disappointed of not seeing any notification about the links I'm about to click on a page. In a way that goes against the secure by default concept that OS makers started adopting in 2003. Or maybe I'm just assuming too much from Apple?
P.S. - Of course, I can turn on the Safari status bar and everything will be fine; but then, would all users do the same?
In general, phishing is a concept that's been around for a while. It revolves around the idea to trick a user into performing an action while thinking he/she was performing another action. One of the mechanisms to do so is through obfuscating links inside a Web page. More on this can be found here.
Typically, Windows based browsers have been pretty good about revealing the URL of a link before clicking on it as this was a valid concern a few years ago (circa 2004/5). However, after switching to Mac I could say that I'm quite disappointed of not seeing any notification about the links I'm about to click on a page. In a way that goes against the secure by default concept that OS makers started adopting in 2003. Or maybe I'm just assuming too much from Apple?
P.S. - Of course, I can turn on the Safari status bar and everything will be fine; but then, would all users do the same?
Labels:
daily life,
security,
web
Jul 15, 2009
Chrome and Privacy Mode
A while back I was playing around with Google Gears and Incognito mode. The test was simple: I store some data in Gears while in Incognito and try to read it while in Normal mode.
The goal
The goal of this test is quite simple: prove that privacy related data (yes, with Gears gaining momentum a lot of apps like Google Docs, Google Reader, Google Calendar, MySpace, etc. are beginning to utilize Gears' SQLite engine to cache information) that was obtained in Incognito mode will persist in Normal mode and vice-versa.
The code
Load the following code in Incognito mode:
Load the following code in Normal mode:
The result
Data indeed persisted. I've posted the code for Incognito mode here and for Normal mode here.
Conclusion
Browsers' attempt to provide additional privacy to users is noble; however, this is valid only for data that the browser controls directly (e.g. cookies, browser cache). As Web applications are becoming richer in features, third party technologies like Google Gears, Flash, and Silverlight will soon need to start playing the privacy game as well if browsers are to fully allow privacy modes to users.
The goal
The goal of this test is quite simple: prove that privacy related data (yes, with Gears gaining momentum a lot of apps like Google Docs, Google Reader, Google Calendar, MySpace, etc. are beginning to utilize Gears' SQLite engine to cache information) that was obtained in Incognito mode will persist in Normal mode and vice-versa.
The code
Load the following code in Incognito mode:
var db = google.gears.factory.create('beta.database');
db.open('privacy-test');
db.execute('drop table if exists secret');
db.execute('create table secret (message text)');
db.execute('insert into secret values (?)', "secret message");Load the following code in Normal mode:
var db = google.gears.factory.create('beta.database');
db.open('privacy-test');
db.execute('create table if not exists secret (message text)');
var rs = db.execute('select message from secret');
if(rs.isValidRow()) {
alert(unescape(rs.field(0)));
}The result
Data indeed persisted. I've posted the code for Incognito mode here and for Normal mode here.
Conclusion
Browsers' attempt to provide additional privacy to users is noble; however, this is valid only for data that the browser controls directly (e.g. cookies, browser cache). As Web applications are becoming richer in features, third party technologies like Google Gears, Flash, and Silverlight will soon need to start playing the privacy game as well if browsers are to fully allow privacy modes to users.
Dec 11, 2008
Google releases Browser Security Handbook
Jason pointed me earlier today to Google's Browser Security Handbook. This is a quite useful collection of information regarding the security models in the mainstream browsers. The read is intended for web application developers, browser engineers, and information security researchers. Enjoy!
Dec 1, 2008
A peek at the "economy" around us
Back in the day (circa 2004) I was somewhat involved with malware research (detection, prevention, etc.)... for the good guys -- namely Symantec and Florida Tech. About that time I was reflecting on some risk analysis, mainly to get a bit more realistic picture of the economic aspects of vulnerabilities, exploits, malware, etc. Although the market was young at the time, there were signs of financial incentives for the bad guys.
Recently, Symantec published their Report on the Underground Economy. From their blog:
Recently, Symantec published their Report on the Underground Economy. From their blog:
A scanner for remote file include vulnerabilities sold for an average price of $26, and ranged from $5 to $100.
A scanner for cross-site scripting vulnerabilities was advertised for an average price of $20, and prices ranged from $10 to $30.
Exploit links to websites that are affected by remote file include vulnerabilities were sold in bulk—100 links could be obtained for an average price of $34 and 200 links could be obtained for an average price of $70.
SQL injection tools were sold for an average price of $63, and ranged from $15 through $150.
Oct 19, 2008
Google Maps API: Tips and Tricks
Google Maps API is awesome! There is no doubt about it. The Javascript functionality allows developers to do anything and everything when it comes to geo positioning. As I've incorporated the maps API into the gt project (release coming soon), I ran into a few issues that require some tricks in order to work. Here is the list:
More tips and tricks to come at a later point. :)
- Never use addOverlay before you call setCenter. If you do, you will experience the "Cannot call 'getProjection' on null" error which results from Google Maps trying to place a marker on a map that does not exist.
- Attach to events in a separate function. In one of the map API examples I found the nice functionality to pop a message box when the user clicks on a marker. This is done through the GEvent.addListener call. The problem comes when addListener and addOverlay are called within the same function. This causes Google Maps to always display the same pop-up at the same location regardless of which marker has been clicked.
More tips and tricks to come at a later point. :)
Sep 2, 2008
Becoming scare of being mobile
For a while I've been meaning to post something about mobile computing and some of the security implications that can result from that. As the mobile platforms have advanced a lot in the past 2-3 years (yay, we can run the Apache Web server on the Nokia N95!), it is becoming inevitable that soon people will begin to do day to day activities, such as shopping, banking, e-mail, from their phones... oops, they already have. The scary part in all of this is that phones are beginning to act like normal computers on the network. For instance, the new phone that I got already has a MAC address and a Netbios name... I'm assuming that when I start using it's Wi-Fi functionality, it will also have a real IP address. However, unlike computers, the interfaces on mobile phones limit the user in knowing what data leaves the phone encrypted and what plaintext (e.g. is mail accessed using TLS/SSL or plain IMAP/POP + SMTP?). Let alone know what data is cached locally and what not.
To resolve these worries I've adopted the following simple strategy: abuse the browser. At least the browser (in the sence of IE, Firefox, Safari, and Opera) will let you know whether SSL is used or not. Additionally, some phones have the functionality to clear the browser's cache, cookies, and history.
P.S. - Let's not discuss non-SSL content embedded into pages that are viewed over HTTPS. :)
To resolve these worries I've adopted the following simple strategy: abuse the browser. At least the browser (in the sence of IE, Firefox, Safari, and Opera) will let you know whether SSL is used or not. Additionally, some phones have the functionality to clear the browser's cache, cookies, and history.
P.S. - Let's not discuss non-SSL content embedded into pages that are viewed over HTTPS. :)
Jul 31, 2008
Estimating a user's gender based on browsing history
Some guys have taken the time to create a small client-side app for estimating a user's gender based on his/her browsing history. Although not very accurate, the app itself is pretty cool. It really sparks more creativity on what can go in the browser.
Labels:
web
Apr 24, 2008
Calling Action Script from the DOM
There is plenty of literature already on how to call Action Script functions from the browser's DOM. The concept is simple:
However, this is not the case when using IE. Because of a timing issue, the Action Script function is not being registered within IE; therefore producing a Javascript error. The workaround for this issue is to manually register the ActionScript function by calling __flash__addCallback(<Flash object>, <name of Action Script function>).
- Write the Action Script function
- Use ExternalInterface.addCallback to register the function for scripting
- Get a handle on the Flash player
- Call the function
However, this is not the case when using IE. Because of a timing issue, the Action Script function is not being registered within IE; therefore producing a Javascript error. The workaround for this issue is to manually register the ActionScript function by calling __flash__addCallback(<Flash object>, <name of Action Script function>).
Apr 14, 2008
Flirting with browser MIME types
While reading another blog, I ran into a paper that describes how different MIME types are rendered by the different browsers. It provides a nice reference section that points out the MIME types that would force the browser to render HTML content (hence, useful in the hunt for cross-site scripting vulnerabilities).
The paper can be found here.
The paper can be found here.
Apr 8, 2008
Google Gears and Information Disclosure
While reading some of the new stuff around Google Gears, I noticed a blog article by the Gears Team regarding the integration of Google Gears with Google Docs (or Office as I like to call it). It is quite interesting to see how Gears will impact the service offered by Docs. However, it also brings to question the confidentiality of the cached information.
Take for instance a simple user-based web application. The application consists of the logon page and some important user information. When Gears is deployed in this scenario, the caching can be directed via one of two ways:
What is the problem with these 2 scenarios?
Because both cases expose the problem of caching using random IDs, retrieving cached data back from Gears relies on either keeping browser history or making session lifetime longer. While the first approach is a concern only at the client, extending the lifetime of a session is generally considered a bad security practice. Additionally, it is not quite clear whether/how Gears allows developers to clear data from the local cache. As a result, anybody with local access to the browser may retrieve data that is otherwise protected by a web application.
Why this matters?
As a final note, combine all of this with a popular web application of choice and public machine such as a library/university computer or a simple Internet kiosk. I believe you'll soon get the idea.
Take for instance a simple user-based web application. The application consists of the logon page and some important user information. When Gears is deployed in this scenario, the caching can be directed via one of two ways:
- Dynamically generate Gears manifest to reflect the user's session ID. This is usually done when the web application uses the session ID as part of the URL. Because Gears caches resources based on URL, it is important to update the manifest when the URL for a to-be-cached resource has changed.
- Look for a specific cookie. The latest version so far (0.3.13.0) allows developers to direct the serving of a page by demanding that a specific cookie is present before the serving can occur. This is done by using the requiredCookie attribute in the Gears manifest.
What is the problem with these 2 scenarios?
Because both cases expose the problem of caching using random IDs, retrieving cached data back from Gears relies on either keeping browser history or making session lifetime longer. While the first approach is a concern only at the client, extending the lifetime of a session is generally considered a bad security practice. Additionally, it is not quite clear whether/how Gears allows developers to clear data from the local cache. As a result, anybody with local access to the browser may retrieve data that is otherwise protected by a web application.
Why this matters?
As a final note, combine all of this with a popular web application of choice and public machine such as a library/university computer or a simple Internet kiosk. I believe you'll soon get the idea.
Debugging Javascript
A few tips and tricks that will make life easier when debugging client-side web apps:
For more advanced debugging, check Rob Chartier's article on debugging Javascript.
- The address bar is your friend. Use the javascript: protocol handler to execute any script command within the context of the current document. For instance, typing javascript:alert(document.cookie) into the address bar will spit out all cookies associated with the page. Likewise, javascript:alert(document.body.innerHTML) will spit out the HTML within the body tag of the loaded document.
- Ctrl-A + Ctrl-C is your friend. Copying from alert boxes in the browser works just like copying from a text field of any other application.
For more advanced debugging, check Rob Chartier's article on debugging Javascript.
Labels:
web
Apr 2, 2008
Using HTML in Silverlight
As Silverlight gets more and more matured, people start to ask more and more about the controls which the platform provides. One of my hopes in dealing with Silverlight was the ability to embed HTML content. Alas, there is no control that will allow me to do so. There are 2 ways to resolve this problem: code your own control that will handle some or all HTML capabilities, or create a wrapper around the browser. I chose option 2.
How do we wrap around the browser?
Luckily, Silverlight exposes almost all DOM objects to the Silverlight application. Using this, a Silverlight application can create new or modify any existing HTML elements in the parent HTML document. Example:
With the help of some CSS, this element can be placed anywhere in the browser window. Example:
The final bit is filling this element with actual content. To do this, I've used a JavaScript helper function that I placed in the parent document. Finally, I use the HtmlPage.Window.Invoke API to call the helper function and place the HTML content into my HTML element.
Some additional info on how to do these things can be found at:
Walkthrough: Calling Managed Code from Client Script
Walkthrough: Calling Client Script from Managed Code
Edit:
There is the possibility of inserting HTML content inside this element without the need for calling an external JavaScript function. This is done by using HtmlElement.SetAttribute to set the innerHTML attribute to whatever HTML content it must be.
How do we wrap around the browser?
Luckily, Silverlight exposes almost all DOM objects to the Silverlight application. Using this, a Silverlight application can create new or modify any existing HTML elements in the parent HTML document. Example:
HtmlElement elem = HtmlPage.Document.CreateElement("div");
HtmlPage.Document.Body.AppendChild(elem);
With the help of some CSS, this element can be placed anywhere in the browser window. Example:
elem.SetStyleAttribute("position", "fixed");
elem.SetStyleAttribute("width", "auto");
elem.SetStyleAttribute("top", "150px");
elem.SetStyleAttribute("left", "250px");
The final bit is filling this element with actual content. To do this, I've used a JavaScript helper function that I placed in the parent document. Finally, I use the HtmlPage.Window.Invoke API to call the helper function and place the HTML content into my HTML element.
Some additional info on how to do these things can be found at:
Walkthrough: Calling Managed Code from Client Script
Walkthrough: Calling Client Script from Managed Code
Edit:
There is the possibility of inserting HTML content inside this element without the need for calling an external JavaScript function. This is done by using HtmlElement.SetAttribute to set the innerHTML attribute to whatever HTML content it must be.
Labels:
silverlight,
web
Mar 24, 2008
Marketing Psychology...
...or just another way to obtain another person's personal information?
Recently I (and probably many more Facebook users) received an invitation to take part in the Psychology Marketing Project in Facebook. The project itself is just another group in which people are asked to join and invite others. So far good, we've seen this in the past.
However, there is a bit of social engineering involved in the steps for participating in this project. If you carefully read the description, you'd notice that users are asked to add the creator as a "friend". Although Facebook allows users to limit the amount of personal information that their contacts can see, it is reasonable to believe that many users have not properly set their privacy settings accordingly. Therefore, by adding the so called "marketing student" as a contact, users allow the creator of this "project" to access their personal information, which then can be used for additional "marketing" purposes.
Recently I (and probably many more Facebook users) received an invitation to take part in the Psychology Marketing Project in Facebook. The project itself is just another group in which people are asked to join and invite others. So far good, we've seen this in the past.
However, there is a bit of social engineering involved in the steps for participating in this project. If you carefully read the description, you'd notice that users are asked to add the creator as a "friend". Although Facebook allows users to limit the amount of personal information that their contacts can see, it is reasonable to believe that many users have not properly set their privacy settings accordingly. Therefore, by adding the so called "marketing student" as a contact, users allow the creator of this "project" to access their personal information, which then can be used for additional "marketing" purposes.
Mar 13, 2008
Silverlight 2
Microsoft has officially released Silverlight 2 Beta 1 to the public. There are a few major changes that come with the release of this version. The list below describe my observations so far:
The last and somewhat important observation is the lack of support for running 1.1 applications into the 2.0 runtime environment. I hope that this move is for the better. :)
- XAML. The XAML schema has somewhat changed since the Alpha Refresh of 1.1. As opposed to the Canvas element in 1.1, UI controls are now implemented using a Grid element that encapsulates all children elements within the control. This leads to somewhat of a confusion when dealing with relative positions of children elements. For instance, if in 1.1 an element's position can be specified using Canvas.Left and Canvas.Top, in 2.0 this position is determined via the Margin attribute for that element.
- Access to children elements. It came as a pleasant surprise that the Silverlight team has really put the effort into making XAML elements easily accessible from the .NET code. While in 1.1 one must use FrameworkElement.FindName API to access any given XAML element, in 2.0 all XAML elements are members of the class and can be directly accessed.
- Event handlers. The very first observation regarding event handling is that many of the raised events have changed. Aside from noticing the naming, I have not spent much time with this part of Silverlight to notice any major differences in the behavior of these events.
- Code deployment. Silverlight 2 code is now deployed through the use of an embedded object as opposed to ActiveX instantiation via scripting. This is good in the sence it will make it easier for web developers to play around it and not worry so much about screwing something up in the process. Another interesting part of the deployment process is the inclusion of the System.Windows.Forms.Controls library in the ClientBin folder. In a previous test, a friend and I tried to see if we can load the full System.Xml from the ClientBin, so I wonder if tricks like that can now be played with the CLR.
The last and somewhat important observation is the lack of support for running 1.1 applications into the 2.0 runtime environment. I hope that this move is for the better. :)
Labels:
silverlight,
web
Feb 29, 2008
Media tracking in Silverlight
During the past few days I spent quite some time looking into the best and possibly most robust way to track audio and video content in Silverlight. The objective is simple: every time a video or an audio clip is loaded, a timeline is to appear and is to give users the ability to play/pause/stop the clip, see its progress, mute it, or simply seek parts in it.
The toughest part of all is creating the progress bar... well, not so much creating it, but making it work. As with most controls created by Microsoft, hooking into the right event is always the way to go. In a similar way, media tracking can be done by setting markers in the media content at certain intervals and then catching the MarkerReached event when those markers are being hit. Unfortunately, modifying the markers through .NET code was not as easy as it seems... apparently Silverlight has issues when markers are being added to a MediaElement. The result of that is a nice crash of the browser.
Luckily, media markers can be embedded through the Expression Encoder. To save time, avoid carpal tunnel syndrome, and spare some nerves, there is an easy way to automate the process of setting the markers into the media file. The steps are:
The toughest part of all is creating the progress bar... well, not so much creating it, but making it work. As with most controls created by Microsoft, hooking into the right event is always the way to go. In a similar way, media tracking can be done by setting markers in the media content at certain intervals and then catching the MarkerReached event when those markers are being hit. Unfortunately, modifying the markers through .NET code was not as easy as it seems... apparently Silverlight has issues when markers are being added to a MediaElement. The result of that is a nice crash of the browser.
Luckily, media markers can be embedded through the Expression Encoder. To save time, avoid carpal tunnel syndrome, and spare some nerves, there is an easy way to automate the process of setting the markers into the media file. The steps are:
- Get the total duration time of the media content.
- Set your step interval (i.e. the time between 2 consecutive markers).
- Create an XML file of the format
<Markers>
<Marker Time="00:00:01"
Value="Marker1"
GenerateKeyFrame="True"
GenerateThumbnail="False" />
...
</Markers> - Import the XML file into the Markers section in Expression Encoder
- Encode the media content.
Labels:
silverlight,
web
Subscribe to:
Posts (Atom)