简体   繁体   中英

Silverlight IsolatedStorageFile.IncreaseQuotaTo

Msdn doc for IsolatedStorageFile.IncreaseQuotaTo states that:

To increase the quota, you must call this method from a user-initiated event, such as in an event handler for a button-click event. When you call the IncreaseQuotaTo method, the common language runtime in Silverlight presents a dialog box for the user to approve the request. If the user declines the request, this method returns false and the quota remains the same size.

How does Silverlight know that the method was called from a user-initiated event like a button click and not from some other thread?

More specifically: What is a user initiated event? Is there any way to overcome this limitation?

And another question:

I do some automatic downloads of files when user first accesses my application, but I don't want the user to press "Download" and then when I detect more space is needed call IncreaseQuota and have the "Silverlight dialog" appearing asking for more space.

I want to start the download automatically (not user initiated), and if I detect more space is needed, call IncreaseQuota and hence have the "Silverlight dialog" appear. (No user pressing download).

After much digging, I did find out what a user initiated event is. Seems that msdn doc specifies what a user initiated event in the section related to "events overview", but there's no link between documentation of IsolatedStorageFile.IncreaseQuotaTo and Events Overview

So a user initiated event according to the definition is:

Silverlight enforces that certain operations are only permitted in the context of a handler that handles a user-initiated event. The following is a list of such operations:

Setting IsFullScreen.

Showing certain dialogs. This includes SaveFileDialog, OpenFileDialog, and the print dialog displayed by PrintDocument.Print.

Navigating from a HyperlinkButton.

Accessing the primary Clipboard API.

Silverlight user-initiated events include the mouse events (such as MouseLeftButtonDown), and the keyboard events (such as KeyDown). Events of controls that are based on such events (such as Click) are also considered user-initiated.

API calls that require user initiation should be called as soon as possible in an event handler. This is because the Silverlight user initiation concept also requires that the calls occur within a certain time window after the event occurrence. In Silverlight 4, this time window is approximately one second.

User-initiated event restrictions also apply to usages of JavaScript API for Silverlight.

When Silverlight is in full-screen mode, some input events are deliberately limited for security reasons, although this can be mitigated for out-of-browser applications using elevated trust. For more information, see Full-Screen Support.

Although I don't see "IncreaseQuotaTo" inside the list of "operations", I'm guessing they just forgot it, since the behavior/limitations are the same as the ones described in the doc.

I was curios how exactly does silverlight know what a user initiated event is but after digging through .net framework source code I've got to a dead end:

if ((browserService == null) || !browserService.InPrivateMode())
{
    //..
}
return false; //means that IncreaseQuota will fail

where browser.IsInPrivateMode is:

[SecuritySafeCritical]
public bool InPrivateMode()
{
    bool privateMode = false;
    return (NativeMethods.SUCCEEDED(UnsafeNativeMethods.DOM_InPrivateMode(this._browserServiceHandle, out privateMode)) && privateMode);
}

where DOM_InPrivateMode is in a DllImport["agcore"] which according to microsoft is confidential :( So it looks like I won't find out soon how they're detecting user initiated events.

Thinking it more about it, I guess microsoft didn't want a user to have many tabs open in a browser and then poof: I call automatically IncreaseQuotaTo.

The IncreaseQuotaTo is a browser modal dialog. This means you can't navigate to other browser tabs while is active. So if the user has now moved from my page to the tab with google.com, and if I would be able to call IncreaseQuotaTo with a delay, the user might think that google.com is asking for more storage :).

This would be a security breach indeed.

Had they implemented this with a page level dialog, then that would have been probably more easily hacked (or worked around).

So all in all, thinking of it, I'm starting to see why they implemented it like this and why these limitations exist.

The documentation isn't incomplete.

If I do this... button_click(..) { new UserControl() } ... Does this still count as a user initiated event?

Yes. But what has that little bit of extra code really achieved?

What i've personally never experimented with is exactly what consitutes a user event; IOW is a mouse-over considered a user event? This will be very simple for you to try, and there are a multitude of other things you can experiment with. If necessary you could have a splash screen popup that welcomes the user and they have to click on it to dismiss it, at which point you make the request. It may seem a bit corny, but you can get away with things like this if you present it well.

Note that the prompt is a one-time thing. If you prompt the user and they accept, that storage is persisted for your application between visits, which means you don't need to prompt them again the next time they use your control, your quota is still increased from last time (unless the user has deliberately deleted it, which they can do by right clicking on the Silverlight control and then going to the Application Storage tab).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM