Even a chimp can write code

Monday, April 27, 2009

Silverlight out-of-browser apps: Local Data Store

Silverlight applications – whether in-browser or out-of-browser, and whether running online or offline - can persist data into a local data store referred to as “Isolated Storage”. With the new offline/out-of-browser support in Silverlight 3, the platform further ensures that an app has access to the same Isolated Storage data regardless of whether it was activated in-browser or locally. This way, apps can share data between the in-browser and out of browser versions. As I’d mentioned in a previous post, Silverlight will enforce the provenance URI of the XAP in either case, ensuring that when each queries for its local store, it gets the very same artifact.

What can you do with this power?

Scenario #0: Local playback sure beats network playback.

Scenario #1: Assuming you have consumer use cases that involve using your in-browser and out-of-browser apps interchangeably, you now have a way to share data between them.

Scenario #2: If you need to share data between your in-browser app and your newly minted out-of-browser app immediately upon install (detach), you can use this local store as your custom “cookie store”.

Scenario #3: If your out-of-browser app detects no network connection, it can still take user input but persist that into local store, to later playback when connectivity is regained. 

Internals

Silverlight’s Isolated Storage feature provides a virtual file system in which apps can create and store both files and directories with arbitrary data.

Apps are abstracted from the lower level file I/O functionality; they do not (need to) know where the files are stored or what sort of internal formats and directory hierarchies are in place. While apps can use file paths and dot-out syntax, these paths cannot escape the bounds of the virtual file system. This sort of virtualization provides isolation of app data, preventing other apps from inadvertently reading from or writing to your app’s store. Hence the term “Isolated” in the name. Apps and app authors do need to recognize that data stored in this persistence store is per-user and per-domain.

The Isolated Storage feature in Silverlight persists app data within a directory in the user profile (\%AppData%\LocalLow\Microsoft\Silverlight\is on Windows Vista and up and /Users/<user>/Library/Application Support/Microsoft/Silverlight/is on Mac OS X). The AppData folder is a hidden folder. This has the beneficial side effect of hiding your data from from OS search utilities (Windows desktop search and Spotlight) as well as the casual user. This should not be seen as a security boundary – only as a perpetuating the isolation of data.

Quotas

The space allocated for local data storage in a Silverlight app is bounded by a default quota assigned to that app’s domain of origin. At install (detach) time out-of-browser Silverlight apps will have 25MB space available within the Isolated Storage by default. Contrast this to the default quota of 1MB enjoyed by conventional in-browser Silverlight apps.

Needless to say, more space is available to the app upon user consent when the app invokes the System.IO.IsolatedStorage.IsolatedStorageFile.IncreaseQuotaTo() method. That method invocation itself needs to be in response to a user-initiated action such as mouse click or key press.

When your out-of-browser app is uninstalled, Silverlight does not reclaim your special quota or erase data persisted there.

Encryption

Although the isolated storage maintains data in an obscure location, it should not be confused with secure or encrypted data. However apps can easily encrypt and decrypt isolated storage files; they may also sign and validate the signature of an isolated storage file using the SHA256 hash function.

Gotchas

When saving to a virtual file system, one needs to be aware of inherent limits on file path size. This is imposed on you because the Isolated Storage’s root dir itself occupies several characters in the path (151 on Vista/Win7, 183 on XP/2K, 160 on OS X) effectively leaving you only the remainder (109, 77 and 100) respectively for your own file and directory names before Silverlight’s limit of 260 chars for a file path is hit.

Saving files outside of Isolated Storage

Silverlight 3 allows for saving files outside of isolated storage. Saving to any location on the client-side file system requires user initiation and the use of the SaveFileDialog control - a new “safe” control which allows saving one file at a time via a stream with your app code not having access to the file system or structure. Saving data to the server via an HTTP postback is another option.

----

This was #6 in my ongoing series of posts on Silverlight’s new offline and out of browser support. Hope it is helping you gear up.

Previous posts in this series:

Related links:

Labels: , , ,

Email this | Bookmark this

Wednesday, April 22, 2009

Silverlight out-of-browser apps: Network Awareness

There will be times when your Silverlight app is run but the end user does not have a network connection. A key attribute of making a functional offline Silverlight app is building in network awareness. In this post, we’ll look at how easy Silverlight 3 makes this for you.

The API

Silverlight provides current network status via the NetworkInterface.GetIsNetworkAvailable() method. Apps can be notified of changes in network availability via the NetworkChange.NetworkAddressChanged event. The NetworkInterface and NetworkChange types are both declared in the System.Net.NetworkInformation namespace.

Here’s sample usage of the network detection APIs:

...

    NetworkChange.NetworkAddressChanged += 
                      new EventHandler (OnNetworkChange);

}


void
OnNetworkChange (object sender, EventArgs e)

{

    if (NetworkInterface.GetIsNetworkAvailable())

    {

        nwIndicatorEllipse.Fill =
                              new SolidColorBrush(Colors.Green);

        // and do something

    }

    else

    {

        nwIndicatorEllipse.Fill =
                              new SolidColorBrush(Colors.Red);

        // and do something else

    }

}

What This Feature Is

The NetworkAddressChanged event – as the name suggests - advertises a change in IP address (availability). It is to be used in concert with the NetworkInformation.GetIsNetworkAvailable() to identify whether the recent change resulted in the system obtaining an IP address or losing one. The IP address is seen as a good primordial proxy for availability of network connection or lack thereof.

This feature is an answer to the question “Is this is a good time to make an outbound network request?”. Silverlight plays an enabling role in detecting offline status, telling you whether it’s worth your while to make an outbound call, or alternately to cache and persist data locally until network connectivity is regained.

What this Feature Isn’t

This feature is not an answer to the question “Is my site (or web service) up and running at this moment?”. The way I see it, Silverlight doesn’t play an enabling role in that situation – that is something your app can achieve with 10 lines of code. And such a service indicator is better off taking the actual URI and returning an actual response, rather than being a glorified HTTP HEAD wrapper.

Gotchas

Say you have 2 adapters – a wireless and wireline Ethernet – both of which are connected. If your wireless connection drops, the NetworkAddressChanged event is raised but in the handler when you query NetworkInformation.GetIsNetworkAvailable(), you still get true because your wireline Ethernet connection is still valid. When that goes down as well, the event is raised yet again and the NetworkInformation.GetIsNetworkAvailable() returns false. Always remember: from your NetworkAddressChanged handler, you must query GetIsNetworkAvailable to definitively find out the connectivity situation.

Other gotchas include the “illusion of connectivity”. This happens when you have some connectivity (say you’re on a WiFi network in an airport or a coffee shop) but not any Internet connectivity until you sign in or pay up. Your app may see GetIsNetworkAvailable return true, but should still try that actual outbound request to ascertain this.

In some cases virtual machines (e.g. Hyper-V running on your Windows Server or running Windows with Parallels on your Mac) may interfere with this feature and your app may see false positives.

---

Previous posts in this series:

Related links:

Labels: , , ,

Email this | Bookmark this

Tuesday, April 21, 2009

Silverlight out-of-browser apps: Launch

Silverlight 3 offline/out-of-browser apps maintain a sticky presence on your desktop upon the initial detach (install) operation. They can be looked up and launched in an experience not unlike the one you see with conventional desktop applications. You can search for and find these apps using OS search utilities (Windows desktop search, Spotlight on OS X) where they show up in as Programs.

Application id

Silverlight uses some indirection from the shortcut to the real app binaries on Windows (however on the Mac, the bundle created on install is the app, with limited metadata squirreled away in the offline application cache). This isn’t because we drink the “architecture astronaut” kool-aid on indirection, rather because doing so in this case allows us to add runtime logic around housekeeping which is effective when updates for the app or runtime exist. If you deconstruct the shortcut to a Silverlight out-of-browser app on Windows, you’ll find a command like this:

“C:\Program Files\Microsoft Silverlight\<version>\
sllauncher.exe <app id>”

Ignore the newlines above. You’ll notice that the app id is a string made with the union of the domain of origin and some random number/text e.g. www.mysite.com.3509. During install on Windows, Silverlight creates a directory hive within your user profile so it can store the app binaries along with other metadata. It also assigns the app an identifier which is unique for a specific user on that machine. It appends this id into the shortcut, wherever the app is to be referenced.


The app launch sequence

When the shortcut is activated, the command is run, and as a result, sllauncher.exe is launched with that app id as argument. The launcher is a container program that chiefly handles the windowing logic for the app, while instantiating and deferring to Silverlight the specific function of loading and running the app. Among the things the launcher controls are the window adornments like icon and title text, a settings such as position. This is just scratching the surface. In future we expect to provide more window customization.


When sllauncher.exe hosts Silverlight, the runtime does a reverse lookup of the XAP file using the app id, additionally collects all metadata persisted in the offline application cache and then initializes Silverlight core services to the provenance URI of the XAP. This is the app’s original site of origin, not the location it was loaded off disk. This cascades into the correct (i.e. original) networking and security settings being applied to the app. All fallback lookups for relative URIs get resolved against the right base URI. All policy settings for cross-domain and cross-scheme access get applied properly; and the app has access to the same local persistence store (Isolated Storage) as its in-browser sibling. If not for the ExecutionState data exposed by the Silverlight runtime, the app would “think” it was running within the browser like it did prior to install. If updates to the XAP were successfully downloaded in a previous app launch, Silverlight will scavenge the old bits and use the updated bits instead. It is now ready to launch the app.


Was the app locally activated?

Upon launch, Silverlight applications can detect whether the current activation was from within a browser, or locally as a standalone window (aka out of browser). This is done by looking at the RunningOffline property of the Application type. When the value is true, the app was locally activated. When false, the app was activated via an OBJECT tag within a web page in the browser.


public partial class App : Application

{

public App ()

{

...

this.Startup += this.App_Startup;

}

void App_Startup(object sender, StartupEventArgs e)

{

     if (Application.Current.IsRunningOutOfBrowser)

{

this.RootVisual = new OutOfBrowserPage();

}

else

{

this.RootVisual = new PageToBeDisplayedInBrowser();

}

}

}



Note: we’re changing API names to better reflect behavior; so expect the code snippet to change with Silverlight 3 RTW, but the principles will more or less remain true.


In the next post we will look at network awareness in offline/out-of-browser Silverlight apps. See you then.


Previous posts in this series:

[Update 10-Jul-09]: Code snippets updated for Silverlight 3 RTW.

Labels: , , ,

Email this | Bookmark this

Sunday, April 12, 2009

Silverlight out-of-browser apps: The Install

There are three main pillars to the new offline and out-of-browser feature set in Silverlight. These pillars are also tied to user experience; namely Install, Launch and Manage. In additions there are framework-level APIs and behind the scenes support from the runtime for a plethora of things that cross-cut these 3 pillars. 

In this post we will look specifically at the Install operation.

A Silverlight app needs to be specially crafted for that out-of-browser function. There’s not much to it really: the application manifest (AppManifest.xaml) should be adorned with the OutOfBrowserSettings element which declares such metadata on the app as short name, window title, blurb and icons. No worries, tools make this easy for you via the Silverlight application project properties pane. Silverlight treats the presence of this element as an indication from the app author for opt-in to the out-of-browser feature set. Only this class of apps can be “installed”.

The install operation itself can be achieved in one of two ways:

  • via platform UI on the context menu that says “Install {app short name} onto this computer…”
  • via app driven UI which calls the Install() method on the Application type

Implicit in either case is the fact that install is required to be a user-initiated operation. And that too user-initiated within the Silverlight display surface on a web page. This allows us (building the runtime and platform) to better control the user experience and guarantee predictability, security etc.

Further, Silverlight apps cannot be installed without the consumer end user specifically consenting to this action. This removes the element of surprise. We’ve tried to maintain consistency with the experience one intuits on a particular operating system, while also balancing the needs of Silverlight app authors and our own user experience goals. As a result, you will see different UX on Windows and Mac – each appealing to its demographic.


On Windows, Silverlight shows an application modal dialog like this, seeking the user’s permission to proceed:

The dialog is modeled as a confirmation dialog, and the user is asked to allow or deny permission in context, with the assertion “You are installing {app short name} from {domain of origin}”

The astute reader will notice that the dialogs are similar across Windows and Mac OS X – at least in principle – but each adheres to the native OS theme. The Mac dialog does not seek shortcut preferences, given that Mac users are expected in the very next step to drag the out-of-browser app bundle into a location of their choice, much like they would when installing another application.

A dialog of the form above is shown when the app declares no icons of its own. You see the “fallback” icon shown by the runtime.  When the app declares its own brand icon, Silverlight will gladly display it at install time, as the following screenshot of the dialog on Windows attests: If the install were initiated via the Install() method call on the UI thread, the method would synchronously block until the consumer end user made their decision. If they declined, the method returns false; otherwise true. The other install related activities happen asynchronously. The platform signals this to the app via the InstallStateChanged event and the InstallState.Installing state; it inducts the XAP, along with some metadata and housekeeping information into the offline application cache within the user’s profile dir. When this is successfully completed, the platform raises the InstallStateChanged event with the InstallState.Installed state. This is the official notification to the hitherto in-browser app that its out-of-browser copy has been installed. The out-of-browser app gets a higher default quota (25MB to the previous 1MB) within Isolated Storage for its local data persistence needs. The in-browser and out-of-browser apps share this Isolated Storage with each other. We’re not yet sure if the magic number of 25MB is the right one (or if there is in fact any right value); it is however orders of magnitude higher than the default for in-browser apps and we hope it will open up new scenarios and result in the proverbial 80% of our apps not having to ask the consumer user for a quota increase yet again.

Upon successful install, Silverlight auto-launches the newly installed app – all sandboxed, out of the browser, and ready to go! The salient points of this Install operation are:


  • keep it lightweight
  • showcase the app brand, not the technology powering it
  • keep the decision simple for the consumer, and in context
  • get the consumer to their desired goal in the shortest time possible i.e. launch the app upon install

More about the story behind the Launch experience in the next post. Until then, cheerio, toodle-ooh and all that.


Related posts:



[Update 10-Jul-09] API names updated to reflect Silverlight 3 RTW

Labels: , ,

Email this | Bookmark this

Wednesday, April 01, 2009

Silverlight out-of-browser support: What kind of apps can you build?

This is first in my series of technical drilldown posts on the new offline and out of browser support in Silverlight 3.

It is something of a tradition in Microsoft to list out scenarios when a new feature set is being conceived. This practice is by no means unique to this company. I feel that doing so establishes a common baseline and taxonomy which immensely helps as the concept matures and gains complexity. Typically these scenarios are fleshed out in functional specifications.

In this post, I summarize the flavors of apps and scenarios that are enabled by the new offline and out of browser support in Silverlight 3. Most of these are self-explanatory and so using another Microsoft tradition, I will stick to concise bullet points rather than prose. A list similar to the one below in fact was used by our crew when we started our planning for this feature set a few months ago:

Connectedness

Fully disconnected app

  • App has no networking needs
  • Reliance on Silverlight just as an installation vehicle for the app
  • We don’t expect this will be very common

Occasionally connected app

  • App is resilient to network outage
  • Conditionally persists data into iso store or cloud based on network availability
  • This is the sweet spot for our feature offerings and where most of our attention goes

Connected app

  • App uses the offline feature set only for the sticky desktop presence
  • We don’t expect this will be very common

User experience

App behaves exactly the same in browser and out

  • App author wants to deliver the same experience in either case
  • “Try before you buy”, “Get more features upon install” and other such progressively enhanced SKU situations
  • Our data suggests consumers find comfort in apps that – in broad brushes – seem similar OOB as when they did in-browser

App shows different UI in-browser and out-of-browser

  • App author wants to exploit the real estate available in standalone window
  • Browser page could have limited functionality which lights up only upon detach
  • Browser page shows only the “Install” badge and the “real” UI only shows up when launched out of browser

Approach

Porting an existing Silverlight 2 app to run offline/out-of-browser

  • Even though the feature is a new addition to SL3, some SL2 apps can benefit from it
  • Requires no changes to code and no rebuilds
  • Can be done as a post-production step by modifying the manifest and optionally adding icons into the XAP
  • Build disconnected and connected apps, but not occasionally connected

Building a new offline/out-of-browser app

  • Our mainline scenario
  • Leverage everything the offline/out-of-browser feature set and the rest of Silverlight has to offer
  • Build disconnected, connected and occasionally connected apps

In the next post, we will look at the pillars of this feature, starting with the install (a.k.a detach) operation.

Related posts:

Labels: , , ,

Email this | Bookmark this