diff --git a/common/djangoapps/xmodule_modifiers.py b/common/djangoapps/xmodule_modifiers.py
index 8e4a305595..f82a194e93 100644
--- a/common/djangoapps/xmodule_modifiers.py
+++ b/common/djangoapps/xmodule_modifiers.py
@@ -113,11 +113,10 @@ def wrap_xblock(runtime_class, block, view, frag, context, usage_id_serializer,
}
if hasattr(frag, 'json_init_args') and frag.json_init_args is not None:
- template_context['js_init_parameters'] = json.dumps(frag.json_init_args)
- template_context['js_pass_parameters'] = True
+ # Replace / with \/ so that "" in the data won't break things.
+ template_context['js_init_parameters'] = json.dumps(frag.json_init_args).replace("/", r"\/")
else:
template_context['js_init_parameters'] = ""
- template_context['js_pass_parameters'] = False
return wrap_fragment(frag, render_to_string('xblock_wrapper.html', template_context))
diff --git a/common/templates/xblock_wrapper.html b/common/templates/xblock_wrapper.html
index 74574907df..41951dc61c 100644
--- a/common/templates/xblock_wrapper.html
+++ b/common/templates/xblock_wrapper.html
@@ -1,5 +1,5 @@
-% if js_pass_parameters:
+% if js_init_parameters:
diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py
index c4463166b9..946c428577 100644
--- a/lms/djangoapps/courseware/tests/test_module_render.py
+++ b/lms/djangoapps/courseware/tests/test_module_render.py
@@ -16,10 +16,12 @@ from django.contrib.auth.models import AnonymousUser
from mock import MagicMock, patch, Mock
from opaque_keys.edx.keys import UsageKey, CourseKey
from opaque_keys.edx.locations import SlashSeparatedCourseKey
+from courseware.module_render import hash_resource
from xblock.field_data import FieldData
from xblock.runtime import Runtime
from xblock.fields import ScopeIds
from xblock.core import XBlock
+from xblock.fragment import Fragment
from capa.tests.response_xml_factory import OptionResponseXMLFactory
from courseware import module_render as render
@@ -660,6 +662,53 @@ class TestHtmlModifiers(ModuleStoreTestCase):
)
+class XBlockWithJsonInitData(XBlock):
+ """
+ Pure XBlock to use in tests, with JSON init data.
+ """
+ the_json_data = None
+
+ def student_view(self, context=None): # pylint: disable=unused-argument
+ """
+ A simple view that returns just enough to test.
+ """
+ frag = Fragment(u"Hello there!")
+ frag.add_javascript(u'alert("Hi!");')
+ frag.initialize_js('ThumbsBlock', self.the_json_data)
+ return frag
+
+
+@ddt.ddt
+class JsonInitDataTest(ModuleStoreTestCase):
+ """Tests for JSON data injected into the JS init function."""
+
+ @ddt.data(
+ ({'a': 17}, '''{"a": 17}'''),
+ ({'xss': 'alert("XSS")'}, r'''{"xss": "<\/script>alert(\"XSS\")"}'''),
+ )
+ @ddt.unpack
+ @XBlock.register_temp_plugin(XBlockWithJsonInitData, identifier='withjson')
+ def test_json_init_data(self, json_data, json_output):
+ XBlockWithJsonInitData.the_json_data = json_data
+ mock_user = UserFactory()
+ mock_request = MagicMock()
+ mock_request.user = mock_user
+ course = CourseFactory()
+ descriptor = ItemFactory(category='withjson', parent=course)
+ field_data_cache = FieldDataCache([course, descriptor], course.id, mock_user) # pylint: disable=no-member
+ module = render.get_module_for_descriptor(
+ mock_user,
+ mock_request,
+ descriptor,
+ field_data_cache,
+ course.id, # pylint: disable=no-member
+ )
+ html = module.render(STUDENT_VIEW).content
+ self.assertIn(json_output, html)
+ # No matter what data goes in, there should only be one close-script tag.
+ self.assertEqual(html.count(""), 1)
+
+
class ViewInStudioTest(ModuleStoreTestCase):
"""Tests for the 'View in Studio' link visiblity."""