Problem/Motivation

New browser features enable better website integration to users' systems. While working on the progressive web app module I came across a W3C draft for a manifest file. This file is used on mobile devices to allow website authors some control over the way the shortcut and initialization screen looks like.

Proposed resolution

  • Add new form fields and reorganize the site information form.
  • Add a <link rel="manifest" href="…/manifest.json"> tag in the head and a way to generate that file.
  • Generation of a manifest.json file containing at least:
    {
      "lang": "en",
      "dir": "ltr",
      "name": "Very good Drupal Website™",
      "short_name": "Drupal Website™",
      "icons": [{
            "src": "my/default/theme/logo.png",
            "sizes": "144x144"
          }],
      "start_url": "/",
      "display": "browser",
      "theme_color": "#ffffff",
      "background_color": "#ffffff"
    }
    
  • We need to add a <meta name="theme-color"> tag for branding color to compliment the values set inside manifest.json

User interface changes

Site information form changes. New fields:

  • short_name (textfield)
  • start_url (textfield) Could be different from the site homepage.
  • display (select list/radio)
  • theme_color (probably expose that to themes)
  • background_color (probably expose that to themes)

API changes


Probably some ways for theme to declare/alter informations in the manifest file.

More details: Web app manifests usher new wave of progressive apps to your homescreen.

Additional tasks

Once this is RTBC'd, create an issue at
https://www.drupal.org/project/pwa
to implement the required changes to keep the module compatible with these core changes and implement the new hooks, instead of creating the manifest in the module

CommentFileSizeAuthor
#206 2698127-206.patch49.17 KBAlbert Volkman
#187 reroll_diff-177-187.txt8.31 KBSpokje
#187 2698127-187.patch50.96 KBSpokje
#186 2698127-186.patch50.79 KBviappidu
#185 2698127-185.patch53.98 KBviappidu
#180 interdiff_178-180.txt545 bytesmunish.kumar
#180 2698127-180.patch50.95 KBmunish.kumar
#178 2698127-178.patch50.99 KBmikemiles86
#177 interdiff_175-177.txt529 bytesraman.b
#177 2698127-177.patch50.9 KBraman.b
#175 interdiff_173-175.txt2.96 KBraman.b
#175 2698127-175.patch50.86 KBraman.b
#173 core-manifest-2698127-173.patch50.61 KBnod_
#172 core-manifest-2698127-172.patch31.64 KBnod_
#166 interdiff-2698127-165-166.txt114.98 KBmartin107
#166 2698127-166.patch84.39 KBmartin107
#165 2698127-165.patch199.4 KBmartin107
#163 interdiff-2698127-162-163.txt1.32 KBmartin107
#163 2698127-163.patch105.87 KBmartin107
#162 2698127-162.patch51.84 KBmartin107
#162 interdiff-2698127-161-162.txt1.15 KBmartin107
#161 interdiff-2698127-159-161.txt894 bytesmartin107
#161 2698127-161.patch51.47 KBmartin107
#159 2698127-159.patch51.74 KBmartin107
#158 2698127-158.patch51.5 KBmartin107
#155 2698127-155.patch51.5 KBmartin107
#155 interdiff-2698127-154-155.patch6.73 KBmartin107
#154 interdiff-2698127-147-154.txt2.66 KBmartin107
#154 2698127-154.patch53.4 KBmartin107
#150 2698127-150.patch53.25 KBManuel Garcia
#150 interdiff-2698127-148-150.txt1.07 KBManuel Garcia
#148 2698127-148.patch53.25 KBManuel Garcia
#148 interdiff-2698127-147-148.txt908 bytesManuel Garcia
#147 2698127-147.patch53.34 KBmartin107
#147 interdiff-2698127-145-147.txt822 bytesmartin107
#145 2698127-145.patch53.27 KBManuel Garcia
#145 interdiff-2698127-143-145.txt815 bytesManuel Garcia
#143 2698127-143.patch53.27 KBManuel Garcia
#143 interdiff-2698127-141-143.txt4.52 KBManuel Garcia
#141 interdiff-2698127-139-141.txt7.02 KBmartin107
#141 2698127-141.patch53.34 KBmartin107
#139 interdiff-2698127-138-139.txt3.76 KBmartin107
#139 2698127-139.patch53.32 KBmartin107
#138 2698127-138.patch49.46 KBManuel Garcia
#138 interdiff-2698127-136-138.txt5.48 KBManuel Garcia
#136 2698127-136.patch46.24 KBManuel Garcia
#136 interdiff-2698127-134-136.txt1.25 KBManuel Garcia
#134 2698127-134.patch46.25 KBmartin107
#134 interdiff-2698127-132-134.txt1.2 KBmartin107
#132 interdiff-2698127-130-132.txt967 bytesmartin107
#132 2698127-132.patch46.21 KBmartin107
#130 interdiff-2698127-128.130.txt747 bytesmartin107
#130 2698127-130.patch46.04 KBmartin107
#128 interdiff-2698127-126-128.txt5.46 KBmartin107
#128 2698127-128.patch46.01 KBmartin107
#126 interdiff-2698127-125-126.txt9.77 KBmartin107
#126 2698127-126.patch44.98 KBmartin107
#125 2698127-125.patch43.11 KBmartin107
#120 interdiff-2698127-118-120.txt10.97 KBmartin107
#120 2698127-120.patch45.45 KBmartin107
#118 interdiff-2698127-115-118.txt2.34 KByogeshmpawar
#118 2698127-118.patch41.57 KByogeshmpawar
#115 interdiff-2698127-113-115.txt2.27 KBmartin107
#115 2698127-115.patch41.48 KBmartin107
#110 InvalidManifest.png41.66 KBmartin107
#110 interdiff-2698127-108-110.txt12.79 KBmartin107
#110 2698127-110.patch38.68 KBmartin107
#108 2698127-108.patch36.07 KBmartin107
#108 interdiff-2698127-106-108.txt843 bytesmartin107
#106 2698127-106-interdiff.txt3.47 KBwannesdr
#106 2698127-106.patch36.03 KBwannesdr
#102 2698127-102.patch35.66 KByogeshmpawar
#100 2698127-100.patch35.89 KBwannesdr
#100 2698127-100-interdiff.txt2.55 KBwannesdr
#95 interdiff-2698127-88-95.txt1.32 KBmartin107
#95 2698127-95.patch35.95 KBmartin107
#88 2698127-88.patch35.81 KBManuel Garcia
#86 interdiff-2698127-72-85.txt7.45 KBManuel Garcia
#85 interdiff-2698127-72-85.txt4.13 KBManuel Garcia
#85 extend_site_informat-2698127-85.patch35.63 KBManuel Garcia
#72 interdiff-2698127-70-72.txt941 bytesronaldtebrake
#72 2698127-72.patch35.07 KBronaldtebrake
#70 interdiff-2698127-68-70.txt941 bytesronaldtebrake
#70 2698127-70.patch35.37 KBronaldtebrake
#68 interdiff-2698127-67-68.txt7.56 KBronaldtebrake
#68 2698127-68.patch35.36 KBronaldtebrake
#67 2698127-67.patch31.44 KBborisson_
#67 interdiff-2698127.txt1.43 KBborisson_
#65 2698127-65.patch31.53 KBborisson_
#65 interdiff-2698127.txt7.29 KBborisson_
#63 2698127-63.patch30.57 KBborisson_
#63 interdiff-2698127.txt8.93 KBborisson_
#59 extend_site_information-2698127-59.patch28.31 KBborisson_
#59 interdiff-2698127.txt2.52 KBborisson_
#58 interdiff-2698127-54-58.txt2.59 KBronaldtebrake
#58 extend_site_information-2698127-58.patch28.39 KBronaldtebrake
#54 extend_site_information-2698127-54.patch27.98 KBborisson_
#54 interdiff-2698127.txt992 bytesborisson_
#52 extend_site_information-2698127-52.patch27.96 KBborisson_
#51 extend_site_information-2698127-51.patch88.89 KBborisson_
#51 interdiff-2698127.txt6.55 KBborisson_
#49 extend_site_information-2698127-49.patch23.36 KBborisson_
#49 interdiff-2698127.txt5.65 KBborisson_
#47 extend_site_information-2698127-47.patch19.37 KBborisson_
#47 interdiff-2698127.txt4.08 KBborisson_
#43 extend_site_information-2698127-43.patch17.61 KBborisson_
#43 interdiff-2698127.txt5.27 KBborisson_
#41 extend_site_information-2698127-41.patch15.64 KBborisson_
#41 interdiff-2698127.txt7.19 KBborisson_
#36 interdiff-2698127.txt2.94 KBborisson_
#36 extend_site_information-2698127-36.patch14.1 KBborisson_
#34 extend_site_information-2698127-34.patch14.51 KBborisson_
#34 interdiff-2698127.txt9.11 KBborisson_
#32 extend_site_information-2698127-32.patch9.63 KBborisson_
#32 interdiff-2698127.txt8.9 KBborisson_
#28 extend_site_information-2698127-28.patch5.84 KBborisson_
#28 interdiff-2698127.txt2.65 KBborisson_
#25 extend_site_information-2698127-25.patch4.98 KBborisson_
#21 interdiff-2698127-18-21.txt2.52 KBfgm
#21 core-manifest-2698127-21.patch6.39 KBfgm
#19 interdiff-2698127-18-19.txt1.81 KBfgm
#19 core-manifest-2698127-19.patch6.32 KBfgm
#18 core-manifest-2698127-18.patch5.57 KBronaldtebrake
#17 core-manifest-2698127-17.patch5.57 KBfrankgraave
#12 core-manifest-2698127-12.patch4.22 KBerik.erskine
#4 core-manifest-2698127-4.patch4.24 KBnod_

Issue fork drupal-2698127

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

nod_ created an issue. See original summary.

heddn’s picture

These all feel like things for which I'd use metatags module. Are we sure this might not be a better fit in contrib?

nod_’s picture

From the metatag module description the module address the issue of SEO and content display on social platform. This has nothing to do with what the manifest file is about. So it wouldn't be a good fit.

The manifest file is really lightweight, needing a module to provide it is overkill. And it should be in core, mobile initiative & all that. It's a low risk/high reward thing. for more details on what the manifest file do check out: Bruce Lawson: Progressive Web Apps: the future of Apps slides, from slide #13 it's all about the manifest file.

nod_’s picture

Don't have time to do more but for now here is a start of something. Adds the extra infos needed out of users to generate the manifest file. The rest we can take from default logo, site name & all.

dawehner’s picture

So the idea is to generate some route which serves this file?

nod_’s picture

We can generate a real file and stick that in public://, it'll end up being used as much as robots.txt and favicon.ico no need to make it expensive, it doesn't need to be dynamic.

After all the manifest file is a href in a link tag, not too hard to change the href to point to something else if a module want to.

dawehner’s picture

We can generate a real file and stick that in public://, it'll end up being used as much as robots.txt and favicon.ico no need to make it expensive, it doesn't need to be dynamic.

Good point, as we can specify the path, there is no reason to not just generate it.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

erik.erskine’s picture

Assigned: Unassigned » erik.erskine
erik.erskine’s picture

Re-roll of #4, also using short array syntax.

Manuel Garcia’s picture

Status: Active » Needs review
Issue tags: +Needs upgrade path, +Needs upgrade path tests

Reroll looks good, thanks @erik.erskine.

I believe this requires an upgrade path since its setting new configuration.

Status: Needs review » Needs work

The last submitted patch, 12: core-manifest-2698127-12.patch, failed testing. View results

nod_’s picture

Issue summary: View changes

With some reflections I think we should let all those values come from the theme info file:

  • display (select list/radio)
  • orientation (select list/radio)
  • theme_color
  • background_color
  • icons

added the meta theme-color in the IS to be able to have 100% coverage on lighthouse reports.

Manuel Garcia’s picture

Assigned: erik.erskine » Unassigned
frankgraave’s picture

Hi there,

Nice to see this! I have added some fields in the manifest form:

  • name (textfield)
  • short name (textfield)
  • icon (managed_file)

While the 'short_name' takes care of the name on mobile devices, the 'name' is the longer (site)name that will be used when you pin it on your homescreen in desktop browsers (e.g. chrome://apps/). The 'name' field will be automatically filled with the 'site_name' unless you change the value yourself.

I've also added a icon field. Probably the nicest thing of the manifest since it will allow you to provide that 'app-like' feel when you pin to your homescreen. However, this topic could use some discussion. It's ideal to have at least the following resolution icons:

  • 128x128
  • 144x144
  • 152x152
  • 192x192

So the big question is, how should we deal with those different icon resolutions to provide a valid icon for the most mobile devices? Here's my take on it along with the question marks I have:

  1. We could take the logo from the theme as a default. But It's kinda unrealistic/hard to provide a generic way of resizing logo's from (custom)themes since they vary a lot in resolution and dimensions.
  2. We could choose to have one dedicated upload field where there's at least one square icon needed with a minimum resolution of 256x256 that will be resized (with image styles?) to fit the correct resolutions.
ronaldtebrake’s picture

Thanks for the patch, it was corrupt probably because a line was removed.
Re-applied your changes, and uploaded a working patch below.

fgm’s picture

Status: Needs work » Needs review
FileSize
6.32 KB
1.81 KB

This should have less errors. Not sure what the proper schema is for a sequence of files, though.

Status: Needs review » Needs work

The last submitted patch, 19: core-manifest-2698127-19.patch, failed testing. View results

fgm’s picture

Status: Needs work » Needs review
FileSize
6.39 KB
2.52 KB

No idea why I can't run the tests locally (phpunit no longer throws the schema errors but marks all tests as skipped). Locally these tests threw in the previous version, and are now marked skipped, unlike the CI bot.

Status: Needs review » Needs work

The last submitted patch, 21: core-manifest-2698127-21.patch, failed testing. View results

fgm’s picture

FWIW these tests now pass locally on 8.5.x HEAD using this command line:

sudo -u _www php core/scripts/run-tests.sh --verbose --sqlite /tmp/test.sqlite --url http://drop8.localhost Ajax

(to run the Ajax group which is the first failing here).

fgm’s picture

Seems to be a problem with the CI use of the --concurrency flag. When I run these tests with concurrency = 8, I get this:

Test summary
------------

Drupal\FunctionalJavascriptTests\Ajax\AjaxFormImageButtonTes   0 passes             1 exceptions
FATAL Drupal\FunctionalJavascriptTests\Ajax\AjaxFormImageButtonTest: test runner returned a non-zero error code (2).
Drupal\FunctionalJavascriptTests\Ajax\AjaxFormImageButtonTes   0 passes   1 fails
Drupal\system\Tests\Ajax\AjaxInGroupTest                      19 passes                            5 messages
Drupal\system\Tests\Ajax\DialogTest                           65 passes   2 fails   1 exceptions  24 messages
- Found database prefix 'test25569037' for test ID 14.
Drupal\FunctionalJavascriptTests\Ajax\AjaxCallbacksTest        0 passes             1 exceptions
FATAL Drupal\FunctionalJavascriptTests\Ajax\AjaxCallbacksTest: test runner returned a non-zero error code (2).
Drupal\FunctionalJavascriptTests\Ajax\AjaxCallbacksTest        0 passes   1 fails
Drupal\FunctionalJavascriptTests\Ajax\AjaxTest                 0 passes             1 exceptions
FATAL Drupal\FunctionalJavascriptTests\Ajax\AjaxTest: test runner returned a non-zero error code (2).
Drupal\FunctionalJavascriptTests\Ajax\AjaxTest                 0 passes   1 fails
Drupal\Tests\Core\Ajax\AjaxCommandsTest                       24 passes
Drupal\Tests\Core\Ajax\AjaxResponseTest                        2 passes
Drupal\system\Tests\Ajax\ElementValidationTest                15 passes                            7 messages
Drupal\FunctionalJavascriptTests\Ajax\AjaxFormPageCacheTest    2 passes
Drupal\Tests\Core\Controller\AjaxRendererTest                  1 passes
Drupal\system\Tests\Ajax\CommandsTest                         24 passes             4 exceptions   9 messages
- Found database prefix 'test90584407' for test ID 13.
Drupal\system\Tests\Ajax\FormValuesTest                       47 passes                           26 messages
Drupal\system\Tests\Ajax\MultiFormTest                        42 passes                           11 messages
Drupal\system\Tests\Ajax\AjaxFormCacheTest                    40 passes             1 exceptions  16 messages
- Found database prefix 'test56849268' for test ID 11.
Drupal\system\Tests\Ajax\FrameworkTest                        49 passes                           16 messages

While without concurrency the result is:

Test summary
------------

Drupal\FunctionalJavascriptTests\Ajax\AjaxCallbacksTest        2 passes
Drupal\FunctionalJavascriptTests\Ajax\AjaxFormImageButtonTes   1 passes
Drupal\FunctionalJavascriptTests\Ajax\AjaxFormPageCacheTest    0 passes   1 fails
Drupal\FunctionalJavascriptTests\Ajax\AjaxTest                 2 passes
Drupal\system\Tests\Ajax\AjaxFormCacheTest                    41 passes                           16 messages
Drupal\system\Tests\Ajax\AjaxInGroupTest                      19 passes                            5 messages
Drupal\system\Tests\Ajax\CommandsTest                         92 passes                           50 messages
Drupal\system\Tests\Ajax\DialogTest                           67 passes                           24 messages
Drupal\system\Tests\Ajax\ElementValidationTest                15 passes                            7 messages
Drupal\system\Tests\Ajax\FormValuesTest                       47 passes                           26 messages
Drupal\system\Tests\Ajax\FrameworkTest                        49 passes                           16 messages
Drupal\system\Tests\Ajax\MultiFormTest                        42 passes                           11 messages
Drupal\Tests\Core\Ajax\AjaxCommandsTest                       24 passes
Drupal\Tests\Core\Ajax\AjaxResponseTest                        2 passes
Drupal\Tests\Core\Controller\AjaxRendererTest                  1 passes
borisson_’s picture

Status: Needs work » Needs review
FileSize
4.98 KB

I agree with #15, this shouldn't come from the system information - at least not all of it. Most of this should be defined in the theme. So the latest patches aren't very useful I think.

The questions in #17:
1. Using the theme logo as default is probably not going to yield good results for most sites.
2. Uploading one 256x256 file and resizing that sounds like a good solution!

In the attached patch I propose a new service to fill the data, not all of it is implemented yet.

Consider this to be a work in progress and not even close to finished, but just an idea. I would like to get feedback on a couple of things:

  1. I first wanted to add a value object for this as well - instead of an array, is that a good idea?.
  2. I'm not going to give this any alter hooks or a plugin system to extend, if a site would like to overwrite the default output - they can swap out the service. Or is that making extensibility too hard?
  3. Writing the file like I'm doing right now is bad and I know that. Do we want to write this to the root or in the public:// directory?
  4. Can we add all of the remaing fields to /admin/appearance/settings
nod_’s picture

Issue tags: +Needs UX review

Thanks so much for getting that going. Did not have the courage to take it on.

I agree some of it needs to be the theme's responsibility but not all of it, I'd like to keep alter possibility, replacing the whole thing to change one field or two seems overkill.

Adding UX folks so they can give us advice on what to do.

Status: Needs review » Needs work

The last submitted patch, 25: extend_site_information-2698127-25.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

borisson_’s picture

Status: Needs work » Needs review
FileSize
2.65 KB
5.84 KB

CS fixes + config subscriber to remove the manifest.json when the system settings changes. Also now using the file in the public directory.

Status: Needs review » Needs work

The last submitted patch, 28: extend_site_information-2698127-28.patch, failed testing. View results

nod_’s picture

I'd like to have a mix of the two patches. We need a separate short_name field that is different from the site name and some display options are more about the whole site, not just the theme. Theme should provide the *_color values and maybe orientation but the display is definitely site-wide.
Also we can't use the page.front path. Drupal uses that to render "/" but to the progressive web app (or the shortcut generated by the manifest) it's just "/", not the drupal path.

I don't think a toogle in the theme to activate the manifest is useful, it should always be there. We have a default favicon, it's on the same level as that.

juliencarnot’s picture

I agree with @nod_ on #30. Regarding the start_url , it should be defined site-wide and configurable: to offer an app-like experience, it might point to another page than the homepage or even to a form.

borisson_’s picture

Still to do:
- Set configuration in theme and get information from it.
- add alter hook
- test all the things.

Done in this patch.
- Merge part of the work previous contributors did into this patch.
- Hopefully fix some of the tests
- Automatically generate the file everytime (remove the theme switch)

Status: Needs review » Needs work

The last submitted patch, 32: extend_site_information-2698127-32.patch, failed testing. View results

borisson_’s picture

Status: Needs work » Needs review
FileSize
9.11 KB
14.51 KB

All information should now come from the correct locations, would love to get feedback before writing tests. I don't think I'll be able to spend a lot of time on this the next couple of days so if someone would like to pick this up - feel free.

We should still fix the icon though.

I also think we should make give this a language-context (if at all possible with the current approach), we should probably also make this vary by active theme.

I think those are good reasons to reconsider @dawehner's point about making this into a route instead of a file.

Status: Needs review » Needs work

The last submitted patch, 34: extend_site_information-2698127-34.patch, failed testing. View results

borisson_’s picture

I don't think we should make the direction configurable, every language object already has that information. So we can reuse it.

Status: Needs review » Needs work

The last submitted patch, 36: extend_site_information-2698127-36.patch, failed testing. View results

idebr’s picture

  1. What is the approach regarding multilingual?
  2. Do we generate a manifest.json file per language to facilitate translating the (short) site name and start url?

Reading the spec (https://www.w3.org/TR/appmanifest) it appears one is not limited to one manifest file by design.

borisson_’s picture

  1. What is the approach regarding multilingual?
  2. Do we generate a manifest.json file per language to facilitate translating the (short) site name and start url?

1. There is no multilingual implementation right now, currently the only thing we do is generate a manifest for the first language that gets accessed. There are 2 options to make this work.
a) Make this into a route instead of generated file, and add cacheability metadata.
b) Generate several files and serve different files based on the cacheability metadata.
2. We should, but don't.

I think the route is a better approach to fix this.

nod_’s picture

route +1 didn't think about it when I went with generating a file. My bad.

borisson_’s picture

Status: Needs work » Needs review
FileSize
7.19 KB
15.64 KB

No longer makes the entire core rely on the json encoder service. This is not done yet. The cache metadata isn't bubbled yet.

However, this makes it into a route.

I think the tests shouldn't be as broken anymore.

Status: Needs review » Needs work

The last submitted patch, 41: extend_site_information-2698127-41.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

borisson_’s picture

Status: Needs work » Needs review
FileSize
5.27 KB
17.61 KB

The tests look to be failing in upgrade path tests, I think that's because the manifest file is added to update.php, we shouldn't do that. No idea how to do that though.

I added an alter hook, as well as a basic test.

Before spending more time on tests, I'd love to get feedback on the implementation as it is now.

Status: Needs review » Needs work

The last submitted patch, 43: extend_site_information-2698127-43.patch, failed testing. View results

juliencarnot’s picture

Thanks @borisson_!
I'd be happy to give it a try and to share my feedback. I don't have a fresh 8.5 install at hand, so I gave it a try on https://simplytest.me choosing the 8.5x branch with the patch #43, but install fails with this error, which seems related to the patch:

Additional uncaught exception thrown while handling exception.
Original

Symfony\Component\Routing\Exception\RouteNotFoundException: in Drupal\Core\Routing\NullGenerator->getRoute() (line 43 of /home/du09m/www/core/lib/Drupal/Core/Routing/NullGenerator.php).

Drupal\Core\Routing\NullGenerator->getRoute('system.manifest') (Line: 271)
Drupal\Core\Routing\UrlGenerator->generateFromRoute('system.manifest', Array, Array, ) (Line: 753)
Drupal\Core\Url->toString() (Line: 622)
system_page_attachments(Array) (Line: 65)
Drupal\Core\Render\BareHtmlPageRenderer->renderBarePage(Array, 'Choose language', 'install_page', Array) (Line: 76)
Drupal\Core\ProxyClass\Render\BareHtmlPageRenderer->renderBarePage(Array, 'Choose language', 'install_page', Array) (Line: 1004)
install_display_output(Array, Array) (Line: 156)
install_drupal(Object) (Line: 44)

Additional

Symfony\Component\Routing\Exception\RouteNotFoundException: in Drupal\Core\Routing\NullGenerator->getRoute() (line 43 of /home/du09m/www/core/lib/Drupal/Core/Routing/NullGenerator.php).

Drupal\Core\Routing\NullGenerator->getRoute('system.manifest') (Line: 271)
Drupal\Core\Routing\UrlGenerator->generateFromRoute('system.manifest', Array, Array, ) (Line: 753)
Drupal\Core\Url->toString() (Line: 622)
system_page_attachments(Array) (Line: 65)
Drupal\Core\Render\BareHtmlPageRenderer->renderBarePage(Array, 'Error', 'install_page', Array) (Line: 76)
Drupal\Core\ProxyClass\Render\BareHtmlPageRenderer->renderBarePage(Array, 'Error', 'install_page', Array) (Line: 1004)
install_display_output(Array, Array, Array) (Line: 265)
_drupal_log_error(Array, 1) (Line: 566)
_drupal_exception_handler(Object)
borisson_’s picture

Looks like that is because the manifest.json is added on install.php and update.php. We should remove it from those - but like I mentioned in #43 I have no idea how to not do that.

borisson_’s picture

Status: Needs work » Needs review
FileSize
4.08 KB
19.37 KB

This should fix the problem with update/install.

Status: Needs review » Needs work

The last submitted patch, 47: extend_site_information-2698127-47.patch, failed testing. View results

borisson_’s picture

Status: Needs work » Needs review
FileSize
5.65 KB
23.36 KB

Test should be all green now.

ronaldtebrake’s picture

Thanks for the great progress, really nice :). Like the approach on the route and love to see the tests are in there :).

Some first remarks/questions after some functional testing on simplytest.me.

  1. It's not really clear to me once you're configuring your site settings the rest of the settings for the manifest.json are found in the theme settings, maybe we can make that a bit more clear by adding a link to the active theme settings page?
  2. As per issue summary: We still need to add a <meta name="theme-color"> tag for branding color to compliment the values set inside manifest.json.
  3. I believe we should add some validation to the theme/background color. We can now put anything random in there. This will just render as undefined if it's not a valid color. See below for a test of the manifest.json that came out of my test.
{
  "lang": "en",
  "dir": "ltr",
  "short_name": "Short test name",
  "name": "Manifest test",
  "display": "standalone",
  "icons": [
    {
      "src": "logo.png",
      "sizes": "144x144"
    }
  ],
  "start_url": "\/user\/1",
  "orientation": "landscape",
  "theme_color": "somethingrandom",
  "background_color": "somethingrandom"
}

If there is any help on development I can do let me know! Will leave it on needs review for others to check it out :)

borisson_’s picture

If there is any help on development I can do let me know! Will leave it on needs review for others to check it out :)

The biggest outstanding thing right now is the files, and how we want to generate the different sizes of those, do we want to ship with predefined (locked) image styles or something else?

The other points you brought up are done. The validation is the same as the one color module used, so I moved that to system.

borisson_’s picture

The patch in #51 is wrong, this one is correct.

Status: Needs review » Needs work

The last submitted patch, 52: extend_site_information-2698127-52.patch, failed testing. View results

borisson_’s picture

Status: Needs work » Needs review
FileSize
992 bytes
27.98 KB

Should fix the tests again - at least colortest is now green again locally - let's see if the rest is as well.

juliencarnot’s picture

I successfully installed and tested patch #54 and the UI part seems good to me! A couple remarks:

  • There is no description object in the manifest: it seems that adding the site slogan as description if the slogan is set could be a good option, although I'm not sure how it can be translated.
  • I changed the default logo.png by an svg or png file with different names using the theme settings in /admin/appearance/settings , and the manifest still links to "src":"logo.png".
ronaldtebrake’s picture

@55

I changed the default logo.png by an svg or png file with different names using the theme settings in /admin/appearance/settings , and the manifest still links to "src":"logo.png".

This still needs to be tackled as mentioned in #51, but we need to come up with a solution on how to add the different sizes of the icon. See also the todo in code.

// @todo Get this from the to-be added file field in the theme
+      // configuration.
+      'icons' => [
+        [
+          'src' => 'logo.png',
+          'sizes' => '144x144',
+        ],
+      ],
There is no description object in the manifest: it seems that adding the site slogan as description if the slogan is set could be a good option

I agree we can provide this as an extra, optional (?), object in the manifest. Don't think we should use the site slogan for that. It's more for describing the purpose of the web application rather than showing the slogan of your website.

borisson_’s picture

Status: Needs review » Needs work

Self-review, most of these are just docs-updates. I'd be super happy if anyone fixes these.

We can do a description in a later followup, let's try to keep this as small as possible for now. It's already ~30kb and we still need to add better testcoverage + fix the logo. We don't want this to turn into an unreviewable monster later down the line :)

  1. +++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
    @@ -0,0 +1,107 @@
    +/**
    + * Class ManifestGenerator.
    + */
    +class ManifestGenerator {
    

    This documentation as it right now is useless. It should be expanded.

  2. +++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
    @@ -0,0 +1,107 @@
    +    $themeSpecificConfig = \Drupal::config($themeName . '.settings');
    ...
    +      $this->themeConfig = \Drupal::config('system.theme.global');
    

    These shouldn't use \Drupal::config but use the configFactory object (that's already injected)

  3. +++ b/core/modules/system/src/Controller/ManifestController.php
    @@ -0,0 +1,68 @@
    +/**
    + * Controller for default HTTP 4xx responses.
    + */
    

    Looks like I copied this from another controller, the docs here are wrong.

  4. +++ b/core/modules/system/src/Controller/ManifestController.php
    @@ -0,0 +1,68 @@
    +class ManifestController extends ControllerBase {
    

    Are we sure we need to extend controllerBase? If we're not using any of it, we should remove the extend here.

  5. +++ b/core/modules/system/src/Controller/ManifestController.php
    @@ -0,0 +1,68 @@
    +   * Return an renderable array of manifest data.
    

    This is wrong, we're not returning a renderable array - we're returning a json response. Let's fix the docs.

  6. +++ b/core/modules/system/system.module
    @@ -799,6 +820,20 @@ function system_form_alter(&$form, FormStateInterface $form_state) {
    +function system_valid_hexadecimal_string($color) {
    +  return preg_match('/^#([a-f0-9]{3}){1,2}$/iD', $color);
    +}
    

    Are we sure we want to just move this to a new global function, or should this move to a service somewhere? I guess for now the global function is good enough.

  7. +++ b/core/modules/system/tests/src/Kernel/Theme/ManifestGeneratorTest.php
    @@ -0,0 +1,72 @@
    +  public function testGenerateManifest() {
    

    Needs a docblock.

ronaldtebrake’s picture

Tried to pitch in a little and fix most of the above.

Still to do:

4.

+++ b/core/modules/system/src/Controller/ManifestController.php
@@ -0,0 +1,68 @@
+class ManifestController extends ControllerBase {
Are we sure we need to extend controllerBase? If we're not using any of it, we should remove the extend here.

6.

+++ b/core/modules/system/system.module
@@ -799,6 +820,20 @@ function system_form_alter(&$form, FormStateInterface $form_state) {
+function system_valid_hexadecimal_string($color) {
+  return preg_match('/^#([a-f0-9]{3}){1,2}$/iD', $color);
+}
Are we sure we want to just move this to a new global function, or should this move to a service somewhere? I guess for now the global function is good enough.
borisson_’s picture

Status: Needs review » Needs work

The last submitted patch, 59: extend_site_information-2698127-59.patch, failed testing. View results

borisson_’s picture

Status: Needs work » Needs review
FileSize
832 bytes
28.41 KB

This should fix the broken tests.

dawehner’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
    @@ -0,0 +1,109 @@
    +    $themeSpecificConfig = $this->configFactory->get($themeName . '.settings');
    +    if (isset($themeSpecificConfig->get()['manifest'])) {
    +      $this->themeConfig = $themeSpecificConfig;
    

    Just a question: Do we really use camelcase variable names? Sorry for my ignorant question.

  2. +++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
    @@ -0,0 +1,109 @@
    +    return $this->generateData();
    ...
    +  protected function generateData() {
    

    I would have had a method $this->loadThemeConfig and a method doGenerateManifest and then a generateManifest which does both. ```generateData``` isn't really a helpful method name.

  3. +++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
    @@ -0,0 +1,109 @@
    +    \Drupal::moduleHandler()->alter('manifest', $data);
    

    Is there a reason this is not injected?

  4. +++ b/core/modules/color/color.module
    @@ -346,9 +346,12 @@ function color_palette_color_value($element, $input, FormStateInterface $form_st
    + * @deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.x. Use
    ...
     function color_valid_hexadecimal_string($color) {
    -  return preg_match('/^#([a-f0-9]{3}){1,2}$/iD', $color);
    +  return system_valid_hexadecimal_string($color);
     }
    

    Let's ensure to add a @trigger_error as I guess we treat this, just like everything else, as some sort of "API"?

  5. +++ b/core/modules/system/src/Controller/ManifestController.php
    @@ -0,0 +1,72 @@
    +    $manifestData = $this->manifestGenerator->generateManifest($themeName);
    ...
    +    $response->addCacheableDependency(CacheableMetadata::createFromRenderArray($manifestData));
    +    unset($manifestData['#cache']);
    

    This render array bit feels so weird. I would rather introduce a new custom value object which implements \Drupal\Core\Cache\RefinableCacheableDependencyInterface and stores the needed data.

  6. +++ b/core/modules/system/system.module
    @@ -675,6 +675,27 @@ function system_page_attachments(array &$page) {
    +  if (!\Drupal::service('router.admin_context')->isAdminRoute() && ($routeName !== 'system.db_update' && $routeName !== '<none>')) {
    

    Can't you use strpos($request->getScriptName(), 'update.php') === FALSE or so?

  7. +++ b/core/modules/system/system.module
    @@ -799,6 +820,20 @@ function system_form_alter(&$form, FormStateInterface $form_state) {
    +function system_valid_hexadecimal_string($color) {
    +  return preg_match('/^#([a-f0-9]{3}){1,2}$/iD', $color);
    +}
    

    A random suggeston: Could we add a Drupal\Component\Utility helper class instead? This sounds for me like something which really doesn't have to exist in system module.

borisson_’s picture

Status: Needs work » Needs review
FileSize
8.93 KB
30.57 KB

Thanks so much for the review daniel, that really helps!

  1. We don't, fixed.
  2. I agree the methodname was bad, I think I understood everything correctly.
  3. Fixed
  4. Added the trigger_error
  5. I agree, I already wondered about that in #25. Fixed.
  6. Done.
  7. Sure, however I'm not sure if we should add a new class just for this. Not yet done.

Status: Needs review » Needs work

The last submitted patch, 63: 2698127-63.patch, failed testing. View results

borisson_’s picture

Status: Needs work » Needs review
FileSize
7.29 KB
31.53 KB

Test should be green again now. I decided to remove the part about the file icon, we can do that as a followup later.

Still todo:

Move the system_valid_hexadecimal_string to a Drupal\Component\Utility helper

Status: Needs review » Needs work

The last submitted patch, 65: 2698127-65.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

borisson_’s picture

Status: Needs work » Needs review
FileSize
1.43 KB
31.44 KB
ronaldtebrake’s picture

Moved the system_valid_hexadecimal_string to a Drupal\Component\Utility helper.

Used Drupal\Component\Color for that, there was already a validateHex function in there, but that accepted strings like "cba" unfortunately that is not strict enough for the manifest.json. Also made sure the tests for both functions reflects the above use case.

borisson_’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Component/Utility/Color.php
    @@ -30,6 +30,21 @@ public static function validateHex($hex) {
    +   * Determines if a hexadecimal CSS color string is valid in a strict way,
    +   * so it should start of with a # followed by at least 3 characters.
    

    The first line of documentation should be only 80 characters long and the rest should be in a new paragraph. Can we rewrite this?

    Determines if a hexadecimal CSS color is valid in a strict way.
    
    It should start with a # and be followed by either 3 or 6 hexacecimal characters.
    
  2. +++ b/core/lib/Drupal/Component/Utility/Color.php
    @@ -30,6 +30,21 @@ public static function validateHex($hex) {
    +   *   TRUE if the string is a valid hexadecimal CSS color string, or FALSE if it
    +   *   isn't.
    

    This goes over the 80 cols line.

I like the new tests, great job on those!

ronaldtebrake’s picture

Status: Needs work » Needs review
FileSize
35.37 KB
941 bytes

Thanks a lot for the review!

Updated the documentation as per your comments.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

ronaldtebrake’s picture

Created the patch against 8.6.x

Notable changes (also see interdiff):

-      $config->set('manifest.' . Unicode::substr($key, 9), $value);
+      $config->set('manifest.' . mb_substr($key, 9), $value);

Necessary because of: https://www.drupal.org/project/drupal/issues/2849669

Still todo

According to the Lighthouse validation there should be at least two icon sizes rendered:

+    'icons' => [
+       [
+        'src' => url(to/image/-512.png),
+        'sizes' => '512x512',
+        'type' => 'image/png',
+      ],
+      [
+        'src' => url(to/image/-192.png'),
+        'sizes' => '192x192',
+        'type' => 'image/png',
+      ],

Can somebody maybe elaborate on how to tackle this best?
Imagestyle? Two separate upload fields with size restrictions?

borisson_’s picture

Issue tags: -Needs tests

I think an image style is the best idea, 2 file fields sounds like making it a lot harder for people when it's not really needed.

Also removed the needs tests tag, I think this has sufficient coverage as-is.

økse’s picture

Status: Needs review » Reviewed & tested by the community

Unit tests did run and passed. Functionality test setting the parameters from the manifest.json file works flawlessly.

A remark about the position of the site manifest parameters fieldset within the basic settings page though. Maybe it would be a good idea to not to nest within the site details fieldset?

andrewmacpherson’s picture

Status: Reviewed & tested by the community » Needs work

This needs API documentation for hook_manifest_alter().

andrewmacpherson’s picture

The manifest file is being served with a Content-type: application/json header, but it's supposed to be application/manifest+json if we're following the W3C Web App manifest working draft.

That draft also describes the file extension as .webmanifest but we currently jdon't have a file extension.

borisson_’s picture

We can change the header really easily, however creating a file is not possible, we tried that earlier and that was harder to fix for multilingual.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

rupl’s picture

Using a JSON is an acceptable file extension for Web Manifest. The file's official structure is JSON so sites like MDN docs often suggest that JSON file extension is a safe convention.

I cleanly applied this to latest 8.7.x and it's still working. I found one issue while clicking through and trying out the admin UI:

+++ b/core/modules/system/config/install/system.site.yml
@@ -10,3 +10,8 @@ admin_compact_mode: false
+  display: 'browser'

I see that browser is the default Display setting in the YML but when I test this patch on a fresh installation I get "Fullscreen" as my default value when I load the form and save.

So in terms of Lighthouse audit checkpoints, the two images sized 192/512 are necessary to make the site installable by default. In the contrib module we just use the Druplicon and I figure that's ok for core to do as well. The PNG inside core/misc is 88x110 but checking in two additional copies at the correct size seems like an easy path to "out of the box" functionality.

Someone mentioned writing docs for the manifest alter hook. That's something I'm happy to do. Does it need to be in this patch or on a d.o page somewhere?

Manuel Garcia’s picture

core.api.php could be a good start perhaps? not sure.

+++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
@@ -0,0 +1,121 @@
+  /**
+   * Load the theme configuration.
+   *
+   * @param string $themeName
+   *   The theme name to generate data for.
+   *
+   * @return \Drupal\Core\Config\ImmutableConfig
+   *   The configuration of the theme.
+   */
+  protected function loadThemeConfig($themeName) {
+    $theme_specific_config = $this->configFactory->get($themeName . '.settings');
+    if (isset($theme_specific_config->get()['manifest'])) {
+      return $theme_specific_config;
+    }
+    return $this->configFactory->get('system.theme.global');
+  }

This looks generic enough, and useful not only for manifests, can we refactor/add it somewhere more accessible?

borisson_’s picture

@Manuel Garcia: I don't think we should do that, at least not yet. Opening this up to a general API might be useful, but this is a DX improvement we can always add somewhere in the future. For now, I'd like to keep the API surfuce of this patch as small as possible.

andrewmacpherson’s picture

Is there any reason why the ManifestGenerator can't just have a Drupal\Core\Theme\ThemeSettings member?

borisson_’s picture

I don't really understand #82.

larowlan’s picture

Issue tags: +Needs documentation
  1. +++ b/core/lib/Drupal/Core/Theme/Manifest.php
    @@ -0,0 +1,54 @@
    +    $this->data = $data;
    ...
    +    return $this->data;
    

    If data is just a keyed array, we're not really making the most of php5.4 memory optimisations.

    Are there known keys here we should be making properties on the object?

    If not - what is the value object adding that an array doesn't provide? Is it just to provide the cacheability methods?

  2. +++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
    @@ -0,0 +1,121 @@
    +class ManifestGenerator {
    

    Should we have a interface for this to allow alternative implementations?

  3. +++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
    @@ -0,0 +1,121 @@
    +    if (isset($theme_specific_config->get()['manifest'])) {
    

    would
    $theme_specific_config->get('manifest') work?

  4. +++ b/core/modules/color/color.module
    @@ -346,9 +347,13 @@ function color_palette_color_value($element, $input, FormStateInterface $form_st
    + * @deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.x. Use
    + * system_valid_hexadecimal_string instead.
    ...
    +  @trigger_error('color_valid_hexadecimal_string is deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.x. Use Drupal\Component\Utility\Color::validateStrictHex instead.', E_USER_DEPRECATED);
    

    these need a link to a change record

  5. +++ b/core/modules/system/src/Form/SiteInformationForm.php
    @@ -118,12 +120,51 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    +      '#description' => $this->t("The site name."),
    ...
    +      '#description' => $this->t("The short name of the site."),
    

    no need for " here, should be ' for consistency?

  6. +++ b/core/modules/system/src/Form/SiteInformationForm.php
    @@ -118,12 +120,51 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    +        'fullscreen' => 'Fullscreen',
    +        'standalone' => 'Standalone',
    +        'minimal-ui' => 'Minimal UI',
    +        'browser' => 'Browser',
    

    shouldn't these be passed through $this->t() ?

  7. +++ b/core/modules/system/src/Form/ThemeSettingsForm.php
    @@ -367,6 +369,37 @@ public function buildForm(array $form, FormStateInterface $form_state, $theme =
    +      '#title' => t('Orientation'),
    ...
    +        'portrait' => t('Portrait'),
    +        'landscape' => t('Landscape'),
    

    Should use $this->t()?

  8. +++ b/core/modules/system/src/Form/ThemeSettingsForm.php
    @@ -420,6 +453,14 @@ public function validateForm(array &$form, FormStateInterface $form_state) {
    +      if (in_array($key, ['manifest_background_color', 'manifest_theme_color']) && !empty($color) && !Color::validateStrictHex($color)) {
    

    Can we use the third argument to in_array here. We're comparing strings, so we should be strict.

    https://3v4l.org/949aT

  9. +++ b/core/modules/system/system.module
    @@ -675,6 +675,33 @@ function system_page_attachments(array &$page) {
    +      ->toArray();
    

    e.g. this would be an ideal candidate for a ->getThemeColor method

  10. +++ b/core/tests/Drupal/Tests/Component/Utility/ColorTest.php
    @@ -12,6 +12,97 @@
    +    // Any invalid arguments should throw an exception.
    ...
    +    // Any invalid arguments should throw an exception.
    

    Do they actually throw an exception?

We also need docs for the new hook, and the update path for the new config (with a test)

Looks great though, really valuable feature

Manuel Garcia’s picture

Status: Needs work » Needs review
Issue tags: +Needs change record
FileSize
35.63 KB
4.13 KB

Thanks @larowlan for the review,

#84.1 - Probably, let's identify these.
#84.2 - Good idea, doing it here please have a look.
#84.3 - I think it should, doing so in this patch.
#84.4 - Yes, we need to write it first, adding the tag.
#84.5 - Good catch, done.
#84.6 - Yes they should, done.
#84.7 - Good catch, done.
#84.8 - Yup, done.
#84.9 - Possibly, lets first sort out #84.1
#84.10 - I don think so, this looks to test just Color::validateStrictHex() which returns the value from the preg_match(bool). Changed the comment to something more generic.

Manuel Garcia’s picture

FileSize
7.45 KB

OK that interdiff came out very wrong, here is the good one.

Status: Needs review » Needs work

The last submitted patch, 85: extend_site_informat-2698127-85.patch, failed testing. View results

Manuel Garcia’s picture

Status: Needs work » Needs review
FileSize
35.81 KB

Sigh back to the old way of generating patches then. Interdiff on #86 is good.

Manuel Garcia’s picture

Manuel Garcia’s picture

Status: Needs review » Needs work

Still needs work for these as far as I can tell:

  • #72
  • #84.1/#84.9
  • Write change record and link to it, see #84.4
  • Write upgrade path & tests
andrewmacpherson’s picture

We need to address WCAG SC 1.3.4 Orientation. Currently this patch prevent site-builders from producing a website that conforms to WCAG level AA.

I propose (maybe insist) we remove the orientation key entirely. Locking the orientation is justified only in rare cases, and including this setting seems irresponsible IMO. The alter hook provides a way to lock the orientation key for sites which can justify it.

I'll expand on this comment later. I'm on a rural bus journey right now.

andrewmacpherson’s picture

@borisson_ Sorry I was too brief in #82.

It was about the loadThemeConfig() method in #80. Is this new method really necessary? There's already a ThemeSettings class which sorts out the global/theme-specific settings. Can manifestgenerator use this existing feature instead?

andrewmacpherson’s picture

The "display" property also has some accessibility concerns.

When a user views a website in a browser, they have lots of useful tools built in to the browser: bookmarking a URL, find in page, share a URL to another app, Firefox add-ons for dictionary look-ups, reader mode, etc..

But when they save a "page" to the homescreen, the PWA manifest "display" property kicks in, and the user may loose access to some browser tools which they depend on - e.g. with "minimal-ui", PWAs on Android/Chrome do not offer bookmarking URLs. I'm highly skeptical of why many web sites would need to do this at all.

I'm not sure what happens if users add a PWA to their homescreen from Android/Firefox, but I'm concerned users will lose the ability to use Firefox addons which they rely on (like dictionary look-ups).

I think use of the "display" property could present problems for users with a large range of cognitive/learning impairments. I'll keep looking for articles which can provide more info on this. I don't think we'll find an outright WCAG failure here, but it's something we can provide guidance about for site builders, in the manifest settings form and help topics.

rupl’s picture

To address #91 concerns: Orientation is just specifying the default orientation. It's not a locking mechanism, rather a signal for what a given site considers its default or most useful orientation. There are more than just two options. Would setting any as a default alleviate the concerns you have?

Other options listed at https://developer.mozilla.org/en-US/docs/Web/Manifest#orientation

Per #93 The display property is similar in that it's only as restrictive to accessibility as the individual settings allow. We can choose the most conservative default of browser and it won't be any different than a normal web page.

If there's really a measurable problem with including these two properties by default, we could add a None option which still makes them easily adjustable without forcing one particular implementation on folks. See an example manifest with just the bare minimum of meta-data (Example1): https://www.w3.org/TR/appmanifest/#example-manifests

@andrewmacpherson do you have some links we could read explaining why these properties have negative effects on a11y? This is the first I've heard of it and I'm keen to learn more in case I need to adjust something in the contrib module.

martin107’s picture

FileSize
35.95 KB
1.32 KB

This is just a minor observation, found while looking over the patch

t() is a antipattern, I have converted a couple of instances into $this->t().. only where we were adding new code.

mgifford’s picture

Status: Needs work » Needs review

Just wanting to test #95

Wim Leers’s picture

Status: Needs review » Needs work

High-level review.

  1. +++ b/core/lib/Drupal/Core/Theme/Manifest.php
    @@ -0,0 +1,54 @@
    + * A value object containing all data for the manifest.
    + */
    +class Manifest implements RefinableCacheableDependencyInterface {
    ...
    +  public function overwriteWithNewData($data) {
    +    return new static($data);
    +  }
    

    Implementing RefinableCDI makes this a mutable value object. In every other way this is immutable.

    Let's keep it immutable.

  2. +++ b/core/modules/system/config/schema/system.schema.yml
    @@ -44,6 +44,22 @@ system.site:
    +        start_url:
    ...
    +          label: 'Default start page'
    

    Inconsistent: URL vs page.

  3. +++ b/core/modules/system/config/schema/system.schema.yml
    @@ -44,6 +44,22 @@ system.site:
    +        display:
    +          type: string
    +          label: 'Display'
    

    Display what? Based on the name, I though this was going to be a boolean.

  4. +++ b/core/modules/system/config/schema/system.schema.yml
    @@ -44,6 +44,22 @@ system.site:
    +        short_name:
    +          type: label
    +          label: 'Short name'
    +        name:
    +          type: label
    +          label: 'Short name'
    

    How can these have the same label?

  5. +++ b/core/modules/system/src/Controller/ManifestController.php
    @@ -0,0 +1,71 @@
    +    $response = new CacheableJsonResponse();
    +    $response->addCacheableDependency($manifestData);
    +    $response->setData($manifestData->toArray());
    +    return $response;
    +  }
    

    🎉

  6. +++ b/core/modules/system/tests/modules/manifest_test/manifest_test.module
    @@ -0,0 +1,17 @@
    +/**
    + * Implements hook_manifest_alter().
    + */
    +function manifest_test_manifest_alter(&$variables) {
    ...
    +    $variables = $variables->overwriteWithNewData($new_data);
    

    This is lacking the ability to influence cacheability.

heddn’s picture

The IS mentions icons, but there's no icons in the latest patch.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

wannesdr’s picture

Status: Needs work » Needs review
FileSize
2.55 KB
35.89 KB

No activity for a long time, but brought to my attention by @borisson_, so thanks for the opportunity!

Attached is a new patch with the feedback by Wim + some additional improvements. I made the naming of the start_url more consistent in the SiteInformationForm.

I was also wondering if the manifest config this patch adds in system.site.yml must also be added to the Standard install profile system.site.yml config file? (and maybe the other install profiles as well?)

yogeshmpawar’s picture

Assigned: Unassigned » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
FileSize
35.66 KB

Re-rolled the #100 patch against 8.8.x branch.

wannesdr’s picture

Thanks for the re-role @yogeshmpawar!
Hope we can move this forward now.

martin107’s picture

A) Just pull out the "additional coding standard errors" out from the test artefacts

/var/lib/drupalci/workspace/jenkins-drupal_patches-102226/source/core/lib/Drupal/Component/Utility/Color.php ✗ 1 more
line 38	Doc comment for parameter $color does not match actual variable name $hex
/var/lib/drupalci/workspace/jenkins-drupal_patches-102226/source/core/tests/Drupal/Tests/Component/Utility/ColorTest.php ✗ 2 more
20	Expected "bool" but found "boolean" for parameter type
65	Expected "bool" but found "boolean" for parameter type 

B) Also there are out of date deprecation notices being added.

+ * @deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.x. Use
+ * system_valid_hexadecimal_string instead.

The is movement to standardise this text. Here is a example from
https://www.drupal.org/core/deprecation

@trigger_error('baz() is deprecated in drupal:8.3.0 and is removed from drupal:9.0.0. Use \Drupal\Foo\Bar::baz() instead. See http://drupal.org/node/the-change-notice-nid', E_USER_DEPRECATED);

(b.2) drupal:8.8.0 is now the preferred label.

(b.3) "is removed from" is intentional so that code can linger in drupal:9.0.0 and be deleted in later minor releases. without warning.

I hope this helps.

wannesdr’s picture

Assigned: Unassigned » wannesdr
Status: Needs review » Active

Thanks @martin107 for the review, I will take a look

wannesdr’s picture

New patch with the feedback from @martin107.

I changed all the 'Boolean' occurrences to 'bool'. So it is consistent with the rest of Core.

martin107’s picture

My time is limited at the moment , but digging in the build artifacts

Error: Call to undefined method Drupal\Core\Theme\Manifest::addCacheContexts()

so that looks like a missing use statement, as addCacheContexts() is not under the Drupal\Core\Theme namespace

I hope this helps

Error: Call to undefined method Drupal\Core\Theme\Manifest::addCacheContexts() in Drupal\Core\Theme\ManifestGenerator->doGenerateManifest() (line 95 of core/lib/Drupal/Core/Theme/ManifestGenerator.php).
Drupal\Core\Theme\ManifestGenerator->doGenerateManifest() (Line: 71)
Drupal\Core\Theme\ManifestGenerator->generateManifest('classy') (Line: 693)
system_page_attachments(Array) (Line: 297)
Drupal\Core\Render\MainContent\HtmlRenderer->invokePageAttachmentHooks(Array) (Line: 273)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 117)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object) (Line: 156)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 191)
Drupal\page_cache\StackMiddleware\PageCache->fetch(Object, 1, 1) (Line: 128)
Drupal\page_cache\StackMiddleware\PageCache->lookup(Object, 1, 1) (Line: 82)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 52)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 693)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)"
    at Object.Test page (/var/www/html/core/tests/Drupal/Nightwatch/Tests/exampleTest.js:15:15)
    at _combinedTickCallback (internal/process/next_tick.js:132:7)
martin107’s picture

FileSize
843 bytes
36.07 KB

This resolves what I described above

CacheableDependencyInterface becomes RefinableCacheableDependencyInterface

when to use a RefinableCacheableDependencyInterface?

The following interface should be implemented by any class whose business logic implies dealing at runtime with variations of a canonical object:

https://www.drupal.org/node/2525764

Anyway locally ManifestGeneratorTest now passes.

borisson_’s picture

Wim's remark in #97 was to remove RefinableCacheableDependencyInterface. Because that makes this VO mutable and it was immutable before. I don't see how we can keep this immutable without creating a new way to pass in the cacheability metadata.

So I think that means #108 is a good start. I think the next thing we should change is to allow for the cache data to also be passed to the new value object as well.

+++ b/core/lib/Drupal/Core/Theme/Manifest.php
@@ -0,0 +1,54 @@
+  public function overwriteWithNewData($data) {
+    return new static($data);
+  }
martin107’s picture

@borisson_ Oh ground swallow my up ... thanks for pointing out my mistake.

I should explain a few judgement calls I have made.

A)

Regarding the manifest.json file, I want to talk about mitigating the differences between what the spec says and what the disparate implementations do.

1) Name and manifest_version are the only required manifest key value pairs. So I have added "manifest_version" as a new form entry and made the 'name' field required.

Browser are pragmatic - If manifest_version is missing form the file then a default is assumed - but I want to follow the spec, while recognising it is not actually needed.

2) I have reworked the manifest_generator so that if, for example, theme_color is missing then instead of the key value pair being
'theme_color' => ''

we now omit the whole thing.

3) Given 2 - theme_color if it is blank then $page['#attached']['html_head'][] is no longer modified.

B) I went looking at the manifest.json generated by a 'standard' and 'unami' install. lots of value were null. Now placeholder values appear.

C) From now on php7.0.3 is required. For new code it is time to specify a return type

Here is a example of the change I have made to ManifestController. We can now mandate a CacheableJsonResponse. yay for 2019

  /**
   * Returns JSON data for the manifest.json file.
   *
   * The actual data is generated by \Drupal\Core\Theme\ManifestGenerator.
   *
   * @return \Drupal\Core\Cache\CacheableJsonResponse
   *   The JSON response.
   */
  public function manifest() : CacheableJsonResponse {}

So on my todo list

Returning to the difference between spec and implementation.

D) Chrome generates lots of warning if it sees missing (optional) png definitions for critical icon sizes.

E) I have made the manifest permanently cached. I want to option to set it to say a week?

Status: Needs review » Needs work

The last submitted patch, 110: 2698127-110.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

martin107’s picture

Status: Needs work » Needs review
FileSize
16.13 KB
41.7 KB

I have not work on my todo list from above, I got sidelined with other issues that arose.
I still plan to work on the todo list.

A) I have converted a kernel test to a unit test.. something I had better justify.

1) Debugging slow tests is painful. Tests that run in milliseconds rather than 5 mins make me happy.
2) The additional assurance the kernel test gave was proving the wiring of the service into core etc
are all duplicated. We have extensive functional testing for that.

B) ThemeSettingsForm had a bug in it. Color was not found.

+use Drupal\Component\Utility\Color;

C) Some optional field are pulled down from a list .. I looked at the spec and added missing values.

D) I add a "--Leave Empty --" pulled down optional so that a user can omit the field.

martin107’s picture

Coding Standard fix up.

zenimagine’s picture

Hi, will this feature allow PUSH notification and offline content ? Thank you

martin107’s picture

All the test fails seem to have common error. so I fixed up Drupal\Tests\file\FunctionalJavascript\FileFieldWidgetTest
and testbot will tell me what is left.

@zenimagine

Hi, will this feature allow PUSH notification and offline content ?

No, those are both big topics .. which we as community need to keep upto date with - just not here.

storing content offline is a massive topic..
In general all solutions of that type need to register a service worker with the browser .. JS code in the browser to act a network proxy .. code intercepting all network requests and providing faked network data from a local store when offline. All core can do there is provide hooks for site specific/ theme specific/ contrib module specific logic to make decisions about what to cache etc. ( by hooks I mean that very loosely in a class driven sense. )

I hope that makes sense.

When I look for further work after this issue. Adding 'content_scripts' to the manifest is a different large topic.

Status: Needs review » Needs work

The last submitted patch, 115: 2698127-115.patch, failed testing. View results

yogeshmpawar’s picture

Assigned: martin107 » yogeshmpawar
yogeshmpawar’s picture

Assigned: yogeshmpawar » Unassigned
Status: Needs work » Needs review
FileSize
41.57 KB
2.34 KB

Updated patch with an interdiff.

martin107’s picture

Assigned: Unassigned » martin107

@yogeshmpawar
Thanks for fixing my errors. - that was helpful

I think I might re-work your test changes a little. It is better to expected the test to return something unexpected something that one can't have come from a default hidden in the system.

In short, I want to set the expected return value to be 'llama'

I grabbing this back to signal that I am actively working on this.

I have a support for icons partially working .. nothing ready for show and tell yet.

martin107’s picture

I added the first cut versions of icons support -- in the manifest file.

A) Added a table to ThemeSettingsForm -- each table row contains a fieldset holding a icon datablock.

B) The schema has been updated to hold a unlimited list of icon data

C) The icon section is now output in the manifest.json file.

I have work to do

D) The form needs 'delete' and 'add new icon' actions associated with the icon block.

E) The icons are cascaded so the table need to be draggable.

Status: Needs review » Needs work

The last submitted patch, 120: 2698127-120.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

martin107’s picture

I have split off the umami design decisions related to the mobile and desktop icons into a separate issue

So that the umami contributors can have their say.

From there perspective - we provide the mechanism, they the icons.

martin107’s picture

While I think about it, whatever I set for the default bartik/core theme has branding implications -- which is a whole discussion to itself.

borisson_’s picture

D) The form needs 'delete' and 'add new icon' actions associated with the icon block.

E) The icons are cascaded so the table need to be draggable.

I agree, but this will make this patch need JS-based testing as well. I'm not sure if we need to do that already in this issue (that has been dragging for a while), or if we should do that in a followup.

martin107’s picture

Just a reroll.

martin107’s picture

Status: Needs work » Needs review
FileSize
44.98 KB
9.77 KB

I still have things on my todo list.....

But in this next patch

a) Add a AJAX "Add Icon" button which appends a blank icon data block onto what every the user has edited or has been pulled form config
b) The main buildForm() is already absurdly long. [ The style guide lines I like limit methods/function to approx 100 lines of code. ]
So I have hived off the icon stuff into a buildIconTable() method.

@borisson_

Regarding the contentious

E) The icons are cascaded so the table need to be draggable.

As this starts to look polished I will make a decision about how much to test.. and try and take in your concerns into account then .. and maybe cut out some code in favor of simpler testing.

Still on my todo list

I need to add a delete action foreach icon data block.

Status: Needs review » Needs work

The last submitted patch, 126: 2698127-126.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

martin107’s picture

Status: Needs work » Needs review
FileSize
46.01 KB
5.46 KB

In this next patch I have added a delete button.

But I am finding trouble removing a bug.

I am going to describe it in detail just in case anyone reading this knows this a "known problem".

I think the mistake is that the form is being incorrectly cached somewhere-- so if anyone can tell me the pattern I am using in bad please let me know.

Adding and deleting works when one button is added then deleted.

BUT it does not work in general. if you live edit three icons and then delete the middle one it fails.

The step to reproduce.

a) Click on the AddIcon set the path to "a"
a) Click on the AddIcon set the path to "b"
a) Click on the AddIcon set the path to "c"

delete the "b" button and observe that the third Icon button "c" is incorrectly deleted.

Note to self - this outlines a test I need to add..

Status: Needs review » Needs work

The last submitted patch, 128: 2698127-128.patch, failed testing. View results

martin107’s picture

Status: Needs work » Needs review
FileSize
46.04 KB
747 bytes

The problem above still exists, but in unrelated news this should reduce the error count.

Status: Needs review » Needs work

The last submitted patch, 130: 2698127-130.patch, failed testing. View results

martin107’s picture

Status: Needs work » Needs review
FileSize
46.21 KB
967 bytes

Again this does not solve the main problem.

But looking at the generated manifest files....

The icon datastructure need to be coerced into an array. [done]

My code for omitting empty key values needed to descend into the icon block and omit values inside that.

Status: Needs review » Needs work

The last submitted patch, 132: 2698127-132.patch, failed testing. View results

martin107’s picture

Status: Needs work » Needs review
FileSize
1.2 KB
46.25 KB

While altering the form

admin/config/system/site-information

I noticed that manifest key, value pairs were not updated ... added a cache tag...fixed.

Also fixed -- a minor coding standard. ( 80 chars overspill )

Status: Needs review » Needs work

The last submitted patch, 134: 2698127-134.patch, failed testing. View results

Manuel Garcia’s picture

Status: Needs work » Needs review
FileSize
1.25 KB
46.24 KB

So excited to see progress on this, great job!

I had a look at the remaining failing tests, easy fix, we were just missing part of the config we install on core/modules/system/config/install/system.site.yml

Status: Needs review » Needs work

The last submitted patch, 136: 2698127-136.patch, failed testing. View results

Manuel Garcia’s picture

Status: Needs work » Needs review
Issue tags: -Needs upgrade path, -Needs upgrade path tests
FileSize
5.48 KB
49.46 KB

Decided to give this another push, here is the upgrade path, and the upgrade path test The test actually identified a typo bug on ManifestGenerator::doGenerateManifest() so fixed that while I was at it.

Also fixed the other issues with the failing MigrateSystemConfigurationTest tests.

martin107’s picture

@Manuel Garcia

Thanks man, thanks for fixing the tests, in particular my idiot move to misspell manifest_version in just the wrong place

-    $data['manifest_verison'] = $site_configuration->get('manifest.manifest_version');
+    $data['manifest_version'] = $site_configuration->get('manifest.manifest_version');

- given the blindness to my own bugs .. I would have been looking for that for a month on Sundays. --- thank you thank you.

The next change is to add a first draft version of the 'live editing of icon data blocks test'.

In short the current bug and what I outlined in #128

Adding icon data blocks a, b and c and then deleting block 'b' before saving the config.

I am seeing problems with my container setup ... I think

I am getting cannot add cookies errors in my output ... I just want to see what testbot does with this new test

There were 3 errors:

1) Drupal\Tests\system\FunctionalJavascript\ThemeFormSettingsTest::testIcons
Exception: unable to set cookie
(Session info: headless chrome=74.0.3729.157)
(Driver info: chromedriver=2.38.552522 (437e6fbedfa8762dec75e2c5b3ddb86763dc9dcb),platform=Linux 4.15.0-1045-oem x86_64)

/var/www/html/web/vendor/instaclick/php-webdriver/lib/WebDriver/Exception.php:144
/var/www/html/web/vendor/instaclick/php-webdriver/lib/WebDriver/AbstractWebDriver.php:157
/var/www/html/web/vendor/instaclick/php-webdriver/lib/WebDriver/Session.php:191
/var/www/html/web/core/tests/Drupal/FunctionalJavascriptTests/DrupalSelenium2Driver.php:43
/var/www/html/web/vendor/behat/mink/src/Session.php:212
/var/www/html/web/core/tests/Drupal/Tests/UiHelperTrait.php:433
/var/www/html/web/core/tests/Drupal/Tests/UiHelperTrait.php:321
/var/www/html/web/core/tests/Drupal/Tests/UiHelperTrait.php:246
/var/www/html/web/core/modules/system/tests/src/FunctionalJavascript/ThemeFormSettingsTest.php:30

Please see the TODO I have yet to define what the manifest should look like when only 'a' and 'c' are saved.

Status: Needs review » Needs work

The last submitted patch, 139: 2698127-139.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

martin107’s picture

Status: Needs work » Needs review
FileSize
53.34 KB
7.02 KB

1) Fixed css selector for the 'Add Icon' button.

2) Fixed a few cut paste errors associated with '$asser_session'

3) Fix tab errors.

There will be a short pause while I sort out my local dev system.

Status: Needs review » Needs work

The last submitted patch, 141: 2698127-141.patch, failed testing. View results

Manuel Garcia’s picture

Status: Needs work » Needs review
FileSize
4.52 KB
53.27 KB

- given the blindness to my own bugs .. I would have been looking for that for a month on Sundays. --- thank you thank you.

Hahah I totally know the feeling, you're very welcome :)

Took the liberty of cleaning up the new test, should hopefully at least run correctly now.

Status: Needs review » Needs work

The last submitted patch, 143: 2698127-143.patch, failed testing. View results

Manuel Garcia’s picture

Status: Needs work » Needs review
FileSize
815 bytes
53.27 KB

Another try

Status: Needs review » Needs work

The last submitted patch, 145: 2698127-145.patch, failed testing. View results

martin107’s picture

Manuel Garcia’s picture

Status: Needs work » Needs review
FileSize
908 bytes
53.25 KB
+++ b/core/modules/system/tests/src/FunctionalJavascript/ThemeFormSettingsTest.php
@@ -30,6 +31,73 @@ protected function setUp() {
+      $assert_session->assertNoElementAfterWait('css', "input[name=\"form_build_id\" value=\"$form_id_old\"]");

As far as I know you cant do a CSS selector by attribute using two attributes, using just the value here which should be enough.

Status: Needs review » Needs work

The last submitted patch, 148: 2698127-148.patch, failed testing. View results

Manuel Garcia’s picture

Status: Needs work » Needs review
FileSize
1.07 KB
53.25 KB

Asserting that the middle icon was removed.

amateescu’s picture

  1. +++ b/core/lib/Drupal/Component/Utility/Color.php
    @@ -25,6 +25,22 @@ public static function validateHex($hex) {
    +  public static function validateStrictHex($hex) {
    

    How about adding a $strict = FALSE argument (or $strict_leading_hash) to the existing validateHex() method?

  2. +++ b/core/lib/Drupal/Core/Theme/Manifest.php
    @@ -0,0 +1,78 @@
    +  public function __construct($data) {
    ...
    +  public function overwriteWithNewData($data) : Manifest {
    

    Should we type hint with array here?

  3. +++ b/core/modules/color/color.module
    @@ -345,9 +345,13 @@ function color_palette_color_value($element, $input, FormStateInterface $form_st
    + * @deprecated in Drupal 8.8.x and is removed from Drupal 9.0.x. Use
    ...
    +  @trigger_error('color_valid_hexadecimal_string is deprecated in Drupal 8.8.x and is removed from Drupal 9.0.x. Use Drupal\Component\Utility\Color::validateStrictHex instead.', E_USER_DEPRECATED);
    

    The deprecated message needs to be in this form:

    @deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use ...

  4. +++ b/core/modules/system/src/Form/ThemeSettingsForm.php
    @@ -388,10 +390,208 @@ public function buildForm(array $form, FormStateInterface $form_state, $theme =
    +   * Reuturn a icon table in reponse to a Add Icon button press.
    

    "Reuturn a icon .." -> "Returns an icon .." :)

  5. +++ b/core/modules/system/src/Form/ThemeSettingsForm.php
    @@ -388,10 +390,208 @@ public function buildForm(array $form, FormStateInterface $form_state, $theme =
    +   * @returns Array
    ...
    +  public function appendEmptyIcon(array &$form, FormStateInterface $form_state) : Array {
    ...
    +   * @returns Array
    ...
    +  public static function deleteSelectedIcons(array &$form, FormStateInterface $form_state) : Array {
    
    @@ -537,4 +748,20 @@ protected function validatePath($path) {
    +  private static function extractIcons(array $icons) : Array {
    

    "Array" -> "array"

  6. +++ b/core/modules/system/src/Form/ThemeSettingsForm.php
    @@ -388,10 +390,208 @@ public function buildForm(array $form, FormStateInterface $form_state, $theme =
    +   * Reuturn a icon table in reponse to a Delete Icon button press.
    

    Deletes an icon table row?

  7. +++ b/core/modules/system/tests/src/Functional/Update/SiteManifestUpdateTest.php
    @@ -0,0 +1,70 @@
    + * @group Entity
    

    I think @group system would be more appropriate.

  8. +++ b/core/profiles/demo_umami/config/install/system.theme.global.yml
    @@ -12,3 +12,7 @@ logo:
    \ No newline at end of file
    

    Needs an empty line at the end of the file.

  9. +++ b/core/tests/Drupal/Tests/Component/Utility/ColorTest.php
    @@ -23,10 +23,27 @@ class ColorTest extends TestCase {
       public function testValidateHex($expected, $value) {
    +
         $this->assertSame($expected, Color::validateHex($value));
    
    @@ -99,7 +116,7 @@ public function testHexToRgb($value, $expected, $invalid = FALSE) {
    -   *     - (optional) Boolean indicating invalid status. Defaults to FALSE.
    +   *     - (optional) Bool indicating invalid status. Defaults to FALSE.
    

    Unneeded changes :)

  10. +++ b/core/tests/Drupal/Tests/Component/Utility/ColorTest.php
    @@ -23,10 +23,27 @@ class ColorTest extends TestCase {
    +  public static function validateStrictHex($hex) {
    

    Why do need to add this method to a test class?

Status: Needs review » Needs work

The last submitted patch, 150: 2698127-150.patch, failed testing. View results

borisson_’s picture

#151.1 I disagree, I think having another method is clearer and makes the code internal to the method also easier.

All the other remarks are things that should be changed.

martin107’s picture

Status: Needs work » Needs review
FileSize
53.4 KB
2.66 KB

@borisson_ thanks for all the comments .. I will address them later .. here is a fix to the tests - well sort of.

As far as I know you can't do a CSS selector by attribute using two attributes, using just the value here which should be enough.

when I looked at the css standard what I as looking for was
input[name="form_build_id"][value="xyz"]

but I could not get it to work ... in the end I reworked the test and now we wait to the progress throbber to blink in and out of existence.
[ in short I copied code from ThrobberTest ]

@Manuel Garcia ...so I am starting from 147 stepping over some of your welcome attempts to fix the problem and but I changed direction once I got stability.

Here is my current issue.

Now the test demand that 'bbb' is deleted in the live edit -- and the test confirm it ...

This is super strange bbb is still not deleted when I manually test it.

I am not sure how test get the correct result of 'aaa', 'ccc' is there extra cache clear or something ?

Note: I only set the expected icons -- once I got testbot to locally report what what actually received.

$icons_expected = [
0 => ['src' => 'aaa'],
1 => ['src' => 'ccc'],
];

I am still trying to track this down.

martin107’s picture

amateescu -- sorry I should have mentioned you above... thanks for the review.

regarding 151

1) I am have not opinion. -one way or the other. - so have taken no action
2) done
3) done
4) done
5) done
6) appendEmptyIcon, and deleteSelectedIcons imply the processing is done in the callback. Which was the intent on the first draft.
So I refactored two functions in to a common updatedIconTable()

7) yes good catch ... thanks.
8) done
9) done
10) done.

idebr’s picture

+++ b/core/lib/Drupal/Core/Theme/ManifestGeneratorInterface.php
@@ -0,0 +1,21 @@
+  public function generateManifest($themeName) : Manifest;

Note that these return type hints require PHP 7.1.x while Drupal 8 currently still supports PHP 7.0.x. How these return values should be type hinted is under discussion in #3050720: [Meta] Implement strict typing in existing code. It appears we can start using these starting in PHP 7.2 if I understood correctly.

martin107’s picture

a) From looking around the web there are lots of PHP 7.0.x tutorials talking about adding the new return type . I have only added a return type to new code not existing interfaces/classes so many of the objections raised in that issue do necessarily apply. But I don't want to hold this issue up anymore than needed it is too hot to argue so I will take it out in the next iteration.

b) I got bored of having to remember to swap the word order when jumping between ThemeSettingsForm to ThemeFormSettingsTest.
The natural convention is to just add 'Test' to the class name

So I created a spin off quick fix issue.

#3069553: Standardise name 'ThemeFormSettingsTest'

c) I want to make a comment in relation to the 'Needs UX review' tag

Intellectually - I appreciate why things have been done

But stand behind a fresh developer and watch his/hers first 20 minutes grappling with the new features.

Watch them discover the 2 forms

admin/config/system/site-information
admin/appearance/settings/bartik

And the reaction will be

'OMG: Why is Drupal getting in my way way.
When I want to to edit the manifest settings I want all the things in one place'

martin107’s picture

FileSize
51.74 KB

reroll - caused by

#3039026: Deprecate file_directory_temp() and move to FileSystem service

our new code has to share space in

function system_update_8801() {}

Berdir’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/system.install
@@ -2346,7 +2346,7 @@ function system_update_8702() {
 
 /**
- * Remove 'path.temporary' config if redundant.
+ * Remove 'path.temporary' config if redundant, set the new system.site manfifest configuration.
  */
 function system_update_8801() {
   // If settings is already being used, or the config is set to the OS default,
@@ -2356,4 +2356,14 @@ function system_update_8801() {

@@ -2356,4 +2356,14 @@ function system_update_8801() {
     $config->clear('path.temporary')
       ->save(TRUE);
   }
+
+  $site = \Drupal::configFactory()->getEditable('system.site');
+  $site->set('manifest', [
+      'start_url' => $site->get('page.front'),
+      'display' => NULL,
+      'short_name' => $site->get('name'),
+      'name' => $site->get('name'),
+      'manifest_version' => 2,
+    ])
+    ->save();
 }
diff --git a/core/modules/system/system.module b/core/modules/system/system.module

It shouldn't be merged, it should be moved to a new update number. Each thing should have its own update function. While dev versions are a grey area as we don't support updating yet, the general rule is to never add to an existing update function, or sites that already executed this are left out.

martin107’s picture

FileSize
51.47 KB
894 bytes

Thanks Bedir, for pointing out my mistake.

Sorry for the slow pace on this issue... I need to sit down on a free weekend with xdebug and step through it.

I have a slight idea on what could be going wrong

As the test runs - the icon data block is never 'aaa', 'bbb' so we can't be inadvertently pulling from cache.

What must be happening is that

1) After the buildForm() has deleted the appropriate mid icon block
2) The ajax callback has run
3) -- then after what is broken is the form_state is being used to further rebuild/re-populate and push 'aaa', 'bbb' into the compacted form before being pushed out the door.

martin107’s picture

Step through the problem with a debugger ...

Bedir had the solution to my problem in Nov 2016

https://drupal.stackexchange.com/questions/220185/clear-form-fields-afte...

Bedir++

The solution: Adjust the user input -- to prevent the rebuild re-imposing stale input.

martin107’s picture

Status: Needs work » Needs review
FileSize
105.87 KB
1.32 KB

When I manually test this ... all is good
It is the test which is off.

I have not affected that...here

I have simplified the delete code.

Status: Needs review » Needs work

The last submitted patch, 163: 2698127-163.patch, failed testing. View results

martin107’s picture

Status: Needs work » Needs review
FileSize
199.4 KB

Reroll.

martin107’s picture

Removed stray alteration to composer.json, composer.lock

Status: Needs review » Needs work

The last submitted patch, 166: 2698127-166.patch, failed testing. View results

martin107’s picture

Regarding 122

I have split off the umami design decisions related to the mobile and desktop icons into a separate issue

So that the umami contributors can have their say

#3064299: Umami: Mobile/Desktop Icon Design

and the response is in effect "let us go with the drupal defaults"

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

xjm’s picture

Issue tags: -needs UX review +Needs usability review

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

nod_’s picture

Assigned: martin107 » Unassigned
Status: Needs work » Needs review
FileSize
31.64 KB

Reroll, hope i didn't break too many things. There were changes in some weird places so removed them.

I don't remember/know why we have a "version" field in the manifest, might need to get rid of it.

We should add support for a few things in the manifest:

https://w3c.github.io/manifest/#dom-webappmanifest-shortcuts
https://w3c.github.io/manifest/#related_applications-member

There is already an alter hook to modify the content of the manifest file, so it's definitely doable in contrib at least.

nod_’s picture

didn't have the new files

Status: Needs review » Needs work

The last submitted patch, 173: core-manifest-2698127-173.patch, failed testing. View results

raman.b’s picture

Status: Needs work » Needs review
FileSize
50.86 KB
2.96 KB

Required another re-roll after 3055193

Also addressing the failed tests from #173

Status: Needs review » Needs work

The last submitted patch, 175: 2698127-175.patch, failed testing. View results

raman.b’s picture

mikemiles86’s picture

I have a project currently running 8.9.x which needs this functionality and is not yet ready to move to 9.1.x. I re-rolled the #177 patch for 8.9.x.

heddn’s picture

Status: Needs review » Needs work

Looks like needs another re-roll. There are PHP linting issues in modules/system/tests/src/FunctionalJavascript/ThemeSettingsFormTest.php

munish.kumar’s picture

Status: Needs work » Needs review
FileSize
50.95 KB
545 bytes

Reroll #178 for 8.9x branch

nod_’s picture

Please keep patches for 9.1.x the feature will not be introduced in drupal 8.

If you need the manifest install the pwa module.

nod_’s picture

Patch to look at is #177

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

viappidu’s picture

Refactored 9.3.x

viappidu’s picture

FileSize
50.79 KB

Found problems in previous patch. Not sure what I did wrong...

Spokje’s picture

Not quite sure what's going on with all the patches after #177, please use interdiffs.

So let's start with a straight-up re-roll from #177 against 9.3.x.

Spokje’s picture

Assigned: Unassigned » Spokje
Status: Needs review » Needs work

Used 2698127-187.patch as base for the new MR.

Spokje’s picture

Spokje’s picture

Assigned: Spokje » Unassigned
Status: Needs work » Needs review
andrewmacpherson’s picture

Issue summary: View changes

Revisiting the accessibility concerns in #91-94.

I'd like to remove the orientation property from the scope of this issue entirely.

Offering site-builders a way to specify the orientation property in a manifest amounts to thermo-nuclear option. "Use this setting if you want to fail WCAG with 99.9% certainty".

Re. #94:

To address #91 concerns: Orientation is just specifying the default orientation. It's not a locking mechanism, rather a signal for what a given site considers its default or most useful orientation.

This isn't the case. In practice, it amounts to an outright lock when the PWA is installed. Users of the PWA don't have a choice in this at all.

If you visit a website using an Android browser, then install the PWA, the orientation will be locked whenever you use the PWA. If the web site has a PWA manifest, users lose the option to "save to home screen" as a mere bookmark; they can only install the PWA.

There are more than just two options. Would setting any as a default alleviate the concerns you have?

No. The only acceptable value is "orientation": "any", but there's no point providing a UI with only one option. The orientation key isn't mandatory in a PWA manifest, so let's omit it entirely.

i.e. Orientation won't be offered in the settings form, and the property won't be present in the manifest.json which is served.

do you have some links we could read explaining why these properties have negative effects on a11y? This is the first I've heard of it and I'm keen to learn more in case I need to adjust something in the contrib module.

The PWA contrib module issue discusses this in detail - #3070058: Document how to specify the orientation parameter via alter hook.

Here's why I think it should be removed:

  • There is NO way for a PWA user (Drupal visitor) to override the orientation specified in the manifest.
  • WCAG SC 1.3.4 Orientation includes an exception for cases where the orientation is considered essential. This is going to be rare; a 1-in-a-1000 use case, say. Most of the sites that Drupal is used for will NOT qualify for the WCAG exemption: product catalogs, news/magazines, forums, intranets, webforms and surveys, directories, etc.
  • It doesn't matter if our default value is "orientation": "any". If we let a site owner set the orientation, then they will. Their visitors will not be able to override this.
  • It doesn't matter how many warnings we give in the UI, help page, online handbook, etc.
  • We have an opportunity to take a stand for accessibility. PWA manifest orientation is at risk of widespread abuse; Drupal core doesn't have to facilitate that. The web has been here before, with sites preventing pinch-zoom through mis-use of the viewport meta tag. The accessibility community went to great effort to raise awareness of this problem; submitting comments on articles, and pull requests to starterkits and frameworks. Yet the damage was already done. Millions of websites still prevent users from zooming. Eventually, after many years, some browser vendors (e.g. Firefox on Android) intervened to provide a user setting to override the author's viewport metatag.

The hook_manifest_alter() API provides a mechanism to add the orientation property, for sites which genuinely qualify for the WCAG SC 1.3.4 essential-orientation exception.

Proposed resolution:

  • Remove the orientation setting from the settings UI.
  • Either remove the orientation property from the manifest.json entirely, or hard-code it to "any".
nod_’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Theme/Manifest.php
    @@ -0,0 +1,78 @@
    +  public function overwriteWithNewData($data) : Manifest {
    +    return new static($data);
    +  }
    
    +++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
    @@ -0,0 +1,146 @@
    +    $this->moduleHandler->alter('manifest', $manifest_data);
    

    I might be missing something but how does that work with the alter hook supposed to let people modify the values of the manifest?

  2. +++ b/core/lib/Drupal/Core/Theme/ManifestGenerator.php
    @@ -0,0 +1,146 @@
    +    $theme_specific_config = $this->configFactory->get($themeName . '.settings');
    +    if (!empty($theme_specific_config->get('manifest'))) {
    +      return $theme_specific_config;
    +    }
    +    return $this->configFactory->get('system.theme.global');
    

    That should probably be additional, as in take the theme settings and merge with the system theme global values.

  3. +++ b/core/modules/color/color.module
    @@ -314,7 +314,7 @@ function color_palette_color_value($element, $input, FormStateInterface $form_st
    +    if (!$value || !isset($complete_form['#token']) || Color::validateStrictHex($value) || \Drupal::csrfToken()->validate($form_state->getValue('form_token'), $complete_form['#token'])) {
    
    @@ -345,7 +345,7 @@ function color_valid_hexadecimal_string($color) {
    +    if (!Color::validateStrictHex($color)) {
    

    We should do data processing/formatting on output not input. let's add a method to ManifestGenerator that makes sure there is a # for color values. no need to duplicate a validation method

  4. +++ b/core/modules/system/src/Form/SiteInformationForm.php
    @@ -118,12 +119,63 @@ public function buildForm(array $form, FormStateInterface $form_state) {
    +    $form['site_information']['manifest']['manifest_version'] = [
    +      '#type' => 'textfield',
    +      '#attributes' => [
    +        'data-type' => 'number',
    +      ],
    +      '#title' => $this->t('Manifest Version'),
    +      '#default_value' => $site_config->get('manifest.manifest_version'),
    +      '#required' => TRUE,
    +    ];
    

    this is not necessary. it's from the pwa module but it's not part of the spec.

  5. +++ b/core/modules/system/src/Form/ThemeSettingsForm.php
    @@ -388,9 +390,201 @@ public function buildForm(array $form, FormStateInterface $form_state, $theme =
    +    $form['manifest']['manifest_orientation'] = [
    

    as said above, let's get rid of this.

  6. +++ b/core/modules/system/src/Form/ThemeSettingsForm.php
    @@ -388,9 +390,201 @@ public function buildForm(array $form, FormStateInterface $form_state, $theme =
    +
    +    if ($name == 'AddButton') {
    +      // Append an empty icon data block.
    +      $unflatterned_icons = $form_state->getValue('manifest_icons') ?: [];
    +      $icons = $this->extractIcons($unflatterned_icons);
    +      $icons[] = [
    +        'src' => '',
    +        'sizes' => '',
    +        'media_type' => '',
    +        'purpose' => '',
    +      ];
    +    }
    +    else {
    +      // Delete and reindex extracted icons.
    +      $matches = [];
    +      $is_icon_button = preg_match(
    +        '/^delete-icon-(\d+)$/',
    +        $name,
    +        $matches);
    +      if ($is_icon_button) {
    +        $button_number = (int) $matches[1];
    +
    +        // Prevent the users input from being reimposed after rebuild.
    +        $input = $form_state->getValues();
    +        unset($input['manifest_icons'][$button_number]);
    +        $input['manifest_icons'] = array_values($input['manifest_icons']);
    +        $form_state->setUserInput($input);
    +
    +        // Rebuild the form's fields with a reduced set of icons.
    +        $extracted_icons = $this->extractIcons($input['manifest_icons']);
    +        $icons = array_values($extracted_icons);
    +
    +        $form_state->setRebuild();
    +      }
    +      else {
    +        $icons = $this->config($config_key)->get('manifest.icons') ?: [];
    +      }
    +    }
    +
    +    $form['manifest']['manifest_icons'] = $this->buildIconTable($icons);
    +
    +    $form['manifest']['add_more_icons'] = [
    +      '#type' => 'button',
    +      '#value' => $this->t('Add Icon'),
    +      '#name' => 'AddButton',
    +      '#ajax' => [
    +        'callback' => '::updatedIconTable',
    +        'effect' => 'slide',
    +        'wrapper' => 'manifest_table_wrapper',
    +      ],
    +    ];
    

    I'd remove that from the initial patch, let's declare that in themes as examples but I'm not sold on providing a generic user-input for this.

    I'd say that if a theme wants to make icons configurable it's their responsibility. Like the color module integration.

AaronMcHale’s picture

I'd just like to jump in to second the points that @andrewmacpherson made in #192.

As a visually impaired web user myself, I feel strongly that sites shouldn't restrict the users' ability to do things like pinch-zoom and control the orientation. Far too often I come across "mobile" sites that are less accessible for me simply because the developer has made the choice to restrict the ability to pinch-zoom.

I would be grateful if Drupal could avoid contributing to this problem generally.

Thanks,
-Aaron

xmacinfo’s picture

I did not read the whole issue But the last few comments about accessibility hit the point.

I am against any binding from a manifest file to Drupal that will prevent:

  • orientation change
  • zooming (pinch to zoom)
  • text size change
  • color contrasts adjustments
  • selecting and copying tests
  • using the reader mode
  • printing (don't support only browsers)

I would prefer that Drupal never generates a manifest file, or if a manifest file exist, that Drupal does not change basic usability/accessibility behaviours based on that file.

Accessibility/usability comes foremost. Don't lock users out.

If Drupal ends implementing a manifest.json, Drupal should also allow any user to disable it entirely.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

MacSim’s picture

I am sorry but I am not following you on the orientation change ; most of the natives apps are locked in the portrait orientation.
I am not telling that it's always a good idea ; it's a fact that people in a wheelchair with a non-rotating mobile/tablet support will feel like these apps are not accessible. But, depending on the PWA you're building, you might choose to ignore that person in their wheelchair, not because you're mean or haven't thought of it, but because your PWA isn't aimed at this type of person - their disability preventing him/her from doing the activity covered by your PWA.
It's up to the developers and UI / UX designers to create an accessible interface regardless of whether the orientation is locked or not. IMHO Drupal shouldn't go against the manifest specs. If an option is available in the specs and supported by most browsers, even if not mandatory, it should be configurable.
If you don't want to lock the orientation change, you would choose the "any" option (which should be the default option since it will be the case in 90% of the WPAs) but if - for some reason - you want to lock the orientation, Drupal should provide the means to do so.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mgifford’s picture

Issue tags: +wcag134
Anybody’s picture

Issue summary: View changes
dercheffe’s picture

It's up to the developers and UI / UX designers to create an accessible interface regardless of whether the orientation is locked or not. IMHO Drupal shouldn't go against the manifest specs. If an option is available in the specs and supported by most browsers, even if not mandatory, it should be configurable.
If you don't want to lock the orientation change, you would choose the "any" option (which should be the default option since it will be the case in 90% of the WPAs) but if - for some reason - you want to lock the orientation, Drupal should provide the means to do so.

As a disabled person I agree with that 👍. Going with the standards/specs of technology is almost a good option. Don't forget that accessibility often plays together with different third party apps. The assistance software (braille device etc.) is more comfy with standards. And in my opinion it might be a kind of exclusion too, to "hard code" an option independent from it's direction. Let the developers/designers decide what is necessary for the individual use case.

xmacinfo’s picture

We can remove “orientation change” from the list I made.

But there is no clear consensus on that one. See #194 and #192.

Creating a good-looking and usable web page/web app in both orientations requires more work. But using responsive CSS code helps to build pages that adapt to most screen sizes.

Personally, on an iPad, for example, I want to be able to use a web page/web app in any orientation and not be left lock-out in one orientation.

tyler36’s picture

From #197

> If an option is available in the specs and supported by most browsers, even if not mandatory, it should be configurable.

This. However, "orientation" is marked as "Experimental: Expect behavior to change in the future." so I would be inclined to skip this (and any other experimental) to increase reliablity.

Currently, patch #187 and the MR reference the "color" module which was removed in Drupal 10.

Albert Volkman’s picture

FileSize
49.17 KB

Created a version of the existing patch to apply to 10.1.x