Page MenuHomePhabricator

D19209.diff
No OneTemporary

D19209.diff

diff --git a/webroot/rsrc/favicons/apple-touch-icon-120x120.png b/resources/builtin/favicon/default-120x120.png
rename from webroot/rsrc/favicons/apple-touch-icon-120x120.png
rename to resources/builtin/favicon/default-120x120.png
diff --git a/webroot/rsrc/favicons/favicon-128.png b/resources/builtin/favicon/default-128x128.png
rename from webroot/rsrc/favicons/favicon-128.png
rename to resources/builtin/favicon/default-128x128.png
diff --git a/webroot/rsrc/favicons/apple-touch-icon-152x152.png b/resources/builtin/favicon/default-152x152.png
rename from webroot/rsrc/favicons/apple-touch-icon-152x152.png
rename to resources/builtin/favicon/default-152x152.png
diff --git a/webroot/rsrc/favicons/apple-touch-icon-76x76.png b/resources/builtin/favicon/default-76x76.png
rename from webroot/rsrc/favicons/apple-touch-icon-76x76.png
rename to resources/builtin/favicon/default-76x76.png
diff --git a/resources/builtin/favicon/dot-pink-64x64.png b/resources/builtin/favicon/dot-pink-64x64.png
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/resources/builtin/favicon/dot-red-64x64.png b/resources/builtin/favicon/dot-red-64x64.png
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -16,7 +16,6 @@
'differential.pkg.js' => 'f6d809c0',
'diffusion.pkg.css' => 'a2d17c7d',
'diffusion.pkg.js' => '6134c5a1',
- 'favicon.ico' => '30672e08',
'maniphest.pkg.css' => '4845691a',
'maniphest.pkg.js' => '4d7e79c8',
'rsrc/audio/basic/alert.mp3' => '98461568',
@@ -270,28 +269,8 @@
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '54f314a0',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => 'ab9e0a82',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '6c0e62fa',
- 'rsrc/favicons/apple-touch-icon-114x114.png' => '12a24178',
- 'rsrc/favicons/apple-touch-icon-120x120.png' => '0d1543c7',
- 'rsrc/favicons/apple-touch-icon-144x144.png' => '8043b5a5',
- 'rsrc/favicons/apple-touch-icon-152x152.png' => '65905ecd',
- 'rsrc/favicons/apple-touch-icon-57x57.png' => '2bfc7b0a',
- 'rsrc/favicons/apple-touch-icon-60x60.png' => '8ff52925',
- 'rsrc/favicons/apple-touch-icon-72x72.png' => 'a2bb65d6',
- 'rsrc/favicons/apple-touch-icon-76x76.png' => '2d061a11',
- 'rsrc/favicons/favicon-128.png' => '72f7e812',
'rsrc/favicons/favicon-16x16.png' => 'fc6275ba',
- 'rsrc/favicons/favicon-196x196.png' => '95db275e',
- 'rsrc/favicons/favicon-32x32.png' => '5bd18b6c',
- 'rsrc/favicons/favicon-96x96.png' => '7242c8e9',
- 'rsrc/favicons/favicon-mention.ico' => '1fdd0fa4',
- 'rsrc/favicons/favicon-message.ico' => '115bc010',
- 'rsrc/favicons/favicon.ico' => 'cdb11121',
'rsrc/favicons/mask-icon.svg' => 'e132a80f',
- 'rsrc/favicons/mstile-144x144.png' => '310c2ee5',
- 'rsrc/favicons/mstile-150x150.png' => '74bf5133',
- 'rsrc/favicons/mstile-310x150.png' => '4a49d3ee',
- 'rsrc/favicons/mstile-310x310.png' => 'a52ab264',
- 'rsrc/favicons/mstile-70x70.png' => '5edce7b8',
'rsrc/image/BFCFDA.png' => 'd5ec91f4',
'rsrc/image/actions/edit.png' => '2fc41442',
'rsrc/image/avatar.png' => '17d346a4',
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2953,6 +2953,8 @@
'PhabricatorFactObjectDimension' => 'applications/fact/storage/PhabricatorFactObjectDimension.php',
'PhabricatorFactRaw' => 'applications/fact/storage/PhabricatorFactRaw.php',
'PhabricatorFactUpdateIterator' => 'applications/fact/extract/PhabricatorFactUpdateIterator.php',
+ 'PhabricatorFaviconRef' => 'applications/files/favicon/PhabricatorFaviconRef.php',
+ 'PhabricatorFaviconRefQuery' => 'applications/files/favicon/PhabricatorFaviconRefQuery.php',
'PhabricatorFavoritesApplication' => 'applications/favorites/application/PhabricatorFavoritesApplication.php',
'PhabricatorFavoritesController' => 'applications/favorites/controller/PhabricatorFavoritesController.php',
'PhabricatorFavoritesMainMenuBarExtension' => 'applications/favorites/engineextension/PhabricatorFavoritesMainMenuBarExtension.php',
@@ -4331,7 +4333,6 @@
'PhabricatorSystemDAO' => 'applications/system/storage/PhabricatorSystemDAO.php',
'PhabricatorSystemDestructionGarbageCollector' => 'applications/system/garbagecollector/PhabricatorSystemDestructionGarbageCollector.php',
'PhabricatorSystemDestructionLog' => 'applications/system/storage/PhabricatorSystemDestructionLog.php',
- 'PhabricatorSystemFaviconController' => 'applications/system/controller/PhabricatorSystemFaviconController.php',
'PhabricatorSystemReadOnlyController' => 'applications/system/controller/PhabricatorSystemReadOnlyController.php',
'PhabricatorSystemRemoveDestroyWorkflow' => 'applications/system/management/PhabricatorSystemRemoveDestroyWorkflow.php',
'PhabricatorSystemRemoveLogWorkflow' => 'applications/system/management/PhabricatorSystemRemoveLogWorkflow.php',
@@ -8512,6 +8513,8 @@
'PhabricatorFactObjectDimension' => 'PhabricatorFactDimension',
'PhabricatorFactRaw' => 'PhabricatorFactDAO',
'PhabricatorFactUpdateIterator' => 'PhutilBufferedIterator',
+ 'PhabricatorFaviconRef' => 'Phobject',
+ 'PhabricatorFaviconRefQuery' => 'Phobject',
'PhabricatorFavoritesApplication' => 'PhabricatorApplication',
'PhabricatorFavoritesController' => 'PhabricatorController',
'PhabricatorFavoritesMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension',
@@ -10142,7 +10145,6 @@
'PhabricatorSystemDAO' => 'PhabricatorLiskDAO',
'PhabricatorSystemDestructionGarbageCollector' => 'PhabricatorGarbageCollector',
'PhabricatorSystemDestructionLog' => 'PhabricatorSystemDAO',
- 'PhabricatorSystemFaviconController' => 'PhabricatorController',
'PhabricatorSystemReadOnlyController' => 'PhabricatorController',
'PhabricatorSystemRemoveDestroyWorkflow' => 'PhabricatorSystemRemoveWorkflow',
'PhabricatorSystemRemoveLogWorkflow' => 'PhabricatorSystemRemoveWorkflow',
diff --git a/src/applications/config/option/PhabricatorUIConfigOptions.php b/src/applications/config/option/PhabricatorUIConfigOptions.php
--- a/src/applications/config/option/PhabricatorUIConfigOptions.php
+++ b/src/applications/config/option/PhabricatorUIConfigOptions.php
@@ -64,6 +64,10 @@
"Phabricator logo in the site header.\n\n".
" - **Wordmark**: Choose new text to display next to the logo. ".
"By default, the header displays //Phabricator//.\n\n")),
+ $this->newOption('ui.favicons', 'wild', array())
+ ->setSummary(pht('Customize favicons.'))
+ ->setDescription(pht('Customize favicons.'))
+ ->setLocked(true),
$this->newOption('ui.footer-items', $footer_type, array())
->setSummary(
pht(
diff --git a/src/applications/files/favicon/PhabricatorFaviconRef.php b/src/applications/files/favicon/PhabricatorFaviconRef.php
new file mode 100644
--- /dev/null
+++ b/src/applications/files/favicon/PhabricatorFaviconRef.php
@@ -0,0 +1,447 @@
+<?php
+
+final class PhabricatorFaviconRef extends Phobject {
+
+ private $viewer;
+ private $width;
+ private $height;
+ private $emblems;
+ private $uri;
+ private $cacheKey;
+
+ public function __construct() {
+ $this->emblems = array(null, null, null, null);
+ }
+
+ public function setViewer(PhabricatorUser $viewer) {
+ $this->viewer = $viewer;
+ return $this;
+ }
+
+ public function getViewer() {
+ return $this->viewer;
+ }
+
+ public function setWidth($width) {
+ $this->width = $width;
+ return $this;
+ }
+
+ public function getWidth() {
+ return $this->width;
+ }
+
+ public function setHeight($height) {
+ $this->height = $height;
+ return $this;
+ }
+
+ public function getHeight() {
+ return $this->height;
+ }
+
+ public function setEmblems(array $emblems) {
+ if (count($emblems) !== 4) {
+ throw new Exception(
+ pht(
+ 'Expected four elements in icon emblem list. To omit an emblem, '.
+ 'pass "null".'));
+ }
+
+ $this->emblems = $emblems;
+ return $this;
+ }
+
+ public function getEmblems() {
+ return $this->emblems;
+ }
+
+ public function setURI($uri) {
+ $this->uri = $uri;
+ return $this;
+ }
+
+ public function getURI() {
+ return $this->uri;
+ }
+
+ public function setCacheKey($cache_key) {
+ $this->cacheKey = $cache_key;
+ return $this;
+ }
+
+ public function getCacheKey() {
+ return $this->cacheKey;
+ }
+
+ public function newDigest() {
+ return PhabricatorHash::digestForIndex(serialize($this->toDictionary()));
+ }
+
+ public function toDictionary() {
+ return array(
+ 'width' => $this->width,
+ 'height' => $this->height,
+ 'emblems' => $this->emblems,
+ );
+ }
+
+ public static function newConfigurationDigest() {
+ $all_resources = self::getAllResources();
+
+ // Because we need to access this cache on every page, it's very sticky.
+ // Try to dirty it automatically if any relevant configuration changes.
+ $inputs = array(
+ 'resources' => $all_resources,
+ 'prod' => PhabricatorEnv::getProductionURI('/'),
+ 'cdn' => PhabricatorEnv::getEnvConfig('security.alternate-file-domain'),
+ 'havepng' => function_exists('imagepng'),
+ );
+
+ return PhabricatorHash::digestForIndex(serialize($inputs));
+ }
+
+ private static function getAllResources() {
+ $custom_resources = PhabricatorEnv::getEnvConfig('ui.favicons');
+
+ foreach ($custom_resources as $key => $custom_resource) {
+ $custom_resources[$key] = array(
+ 'source-type' => 'file',
+ 'default' => false,
+ ) + $custom_resource;
+ }
+
+ $builtin_resources = self::getBuiltinResources();
+
+ return array_merge($builtin_resources, $custom_resources);
+ }
+
+ private static function getBuiltinResources() {
+ return array(
+ array(
+ 'source-type' => 'builtin',
+ 'source' => 'favicon/default-76x76.png',
+ 'version' => 1,
+ 'width' => 76,
+ 'height' => 76,
+ 'default' => true,
+ ),
+ array(
+ 'source-type' => 'builtin',
+ 'source' => 'favicon/default-120x120.png',
+ 'version' => 1,
+ 'width' => 120,
+ 'height' => 120,
+ 'default' => true,
+ ),
+ array(
+ 'source-type' => 'builtin',
+ 'source' => 'favicon/default-128x128.png',
+ 'version' => 1,
+ 'width' => 128,
+ 'height' => 128,
+ 'default' => true,
+ ),
+ array(
+ 'source-type' => 'builtin',
+ 'source' => 'favicon/default-152x152.png',
+ 'version' => 1,
+ 'width' => 152,
+ 'height' => 152,
+ 'default' => true,
+ ),
+ array(
+ 'source-type' => 'builtin',
+ 'source' => 'favicon/dot-pink-64x64.png',
+ 'version' => 1,
+ 'width' => 64,
+ 'height' => 64,
+ 'emblem' => 'dot-pink',
+ 'default' => true,
+ ),
+ array(
+ 'source-type' => 'builtin',
+ 'source' => 'favicon/dot-red-64x64.png',
+ 'version' => 1,
+ 'width' => 64,
+ 'height' => 64,
+ 'emblem' => 'dot-red',
+ 'default' => true,
+ ),
+ );
+ }
+
+ public function newURI() {
+ $dst_w = $this->getWidth();
+ $dst_h = $this->getHeight();
+
+ $template = $this->newTemplateFile(null, $dst_w, $dst_h);
+ $template_file = $template['file'];
+
+ $cache = $this->loadCachedFile($template_file);
+ if ($cache) {
+ return $cache->getViewURI();
+ }
+
+ $data = $this->newCompositedFavicon($template);
+
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+
+ $caught = null;
+ try {
+ $favicon_file = $this->newFaviconFile($data);
+
+ $xform = id(new PhabricatorTransformedFile())
+ ->setOriginalPHID($template_file->getPHID())
+ ->setTransformedPHID($favicon_file->getPHID())
+ ->setTransform($this->getCacheKey());
+
+ try {
+ $xform->save();
+ } catch (AphrontDuplicateKeyQueryException $ex) {
+ unset($unguarded);
+
+ $cache = $this->loadCachedFile($template_file);
+ if (!$cache) {
+ throw $ex;
+ }
+
+ id(new PhabricatorDestructionEngine())
+ ->destroyObject($favicon_file);
+
+ return $cache->getViewURI();
+ }
+ } catch (Exception $ex) {
+ $caught = $ex;
+ }
+
+ unset($unguarded);
+
+ if ($caught) {
+ throw $caught;
+ }
+
+ return $favicon_file->getViewURI();
+ }
+
+ private function loadCachedFile(PhabricatorFile $template_file) {
+ $viewer = $this->getViewer();
+
+ $xform = id(new PhabricatorTransformedFile())->loadOneWhere(
+ 'originalPHID = %s AND transform = %s',
+ $template_file->getPHID(),
+ $this->getCacheKey());
+ if (!$xform) {
+ return null;
+ }
+
+ return id(new PhabricatorFileQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($xform->getTransformedPHID()))
+ ->executeOne();
+ }
+
+ private function newCompositedFavicon($template) {
+ $dst_w = $this->getWidth();
+ $dst_h = $this->getHeight();
+ $src_w = $template['width'];
+ $src_h = $template['height'];
+
+ $template_data = $template['file']->loadFileData();
+
+ if (!function_exists('imagecreatefromstring')) {
+ return $template_data;
+ }
+
+ $src = @imagecreatefromstring($template_data);
+ if (!$src) {
+ return $template_data;
+ }
+
+ $dst = imagecreatetruecolor($dst_w, $dst_h);
+ imagesavealpha($dst, true);
+
+ $transparent = imagecolorallocatealpha($dst, 0, 255, 0, 127);
+ imagefill($dst, 0, 0, $transparent);
+
+ imagecopyresampled(
+ $dst,
+ $src,
+ 0,
+ 0,
+ 0,
+ 0,
+ $dst_w,
+ $dst_h,
+ $src_w,
+ $src_h);
+
+ // Now, copy any icon emblems on top of the image. These are dots or other
+ // marks used to indicate status information.
+ $emblem_w = (int)floor(min($dst_w, $dst_h) / 2);
+ $emblem_h = $emblem_w;
+ foreach ($this->emblems as $key => $emblem) {
+ if ($emblem === null) {
+ continue;
+ }
+
+ $emblem_template = $this->newTemplateFile(
+ $emblem,
+ $emblem_w,
+ $emblem_h);
+
+ switch ($key) {
+ case 0:
+ $emblem_x = $dst_w - $emblem_w;
+ $emblem_y = 0;
+ break;
+ case 1:
+ $emblem_x = $dst_w - $emblem_w;
+ $emblem_y = $dst_h - $emblem_h;
+ break;
+ case 2:
+ $emblem_x = 0;
+ $emblem_y = $dst_h - $emblem_h;
+ break;
+ case 3:
+ $emblem_x = 0;
+ $emblem_y = 0;
+ break;
+ }
+
+ $emblem_data = $emblem_template['file']->loadFileData();
+
+ $src = @imagecreatefromstring($emblem_data);
+ if (!$src) {
+ continue;
+ }
+
+ imagecopyresampled(
+ $dst,
+ $src,
+ $emblem_x,
+ $emblem_y,
+ 0,
+ 0,
+ $emblem_w,
+ $emblem_h,
+ $emblem_template['width'],
+ $emblem_template['height']);
+ }
+
+ return PhabricatorImageTransformer::saveImageDataInAnyFormat(
+ $dst,
+ 'image/png');
+ }
+
+ private function newTemplateFile($emblem, $width, $height) {
+ $all_resources = self::getAllResources();
+
+ $scores = array();
+ $ratio = $width / $height;
+ foreach ($all_resources as $key => $resource) {
+ // We can't use an emblem resource for a different emblem, nor for an
+ // icon base. We also can't use an icon base as an emblem. That is, if
+ // we're looking for a picture of a red dot, we have to actually find
+ // a red dot, not just any image which happens to have a similar size.
+ if (idx($resource, 'emblem') !== $emblem) {
+ continue;
+ }
+
+ $resource_width = $resource['width'];
+ $resource_height = $resource['height'];
+
+ // Never use a resource with a different aspect ratio.
+ if (($resource_width / $resource_height) !== $ratio) {
+ continue;
+ }
+
+ // Try to use custom resources instead of default resources.
+ if ($resource['default']) {
+ $default_score = 1;
+ } else {
+ $default_score = 0;
+ }
+
+ $width_diff = ($resource_width - $width);
+
+ // If we have to resize an image, we'd rather scale a larger image down
+ // than scale a smaller image up.
+ if ($width_diff < 0) {
+ $scale_score = 1;
+ } else {
+ $scale_score = 0;
+ }
+
+ // Otherwise, we'd rather scale an image a little bit (ideally, zero)
+ // than scale an image a lot.
+ $width_score = abs($width_diff);
+
+ $scores[$key] = id(new PhutilSortVector())
+ ->addInt($default_score)
+ ->addInt($scale_score)
+ ->addInt($width_score);
+ }
+
+ if (!$scores) {
+ if ($emblem === null) {
+ throw new Exception(
+ pht(
+ 'Found no background template resource for dimensions %dx%d.',
+ $width,
+ $height));
+ } else {
+ throw new Exception(
+ pht(
+ 'Found no template resource (for emblem "%s") with dimensions '.
+ '%dx%d.',
+ $emblem,
+ $width,
+ $height));
+ }
+ }
+
+ $scores = msortv($scores, 'getSelf');
+ $best_score = head_key($scores);
+
+ $viewer = $this->getViewer();
+
+ $resource = $all_resources[$best_score];
+ if ($resource['source-type'] === 'builtin') {
+ $file = PhabricatorFile::loadBuiltin($viewer, $resource['source']);
+ if (!$file) {
+ throw new Exception(
+ pht(
+ 'Failed to load favicon template builtin "%s".',
+ $resource['source']));
+ }
+ } else {
+ $file = id(new PhabricatorFileQuery())
+ ->setViewer($viewer)
+ ->withPHIDs(array($resource['source']))
+ ->executeOne();
+ if (!$file) {
+ throw new Exception(
+ pht(
+ 'Failed to load favicon template with PHID "%s".',
+ $resource['source']));
+ }
+ }
+
+ return array(
+ 'width' => $resource['width'],
+ 'height' => $resource['height'],
+ 'file' => $file,
+ );
+ }
+
+ private function newFaviconFile($data) {
+ return PhabricatorFile::newFromFileData(
+ $data,
+ array(
+ 'name' => 'favicon',
+ 'canCDN' => true,
+ ));
+ }
+
+}
diff --git a/src/applications/files/favicon/PhabricatorFaviconRefQuery.php b/src/applications/files/favicon/PhabricatorFaviconRefQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/files/favicon/PhabricatorFaviconRefQuery.php
@@ -0,0 +1,55 @@
+<?php
+
+final class PhabricatorFaviconRefQuery extends Phobject {
+
+ private $refs;
+
+ public function withRefs(array $refs) {
+ assert_instances_of($refs, 'PhabricatorFaviconRef');
+ $this->refs = $refs;
+ return $this;
+ }
+
+ public function execute() {
+ $viewer = PhabricatorUser::getOmnipotentUser();
+
+ $refs = $this->refs;
+
+ $config_digest = PhabricatorFaviconRef::newConfigurationDigest();
+
+ $ref_map = array();
+ foreach ($refs as $ref) {
+ $ref_digest = $ref->newDigest();
+ $ref_key = "favicon({$config_digest},{$ref_digest},8)";
+
+ $ref
+ ->setViewer($viewer)
+ ->setCacheKey($ref_key);
+
+ $ref_map[$ref_key] = $ref;
+ }
+
+ $cache = PhabricatorCaches::getImmutableCache();
+ $ref_hits = $cache->getKeys(array_keys($ref_map));
+
+ foreach ($ref_hits as $ref_key => $ref_uri) {
+ $ref_map[$ref_key]->setURI($ref_uri);
+ unset($ref_map[$ref_key]);
+ }
+
+ if ($ref_map) {
+ $new_map = array();
+ foreach ($ref_map as $ref_key => $ref) {
+ $ref_uri = $ref->newURI();
+ $ref->setURI($ref_uri);
+ $new_map[$ref_key] = $ref_uri;
+ }
+
+ $cache->setKeys($new_map);
+ }
+
+ return $refs;
+ }
+
+
+}
diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php
--- a/src/applications/files/storage/PhabricatorFile.php
+++ b/src/applications/files/storage/PhabricatorFile.php
@@ -1152,7 +1152,6 @@
$params = array(
'name' => $builtin->getBuiltinDisplayName(),
- 'ttl.relative' => phutil_units('7 days in seconds'),
'canCDN' => true,
'builtin' => $key,
);
@@ -1648,7 +1647,7 @@
public function getFieldValuesForConduit() {
return array(
'name' => $this->getName(),
- 'dataURI' => $this->getCDNURI(),
+ 'dataURI' => $this->getCDNURI('data'),
'size' => (int)$this->getByteSize(),
);
}
diff --git a/src/applications/system/application/PhabricatorSystemApplication.php b/src/applications/system/application/PhabricatorSystemApplication.php
--- a/src/applications/system/application/PhabricatorSystemApplication.php
+++ b/src/applications/system/application/PhabricatorSystemApplication.php
@@ -26,7 +26,6 @@
'/readonly/' => array(
'(?P<reason>[^/]+)/' => 'PhabricatorSystemReadOnlyController',
),
- '/favicon.ico' => 'PhabricatorSystemFaviconController',
);
}
diff --git a/src/applications/system/controller/PhabricatorSystemFaviconController.php b/src/applications/system/controller/PhabricatorSystemFaviconController.php
deleted file mode 100644
--- a/src/applications/system/controller/PhabricatorSystemFaviconController.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-final class PhabricatorSystemFaviconController extends PhabricatorController {
-
- public function shouldRequireLogin() {
- return false;
- }
-
- public function processRequest() {
- $webroot = dirname(phutil_get_library_root('phabricator')).'/webroot/';
- $content = Filesystem::readFile($webroot.'/rsrc/favicons/favicon.ico');
-
- return id(new AphrontFileResponse())
- ->setContent($content)
- ->setMimeType('image/x-icon')
- ->setCacheDurationInSeconds(phutil_units('24 hours in seconds'))
- ->setCanCDN(true);
- }
-}
diff --git a/src/view/page/PhabricatorBarePageView.php b/src/view/page/PhabricatorBarePageView.php
--- a/src/view/page/PhabricatorBarePageView.php
+++ b/src/view/page/PhabricatorBarePageView.php
@@ -71,56 +71,24 @@
));
}
- $mask_icon = phutil_tag(
- 'link',
- array(
- 'rel' => 'mask-icon',
- 'color' => '#3D4B67',
- 'href' => celerity_get_resource_uri(
- '/rsrc/favicons/mask-icon.svg'),
- ));
-
- $icon_tag_76 = phutil_tag(
- 'link',
- array(
- 'rel' => 'apple-touch-icon',
- 'href' => celerity_get_resource_uri(
- '/rsrc/favicons/apple-touch-icon-76x76.png'),
- ));
-
- $icon_tag_120 = phutil_tag(
- 'link',
+ $referrer_tag = phutil_tag(
+ 'meta',
array(
- 'rel' => 'apple-touch-icon',
- 'sizes' => '120x120',
- 'href' => celerity_get_resource_uri(
- '/rsrc/favicons/apple-touch-icon-120x120.png'),
+ 'name' => 'referrer',
+ 'content' => 'no-referrer',
));
- $icon_tag_152 = phutil_tag(
- 'link',
- array(
- 'rel' => 'apple-touch-icon',
- 'sizes' => '152x152',
- 'href' => celerity_get_resource_uri(
- '/rsrc/favicons/apple-touch-icon-152x152.png'),
- ));
- $favicon_tag = phutil_tag(
+ $mask_icon = phutil_tag(
'link',
array(
- 'id' => 'favicon',
- 'rel' => 'shortcut icon',
+ 'rel' => 'mask-icon',
+ 'color' => '#3D4B67',
'href' => celerity_get_resource_uri(
- '/rsrc/favicons/favicon.ico'),
+ '/rsrc/favicons/mask-icon.svg'),
));
- $referrer_tag = phutil_tag(
- 'meta',
- array(
- 'name' => 'referrer',
- 'content' => 'no-referrer',
- ));
+ $favicon_links = $this->newFavicons();
$response = CelerityAPI::getStaticResourceResponse();
@@ -136,13 +104,10 @@
}
return hsprintf(
- '%s%s%s%s%s%s%s%s',
+ '%s%s%s%s%s',
$viewport_tag,
$mask_icon,
- $icon_tag_76,
- $icon_tag_120,
- $icon_tag_152,
- $favicon_tag,
+ $favicon_links,
$referrer_tag,
$response->renderResourcesOfType('css'));
}
@@ -156,4 +121,61 @@
return $response->renderResourcesOfType('js');
}
+ private function newFavicons() {
+ $favicon_refs = array(
+ array(
+ 'rel' => 'apple-touch-icon',
+ 'sizes' => '76x76',
+ 'width' => 76,
+ 'height' => 76,
+ ),
+ array(
+ 'rel' => 'apple-touch-icon',
+ 'sizes' => '120x120',
+ 'width' => 120,
+ 'height' => 120,
+ ),
+ array(
+ 'rel' => 'apple-touch-icon',
+ 'sizes' => '152x152',
+ 'width' => 152,
+ 'height' => 152,
+ ),
+ array(
+ 'rel' => 'icon',
+ 'id' => 'favicon',
+ 'width' => 64,
+ 'height' => 64,
+ ),
+ );
+
+ $fetch_refs = array();
+ foreach ($favicon_refs as $key => $spec) {
+ $ref = id(new PhabricatorFaviconRef())
+ ->setWidth($spec['width'])
+ ->setHeight($spec['height']);
+
+ $favicon_refs[$key]['ref'] = $ref;
+ $fetch_refs[] = $ref;
+ }
+
+ id(new PhabricatorFaviconRefQuery())
+ ->withRefs($fetch_refs)
+ ->execute();
+
+ $favicon_links = array();
+ foreach ($favicon_refs as $spec) {
+ $favicon_links[] = phutil_tag(
+ 'link',
+ array(
+ 'rel' => $spec['rel'],
+ 'sizes' => idx($spec, 'sizes'),
+ 'id' => idx($spec, 'id'),
+ 'href' => $spec['ref']->getURI(),
+ ));
+ }
+
+ return $favicon_links;
+ }
+
}
diff --git a/src/view/page/menu/PhabricatorMainMenuView.php b/src/view/page/menu/PhabricatorMainMenuView.php
--- a/src/view/page/menu/PhabricatorMainMenuView.php
+++ b/src/view/page/menu/PhabricatorMainMenuView.php
@@ -23,15 +23,29 @@
return $this->controller;
}
- private function getFaviconURI($type = null) {
- switch ($type) {
- case 'message':
- return celerity_get_resource_uri('/rsrc/favicons/favicon-message.ico');
- case 'mention':
- return celerity_get_resource_uri('/rsrc/favicons/favicon-mention.ico');
- default:
- return celerity_get_resource_uri('/rsrc/favicons/favicon.ico');
- }
+ private static function getFavicons() {
+ $refs = array();
+
+ $refs['favicon'] = id(new PhabricatorFaviconRef())
+ ->setWidth(64)
+ ->setHeight(64);
+
+ $refs['message_favicon'] = id(new PhabricatorFaviconRef())
+ ->setWidth(64)
+ ->setHeight(64)
+ ->setEmblems(
+ array(
+ 'dot-pink',
+ null,
+ null,
+ null,
+ ));
+
+ id(new PhabricatorFaviconRefQuery())
+ ->withRefs($refs)
+ ->execute();
+
+ return mpull($refs, 'getURI');
}
public function render() {
@@ -428,10 +442,7 @@
'countType' => $conpherence_data['countType'],
'countNumber' => $message_count_number,
'unreadClass' => 'message-unread',
- 'favicon' => $this->getFaviconURI('default'),
- 'message_favicon' => $this->getFaviconURI('message'),
- 'mention_favicon' => $this->getFaviconURI('mention'),
- ));
+ ) + self::getFavicons());
$message_notification_dropdown = javelin_tag(
'div',
@@ -509,10 +520,7 @@
'countType' => $notification_data['countType'],
'countNumber' => $count_number,
'unreadClass' => 'alert-unread',
- 'favicon' => $this->getFaviconURI('default'),
- 'message_favicon' => $this->getFaviconURI('message'),
- 'mention_favicon' => $this->getFaviconURI('mention'),
- ));
+ ) + self::getFavicons());
$notification_dropdown = javelin_tag(
'div',
@@ -594,10 +602,7 @@
'countType' => null,
'countNumber' => null,
'unreadClass' => 'setup-unread',
- 'favicon' => $this->getFaviconURI('default'),
- 'message_favicon' => $this->getFaviconURI('message'),
- 'mention_favicon' => $this->getFaviconURI('mention'),
- ));
+ ) + self::getFavicons());
$setup_notification_dropdown = javelin_tag(
'div',
diff --git a/webroot/favicon.ico b/webroot/favicon.ico
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/apple-touch-icon-114x114.png b/webroot/rsrc/favicons/apple-touch-icon-114x114.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/apple-touch-icon-144x144.png b/webroot/rsrc/favicons/apple-touch-icon-144x144.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/apple-touch-icon-57x57.png b/webroot/rsrc/favicons/apple-touch-icon-57x57.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/apple-touch-icon-60x60.png b/webroot/rsrc/favicons/apple-touch-icon-60x60.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/apple-touch-icon-72x72.png b/webroot/rsrc/favicons/apple-touch-icon-72x72.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/favicon-196x196.png b/webroot/rsrc/favicons/favicon-196x196.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/favicon-32x32.png b/webroot/rsrc/favicons/favicon-32x32.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/favicon-96x96.png b/webroot/rsrc/favicons/favicon-96x96.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/favicon-mention.ico b/webroot/rsrc/favicons/favicon-mention.ico
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/favicon-message.ico b/webroot/rsrc/favicons/favicon-message.ico
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/favicon.ico b/webroot/rsrc/favicons/favicon.ico
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/mstile-144x144.png b/webroot/rsrc/favicons/mstile-144x144.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/mstile-150x150.png b/webroot/rsrc/favicons/mstile-150x150.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/mstile-310x150.png b/webroot/rsrc/favicons/mstile-310x150.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/mstile-310x310.png b/webroot/rsrc/favicons/mstile-310x310.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001
diff --git a/webroot/rsrc/favicons/mstile-70x70.png b/webroot/rsrc/favicons/mstile-70x70.png
deleted file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
literal 0
Hc$@<O00001

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 13, 2:59 AM (4 d, 18 h ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/li/yu/qhbgcvu3whizhqkv
Default Alt Text
D19209.diff (32 KB)

Event Timeline