Skip to content

Commit

Permalink
Initial PWA implementation for ChromeOS (#2613)
Browse files Browse the repository at this point in the history
* XMDS: file downloads should output content type
* XMDS - CSP: Add response headers and fix param for soap endpoint
* Display Settings: add chromeOS
* ChromeOS: uploading .chrome file, unpacking into the library, serving via PWA.

relates to xibosignageltd/xibo-private#772
---------

Co-authored-by: Ruben Pingol <ruben.pingol@xibosignage.com>
  • Loading branch information
dasgarner and rubenberttpingol authored Oct 8, 2024
1 parent 258160e commit 8e07966
Show file tree
Hide file tree
Showing 28 changed files with 1,256 additions and 132 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build-container.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
- release23
- release33
- release40
- feature/kopff_chromeos

jobs:
build:
Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"ext-pdo": "1",
"ext-json": "1",
"ext-soap": "1",
"ext-zip": "1"
"ext-zip": "1",
"ext-fileinfo": "*"
}
},
"minimum-stability": "dev",
Expand All @@ -48,6 +49,7 @@
"ext-soap": "*",
"ext-zip": "*",
"ext-openssl": "*",
"ext-fileinfo": "*",
"slim/slim": "^4.3",
"slim/http": "^1.2",
"slim/flash": "^0.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
/*
* Copyright (C) 2024 Xibo Signage Ltd
*
* Xibo - Digital Signage - https://xibosignage.com
*
* This file is part of Xibo.
*
* Xibo is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Xibo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Xibo. If not, see <http://www.gnu.org/licenses/>.
*/

use Phinx\Migration\AbstractMigration;

/**
* @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
*/
class AddDefaultChromeOSDisplayProfileMigration extends AbstractMigration
{
public function change(): void
{
// add default display profile for tizen
if (!$this->fetchRow('SELECT * FROM displayprofile WHERE type = \'chromeOS\' AND isDefault = 1')) {
// Get system user
$user = $this->fetchRow('SELECT userId FROM `user` WHERE userTypeId = 1');

$this->table('displayprofile')->insert([
'name' => 'ChromeOS',
'type' => 'chromeOS',
'config' => '[]',
'userId' => $user['userId'],
'isDefault' => 1
])->save();
}
}
}
9 changes: 9 additions & 0 deletions docker/etc/apache2/sites-available/000-default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ ServerTokens OS
Require all granted
</Directory>

Alias /chromeos /var/www/cms/library/playersoftware/chromeos/latest
<Directory /var/www/cms/library/playersoftware/chromeos/latest>
php_admin_value engine Off
DirectoryIndex index.html
Options -Indexes -FollowSymLinks -MultiViews
AllowOverride None
Require all granted
</Directory>

ErrorLog /dev/stderr

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" *%Ts* *%Dus*" requesttime
Expand Down
2 changes: 1 addition & 1 deletion lib/Controller/Display.php
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ public function grid(Request $request, Response $response)
];
}

if (in_array($display->clientType, ['android', 'lg', 'sssp'])) {
if (in_array($display->clientType, ['android', 'lg', 'sssp', 'chromeOS'])) {
$display->buttons[] = array(
'id' => 'display_button_checkLicence',
'url' => $this->urlFor($request, 'display.licencecheck.form', ['id' => $display->displayId]),
Expand Down
30 changes: 26 additions & 4 deletions lib/Controller/DisplayProfile.php
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,10 @@ public function editForm(Request $request, Response $response, $id)
}

// Player Version Setting
$versionId = $displayProfile->getSetting('versionMediaId');
$versionId = $displayProfile->type === 'chromeOS'
? $displayProfile->getSetting('playerVersionId')
: $displayProfile->getSetting('versionMediaId');

$playerVersions = [];

// Daypart - Operating Hours
Expand All @@ -358,8 +361,9 @@ public function editForm(Request $request, Response $response, $id)
if ($versionId !== null) {
try {
$playerVersions[] = $this->playerVersionFactory->getById($versionId);
} catch (NotFoundException $e) {
$this->getLog()->debug('Unknown versionId set on Display Profile. ' . $displayProfile->displayProfileId);
} catch (NotFoundException) {
$this->getLog()->debug('Unknown versionId set on Display Profile. '
. $displayProfile->displayProfileId);
}
}

Expand Down Expand Up @@ -456,12 +460,14 @@ public function edit(Request $request, Response $response, $id)
$displayProfile->name = $parsedParams->getString('name');
$displayProfile->isDefault = $parsedParams->getCheckbox('isDefault');

// Track changes to versionMediaId
$originalPlayerVersionId = $displayProfile->getSetting('playerVersionId');

// Different fields for each client type
$this->editConfigFields($displayProfile, $parsedParams);

// Capture and update commands
foreach ($this->commandFactory->query() as $command) {
/* @var \Xibo\Entity\Command $command */
if ($parsedParams->getString('commandString_' . $command->commandId) != null) {
// Set and assign the command
$command->commandString = $parsedParams->getString('commandString_' . $command->commandId);
Expand All @@ -474,6 +480,22 @@ public function edit(Request $request, Response $response, $id)
}
}

// If we are chromeOS and the default profile, has the player version changed?
if ($displayProfile->type === 'chromeOS'
&& ($displayProfile->isDefault || $displayProfile->hasPropertyChanged('isDefault'))
&& ($originalPlayerVersionId !== $displayProfile->getSetting('playerVersionId'))
) {
$this->getLog()->debug('edit: updating symlink to the latest chromeOS version');

// Update a symlink to the new player version.
try {
$version = $this->playerVersionFactory->getById($displayProfile->getSetting('playerVersionId'));
$version->setActive();
} catch (NotFoundException) {
$this->getLog()->error('edit: Player version does not exist');
}
}

// Save the changes
$displayProfile->save();

Expand Down
65 changes: 65 additions & 0 deletions lib/Controller/DisplayProfileConfigFields.php
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,71 @@ public function editConfigFields($displayProfile, $sanitizedParams, $config = nu

break;

case 'chromeOS':
if ($sanitizedParams->hasParam('licenceCode')) {
$this->handleChangedSettings('licenceCode', ($ownConfig) ? $displayProfile->getSetting('licenceCode') : $display->getSetting('licenceCode'), $sanitizedParams->getString('licenceCode'), $changedSettings);
$displayProfile->setSetting('licenceCode', $sanitizedParams->getString('licenceCode'), $ownConfig, $config);
}

if ($sanitizedParams->hasParam('collectInterval')) {
$this->handleChangedSettings('collectInterval', ($ownConfig) ? $displayProfile->getSetting('collectInterval') : $display->getSetting('collectInterval'), $sanitizedParams->getInt('collectInterval'), $changedSettings);
$displayProfile->setSetting('collectInterval', $sanitizedParams->getInt('collectInterval'), $ownConfig, $config);
}

if ($sanitizedParams->hasParam('dayPartId')) {
$this->handleChangedSettings('dayPartId', ($ownConfig) ? $displayProfile->getSetting('dayPartId') : $display->getSetting('dayPartId'), $sanitizedParams->getInt('dayPartId'), $changedSettings);
$displayProfile->setSetting('dayPartId', $sanitizedParams->getInt('dayPartId'), $ownConfig, $config);
}

if ($sanitizedParams->hasParam('xmrNetworkAddress')) {
$this->handleChangedSettings('xmrNetworkAddress',($ownConfig) ? $displayProfile->getSetting('xmrNetworkAddress') : $display->getSetting('xmrNetworkAddress'), $sanitizedParams->getString('xmrNetworkAddress'), $changedSettings);
$displayProfile->setSetting('xmrNetworkAddress', $sanitizedParams->getString('xmrNetworkAddress'), $ownConfig, $config);
}

if ($sanitizedParams->hasParam('statsEnabled')) {
$this->handleChangedSettings('statsEnabled', ($ownConfig) ? $displayProfile->getSetting('statsEnabled') : $display->getSetting('statsEnabled'), $sanitizedParams->getCheckbox('statsEnabled'), $changedSettings);
$displayProfile->setSetting('statsEnabled', $sanitizedParams->getCheckbox('statsEnabled'), $ownConfig, $config);
}

if ($sanitizedParams->hasParam('aggregationLevel')) {
$this->handleChangedSettings('aggregationLevel', ($ownConfig) ? $displayProfile->getSetting('aggregationLevel') : $display->getSetting('aggregationLevel'), $sanitizedParams->getString('aggregationLevel'), $changedSettings);
$displayProfile->setSetting('aggregationLevel', $sanitizedParams->getString('aggregationLevel'), $ownConfig, $config);
}

if ($sanitizedParams->hasParam('logLevel')) {
$this->handleChangedSettings('logLevel', ($ownConfig) ? $displayProfile->getSetting('logLevel') : $display->getSetting('logLevel'), $sanitizedParams->getString('logLevel'), $changedSettings);
$displayProfile->setSetting('logLevel', $sanitizedParams->getString('logLevel'), $ownConfig, $config);
}

if ($sanitizedParams->hasParam('elevateLogsUntil')) {
$this->handleChangedSettings(
'elevateLogsUntil',
($ownConfig)
? $displayProfile->getSetting('elevateLogsUntil')
: $display->getSetting('elevateLogsUntil'),
$sanitizedParams->getDate('elevateLogsUntil')?->format('U'),
$changedSettings
);
$displayProfile->setSetting(
'elevateLogsUntil',
$sanitizedParams->getDate('elevateLogsUntil')?->format('U'),
$ownConfig,
$config
);
}

if ($sanitizedParams->hasParam('playerVersionId')) {
$this->handleChangedSettings('playerVersionId', ($ownConfig) ? $displayProfile->getSetting('playerVersionId') : $display->getSetting('playerVersionId'), $sanitizedParams->getInt('playerVersionId'), $changedSettings);
$displayProfile->setSetting('playerVersionId', $sanitizedParams->getInt('playerVersionId'), $ownConfig, $config);
}

if ($sanitizedParams->hasParam('screenShotSize')) {
$this->handleChangedSettings('screenShotSize', ($ownConfig) ? $displayProfile->getSetting('screenShotSize') : $display->getSetting('screenShotSize'), $sanitizedParams->getInt('screenShotSize'), $changedSettings);
$displayProfile->setSetting('screenShotSize', $sanitizedParams->getInt('screenShotSize'), $ownConfig, $config);
}

break;

default:
if ($displayProfile->isCustom()) {
$this->getLog()->info('Edit for custom Display profile type ' . $displayProfile->getClientType());
Expand Down
14 changes: 12 additions & 2 deletions lib/Controller/PlayerSoftware.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,14 +258,21 @@ public function delete(Request $request, Response $response, $id)
// Unset player version from Display Profile
$displayProfiles = $this->displayProfileFactory->query();

foreach($displayProfiles as $displayProfile) {
foreach ($displayProfiles as $displayProfile) {
if (in_array($displayProfile->type, ['android', 'lg', 'sssp'])) {
$currentVersionId = $displayProfile->getSetting('versionMediaId');

if ($currentVersionId === $version->versionId) {
$displayProfile->setSetting('versionMediaId', null);
$displayProfile->save();
}
} else if ($displayProfile->type === 'chromeOS') {
$currentVersionId = $displayProfile->getSetting('playerVersionId');

if ($currentVersionId === $version->versionId) {
$displayProfile->setSetting('playerVersionId', null);
$displayProfile->save();
}
}
}

Expand Down Expand Up @@ -630,6 +637,9 @@ public function add(Request $request, Response $response)
// everything is fine, move the file from temp folder.
rename($filePath, $libraryFolder . 'playersoftware/' . $playerSoftware->fileName);

// Unpack if necessary
$playerSoftware->unpack($libraryFolder);

// return
$file->id = $playerSoftware->versionId;
$file->md5 = $playerSoftware->md5;
Expand Down Expand Up @@ -737,6 +747,6 @@ private function outputSsspXml($version, $size)
*/
private function getValidExtensions()
{
return ['apk','ipk','wgt'];
return ['apk', 'ipk', 'wgt', 'chrome'];
}
}
Loading

0 comments on commit 8e07966

Please sign in to comment.