mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
Add useragent-based detection of JS version (#10776)
* Add useragent-based detection of JS version * Keep es5 as default meanwhile * Update test
This commit is contained in:
parent
7ab15c0e79
commit
99ea2c17a1
@ -23,7 +23,7 @@ from homeassistant.const import CONF_NAME, EVENT_THEMES_UPDATED
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
REQUIREMENTS = ['home-assistant-frontend==20171127.0']
|
||||
REQUIREMENTS = ['home-assistant-frontend==20171127.0', 'user-agents==1.1.0']
|
||||
|
||||
DOMAIN = 'frontend'
|
||||
DEPENDENCIES = ['api', 'websocket_api', 'http', 'system_log']
|
||||
@ -32,6 +32,7 @@ URL_PANEL_COMPONENT_FP = '/frontend/panels/{}-{}.html'
|
||||
|
||||
CONF_THEMES = 'themes'
|
||||
CONF_EXTRA_HTML_URL = 'extra_html_url'
|
||||
CONF_EXTRA_HTML_URL_ES5 = 'extra_html_url_es5'
|
||||
CONF_FRONTEND_REPO = 'development_repo'
|
||||
CONF_JS_VERSION = 'javascript_version'
|
||||
JS_DEFAULT_OPTION = 'es5'
|
||||
@ -63,6 +64,7 @@ DATA_FINALIZE_PANEL = 'frontend_finalize_panel'
|
||||
DATA_PANELS = 'frontend_panels'
|
||||
DATA_JS_VERSION = 'frontend_js_version'
|
||||
DATA_EXTRA_HTML_URL = 'frontend_extra_html_url'
|
||||
DATA_EXTRA_HTML_URL_ES5 = 'frontend_extra_html_url_es5'
|
||||
DATA_THEMES = 'frontend_themes'
|
||||
DATA_DEFAULT_THEME = 'frontend_default_theme'
|
||||
DEFAULT_THEME = 'default'
|
||||
@ -79,6 +81,8 @@ CONFIG_SCHEMA = vol.Schema({
|
||||
}),
|
||||
vol.Optional(CONF_EXTRA_HTML_URL):
|
||||
vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(CONF_EXTRA_HTML_URL_ES5):
|
||||
vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(CONF_JS_VERSION, default=JS_DEFAULT_OPTION):
|
||||
vol.In(JS_OPTIONS)
|
||||
}),
|
||||
@ -269,11 +273,12 @@ def async_register_panel(hass, component_name, path, md5=None,
|
||||
|
||||
@bind_hass
|
||||
@callback
|
||||
def add_extra_html_url(hass, url):
|
||||
def add_extra_html_url(hass, url, es5=False):
|
||||
"""Register extra html url to load."""
|
||||
url_set = hass.data.get(DATA_EXTRA_HTML_URL)
|
||||
key = DATA_EXTRA_HTML_URL_ES5 if es5 else DATA_EXTRA_HTML_URL
|
||||
url_set = hass.data.get(key)
|
||||
if url_set is None:
|
||||
url_set = hass.data[DATA_EXTRA_HTML_URL] = set()
|
||||
url_set = hass.data[key] = set()
|
||||
url_set.add(url)
|
||||
|
||||
|
||||
@ -358,9 +363,13 @@ def async_setup(hass, config):
|
||||
|
||||
if DATA_EXTRA_HTML_URL not in hass.data:
|
||||
hass.data[DATA_EXTRA_HTML_URL] = set()
|
||||
if DATA_EXTRA_HTML_URL_ES5 not in hass.data:
|
||||
hass.data[DATA_EXTRA_HTML_URL_ES5] = set()
|
||||
|
||||
for url in conf.get(CONF_EXTRA_HTML_URL, []):
|
||||
add_extra_html_url(hass, url)
|
||||
add_extra_html_url(hass, url, False)
|
||||
for url in conf.get(CONF_EXTRA_HTML_URL_ES5, []):
|
||||
add_extra_html_url(hass, url, True)
|
||||
|
||||
yield from async_setup_themes(hass, conf.get(CONF_THEMES))
|
||||
|
||||
@ -488,12 +497,14 @@ class IndexView(HomeAssistantView):
|
||||
|
||||
template = yield from hass.async_add_job(self.get_template, latest)
|
||||
|
||||
extra_key = DATA_EXTRA_HTML_URL if latest else DATA_EXTRA_HTML_URL_ES5
|
||||
|
||||
resp = template.render(
|
||||
no_auth=no_auth,
|
||||
panel_url=panel_url,
|
||||
panels=hass.data[DATA_PANELS],
|
||||
theme_color=MANIFEST_JSON['theme_color'],
|
||||
extra_urls=hass.data[DATA_EXTRA_HTML_URL],
|
||||
extra_urls=hass.data[extra_key],
|
||||
)
|
||||
|
||||
return web.Response(text=resp, content_type='text/html')
|
||||
@ -545,10 +556,36 @@ def _is_latest(js_option, request):
|
||||
"""
|
||||
if request is None:
|
||||
return js_option == 'latest'
|
||||
latest_in_query = 'latest' in request.query or (
|
||||
request.headers.get('Referer') and
|
||||
'latest' in urlparse(request.headers['Referer']).query)
|
||||
es5_in_query = 'es5' in request.query or (
|
||||
request.headers.get('Referer') and
|
||||
'es5' in urlparse(request.headers['Referer']).query)
|
||||
return latest_in_query or (not es5_in_query and js_option == 'latest')
|
||||
|
||||
# latest in query
|
||||
if 'latest' in request.query or (
|
||||
request.headers.get('Referer') and
|
||||
'latest' in urlparse(request.headers['Referer']).query):
|
||||
return True
|
||||
|
||||
# es5 in query
|
||||
if 'es5' in request.query or (
|
||||
request.headers.get('Referer') and
|
||||
'es5' in urlparse(request.headers['Referer']).query):
|
||||
return False
|
||||
|
||||
# non-auto option in config
|
||||
if js_option != 'auto':
|
||||
return js_option == 'latest'
|
||||
|
||||
from user_agents import parse
|
||||
useragent = parse(request.headers.get('User-Agent'))
|
||||
|
||||
# on iOS every browser is a Safari which we support from version 10.
|
||||
if useragent.os.family == 'iOS':
|
||||
return useragent.os.version[0] >= 10
|
||||
|
||||
family_min_version = {
|
||||
'Chrome': 50, # Probably can reduce this
|
||||
'Firefox': 41, # Destructuring added in 41
|
||||
'Opera': 40, # Probably can reduce this
|
||||
'Edge': 14, # Maybe can reduce this
|
||||
'Safari': 10, # many features not supported by 9
|
||||
}
|
||||
version = family_min_version.get(useragent.browser.family)
|
||||
return version and useragent.browser.version[0] >= version
|
||||
|
@ -1100,6 +1100,9 @@ uber_rides==0.6.0
|
||||
# homeassistant.components.sensor.ups
|
||||
upsmychoice==1.0.6
|
||||
|
||||
# homeassistant.components.frontend
|
||||
user-agents==1.1.0
|
||||
|
||||
# homeassistant.components.camera.uvc
|
||||
uvcclient==0.10.1
|
||||
|
||||
|
@ -7,7 +7,8 @@ import pytest
|
||||
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.components.frontend import (
|
||||
DOMAIN, CONF_THEMES, CONF_EXTRA_HTML_URL, DATA_PANELS)
|
||||
DOMAIN, CONF_JS_VERSION, CONF_THEMES, CONF_EXTRA_HTML_URL,
|
||||
CONF_EXTRA_HTML_URL_ES5, DATA_PANELS)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -36,7 +37,10 @@ def mock_http_client_with_urls(hass, test_client):
|
||||
"""Start the Hass HTTP component."""
|
||||
hass.loop.run_until_complete(async_setup_component(hass, 'frontend', {
|
||||
DOMAIN: {
|
||||
CONF_EXTRA_HTML_URL: ["https://domain.com/my_extra_url.html"]
|
||||
CONF_JS_VERSION: 'auto',
|
||||
CONF_EXTRA_HTML_URL: ["https://domain.com/my_extra_url.html"],
|
||||
CONF_EXTRA_HTML_URL_ES5:
|
||||
["https://domain.com/my_extra_url_es5.html"]
|
||||
}}))
|
||||
return hass.loop.run_until_complete(test_client(hass.http.app))
|
||||
|
||||
@ -163,12 +167,21 @@ def test_missing_themes(mock_http_client):
|
||||
@asyncio.coroutine
|
||||
def test_extra_urls(mock_http_client_with_urls):
|
||||
"""Test that extra urls are loaded."""
|
||||
resp = yield from mock_http_client_with_urls.get('/states')
|
||||
resp = yield from mock_http_client_with_urls.get('/states?latest')
|
||||
assert resp.status == 200
|
||||
text = yield from resp.text()
|
||||
assert text.find('href="https://domain.com/my_extra_url.html"') >= 0
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_extra_urls_es5(mock_http_client_with_urls):
|
||||
"""Test that es5 extra urls are loaded."""
|
||||
resp = yield from mock_http_client_with_urls.get('/states?es5')
|
||||
assert resp.status == 200
|
||||
text = yield from resp.text()
|
||||
assert text.find('href="https://domain.com/my_extra_url_es5.html"') >= 0
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_panel_without_path(hass):
|
||||
"""Test panel registration without file path."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user