patridge
patridge

Reputation: 26565

Using jQuery with Windows 8 Metro JavaScript App causes security error

Since it sounded like jQuery was an option for Metro JavaScript apps, I was starting to look forward to Windows 8 dev. I installed Visual Studio 2012 Express RC and started a new project (both empty and grid templates have the same problem).

I made a local copy of jQuery 1.7.2 and added it as a script reference.

<!-- SomeTestApp references -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/jquery-1.7.2.js"></script>
<script src="/js/default.js"></script>

Unfortunately, as soon as I ran the resulting app it tosses out a console error:

HTML1701: Unable to add dynamic content ' a' A script attempted to inject dynamic content, or elements previously modified dynamically, that might be unsafe. For example, using the innerHTML property to add script or malformed HTML will generate this exception. Use the toStaticHTML method to filter dynamic content, or explicitly create elements and attributes with a method such as createElement. For more information, see http://go.microsoft.com/fwlink/?LinkID=247104.

I slapped a breakpoint in a non-minified version of jQuery and found the offending line:

div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";

Apparently, the security model for Metro apps forbids creating elements this way. This error doesn't cause any immediate issues for the user, but given its location, I am worried it will cause capability-discovery tests in jQuery to fail that shouldn't.

I definitely want jQuery $.Deferred for making just about everything easier. I would prefer to be able to use the selector engine and event handling systems, but I would live without them if I had to.

How does one get the latest jQuery to play nicely with Metro development?

Upvotes: 44

Views: 32658

Answers (11)

buildwinjs
buildwinjs

Reputation: 79

The JavaScript Dynamic Content shim on GitHub was created and released by Microsoft Open Technologies to address this error. It has not been tested with jQuery but will most likely solve your problem. Reference the winstore-jscompat.js file in the beginning of your app before any other scripts are run and you should no longer see this error.

Upvotes: 6

Dave Voyles
Dave Voyles

Reputation: 4605

I wrote a pretty detailed explanation on how to get jQuery to work with Windows 8 here http://davidvoyles.wordpress.com/2013/09/23/hacking-jquery-to-work-in-windows-8/

Upvotes: 1

Nikhil Ranjan
Nikhil Ranjan

Reputation: 992

Here is your answer

https://github.com/appendto/jquery-win8

Its official jquery library for windows 8

Upvotes: 8

Sagar Sane
Sagar Sane

Reputation: 101

After the recent //Build/ 2012 conference and this talk talks about using jQuery in Windows 8 Store Apps. Specifically, they talk about the exact exception of script injection inside innerHTML, and talk about the updates done in this.

The company AppendTo also officially unveiled jQuery for Windows 8 during that talk. It looks neat from the demonstration given in the talk in the link about.

They also say that it is not a good idea to get jQuery from CDN for Windows 8 Apps in Local Context!

Upvotes: 7

Rob M.
Rob M.

Reputation: 36511

For what it's worth, I've ported the majority of jQuery core to wrap the native WinJS library. It's lightweight and provides just about everything that jQuery does with the addition of some plugins for badges, notifications, etc.

It is a work in progress, but I'm trying to get some people to join in the fun.

https://github.com/rmcvey/winjq

Quick write-up (documentation is being added to): http://practicaljs.com/jquery-in-windows-8-apps/

Upvotes: 7

fpintos
fpintos

Reputation: 1

I was able to eliminate the problem by finding all places in jQuery that set innerHTML and wrapping the value being set with toStaticHTML().

So, for example:

div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";

became:

div.innerHTML = toStaticHTML("   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>");

To be safe, I've also defined this just before jQuery is defined, in case the file is used in a normal browser:

window.toStaticHTML = window.toStaticHTML || function (s) { return s; };

To me that seemed to be the safest change, although it required patching a dozen places in jQuery. (don't use a var statement before the toStaticHTML)

Upvotes: 0

Konstantin Dinev
Konstantin Dinev

Reputation: 34895

jQuery itself did not throw such exceptions for me in the latest version as long as I replaced all code of the form e.g.:

$('<input type="button" value="Press Me" />')

with

$(toStaticHTML('<input type="button" value="Press Me" />'))

Note that not all HTML strings are considered unsafe e.g.:

$('<span></span>')

Does not throw any exceptions. However jQuery still throws exceptions on append if you do something of the sort:

var div = '<div class="' + classesToApply + '"';
div += attrToAdd;
div += '</div>';

$(div).appendTo(container);

The above is not an example for good practices using jQuery still some people do it so you may encounter the error. Notice the above code does not generate the same error as the very first snippet but instead throws the error inside jQuery.append. This error is still fixed via performing $(toStaticHTML(div)).appendTo(container);

Upvotes: 0

Dave Methvin
Dave Methvin

Reputation: 1468

I believe this is the same restriction as imposed by Content Security Policy (CSP). That specific case was addressed in jQuery 1.8.0. Does the problem still occur there?

https://github.com/jquery/jquery/commit/dc83072878ed9636c8158a014bd9fa4acc1ccce3

Upvotes: 0

Nicolas Ramz
Nicolas Ramz

Reputation: 1

If you still need it, I am writting a reimplementation of the Deferred object found in jQuery.

Once finished it should be 100% compatible with jQuery's Deferred object. Right now it's quite complete but needs some testing.

See this.

Hope this will help!

That said, I think it should be a good idea to learn how to use Microsoft's implementation of Promise instead of jQuery when working on Windows 8 apps.

Upvotes: 0

Chris Tavares
Chris Tavares

Reputation: 30401

I've done a little more investigation, and wanted to clarify a couple of things.

The error you see is in the JavaScript console, not an actual exception. The jQuery code continues to run just fine. It's actually something the underlying system is logging, not an error or exception.

There's no reason to patch jQuery or do anything else - it's a noisy system component, not an actual error.

Upvotes: 2

Adam Freeman
Adam Freeman

Reputation: 1184

You need to edit the jQuery source so that you pass the jQuery.support function to MSApp.execUnsafeLocalFunction, which disables the unsafe content checking, like this:

jQuery.support = MSApp.execUnsafeLocalFunction(function() {

    var support,
        all,
        a,
        select,
        opt,
        input,
        fragment,
        tds,
        events,
        eventName,
        i,
        isSupported,
        div = document.createElement( "div" ),
        documentElement = document.documentElement;


    // lots of statements removed for brevity

    return support;
});

You need to remember to remove the last pair of parenthesis - you don't need a self-executing function because execUnsafeLocalFunction automatically executes the function it is passed.

I suggest that a better approach is to use the WinJS features - this includes the WinJS.Promise object as an alternative to deferred operations (which are themselves an implementation of the Promise pattern). And you can do some basic DOM manipulation using the WinJS.Utilities namespace.

You should think twice about using jQuery for deferred operations. The WinJS.Promise object is used throughout the Metro APIs to represent async activities and you will end up using two similar-but-different approaches.

Upvotes: 33

Related Questions