aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2017-09-12 15:10:08 +0200
committerGitHub <noreply@github.com>2017-09-12 15:10:08 +0200
commit83508d7be3fb9b151c4b73152cf3719d38060d39 (patch)
treeadc85178cab74b9f5877f9566c3111415a3f72d6
parentff27308b88015126c1a8c892779d53a79e764d57 (diff)
parent81ef116bfb9e69f361ded5c6dd8a8ae472909fd6 (diff)
downloadnextcloud-server-83508d7be3fb9b151c4b73152cf3719d38060d39.tar.gz
nextcloud-server-83508d7be3fb9b151c4b73152cf3719d38060d39.zip
Merge pull request #6451 from nextcloud/theming-manifest-json
Theming app support for chrome manifest.json file
-rw-r--r--apps/theming/appinfo/routes.php6
-rw-r--r--apps/theming/lib/Controller/ThemingController.php35
-rw-r--r--apps/theming/lib/ThemingDefaults.php46
-rw-r--r--apps/theming/tests/Controller/ThemingControllerTest.php49
-rw-r--r--apps/theming/tests/ThemingDefaultsTest.php34
-rw-r--r--core/templates/layout.guest.php1
-rw-r--r--lib/private/Server.php3
-rw-r--r--lib/private/URLGenerator.php15
8 files changed, 176 insertions, 13 deletions
diff --git a/apps/theming/appinfo/routes.php b/apps/theming/appinfo/routes.php
index f4aa2f93162..530e13f53d4 100644
--- a/apps/theming/appinfo/routes.php
+++ b/apps/theming/appinfo/routes.php
@@ -61,6 +61,12 @@ return ['routes' => [
'verb' => 'GET',
],
[
+ 'name' => 'Theming#getManifest',
+ 'url' => '/manifest/{app}',
+ 'verb' => 'GET',
+ 'defaults' => array('app' => 'core')
+ ],
+ [
'name' => 'Icon#getFavicon',
'url' => '/favicon/{app}',
'verb' => 'GET',
diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php
index b409d309f4d..06c2c430b7f 100644
--- a/apps/theming/lib/Controller/ThemingController.php
+++ b/apps/theming/lib/Controller/ThemingController.php
@@ -423,4 +423,39 @@ class ThemingController extends Controller {
$response->cacheFor(3600);
return $response;
}
+
+ /**
+ * @NoCSRFRequired
+ * @PublicPage
+ *
+ * @return Http\JSONResponse
+ */
+ public function getManifest($app) {
+ $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
+ $responseJS = [
+ 'name' => $this->themingDefaults->getName(),
+ 'start_url' => $this->urlGenerator->getBaseUrl(),
+ 'icons' =>
+ [
+ [
+ 'src' => $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon',
+ ['app' => $app]) . '?v=' . $cacheBusterValue,
+ 'type'=> 'image/png',
+ 'sizes'=> '128x128'
+ ],
+ [
+ 'src' => $this->urlGenerator->linkToRoute('theming.Icon.getFavicon',
+ ['app' => $app]) . '?v=' . $cacheBusterValue,
+ 'type' => 'image/svg+xml',
+ 'sizes' => '16x16'
+ ]
+ ],
+ 'display' => 'standalone'
+ ];
+ $response = new Http\JSONResponse($responseJS);
+ $response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
+ $response->addHeader('Pragma', 'cache');
+ $response->cacheFor(3600);
+ return $response;
+ }
}
diff --git a/apps/theming/lib/ThemingDefaults.php b/apps/theming/lib/ThemingDefaults.php
index 8200957edc0..5dd22fb6326 100644
--- a/apps/theming/lib/ThemingDefaults.php
+++ b/apps/theming/lib/ThemingDefaults.php
@@ -23,6 +23,8 @@
namespace OCA\Theming;
+use OCP\App\AppPathNotFoundException;
+use OCP\App\IAppManager;
use OCP\Files\IAppData;
use OCP\ICacheFactory;
use OCP\IConfig;
@@ -41,6 +43,10 @@ class ThemingDefaults extends \OC_Defaults {
private $appData;
/** @var ICacheFactory */
private $cacheFactory;
+ /** @var Util */
+ private $util;
+ /** @var IAppManager */
+ private $appManager;
/** @var string */
private $name;
/** @var string */
@@ -49,8 +55,7 @@ class ThemingDefaults extends \OC_Defaults {
private $slogan;
/** @var string */
private $color;
- /** @var Util */
- private $util;
+
/** @var string */
private $iTunesAppId;
/** @var string */
@@ -68,13 +73,15 @@ class ThemingDefaults extends \OC_Defaults {
* @param IAppData $appData
* @param ICacheFactory $cacheFactory
* @param Util $util
+ * @param IAppManager $appManager
*/
public function __construct(IConfig $config,
IL10N $l,
IURLGenerator $urlGenerator,
IAppData $appData,
ICacheFactory $cacheFactory,
- Util $util
+ Util $util,
+ IAppManager $appManager
) {
parent::__construct();
$this->config = $config;
@@ -83,6 +90,7 @@ class ThemingDefaults extends \OC_Defaults {
$this->appData = $appData;
$this->cacheFactory = $cacheFactory;
$this->util = $util;
+ $this->appManager = $appManager;
$this->name = parent::getName();
$this->url = parent::getBaseUrl();
@@ -249,6 +257,38 @@ class ThemingDefaults extends \OC_Defaults {
}
/**
+ * Check if the image should be replaced by the theming app
+ * and return the new image location then
+ *
+ * @param string $app name of the app
+ * @param string $image filename of the image
+ * @return bool|string false if image should not replaced, otherwise the location of the image
+ */
+ public function replaceImagePath($app, $image) {
+ if($app==='') {
+ $app = 'core';
+ }
+ $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
+
+ if ($image === 'favicon.ico' && $this->shouldReplaceIcons()) {
+ return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
+ }
+ if ($image === 'favicon-touch.png' && $this->shouldReplaceIcons()) {
+ return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
+ }
+ if ($image === 'manifest.json') {
+ try {
+ $appPath = $this->appManager->getAppPath($app);
+ if (file_exists($appPath . '/img/manifest.json')) {
+ return false;
+ }
+ } catch (AppPathNotFoundException $e) {}
+ return $this->urlGenerator->linkToRoute('theming.Theming.getManifest') . '?v=' . $cacheBusterValue;
+ }
+ return false;
+ }
+
+ /**
* Check if Imagemagick is enabled and if SVG is supported
* otherwise we can't render custom icons
*
diff --git a/apps/theming/tests/Controller/ThemingControllerTest.php b/apps/theming/tests/Controller/ThemingControllerTest.php
index 5e6e43ca3cb..c03eccb6eef 100644
--- a/apps/theming/tests/Controller/ThemingControllerTest.php
+++ b/apps/theming/tests/Controller/ThemingControllerTest.php
@@ -729,4 +729,53 @@ class ThemingControllerTest extends TestCase {
$expected->cacheFor(3600);
@$this->assertEquals($expected, $this->themingController->getJavascript());
}
+
+ public function testGetManifest() {
+ $this->config
+ ->expects($this->once())
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('0');
+ $this->themingDefaults
+ ->expects($this->any())
+ ->method('getName')
+ ->willReturn('Nextcloud');
+ $this->urlGenerator
+ ->expects($this->at(0))
+ ->method('getBaseUrl')
+ ->willReturn('localhost');
+ $this->urlGenerator
+ ->expects($this->at(1))
+ ->method('linkToRoute')
+ ->with('theming.Icon.getTouchIcon', ['app' => 'core'])
+ ->willReturn('touchicon');
+ $this->urlGenerator
+ ->expects($this->at(2))
+ ->method('linkToRoute')
+ ->with('theming.Icon.getFavicon', ['app' => 'core'])
+ ->willReturn('favicon');
+ $response = new Http\JSONResponse([
+ 'name' => 'Nextcloud',
+ 'start_url' => 'localhost',
+ 'icons' =>
+ [
+ [
+ 'src' => 'touchicon?v=0',
+ 'type'=> 'image/png',
+ 'sizes'=> '128x128'
+ ],
+ [
+ 'src' => 'favicon?v=0',
+ 'type' => 'image/svg+xml',
+ 'sizes' => '16x16'
+ ]
+ ],
+ 'display' => 'standalone'
+ ]);
+ $response->addHeader('Expires', date(\DateTime::RFC2822, $this->timeFactory->getTime()));
+ $response->addHeader('Pragma', 'cache');
+ $response->cacheFor(3600);
+ $this->assertEquals($response, $this->themingController->getManifest('core'));
+ }
+
}
diff --git a/apps/theming/tests/ThemingDefaultsTest.php b/apps/theming/tests/ThemingDefaultsTest.php
index c6d1fec91dd..abd85a612c9 100644
--- a/apps/theming/tests/ThemingDefaultsTest.php
+++ b/apps/theming/tests/ThemingDefaultsTest.php
@@ -24,6 +24,7 @@
namespace OCA\Theming\Tests;
use OCA\Theming\ThemingDefaults;
+use OCP\App\IAppManager;
use OCP\Files\IAppData;
use OCA\Theming\Util;
use OCP\Files\NotFoundException;
@@ -55,6 +56,8 @@ class ThemingDefaultsTest extends TestCase {
private $util;
/** @var ICache|\PHPUnit_Framework_MockObject_MockObject */
private $cache;
+ /** @var IAppManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $appManager;
public function setUp() {
parent::setUp();
@@ -65,6 +68,7 @@ class ThemingDefaultsTest extends TestCase {
$this->cacheFactory = $this->createMock(ICacheFactory::class);
$this->cache = $this->createMock(ICache::class);
$this->util = $this->createMock(Util::class);
+ $this->appManager = $this->createMock(IAppManager::class);
$this->defaults = new \OC_Defaults();
$this->cacheFactory
->expects($this->any())
@@ -77,7 +81,8 @@ class ThemingDefaultsTest extends TestCase {
$this->urlGenerator,
$this->appData,
$this->cacheFactory,
- $this->util
+ $this->util,
+ $this->appManager
);
}
@@ -607,4 +612,31 @@ class ThemingDefaultsTest extends TestCase {
$this->assertEquals('1234567890', $this->template->getiTunesAppId());
}
+ public function dataReplaceImagePath() {
+ return [
+ ['core', 'test.png', false],
+ ['core', 'manifest.json'],
+ ['core', 'favicon.ico'],
+ ['core', 'favicon-touch.png']
+ ];
+ }
+
+ /** @dataProvider dataReplaceImagePath */
+ public function testReplaceImagePath($app, $image, $result = 'themingRoute?v=0') {
+ $this->cache->expects($this->any())
+ ->method('get')
+ ->with('shouldReplaceIcons')
+ ->willReturn(true);
+ $this->config
+ ->expects($this->any())
+ ->method('getAppValue')
+ ->with('theming', 'cachebuster', '0')
+ ->willReturn('0');
+ $this->urlGenerator
+ ->expects($this->any())
+ ->method('linkToRoute')
+ ->willReturn('themingRoute');
+ $this->assertEquals($result, $this->template->replaceImagePath($app, $image));
+ }
+
}
diff --git a/core/templates/layout.guest.php b/core/templates/layout.guest.php
index 9a4f9c37198..ce0eccb971d 100644
--- a/core/templates/layout.guest.php
+++ b/core/templates/layout.guest.php
@@ -13,6 +13,7 @@
<link rel="icon" href="<?php print_unescaped(image_path('', 'favicon.ico')); /* IE11+ supports png */ ?>">
<link rel="apple-touch-icon-precomposed" href="<?php print_unescaped(image_path('', 'favicon-touch.png')); ?>">
<link rel="mask-icon" sizes="any" href="<?php print_unescaped(image_path('', 'favicon-mask.svg')); ?>" color="<?php p($theme->getColorPrimary()); ?>">
+ <link rel="manifest" href="<?php print_unescaped(image_path('', 'manifest.json')); ?>">
<?php emit_css_loading_tags($_); ?>
<?php emit_script_loading_tags($_); ?>
<?php print_unescaped($_['headers']); ?>
diff --git a/lib/private/Server.php b/lib/private/Server.php
index fb0aa76cd17..a20d9ccfc01 100644
--- a/lib/private/Server.php
+++ b/lib/private/Server.php
@@ -892,7 +892,8 @@ class Server extends ServerContainer implements IServerContainer {
$c->getURLGenerator(),
$c->getAppDataDir('theming'),
$c->getMemCacheFactory(),
- new Util($c->getConfig(), $this->getAppManager(), $this->getAppDataDir('theming'))
+ new Util($c->getConfig(), $this->getAppManager(), $this->getAppDataDir('theming')),
+ $this->getAppManager()
);
}
return new \OC_Defaults();
diff --git a/lib/private/URLGenerator.php b/lib/private/URLGenerator.php
index 9c73ba4cbc7..ee75f8b21bb 100644
--- a/lib/private/URLGenerator.php
+++ b/lib/private/URLGenerator.php
@@ -166,6 +166,11 @@ class URLGenerator implements IURLGenerator {
// Check if the app is in the app folder
$path = '';
$themingEnabled = $this->config->getSystemValue('installed', false) && \OCP\App::isEnabled('theming') && \OC_App::isAppLoaded('theming');
+ $themingImagePath = false;
+ if($themingEnabled) {
+ $themingImagePath = \OC::$server->getThemingDefaults()->replaceImagePath($app, $image);
+ }
+
if (file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$image")) {
$path = \OC::$WEBROOT . "/themes/$theme/apps/$app/img/$image";
} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/apps/$app/img/$basename.svg")
@@ -181,14 +186,8 @@ class URLGenerator implements IURLGenerator {
} elseif (!file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.svg")
&& file_exists(\OC::$SERVERROOT . "/themes/$theme/core/img/$basename.png")) {
$path = \OC::$WEBROOT . "/themes/$theme/core/img/$basename.png";
- } elseif($themingEnabled && $image === "favicon.ico" && \OC::$server->getThemingDefaults()->shouldReplaceIcons()) {
- $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
- if($app==="") { $app = "core"; }
- $path = $this->linkToRoute('theming.Icon.getFavicon', [ 'app' => $app ]) . '?v='. $cacheBusterValue;
- } elseif($themingEnabled && $image === "favicon-touch.png" && \OC::$server->getThemingDefaults()->shouldReplaceIcons()) {
- $cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
- if($app==="") { $app = "core"; }
- $path = $this->linkToRoute('theming.Icon.getTouchIcon', [ 'app' => $app ]) . '?v='. $cacheBusterValue;
+ } elseif($themingEnabled && $themingImagePath) {
+ $path = $themingImagePath;
} elseif ($appPath && file_exists($appPath . "/img/$image")) {
$path = \OC_App::getAppWebPath($app) . "/img/$image";
} elseif ($appPath && !file_exists($appPath . "/img/$basename.svg")