Revert "remove Content-Type restriction for manifests (bug 778214)"

This reverts commit 35ce8e5844.
This commit is contained in:
Chris Van 2012-08-30 14:25:39 -07:00
Родитель c9f2f1b10c
Коммит 17bc34e36f
10 изменённых файлов: 83 добавлений и 21 удалений

Просмотреть файл

@ -800,6 +800,8 @@ class TestCreateApp(BaseOAuth):
response_mock = Mock()
response_mock.read.return_value = '{"name": "Some App"}'
response_mock.headers = {'Content-Type':
'application/x-web-app-manifest+json'}
self.urlopen_mock = patcher.start()
self.urlopen_mock.return_value = response_mock

Просмотреть файл

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import base64
from datetime import date
import json
import logging
import os
@ -13,6 +14,7 @@ import uuid
from django.conf import settings
from django.core.files.storage import default_storage as storage
from django.core.management import call_command
from django.utils.http import urlencode
from celeryutils import task
from django_statsd.clients import statsd
@ -152,8 +154,8 @@ def run_validator(file_path, for_appversions=None, test_all_tiers=False,
return validate(path,
for_appversions=for_appversions,
format='json',
# When False, this flag says to stop testing after
# one tier fails.
# When False, this flag says to stop testing after one
# tier fails.
determined=test_all_tiers,
approved_applications=apps,
spidermonkey=settings.SPIDERMONKEY,
@ -252,9 +254,11 @@ def get_preview_sizes(ids, **kw):
for preview in previews:
try:
log.info('Getting size for preview: %s' % preview.pk)
thumb = Image.open(storage.open(preview.thumbnail_path)).size
img = Image.open(storage.open(preview.image_path)).size
preview.update(sizes={'thumbnail': thumb, 'image': img})
sizes = {
'thumbnail': Image.open(storage.open(preview.thumbnail_path)).size,
'image': Image.open(storage.open(preview.image_path)).size,
}
preview.update(sizes=sizes)
except Exception, err:
log.error('Failed to find size of preview: %s, error: %s'
% (addon.pk, err))
@ -329,6 +333,16 @@ def _fetch_content(url):
raise Exception(str(e.reason))
def check_content_type(response, content_type,
no_ct_message, wrong_ct_message):
if not response.headers.get('Content-Type', '').startswith(content_type):
if 'Content-Type' in response.headers:
raise Exception(wrong_ct_message %
(content_type, response.headers['Content-Type']))
else:
raise Exception(no_ct_message % content_type)
def get_content_and_check_size(response, max_size, error_message):
# Read one extra byte. Reject if it's too big so we don't have issues
# downloading huge files.
@ -392,6 +406,13 @@ def fetch_manifest(url, upload_pk=None, **kw):
try:
response = _fetch_content(url)
no_ct_message = _('Your manifest must be served with the HTTP '
'header "Content-Type: %s".')
wrong_ct_message = _('Your manifest must be served with the HTTP '
'header "Content-Type: %s". We saw "%s".')
check_content_type(response, 'application/x-web-app-manifest+json',
no_ct_message, wrong_ct_message)
size_error_message = _('Your manifest must be less than %s bytes.')
content = get_content_and_check_size(response,
settings.MAX_WEBAPP_UPLOAD_SIZE,

Просмотреть файл

@ -284,9 +284,15 @@ def fetch_icon(webapp, **kw):
def _fetch_manifest(url):
try:
response = _fetch_content(url)
ct = response.headers.get('Content-Type', '')
if not ct.startswith('application/x-web-app-manifest+json'):
raise Exception('Content type is ' + ct)
except Exception, e:
log.error('Failed to fetch manifest from %r: %s' % (url, e))
raise Exception('No manifest was found at that URL.')
raise Exception('No manifest was found at that URL. Check the '
'address and make sure the manifest is served '
'with the HTTP header "Content-Type: '
'application/x-web-app-manifest+json".')
size_error_message = _('Your manifest must be less than %s bytes.')
content = get_content_and_check_size(response,

Просмотреть файл

@ -151,6 +151,7 @@ class TestFetchManifest(amo.tests.TestCase):
def setUp(self):
self.upload = FileUpload.objects.create()
self.content_type = 'application/x-web-app-manifest+json'
patcher = mock.patch('mkt.developers.tasks.urllib2.urlopen')
self.urlopen_mock = patcher.start()
@ -166,6 +167,7 @@ class TestFetchManifest(amo.tests.TestCase):
def patch_urlopen(self):
response_mock = mock.Mock()
response_mock.read.return_value = '<default>'
response_mock.headers = {'Content-Type': self.content_type}
yield response_mock
self.urlopen_mock.return_value = response_mock
@ -173,6 +175,7 @@ class TestFetchManifest(amo.tests.TestCase):
def test_success_add_file(self, validator_mock):
with self.patch_urlopen() as ur:
ur.read.return_value = 'woo'
ur.headers = {'Content-Type': self.content_type}
tasks.fetch_manifest('http://xx.com/manifest.json', self.upload.pk)
upload = FileUpload.objects.get(pk=self.upload.pk)
@ -183,7 +186,8 @@ class TestFetchManifest(amo.tests.TestCase):
@mock.patch('mkt.developers.tasks.validator')
def test_success_call_validator(self, validator_mock):
with self.patch_urlopen() as ur:
ur.read.return_value = 'woo'
ct = self.content_type + '; charset=utf-8'
ur.headers = {'Content-Type': ct}
tasks.fetch_manifest('http://xx.com/manifest.json', self.upload.pk)
assert validator_mock.called
@ -200,33 +204,48 @@ class TestFetchManifest(amo.tests.TestCase):
reason = socket.gaierror(8, 'nodename nor servname provided')
self.urlopen_mock.side_effect = urllib2.URLError(reason)
tasks.fetch_manifest('url', self.upload.pk)
self.check_validation('No manifest was found at that URL.')
self.check_validation(
'No manifest was found at that URL. Check the address and make'
' sure the manifest is served with the HTTP header '
'"Content-Type: application/x-web-app-manifest+json".')
def test_url_timeout(self):
reason = socket.timeout('too slow')
self.urlopen_mock.side_effect = urllib2.URLError(reason)
tasks.fetch_manifest('url', self.upload.pk)
self.check_validation('No manifest was found at that URL.')
self.check_validation(
'No manifest was found at that URL. Check the address and make'
' sure the manifest is served with the HTTP header '
'"Content-Type: application/x-web-app-manifest+json".')
def test_other_url_error(self):
reason = Exception('Some other failure.')
self.urlopen_mock.side_effect = urllib2.URLError(reason)
tasks.fetch_manifest('url', self.upload.pk)
self.check_validation('No manifest was found at that URL.')
self.check_validation(
'No manifest was found at that URL. Check the address and make'
' sure the manifest is served with the HTTP header '
'"Content-Type: application/x-web-app-manifest+json".')
def test_no_content_type_bad_json(self):
def test_no_content_type(self):
with self.patch_urlopen() as ur:
ur.headers = {}
tasks.fetch_manifest('url', self.upload.pk)
self.check_validation('JSON Parse Error')
self.check_validation(
'No manifest was found at that URL. Check the address and make'
' sure the manifest is served with the HTTP header '
'"Content-Type: application/x-web-app-manifest+json".')
def test_bad_content_type_bad_json(self):
def test_bad_content_type(self):
with self.patch_urlopen() as ur:
ur.headers = {'Content-Type': 'x'}
tasks.fetch_manifest('url', self.upload.pk)
self.check_validation('JSON Parse Error')
self.check_validation(
'No manifest was found at that URL. Check the address and make'
' sure the manifest is served with the HTTP header '
'"Content-Type: application/x-web-app-manifest+json".')
def test_response_too_large(self):
with self.patch_urlopen() as ur:
@ -240,7 +259,10 @@ class TestFetchManifest(amo.tests.TestCase):
self.urlopen_mock.side_effect = urllib2.HTTPError(
'url', 404, 'Not Found', [], None)
tasks.fetch_manifest('url', self.upload.pk)
self.check_validation('No manifest was found at that URL.')
self.check_validation(
'No manifest was found at that URL. Check the address and make'
' sure the manifest is served with the HTTP header '
'"Content-Type: application/x-web-app-manifest+json".')
def test_strip_utf8_bom(self):
with self.patch_urlopen() as ur:

Просмотреть файл

@ -1433,6 +1433,7 @@ class TestUploadDetail(BaseUploadTest):
urlopen_mock):
rs = mock.Mock()
rs.read.return_value = self.file_content('mozball.owa')
rs.headers = {'Content-Type': 'application/x-web-app-manifest+json'}
urlopen_mock.return_value = rs
validator_mock.return_value = json.dumps(self.validation_ok())
self.upload_file('mozball.owa')

Просмотреть файл

@ -47,6 +47,8 @@ response_mock.read.return_value = '''
"installs_allowed_from": [ "https://marketplace.mozilla.org" ]
}
'''
response_mock.headers = {'Content-Type':
'application/x-web-app-manifest+json'}
def get_section_url(addon, section, edit=False):

Просмотреть файл

@ -23,22 +23,22 @@ class Test404(amo.tests.TestCase):
return r
def test_404(self):
self._test_404('/xxx')
r = self._test_404('/xxx')
def test_404_devhub(self):
# TODO: Remove log-in bit when we remove `request.can_view_consumer`.
assert self.client.login(username='steamcube@mozilla.com',
password='password')
self._test_404('/developers/xxx')
r = self._test_404('/developers/xxx')
def test_404_consumer_legacy(self):
self._test_404('/xxx')
r = self._test_404('/xxx')
def test_404_consumer(self):
# TODO: Remove log-in bit when we remove `request.can_view_consumer`.
assert self.client.login(username='steamcube@mozilla.com',
password='password')
self._test_404('/xxx')
r = self._test_404('/xxx')
class TestManifest(amo.tests.TestCase):
@ -46,6 +46,7 @@ class TestManifest(amo.tests.TestCase):
def test_manifest(self):
response = self.client.get(reverse('manifest.webapp'))
eq_(response.status_code, 200)
eq_(response['Content-Type'], 'application/x-web-app-manifest+json')
content = json.loads(response.content)
eq_(content['name'], 'Firefox Marketplace')
eq_(content['default_locale'], 'en-US')

Просмотреть файл

@ -65,7 +65,8 @@ def manifest(request):
'locales': {},
'default_locale': 'en-US'
}
return HttpResponse(json.dumps(data))
return HttpResponse(json.dumps(data),
mimetype='application/x-web-app-manifest+json')
def robots(request):

Просмотреть файл

@ -82,6 +82,8 @@ class TestUpdateManifest(amo.tests.TestCase):
self.response_mock = mock.Mock()
self.response_mock.read.return_value = self._data()
self.response_mock.headers = {
'Content-Type': 'application/x-web-app-manifest+json'}
self.urlopen_mock.return_value = self.response_mock
@mock.patch('mkt.webapps.tasks._get_content_hash')
@ -166,6 +168,8 @@ class TestUpdateManifest(amo.tests.TestCase):
n['name'] = 'Mozilla Ball Ultimate Edition'
response_mock = mock.Mock()
response_mock.read.return_value = json.dumps(n)
response_mock.headers = {
'Content-Type': 'application/x-web-app-manifest+json'}
self.urlopen_mock.return_value = response_mock
eq_(RereviewQueue.objects.count(), 0)
@ -185,6 +189,8 @@ class TestUpdateManifest(amo.tests.TestCase):
n['locale'] = 'en-US'
response_mock = mock.Mock()
response_mock.read.return_value = json.dumps(n)
response_mock.headers = {
'Content-Type': 'application/x-web-app-manifest+json'}
self.urlopen_mock.return_value = response_mock
eq_(RereviewQueue.objects.count(), 0)

Просмотреть файл

@ -31,7 +31,7 @@ def fileapp(environ, start_response):
body = "".join(out)
else:
f = open(full_path, 'r')
if full_path.endswith(('.webapp', '.json')):
if full_path.endswith('.webapp') or full_path.endswith('.json'):
content_type = 'application/x-web-app-manifest+json'
body = f.read() # optimized for small files :)