Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,12 +111,6 @@ src/kolibri: clean
patch -d src/ -p1 < patches/0001-Add-track-progress-information-to-channelimport.patch
patch -d src/ -p1 < patches/0001-Break-up-DynamicWhiteNoise-code.patch

src/evil_kolibri: src/kolibri
mkdir -p src/evil_kolibri/utils
touch src/evil_kolibri/__init__.py
touch src/evil_kolibri/utils/__init__.py
cp src/kolibri/utils/kolibri_whitenoise.py src/evil_kolibri/utils/kolibri_whitenoise.py

.PHONY: apps-bundle.zip
apps-bundle.zip:
wget -N https://github.com/endlessm/kolibri-explore-plugin/releases/latest/download/apps-bundle.zip
Expand Down Expand Up @@ -164,7 +158,6 @@ dist/version.json: needs-version
DIST_DEPS = \
p4a_android_distro \
src/kolibri \
src/evil_kolibri \
src/apps-bundle \
src/collections \
assets/welcomeScreen \
Expand Down
11 changes: 4 additions & 7 deletions src/kolibri_android/android_whitenoise.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
from urllib.parse import urlparse

from django.utils.functional import cached_property
from evil_kolibri.utils.kolibri_whitenoise import compressed_file_extensions
from evil_kolibri.utils.kolibri_whitenoise import DynamicWhiteNoise
from evil_kolibri.utils.kolibri_whitenoise import EndRangeStaticFile
from evil_kolibri.utils.kolibri_whitenoise import FileFinder
from jnius import autoclass
from kolibri.utils.kolibri_whitenoise import compressed_file_extensions
from kolibri.utils.kolibri_whitenoise import DynamicWhiteNoise
from kolibri.utils.kolibri_whitenoise import EndRangeStaticFile
from kolibri.utils.kolibri_whitenoise import FileFinder
from whitenoise.httpstatus_backport import HTTPStatus
from whitenoise.responders import NOT_ALLOWED_RESPONSE
from whitenoise.responders import Response
Expand All @@ -18,9 +18,6 @@
from .android_utils import open_file
from .android_utils import stat_file

# We import from evil_kolibri so we can monkey-patch DynamicWhiteNoise from
# kolibri without creating a circular dependency.

logger = logging.getLogger(__name__)

Uri = autoclass("android.net.Uri")
Expand Down
39 changes: 39 additions & 0 deletions src/kolibri_android/kolibri_extra/alt_wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""
WSGI config for the alternate origin server used for serving
sandboxed content
"""
import os

import kolibri.core.content
from kolibri.core.content.utils import paths
from kolibri.core.content.zip_wsgi import get_application
from kolibri_android.android_whitenoise import AndroidDynamicWhiteNoise

os.environ.setdefault(
"DJANGO_SETTINGS_MODULE", "kolibri.deployment.default.settings.base"
)


def generate_alt_wsgi_application():
alt_content_path = "/" + paths.get_content_url(
paths.zip_content_path_prefix()
).lstrip("/")

content_dirs = [paths.get_content_dir_path()] + paths.get_content_fallback_paths()

content_static_path = os.path.join(
os.path.dirname(kolibri.core.content.__file__), "static"
)

# Mount static files
return AndroidDynamicWhiteNoise(
get_application(),
dynamic_locations=[
(alt_content_path, content_dir) for content_dir in content_dirs
]
+ [(paths.zip_content_static_root(), content_static_path)],
app_paths=[paths.get_zip_content_base_path()],
)


alt_application = generate_alt_wsgi_application()
2 changes: 2 additions & 0 deletions src/kolibri_android/kolibri_extra/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
SESSION_COOKIE_AGE = 52560000

WSGI_APPLICATION = "kolibri_android.kolibri_extra.wsgi.application"


MIDDLEWARE = list(MIDDLEWARE) + [ # noqa F405
"kolibri_android.kolibri_extra.middleware.AlwaysAuthenticatedMiddleware"
Expand Down
63 changes: 63 additions & 0 deletions src/kolibri_android/kolibri_extra/wsgi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
WSGI config for Kolibri on Android.

This is copied from kolibri/deployment/default/wsgi.py in upstream Kolibri,
but with a small change to use our Android variant of DynamicWhiteNoise.
"""
import os
import time

from django.conf import settings
from django.core.wsgi import get_wsgi_application
from django.db.utils import OperationalError
from kolibri.core.content.utils import paths
from kolibri.utils import conf
from kolibri_android.android_whitenoise import AndroidDynamicWhiteNoise

os.environ.setdefault(
"DJANGO_SETTINGS_MODULE", "kolibri.deployment.default.settings.base"
)


def generate_wsgi_application():
django_application = get_wsgi_application()
base_content_path = "/" + paths.get_content_url(
conf.OPTIONS["Deployment"]["URL_PATH_PREFIX"]
).lstrip("/")
content_dirs = [paths.get_content_dir_path()] + paths.get_content_fallback_paths()

# Mount static files
return AndroidDynamicWhiteNoise(
django_application,
static_prefix=settings.STATIC_URL,
dynamic_locations=[
(base_content_path, content_dir) for content_dir in content_dirs
]
+ [(settings.MEDIA_URL, settings.MEDIA_ROOT)],
)


application = None
tries_remaining = 6
interval = 10
while not application and tries_remaining:
try:
application = generate_wsgi_application()
except OperationalError:
# An OperationalError happens when sqlite vacuum is being
# executed. the db is locked
print(
"Database assumed to be undergoing a VACUUM, retrying again in {} seconds...".format(
interval
)
)
tries_remaining -= 1
time.sleep(interval)

if not application:
print(
"Could not start Kolibri with {} retries. Trying one last time".format(
tries_remaining
)
)
application = generate_wsgi_application()
9 changes: 0 additions & 9 deletions src/kolibri_android/kolibri_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ def init_kolibri(**kwargs):
_update_kolibri_content_fallback_dirs()
_update_explore_plugin_options()

_monkeypatch_whitenoise()

for plugin_name in DISABLED_PLUGINS:
_kolibri_disable_plugin(plugin_name)

Expand Down Expand Up @@ -122,13 +120,6 @@ def _update_kolibri_content_fallback_dirs():
os.environ["KOLIBRI_CONTENT_FALLBACK_DIRS"] = content_fallback_dirs


def _monkeypatch_whitenoise():
from kolibri.utils import kolibri_whitenoise

logger.info("Applying DynamicWhiteNoise workarounds")
kolibri_whitenoise.DynamicWhiteNoise = AndroidDynamicWhiteNoise


def _kolibri_initialize(**kwargs):
from kolibri.utils.main import initialize

Expand Down
20 changes: 18 additions & 2 deletions src/kolibri_android/main_activity/kolibri_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ def __init__(self, *args, enable_zeroconf=True, **kwargs):
if enable_zeroconf:
ZeroConfPlugin(self, self.port).subscribe()

KolibriServerPlugin(self, self.port).subscribe()
AndroidKolibriServerPlugin(self, self.port).subscribe()

ZipContentServerPlugin(self, self.zip_port).subscribe()
AndroidZipContentServerPlugin(self, self.zip_port).subscribe()

def get_app_key(self):
return DeviceAppKey.get_app_key()
Expand Down Expand Up @@ -71,3 +71,19 @@ def SERVING(self, port):
next_url = self.application.get_saved_kolibri_path() or ""
start_url = urljoin(base_url, next_url)
self.application.replace_url(start_url)


class AndroidKolibriServerPlugin(KolibriServerPlugin):
@property
def application(self):
from kolibri_android.kolibri_extra.wsgi import application

return application


class AndroidZipContentServerPlugin(ZipContentServerPlugin):
@property
def application(self):
from kolibri_android.kolibri_extra.alt_wsgi import alt_application

return alt_application